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, ANNOTATIONS,
13 COLOUR, FEATURES, GROOVY, GROUPS, HEADLESS, JABAWS, DISPLAY, GUI, NEWS,
14 SORTBYTREE, USAGESTATS, APPEND, OPEN, PROPS, QUESTIONNAIRE, SETPROP, TREE,
15 VDOC, VSESS, OUTPUT, SSANNOTATIONS, NOTEMPFAC, TEMPFAC, TITLE, PAEMATRIX,
16 WRAP, NOSTRUCTURE, STRUCTURE, STRUCTUREVIEWER, IMAGE, TYPE, RENDERER,
17 QUIT, CLOSE, DEBUG("d"), QUIET("q"), ARGFILE, NEWFRAME, NPP("n++"),
18 SUBSTITUTIONS, INITSUBSTITUTIONS, NIL, SPLASH, SETARGFILE, UNSETARGFILE,
19 WEBSERVICEDISCOVERY, ALLFRAMES;
21 protected static enum Opt
23 BOOLEAN, // This Arg can be specified as --arg or --noarg to give true or
24 // false. A default can be given with setOptions(bool, Opt....).
25 // Use ArgParser.isSet(Arg) to see if this arg was not specified.
26 STRING, // This Arg can accept a value either through --arg=value or --arg
28 UNARY, // This Arg is a boolean value, true if present, false if not. Like
29 // BOOLEAN but without the --noarg option.
30 MULTI, // This Arg can be specified multiple times. Multiple values are
31 // stored in the ArgValuesMap (along with their positional index) for
33 LINKED, // This Arg can be linked to others through a --arg[linkedId] or
34 // --arg[linkedId]=value. If no linkedId is specified then the
35 // current default linkedId will be used.
36 NODUPLICATEVALUES, // This Arg can only have one value (per linkedId). The
37 // first value will be used and subsequent values ignored
39 BOOTSTRAP, // This Arg value(s) can be determined at an earlier stage than
40 // non-BOOTSTRAP Args. Substitutions do not happen in BOOTSTRAP
41 // Args and they cannot be linked or contain SubVals. See
42 // jalview.bin.argparser.BootstrapArgs.
43 GLOB, // This Arg can expand wildcard filename "globs" (e.g.
44 // path/*/filename*). If the Arg value is given as --arg filename*
45 // then the shell will have expanded the glob already, but if
46 // specified as --arg=filename* then the Java glob expansion method
47 // will be used (see FileUtils.getFilenamesFromGlob()). Note that this
48 // might be different from the shell expansion rules.
49 NOACTION, // This Arg does not perform a data task, usually used to control
50 // flow in ArgParser.parse(args).
51 ALLOWSUBSTITUTIONS, // This Arg allows substitutions in its linkedId,
52 // SubVals and values.
53 PRIVATE, // This Arg is used internally, and cannot be specified by the
55 ALLOWALL, // This Arg can use the '*' linkedId to apply to all known
57 INCREMENTDEFAULTCOUNTER, // If an Arg has this option and the default
58 // linkedId is used, the defaultLinkedIdCounter is
59 // incremented *first*.
60 INPUT, // This Arg counts as an input for REQUIREINPUT
61 REQUIREINPUT, // This Arg can only be applied via --allframes if there is an
62 // input (i.e. --open or --append)
67 HELP.setOptions("Display this help message", Opt.UNARY, Opt.BOOTSTRAP);
68 CALCULATION.setOptions(true, Opt.BOOLEAN); // default "true" implies only
69 // expecting "--nocalculation"
70 MENUBAR.setOptions(true, Opt.BOOLEAN);
71 STATUS.setOptions(true, Opt.BOOLEAN);
72 SHOWOVERVIEW.setOptions(Opt.UNARY, Opt.LINKED);
73 ANNOTATIONS.setOptions(Opt.BOOLEAN, Opt.LINKED);
74 COLOUR.setOptions(Opt.STRING, Opt.LINKED);
75 FEATURES.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
76 Opt.ALLOWSUBSTITUTIONS);
77 GROOVY.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
78 Opt.ALLOWSUBSTITUTIONS);
79 GROUPS.setOptions(Opt.STRING, Opt.LINKED);
80 HEADLESS.setOptions(Opt.UNARY, Opt.BOOTSTRAP);
81 JABAWS.setOptions(Opt.STRING);
82 DISPLAY.setOptions(true, Opt.BOOLEAN);
83 GUI.setOptions(true, Opt.BOOLEAN);
84 NEWS.setOptions(true, Opt.BOOLEAN, Opt.BOOTSTRAP);
85 SPLASH.setOptions(true, Opt.BOOLEAN, Opt.BOOTSTRAP);
86 // expects a string value
87 SORTBYTREE.setOptions(true, Opt.BOOLEAN);
88 USAGESTATS.setOptions(true, Opt.BOOLEAN);
89 APPEND.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI, Opt.GLOB,
90 Opt.ALLOWSUBSTITUTIONS, Opt.INPUT);
91 OPEN.setOptions(Opt.STRING, Opt.LINKED, Opt.INCREMENTDEFAULTCOUNTER,
92 Opt.MULTI, Opt.GLOB, Opt.ALLOWSUBSTITUTIONS, Opt.INPUT);
93 PROPS.setOptions(Opt.STRING, Opt.BOOTSTRAP);
94 QUESTIONNAIRE.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
95 SETPROP.setOptions(Opt.STRING, Opt.MULTI, Opt.BOOTSTRAP);
96 TREE.setOptions(Opt.STRING);
98 VDOC.setOptions(Opt.UNARY);
99 VSESS.setOptions(Opt.UNARY);
101 OUTPUT.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWSUBSTITUTIONS,
102 Opt.ALLOWALL, Opt.REQUIREINPUT);
104 SSANNOTATIONS.setOptions(Opt.BOOLEAN, Opt.LINKED);
105 NOTEMPFAC.setOptions(Opt.UNARY, Opt.LINKED);
106 TEMPFAC.setOptions(Opt.STRING, Opt.LINKED);
107 TITLE.setOptions(Opt.STRING, Opt.LINKED);
108 PAEMATRIX.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
109 Opt.ALLOWSUBSTITUTIONS);
110 NOSTRUCTURE.setOptions(Opt.UNARY, Opt.LINKED);
111 STRUCTURE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
112 Opt.ALLOWSUBSTITUTIONS);
113 STRUCTUREVIEWER.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
114 WRAP.setOptions(Opt.BOOLEAN, Opt.LINKED);
115 IMAGE.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWSUBSTITUTIONS,
116 Opt.ALLOWALL, Opt.REQUIREINPUT);
117 TYPE.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWALL);
118 RENDERER.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWALL);
119 QUIT.setOptions(Opt.UNARY);
120 CLOSE.setOptions(Opt.UNARY, Opt.LINKED, Opt.ALLOWALL);
121 DEBUG.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
122 QUIET.setOptions(Opt.UNARY, Opt.MULTI, Opt.BOOTSTRAP);
123 ARGFILE.setOptions(Opt.STRING, Opt.MULTI, Opt.BOOTSTRAP, Opt.GLOB,
124 Opt.ALLOWSUBSTITUTIONS);
125 NEWFRAME.setOptions(Opt.UNARY, Opt.MULTI, Opt.NOACTION);
126 NPP.setOptions(Opt.UNARY, Opt.MULTI, Opt.NOACTION);
127 SUBSTITUTIONS.setOptions(Opt.BOOLEAN, Opt.MULTI, Opt.NOACTION);
128 INITSUBSTITUTIONS.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP, Opt.NOACTION);
129 NIL.setOptions(Opt.UNARY, Opt.LINKED, Opt.MULTI, Opt.NOACTION);
130 SETARGFILE.setOptions(Opt.STRING, Opt.MULTI, Opt.PRIVATE, Opt.NOACTION);
131 UNSETARGFILE.setOptions(Opt.MULTI, Opt.PRIVATE, Opt.NOACTION);
132 WEBSERVICEDISCOVERY.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
133 ALLFRAMES.setOptions(Opt.BOOLEAN, Opt.MULTI, Opt.NOACTION);
137 private final String[] argNames;
139 private Opt[] argOptions;
141 private boolean defaultBoolValue = false;
143 private String description = null;
150 private Arg(String... names)
152 int length = (names == null || names.length == 0
153 || (names.length == 1 && names[0] == null)) ? 1
155 this.argNames = new String[length];
156 this.argNames[0] = this.getName();
158 System.arraycopy(names, 0, this.argNames, 1, names.length);
161 public String argString()
163 return argString(false);
166 public String negateArgString()
168 return argString(true);
171 private String argString(boolean negate)
173 StringBuilder sb = new StringBuilder(ArgParser.DOUBLEDASH);
174 if (negate && hasOption(Opt.BOOLEAN))
175 sb.append(ArgParser.NEGATESTRING);
176 sb.append(getName());
177 return sb.toString();
180 public String toLongString()
182 StringBuilder sb = new StringBuilder();
183 sb.append(this.getClass().getName()).append('.').append(this.name());
185 if (getNames().length > 0)
187 sb.append(String.join("\", \"", getNames()));
188 if (getNames().length > 0)
191 sb.append("\nOpt: ");
192 // map List<Opt> to List<String> for the String.join
193 List<String> optList = Arrays.asList(argOptions).stream()
194 .map(opt -> opt.name()).collect(Collectors.toList());
195 sb.append(String.join(", ", optList));
197 return sb.toString();
200 public String[] getNames()
205 public String getName()
207 return this.name().toLowerCase(Locale.ROOT).replace('_', '-');
211 public final String toString()
216 public boolean hasOption(Opt o)
218 if (argOptions == null)
220 for (Opt option : argOptions)
228 protected void setOptions(Opt... options)
230 setOptions("", false, options);
233 protected void setOptions(String desc, Opt... options)
235 setOptions(desc, false, options);
238 protected void setOptions(boolean defaultBoolValue, Opt... options)
240 setOptions("", defaultBoolValue, options);
243 protected void setOptions(String desc, boolean defaultBoolValue,
246 this.description = desc;
247 this.defaultBoolValue = defaultBoolValue;
248 this.argOptions = options;
251 protected boolean getDefaultBoolValue()
253 return defaultBoolValue;
256 private void setDescription(String d)
261 protected String getDescription()
266 public static String booleanArgString(Arg a)
268 StringBuilder sb = new StringBuilder(a.argString());
269 if (a.hasOption(Opt.BOOLEAN))
272 sb.append(a.negateArgString());
274 return sb.toString();
277 public static final String usage()
279 StringBuilder sb = new StringBuilder();
281 sb.append("Usage: jalview [args]");
282 sb.append(System.lineSeparator());
284 int maxArgLength = 0;
285 for (Arg a : EnumSet.allOf(Arg.class))
287 if (a.hasOption(Opt.PRIVATE))
289 StringBuilder argSb = new StringBuilder();
290 argSb.append(a.hasOption(Opt.BOOLEAN) ? booleanArgString(a)
292 if (a.hasOption(Opt.STRING))
293 argSb.append("=value");
294 if (argSb.length() > maxArgLength)
295 maxArgLength = argSb.length();
298 // might want to sort these
299 for (Arg a : EnumSet.allOf(Arg.class))
301 if (a.hasOption(Opt.PRIVATE))
303 StringBuilder argSb = new StringBuilder();
304 argSb.append(a.hasOption(Opt.BOOLEAN) ? booleanArgString(a)
306 if (a.hasOption(Opt.STRING))
307 argSb.append("=value");
308 sb.append(String.format("%-" + maxArgLength + "s - %s",
309 argSb.toString(), a.getDescription()));
311 List<String> options = new ArrayList<>();
313 if (a.hasOption(Opt.BOOLEAN))
315 options.add("default " + (a.getDefaultBoolValue() ? a.argString()
316 : a.negateArgString()));
319 if (a.hasOption(Opt.MULTI))
321 options.add("multiple");
324 if (a.hasOption(Opt.LINKED))
326 options.add("can be linked");
329 if (a.hasOption(Opt.GLOB))
331 options.add("allows file globs");
334 if (a.hasOption(Opt.ALLOWSUBSTITUTIONS))
336 options.add("allows substitutions");
339 if (options.size() > 0)
342 sb.append(String.join("; ", options));
345 sb.append(System.lineSeparator());
347 return sb.toString();