X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fbin%2Fargparser%2FArgParser.java;h=fd42bb24a506e3903c3fbbac38317c9d1cdc98d6;hb=85240f268c71a9d0dc91dc196a93cb10d29794d3;hp=907b1fa5911717be31bbbb3b635940371a9df787;hpb=388622051f3d669942d9df63557c7a1401d7ff6d;p=jalview.git diff --git a/src/jalview/bin/argparser/ArgParser.java b/src/jalview/bin/argparser/ArgParser.java index 907b1fa..fd42bb2 100644 --- a/src/jalview/bin/argparser/ArgParser.java +++ b/src/jalview/bin/argparser/ArgParser.java @@ -31,12 +31,11 @@ import java.util.EnumSet; import java.util.Enumeration; import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; -import jalview.bin.Cache; import jalview.bin.Console; import jalview.bin.Jalview; +import jalview.bin.Jalview.ExitCode; import jalview.bin.argparser.Arg.Opt; import jalview.bin.argparser.Arg.Type; import jalview.util.FileUtils; @@ -50,6 +49,8 @@ public class ArgParser public static final char EQUALS = '='; + public static final String STDOUTFILENAME = "-"; + protected static final String NEGATESTRING = "no"; /** @@ -148,12 +149,6 @@ public class ArgParser private boolean allLinkedIds = false; /** - * flag to say whether the default linkedId is the current default linked id - * or OPENED linkedIds - */ - private boolean openedLinkedIds = false; - - /** * flag to say whether the structure arguments should be applied to all * structures with this linked id */ @@ -175,6 +170,15 @@ public class ArgParser private BootstrapArgs bootstrapArgs = null; + private boolean oldArguments = false; + + private boolean mixedArguments = false; + + /** + * saved examples of mixed arguments + */ + private String[] mixedExamples = new String[] { null, null }; + static { argMap = new HashMap<>(); @@ -209,12 +213,15 @@ public class ArgParser public ArgParser(String[] args, boolean initsubstitutions, BootstrapArgs bsa) { - // Make a mutable new ArrayList so that shell globbing parser works. - // (When shell file globbing is used, there are a sequence of non-Arg - // arguments (which are the expanded globbed filenames) that need to be - // consumed by the --append/--argfile/etc Arg which is most easily done by - // removing these filenames from the list one at a time. This can't be done - // with an ArrayList made with only Arrays.asList(String[] args). ) + /* + * Make a mutable new ArrayList so that shell globbing parser works. + * (When shell file globbing is used, there are a sequence of non-Arg + * arguments (which are the expanded globbed filenames) that need to be + * consumed by the --append/--argfile/etc Arg which is most easily done + * by removing these filenames from the list one at a time. This can't be + * done with an ArrayList made with only Arrays.asList(String[] args) as + * that is not mutable. ) + */ this(new ArrayList<>(Arrays.asList(args)), initsubstitutions, false, bsa); } @@ -236,19 +243,40 @@ public class ArgParser if (arg.startsWith(DOUBLEDASH)) { dd = true; - break; + if (mixedExamples[1] == null) + { + mixedExamples[1] = arg; + } } - else if (arg.startsWith("-") || arg.equals("open")) + else if ((arg.startsWith("-") && !arg.equals(STDOUTFILENAME)) + || arg.equals("open")) { d = true; + if (mixedExamples[0] == null) + { + mixedExamples[0] = arg; + } } } - if (d && !dd) + if (d) + { + if (dd) + { + mixedArguments = true; + } + else + { + oldArguments = true; + } + } + + if (oldArguments || mixedArguments) { // leave it to the old style -- parse an empty list parse(new ArrayList(), false, false); return; } + if (bsa != null) this.bootstrapArgs = bsa; else @@ -260,27 +288,30 @@ public class ArgParser boolean allowPrivate) { this.substitutions = initsubstitutions; - boolean openEachInitialFilenames = true; - for (int i = 0; i < args.size(); i++) - { - String arg = args.get(i); - // If the first arguments do not start with "--" or "-" or is not "open" - // and` is a filename that exists it is probably a file/list of files to - // open so we fake an Arg.OPEN argument and when adding files only add the - // single arg[i] and increment the defaultLinkedIdCounter so that each of - // these files is opened separately. - if (openEachInitialFilenames && !arg.startsWith(DOUBLEDASH) - && !arg.startsWith("-") && !arg.equals("open") - && (new File(arg).exists() - || HttpUtils.startsWithHttpOrHttps(arg))) - { - arg = Arg.OPEN.argString(); - } - else + /* + * If the first argument does not start with "--" or "-" or is not "open", + * and is a filename that exists or a URL, it is probably a file/list of + * files to open so we insert an Arg.OPEN argument before it. This will + * mean the list of files at the start of the arguments are all opened + * separately. + */ + if (args.size() > 0) + { + String arg0 = args.get(0); + if (arg0 != null + && (!arg0.startsWith(DOUBLEDASH) && !arg0.startsWith("-") + && !arg0.equals("open") && (new File(arg0).exists() + || HttpUtils.startsWithHttpOrHttps(arg0)))) { - openEachInitialFilenames = false; + // insert "--open" at the start + args.add(0, Arg.OPEN.argString()); } + } + + for (int i = 0; i < args.size(); i++) + { + String arg = args.get(i); // look for double-dash, e.g. --arg if (arg.startsWith(DOUBLEDASH)) @@ -371,10 +402,12 @@ public class ArgParser { // arg not found Console.error("Argument '" + arg + "' not recognised. Exiting."); - Jalview.exit("Invalid argument used." + System.lineSeparator() - + "Use" + System.lineSeparator() + "jalview " - + Arg.HELP.argString() + System.lineSeparator() - + "for a usage statement.", 13); + Jalview.exit( + "Invalid argument used." + System.lineSeparator() + "Use" + + System.lineSeparator() + "jalview " + + Arg.HELP.argString() + System.lineSeparator() + + "for a usage statement.", + ExitCode.INVALID_ARGUMENT); continue; } if (a.hasOption(Opt.PRIVATE) && !allowPrivate) @@ -431,7 +464,7 @@ public class ArgParser { // There is no "=" so value is next arg or args (possibly shell // glob-expanded) - if ((openEachInitialFilenames ? i : i + 1) >= args.size()) + if (i + 1 >= args.size()) { // no value to take for arg, which wants a value Console.error("Argument '" + a.getName() @@ -446,8 +479,7 @@ public class ArgParser { // if this is the first argument with a file list at the start of // the args we add filenames from index i instead of i+1 - globVals = getShellGlobbedFilenameValues(a, args, - openEachInitialFilenames ? i : i + 1); + globVals = getShellGlobbedFilenameValues(a, args, i + 1); } else { @@ -477,12 +509,6 @@ public class ArgParser else if (a == Arg.ALL) { allLinkedIds = !negated; - openedLinkedIds = false; - } - else if (a == Arg.OPENED) - { - openedLinkedIds = !negated; - allLinkedIds = false; } else if (a == Arg.ALLSTRUCTURES) { @@ -509,35 +535,25 @@ public class ArgParser { if (linkedId == null) { - if (a.hasOption(Opt.OUTPUTFILE) && a.hasOption(Opt.ALLOWALL) - && val.startsWith(MATCHALLLINKEDIDS)) + if (a.hasOption(Opt.OUTPUTFILE) && a.hasOption(Opt.ALLOWMULTIID) + && val.contains(MATCHALLLINKEDIDS)) { - // --output=*.ext is shorthand for --all --output {basename}.ext + // --output=*.ext is shorthand for --output {basename}.ext + // --output=*/*.ext is shorthand for + // --output {dirname}/{basename}.ext // (or --image=*.ext) - allLinkedIds = true; - openedLinkedIds = false; - linkedId = MATCHALLLINKEDIDS; - val = LINKEDIDDIRNAME + File.separator + LINKEDIDBASENAME - + val.substring(MATCHALLLINKEDIDS.length()); - } - else if (a.hasOption(Opt.OUTPUTFILE) - && a.hasOption(Opt.ALLOWALL) - && val.startsWith(MATCHOPENEDLINKEDIDS)) - { - // --output=open*.ext is shorthand for --opened --output - // {basename}.ext - // (or --image=open*.ext) - openedLinkedIds = true; - allLinkedIds = false; - linkedId = MATCHOPENEDLINKEDIDS; - val = LINKEDIDDIRNAME + File.separator + LINKEDIDBASENAME - + val.substring(MATCHOPENEDLINKEDIDS.length()); + linkedId = allLinkedIds ? MATCHALLLINKEDIDS + : MATCHOPENEDLINKEDIDS; + val = FileUtils.convertWildcardsToPath(val, MATCHALLLINKEDIDS, + LINKEDIDDIRNAME, LINKEDIDBASENAME); } - else if (allLinkedIds && a.hasOption(Opt.ALLOWALL)) + else if (allLinkedIds && a.hasOption(Opt.ALLOWMULTIID)) { linkedId = MATCHALLLINKEDIDS; } - else if (openedLinkedIds && a.hasOption(Opt.ALLOWALL)) + else if (a.hasOption(Opt.ALLOWMULTIID) + && this.storedLinkedIds != null + && this.storedLinkedIds.size() > 0) { linkedId = MATCHOPENEDLINKEDIDS; } @@ -601,10 +617,9 @@ public class ArgParser // set allstructures to all non-primary structure options in this linked // id if --allstructures has been set - if (allStructures - && (a.getType() == Type.STRUCTURE - || a.getType() == Type.STRUCTUREIMAGE) - && !a.hasOption(Opt.PRIMARY)) + if (allStructures && (a.getType() == Type.STRUCTURE + // || a.getType() == Type.STRUCTUREIMAGE) + ) && !a.hasOption(Opt.PRIMARY)) { if (!subvals.has(Arg.ALLSTRUCTURES.getName())) // && !subvals.has("structureid")) @@ -661,9 +676,8 @@ public class ArgParser // remove the '*' or 'open*' linkedId that should be empty if it was // created if ((MATCHALLLINKEDIDS.equals(linkedId) + || MATCHOPENEDLINKEDIDS.equals(linkedId)) && linkedArgs.containsKey(linkedId)) - || (MATCHOPENEDLINKEDIDS.equals(linkedId) - && linkedArgs.containsKey(linkedId))) { linkedArgs.remove(linkedId); } @@ -908,7 +922,7 @@ public class ArgParser { String message = Arg.ARGFILE.argString() + EQUALS + "\"" + argFile.getPath() + "\": File does not exist."; - Jalview.exit(message, 2); + Jalview.exit(message, ExitCode.FILE_NOT_FOUND); } try { @@ -922,7 +936,7 @@ public class ArgParser { String message = Arg.ARGFILE.argString() + "=\"" + argFile.getPath() + "\": File could not be read."; - Jalview.exit(message, 3); + Jalview.exit(message, ExitCode.FILE_NOT_READABLE); } } // Third param "true" uses Opt.PRIVATE args --setargile=argfile and @@ -948,167 +962,12 @@ public class ArgParser String message = Arg.ARGFILE.argString() + "=\"" + argFile.getPath() + "\": File could not be read."; Console.debug(message, e); - Jalview.exit(message, 3); + Jalview.exit(message, ExitCode.FILE_NOT_READABLE); } } return args; } - public static enum Position - { - FIRST, BEFORE, AFTER - } - - /** - * get from following Arg of type a or subval of same name (lowercase) - */ - public static String getValueFromSubValOrArg(ArgValuesMap avm, - ArgValue av, Arg a, SubVals sv) - { - return getFromSubValArgOrPref(avm, av, a, sv, null, null, null); - } - - /** - * get from following Arg of type a or subval key or preference pref or - * default def - */ - public static String getFromSubValArgOrPref(ArgValuesMap avm, ArgValue av, - Arg a, SubVals sv, String key, String pref, String def) - { - return getFromSubValArgOrPref(avm, a, Position.AFTER, av, sv, key, pref, - def); - } - - /** - * get from following(AFTER), first occurence of (FIRST) or previous (BEFORE) - * Arg of type a or subval key or preference pref or default def - */ - public static String getFromSubValArgOrPref(ArgValuesMap avm, Arg a, - Position pos, ArgValue av, SubVals sv, String key, String pref, - String def) - { - return getFromSubValArgOrPrefWithSubstitutions(null, avm, a, pos, av, - sv, key, pref, def); - } - - public static String getFromSubValArgOrPrefWithSubstitutions(ArgParser ap, - ArgValuesMap avm, Arg a, Position pos, ArgValue av, SubVals sv, - String key, String pref, String def) - { - if (key == null) - key = a.getName(); - String value = null; - if (sv != null && sv.has(key) && sv.get(key) != null) - { - value = ap == null ? sv.get(key) - : sv.getWithSubstitutions(ap, avm.getLinkedId(), key); - } - else if (avm != null && avm.containsArg(a)) - { - if (pos == Position.FIRST && avm.getValue(a) != null) - value = avm.getValue(a); - else if (pos == Position.BEFORE - && avm.getClosestPreviousArgValueOfArg(av, a) != null) - value = avm.getClosestPreviousArgValueOfArg(av, a).getValue(); - else if (pos == Position.AFTER - && avm.getClosestNextArgValueOfArg(av, a) != null) - value = avm.getClosestNextArgValueOfArg(av, a).getValue(); - - // look for allstructures subval for Type.STRUCTURE* - Arg arg = av.getArg(); - if (value == null && arg.hasOption(Opt.PRIMARY) - && arg.getType() == Type.STRUCTURE - && !a.hasOption(Opt.PRIMARY) && (a.getType() == Type.STRUCTURE - || a.getType() == Type.STRUCTUREIMAGE)) - { - ArgValue av2 = avm.getArgValueOfArgWithSubValKey(a, - Arg.ALLSTRUCTURES.getName()); - if (av2 != null) - { - value = av2.getValue(); - } - } - } - if (value == null) - { - value = pref != null ? Cache.getDefault(pref, def) : def; - } - return value; - } - - public static boolean getBoolFromSubValOrArg(ArgValuesMap avm, Arg a, - SubVals sv) - { - return getFromSubValArgOrPref(avm, a, sv, null, null, false); - } - - public static boolean getFromSubValArgOrPref(ArgValuesMap avm, Arg a, - SubVals sv, String key, String pref, boolean def) - { - return getFromSubValArgOrPref(avm, a, sv, key, pref, def, false); - } - - public static boolean getFromSubValArgOrPref(ArgValuesMap avm, Arg a, - SubVals sv, String key, String pref, boolean def, - boolean invertPref) - { - if ((key == null && a == null) || (sv == null && a == null)) - return false; - - boolean usingArgKey = false; - if (key == null) - { - key = a.getName(); - usingArgKey = true; - } - - String nokey = ArgParser.NEGATESTRING + key; - - // look for key or nokey in subvals first (if using Arg check options) - if (sv != null) - { - // check for true boolean - if (sv.has(key) && sv.get(key) != null) - { - if (usingArgKey) - { - if (!(a.hasOption(Opt.BOOLEAN) || a.hasOption(Opt.UNARY))) - { - Console.debug( - "Looking for boolean in subval from non-boolean/non-unary Arg " - + a.getName()); - return false; - } - } - return sv.get(key).toLowerCase(Locale.ROOT).equals("true"); - } - - // check for negative boolean (subval "no..." will be "true") - if (sv.has(nokey) && sv.get(nokey) != null) - { - if (usingArgKey) - { - if (!(a.hasOption(Opt.BOOLEAN))) - { - Console.debug( - "Looking for negative boolean in subval from non-boolean Arg " - + a.getName()); - return false; - } - } - return !sv.get(nokey).toLowerCase(Locale.ROOT).equals("true"); - } - } - - // check argvalues - if (avm != null && avm.containsArg(a)) - return avm.getBoolean(a); - - // return preference or default - boolean prefVal = pref != null ? Cache.getDefault(pref, def) : false; - return pref != null ? (invertPref ? !prefVal : prefVal) : def; - } - // the following methods look for the "*" linkedId and add the argvalue to all // linkedId ArgValues if it does. /** @@ -1121,13 +980,6 @@ public class ArgParser argIndex, doSubs); } - private void addValue(String linkedId, Type type, ArgValues avs, String v, - int argIndex, boolean doSubs) - { - this.argValueOperation(Op.ADDVALUE, linkedId, type, avs, null, v, false, - argIndex, doSubs); - } - private void setBoolean(String linkedId, Type type, ArgValues avs, boolean b, int argIndex) { @@ -1195,7 +1047,7 @@ public class ArgParser Arg a = avs.arg(); List wildcardLinkedIds = null; - if (a.hasOption(Opt.ALLOWALL)) + if (a.hasOption(Opt.ALLOWMULTIID)) { switch (linkedId) { @@ -1226,7 +1078,9 @@ public class ArgParser // skip incorrectly stored wildcard ids! if (id == null || MATCHALLLINKEDIDS.equals(id) || MATCHOPENEDLINKEDIDS.equals(id)) + { continue; + } ArgValuesMap avm = linkedArgs.get(id); // don't set an output if there isn't an input if (a.hasOption(Opt.REQUIREINPUT) @@ -1334,4 +1188,19 @@ public class ArgParser return linkedArgs.get(linkedId); } + public boolean isOldStyle() + { + return oldArguments; + } + + public boolean isMixedStyle() + { + return mixedArguments; + } + + public String[] getMixedExamples() + { + return mixedExamples; + } + } \ No newline at end of file