diff --git a/src/main/java/de/undercouch/citeproc/CSLTool.java b/src/main/java/de/undercouch/citeproc/CSLTool.java index 137678d8..b44c50d1 100644 --- a/src/main/java/de/undercouch/citeproc/CSLTool.java +++ b/src/main/java/de/undercouch/citeproc/CSLTool.java @@ -50,9 +50,9 @@ import de.undercouch.citeproc.helper.oauth.FileAuthenticationStore; import de.undercouch.citeproc.helper.oauth.RequestException; import de.undercouch.citeproc.helper.oauth.UnauthorizedException; -import de.undercouch.citeproc.helper.tool.Option; import de.undercouch.citeproc.helper.tool.Option.ArgumentType; import de.undercouch.citeproc.helper.tool.OptionBuilder; +import de.undercouch.citeproc.helper.tool.OptionGroup; import de.undercouch.citeproc.helper.tool.OptionParser; import de.undercouch.citeproc.helper.tool.OptionParserException; import de.undercouch.citeproc.helper.tool.Value; @@ -99,12 +99,9 @@ private static enum FileFormat { /** * A list of possible command line options for this tool */ - private static List> options = new OptionBuilder() + private static OptionGroup options = new OptionBuilder() .add(OID.BIBLIOGRAPHY, "bibliography", "b", "input bibliography FILE (*.bib, *.json)", "FILE", ArgumentType.STRING) - .add(OID.MENDELEY, "mendeley", "read input bibliography from Mendeley Web") - .add(OID.MENDELEY_SYNC, "mendeley-sync", "synchronize with Mendeley Web, " - + "implies --mendeley") .add(OID.STYLE, "style", "s", "citation STYLE name (default: ieee)", "STYLE", ArgumentType.STRING) .add(OID.LOCALE, "locale", "l", "citation LOCALE (default: en-US)", @@ -113,8 +110,17 @@ private static enum FileFormat { "FORMAT", ArgumentType.STRING) .add(OID.CITATION, "citation", "c", "generate citations and not a bibliography") .add(OID.LIST, "list", "display sorted list of available citation IDs") - .add(OID.HELP, "help", "h", "display this help and exit") - .add(OID.VERSION, "version", "V", "output version information and exit") + .add(new OptionBuilder("Mendeley:") + .add(OID.MENDELEY, "mendeley", "read input bibliography from Mendeley Web") + .add(OID.MENDELEY_SYNC, "mendeley-sync", "synchronize with Mendeley Web, " + + "implies --mendeley") + .build() + ) + .add(new OptionBuilder("Miscellaneous:") + .add(OID.HELP, "help", "h", "display this help and exit") + .add(OID.VERSION, "version", "V", "output version information and exit") + .build() + ) .build(); /** diff --git a/src/main/java/de/undercouch/citeproc/helper/tool/OptionBuilder.java b/src/main/java/de/undercouch/citeproc/helper/tool/OptionBuilder.java index 3a8fc706..5b982adc 100644 --- a/src/main/java/de/undercouch/citeproc/helper/tool/OptionBuilder.java +++ b/src/main/java/de/undercouch/citeproc/helper/tool/OptionBuilder.java @@ -14,18 +14,31 @@ package de.undercouch.citeproc.helper.tool; -import java.util.ArrayList; -import java.util.List; - import de.undercouch.citeproc.helper.tool.Option.ArgumentType; /** - * Builder for a list of command line options + * Builder for a group of command line options * @author Michel Kraemer * @param identifier type */ public class OptionBuilder { - private List> options = new ArrayList>(); + private final OptionGroup options; + + /** + * Creates a new option builder + */ + public OptionBuilder() { + options = new OptionGroup(); + } + + /** + * Creates a new option builder + * @param groupName the name of the option group the builder will create + * when calling {@link #build()} + */ + public OptionBuilder(String groupName) { + options = new OptionGroup(groupName); + } /** * Adds a new option without arguments @@ -35,7 +48,7 @@ public class OptionBuilder { * @return this option builder */ public OptionBuilder add(T id, String longName, String description) { - options.add(new Option(id, longName, description)); + options.addOption(new Option(id, longName, description)); return this; } @@ -49,7 +62,7 @@ public OptionBuilder add(T id, String longName, String description) { * @return this option builder */ public OptionBuilder add(T id, String longName, String shortName, String description) { - options.add(new Option(id, longName, shortName, description)); + options.addOption(new Option(id, longName, shortName, description)); return this; } @@ -68,14 +81,24 @@ public OptionBuilder add(T id, String longName, String shortName, String desc */ public OptionBuilder add(T id, String longName, String shortName, String description, String argumentName, ArgumentType argumentType) { - options.add(new Option(id, longName, shortName, description, argumentName, argumentType)); + options.addOption(new Option(id, longName, shortName, description, argumentName, argumentType)); + return this; + } + + /** + * Adds a new option group + * @param group the group to add + * @return this option builder + */ + public OptionBuilder add(OptionGroup group) { + options.addChild(group); return this; } /** - * @return the built list of options + * @return the built group of options */ - public List> build() { + public OptionGroup build() { return options; } } diff --git a/src/main/java/de/undercouch/citeproc/helper/tool/OptionGroup.java b/src/main/java/de/undercouch/citeproc/helper/tool/OptionGroup.java new file mode 100644 index 00000000..4bbf5cfe --- /dev/null +++ b/src/main/java/de/undercouch/citeproc/helper/tool/OptionGroup.java @@ -0,0 +1,93 @@ +// Copyright 2013 Michel Kraemer +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package de.undercouch.citeproc.helper.tool; + +import java.util.ArrayList; +import java.util.List; + +/** + * A group of command line options + * @author Michel Kraemer + * @param identifier type + */ +public class OptionGroup { + private final String name; + private final List> options = new ArrayList>(); + private final List> children = new ArrayList>(); + + /** + * Creates a new option group with no name + */ + public OptionGroup() { + this.name = ""; + } + + /** + * Creates a new option group + * @param name the group's name + */ + public OptionGroup(String name) { + this.name = name; + } + + /** + * @return the group's name + */ + public String getName() { + return name; + } + + /** + * @return the options in this group + */ + public List> getOptions() { + return options; + } + + /** + * @return a flat list of options in this group and all options from all children + */ + public List> getFlatOptions() { + List> result = new ArrayList>(); + result.addAll(getOptions()); + for (OptionGroup g : getChildren()) { + result.addAll(g.getFlatOptions()); + } + return result; + } + + /** + * @return the group's children + */ + public List> getChildren() { + return children; + } + + /** + * Adds an option to this group + * @param o the option to add + */ + public void addOption(Option o) { + options.add(o); + } + + /** + * Adds a child to this group + * @param c the child to add + */ + public void addChild(OptionGroup c) { + children.add(c); + } +} diff --git a/src/main/java/de/undercouch/citeproc/helper/tool/OptionParser.java b/src/main/java/de/undercouch/citeproc/helper/tool/OptionParser.java index a9e3ff0f..18631c27 100644 --- a/src/main/java/de/undercouch/citeproc/helper/tool/OptionParser.java +++ b/src/main/java/de/undercouch/citeproc/helper/tool/OptionParser.java @@ -35,7 +35,7 @@ public class OptionParser { * @param out destination stream */ public static void usage(String command, String description, - List> options, PrintStream out) { + OptionGroup options, PrintStream out) { out.println("Usage: " + command); out.println(description); out.println(); @@ -43,7 +43,7 @@ public static void usage(String command, String description, //calculate column widths int firstColumnWidth = 0; int secondColumnWidth = 0; - for (Option o : options) { + for (Option o : options.getFlatOptions()) { //calculate width of first column (short name) if (o.getShortName() != null) { int fcw = o.getShortName().length() + 1; @@ -63,7 +63,18 @@ public static void usage(String command, String description, } //output options - for (Option o : options) { + printOptions(options, out, firstColumnWidth, secondColumnWidth); + } + + private static void printOptions(OptionGroup options, PrintStream out, + int firstColumnWidth, int secondColumnWidth) { + //print group name (if any) + if (options.getName() != null && !options.getName().isEmpty()) { + System.out.println(); + System.out.println(options.getName()); + } + + for (Option o : options.getOptions()) { out.print(" "); //output short name @@ -115,6 +126,11 @@ public static void usage(String command, String description, } out.println(desc); } + + //print children + for (OptionGroup c : options.getChildren()) { + printOptions(c, out, firstColumnWidth, secondColumnWidth); + } } /** @@ -128,7 +144,7 @@ public static void usage(String command, String description, * @throws MissingArgumentException if an option misses a required argument * @throws InvalidOptionException if one of the arguments is unknown */ - public static List> parse(String[] args, List> options, + public static List> parse(String[] args, OptionGroup options, T def) throws MissingArgumentException, InvalidOptionException { List> result = new ArrayList>(); for (int i = 0; i < args.length; ++i) { @@ -139,7 +155,7 @@ public static List> parse(String[] args, List> options, if (a.startsWith("--")) { //handle long name options String an = a.substring(2); - for (Option o : options) { + for (Option o : options.getFlatOptions()) { if (o.getLongName().equals(an)) { i += parseValue(o, args, i, result); found = true; @@ -149,7 +165,7 @@ public static List> parse(String[] args, List> options, } else if (a.startsWith("-")) { //handle short name options String an = a.substring(1); - for (Option o : options) { + for (Option o : options.getFlatOptions()) { if (o.getShortName() != null && o.getShortName().equals(an)) { i += parseValue(o, args, i, result); found = true;