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;
private static final String LINKEDIDDIRNAME = "{dirname}";
/**
+ * On-the-fly substitution (not made at argument parsing time)! the current
+ * structure filename extension
+ */
+ private static final String STRUCTUREEXTENSION = "{structureextension}";
+
+ /**
+ * On-the-fly substitution (not made at argument parsing time)! the current
+ * structure filename base
+ */
+ private static final String STRUCTUREBASENAME = "{structurebasename}";
+
+ /**
+ * On-the-fly substitution (not made at argument parsing time)! the current
+ * structure filename dir path
+ */
+ private static final String STRUCTUREDIRNAME = "{structuredirname}";
+
+ /**
+ * On-the-fly substitution (not made at argument parsing time)! increment the
+ * on-the-fly counter and substitute the incremented value
+ */
+ private static final String INCREMENTONTHEFLYCOUNTER = "{++m}";
+
+ /**
+ * On-the-fly substitution (not made at argument parsing time)! the current
+ * substitute with the on-the-fly counter
+ */
+ private static final String ONTHEFLYCOUNTER = "{m}";
+
+ /**
+ * the string used for on-the-fly structure filename substitutions
+ */
+ private String currentStructureFilename = null;
+
+ /**
+ * the counter used for on-the-fly {m} substitutions
+ */
+ private int ontheflyCounter = 0;
+
+ /**
* the current argfile
*/
private String argFile = null;
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
*/
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<>();
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<String>(), false, false);
return;
}
+
if (bsa != null)
+ {
this.bootstrapArgs = bsa;
+ }
else
+ {
this.bootstrapArgs = BootstrapArgs.getBootstrapArgs(args);
+ }
parse(args, initsubstitutions, allowPrivate);
}
List<String> globVals = null; // for Opt.GLOB only
SubVals globSubVals = null; // also for use by Opt.GLOB only
String linkedId = null;
+ String givenLinkedId = null; // this is preserved to add to each
+ // "ArgValue"
Type type = null;
// look for equals e.g. --arg=value
if (idOpen > -1 && idClose == argName.length() - 1)
{
linkedId = argName.substring(idOpen + 1, idClose);
+ givenLinkedId = linkedId;
argName = argName.substring(0, idOpen);
}
{
// 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)
else if (a == Arg.ALL)
{
allLinkedIds = !negated;
- openedLinkedIds = false;
- }
- else if (a == Arg.OPENED)
- {
- openedLinkedIds = !negated;
- allLinkedIds = false;
}
else if (a == Arg.ALLSTRUCTURES)
{
{
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());
+ linkedId = allLinkedIds ? MATCHALLLINKEDIDS
+ : MATCHOPENEDLINKEDIDS;
+ val = FileUtils.convertWildcardsToPath(val, MATCHALLLINKEDIDS,
+ LINKEDIDDIRNAME, LINKEDIDBASENAME);
}
- else if (a.hasOption(Opt.OUTPUTFILE)
- && a.hasOption(Opt.ALLOWALL)
- && val.startsWith(MATCHOPENEDLINKEDIDS))
+ else if (allLinkedIds && a.hasOption(Opt.ALLOWMULTIID))
{
- // --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 = MATCHALLLINKEDIDS;
}
- else if (allLinkedIds && a.hasOption(Opt.ALLOWALL))
+ if (allLinkedIds)
{
- linkedId = MATCHALLLINKEDIDS;
+ // user has made conscious decision for these args to apply to
+ // all, so set givenLinkedId too
+ givenLinkedId = linkedId;
}
- else if (openedLinkedIds && a.hasOption(Opt.ALLOWALL))
+ else if (a.hasOption(Opt.ALLOWMULTIID)
+ && this.storedLinkedIds != null
+ && this.storedLinkedIds.size() > 0)
{
linkedId = MATCHOPENEDLINKEDIDS;
}
// 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.hasType(Type.STRUCTURE)
+ // || a.getType() == Type.STRUCTUREIMAGE)
+ ) && !a.hasOption(Opt.PRIMARY))
{
if (!subvals.has(Arg.ALLSTRUCTURES.getName()))
// && !subvals.has("structureid"))
{
String v = gve.nextElement();
SubVals vsv = new SubVals(globSubVals, v);
- addValue(linkedId, type, avs, vsv, v, argIndex++, true);
+ addValue(linkedId, givenLinkedId, type, avs, vsv, v,
+ argIndex++, true);
// if we're using defaultLinkedId and the arg increments the
// counter:
if (gve.hasMoreElements() && usingDefaultLinkedId
else
{
// addValue(linkedId, type, avs, val, argIndex, true);
- addValue(linkedId, type, avs, addNewSubVals ? subvals : null,
- val, argIndex, true);
+ addValue(linkedId, givenLinkedId, type, avs,
+ addNewSubVals ? subvals : null, val, argIndex, true);
}
}
else if (a.hasOption(Opt.BOOLEAN))
{
- setBoolean(linkedId, type, avs, !negated, argIndex);
+ setBoolean(linkedId, givenLinkedId, type, avs, !negated,
+ argIndex);
setNegated(linkedId, avs, negated);
}
else if (a.hasOption(Opt.UNARY))
{
- setBoolean(linkedId, type, avs, true, argIndex);
+ setBoolean(linkedId, givenLinkedId, type, avs, true, argIndex);
}
// 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);
}
public String makeSubstitutions(String val, String linkedId)
{
+ return makeSubstitutions(val, linkedId, false);
+ }
+
+ public String makeSubstitutions(String val, String linkedId,
+ boolean onthefly)
+ {
if (!this.substitutions || val == null)
return val;
rest = val;
}
if (rest.contains(LINKEDIDAUTOCOUNTER))
+ {
rest = rest.replace(LINKEDIDAUTOCOUNTER,
String.valueOf(linkedIdAutoCounter));
+ }
if (rest.contains(INCREMENTLINKEDIDAUTOCOUNTER))
+ {
rest = rest.replace(INCREMENTLINKEDIDAUTOCOUNTER,
String.valueOf(++linkedIdAutoCounter));
+ }
if (rest.contains(DEFAULTLINKEDIDCOUNTER))
+ {
rest = rest.replace(DEFAULTLINKEDIDCOUNTER,
String.valueOf(defaultLinkedIdCounter));
+ }
ArgValuesMap avm = linkedArgs.get(linkedId);
if (avm != null)
{
FileUtils.getDirname(new File(argFile)));
}
}
+ if (onthefly)
+ {
+ if (rest.contains(ONTHEFLYCOUNTER))
+ {
+ rest = rest.replace(ONTHEFLYCOUNTER,
+ String.valueOf(ontheflyCounter));
+ }
+ if (rest.contains(INCREMENTONTHEFLYCOUNTER))
+ {
+ rest = rest.replace(INCREMENTONTHEFLYCOUNTER,
+ String.valueOf(++ontheflyCounter));
+ }
+ if (currentStructureFilename != null)
+ {
+ if (rest.contains(STRUCTUREBASENAME))
+ {
+ rest = rest.replace(STRUCTUREBASENAME, FileUtils
+ .getBasename(new File(currentStructureFilename)));
+ }
+ if (rest.contains(STRUCTUREDIRNAME))
+ {
+ rest = rest.replace(STRUCTUREDIRNAME,
+ FileUtils.getDirname(new File(currentStructureFilename)));
+ }
+ }
+ }
return new StringBuilder(subvals).append(rest).toString();
}
{
String message = Arg.ARGFILE.argString() + EQUALS + "\""
+ argFile.getPath() + "\": File does not exist.";
- Jalview.exit(message, 2);
+ Jalview.exit(message, ExitCode.FILE_NOT_FOUND);
}
try
{
{
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
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.
/**
* This version inserts the subvals sv into all created values
*/
- private void addValue(String linkedId, Type type, ArgValues avs,
- SubVals sv, String v, int argIndex, boolean doSubs)
- {
- this.argValueOperation(Op.ADDVALUE, linkedId, type, avs, sv, v, false,
- argIndex, doSubs);
- }
-
- private void addValue(String linkedId, Type type, ArgValues avs, String v,
- int argIndex, boolean doSubs)
+ private void addValue(String linkedId, String givenLinkedId, Type type,
+ ArgValues avs, SubVals sv, String v, int argIndex, boolean doSubs)
{
- this.argValueOperation(Op.ADDVALUE, linkedId, type, avs, null, v, false,
- argIndex, doSubs);
+ this.argValueOperation(Op.ADDVALUE, linkedId, givenLinkedId, type, avs,
+ sv, v, false, argIndex, doSubs);
}
- private void setBoolean(String linkedId, Type type, ArgValues avs,
- boolean b, int argIndex)
+ private void setBoolean(String linkedId, String givenLinkedId, Type type,
+ ArgValues avs, boolean b, int argIndex)
{
- this.argValueOperation(Op.SETBOOLEAN, linkedId, type, avs, null, null,
- b, argIndex, false);
+ this.argValueOperation(Op.SETBOOLEAN, linkedId, givenLinkedId, type,
+ avs, null, null, b, argIndex, false);
}
private void setNegated(String linkedId, ArgValues avs, boolean b)
{
- this.argValueOperation(Op.SETNEGATED, linkedId, null, avs, null, null,
- b, 0, false);
+ this.argValueOperation(Op.SETNEGATED, linkedId, null, null, avs, null,
+ null, b, 0, false);
}
private void incrementCount(String linkedId, ArgValues avs)
{
- this.argValueOperation(Op.INCREMENTCOUNT, linkedId, null, avs, null,
- null, false, 0, false);
+ this.argValueOperation(Op.INCREMENTCOUNT, linkedId, null, null, avs,
+ null, null, false, 0, false);
}
private enum Op
ADDVALUE, SETBOOLEAN, SETNEGATED, INCREMENTCOUNT
}
- private void argValueOperation(Op op, String linkedId, Type type,
- ArgValues avs, SubVals sv, String v, boolean b, int argIndex,
- boolean doSubs)
+ private void argValueOperation(Op op, String linkedId,
+ String givenLinkedId, Type type, ArgValues avs, SubVals sv,
+ String v, boolean b, int argIndex, boolean doSubs)
{
// default to merge subvals if subvals are provided
- argValueOperation(op, linkedId, type, avs, sv, true, v, b, argIndex,
- doSubs);
+ argValueOperation(op, linkedId, givenLinkedId, type, avs, sv, true, v,
+ b, argIndex, doSubs);
}
/**
* @param doSubs
* Whether to perform substitutions on the subvals and value.
*/
- private void argValueOperation(Op op, String linkedId, Type type,
- ArgValues avs, SubVals sv, boolean merge, String v, boolean b,
- int argIndex, boolean doSubs)
+ private void argValueOperation(Op op, String linkedId,
+ String givenLinkedId, Type type, ArgValues avs, SubVals sv,
+ boolean merge, String v, boolean b, int argIndex, boolean doSubs)
{
Arg a = avs.arg();
List<String> wildcardLinkedIds = null;
- if (a.hasOption(Opt.ALLOWALL))
+ if (a.hasOption(Opt.ALLOWMULTIID))
{
switch (linkedId)
{
// linkedIds
if (wildcardLinkedIds != null)
{
- for (String id : wildcardLinkedIds)
+ for (String matchedLinkedId : wildcardLinkedIds)
{
// skip incorrectly stored wildcard ids!
- if (id == null || MATCHALLLINKEDIDS.equals(id)
- || MATCHOPENEDLINKEDIDS.equals(id))
+ if (matchedLinkedId == null
+ || MATCHALLLINKEDIDS.equals(matchedLinkedId)
+ || MATCHOPENEDLINKEDIDS.equals(matchedLinkedId))
+ {
continue;
- ArgValuesMap avm = linkedArgs.get(id);
+ }
+ ArgValuesMap avm = linkedArgs.get(matchedLinkedId);
// don't set an output if there isn't an input
if (a.hasOption(Opt.REQUIREINPUT)
&& !avm.hasArgWithOption(Opt.INPUT))
if (doSubs)
{
sv = new SubVals(sv, val, merge);
- val = makeSubstitutions(sv.getContent(), id);
+ val = makeSubstitutions(sv.getContent(), matchedLinkedId);
}
- tavs.addValue(sv, type, val, argIndex, true);
+ tavs.addValue(sv, type, val, argIndex, true, givenLinkedId);
}
else
{
if (doSubs)
{
- val = makeSubstitutions(v, id);
+ val = makeSubstitutions(v, matchedLinkedId);
}
- tavs.addValue(type, val, argIndex, true);
+ tavs.addValue(type, val, argIndex, true, givenLinkedId);
}
- finaliseStoringArgValue(id, tavs);
+ finaliseStoringArgValue(matchedLinkedId, tavs);
break;
case SETBOOLEAN:
- tavs.setBoolean(type, b, argIndex, true);
- finaliseStoringArgValue(id, tavs);
+ tavs.setBoolean(type, b, argIndex, true, givenLinkedId);
+ finaliseStoringArgValue(matchedLinkedId, tavs);
break;
case SETNEGATED:
val = makeSubstitutions(v, linkedId);
sv = new SubVals(sv, val);
}
- avs.addValue(sv, type, val, argIndex, false);
+ avs.addValue(sv, type, val, argIndex, false, givenLinkedId);
}
else
{
{
val = makeSubstitutions(v, linkedId);
}
- avs.addValue(type, val, argIndex, false);
+ avs.addValue(type, val, argIndex, false, givenLinkedId);
}
finaliseStoringArgValue(linkedId, avs);
break;
case SETBOOLEAN:
- avs.setBoolean(type, b, argIndex, false);
+ avs.setBoolean(type, b, argIndex, false, givenLinkedId);
finaliseStoringArgValue(linkedId, avs);
break;
return linkedArgs.get(linkedId);
}
+ public boolean isOldStyle()
+ {
+ return oldArguments;
+ }
+
+ public boolean isMixedStyle()
+ {
+ return mixedArguments;
+ }
+
+ public String[] getMixedExamples()
+ {
+ return mixedExamples;
+ }
+
+ public void setStructureFilename(String s)
+ {
+ this.currentStructureFilename = s;
+ }
+
}
\ No newline at end of file