[PATCH 1 of 1] dispatch: provide more flexible ways to work with shell alias arguments

Steve Losh steve at stevelosh.com
Tue Aug 17 18:24:24 CDT 2010


# HG changeset patch
# User Steve Losh <steve at stevelosh.com>
# Date 1280375531 14400
# Node ID 0fa021cfb33433d4365d00dec8ad4cde5db19a3a
# Parent  7d2ea5ce4aace67e299a99e6292b379686b1bde9
dispatch: provide more flexible ways to work with shell alias arguments

This patch changes the functionality of shell aliases to add more powerful
options for working with shell alias arguments.

First: the alias name + arguments to a shell alias are set as an HG_ARGS
environment variable, delimited by spaces. This matches the behavior of hooks.

Second: any occurrences of "$@" (without quotes) are replaced with the
arguments, separated by spaces. This happens *before* the alias gets to the shell.

Third: any positive numeric variables ("$1", "$2", etc) are replaced with the
appropriate argument, indexed from 1. "$0" is replaced with the name of the
alias. Any "extra" numeric variables are replaced with an empty string.  This
happens *before* the alias gets to the shell.

These changes allow for more flexible shell aliases:

    [alias]
    echo = !echo $@
    count = !hg log -r "$@" --template='.' | wc -c | sed -e 's/ //g'
    qqueuemv = !mv "`hg root`/.hg/patches-$1" "`hg root`/.hg/patches-$2"

In action:

    $ hg echo foo
    foo

    $ hg count 'branch(default)'
    901

    $ hg count 'branch(stable) and keyword(fixes)'
    102

    $ hg qqueuemv myfeature somefeature

diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -4,11 +4,11 @@
 #
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
 from i18n import _
-import os, sys, atexit, signal, pdb, socket, errno, shlex, time, traceback
+import os, sys, atexit, signal, pdb, socket, errno, shlex, time, traceback, re
 import util, commands, hg, fancyopts, extensions, hook, error
 import cmdutil, encoding
 import ui as uimod
 
 def run():
@@ -212,12 +212,17 @@
 
             return
 
         if self.definition.startswith('!'):
             def fn(ui, *args):
-                cmd = '%s %s' % (self.definition[1:], ' '.join(args))
-                return util.system(cmd)
+                env = {'HG_ARGS': ' '.join((self.name,) + args)}
+                definition = self.definition.replace('$@', ' '.join(args))
+                definition = definition.replace('$0', self.name)
+                for i, arg in enumerate(args):
+                    definition = definition.replace('$%d' % (i + 1), arg)
+                definition = re.sub(r'\$\d+', '', definition)
+                return util.system(definition[1:], environ=env)
             self.fn = fn
             return
 
         args = shlex.split(self.definition)
         cmd = args.pop(0)
@@ -272,11 +277,14 @@
 
     def __call__(self, ui, *args, **opts):
         if self.shadows:
             ui.debug("alias '%s' shadows command\n" % self.name)
 
-        return util.checksignature(self.fn)(ui, *args, **opts)
+        if self.definition.startswith('!'):
+            return self.fn(ui, *args, **opts)
+        else:
+            return util.checksignature(self.fn)(ui, *args, **opts)
 
 def addaliases(ui, cmdtable):
     # aliases are processed after extensions have been loaded, so they
     # may use extension commands. Aliases can also use other alias definitions,
     # but only if they have been defined prior to the current definition.
diff --git a/tests/test-alias.t b/tests/test-alias.t
--- a/tests/test-alias.t
+++ b/tests/test-alias.t
@@ -14,11 +14,17 @@
   > lognull = log -r null
   > shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
   > dln = lognull --debug
   > nousage = rollback
   > put = export -r 0 -o "\$FOO/%R.diff"
-  > echo = !echo
+  > blank = !echo
+  > self = !echo \$0
+  > echo = !echo \$@
+  > echo1 = !echo \$1
+  > echo2 = !echo \$2
+  > echo13 = !echo \$1 \$3
+  > count = !hg log -r "\$@" --template='.' | wc -c | sed -e 's/ //g'
   > rt = root
   > 
   > [defaults]
   > mylog = -q
   > lognull = -q
@@ -146,12 +152,31 @@
   +foo
 
 
 shell aliases
 
+  $ hg blank
+  
+  $ hg echo
+  
+  $ hg self
+  self
   $ hg echo foo
   foo
+  $ hg echo1 foo bar baz
+  foo
+  $ hg echo2 foo bar baz
+  bar
+  $ hg echo13 foo bar baz test
+  foo baz
+  $ echo bar > bar
+  $ hg ci -qA -m bar
+  $ hg count .
+  1
+  $ hg count 'branch(default)'
+  2
+
 
 invalid arguments
 
   $ hg rt foo
   hg rt: invalid arguments


More information about the Mercurial-devel mailing list