Mercurial > hg
changeset 8655:21688b8a594b
Move alias into core
author | Brendan Cully <brendan@kublai.com> |
---|---|
date | Sat, 30 May 2009 11:32:23 -0700 |
parents | f6cc3638f468 |
children | 284fda4cd093 |
files | doc/hgrc.5.txt hgext/alias.py mercurial/dispatch.py tests/test-alias tests/test-alias.out |
diffstat | 5 files changed, 117 insertions(+), 86 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/hgrc.5.txt Sat May 30 19:37:01 2009 +0200 +++ b/doc/hgrc.5.txt Sat May 30 11:32:23 2009 -0700 @@ -100,6 +100,29 @@ Mercurial "hgrc" file, the purpose of each section, its possible keys, and their possible values. +[[alias]] +alias:: + Defines command aliases. + Aliases allow you to define your own commands in terms of other + commands (or aliases), optionally including arguments. ++ +Alias definitions consist of lines of the form: ++ + <alias> = <command> [<argument]... ++ +For example, this definition: ++ + latest = log --limit 5 ++ +creates a new command `latest` that shows only the five most recent +changesets. You can define subsequent aliases using earlier ones: ++ + stable5 = latest -b stable ++ +*Note*: It is possible to create aliases with the same names as +existing commands, which will then override the original +definitions. This is almost always a bad idea! + [[auth]] auth:: Authentication credentials for HTTP authentication.
--- a/hgext/alias.py Sat May 30 19:37:01 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -# Copyright (C) 2007 Brendan Cully <brendan@kublai.com> -# This file is published under the GNU GPL. - -'''allow user-defined command aliases - -To use, create entries in your hgrc of the form - -[alias] -mycmd = cmd --args -''' - -from mercurial.i18n import _ -from mercurial import commands, cmdutil, error - -cmdtable = {} - -class RecursiveCommand(Exception): pass - -class lazycommand(object): - '''defer command lookup until needed, so that extensions loaded - after alias can be aliased''' - def __init__(self, ui, name, target): - self._ui = ui - self._name = name - self._target = target - self._cmd = None - - def __len__(self): - self._resolve() - return len(self._cmd) - - def __getitem__(self, key): - self._resolve() - return self._cmd[key] - - def __iter__(self): - self._resolve() - return self._cmd.__iter__() - - def _resolve(self): - if self._cmd is not None: - return - - try: - self._cmd = cmdutil.findcmd(self._target, commands.table, False)[1] - if self._cmd == self: - raise RecursiveCommand() - if self._target in commands.norepo.split(' '): - commands.norepo += ' %s' % self._name - return - except error.UnknownCommand: - msg = _('*** [alias] %s: command %s is unknown') % \ - (self._name, self._target) - except error.AmbiguousCommand: - msg = _('*** [alias] %s: command %s is ambiguous') % \ - (self._name, self._target) - except RecursiveCommand: - msg = _('*** [alias] %s: circular dependency on %s') % \ - (self._name, self._target) - def nocmd(*args, **opts): - self._ui.warn(msg + '\n') - return 1 - nocmd.__doc__ = msg - self._cmd = (nocmd, [], '') - commands.norepo += ' %s' % self._name - -def uisetup(ui): - for cmd, target in ui.configitems('alias'): - if not target: - ui.warn(_('*** [alias] %s: no definition\n') % cmd) - continue - args = target.split(' ', 1) - tcmd = args.pop(0) - if args: - args = args[0] - defaults = ui.config('defaults', cmd) - if defaults: - args = ' '.join((args, defaults)) - ui.setconfig('defaults', cmd, args) - cmdtable[cmd] = lazycommand(ui, cmd, tcmd)
--- a/mercurial/dispatch.py Sat May 30 19:37:01 2009 +0200 +++ b/mercurial/dispatch.py Sat May 30 11:32:23 2009 -0700 @@ -161,6 +161,74 @@ return p +def aliasargs(fn): + if hasattr(fn, 'args'): + return fn.args + return [] + +class cmdalias(object): + def __init__(self, name, definition, cmdtable): + self.name = name + self.definition = definition + self.args = [] + self.opts = [] + self.help = '' + self.norepo = True + + try: + cmdutil.findcmd(self.name, cmdtable, True) + self.shadows = True + except error.UnknownCommand: + self.shadows = False + + if not self.definition: + def fn(ui, *args): + ui.warn(_("no definition for alias '%s'\n") % self.name) + return 1 + self.fn = fn + + return + + args = shlex.split(self.definition) + cmd = args.pop(0) + opts = [] + help = '' + + try: + self.fn, self.opts, self.help = cmdutil.findcmd(cmd, cmdtable, False)[1] + self.args = aliasargs(self.fn) + args + if cmd not in commands.norepo.split(' '): + self.norepo = False + except error.UnknownCommand: + def fn(ui, *args): + ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \ + % (self.name, cmd)) + return 1 + self.fn = fn + except error.AmbiguousCommand: + def fn(ui, *args): + ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \ + % (self.name, cmd)) + return 1 + self.fn = fn + + def __call__(self, ui, *args, **opts): + if self.shadows: + ui.debug(_("alias '%s' shadows command\n") % self.name) + + return 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. + for alias, definition in ui.configitems('alias'): + aliasdef = cmdalias(alias, definition, cmdtable) + + cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help) + if aliasdef.norepo: + commands.norepo += ' %s' % alias + def _parse(ui, args): options = {} cmdoptions = {} @@ -175,6 +243,7 @@ aliases, i = cmdutil.findcmd(cmd, commands.table, ui.config("ui", "strict")) cmd = aliases[0] + args = aliasargs(i[0]) + args defaults = ui.config("defaults", cmd) if defaults: args = shlex.split(defaults) + args @@ -301,6 +370,9 @@ % (name, " ".join(overrides))) commands.table.update(cmdtable) _loaded.add(name) + + addaliases(lui, commands.table) + # check for fallback encoding fallback = lui.config('ui', 'fallbackencoding') if fallback:
--- a/tests/test-alias Sat May 30 19:37:01 2009 +0200 +++ b/tests/test-alias Sat May 30 11:32:23 2009 -0700 @@ -1,18 +1,17 @@ #!/bin/sh cat >> $HGRCPATH <<EOF -[extensions] -alias= - [alias] myinit = init cleanstatus = status -c unknown = bargle ambiguous = s recursive = recursive +nodefinition = mylog = log lognull = log -r null shortlog = log --template '{rev} {node|short} | {date|isodate}\n' +dln = lognull --debug [defaults] mylog = -q @@ -32,6 +31,9 @@ echo '% recursive' hg recursive +echo '% no definition' +hg nodef + cd alias echo foo > foo hg ci -Amfoo @@ -45,3 +47,6 @@ echo '% interaction with defaults' hg mylog hg lognull + +echo '% properly recursive' +hg dln
--- a/tests/test-alias.out Sat May 30 19:37:01 2009 +0200 +++ b/tests/test-alias.out Sat May 30 11:32:23 2009 -0700 @@ -1,10 +1,12 @@ % basic % unknown -*** [alias] unknown: command bargle is unknown +alias 'unknown' resolves to unknown command 'bargle' % ambiguous -*** [alias] ambiguous: command s is ambiguous +alias 'ambiguous' resolves to ambiguous command 's' % recursive -*** [alias] recursive: circular dependency on recursive +alias 'recursive' resolves to unknown command 'recursive' +% no definition +no definition for alias 'nodefinition' adding foo % with opts C foo @@ -13,3 +15,12 @@ % interaction with defaults 0:e63c23eaa88a -1:000000000000 +% properly recursive +changeset: -1:0000000000000000000000000000000000000000 +parent: -1:0000000000000000000000000000000000000000 +parent: -1:0000000000000000000000000000000000000000 +manifest: -1:0000000000000000000000000000000000000000 +user: +date: Thu Jan 01 00:00:00 1970 +0000 +extra: branch=default +