com.redhat.ceylon.common.tools.help.DocBuilder Maven / Gradle / Ivy
/*
* Copyright Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the authors tag. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License version 2.
*
* This particular file is subject to the "Classpath" exception as provided in the
* LICENSE file that accompanied this code.
*
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License,
* along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.redhat.ceylon.common.tools.help;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ProcessBuilder.Redirect;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.tautua.markdownpapers.ast.Document;
import com.redhat.ceylon.common.OSUtil;
import com.redhat.ceylon.common.Versions;
import com.redhat.ceylon.common.tool.AnnotatedToolModel;
import com.redhat.ceylon.common.tool.ArgumentModel;
import com.redhat.ceylon.common.tool.Description;
import com.redhat.ceylon.common.tool.Hidden;
import com.redhat.ceylon.common.tool.Multiplicity;
import com.redhat.ceylon.common.tool.OptionModel;
import com.redhat.ceylon.common.tool.OptionModel.ArgumentType;
import com.redhat.ceylon.common.tool.PluginToolModel;
import com.redhat.ceylon.common.tool.RemainingSections;
import com.redhat.ceylon.common.tool.ScriptToolModel;
import com.redhat.ceylon.common.tool.SubtoolModel;
import com.redhat.ceylon.common.tool.Summary;
import com.redhat.ceylon.common.tool.ToolLoader;
import com.redhat.ceylon.common.tool.ToolModel;
import com.redhat.ceylon.common.tool.Tools;
import com.redhat.ceylon.common.tools.CeylonTool;
import com.redhat.ceylon.common.tools.help.Markdown.Section;
import com.redhat.ceylon.common.tools.help.model.DescribedSection;
import com.redhat.ceylon.common.tools.help.model.DescribedSection.Role;
import com.redhat.ceylon.common.tools.help.model.Doc;
import com.redhat.ceylon.common.tools.help.model.Option;
import com.redhat.ceylon.common.tools.help.model.OptionsSection;
import com.redhat.ceylon.common.tools.help.model.SubtoolVisitor;
import com.redhat.ceylon.common.tools.help.model.SummarySection;
import com.redhat.ceylon.common.tools.help.model.SynopsesSection;
import com.redhat.ceylon.common.tools.help.model.Synopsis;
public class DocBuilder {
protected ToolLoader toolLoader;
protected boolean includeHidden = false;
public DocBuilder(ToolLoader toolLoader) {
super();
this.toolLoader = toolLoader;
}
public boolean isIncludeHidden() {
return includeHidden;
}
public void setIncludeHidden(boolean includeHidden) {
this.includeHidden = includeHidden;
}
public Doc buildDoc(ToolModel> model, boolean specialRoot) {
checkModel(model);
boolean rootHack = specialRoot && (model instanceof AnnotatedToolModel) && CeylonTool.class.isAssignableFrom(((AnnotatedToolModel>)model).getToolClass());
Doc doc = new Doc();
doc.setVersion(Versions.CEYLON_VERSION);
doc.setToolModel(model);
doc.setInvocation(getCeylonInvocation(model));
doc.setSummary(buildSummary(model));
doc.setSynopses(rootHack ? buildRootSynopsis(model) : buildSynopsis(model));
doc.setDescription(rootHack ? buildRootDescription(model) : buildDescription(model));
doc.setOptions(buildOptions(model));
if (model.getSubtoolModel() != null) {
//doc.setSubcommands(buildSubcommands(model));
}
doc.setAdditionalSections(buildAdditionalSections(model));
return doc;
}
private void checkModel(ToolModel> model) {
new SubtoolVisitor(model) {
@Override
protected void visit(ToolModel> model, SubtoolModel> subtoolModel) {
if (model != root) {
if (getSummary(model) != null) {
System.err.println("@Summary not supported on subtools: " + model.getName());
}
if (!getSections(model).isEmpty()) {
System.err.println("@RemainingSections not supported on subtools: " + model.getName());
}
}
}
}.accept();
}
private SynopsesSection buildRootSynopsis(ToolModel> model) {
SynopsesSection synopsis = new SynopsesSection();
synopsis.setTitle(CeylonHelpToolMessages.msg("section.SYNOPSIS"));
List synopsisList = new ArrayList<>();
{
Synopsis s1 = new Synopsis();
s1.setInvocation(Tools.progName());
OptionModel option = new OptionModel();
option.setLongName("version");
option.setArgumentType(ArgumentType.NOT_ALLOWED);
ArgumentModel argument = new ArgumentModel<>();
argument.setMultiplicity(Multiplicity._1);
argument.setType(Boolean.TYPE);
option.setArgument(argument);
s1.setOptionsAndArguments(Collections.singletonList(option));//model.getOption("version")));
synopsisList.add(s1);
}
{
Synopsis s2 = new Synopsis();
s2.setInvocation(Tools.progName());
ArrayList args = new ArrayList(model.getOptions());
args.remove(model.getOption("version"));
/*ArgumentModel> options = new ArgumentModel();
options.setMultiplicity(Multiplicity._0_OR_MORE);
options.setName("cey\u2011options");
args.add(options);*/
ArgumentModel> command = new ArgumentModel();
command.setMultiplicity(Multiplicity._1);
command.setName("command");
args.add(command);
ArgumentModel> commandOptions = new ArgumentModel();
commandOptions.setMultiplicity(Multiplicity._0_OR_MORE);
commandOptions.setName("command\u2011options");
args.add(commandOptions);
ArgumentModel> commandArgs = new ArgumentModel();
commandArgs.setMultiplicity(Multiplicity._0_OR_MORE);
commandArgs.setName("command\u2011args");
args.add(commandArgs);
s2.setOptionsAndArguments(args);
synopsisList.add(s2);
}
synopsis.setSynopses(synopsisList);
return synopsis;
}
private DescribedSection buildRootDescription(
ToolModel> rootModel) {
StringBuilder sb = new StringBuilder();
final String newline = "\n";
sb.append(newline);
sb.append(newline);
for (String toolName : toolLoader.getToolNames()) {
final ToolModel> model = toolLoader.loadToolModel(toolName);
if (model == null) {
throw new RuntimeException(toolName);
}
if (!model.isPorcelain() && !includeHidden) {
continue;
}
sb.append("* `").append(toolName).append("` - ");
String summary = getSummaryValue(model);
if (summary != null) {
sb.append(summary);
}
sb.append(newline);
sb.append(newline);
}
sb.append(newline);
sb.append(CeylonHelpToolMessages.getMoreInfo());
sb.append(newline);
sb.append(newline);
String both = getDescription(rootModel) + sb.toString();
DescribedSection description = buildDescription(rootModel, both);
return description;
}
public Doc buildDoc(ToolModel> model) {
return buildDoc(model, false);
}
private List buildAdditionalSections(ToolModel> model) {
List additionalSections = new ArrayList();
String sections = getSections(model);
if (sections != null && !sections.isEmpty()) {
Document doc = Markdown.markdown(sections);
List markdownSections = Markdown.extractSections(doc);
for (Markdown.Section sect : markdownSections) {
DescribedSection ds = new DescribedSection();
ds.setRole(Role.ADDITIONAL);
Document sectionDoc = sect.getDoc();
if (sect.getHeading() == null) {
// TODO Warn that there were no section headings
continue;
} else {
// Adjust the heading levels, so that the most prominent
// heading is H2
Markdown.adjustHeadings(sectionDoc, 2-sect.getHeading().getLevel());
}
ds.setTitle(sect.getHeading());
ds.setDescription(sectionDoc);
additionalSections.add(ds);
}
}
return additionalSections;
}
private OptionsSection buildOptions(ToolModel> model) {
if(!(model instanceof AnnotatedToolModel))
return null;
final HashMap, OptionsSection> map = new HashMap<>();
new SubtoolVisitor(model) {
@Override
protected void visit(ToolModel> model,
SubtoolModel> subtoolModel) {
OptionsSection optionsSection = new OptionsSection();
map.put(model, optionsSection);
if (model==root) {
optionsSection.setTitle(
Markdown.markdown("##" + CeylonHelpToolMessages.msg("section.OPTIONS")));
} else {
optionsSection.setTitle(
Markdown.markdown("###" + CeylonHelpToolMessages.msg("section.OPTIONS.sub", model.getName())));
}
List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy