1 package jalview.bin.argparser;
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.EnumSet;
7 import java.util.Locale;
8 import java.util.stream.Collectors;
12 HELP("h"), CALCULATION, MENUBAR, STATUS, SHOWOVERVIEW, SHOWANNOTATIONS,
13 COLOUR("color"), FEATURES, ANNOTATIONS, GROOVY, GROUPS, HEADLESS, JABAWS,
14 DISPLAY, NEWS, SORTBYTREE, USAGESTATS, APPEND, OPEN, PROPS, QUESTIONNAIRE,
15 SETPROP, TREE, VDOC, VSESS, OUTPUT, SSANNOTATIONS, NOTEMPFAC, TEMPFAC,
16 TITLE, PAEMATRIX, WRAP, NOSTRUCTURE, STRUCTURE, STRUCTUREVIEWER, IMAGE,
17 TYPE, FORMAT, OVERWRITE, TEXTRENDERER, QUIT, CLOSE, DEBUG("d"), TRACE,
18 QUIET("q"), ARGFILE, NEW, NPP("n++"), SUBSTITUTIONS, INITSUBSTITUTIONS,
19 NIL, SPLASH, SETARGFILE, UNSETARGFILE, WEBSERVICEDISCOVERY, ALL, BACKUPS,
22 public static enum Opt
24 BOOLEAN, // This Arg can be specified as --arg or --noarg to give true or
25 // false. A default can be given with setOptions(bool, Opt....).
26 // Use ArgParser.isSet(Arg) to see if this arg was not specified.
27 STRING, // This Arg can accept a value either through --arg=value or --arg
29 UNARY, // This Arg is a boolean value, true if present, false if not. Like
30 // BOOLEAN but without the --noarg option.
31 MULTI, // This Arg can be specified multiple times. Multiple values are
32 // stored in the ArgValuesMap (along with their positional index) for
34 LINKED, // This Arg can be linked to others through a --arg[linkedId] or
35 // --arg[linkedId]=value. If no linkedId is specified then the
36 // current default linkedId will be used.
37 NODUPLICATEVALUES, // This Arg can only have one value (per linkedId). The
38 // first value will be used and subsequent values ignored
40 BOOTSTRAP, // This Arg value(s) can be determined at an earlier stage than
41 // non-BOOTSTRAP Args. Substitutions do not happen in BOOTSTRAP
42 // Args and they cannot be linked or contain SubVals. See
43 // jalview.bin.argparser.BootstrapArgs.
44 GLOB, // This Arg can expand wildcard filename "globs" (e.g.
45 // path/*/filename*). If the Arg value is given as --arg filename*
46 // then the shell will have expanded the glob already, but if
47 // specified as --arg=filename* then the Java glob expansion method
48 // will be used (see FileUtils.getFilenamesFromGlob()). Note that this
49 // might be different from the shell expansion rules.
50 NOACTION, // This Arg does not perform a data task, usually used to control
51 // flow in ArgParser.parse(args).
52 ALLOWSUBSTITUTIONS, // This Arg allows substitutions in its linkedId,
53 // SubVals and values.
54 PRIVATE, // This Arg is used internally, and cannot be specified by the
56 ALLOWALL, // This Arg can use the '*' linkedId to apply to all known
58 INCREMENTDEFAULTCOUNTER, // If an Arg has this option and the default
59 // linkedId is used, the defaultLinkedIdCounter is
60 // incremented *first*.
61 INPUT, // This Arg counts as an input for REQUIREINPUT
62 REQUIREINPUT, // This Arg can only be applied via --all if there is an
63 // input (i.e. --open or --append)
68 HELP.setOptions("Display this help message", Opt.UNARY, Opt.BOOTSTRAP);
69 CALCULATION.setOptions(true, Opt.BOOLEAN); // default "true" implies only
70 // expecting "--nocalculation"
71 MENUBAR.setOptions(true, Opt.BOOLEAN);
72 STATUS.setOptions(true, Opt.BOOLEAN);
73 SHOWOVERVIEW.setOptions(Opt.UNARY, Opt.LINKED);
74 SHOWANNOTATIONS.setOptions(Opt.BOOLEAN, Opt.LINKED);
75 COLOUR.setOptions(Opt.STRING, Opt.LINKED);
76 FEATURES.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
77 Opt.ALLOWSUBSTITUTIONS);
78 ANNOTATIONS.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
79 Opt.ALLOWSUBSTITUTIONS);
80 TREE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
81 Opt.ALLOWSUBSTITUTIONS);
82 GROOVY.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
83 Opt.ALLOWSUBSTITUTIONS);
84 GROUPS.setOptions(Opt.STRING, Opt.LINKED);
85 HEADLESS.setOptions(Opt.UNARY, Opt.BOOTSTRAP);
86 TESTOUTPUT.setOptions(Opt.UNARY, Opt.BOOTSTRAP);
87 JABAWS.setOptions(Opt.STRING, Opt.BOOTSTRAP);
88 DISPLAY.setOptions(true, Opt.BOOLEAN);
89 NEWS.setOptions(true, Opt.BOOLEAN, Opt.BOOTSTRAP);
90 SPLASH.setOptions(true, Opt.BOOLEAN, Opt.BOOTSTRAP);
91 SORTBYTREE.setOptions(true, Opt.LINKED, Opt.BOOLEAN);
92 QUESTIONNAIRE.setOptions(true, Opt.BOOLEAN, Opt.BOOTSTRAP);
93 USAGESTATS.setOptions(true, Opt.BOOLEAN, Opt.BOOTSTRAP);
94 WEBSERVICEDISCOVERY.setOptions(true, Opt.BOOLEAN, Opt.BOOTSTRAP);
95 APPEND.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI, Opt.GLOB,
96 Opt.ALLOWSUBSTITUTIONS, Opt.INPUT);
97 OPEN.setOptions(Opt.STRING, Opt.LINKED, Opt.INCREMENTDEFAULTCOUNTER,
98 Opt.MULTI, Opt.GLOB, Opt.ALLOWSUBSTITUTIONS, Opt.INPUT);
99 PROPS.setOptions(Opt.STRING, Opt.BOOTSTRAP);
100 SETPROP.setOptions(Opt.STRING, Opt.MULTI, Opt.BOOTSTRAP);
102 VDOC.setOptions(Opt.UNARY);
103 VSESS.setOptions(Opt.UNARY);
105 OUTPUT.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWSUBSTITUTIONS,
106 Opt.ALLOWALL, Opt.REQUIREINPUT);
108 SSANNOTATIONS.setOptions(Opt.BOOLEAN, Opt.LINKED);
109 NOTEMPFAC.setOptions(Opt.UNARY, Opt.LINKED);
110 TEMPFAC.setOptions(Opt.STRING, Opt.LINKED);
111 TITLE.setOptions(Opt.STRING, Opt.LINKED);
112 PAEMATRIX.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
113 Opt.ALLOWSUBSTITUTIONS);
114 SEQID.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
115 Opt.ALLOWSUBSTITUTIONS);
116 NOSTRUCTURE.setOptions(Opt.UNARY, Opt.LINKED);
117 STRUCTURE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
118 Opt.ALLOWSUBSTITUTIONS);
119 STRUCTUREVIEWER.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
120 WRAP.setOptions(Opt.BOOLEAN, Opt.LINKED);
121 IMAGE.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWSUBSTITUTIONS,
122 Opt.ALLOWALL, Opt.REQUIREINPUT);
123 TYPE.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWALL);
124 FORMAT.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWALL);
125 TEXTRENDERER.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWALL);
126 QUIT.setOptions(Opt.UNARY);
127 OVERWRITE.setOptions(Opt.BOOLEAN, Opt.LINKED, Opt.ALLOWALL);
128 BACKUPS.setOptions(true, Opt.BOOLEAN, Opt.LINKED, Opt.ALLOWALL);
129 CLOSE.setOptions(Opt.UNARY, Opt.LINKED, Opt.ALLOWALL);
130 DEBUG.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
131 TRACE.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
132 QUIET.setOptions(Opt.UNARY, Opt.MULTI, Opt.BOOTSTRAP);
133 ARGFILE.setOptions(Opt.STRING, Opt.MULTI, Opt.BOOTSTRAP, Opt.GLOB,
134 Opt.ALLOWSUBSTITUTIONS);
135 NEW.setOptions(Opt.UNARY, Opt.MULTI, Opt.NOACTION,
136 Opt.INCREMENTDEFAULTCOUNTER);
137 NPP.setOptions(Opt.UNARY, Opt.MULTI, Opt.NOACTION);
138 SUBSTITUTIONS.setOptions(Opt.BOOLEAN, Opt.MULTI, Opt.NOACTION);
139 INITSUBSTITUTIONS.setOptions(true, Opt.BOOLEAN, Opt.BOOTSTRAP,
140 Opt.NOACTION); // defaulting substitutions to true
141 NIL.setOptions(Opt.UNARY, Opt.LINKED, Opt.MULTI, Opt.NOACTION);
142 SETARGFILE.setOptions(Opt.STRING, Opt.MULTI, Opt.PRIVATE, Opt.NOACTION);
143 UNSETARGFILE.setOptions(Opt.MULTI, Opt.PRIVATE, Opt.NOACTION);
144 ALL.setOptions(Opt.BOOLEAN, Opt.MULTI, Opt.NOACTION);
148 private final String[] argNames;
150 private Opt[] argOptions;
152 private boolean defaultBoolValue = false;
154 private String description = null;
161 private Arg(String... names)
163 int length = (names == null || names.length == 0
164 || (names.length == 1 && names[0] == null)) ? 1
166 this.argNames = new String[length];
167 this.argNames[0] = this.getName();
169 System.arraycopy(names, 0, this.argNames, 1, names.length);
172 public String argString()
174 return argString(false);
177 public String negateArgString()
179 return argString(true);
182 private String argString(boolean negate)
184 StringBuilder sb = new StringBuilder(ArgParser.DOUBLEDASH);
185 if (negate && hasOption(Opt.BOOLEAN))
186 sb.append(ArgParser.NEGATESTRING);
187 sb.append(getName());
188 return sb.toString();
191 public String toLongString()
193 StringBuilder sb = new StringBuilder();
194 sb.append(this.getClass().getName()).append('.').append(this.name());
196 if (getNames().length > 0)
198 sb.append(String.join("\", \"", getNames()));
199 if (getNames().length > 0)
202 sb.append("\nOpt: ");
203 // map List<Opt> to List<String> for the String.join
204 List<String> optList = Arrays.asList(argOptions).stream()
205 .map(opt -> opt.name()).collect(Collectors.toList());
206 sb.append(String.join(", ", optList));
208 return sb.toString();
211 public String[] getNames()
216 public String getName()
218 return this.name().toLowerCase(Locale.ROOT).replace('_', '-');
222 public final String toString()
227 public boolean hasOption(Opt o)
229 if (argOptions == null)
231 for (Opt option : argOptions)
239 protected void setOptions(Opt... options)
241 setOptions("", false, options);
244 protected void setOptions(String desc, Opt... options)
246 setOptions(desc, false, options);
249 protected void setOptions(boolean defaultBoolValue, Opt... options)
251 setOptions("", defaultBoolValue, options);
254 protected void setOptions(String desc, boolean defaultBoolValue,
257 this.description = desc;
258 this.defaultBoolValue = defaultBoolValue;
259 this.argOptions = options;
262 protected boolean getDefaultBoolValue()
264 return defaultBoolValue;
267 private void setDescription(String d)
272 protected String getDescription()
277 public static String booleanArgString(Arg a)
279 StringBuilder sb = new StringBuilder(a.argString());
280 if (a.hasOption(Opt.BOOLEAN))
283 sb.append(a.negateArgString());
285 return sb.toString();
288 public static final String usage()
290 StringBuilder sb = new StringBuilder();
292 sb.append("Usage: jalview [args]");
293 sb.append(System.lineSeparator());
295 int maxArgLength = 0;
296 for (Arg a : EnumSet.allOf(Arg.class))
298 if (a.hasOption(Opt.PRIVATE))
300 StringBuilder argSb = new StringBuilder();
301 argSb.append(a.hasOption(Opt.BOOLEAN) ? booleanArgString(a)
303 if (a.hasOption(Opt.STRING))
304 argSb.append("=value");
305 if (argSb.length() > maxArgLength)
306 maxArgLength = argSb.length();
309 // might want to sort these
310 for (Arg a : EnumSet.allOf(Arg.class))
312 if (a.hasOption(Opt.PRIVATE))
314 StringBuilder argSb = new StringBuilder();
315 argSb.append(a.hasOption(Opt.BOOLEAN) ? booleanArgString(a)
317 if (a.hasOption(Opt.STRING))
318 argSb.append("=value");
319 sb.append(String.format("%-" + maxArgLength + "s - %s",
320 argSb.toString(), a.getDescription()));
322 List<String> options = new ArrayList<>();
324 if (a.hasOption(Opt.BOOLEAN))
326 options.add("default " + (a.getDefaultBoolValue() ? a.argString()
327 : a.negateArgString()));
330 if (a.hasOption(Opt.MULTI))
332 options.add("multiple");
335 if (a.hasOption(Opt.LINKED))
337 options.add("can be linked");
340 if (a.hasOption(Opt.GLOB))
342 options.add("allows file globs");
345 if (a.hasOption(Opt.ALLOWSUBSTITUTIONS))
347 options.add("allows substitutions");
350 if (options.size() > 0)
353 sb.append(String.join("; ", options));
356 sb.append(System.lineSeparator());
358 return sb.toString();