[cig-commits] r6121 - cs/pythia/trunk/pyre/applications

leif at geodynamics.org leif at geodynamics.org
Mon Feb 26 20:48:24 PST 2007


Author: leif
Date: 2007-02-26 20:48:24 -0800 (Mon, 26 Feb 2007)
New Revision: 6121

Modified:
   cs/pythia/trunk/pyre/applications/CommandlineParser.py
   cs/pythia/trunk/pyre/applications/Executive.py
Log:
Issue5: Implemented simple Bash "programmable completion" for Pyre
apps.  Add the following to your .bashrc to use:

    complete -C "pyreapp -c" pyreapp

where 'pyreapp' is any Pyre application, e.g.,

    complete -C "citcoms -c" citcoms

~~~ Benefits ~~~

Say you don't remember how to set the time limit for a job.  Type

    citcoms <TAB>

A list of all top-level properties and facilities is presented (plus
all .cfg and .pml files in the current working directory).

Hmmm.  Perhaps it is under 'job'.  So you continue typing:

    citcoms --job.<TAB>

A list of the properties and facilities for 'job' appears.  Ah, there
it is -- "job.walltime".  But you are lazy, so you just type a 'w' and
hit <TAB> again:

    citcoms --job.w<TAB>

And the shell completes "walltime" for you :-)

~~~ Limitations ~~~

Pyre will not help you with trait values:

    myapp --foo=<TAB>

will do nothing.  But in the future, it could print a list of valid
values for 'foo' in certain cases.

Currently, tab-completion does not work for apps which override the
default CommandlineParser.  (There is exactly one such app: PyLith
v0.8.)

~~~ Bugs ~~~

If you override a facility setting on the command line, the
completions for traits of the corresponding component will be
wrong.  E.g.,

    myapp --solver=xyz --solver.<TAB>

will show you the traits for the solver set by default or in a
configuration file -- not necessarily those of the 'xyz' solver.


Modified: cs/pythia/trunk/pyre/applications/CommandlineParser.py
===================================================================
--- cs/pythia/trunk/pyre/applications/CommandlineParser.py	2007-02-27 00:57:27 UTC (rev 6120)
+++ cs/pythia/trunk/pyre/applications/CommandlineParser.py	2007-02-27 04:48:24 UTC (rev 6121)
@@ -25,6 +25,22 @@
         return
 
 
+    def parseArgument(self, arg, prevArg):
+        if arg == "":
+            return self.prefixes[0], [], "", ""
+        candidate = self._filterNonOptionArgument(arg)
+        for p in self.prefixes:
+            if arg.startswith(p):
+                prefix = p
+                candidate = arg[len(p):]
+                break
+        else:
+            return None, None, None, arg
+        key, value = self._parseArgument(candidate)
+        fields = key.split(self.separator)
+        return prefix, fields, value, None
+
+
     def __init__(self):
         self.actions = {
             'help': ['?', 'h'],

Modified: cs/pythia/trunk/pyre/applications/Executive.py
===================================================================
--- cs/pythia/trunk/pyre/applications/Executive.py	2007-02-27 00:57:27 UTC (rev 6120)
+++ cs/pythia/trunk/pyre/applications/Executive.py	2007-02-27 04:48:24 UTC (rev 6121)
@@ -93,7 +93,69 @@
 
 
     def complete(self):
-        # NYI: bash tab-completion
+        """perform shell command completion"""
+        
+        from glob import glob
+        import os
+        
+        arg, prevArg = self.unprocessedArguments[1:3]
+        if arg == "":
+            line = os.environ['COMP_LINE']
+            point = int(os.environ['COMP_POINT'])
+            if line[point - 1] == "=":
+                # NYI: value completion
+                return
+        
+        parser = self.createCommandlineParser()
+        prefix, fields, value, filenameStem = parser.parseArgument(arg, prevArg)
+
+        # Match filenames.
+        if filenameStem is not None:
+            for codec in self.getCurator().codecs.itervalues():
+                extension = "." + codec.extension
+                if filenameStem:
+                    pattern = "%s*" % filenameStem
+                    for filename in glob(pattern):
+                        if filename.endswith(extension):
+                            print filename
+                else:
+                    pattern = "%s*%s" % (filenameStem, extension)
+                    for filename in glob(pattern):
+                        print filename
+
+        # Match traits.
+        if fields is not None:
+            component = self
+            path = ""
+            for field in fields[:-1]:
+                facilityNames = component.inventory.facilityNames()
+                if not field in facilityNames:
+                    return
+                path += field + "."
+                component = component.getTraitValue(field)
+            if fields:
+                field = fields[-1]
+            else:
+                field = ""
+            propertyNames = component.inventory.propertyNames()
+            candidates = []
+            for prop in propertyNames:
+                if prop.startswith(field):
+                    candidates.append(prop)
+            if not candidates:
+                return
+            if len(candidates) == 1:
+                prop = candidates[0]
+                facilityNames = component.inventory.facilityNames()
+                if prop in facilityNames:
+                    print "%s%s%s." % (prefix, path, prop)
+                    print "%s%s%s=" % (prefix, path, prop)
+                else:
+                    print "%s%s%s" % (prefix, path, prop)
+            else:
+                for prop in candidates:
+                    print "%s%s%s" % (prefix, path, prop)        
+
         return
 
 



More information about the cig-commits mailing list