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, OUTPUTTYPE, SSANNOTATIONS, NOTEMPFAC, TEMPFAC, TITLE,
16 PAEMATRIX, WRAP, NOSTRUCTURE, STRUCTURE, STRUCTUREVIEWER, IMAGE, QUIT,
17 CLOSE, DEBUG("d"), QUIET("q"), ARGFILE, NEWFRAME, NPP("n++"),
18 SUBSTITUTIONS, INITSUBSTITUTIONS, NIL, SPLASH, SETARGFILE, UNSETARGFILE,
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 user.
58 HELP.setOptions("Display this help message", Opt.UNARY, Opt.BOOTSTRAP);
59 CALCULATION.setOptions(true, Opt.BOOLEAN); // default "true" implies only
60 // expecting "--nocalculation"
61 MENUBAR.setOptions(true, Opt.BOOLEAN);
62 STATUS.setOptions(true, Opt.BOOLEAN);
63 SHOWOVERVIEW.setOptions(Opt.UNARY, Opt.LINKED);
64 ANNOTATIONS.setOptions(Opt.BOOLEAN, Opt.LINKED);
65 COLOUR.setOptions(Opt.STRING, Opt.LINKED);
66 FEATURES.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
67 Opt.ALLOWSUBSTITUTIONS);
68 GROOVY.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
69 Opt.ALLOWSUBSTITUTIONS);
70 GROUPS.setOptions(Opt.STRING, Opt.LINKED);
71 HEADLESS.setOptions(Opt.UNARY, Opt.BOOTSTRAP);
72 JABAWS.setOptions(Opt.STRING);
73 DISPLAY.setOptions(true, Opt.BOOLEAN);
74 GUI.setOptions(true, Opt.BOOLEAN);
75 NEWS.setOptions(true, Opt.BOOLEAN, Opt.BOOTSTRAP);
76 SPLASH.setOptions(true, Opt.BOOLEAN, Opt.BOOTSTRAP);
77 // expects a string value
78 SORTBYTREE.setOptions(true, Opt.BOOLEAN);
79 USAGESTATS.setOptions(true, Opt.BOOLEAN);
80 APPEND.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI, Opt.GLOB,
81 Opt.ALLOWSUBSTITUTIONS);
82 OPEN.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI, Opt.GLOB,
83 Opt.ALLOWSUBSTITUTIONS);
84 PROPS.setOptions(Opt.STRING, Opt.BOOTSTRAP);
85 QUESTIONNAIRE.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
86 SETPROP.setOptions(Opt.STRING, Opt.MULTI, Opt.BOOTSTRAP);
87 TREE.setOptions(Opt.STRING);
89 VDOC.setOptions(Opt.UNARY);
90 VSESS.setOptions(Opt.UNARY);
92 OUTPUT.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWSUBSTITUTIONS);
93 OUTPUTTYPE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
95 SSANNOTATIONS.setOptions(Opt.BOOLEAN, Opt.LINKED);
96 NOTEMPFAC.setOptions(Opt.UNARY, Opt.LINKED);
97 TEMPFAC.setOptions(Opt.STRING, Opt.LINKED);
98 TITLE.setOptions(Opt.STRING, Opt.LINKED);
99 PAEMATRIX.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
100 Opt.ALLOWSUBSTITUTIONS);
101 NOSTRUCTURE.setOptions(Opt.UNARY, Opt.LINKED);
102 STRUCTURE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI,
103 Opt.ALLOWSUBSTITUTIONS);
104 STRUCTUREVIEWER.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
105 WRAP.setOptions(Opt.BOOLEAN, Opt.LINKED);
106 IMAGE.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWSUBSTITUTIONS);
107 QUIT.setOptions(Opt.UNARY);
108 CLOSE.setOptions(Opt.UNARY, Opt.LINKED);
109 DEBUG.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
110 QUIET.setOptions(Opt.UNARY, Opt.MULTI, Opt.BOOTSTRAP);
111 ARGFILE.setOptions(Opt.STRING, Opt.MULTI, Opt.BOOTSTRAP, Opt.GLOB,
112 Opt.ALLOWSUBSTITUTIONS);
113 NEWFRAME.setOptions(Opt.UNARY, Opt.MULTI, Opt.NOACTION);
114 NPP.setOptions(Opt.UNARY, Opt.MULTI, Opt.NOACTION);
115 SUBSTITUTIONS.setOptions(Opt.BOOLEAN, Opt.MULTI, Opt.NOACTION);
116 INITSUBSTITUTIONS.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP, Opt.NOACTION);
117 NIL.setOptions(Opt.UNARY, Opt.LINKED, Opt.MULTI, Opt.NOACTION);
118 SETARGFILE.setOptions(Opt.STRING, Opt.MULTI, Opt.PRIVATE, Opt.NOACTION);
119 UNSETARGFILE.setOptions(Opt.MULTI, Opt.PRIVATE, Opt.NOACTION);
120 WEBSERVICEDISCOVERY.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
123 private final String[] argNames;
125 private Opt[] argOptions;
127 private boolean defaultBoolValue = false;
129 private String description = null;
136 private Arg(String... names)
138 int length = (names == null || names.length == 0
139 || (names.length == 1 && names[0] == null)) ? 1
141 this.argNames = new String[length];
142 this.argNames[0] = this.getName();
144 System.arraycopy(names, 0, this.argNames, 1, names.length);
147 public String argString()
149 return argString(false);
152 public String negateArgString()
154 return argString(true);
157 private String argString(boolean negate)
159 StringBuilder sb = new StringBuilder(ArgParser.DOUBLEDASH);
160 if (negate && hasOption(Opt.BOOLEAN))
161 sb.append(ArgParser.NEGATESTRING);
162 sb.append(getName());
163 return sb.toString();
166 public String toLongString()
168 StringBuilder sb = new StringBuilder();
169 sb.append(this.getClass().getName()).append('.').append(this.name());
171 if (getNames().length > 0)
173 sb.append(String.join("\", \"", getNames()));
174 if (getNames().length > 0)
177 sb.append("\nOpt: ");
178 // map List<Opt> to List<String> for the String.join
179 List<String> optList = Arrays.asList(argOptions).stream()
180 .map(opt -> opt.name()).collect(Collectors.toList());
181 sb.append(String.join(", ", optList));
183 return sb.toString();
186 public String[] getNames()
191 public String getName()
193 return this.name().toLowerCase(Locale.ROOT).replace('_', '-');
197 public final String toString()
202 public boolean hasOption(Opt o)
204 if (argOptions == null)
206 for (Opt option : argOptions)
214 protected void setOptions(Opt... options)
216 setOptions("", false, options);
219 protected void setOptions(String desc, Opt... options)
221 setOptions(desc, false, options);
224 protected void setOptions(boolean defaultBoolValue, Opt... options)
226 setOptions("", defaultBoolValue, options);
229 protected void setOptions(String desc, boolean defaultBoolValue,
232 this.description = desc;
233 this.defaultBoolValue = defaultBoolValue;
234 this.argOptions = options;
237 protected boolean getDefaultBoolValue()
239 return defaultBoolValue;
242 private void setDescription(String d)
247 protected String getDescription()
252 public static String booleanArgString(Arg a)
254 StringBuilder sb = new StringBuilder(a.argString());
255 if (a.hasOption(Opt.BOOLEAN))
258 sb.append(a.negateArgString());
260 return sb.toString();
263 public static final String usage()
265 StringBuilder sb = new StringBuilder();
267 sb.append("Usage: jalview [args]");
268 sb.append(System.lineSeparator());
270 int maxArgLength = 0;
271 for (Arg a : EnumSet.allOf(Arg.class))
273 if (a.hasOption(Opt.PRIVATE))
275 StringBuilder argSb = new StringBuilder();
276 argSb.append(a.hasOption(Opt.BOOLEAN) ? booleanArgString(a)
278 if (a.hasOption(Opt.STRING))
279 argSb.append("=value");
280 if (argSb.length() > maxArgLength)
281 maxArgLength = argSb.length();
284 // might want to sort these
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 sb.append(String.format("%-" + maxArgLength + "s - %s",
295 argSb.toString(), a.getDescription()));
297 List<String> options = new ArrayList<>();
299 if (a.hasOption(Opt.BOOLEAN))
301 options.add("default " + (a.getDefaultBoolValue() ? a.argString()
302 : a.negateArgString()));
305 if (a.hasOption(Opt.MULTI))
307 options.add("multiple");
310 if (a.hasOption(Opt.LINKED))
312 options.add("can be linked");
315 if (a.hasOption(Opt.GLOB))
317 options.add("allows file globs");
320 if (a.hasOption(Opt.ALLOWSUBSTITUTIONS))
322 options.add("allows substitutions");
325 if (options.size() > 0)
328 sb.append(String.join("; ", options));
331 sb.append(System.lineSeparator());
333 return sb.toString();