D2678: help: supporting both help and doc for aliases

rdamazio (Rodrigo Damazio Bovendorp) phabricator at mercurial-scm.org
Sun Mar 4 17:40:49 EST 2018


rdamazio updated this revision to Diff 6634.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2678?vs=6632&id=6634

REVISION DETAIL
  https://phab.mercurial-scm.org/D2678

AFFECTED FILES
  mercurial/configitems.py
  mercurial/dispatch.py
  mercurial/help.py
  tests/test-alias.t

CHANGE DETAILS

diff --git a/tests/test-alias.t b/tests/test-alias.t
--- a/tests/test-alias.t
+++ b/tests/test-alias.t
@@ -4,6 +4,8 @@
   > # 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
   > optionalrepo = showconfig alias.myinit
   > cleanstatus = status -c
@@ -53,11 +55,34 @@
   > log = -v
   > EOF
 
-
 basic
 
   $ hg myinit alias
 
+help
+
+  $ hg help -c | grep myinit
+   myinit             This is my documented alias for init.
+  $ 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)
 
 unknown
 
@@ -440,6 +465,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 +478,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
diff --git a/mercurial/help.py b/mercurial/help.py
--- a/mercurial/help.py
+++ b/mercurial/help.py
@@ -366,8 +366,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))
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -420,7 +420,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
@@ -447,6 +447,7 @@
             return
 
         if self.definition.startswith('!'):
+            shdef = self.definition[1:]
             self.shell = True
             def fn(ui, *args):
                 env = {'HG_ARGS': ' '.join((self.name,) + args)}
@@ -460,11 +461,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:
@@ -486,14 +488,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'")
@@ -503,6 +503,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)
@@ -547,15 +555,17 @@
 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()
         self.source = source
 
     @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
@@ -579,16 +589,16 @@
     # 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
         except (KeyError, AttributeError):
             # definition might not exist or it might not be a cmdalias
             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):
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -114,7 +114,7 @@
 coreconfigitem = getitemregister(coreitems)
 
 coreconfigitem('alias', '.*',
-    default=None,
+    default=dynamicdefault,
     generic=True,
 )
 coreconfigitem('annotate', 'nodates',



To: rdamazio, #hg-reviewers
Cc: pulkit, mercurial-devel


More information about the Mercurial-devel mailing list