/*******************************************************************************
* Copyright (c) 2015-2016 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat - initial API and implementation
*******************************************************************************/
package org.eclipse.linuxtools.internal.man.help;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.help.IToc;
import org.eclipse.help.ITopic;
import org.eclipse.help.IUAElement;
import org.eclipse.linuxtools.internal.man.parser.ManParser;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
/**
* A table of contents that will have one topic for every manual section that
* contains at least one installed man page. Each of those topics will have one
* sub-topic for manual page in the section.
*/
public class ManualToc implements IToc {
private final Map<String, SectionTopic> sections = new HashMap<>();
@Override
public ITopic[] getTopics() {
if (sections.isEmpty()) {
generateSections();
}
List<SectionTopic> sectionList = new ArrayList<>(sections.values());
Collections.sort(sectionList);
return sectionList.toArray(new SectionTopic[sectionList.size()]);
}
private void generateSections() {
// Filter to make sure we only get manual section directories
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
private final Pattern p = Pattern.compile("^man\\d[xp]?"); //$NON-NLS-1$
@Override
public boolean accept(Path path) throws IOException {
Matcher m = p.matcher(path.getFileName().toString());
return Files.isDirectory(path) && m.matches();
}
};
// Search all man paths in the order that man would, adding sections and
// pages as we encounter them
List<Path> manPaths = ManParser.getManPaths();
for (Path manPath : manPaths) {
if (Files.notExists(manPath)) {
continue;
}
try (DirectoryStream<Path> manPathStream = Files
.newDirectoryStream(manPath, filter)) {
for (Path sectionPath : manPathStream) {
try (DirectoryStream<Path> sectionPathStream = Files
.newDirectoryStream(sectionPath)) {
for (Path pagePath : sectionPathStream) {
String pageName = pagePath.getFileName().toString();
if (pageName.endsWith(".gz")) { //$NON-NLS-1$
pageName = pageName.substring(0,
pageName.length() - 3);
}
// Add page to section
int dot = pageName.lastIndexOf('.');
String sectionId = pageName.substring(dot + 1,
pageName.length());
String pageId = pageName.substring(0, dot);
addSectionPage(sectionId, pageId);
}
}
}
} catch (IOException e) {
Bundle bundle = FrameworkUtil.getBundle(this.getClass());
Status status = new Status(IStatus.ERROR, e.getMessage(),
bundle.getSymbolicName());
Platform.getLog(bundle).log(status);
}
}
}
@Override
public ITopic getTopic(String href) {
return null;
}
@Override
public boolean isEnabled(IEvaluationContext context) {
return true;
}
@Override
public IUAElement[] getChildren() {
return getTopics();
}
@Override
public String getHref() {
return null;
}
@Override
public String getLabel() {
return Messages.ManualToc_TocLabel;
}
private void addSectionPage(String sectionId, String pageId) {
StringBuilder label = new StringBuilder();
String displaySectionId = sectionId;
// Decide section label
switch (sectionId.substring(0, 1)) {
case "0": //$NON-NLS-1$
label.append(Messages.ManualToc_Section0);
break;
case "1": //$NON-NLS-1$
label.append(Messages.ManualToc_Section1);
break;
case "2": //$NON-NLS-1$
label.append(Messages.ManualToc_Section2);
break;
case "3": //$NON-NLS-1$
label.append(Messages.ManualToc_Section3);
break;
case "4": //$NON-NLS-1$
label.append(Messages.ManualToc_Section4);
break;
case "5": //$NON-NLS-1$
label.append(Messages.ManualToc_Section5);
break;
case "6": //$NON-NLS-1$
label.append(Messages.ManualToc_Section6);
break;
case "7": //$NON-NLS-1$
label.append(Messages.ManualToc_Section7);
break;
case "8": //$NON-NLS-1$
label.append(Messages.ManualToc_Section8);
break;
case "9": //$NON-NLS-1$
label.append(Messages.ManualToc_Section9);
break;
}
// Decide sub-section label
switch (sectionId.substring(1, sectionId.length())) {
case "am": //$NON-NLS-1$
label.append(Messages.ManualToc_SectionAM);
break;
case "G": //$NON-NLS-1$
label.append(Messages.ManualToc_SectionG);
break;
case "p": //$NON-NLS-1$
label.append(Messages.ManualToc_SectionP);
break;
case "pm": //$NON-NLS-1$
label.append(Messages.ManualToc_SectionPM);
break;
case "python": //$NON-NLS-1$
label.append(Messages.ManualToc_SectionPY);
break;
case "x": //$NON-NLS-1$
label.append(Messages.ManualToc_SectionX);
break;
case "ssl": //$NON-NLS-1$
label.append(Messages.ManualToc_SectionSSL);
break;
case "stap": //$NON-NLS-1$
label.append(Messages.ManualToc_SectionSTAP);
break;
default:
// If the sub section is not known to us, truncate it and just
// display the page in the main section
displaySectionId = sectionId.substring(0, 1);
break;
}
SectionTopic section = sections.get(displaySectionId);
if (section == null) {
section = new SectionTopic(displaySectionId, label.toString());
sections.put(displaySectionId, section);
}
section.addPage(sectionId, pageId);
}
}