JAL-629 added setprop. More filename based substitutions enabled. Test for these.
[jalview.git] / src / jalview / bin / argparser / ArgParser.java
index 81ba0cc..c2568bb 100644 (file)
@@ -41,6 +41,8 @@ public class ArgParser
 {
   protected static final String DOUBLEDASH = "--";
 
+  protected static final char EQUALS = '=';
+
   protected static final String NEGATESTRING = "no";
 
   // the default linked id prefix used for no id (not even square braces)
@@ -55,13 +57,32 @@ public class ArgParser
   // the counter added to the default linked id prefix
   private int opennewLinkedIdCounter = 0;
 
-  // the linked id used to increment the idCounter (and use the incremented
-  // value)
+  // the linked id substitution string used to increment the idCounter (and use
+  // the incremented value)
   private static final String INCREMENTAUTOCOUNTERLINKEDID = "{++n}";
 
-  // the linked id used to use the idCounter
+  // the linked id substitution string used to use the idCounter
   private static final String AUTOCOUNTERLINKEDID = "{n}";
 
+  // the linked id substitution string used to use the base filename of --open
+  // or --opennew
+  private static final String LINKEDIDBASENAME = "{basename}";
+
+  // the linked id substitution string used to use the dir path of --open
+  // or --opennew
+  private static final String LINKEDIDDIRNAME = "{dirname}";
+
+  // the current argfile
+  private String argFile = null;
+
+  // the linked id substitution string used to use the dir path of the latest
+  // --argfile name
+  private static final String ARGFILEBASENAME = "{argfilebasename}";
+
+  // the linked id substitution string used to use the dir path of the latest
+  // --argfile name
+  private static final String ARGFILEDIRNAME = "{argfiledirname}";
+
   private int linkedIdAutoCounter = 0;
 
   // flag to say whether {n} subtitutions in output filenames should be made.
@@ -115,6 +136,11 @@ public class ArgParser
 
   public ArgParser(List<String> args)
   {
+    this(args, false);
+  }
+
+  public ArgParser(List<String> args, boolean allowPrivate)
+  {
     // do nothing if there are no "--" args and some "-" args
     boolean d = false;
     boolean dd = false;
@@ -133,13 +159,13 @@ public class ArgParser
     if (d && !dd)
     {
       // leave it to the old style -- parse an empty list
-      parse(new ArrayList<String>());
+      parse(new ArrayList<String>(), allowPrivate);
       return;
     }
-    parse(args);
+    parse(args, allowPrivate);
   }
 
-  private void parse(List<String> args)
+  private void parse(List<String> args, boolean allowPrivate)
   {
     int argIndex = 0;
     boolean openEachInitialFilenames = true;
@@ -169,7 +195,7 @@ public class ArgParser
       String linkedId = null;
       if (arg.startsWith(DOUBLEDASH))
       {
-        int equalPos = arg.indexOf('=');
+        int equalPos = arg.indexOf(EQUALS);
         if (equalPos > -1)
         {
           argName = arg.substring(DOUBLEDASH.length(), equalPos);
@@ -206,17 +232,23 @@ public class ArgParser
           Console.error("Argument '" + arg + "' not recognised. Ignoring.");
           continue;
         }
+        if (a.hasOption(Opt.PRIVATE) && !allowPrivate)
+        {
+          Console.error("Argument '" + DOUBLEDASH + argName
+                  + "' is private. Ignoring.");
+          continue;
+        }
         if (!a.hasOption(Opt.BOOLEAN) && negated)
         {
           // used "no" with a non-boolean option
-          Console.error("Argument '--" + NEGATESTRING + argName
+          Console.error("Argument '" + DOUBLEDASH + NEGATESTRING + argName
                   + "' not a boolean option. Ignoring.");
           continue;
         }
         if (!a.hasOption(Opt.STRING) && equalPos > -1)
         {
           // set --argname=value when arg does not accept values
-          Console.error("Argument '--" + argName
+          Console.error("Argument '" + DOUBLEDASH + argName
                   + "' does not expect a value (given as '" + arg
                   + "').  Ignoring.");
           continue;
@@ -224,7 +256,7 @@ public class ArgParser
         if (!a.hasOption(Opt.LINKED) && linkedId != null)
         {
           // set --argname[linkedId] when arg does not use linkedIds
-          Console.error("Argument '--" + argName
+          Console.error("Argument '" + DOUBLEDASH + argName
                   + "' does not expect a linked id (given as '" + arg
                   + "'). Ignoring.");
           continue;
@@ -239,8 +271,10 @@ public class ArgParser
             {
               // strip off and save the SubVals to be added individually later
               globSubVals = ArgParser.getSubVals(val);
-              globVals = FileUtils
-                      .getFilenamesFromGlob(globSubVals.getContent());
+              // make substitutions before looking for files
+              String fileGlob = makeSubstitutions(globSubVals.getContent(),
+                      linkedId);
+              globVals = FileUtils.getFilenamesFromGlob(fileGlob);
             }
             else
             {
@@ -291,6 +325,14 @@ public class ArgParser
         {
           substitutions = !negated;
         }
+        else if (a == Arg.SETARGFILE)
+        {
+          argFile = val;
+        }
+        else if (a == Arg.UNSETARGFILE)
+        {
+          argFile = null;
+        }
 
         String autoCounterString = null;
         boolean usingAutoCounterLinkedId = false;
@@ -353,7 +395,7 @@ public class ArgParser
         // not dealing with both NODUPLICATEVALUES and GLOB
         if (a.hasOption(Opt.NODUPLICATEVALUES) && avm.hasValue(a, val))
         {
-          Console.error("Argument '--" + argName
+          Console.error("Argument '" + DOUBLEDASH + argName
                   + "' cannot contain a duplicate value ('" + val
                   + "'). Ignoring this and subsequent occurrences.");
           continue;
@@ -364,8 +406,8 @@ public class ArgParser
         String id = idsv.get(ArgValues.ID);
         if (id != null && avm.hasId(a, id))
         {
-          Console.error("Argument '--" + argName + "' has a duplicate id ('"
-                  + id + "'). Ignoring.");
+          Console.error("Argument '" + DOUBLEDASH + argName
+                  + "' has a duplicate id ('" + id + "'). Ignoring.");
           continue;
         }
 
@@ -380,7 +422,7 @@ public class ArgParser
           {
             for (String v : globVals)
             {
-              v = makeSubstitutions(v);
+              v = makeSubstitutions(v, linkedId);
               SubVals vsv = new SubVals(globSubVals, v);
               avs.addValue(vsv, v, argIndex++);
               argIndexIncremented = true;
@@ -388,7 +430,7 @@ public class ArgParser
           }
           else
           {
-            avs.addValue(makeSubstitutions(val), argIndex);
+            avs.addValue(makeSubstitutions(val, linkedId), argIndex);
           }
         }
         else if (a.hasOption(Opt.BOOLEAN))
@@ -424,7 +466,7 @@ public class ArgParser
     }
   }
 
-  private String makeSubstitutions(String val)
+  private String makeSubstitutions(String val, String linkedId)
   {
     if (!this.substitutions)
       return val;
@@ -444,14 +486,39 @@ public class ArgParser
       subvals = "";
       rest = val;
     }
-    if ((rest.contains(AUTOCOUNTERLINKEDID)))
+    if (rest.contains(AUTOCOUNTERLINKEDID))
       rest = rest.replace(AUTOCOUNTERLINKEDID,
               String.valueOf(linkedIdAutoCounter));
-    if ((rest.contains(INCREMENTAUTOCOUNTERLINKEDID)))
+    if (rest.contains(INCREMENTAUTOCOUNTERLINKEDID))
       rest = rest.replace(INCREMENTAUTOCOUNTERLINKEDID,
               String.valueOf(++linkedIdAutoCounter));
-    if ((rest.contains("{}")))
+    if (rest.contains("{}"))
       rest = rest.replace("{}", String.valueOf(defaultLinkedIdCounter));
+    ArgValuesMap avm = linkedArgs.get(linkedId);
+    if (avm != null)
+    {
+      if (rest.contains(LINKEDIDBASENAME))
+      {
+        rest = rest.replace(LINKEDIDBASENAME, avm.getBasename());
+      }
+      if (rest.contains(LINKEDIDDIRNAME))
+      {
+        rest = rest.replace(LINKEDIDDIRNAME, avm.getDirname());
+      }
+    }
+    if (argFile != null)
+    {
+      if (rest.contains(ARGFILEBASENAME))
+      {
+        rest = rest.replace(ARGFILEBASENAME,
+                FileUtils.getBasename(new File(argFile)));
+      }
+      if (rest.contains(ARGFILEDIRNAME))
+      {
+        rest = rest.replace(ARGFILEDIRNAME,
+                FileUtils.getDirname(new File(argFile)));
+      }
+    }
 
     return new StringBuilder(subvals).append(rest).toString();
   }
@@ -582,13 +649,19 @@ public class ArgParser
       if (!argFile.exists())
       {
         String message = DOUBLEDASH
-                + Arg.ARGFILE.name().toLowerCase(Locale.ROOT) + "=\""
-                + argFile.getPath() + "\": File does not exist.";
+                + Arg.ARGFILE.name().toLowerCase(Locale.ROOT) + EQUALS
+                + "\"" + argFile.getPath() + "\": File does not exist.";
         Jalview.exit(message, 2);
       }
       try
       {
+        String setargfile = new StringBuilder(ArgParser.DOUBLEDASH)
+                .append(Arg.SETARGFILE.getName()).append(EQUALS)
+                .append(argFile.getCanonicalPath()).toString();
+        argsList.add(setargfile);
         argsList.addAll(Files.readAllLines(Paths.get(argFile.getPath())));
+        argsList.add(new StringBuilder(ArgParser.DOUBLEDASH)
+                .append(Arg.UNSETARGFILE.getName()).toString());
       } catch (IOException e)
       {
         String message = DOUBLEDASH
@@ -597,7 +670,9 @@ public class ArgParser
         Jalview.exit(message, 3);
       }
     }
-    return new ArgParser(argsList);
+    // Second param "true" uses Opt.PRIVATE args --setargile=argfile and
+    // --unsetargfile
+    return new ArgParser(argsList, true);
   }
 
 }
\ No newline at end of file