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, FORMAT,
17 OVERWRITE, RENDERER, QUIT, CLOSE, DEBUG("d"), TRACE, QUIET("q"), ARGFILE,
18 NEW, NPP("n++"), SUBSTITUTIONS, INITSUBSTITUTIONS, NIL, SPLASH,
19 SETARGFILE, UNSETARGFILE, WEBSERVICEDISCOVERY, ALL, BACKUPS;
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 --all 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 FORMAT.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWALL);
119 RENDERER.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWALL);
120 QUIT.setOptions(Opt.UNARY);
121 OVERWRITE.setOptions(Opt.BOOLEAN, Opt.LINKED, Opt.ALLOWALL);
122 BACKUPS.setOptions(true, Opt.BOOLEAN, Opt.LINKED, Opt.ALLOWALL);
123 CLOSE.setOptions(Opt.UNARY, Opt.LINKED, Opt.ALLOWALL);
124 DEBUG.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
125 TRACE.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
126 QUIET.setOptions(Opt.UNARY, Opt.MULTI, Opt.BOOTSTRAP);
127 ARGFILE.setOptions(Opt.STRING, Opt.MULTI, Opt.BOOTSTRAP, Opt.GLOB,
128 Opt.ALLOWSUBSTITUTIONS);
129 NEW.setOptions(Opt.UNARY, Opt.MULTI, Opt.NOACTION,
130 Opt.INCREMENTDEFAULTCOUNTER);
131 NPP.setOptions(Opt.UNARY, Opt.MULTI, Opt.NOACTION);
132 SUBSTITUTIONS.setOptions(Opt.BOOLEAN, Opt.MULTI, Opt.NOACTION);
133 INITSUBSTITUTIONS.setOptions(true, Opt.BOOLEAN, Opt.BOOTSTRAP,
134 Opt.NOACTION); // defaulting substitutions to true
135 NIL.setOptions(Opt.UNARY, Opt.LINKED, Opt.MULTI, Opt.NOACTION);
136 SETARGFILE.setOptions(Opt.STRING, Opt.MULTI, Opt.PRIVATE, Opt.NOACTION);
137 UNSETARGFILE.setOptions(Opt.MULTI, Opt.PRIVATE, Opt.NOACTION);
138 WEBSERVICEDISCOVERY.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
139 ALL.setOptions(Opt.BOOLEAN, Opt.MULTI, Opt.NOACTION);
143 private final String[] argNames;
145 private Opt[] argOptions;
147 private boolean defaultBoolValue = false;
149 private String description = null;
156 private Arg(String... names)
158 int length = (names == null || names.length == 0
159 || (names.length == 1 && names[0] == null)) ? 1
161 this.argNames = new String[length];
162 this.argNames[0] = this.getName();
164 System.arraycopy(names, 0, this.argNames, 1, names.length);
167 public String argString()
169 return argString(false);
172 public String negateArgString()
174 return argString(true);
177 private String argString(boolean negate)
179 StringBuilder sb = new StringBuilder(ArgParser.DOUBLEDASH);
180 if (negate && hasOption(Opt.BOOLEAN))
181 sb.append(ArgParser.NEGATESTRING);
182 sb.append(getName());
183 return sb.toString();
186 public String toLongString()
188 StringBuilder sb = new StringBuilder();
189 sb.append(this.getClass().getName()).append('.').append(this.name());
191 if (getNames().length > 0)
193 sb.append(String.join("\", \"", getNames()));
194 if (getNames().length > 0)
197 sb.append("\nOpt: ");
198 // map List<Opt> to List<String> for the String.join
199 List<String> optList = Arrays.asList(argOptions).stream()
200 .map(opt -> opt.name()).collect(Collectors.toList());
201 sb.append(String.join(", ", optList));
203 return sb.toString();
206 public String[] getNames()
211 public String getName()
213 return this.name().toLowerCase(Locale.ROOT).replace('_', '-');
217 public final String toString()
222 public boolean hasOption(Opt o)
224 if (argOptions == null)
226 for (Opt option : argOptions)
234 protected void setOptions(Opt... options)
236 setOptions("", false, options);
239 protected void setOptions(String desc, Opt... options)
241 setOptions(desc, false, options);
244 protected void setOptions(boolean defaultBoolValue, Opt... options)
246 setOptions("", defaultBoolValue, options);
249 protected void setOptions(String desc, boolean defaultBoolValue,
252 this.description = desc;
253 this.defaultBoolValue = defaultBoolValue;
254 this.argOptions = options;
257 protected boolean getDefaultBoolValue()
259 return defaultBoolValue;
262 private void setDescription(String d)
267 protected String getDescription()
272 public static String booleanArgString(Arg a)
274 StringBuilder sb = new StringBuilder(a.argString());
275 if (a.hasOption(Opt.BOOLEAN))
278 sb.append(a.negateArgString());
280 return sb.toString();
283 public static final String usage()
285 StringBuilder sb = new StringBuilder();
287 sb.append("Usage: jalview [args]");
288 sb.append(System.lineSeparator());
290 int maxArgLength = 0;
291 for (Arg a : EnumSet.allOf(Arg.class))
293 if (a.hasOption(Opt.PRIVATE))
295 StringBuilder argSb = new StringBuilder();
296 argSb.append(a.hasOption(Opt.BOOLEAN) ? booleanArgString(a)
298 if (a.hasOption(Opt.STRING))
299 argSb.append("=value");
300 if (argSb.length() > maxArgLength)
301 maxArgLength = argSb.length();
304 // might want to sort these
305 for (Arg a : EnumSet.allOf(Arg.class))
307 if (a.hasOption(Opt.PRIVATE))
309 StringBuilder argSb = new StringBuilder();
310 argSb.append(a.hasOption(Opt.BOOLEAN) ? booleanArgString(a)
312 if (a.hasOption(Opt.STRING))
313 argSb.append("=value");
314 sb.append(String.format("%-" + maxArgLength + "s - %s",
315 argSb.toString(), a.getDescription()));
317 List<String> options = new ArrayList<>();
319 if (a.hasOption(Opt.BOOLEAN))
321 options.add("default " + (a.getDefaultBoolValue() ? a.argString()
322 : a.negateArgString()));
325 if (a.hasOption(Opt.MULTI))
327 options.add("multiple");
330 if (a.hasOption(Opt.LINKED))
332 options.add("can be linked");
335 if (a.hasOption(Opt.GLOB))
337 options.add("allows file globs");
340 if (a.hasOption(Opt.ALLOWSUBSTITUTIONS))
342 options.add("allows substitutions");
345 if (options.size() > 0)
348 sb.append(String.join("; ", options));
351 sb.append(System.lineSeparator());
353 return sb.toString();