From 988d7abeef3e08d01ff8ebb918325d95caae70b7 Mon Sep 17 00:00:00 2001 From: Ben Soares Date: Wed, 29 Mar 2023 23:31:46 +0100 Subject: [PATCH] JAL-629 Added --opennew --nonews --nosplash. Added java globbing for = e.g. --open=**/*.fa. General debugging of argparser features for tests --- src/jalview/bin/Commands.java | 4 +- src/jalview/bin/Jalview.java | 7 +- src/jalview/bin/argparser/Arg.java | 2 +- src/jalview/bin/argparser/ArgParser.java | 142 ++++++++++++-------- src/jalview/bin/argparser/ArgValue.java | 11 +- src/jalview/bin/argparser/ArgValues.java | 5 + src/jalview/bin/argparser/BootstrapArgs.java | 4 - src/jalview/bin/argparser/SubVals.java | 42 ++++-- src/jalview/util/FileUtils.java | 19 ++- .../bin/{argparser => }/ArgsParserTest.java | 0 10 files changed, 159 insertions(+), 77 deletions(-) rename test/jalview/bin/{argparser => }/ArgsParserTest.java (100%) diff --git a/src/jalview/bin/Commands.java b/src/jalview/bin/Commands.java index 43dc1fd..e92ee61 100644 --- a/src/jalview/bin/Commands.java +++ b/src/jalview/bin/Commands.java @@ -159,7 +159,7 @@ public class Commands FileFormatI format = null; DataSourceType protocol = null; */ - if (avm.containsArg(Arg.OPEN)) + if (avm.containsArg(Arg.OPEN) || avm.containsArg(Arg.OPENNEW)) { commandArgsProvided = true; long progress = -1; @@ -167,6 +167,8 @@ public class Commands boolean first = true; boolean progressBarSet = false; AlignFrame af; + // Combine the OPEN and OPENNEW files into one list, along with whether it + // was OPEN or OPENNEW List> openAvList = new ArrayList<>(); avm.getArgValueList(Arg.OPEN).stream() .forEachOrdered(av -> openAvList.add( diff --git a/src/jalview/bin/Jalview.java b/src/jalview/bin/Jalview.java index bc8c997..689080e 100755 --- a/src/jalview/bin/Jalview.java +++ b/src/jalview/bin/Jalview.java @@ -416,9 +416,11 @@ public class Jalview String usrPropsFile = bootstrapArgs.contains(Arg.PROPS) ? bootstrapArgs.get(Arg.PROPS) : aparser.getValue("props"); + // if usrPropsFile == null, loadProperties will use the Channel + // preferences.file + Cache.loadProperties(usrPropsFile); if (usrPropsFile != null) { - Cache.loadProperties(usrPropsFile); System.out.println( "CMD [-props " + usrPropsFile + "] executed successfully!"); } @@ -542,7 +544,8 @@ public class Jalview if (!(headless || headlessArg)) { - Desktop.nosplash = aparser.contains("nosplash"); + Desktop.nosplash = "false".equals(bootstrapArgs.get(Arg.SPLASH)) + || aparser.contains("nosplash"); desktop = new Desktop(); desktop.setInBatchMode(true); // indicate we are starting up diff --git a/src/jalview/bin/argparser/Arg.java b/src/jalview/bin/argparser/Arg.java index 4c2465c..c19012b 100644 --- a/src/jalview/bin/argparser/Arg.java +++ b/src/jalview/bin/argparser/Arg.java @@ -52,7 +52,7 @@ public enum Arg USAGESTATS.setOptions(true, Opt.BOOLEAN); OPEN.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI, Opt.GLOB, Opt.ALLOWSUBSTITUTIONS); - OPENNEW.setOptions(Opt.STRING, Opt.MULTI, Opt.GLOB, + OPENNEW.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI, Opt.GLOB, Opt.ALLOWSUBSTITUTIONS); PROPS.setOptions(Opt.STRING, Opt.BOOTSTRAP); QUESTIONNAIRE.setOptions(Opt.STRING); diff --git a/src/jalview/bin/argparser/ArgParser.java b/src/jalview/bin/argparser/ArgParser.java index f22ca7f..19cf276 100644 --- a/src/jalview/bin/argparser/ArgParser.java +++ b/src/jalview/bin/argparser/ArgParser.java @@ -62,7 +62,7 @@ public class ArgParser // the linked id used to use the idCounter private static final String AUTOCOUNTERLINKEDID = "{n}"; - private int idCounter = 0; + private int linkedIdAutoCounter = 0; // flag to say whether {n} subtitutions in output filenames should be made. // Turn on and off with --subs and --nosubs @@ -126,8 +126,6 @@ public class ArgParser { String arg = args.get(i); - Console.debug("##### Looking at arg '" + arg + "'"); - // If the first arguments do not start with "--" or "-" or is "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 @@ -145,7 +143,8 @@ public class ArgParser String argName = null; String val = null; - List vals = null; // for Opt.GLOB only + List globVals = null; // for Opt.GLOB only + SubVals globSubVals = null; // also for use by Opt.GLOB only String linkedId = null; if (arg.startsWith(DOUBLEDASH)) { @@ -210,31 +209,50 @@ public class ArgParser continue; } - if (a.hasOption(Opt.STRING) && equalPos == -1) + // String value(s) + if (a.hasOption(Opt.STRING)) { - // take next arg as value if required, and '=' was not found - // if (!argE.hasMoreElements()) - if (i + 1 >= args.size()) - { - // no value to take for arg, which wants a value - Console.error("Argument '" + a.getName() - + "' requires a value, none given. Ignoring."); - continue; - } - // deal with bash globs here (--arg val* is expanded before reaching - // the JVM). Note that SubVals cannot be used in this case. - // If using the --arg=val then the glob is preserved and Java globs - // will be used later. SubVals can be used. - if (a.hasOption(Opt.GLOB)) + if (equalPos >= 0) { - // 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 - vals = getShellGlobbedFilenameValues(a, args, - openEachInitialFilenames ? i : i + 1); + if (a.hasOption(Opt.GLOB)) + { + // strip off and save the SubVals to be added individually later + globSubVals = ArgParser.getSubVals(val); + globVals = FileUtils + .getFilenamesFromGlob(globSubVals.getContent()); + } + else + { + // val is already set -- will be saved in the ArgValue later in + // the normal way + } } else { - val = args.get(i + 1); + // There is no "=" so value is next arg or args (possibly shell + // glob-expanded) + if (i + 1 >= args.size()) + { + // no value to take for arg, which wants a value + Console.error("Argument '" + a.getName() + + "' requires a value, none given. Ignoring."); + continue; + } + // deal with bash globs here (--arg val* is expanded before reaching + // the JVM). Note that SubVals cannot be used in this case. + // If using the --arg=val then the glob is preserved and Java globs + // will be used later. SubVals can be used. + if (a.hasOption(Opt.GLOB)) + { + // 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); + } + else + { + val = args.get(i + 1); + } } } @@ -246,7 +264,7 @@ public class ArgParser } else if (a == Arg.NPP) { - idCounter++; + linkedIdAutoCounter++; } else if (a == Arg.SUBSTITUTIONS) { @@ -259,37 +277,43 @@ public class ArgParser .append(Integer.toString(defaultLinkedIdCounter)) .toString(); boolean usingDefaultLinkedId = false; - if (a == Arg.OPENNEW) - { - linkedId = new StringBuilder(OPENNEWLINKEDIDPREFIX) - .append(Integer.toString(opennewLinkedIdCounter)) - .toString(); - opennewLinkedIdCounter++; - } - else if (a.hasOption(Opt.LINKED)) + if (a.hasOption(Opt.LINKED)) { if (linkedId == null) { - // use default linkedId for linked arguments - linkedId = defaultLinkedId; - usingDefaultLinkedId = true; - Console.debug( - "Changing linkedId to '" + linkedId + "' from " + arg); + if (a == Arg.OPENNEW) + { + // use the next default prefixed OPENNEWLINKEDID + linkedId = new StringBuilder(OPENNEWLINKEDIDPREFIX) + .append(Integer.toString(opennewLinkedIdCounter)) + .toString(); + opennewLinkedIdCounter++; + } + else + { + // use default linkedId for linked arguments + linkedId = defaultLinkedId; + usingDefaultLinkedId = true; + Console.debug("Changing linkedId to '" + linkedId + "' from " + + arg); + } } - else if (linkedId.equals(AUTOCOUNTERLINKEDID)) + else if (linkedId.contains(AUTOCOUNTERLINKEDID)) { // turn {n} to the autoCounter - autoCounterString = Integer.toString(idCounter); - linkedId = autoCounterString; + autoCounterString = Integer.toString(linkedIdAutoCounter); + linkedId = linkedId.replace(AUTOCOUNTERLINKEDID, + autoCounterString); usingAutoCounterLinkedId = true; Console.debug( "Changing linkedId to '" + linkedId + "' from " + arg); } - else if (linkedId.equals(INCREMENTAUTOCOUNTERLINKEDID)) + else if (linkedId.contains(INCREMENTAUTOCOUNTERLINKEDID)) { // turn {++n} to the incremented autoCounter - autoCounterString = Integer.toString(++idCounter); - linkedId = autoCounterString; + autoCounterString = Integer.toString(++linkedIdAutoCounter); + linkedId = linkedId.replace(INCREMENTAUTOCOUNTERLINKEDID, + autoCounterString); usingAutoCounterLinkedId = true; Console.debug( "Changing linkedId to '" + linkedId + "' from " + arg); @@ -315,8 +339,8 @@ public class ArgParser } // check for unique id - SubVals sv = ArgParser.getSubVals(val); - String id = sv.get(ArgValues.ID); + SubVals idsv = ArgParser.getSubVals(val); + String id = idsv.get(ArgValues.ID); if (id != null && avm.hasId(a, id)) { Console.error("Argument '--" + argName + "' has a duplicate id ('" @@ -327,14 +351,18 @@ public class ArgParser boolean argIndexIncremented = false; ArgValues avs = avm.getOrCreateArgValues(a); - // store appropriate value + // store appropriate String value(s) if (a.hasOption(Opt.STRING)) { - if (a.hasOption(Opt.GLOB) && vals != null && vals.size() > 0) + if (a.hasOption(Opt.GLOB) && globVals != null + && globVals.size() > 0) { - for (String v : vals) + for (String v : globVals) { - avs.addValue(makeSubstitutions(v), argIndex++); + v = makeSubstitutions(v); + SubVals vsv = new SubVals(globSubVals == null ? null + : globSubVals.getSubValsMap(), v); + avs.addValue(vsv, v, argIndex++); argIndexIncremented = true; } } @@ -371,6 +399,7 @@ public class ArgParser argList = new ArrayList<>(); if (!argList.contains(a)) argList.add(a); + } } } @@ -395,9 +424,14 @@ public class ArgParser subvals = ""; rest = val; } - rest.replace(AUTOCOUNTERLINKEDID, String.valueOf(idCounter)); - rest.replace(INCREMENTAUTOCOUNTERLINKEDID, String.valueOf(++idCounter)); - rest.replace("{}", String.valueOf(defaultLinkedIdCounter)); + if ((rest.contains(AUTOCOUNTERLINKEDID))) + rest = rest.replace(AUTOCOUNTERLINKEDID, + String.valueOf(linkedIdAutoCounter)); + if ((rest.contains(INCREMENTAUTOCOUNTERLINKEDID))) + rest = rest.replace(INCREMENTAUTOCOUNTERLINKEDID, + String.valueOf(++linkedIdAutoCounter)); + if ((rest.contains("{}"))) + rest = rest.replace("{}", String.valueOf(defaultLinkedIdCounter)); return new StringBuilder(subvals).append(rest).toString(); } @@ -418,7 +452,7 @@ public class ArgParser List vals = new ArrayList<>(); while (i < args.size() && !args.get(i).startsWith(DOUBLEDASH)) { - vals.add(args.remove(i)); + vals.add(FileUtils.substituteHomeDir(args.remove(i))); if (!a.hasOption(Opt.GLOB)) break; } diff --git a/src/jalview/bin/argparser/ArgValue.java b/src/jalview/bin/argparser/ArgValue.java index 2aa32df..28cead9 100644 --- a/src/jalview/bin/argparser/ArgValue.java +++ b/src/jalview/bin/argparser/ArgValue.java @@ -13,11 +13,18 @@ public class ArgValue private SubVals subVals = null; + protected ArgValue(SubVals sv, String content, int argIndex) + { + this.value = content; + this.argIndex = argIndex; + this.subVals = sv; + } + protected ArgValue(String value, int argIndex) { - this.value = value; this.argIndex = argIndex; - this.subVals = ArgParser.getSubVals(getValue()); + this.subVals = ArgParser.getSubVals(value); + this.value = getSubVals().getContent(); } public String getValue() diff --git a/src/jalview/bin/argparser/ArgValues.java b/src/jalview/bin/argparser/ArgValues.java index 2c71f63..27d52ba 100644 --- a/src/jalview/bin/argparser/ArgValues.java +++ b/src/jalview/bin/argparser/ArgValues.java @@ -108,6 +108,11 @@ public class ArgValues addArgValue(new ArgValue(val, argIndex)); } + protected void addValue(SubVals sv, String content, int argIndex) + { + addArgValue(new ArgValue(sv, content, argIndex)); + } + protected void addArgValue(ArgValue av) { if ((!arg.hasOption(Opt.MULTI) && argValueList.size() > 0) diff --git a/src/jalview/bin/argparser/BootstrapArgs.java b/src/jalview/bin/argparser/BootstrapArgs.java index 49e8686..f6b592b 100644 --- a/src/jalview/bin/argparser/BootstrapArgs.java +++ b/src/jalview/bin/argparser/BootstrapArgs.java @@ -37,7 +37,6 @@ public class BootstrapArgs if (arg.startsWith(ArgParser.DOUBLEDASH)) { // remove "--" - System.out.println("###### BOOTSTRAP: '" + arg + "'"); arg = arg.substring(ArgParser.DOUBLEDASH.length()); int equalPos = arg.indexOf('='); if (equalPos > -1 @@ -51,7 +50,6 @@ public class BootstrapArgs && ArgParser.argMap.containsKey( arg.substring(ArgParser.NEGATESTRING.length()))) { - System.out.println("###### BOOTSTRAP IN NEGATESTRING"); argName = arg.substring(ArgParser.NEGATESTRING.length()); val = "false"; } @@ -86,8 +84,6 @@ public class BootstrapArgs } else { - System.err.println( - "###### Adding '" + a.getName() + "' with '" + val + "'"); add(a, val); } } diff --git a/src/jalview/bin/argparser/SubVals.java b/src/jalview/bin/argparser/SubVals.java index e6a7cb2..aea6df3 100644 --- a/src/jalview/bin/argparser/SubVals.java +++ b/src/jalview/bin/argparser/SubVals.java @@ -1,6 +1,8 @@ package jalview.bin.argparser; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import jalview.bin.Console; @@ -21,8 +23,16 @@ public class SubVals private static char SEPARATOR = ';'; + private static char EQUALS = '='; + private String content = null; + public SubVals(Map sv, String c) + { + this.subVals = sv; + this.content = c; + } + public SubVals(String item) { this.parseVals(item); @@ -42,11 +52,11 @@ public class SubVals for (String subvalString : subvalsString .split(Character.toString(SEPARATOR))) { - int equals = subvalString.indexOf('='); + if (subVals == null) + subVals = new HashMap<>(); + int equals = subvalString.indexOf(EQUALS); if (equals > -1) { - if (subVals == null) - subVals = new HashMap<>(); this.put(subvalString.substring(0, equals), subvalString.substring(equals + 1)); } @@ -59,7 +69,7 @@ public class SubVals } catch (NumberFormatException e) { // store this non-numeric key as a "true" value - subVals.put(subvalsString, "true"); + subVals.put(subvalString, "true"); } } } @@ -108,15 +118,27 @@ public class SubVals return content; } + protected Map getSubValsMap() + { + return subVals; + } + public String toString() { - StringBuilder sb = new StringBuilder(); - if (subVals == null) + if (subVals == null && getIndex() == NOTSET) return ""; - for (Map.Entry m : subVals.entrySet()) - { - sb.append(m.getKey()).append('=').append(m.getValue()).append("\n"); - } + + StringBuilder sb = new StringBuilder(); + List entries = new ArrayList<>(); + subVals.entrySet().stream().forEachOrdered( + m -> entries.add(m.getValue().equals("true") ? m.getKey() + : new StringBuilder().append(m.getKey()).append(EQUALS) + .append(m.getValue()).toString())); + if (getIndex() != NOTSET) + entries.add(Integer.toString(getIndex())); + sb.append('['); + sb.append(String.join(Character.toString(SEPARATOR), entries)); + sb.append(']'); return sb.toString(); } } \ No newline at end of file diff --git a/src/jalview/util/FileUtils.java b/src/jalview/util/FileUtils.java index 9aa27f9..63af0bc 100644 --- a/src/jalview/util/FileUtils.java +++ b/src/jalview/util/FileUtils.java @@ -26,9 +26,16 @@ public class FileUtils */ public static List getFilesFromGlob(String pattern) { + return getFilesFromGlob(pattern, true); + } + + public static List getFilesFromGlob(String pattern, + boolean allowSingleFilenameThatDoesNotExist) + { + pattern = substituteHomeDir(pattern); List files = new ArrayList<>(); /* - * For efficiency of the Files.walkFileTree, let's find the longest path that doesn't need globbing. + * For efficiency of the Files.walkFileTree(), let's find the longest path that doesn't need globbing. * We look for the first glob character * { ? and then look for the last File.separator before that. * Then we can reset the path to look at and shorten the globbing pattern. * Relative paths can be used in pattern, which work from the pwd (though these are converted into @@ -94,7 +101,7 @@ public class FileUtils { // no wildcards File f = new File(pattern); - if (f.exists()) + if (allowSingleFilenameThatDoesNotExist || f.exists()) { files.add(f); } @@ -110,4 +117,10 @@ public class FileUtils .collect(Collectors.toList()); } -} \ No newline at end of file + public static String substituteHomeDir(String path) + { + return path.startsWith("~" + File.separator) + ? System.getProperty("user.home") + path.substring(1) + : path; + } +} diff --git a/test/jalview/bin/argparser/ArgsParserTest.java b/test/jalview/bin/ArgsParserTest.java similarity index 100% rename from test/jalview/bin/argparser/ArgsParserTest.java rename to test/jalview/bin/ArgsParserTest.java -- 1.7.10.2