help: supporting both help and doc for aliases
This allows an alias to be definted like:
[alias]
lj = log -Tjson
lj:help = [-r REV]
lj:doc = Shows the revision log in JSON format.
Differential Revision: https://phab.mercurial-scm.org/D2678
--- a/hgext/show.py Tue Mar 27 20:21:30 2018 +0530
+++ b/hgext/show.py Sun Mar 04 17:11:33 2018 -0500
@@ -427,7 +427,7 @@
continue
# Same for aliases.
- if ui.config('alias', name):
+ if ui.config('alias', name, None):
continue
ui.setconfig('alias', name, 'show %s' % view, source='show')
--- a/mercurial/configitems.py Tue Mar 27 20:21:30 2018 +0530
+++ b/mercurial/configitems.py Sun Mar 04 17:11:33 2018 -0500
@@ -114,7 +114,7 @@
coreconfigitem = getitemregister(coreitems)
coreconfigitem('alias', '.*',
- default=None,
+ default=dynamicdefault,
generic=True,
)
coreconfigitem('annotate', 'nodates',
--- a/mercurial/dispatch.py Tue Mar 27 20:21:30 2018 +0530
+++ b/mercurial/dispatch.py Sun Mar 04 17:11:33 2018 -0500
@@ -450,7 +450,7 @@
return r.sub(lambda x: replacemap[x.group()], cmd)
class cmdalias(object):
- def __init__(self, name, definition, cmdtable, source):
+ def __init__(self, ui, name, definition, cmdtable, source):
self.name = self.cmd = name
self.cmdname = ''
self.definition = definition
@@ -477,6 +477,7 @@
return
if self.definition.startswith('!'):
+ shdef = self.definition[1:]
self.shell = True
def fn(ui, *args):
env = {'HG_ARGS': ' '.join((self.name,) + args)}
@@ -490,11 +491,12 @@
"of %i variable in alias '%s' definition.\n"
% (int(m.groups()[0]), self.name))
return ''
- cmd = re.sub(br'\$(\d+|\$)', _checkvar, self.definition[1:])
+ cmd = re.sub(br'\$(\d+|\$)', _checkvar, shdef)
cmd = aliasinterpolate(self.name, args, cmd)
return ui.system(cmd, environ=env,
blockedtag='alias_%s' % self.name)
self.fn = fn
+ self._populatehelp(ui, name, shdef, self.fn)
return
try:
@@ -516,14 +518,12 @@
try:
tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
if len(tableentry) > 2:
- self.fn, self.opts, self.help = tableentry
+ self.fn, self.opts, cmdhelp = tableentry
else:
self.fn, self.opts = tableentry
+ cmdhelp = None
- if self.help.startswith("hg " + cmd):
- # drop prefix in old-style help lines so hg shows the alias
- self.help = self.help[4 + len(cmd):]
- self.__doc__ = self.fn.__doc__
+ self._populatehelp(ui, name, cmd, self.fn, cmdhelp)
except error.UnknownCommand:
self.badalias = (_("alias '%s' resolves to unknown command '%s'")
@@ -533,6 +533,14 @@
self.badalias = (_("alias '%s' resolves to ambiguous command '%s'")
% (self.name, cmd))
+ def _populatehelp(self, ui, name, cmd, fn, defaulthelp=None):
+ self.help = ui.config('alias', '%s:help' % name, defaulthelp or '')
+ if self.help and self.help.startswith("hg " + cmd):
+ # drop prefix in old-style help lines so hg shows the alias
+ self.help = self.help[4 + len(cmd):]
+
+ self.__doc__ = ui.config('alias', '%s:doc' % name, fn.__doc__)
+
@property
def args(self):
args = pycompat.maplist(util.expandpath, self.givenargs)
@@ -577,7 +585,8 @@
class lazyaliasentry(object):
"""like a typical command entry (func, opts, help), but is lazy"""
- def __init__(self, name, definition, cmdtable, source):
+ def __init__(self, ui, name, definition, cmdtable, source):
+ self.ui = ui
self.name = name
self.definition = definition
self.cmdtable = cmdtable.copy()
@@ -585,7 +594,8 @@
@util.propertycache
def _aliasdef(self):
- return cmdalias(self.name, self.definition, self.cmdtable, self.source)
+ return cmdalias(self.ui, self.name, self.definition, self.cmdtable,
+ self.source)
def __getitem__(self, n):
aliasdef = self._aliasdef
@@ -609,7 +619,7 @@
# 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'):
+ for alias, definition in ui.configitems('alias', ignoresub=True):
try:
if cmdtable[alias].definition == definition:
continue
@@ -618,7 +628,7 @@
pass
source = ui.configsource('alias', alias)
- entry = lazyaliasentry(alias, definition, cmdtable, source)
+ entry = lazyaliasentry(ui, alias, definition, cmdtable, source)
cmdtable[alias] = entry
def _parse(ui, args):
--- a/mercurial/help.py Tue Mar 27 20:21:30 2018 +0530
+++ b/mercurial/help.py Sun Mar 04 17:11:33 2018 -0500
@@ -370,8 +370,8 @@
if util.safehasattr(entry[0], 'definition'): # aliased command
source = entry[0].source
if entry[0].definition.startswith('!'): # shell alias
- doc = (_('shell alias for::\n\n %s\n\ndefined by: %s\n') %
- (entry[0].definition[1:], source))
+ doc = (_('shell alias for: %s\n\n%s\n\ndefined by: %s\n') %
+ (entry[0].definition[1:], doc, source))
else:
doc = (_('alias for: hg %s\n\n%s\n\ndefined by: %s\n') %
(entry[0].definition, doc, source))
--- a/mercurial/ui.py Tue Mar 27 20:21:30 2018 +0530
+++ b/mercurial/ui.py Sun Mar 04 17:11:33 2018 -0500
@@ -739,11 +739,7 @@
def configitems(self, section, untrusted=False, ignoresub=False):
items = self._data(untrusted).items(section)
if ignoresub:
- newitems = {}
- for k, v in items:
- if ':' not in k:
- newitems[k] = v
- items = list(newitems.iteritems())
+ items = [i for i in items if ':' not in i[0]]
if self.debugflag and not untrusted and self._reportuntrusted:
for k, v in self._ucfg.items(section):
if self._tcfg.get(section, k) != v:
--- a/tests/test-alias.t Tue Mar 27 20:21:30 2018 +0530
+++ b/tests/test-alias.t Sun Mar 04 17:11:33 2018 -0500
@@ -4,9 +4,13 @@
> # should clobber ci but not commit (issue2993)
> ci = version
> myinit = init
+ > myinit:doc = This is my documented alias for init.
+ > myinit:help = [OPTIONS] [BLA] [BLE]
> mycommit = commit
+ > mycommit:doc = This is my alias with only doc.
> optionalrepo = showconfig alias.myinit
> cleanstatus = status -c
+ > cleanstatus:help = [ONLYHELPHERE]
> unknown = bargle
> ambiguous = s
> recursive = recursive
@@ -20,9 +24,13 @@
> no--config = status --config a.config=1
> mylog = log
> lognull = log -r null
+ > lognull:doc = Logs the null rev
+ > lognull:help = foo bar baz
> shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
> positional = log --template '{\$2} {\$1} | {date|isodate}\n'
> dln = lognull --debug
+ > recursivedoc = dln
+ > recursivedoc:doc = Logs the null rev in debug mode
> nousage = rollback
> put = export -r 0 -o "\$FOO/%R.diff"
> blank = !printf '\n'
@@ -53,11 +61,148 @@
> log = -v
> EOF
-
basic
$ hg myinit alias
+help
+
+ $ hg help -c | grep myinit
+ myinit This is my documented alias for init.
+ $ hg help -c | grep mycommit
+ mycommit This is my alias with only doc.
+ $ hg help -c | grep cleanstatus
+ cleanstatus show changed files in the working directory
+ $ hg help -c | grep lognull
+ lognull Logs the null rev
+ $ hg help -c | grep dln
+ dln Logs the null rev
+ $ hg help -c | grep recursivedoc
+ recursivedoc Logs the null rev in debug mode
+ $ hg help myinit
+ hg myinit [OPTIONS] [BLA] [BLE]
+
+ alias for: hg init
+
+ This is my documented alias for init.
+
+ defined by: * (glob)
+ */* (glob) (?)
+ */* (glob) (?)
+ */* (glob) (?)
+
+ options:
+
+ -e --ssh CMD specify ssh command to use
+ --remotecmd CMD specify hg command to run on the remote side
+ --insecure do not verify server certificate (ignoring web.cacerts
+ config)
+
+ (some details hidden, use --verbose to show complete help)
+
+ $ hg help mycommit
+ hg mycommit [OPTION]... [FILE]...
+
+ alias for: hg commit
+
+ This is my alias with only doc.
+
+ defined by: * (glob)
+ */* (glob) (?)
+ */* (glob) (?)
+ */* (glob) (?)
+
+ options ([+] can be repeated):
+
+ -A --addremove mark new/missing files as added/removed before
+ committing
+ --close-branch mark a branch head as closed
+ --amend amend the parent of the working directory
+ -s --secret use the secret phase for committing
+ -e --edit invoke editor on commit messages
+ -i --interactive use interactive mode
+ -I --include PATTERN [+] include names matching the given patterns
+ -X --exclude PATTERN [+] exclude names matching the given patterns
+ -m --message TEXT use text as commit message
+ -l --logfile FILE read commit message from file
+ -d --date DATE record the specified date as commit date
+ -u --user USER record the specified user as committer
+ -S --subrepos recurse into subrepositories
+
+ (some details hidden, use --verbose to show complete help)
+
+ $ hg help cleanstatus
+ hg cleanstatus [ONLYHELPHERE]
+
+ alias for: hg status -c
+
+ show changed files in the working directory
+
+ Show status of files in the repository. If names are given, only files
+ that match are shown. Files that are clean or ignored or the source of a
+ copy/move operation, are not listed unless -c/--clean, -i/--ignored,
+ -C/--copies or -A/--all are given. Unless options described with "show
+ only ..." are given, the options -mardu are used.
+
+ Option -q/--quiet hides untracked (unknown and ignored) files unless
+ explicitly requested with -u/--unknown or -i/--ignored.
+
+ Note:
+ 'hg status' may appear to disagree with diff if permissions have
+ changed or a merge has occurred. The standard diff format does not
+ report permission changes and diff only reports changes relative to one
+ merge parent.
+
+ If one revision is given, it is used as the base revision. If two
+ revisions are given, the differences between them are shown. The --change
+ option can also be used as a shortcut to list the changed files of a
+ revision from its first parent.
+
+ The codes used to show the status of files are:
+
+ M = modified
+ A = added
+ R = removed
+ C = clean
+ ! = missing (deleted by non-hg command, but still tracked)
+ ? = not tracked
+ I = ignored
+ = origin of the previous file (with --copies)
+
+ Returns 0 on success.
+
+ defined by: * (glob)
+ */* (glob) (?)
+ */* (glob) (?)
+ */* (glob) (?)
+
+ options ([+] can be repeated):
+
+ -A --all show status of all files
+ -m --modified show only modified files
+ -a --added show only added files
+ -r --removed show only removed files
+ -d --deleted show only deleted (but tracked) files
+ -c --clean show only files without changes
+ -u --unknown show only unknown (not tracked) files
+ -i --ignored show only ignored files
+ -n --no-status hide status prefix
+ -C --copies show source of copied files
+ -0 --print0 end filenames with NUL, for use with xargs
+ --rev REV [+] show difference from revision
+ --change REV list the changed files of a revision
+ -I --include PATTERN [+] include names matching the given patterns
+ -X --exclude PATTERN [+] exclude names matching the given patterns
+ -S --subrepos recurse into subrepositories
+
+ (some details hidden, use --verbose to show complete help)
+
+ $ hg help recursivedoc | head -n 5
+ hg recursivedoc foo bar baz
+
+ alias for: hg dln
+
+ Logs the null rev in debug mode
unknown
@@ -440,6 +585,10 @@
> rebate = !echo this is \$HG_ARGS
> EOF
#endif
+ $ cat >> .hg/hgrc <<EOF
+ > rebate:doc = This is my alias which just prints something.
+ > rebate:help = [MYARGS]
+ > EOF
$ hg reba
hg: command 'reba' is ambiguous:
rebase rebate
@@ -449,6 +598,24 @@
$ hg rebat --foo-bar
this is rebate --foo-bar
+help for a shell alias
+
+ $ hg help -c | grep rebate
+ rebate This is my alias which just prints something.
+ $ hg help rebate
+ hg rebate [MYARGS]
+
+ shell alias for: echo this is $HG_ARGS
+
+ This is my alias which just prints something.
+
+ defined by:* (glob)
+ */* (glob) (?)
+ */* (glob) (?)
+ */* (glob) (?)
+
+ (some details hidden, use --verbose to show complete help)
+
invalid arguments
$ hg rt foo
--- a/tests/test-help.t Tue Mar 27 20:21:30 2018 +0530
+++ b/tests/test-help.t Sun Mar 04 17:11:33 2018 -0500
@@ -777,9 +777,9 @@
$ hg help shellalias
hg shellalias
- shell alias for:
-
- echo hi
+ shell alias for: echo hi
+
+ (no help text available)
defined by: helpext