aliases: 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
--- a/mercurial/dispatch.py Wed Aug 18 18:18:26 2010 -0400
+++ b/mercurial/dispatch.py Wed Aug 18 18:56:44 2010 -0400
@@ -6,7 +6,7 @@
# 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
@@ -214,8 +214,18 @@
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)}
+ def _checkvar(m):
+ if int(m.groups()[0]) <= len(args):
+ return m.group()
+ else:
+ return ''
+ cmd = re.sub(r'\$(\d+)', _checkvar, self.definition[1:])
+ replace = dict((str(i + 1), arg) for i, arg in enumerate(args))
+ replace['0'] = self.name
+ replace['@'] = ' '.join(args)
+ cmd = util.interpolate(r'\$', replace, cmd)
+ return util.system(cmd, environ=env)
self.fn = fn
return
@@ -274,7 +284,10 @@
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
--- a/tests/test-alias.t Wed Aug 18 18:18:26 2010 -0400
+++ b/tests/test-alias.t Wed Aug 18 18:56:44 2010 -0400
@@ -16,7 +16,13 @@
> 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]
@@ -146,10 +152,35 @@
+foo
-shell aliases
+simple shell aliases
+ $ hg blank
+
+ $ hg blank foo
+
+ $ hg echo
+
+ $ hg self
+ self
$ hg echo foo
foo
+ $ hg echo 'test $2' foo
+ test $2 foo
+ $ hg echo1 foo bar baz
+ foo
+ $ hg echo2 foo bar baz
+ bar
+ $ hg echo13 foo bar baz test
+ foo baz
+ $ hg echo2 foo
+
+ $ echo bar > bar
+ $ hg ci -qA -m bar
+ $ hg count .
+ 1
+ $ hg count 'branch(default)'
+ 2
+
invalid arguments