D2678: help: supporting both help and doc for aliases

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
22 messages Options
12
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
rdamazio created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  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.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/configitems.py
  mercurial/dispatch.py

CHANGE DETAILS

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: mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
pulkit added a comment.


  I am very very much excited about this. But, this patch lacks test. :(

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers
Cc: pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
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
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
rdamazio added a comment.


  In https://phab.mercurial-scm.org/D2678#43196, @pulkit wrote:
 
  > I am very very much excited about this. But, this patch lacks test. :(
 
 
  Sorry, added now (and re-running tests in parallel)

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers
Cc: pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
rdamazio added a comment.


  (I'll have more test updates in a min, sorry, please hold :) )

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers
Cc: pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
rdamazio updated this revision to Diff 6635.

REPOSITORY
  rHG Mercurial

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

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

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

CHANGE DETAILS

diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -769,9 +769,9 @@
   $ hg help shellalias
   hg shellalias
   
-  shell alias for:
-  
-    echo hi
+  shell alias for: echo hi
+  
+  (no help text available)
   
   defined by: helpext
   
diff --git a/tests/test-alias.t b/tests/test-alias.t
--- a/tests/test-alias.t
+++ b/tests/test-alias.t
@@ -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
@@ -53,11 +57,135 @@
   > 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 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)
 
 unknown
 
@@ -440,6 +568,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 +581,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
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
rdamazio added a comment.


  Ok, should be good to go now :)

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers
Cc: pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
mharbison72 added a comment.


  I really like this feature too.  Any plans to extend it to {fileset,revset,template}alias?
 
  I don't think this should prevent it from being accepted, but is there a way to get the help text rendered as-is, without reflowing?  For example, to simulate the usual 1 line summary + extended detail, I tried:
 
    [alias]
    phabimport:doc = Import a stack of revisions from phabricator.
      .
      This is extended help.
 
  That got me:
 
    $ ../hg help phabimport
    hg phabimport
   
    shell alias for: "%HG%" phabread $1 | "%HG%" import --bypass -
   
    Import a stack of revisions from phabricator. . This is extended help.
   
    defined by: c:\Users\Matt\projects\hg\.hg\hgrc:28
   
    (some details hidden, use --verbose to show complete help)
 
  (The middle '.' line is necessary, because the config parser throws away empty lines, complains about unexpected leading whitespace in the next line, and then exits without the usual 'abort: ' prefix.  That bad format even kills `hg version`, but the output does indicate exactly where the problem is.)

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
spectral added a comment.


  (I'm stepping in and responding while rdamazio is out for a few days)
 
  In https://phab.mercurial-scm.org/D2678#43299, @mharbison72 wrote:
 
  > I really like this feature too.  Any plans to extend it to {fileset,revset,template}alias?
 
 
  We don't have any concrete plans to do so, but would not be opposed.
 
  > I don't think this should prevent it from being accepted, but is there a way to get the help text rendered as-is, without reflowing?  For example, to simulate the usual 1 line summary + extended detail, I tried:
  >
  >   [alias]
  >   phabimport:doc = Import a stack of revisions from phabricator.
  >     .
  >     This is extended help.
  >
  >
  > That got me:
  >
  >   $ ../hg help phabimport
  >   hg phabimport
  >  
  >   shell alias for: "%HG%" phabread $1 | "%HG%" import --bypass -
  >  
  >   Import a stack of revisions from phabricator. . This is extended help.
  >  
  >   defined by: c:\Users\Matt\projects\hg\.hg\hgrc:28
  >  
  >   (some details hidden, use --verbose to show complete help)
  >
  >
  > (The middle '.' line is necessary, because the config parser throws away empty lines, complains about unexpected leading whitespace in the next line, and then exits without the usual 'abort: ' prefix.  That bad format even kills `hg version`, but the output does indicate exactly where the problem is.)
 
  I don't think that it'll be easy to make it avoid reflowing, I believe that's a pretty low-level aspect of the help command.  It would be better to fix the command parser to allow interstitial blank lines, but I don't have an estimate on how hard that would be.  Looks like our internal use of the feature from this patch is avoiding multi-line messages, I don't know if this is because they don't work, or because rdamazio didn't try it.  I agree it should hopefully not block the review in the meantime, especially if the desired+expected end-goal is that the config parser lets us have the blank lines (because then we won't need to change the text in a BC way; if we can't get the config parser to work, we may need to have this parse the text looking for things like \n, which could possibly be BC [though so mild I suspect it'll not be a problem])

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
mharbison72 added a comment.


  In https://phab.mercurial-scm.org/D2678#43533, @spectral wrote:
 
  > (I'm stepping in and responding while rdamazio is out for a few days)
  >
  > In https://phab.mercurial-scm.org/D2678#43299, @mharbison72 wrote:
  >
  > > I really like this feature too.  Any plans to extend it to {fileset,revset,template}alias?
  >
  >
  > We don't have any concrete plans to do so, but would not be opposed.
  >
  > > I don't think this should prevent it from being accepted, but is there a way to get the help text rendered as-is, without reflowing?  For example, to simulate the usual 1 line summary + extended detail, I tried:
  > >
  > >   [alias]
  > >   phabimport:doc = Import a stack of revisions from phabricator.
  > >     .
  > >     This is extended help.
  > >
  > >
  > > That got me:
  > >
  > >   $ ../hg help phabimport
  > >   hg phabimport
  > >  
  > >   shell alias for: "%HG%" phabread $1 | "%HG%" import --bypass -
  > >  
  > >   Import a stack of revisions from phabricator. . This is extended help.
  > >  
  > >   defined by: c:\Users\Matt\projects\hg\.hg\hgrc:28
  > >  
  > >   (some details hidden, use --verbose to show complete help)
  > >
  > >
  > > (The middle '.' line is necessary, because the config parser throws away empty lines, complains about unexpected leading whitespace in the next line, and then exits without the usual 'abort: ' prefix.  That bad format even kills `hg version`, but the output does indicate exactly where the problem is.)
  >
  > I don't think that it'll be easy to make it avoid reflowing, I believe that's a pretty low-level aspect of the help command.
 
 
  Yeah, avoiding reflow in general is too broad.  It is useful, until trying to make paragraphs or the table of options at the bottom of a help command.
 
  > It would be better to fix the command parser to allow interstitial blank lines, but I don't have an estimate on how hard that would be.
 
  That's probably not enough for things beyond paragraph breaks, like the options table.  FWIW, `hg help config.syntax` does say such lines are skipped.  IDK what changing that would break if extra blank lines happen to be after a random option.
 
  > Looks like our internal use of the feature from this patch is avoiding multi-line messages, I don't know if this is because they don't work, or because rdamazio didn't try it.  I agree it should hopefully not block the review in the meantime, especially if the desired+expected end-goal is that the config parser lets us have the blank lines (because then we won't need to change the text in a BC way; if we can't get the config parser to work, we may need to have this parse the text looking for things like \n, which could possibly be BC [though so mild I suspect it'll not be a problem])
 
  Maybe breaking after an explicit '\n' (string) which doesn't have an escaping '\' is the way to go.  I think templates support similar in that the lines for the item are all joined, and then the visible '\n' become hard breaks.  Assuming the code that injects it into the help system is what makes the substitution, I'm not sure where the BC comes in (unless you mean FB might have '\n' which should be rendered literally).  I don't know much about the help rendering though, so I have no idea how easy this is.

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
durin42 added a comment.


  Ugh:
 
    --- /home/augie/hg/tests/test-alias.t
    +++ /home/augie/hg/tests/test-alias.t.err
    @@ -357,15 +357,8 @@
     properly recursive
   
       $ hg dln
    -  changeset:   -1:0000000000000000000000000000000000000000
    -  phase:       public
    -  parent:      -1:0000000000000000000000000000000000000000
    -  parent:      -1:0000000000000000000000000000000000000000
    -  manifest:    -1:0000000000000000000000000000000000000000
    -  user:
    -  date:        Thu Jan 01 00:00:00 1970 +0000
    -  extra:       branch=default
    -
    +  abort: alias 'dln' resolves to unknown command 'lognull'
    +  [255]
   
   
     path expanding
   
    ERROR: test-alias.t output changed
    --- /home/augie/hg/tests/test-show.t
    +++ /home/augie/hg/tests/test-show.t.err
    @@ -135,19 +135,37 @@
     commands.show.aliasprefix aliases values to `show <view>`
   
       $ hg --config commands.show.aliasprefix=s sbookmarks
    +  devel-warn: config item requires an explicit default value: 'alias.sstack' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.swork' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.sbookmarks' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
       (no bookmarks set)
   
       $ hg --config commands.show.aliasprefix=sh shwork
    +  devel-warn: config item requires an explicit default value: 'alias.shstack' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.shwork' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.shbookmarks' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
       @  7b57 commit for book2
       o  b757 commit for book1
       o  ba59 initial
   
       $ hg --config commands.show.aliasprefix='s sh' swork
    +  devel-warn: config item requires an explicit default value: 'alias.sstack' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.swork' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.sbookmarks' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.shstack' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.shwork' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.shbookmarks' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
       @  7b57 commit for book2
       o  b757 commit for book1
       o  ba59 initial
   
       $ hg --config commands.show.aliasprefix='s sh' shwork
    +  devel-warn: config item requires an explicit default value: 'alias.sstack' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.swork' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.sbookmarks' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.shstack' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.shwork' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.shbookmarks' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
       @  7b57 commit for book2
       o  b757 commit for book1
       o  ba59 initial
    @@ -155,11 +173,17 @@
     The aliases don't appear in `hg config`
   
       $ hg --config commands.show.aliasprefix=s config alias
    +  devel-warn: config item requires an explicit default value: 'alias.sstack' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.swork' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.sbookmarks' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
       [1]
   
     Doesn't overwrite existing alias
   
       $ hg --config alias.swork='log -r .' --config commands.show.aliasprefix=s swork
    +  devel-warn: config item requires an explicit default value: 'alias.sstack' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.swork' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.sbookmarks' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
       changeset:   2:7b5709ab64cb
       tag:         tip
       user:        test
    @@ -168,6 +192,9 @@
   
   
       $ hg --config alias.swork='log -r .' --config commands.show.aliasprefix=s config alias
    +  devel-warn: config item requires an explicit default value: 'alias.sstack' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.swork' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
    +  devel-warn: config item requires an explicit default value: 'alias.sbookmarks' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup)
       alias.swork=log -r .
   
       $ cd ..
   
    ERROR: test-show.t output changed
 
  Discarding for now.

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers, durin42
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
spectral updated this revision to Diff 6980.

REPOSITORY
  rHG Mercurial

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

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

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

CHANGE DETAILS

diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -769,9 +769,9 @@
   $ hg help shellalias
   hg shellalias
   
-  shell alias for:
-  
-    echo hi
+  shell alias for: echo hi
+  
+  (no help text available)
   
   defined by: helpext
   
diff --git a/tests/test-alias.t b/tests/test-alias.t
--- a/tests/test-alias.t
+++ b/tests/test-alias.t
@@ -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
@@ -53,11 +57,135 @@
   > 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 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)
 
 unknown
 
@@ -440,6 +568,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 +581,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
@@ -445,7 +445,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
@@ -472,6 +472,7 @@
             return
 
         if self.definition.startswith('!'):
+            shdef = self.definition[1:]
             self.shell = True
             def fn(ui, *args):
                 env = {'HG_ARGS': ' '.join((self.name,) + args)}
@@ -485,11 +486,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:
@@ -511,14 +513,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'")
@@ -528,6 +528,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)
@@ -572,15 +580,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
@@ -604,16 +614,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',
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -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')



To: rdamazio, #hg-reviewers, durin42
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
spectral added a comment.


  In https://phab.mercurial-scm.org/D2678#45552, @durin42 wrote:
 
  > Ugh:
  >
  >   --- /home/augie/hg/tests/test-alias.t
  >   +++ /home/augie/hg/tests/test-alias.t.err
  >   @@ -357,15 +357,8 @@
  >    properly recursive
  >  
  >      $ hg dln
  >   -  changeset:   -1:0000000000000000000000000000000000000000
  >   -  phase:       public
  >   -  parent:      -1:0000000000000000000000000000000000000000
  >   -  parent:      -1:0000000000000000000000000000000000000000
  >   -  manifest:    -1:0000000000000000000000000000000000000000
  >   -  user:
  >   -  date:        Thu Jan 01 00:00:00 1970 +0000
  >   -  extra:       branch=default
  >   -
  >   +  abort: alias 'dln' resolves to unknown command 'lognull'
  >   +  [255]
 
 
  I wasn't able to reproduce this error when based off of https://phab.mercurial-scm.org/rHG31581528f2421dc5d8a567125b8ecc0367b2b906
 
  >
  >
  >   path expanding
  >    
  >
  > ERROR: test-alias.t output changed
  >
  > - /home/augie/hg/tests/test-show.t +++ /home/augie/hg/tests/test-show.t.err @@ -135,19 +135,37 @@ commands.show.aliasprefix aliases values to `show <view>`
  >
  >   $ hg --config commands.show.aliasprefix=s sbookmarks +  devel-warn: config item requires an explicit default value: 'alias.sstack' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup) +  devel-warn: config item requires an explicit default value: 'alias.swork' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup) +  devel-warn: config item requires an explicit default value: 'alias.sbookmarks' at: /tmp/hgtests.iyj57T/install/lib/python/hgext/show.py:430 (extsetup) (no bookmarks set)
 
  ... etc ....
 
  I fixed this one. PTAL (added third argument of None to call in hgext/show.py).

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers, durin42
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
pulkit added a comment.


  In https://phab.mercurial-scm.org/D2678#45633, @spectral wrote:
 
  > In https://phab.mercurial-scm.org/D2678#45552, @durin42 wrote:
  >
  > > Ugh:
  > >
  > >   --- /home/augie/hg/tests/test-alias.t
  > >   +++ /home/augie/hg/tests/test-alias.t.err
  > >   @@ -357,15 +357,8 @@
  > >    properly recursive
  > >  
  > >      $ hg dln
  > >   -  changeset:   -1:0000000000000000000000000000000000000000
  > >   -  phase:       public
  > >   -  parent:      -1:0000000000000000000000000000000000000000
  > >   -  parent:      -1:0000000000000000000000000000000000000000
  > >   -  manifest:    -1:0000000000000000000000000000000000000000
  > >   -  user:
  > >   -  date:        Thu Jan 01 00:00:00 1970 +0000
  > >   -  extra:       branch=default
  > >   -
  > >   +  abort: alias 'dln' resolves to unknown command 'lognull'
  > >   +  [255]
  >
  >
  > I wasn't able to reproduce this error when based off of https://phab.mercurial-scm.org/rHG31581528f2421dc5d8a567125b8ecc0367b2b906
 
 
  I was queuing this patch, but I see this test failure. It's flaky, sometimes it passes, sometimes it fails. So dropping for now.

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers, durin42, pulkit
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
rdamazio added a comment.


  The flakiness was just due to Python map order randomization in tests (a fixed PYTHONHASHSEED=3170796678 or similar reproduces it consistently by getting dln before lognull).
  The real issue was the added "ignoresub=True" argument which broke strict ordering guarantees in the return value, combined with the fact that each lazy alias entry makes a copy of the cmdtable *at the state when it's created*.
 
  I've fixed this in ui.configitems so it preserves ordering - PTAL. Should also be a tiny bit faster now.
  I've also added tests for the recursive alias case.

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers, durin42, pulkit
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
rdamazio updated this revision to Diff 7330.

REPOSITORY
  rHG Mercurial

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

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

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

CHANGE DETAILS

diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -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
   
diff --git a/tests/test-alias.t b/tests/test-alias.t
--- a/tests/test-alias.t
+++ b/tests/test-alias.t
@@ -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
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -738,11 +738,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 = ((k,v) for k,v in items if ':' not in k)
         if self.debugflag and not untrusted and self._reportuntrusted:
             for k, v in self._ucfg.items(section):
                 if self._tcfg.get(section, k) != v:
diff --git a/mercurial/help.py b/mercurial/help.py
--- a/mercurial/help.py
+++ b/mercurial/help.py
@@ -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))
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -449,7 +449,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
@@ -476,6 +476,7 @@
             return
 
         if self.definition.startswith('!'):
+            shdef = self.definition[1:]
             self.shell = True
             def fn(ui, *args):
                 env = {'HG_ARGS': ' '.join((self.name,) + args)}
@@ -489,11 +490,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:
@@ -515,14 +517,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'")
@@ -532,6 +532,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)
@@ -576,15 +584,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
@@ -608,16 +618,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',
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -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')



To: rdamazio, #hg-reviewers, durin42, pulkit
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
rdamazio updated this revision to Diff 7331.

REPOSITORY
  rHG Mercurial

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

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

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

CHANGE DETAILS

diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -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
   
diff --git a/tests/test-alias.t b/tests/test-alias.t
--- a/tests/test-alias.t
+++ b/tests/test-alias.t
@@ -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
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -738,11 +738,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:
diff --git a/mercurial/help.py b/mercurial/help.py
--- a/mercurial/help.py
+++ b/mercurial/help.py
@@ -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))
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -449,7 +449,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
@@ -476,6 +476,7 @@
             return
 
         if self.definition.startswith('!'):
+            shdef = self.definition[1:]
             self.shell = True
             def fn(ui, *args):
                 env = {'HG_ARGS': ' '.join((self.name,) + args)}
@@ -489,11 +490,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:
@@ -515,14 +517,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'")
@@ -532,6 +532,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)
@@ -576,15 +584,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
@@ -608,16 +618,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',
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -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')



To: rdamazio, #hg-reviewers, durin42, pulkit
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
pulkit added a comment.


  :(
 
    --- /home/foobar/repo/pushaccess/tests/test-paths.t
    +++ /home/foobar/repo/pushaccess/tests/test-paths.t.err
    @@ -132,10 +132,52 @@
     zeroconf wraps ui.configitems(), which shouldn't crash at least:
     
       $ hg paths --config extensions.zeroconf=
    -  dupe = $TESTTMP/b#tip
    -  dupe:pushurl = https://example.com/dupe
    -  expand = $TESTTMP/a/$SOMETHING/bar
    -  insecure = http://foo:***@example.com/
    +  ** unknown exception encountered, please report by visiting
    +  ** https://mercurial-scm.org/wiki/BugTracker
    +  ** Python 2.7.12 (default, Dec  4 2017, 14:50:18) [GCC 5.4.0 20160609]
    +  ** Mercurial Distributed SCM (version 4.5.2+1280-deb4b1721fe0)
    +  ** Extensions loaded: zeroconf
    +  Traceback (most recent call last):
    +    File "/tmp/hgtests.p14OA8/install/bin/hg", line 41, in <module>
    +      dispatch.run()
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/dispatch.py", line 93, in run
    +      status = (dispatch(req) or 0)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/dispatch.py", line 213, in dispatch
    +      ret = _runcatch(req)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/dispatch.py", line 354, in _runcatch
    +      return _callcatch(ui, _runcatchfunc)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/dispatch.py", line 362, in _callcatch
    +      return scmutil.callcatch(ui, func)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/scmutil.py", line 159, in callcatch
    +      return func()
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/dispatch.py", line 344, in _runcatchfunc
    +      return _dispatch(req)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/dispatch.py", line 958, in _dispatch
    +      cmdpats, cmdoptions)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/dispatch.py", line 715, in runcommand
    +      ret = _runcommand(ui, options, cmd, d)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/hgext/zeroconf/__init__.py", line 205, in cleanupafterdispatch
    +      return orig(ui, options, cmd, cmdfunc)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/dispatch.py", line 966, in _runcommand
    +      return cmdfunc()
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/dispatch.py", line 955, in <lambda>
    +      d = lambda: util.checksignature(func)(ui, *args, **strcmdopt)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/util.py", line 1537, in check
    +      return func(*args, **kwargs)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/commands.py", line 3789, in paths
    +      pathitems = sorted(ui.paths.iteritems())
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/util.py", line 1421, in __get__
    +      result = self.func(obj)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/ui.py", line 848, in paths
    +      return paths(self)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/ui.py", line 1699, in __init__
    +      for name, loc in ui.configitems('paths', ignoresub=True):
    +    File "/tmp/hgtests.p14OA8/install/lib/python/mercurial/extensions.py", line 359, in closure
    +      return func(*(args + a), **kw)
    +    File "/tmp/hgtests.p14OA8/install/lib/python/hgext/zeroconf/__init__.py", line 184, in configitems
    +      repos += getzcpaths()
    +  TypeError: unsupported operand type(s) for +=: 'generator' and 'generator'
    +  [1]
     
       $ cd ..
     
   
    ERROR: test-paths.t output changed

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers, durin42, pulkit
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
rdamazio added a comment.


  Sorry about that, I had fixed this one and forgot to re-upload. Try now.

REPOSITORY
  rHG Mercurial

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

To: rdamazio, #hg-reviewers, durin42, pulkit
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

D2678: help: supporting both help and doc for aliases

indygreg (Gregory Szorc)
In reply to this post by indygreg (Gregory Szorc)
rdamazio updated this revision to Diff 7346.

REPOSITORY
  rHG Mercurial

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

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

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

CHANGE DETAILS

diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -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
   
diff --git a/tests/test-alias.t b/tests/test-alias.t
--- a/tests/test-alias.t
+++ b/tests/test-alias.t
@@ -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
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -738,11 +738,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:
diff --git a/mercurial/help.py b/mercurial/help.py
--- a/mercurial/help.py
+++ b/mercurial/help.py
@@ -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))
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -449,7 +449,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
@@ -476,6 +476,7 @@
             return
 
         if self.definition.startswith('!'):
+            shdef = self.definition[1:]
             self.shell = True
             def fn(ui, *args):
                 env = {'HG_ARGS': ' '.join((self.name,) + args)}
@@ -489,11 +490,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:
@@ -515,14 +517,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'")
@@ -532,6 +532,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)
@@ -576,15 +584,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
@@ -608,16 +618,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',
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -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')



To: rdamazio, #hg-reviewers, durin42, pulkit
Cc: mharbison72, spectral, pulkit, mercurial-devel
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
12