changeset 40293:c303d65d2e34

help: assigning categories to existing commands I'm separating this into its own commit so people can bikeshed over the actual categorization (vs the support for categories). These categories are based on the help implementation we've been using internally at Google, and have had zero complaints. Differential Revision: https://phab.mercurial-scm.org/D5067
author rdamazio@google.com
date Sat, 13 Oct 2018 02:17:41 -0700
parents 9c6473d2038b
children fabbf9310025
files hgext/absorb.py hgext/amend.py hgext/blackbox.py hgext/censor.py hgext/children.py hgext/churn.py hgext/closehead.py hgext/extdiff.py hgext/fetch.py hgext/fix.py hgext/githelp.py hgext/gpg.py hgext/graphlog.py hgext/hgk.py hgext/histedit.py hgext/journal.py hgext/mq.py hgext/patchbomb.py hgext/purge.py hgext/rebase.py hgext/record.py hgext/releasenotes.py hgext/relink.py hgext/share.py hgext/shelve.py hgext/show.py hgext/split.py hgext/strip.py hgext/transplant.py hgext/uncommit.py mercurial/commands.py mercurial/help.py mercurial/registrar.py tests/test-globalopts.t tests/test-help.t tests/test-mq.t
diffstat 36 files changed, 588 insertions(+), 244 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/absorb.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/absorb.py	Sat Oct 13 02:17:41 2018 -0700
@@ -993,7 +993,8 @@
            _('edit what lines belong to which changesets before commit '
              '(EXPERIMENTAL)')),
          ] + commands.dryrunopts + commands.templateopts + commands.walkopts,
-         _('hg absorb [OPTION] [FILE]...'))
+         _('hg absorb [OPTION] [FILE]...'),
+         helpcategory=command.CATEGORY_COMMITTING)
 def absorbcmd(ui, repo, *pats, **opts):
     """incorporate corrections into the stack of draft changesets
 
--- a/hgext/amend.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/amend.py	Sat Oct 13 02:17:41 2018 -0700
@@ -38,6 +38,7 @@
      ('n', 'note', '', _('store a note on the amend')),
     ] + cmdutil.walkopts + cmdutil.commitopts + cmdutil.commitopts2,
     _('[OPTION]... [FILE]...'),
+    helpcategory=command.CATEGORY_COMMITTING,
     inferrepo=True)
 def amend(ui, repo, *pats, **opts):
     """amend the working copy parent with all or specified outstanding changes
--- a/hgext/blackbox.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/blackbox.py	Sat Oct 13 02:17:41 2018 -0700
@@ -229,7 +229,8 @@
 @command('^blackbox',
     [('l', 'limit', 10, _('the number of events to show')),
     ],
-    _('hg blackbox [OPTION]...'))
+    _('hg blackbox [OPTION]...'),
+    helpcategory=command.CATEGORY_MAINTENANCE)
 def blackbox(ui, repo, *revs, **opts):
     '''view the recent repository events
     '''
--- a/hgext/censor.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/censor.py	Sat Oct 13 02:17:41 2018 -0700
@@ -47,7 +47,8 @@
 @command('censor',
     [('r', 'rev', '', _('censor file from specified revision'), _('REV')),
      ('t', 'tombstone', '', _('replacement tombstone data'), _('TEXT'))],
-    _('-r REV [-t TEXT] [FILE]'))
+    _('-r REV [-t TEXT] [FILE]'),
+    helpcategory=command.CATEGORY_MAINTENANCE)
 def censor(ui, repo, path, rev='', tombstone='', **opts):
     with repo.wlock(), repo.lock():
         return _docensor(ui, repo, path, rev, tombstone, **opts)
--- a/hgext/children.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/children.py	Sat Oct 13 02:17:41 2018 -0700
@@ -40,6 +40,7 @@
      _('show children of the specified revision'), _('REV')),
     ] + templateopts,
     _('hg children [-r REV] [FILE]'),
+    helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
     inferrepo=True)
 def children(ui, repo, file_=None, **opts):
     """show the children of the given or working directory revision
--- a/hgext/churn.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/churn.py	Sat Oct 13 02:17:41 2018 -0700
@@ -116,6 +116,7 @@
     ('', 'aliases', '', _('file with email aliases'), _('FILE')),
     ] + cmdutil.walkopts,
     _("hg churn [-d DATE] [-r REV] [--aliases FILE] [FILE]"),
+    helpcategory=command.CATEGORY_MAINTENANCE,
     inferrepo=True)
 def churn(ui, repo, *pats, **opts):
     '''histogram of changes to the repository
--- a/hgext/closehead.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/closehead.py	Sat Oct 13 02:17:41 2018 -0700
@@ -32,7 +32,9 @@
                _('revision to check'), _('REV'))]
 
 @command('close-head|close-heads', commitopts + commitopts2 + commitopts3,
-    _('[OPTION]... [REV]...'), inferrepo=True)
+    _('[OPTION]... [REV]...'),
+    helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
+    inferrepo=True)
 def close_branch(ui, repo, *revs, **opts):
     """close the given head revisions
 
--- a/hgext/extdiff.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/extdiff.py	Sat Oct 13 02:17:41 2018 -0700
@@ -338,6 +338,7 @@
     [('p', 'program', '', _('comparison program to run'), _('CMD')),
      ] + extdiffopts,
     _('hg extdiff [OPT]... [FILE]...'),
+    helpcategory=command.CATEGORY_FILE_CONTENTS,
     inferrepo=True)
 def extdiff(ui, repo, *pats, **opts):
     '''use external program to diff repository (or selected files)
--- a/hgext/fetch.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/fetch.py	Sat Oct 13 02:17:41 2018 -0700
@@ -41,7 +41,8 @@
     ('', 'force-editor', None, _('edit commit message (DEPRECATED)')),
     ('', 'switch-parent', None, _('switch parents when merging')),
     ] + cmdutil.commitopts + cmdutil.commitopts2 + cmdutil.remoteopts,
-    _('hg fetch [SOURCE]'))
+    _('hg fetch [SOURCE]'),
+    helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
 def fetch(ui, repo, source='default', **opts):
     '''pull changes from a remote repository, merge new changes if needed.
 
--- a/hgext/fix.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/fix.py	Sat Oct 13 02:17:41 2018 -0700
@@ -109,7 +109,8 @@
 wholeopt = ('', 'whole', False, _('always fix every line of a file'))
 usage = _('[OPTION]... [FILE]...')
 
-@command('fix', [allopt, baseopt, revopt, wdiropt, wholeopt], usage)
+@command('fix', [allopt, baseopt, revopt, wdiropt, wholeopt], usage,
+        helpcategory=command.CATEGORY_FILE_CONTENTS)
 def fix(ui, repo, *pats, **opts):
     """rewrite file content in changesets or working directory
 
--- a/hgext/githelp.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/githelp.py	Sat Oct 13 02:17:41 2018 -0700
@@ -51,7 +51,8 @@
     return s
 
 @command('^githelp|git', [
-    ], _('hg githelp'))
+    ], _('hg githelp'),
+    helpcategory=command.CATEGORY_HELP)
 def githelp(ui, repo, *args, **kwargs):
     '''suggests the Mercurial equivalent of the given git command
 
--- a/hgext/gpg.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/gpg.py	Sat Oct 13 02:17:41 2018 -0700
@@ -14,6 +14,7 @@
 from mercurial import (
     cmdutil,
     error,
+    help,
     match,
     node as hgnode,
     pycompat,
@@ -46,6 +47,9 @@
     generic=True,
 )
 
+# Custom help category
+_HELP_CATEGORY = 'gpg'
+
 class gpg(object):
     def __init__(self, path, key=None):
         self.path = path
@@ -169,7 +173,7 @@
         validkeys.append((key[1], key[2], key[3]))
     return validkeys
 
-@command("sigs", [], _('hg sigs'))
+@command("sigs", [], _('hg sigs'), helpcategory=_HELP_CATEGORY)
 def sigs(ui, repo):
     """list signed changesets"""
     mygpg = newgpg(ui)
@@ -194,7 +198,7 @@
             r = "%5d:%s" % (rev, hgnode.hex(repo.changelog.node(rev)))
             ui.write("%-30s %s\n" % (keystr(ui, k), r))
 
-@command("sigcheck", [], _('hg sigcheck REV'))
+@command("sigcheck", [], _('hg sigcheck REV'), helpcategory=_HELP_CATEGORY)
 def sigcheck(ui, repo, rev):
     """verify all the signatures there may be for a particular revision"""
     mygpg = newgpg(ui)
@@ -237,7 +241,8 @@
            _('use text as commit message'), _('TEXT')),
           ('e', 'edit', False, _('invoke editor on commit messages')),
          ] + cmdutil.commitopts2,
-         _('hg sign [OPTION]... [REV]...'))
+         _('hg sign [OPTION]... [REV]...'),
+         helpcategory=_HELP_CATEGORY)
 def sign(ui, repo, *revs, **opts):
     """add a signature for the current or given revision
 
@@ -327,3 +332,10 @@
         return "%s\n" % hgnode.hex(node)
     else:
         raise error.Abort(_("unknown signature version"))
+
+def extsetup(ui):
+    # Add our category before "Repository maintenance".
+    help.CATEGORY_ORDER.insert(
+        help.CATEGORY_ORDER.index(command.CATEGORY_MAINTENANCE),
+        _HELP_CATEGORY)
+    help.CATEGORY_NAMES[_HELP_CATEGORY] = 'GPG signing'
--- a/hgext/graphlog.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/graphlog.py	Sat Oct 13 02:17:41 2018 -0700
@@ -54,6 +54,7 @@
      _('do not display revision or any of its ancestors'), _('REV')),
     ] + cmdutil.logopts + cmdutil.walkopts,
     _('[OPTION]... [FILE]'),
+    helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
     inferrepo=True)
 def glog(ui, repo, *pats, **opts):
     """show revision history alongside an ASCII revision graph
--- a/hgext/hgk.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/hgk.py	Sat Oct 13 02:17:41 2018 -0700
@@ -345,7 +345,8 @@
 @command('view',
     [('l', 'limit', '',
      _('limit number of changes displayed'), _('NUM'))],
-    _('[-l LIMIT] [REVRANGE]'))
+    _('[-l LIMIT] [REVRANGE]'),
+    helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
 def view(ui, repo, *etc, **opts):
     "start interactive history viewer"
     opts = pycompat.byteskwargs(opts)
--- a/hgext/histedit.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/histedit.py	Sat Oct 13 02:17:41 2018 -0700
@@ -929,7 +929,8 @@
       _('force outgoing even for unrelated repositories')),
      ('r', 'rev', [], _('first revision to be edited'), _('REV'))] +
     cmdutil.formatteropts,
-     _("[OPTIONS] ([ANCESTOR] | --outgoing [URL])"))
+     _("[OPTIONS] ([ANCESTOR] | --outgoing [URL])"),
+    helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
 def histedit(ui, repo, *freeargs, **opts):
     """interactively edit changeset history
 
--- a/hgext/journal.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/journal.py	Sat Oct 13 02:17:41 2018 -0700
@@ -440,7 +440,8 @@
         ('', 'all', None, 'show history for all names'),
         ('c', 'commits', None, 'show commit metadata'),
     ] + [opt for opt in cmdutil.logopts if opt[1] not in _ignoreopts],
-    '[OPTION]... [BOOKMARKNAME]')
+    '[OPTION]... [BOOKMARKNAME]',
+    helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def journal(ui, repo, *args, **opts):
     """show the previous position of bookmarks and the working copy
 
--- a/hgext/mq.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/mq.py	Sat Oct 13 02:17:41 2018 -0700
@@ -2266,7 +2266,8 @@
          [('k', 'keep', None, _('keep patch file')),
           ('r', 'rev', [],
            _('stop managing a revision (DEPRECATED)'), _('REV'))],
-         _('hg qdelete [-k] [PATCH]...'))
+         _('hg qdelete [-k] [PATCH]...'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def delete(ui, repo, *patches, **opts):
     """remove patches from queue
 
@@ -2284,7 +2285,8 @@
 @command("qapplied",
          [('1', 'last', None, _('show only the preceding applied patch'))
           ] + seriesopts,
-         _('hg qapplied [-1] [-s] [PATCH]'))
+         _('hg qapplied [-1] [-s] [PATCH]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def applied(ui, repo, patch=None, **opts):
     """print the patches already applied
 
@@ -2318,7 +2320,8 @@
 
 @command("qunapplied",
          [('1', 'first', None, _('show only the first patch'))] + seriesopts,
-         _('hg qunapplied [-1] [-s] [PATCH]'))
+         _('hg qunapplied [-1] [-s] [PATCH]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def unapplied(ui, repo, patch=None, **opts):
     """print the patches not yet applied
 
@@ -2353,7 +2356,8 @@
            _('place existing revisions under mq control'), _('REV')),
           ('g', 'git', None, _('use git extended diff format')),
           ('P', 'push', None, _('qpush after importing'))],
-         _('hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... [FILE]...'))
+         _('hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... [FILE]...'),
+         helpcategory=command.CATEGORY_IMPORT_EXPORT)
 def qimport(ui, repo, *filename, **opts):
     """import a patch or existing changeset
 
@@ -2431,7 +2435,8 @@
 
 @command("^qinit",
          [('c', 'create-repo', None, _('create queue repository'))],
-         _('hg qinit [-c]'))
+         _('hg qinit [-c]'),
+         helpcategory=command.CATEGORY_REPO_CREATION)
 def init(ui, repo, **opts):
     """init a new queue repository (DEPRECATED)
 
@@ -2455,6 +2460,7 @@
            _('location of source patch repository'), _('REPO')),
          ] + cmdutil.remoteopts,
          _('hg qclone [OPTION]... SOURCE [DEST]'),
+         helpcategory=command.CATEGORY_REPO_CREATION,
          norepo=True)
 def clone(ui, source, dest=None, **opts):
     '''clone main and patch repository at same time
@@ -2536,6 +2542,7 @@
 @command("qcommit|qci",
          commands.table["^commit|ci"][1],
          _('hg qcommit [OPTION]... [FILE]...'),
+         helpcategory=command.CATEGORY_COMMITTING,
          inferrepo=True)
 def commit(ui, repo, *pats, **opts):
     """commit changes in the queue repository (DEPRECATED)
@@ -2550,7 +2557,8 @@
 @command("qseries",
          [('m', 'missing', None, _('print patches not in series')),
          ] + seriesopts,
-          _('hg qseries [-ms]'))
+          _('hg qseries [-ms]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def series(ui, repo, **opts):
     """print the entire series file
 
@@ -2559,7 +2567,8 @@
                     summary=opts.get(r'summary'))
     return 0
 
-@command("qtop", seriesopts, _('hg qtop [-s]'))
+@command("qtop", seriesopts, _('hg qtop [-s]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def top(ui, repo, **opts):
     """print the name of the current patch
 
@@ -2577,7 +2586,8 @@
         ui.write(_("no patches applied\n"))
         return 1
 
-@command("qnext", seriesopts, _('hg qnext [-s]'))
+@command("qnext", seriesopts, _('hg qnext [-s]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def next(ui, repo, **opts):
     """print the name of the next pushable patch
 
@@ -2589,7 +2599,8 @@
         return 1
     q.qseries(repo, start=end, length=1, summary=opts.get(r'summary'))
 
-@command("qprev", seriesopts, _('hg qprev [-s]'))
+@command("qprev", seriesopts, _('hg qprev [-s]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def prev(ui, repo, **opts):
     """print the name of the preceding applied patch
 
@@ -2624,6 +2635,7 @@
            _('add "Date: <DATE>" to patch'), _('DATE'))
           ] + cmdutil.walkopts + cmdutil.commitopts,
          _('hg qnew [-e] [-m TEXT] [-l FILE] PATCH [FILE]...'),
+         helpcategory=command.CATEGORY_COMMITTING,
          inferrepo=True)
 def new(ui, repo, patch, *args, **opts):
     """create a new patch
@@ -2674,6 +2686,7 @@
            _('add/update date field in patch with given date'), _('DATE'))
           ] + cmdutil.walkopts + cmdutil.commitopts,
          _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'),
+         helpcategory=command.CATEGORY_COMMITTING,
          inferrepo=True)
 def refresh(ui, repo, *pats, **opts):
     """update the current patch
@@ -2708,6 +2721,7 @@
 @command("^qdiff",
          cmdutil.diffopts + cmdutil.diffopts2 + cmdutil.walkopts,
          _('hg qdiff [OPTION]... [FILE]...'),
+         helpcategory=command.CATEGORY_FILE_CONTENTS,
          inferrepo=True)
 def diff(ui, repo, *pats, **opts):
     """diff of the current patch and subsequent modifications
@@ -2732,7 +2746,8 @@
          [('e', 'edit', None, _('invoke editor on commit messages')),
           ('k', 'keep', None, _('keep folded patch files')),
          ] + cmdutil.commitopts,
-         _('hg qfold [-e] [-k] [-m TEXT] [-l FILE] PATCH...'))
+         _('hg qfold [-e] [-k] [-m TEXT] [-l FILE] PATCH...'),
+         helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
 def fold(ui, repo, *files, **opts):
     """fold the named patches into the current patch
 
@@ -2801,7 +2816,8 @@
            _('tolerate non-conflicting local changes')),
           ('f', 'force', None, _('overwrite any local changes')),
           ('', 'no-backup', None, _('do not save backup copies of files'))],
-         _('hg qgoto [OPTION]... PATCH'))
+         _('hg qgoto [OPTION]... PATCH'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def goto(ui, repo, patch, **opts):
     '''push or pop patches until named patch is at top of stack
 
@@ -2824,7 +2840,8 @@
 @command("qguard",
          [('l', 'list', None, _('list all patches and guards')),
           ('n', 'none', None, _('drop all guards'))],
-         _('hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]'))
+         _('hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def guard(ui, repo, *args, **opts):
     '''set or print guards for a patch
 
@@ -2896,7 +2913,8 @@
     else:
         status(q.series.index(q.lookup(patch)))
 
-@command("qheader", [], _('hg qheader [PATCH]'))
+@command("qheader", [], _('hg qheader [PATCH]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def header(ui, repo, patch=None):
     """print the header of the topmost or specified patch
 
@@ -2952,7 +2970,8 @@
           ('', 'move', None,
            _('reorder patch series and apply only the patch')),
           ('', 'no-backup', None, _('do not save backup copies of files'))],
-         _('hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]'))
+         _('hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def push(ui, repo, patch=None, **opts):
     """push the next patch onto the stack
 
@@ -2992,7 +3011,8 @@
            _('tolerate non-conflicting local changes')),
           ('f', 'force', None, _('forget any local changes to patched files')),
           ('', 'no-backup', None, _('do not save backup copies of files'))],
-         _('hg qpop [-a] [-f] [PATCH | INDEX]'))
+         _('hg qpop [-a] [-f] [PATCH | INDEX]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def pop(ui, repo, patch=None, **opts):
     """pop the current patch off the stack
 
@@ -3022,7 +3042,8 @@
     q.savedirty()
     return ret
 
-@command("qrename|qmv", [], _('hg qrename PATCH1 [PATCH2]'))
+@command("qrename|qmv", [], _('hg qrename PATCH1 [PATCH2]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def rename(ui, repo, patch, name=None, **opts):
     """rename a patch
 
@@ -3080,7 +3101,8 @@
 @command("qrestore",
          [('d', 'delete', None, _('delete save entry')),
           ('u', 'update', None, _('update queue working directory'))],
-         _('hg qrestore [-d] [-u] REV'))
+         _('hg qrestore [-d] [-u] REV'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def restore(ui, repo, rev, **opts):
     """restore the queue state saved by a revision (DEPRECATED)
 
@@ -3098,7 +3120,8 @@
            _('copy directory name'), _('NAME')),
           ('e', 'empty', None, _('clear queue status file')),
           ('f', 'force', None, _('force copy'))] + cmdutil.commitopts,
-         _('hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'))
+         _('hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def save(ui, repo, **opts):
     """save current queue state (DEPRECATED)
 
@@ -3137,7 +3160,8 @@
           ('s', 'series', None, _('list all guards in series file')),
           ('', 'pop', None, _('pop to before first guarded applied patch')),
           ('', 'reapply', None, _('pop, then reapply patches'))],
-         _('hg qselect [OPTION]... [GUARD]...'))
+         _('hg qselect [OPTION]... [GUARD]...'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def select(ui, repo, *args, **opts):
     '''set or print guarded patches to push
 
@@ -3246,7 +3270,8 @@
 
 @command("qfinish",
          [('a', 'applied', None, _('finish all applied changesets'))],
-         _('hg qfinish [-a] [REV]...'))
+         _('hg qfinish [-a] [REV]...'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def finish(ui, repo, *revrange, **opts):
     """move applied patches into repository history
 
@@ -3294,7 +3319,8 @@
           ('', 'delete', False, _('delete reference to queue')),
           ('', 'purge', False, _('delete queue, and remove patch dir')),
          ],
-         _('[OPTION] [QUEUE]'))
+         _('[OPTION] [QUEUE]'),
+         helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def qqueue(ui, repo, name=None, **opts):
     '''manage multiple patch queues
 
--- a/hgext/patchbomb.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/patchbomb.py	Sat Oct 13 02:17:41 2018 -0700
@@ -509,7 +509,8 @@
        '(with -b/--bundle)'), _('REV')),
     ('', 'intro', None, _('send an introduction email for a single patch')),
     ] + emailopts + cmdutil.remoteopts,
-    _('hg email [OPTION]... [DEST]...'))
+    _('hg email [OPTION]... [DEST]...'),
+    helpcategory=command.CATEGORY_IMPORT_EXPORT)
 def email(ui, repo, *revs, **opts):
     '''send changesets by email
 
--- a/hgext/purge.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/purge.py	Sat Oct 13 02:17:41 2018 -0700
@@ -51,7 +51,8 @@
     ('0', 'print0', None, _('end filenames with NUL, for use with xargs'
                             ' (implies -p/--print)')),
     ] + cmdutil.walkopts,
-    _('hg purge [OPTION]... [DIR]...'))
+    _('hg purge [OPTION]... [DIR]...'),
+    helpcategory=command.CATEGORY_MAINTENANCE)
 def purge(ui, repo, *dirs, **opts):
     '''removes files not tracked by Mercurial
 
--- a/hgext/rebase.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/rebase.py	Sat Oct 13 02:17:41 2018 -0700
@@ -679,7 +679,8 @@
     ('', 'auto-orphans', '', _('automatically rebase orphan revisions '
                                'in the specified revset (EXPERIMENTAL)')),
      ] + cmdutil.dryrunopts + cmdutil.formatteropts + cmdutil.confirmopts,
-    _('[-s REV | -b REV] [-d REV] [OPTION]'))
+    _('[-s REV | -b REV] [-d REV] [OPTION]'),
+    helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
 def rebase(ui, repo, **opts):
     """move changeset (and descendants) to a different branch
 
--- a/hgext/record.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/record.py	Sat Oct 13 02:17:41 2018 -0700
@@ -34,7 +34,8 @@
          # same options as commit + white space diff options
         [c for c in commands.table['^commit|ci'][1][:]
             if c[1] != "interactive"] + cmdutil.diffwsopts,
-          _('hg record [OPTION]... [FILE]...'))
+          _('hg record [OPTION]... [FILE]...'),
+        helpcategory=command.CATEGORY_COMMITTING)
 def record(ui, repo, *pats, **opts):
     '''interactively select changes to commit
 
@@ -94,6 +95,7 @@
 @command('qrecord',
     [],
     _('hg qrecord [OPTION]... PATCH [FILE]...'),
+    helpcategory=command.CATEGORY_COMMITTING,
     inferrepo=True)
 def qrecord(ui, repo, patch, *pats, **opts):
     '''interactively record a new patch
--- a/hgext/releasenotes.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/releasenotes.py	Sat Oct 13 02:17:41 2018 -0700
@@ -492,7 +492,8 @@
         _('REV')),
     ('l', 'list', False, _('list the available admonitions with their title'),
         None)],
-    _('hg releasenotes [-r REV] [-c] FILE'))
+    _('hg releasenotes [-r REV] [-c] FILE'),
+    helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
 def releasenotes(ui, repo, file_=None, **opts):
     """parse release notes from commit messages into an output file
 
--- a/hgext/relink.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/relink.py	Sat Oct 13 02:17:41 2018 -0700
@@ -30,7 +30,7 @@
 # leave the attribute unspecified.
 testedwith = 'ships-with-hg-core'
 
-@command('relink', [], _('[ORIGIN]'))
+@command('relink', [], _('[ORIGIN]'), helpcategory=command.CATEGORY_MAINTENANCE)
 def relink(ui, repo, origin=None, **opts):
     """recreate hardlinks between two repositories
 
--- a/hgext/share.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/share.py	Sat Oct 13 02:17:41 2018 -0700
@@ -67,6 +67,7 @@
                               '(EXPERIMENTAL)')),
     ],
     _('[-U] [-B] SOURCE [DEST]'),
+    helpcategory=command.CATEGORY_REPO_CREATION,
     norepo=True)
 def share(ui, source, dest=None, noupdate=False, bookmarks=False,
           relative=False):
@@ -91,7 +92,7 @@
              bookmarks=bookmarks, relative=relative)
     return 0
 
-@command('unshare', [], '')
+@command('unshare', [], '', helpcategory=command.CATEGORY_MAINTENANCE)
 def unshare(ui, repo):
     """convert a shared repository to a normal one
 
--- a/hgext/shelve.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/shelve.py	Sat Oct 13 02:17:41 2018 -0700
@@ -903,7 +903,8 @@
           ('t', 'tool', '', _('specify merge tool')),
           ('', 'date', '',
            _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
-         _('hg unshelve [[-n] SHELVED]'))
+         _('hg unshelve [[-n] SHELVED]'),
+         helpcategory=command.CATEGORY_WORKING_DIRECTORY)
 def unshelve(ui, repo, *shelved, **opts):
     """restore a shelved change to the working directory
 
@@ -1073,7 +1074,8 @@
            _('output diffstat-style summary of changes (provide the names of '
              'the shelved changes as positional arguments)')
            )] + cmdutil.walkopts,
-         _('hg shelve [OPTION]... [FILE]...'))
+         _('hg shelve [OPTION]... [FILE]...'),
+         helpcategory=command.CATEGORY_WORKING_DIRECTORY)
 def shelvecmd(ui, repo, *pats, **opts):
     '''save and set aside changes from the working directory
 
--- a/hgext/show.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/show.py	Sat Oct 13 02:17:41 2018 -0700
@@ -93,7 +93,8 @@
     # is an important part of the 'hg show' user experience and the entire
     # 'hg show' experience is experimental.
     ('T', 'template', '', ('display with template'), _('TEMPLATE')),
-    ], _('VIEW'))
+    ], _('VIEW'),
+    helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
 def show(ui, repo, view=None, template=None):
     """show various repository information
 
--- a/hgext/split.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/split.py	Sat Oct 13 02:17:41 2018 -0700
@@ -48,7 +48,8 @@
     [('r', 'rev', '', _("revision to split"), _('REV')),
      ('', 'rebase', True, _('rebase descendants after split')),
     ] + cmdutil.commitopts2,
-    _('hg split [--no-rebase] [[-r] REV]'))
+    _('hg split [--no-rebase] [[-r] REV]'),
+    helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
 def split(ui, repo, *revs, **opts):
     """split a changeset into smaller ones
 
--- a/hgext/strip.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/strip.py	Sat Oct 13 02:17:41 2018 -0700
@@ -111,7 +111,8 @@
                                 "strip")),
           ('B', 'bookmark', [], _("remove revs only reachable from given"
                                   " bookmark"))],
-          _('hg strip [-k] [-f] [-B bookmark] [-r] REV...'))
+          _('hg strip [-k] [-f] [-B bookmark] [-r] REV...'),
+          helpcategory=command.CATEGORY_MAINTENANCE)
 def stripcmd(ui, repo, *revs, **opts):
     """strip changesets and all their descendants from the repository
 
--- a/hgext/transplant.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/transplant.py	Sat Oct 13 02:17:41 2018 -0700
@@ -562,7 +562,8 @@
     ('', 'filter', '',
      _('filter changesets through command'), _('CMD'))],
     _('hg transplant [-s REPO] [-b BRANCH [-a]] [-p REV] '
-      '[-m REV] [REV]...'))
+      '[-m REV] [REV]...'),
+    helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
 def transplant(ui, repo, *revs, **opts):
     '''transplant changesets from another branch
 
--- a/hgext/uncommit.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/hgext/uncommit.py	Sat Oct 13 02:17:41 2018 -0700
@@ -138,7 +138,8 @@
 @command('uncommit',
     [('', 'keep', False, _('allow an empty commit after uncommiting')),
     ] + commands.walkopts,
-    _('[OPTION]... [FILE]...'))
+    _('[OPTION]... [FILE]...'),
+    helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
 def uncommit(ui, repo, *pats, **opts):
     """uncommit part or all of a local changeset
 
@@ -190,7 +191,7 @@
     for data in ctx.repo().obsstore.predecessors.get(ctx.node(), ()):
         yield obsutil.marker(ctx.repo(), data)
 
-@command('^unamend', [])
+@command('^unamend', [], helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
 def unamend(ui, repo, **opts):
     """undo the most recent amend operation on a current changeset
 
--- a/mercurial/commands.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/mercurial/commands.py	Sat Oct 13 02:17:41 2018 -0700
@@ -134,6 +134,7 @@
 @command('^add',
     walkopts + subrepoopts + dryrunopts,
     _('[OPTION]... [FILE]...'),
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY,
     inferrepo=True)
 def add(ui, repo, *pats, **opts):
     """add the specified files on the next commit
@@ -185,6 +186,7 @@
 @command('addremove',
     similarityopts + subrepoopts + walkopts + dryrunopts,
     _('[OPTION]... [FILE]...'),
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY,
     inferrepo=True)
 def addremove(ui, repo, *pats, **opts):
     """add all new files, delete all missing files
@@ -269,6 +271,7 @@
     ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
     ] + diffwsopts + walkopts + formatteropts,
     _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
+    helpcategory=command.CATEGORY_FILE_CONTENTS,
     inferrepo=True)
 def annotate(ui, repo, *pats, **opts):
     """show changeset information by line for each file
@@ -451,7 +454,8 @@
     ('r', 'rev', '', _('revision to distribute'), _('REV')),
     ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
     ] + subrepoopts + walkopts,
-    _('[OPTION]... DEST'))
+    _('[OPTION]... DEST'),
+    helpcategory=command.CATEGORY_IMPORT_EXPORT)
 def archive(ui, repo, dest, **opts):
     '''create an unversioned archive of a repository revision
 
@@ -530,7 +534,8 @@
     ('r', 'rev', '', _('revision to backout'), _('REV')),
     ('e', 'edit', False, _('invoke editor on commit messages')),
     ] + mergetoolopts + walkopts + commitopts + commitopts2,
-    _('[OPTION]... [-r] REV'))
+    _('[OPTION]... [-r] REV'),
+    helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
 def backout(ui, repo, node=None, rev=None, **opts):
     '''reverse effect of earlier changeset
 
@@ -693,7 +698,8 @@
     ('e', 'extend', False, _('extend the bisect range')),
     ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
     ('U', 'noupdate', False, _('do not update to target'))],
-    _("[-gbsr] [-U] [-c CMD] [REV]"))
+    _("[-gbsr] [-U] [-c CMD] [REV]"),
+    helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
 def bisect(ui, repo, rev=None, extra=None, command=None,
                reset=None, good=None, bad=None, skip=None, extend=None,
                noupdate=None):
@@ -926,7 +932,8 @@
     ('i', 'inactive', False, _('mark a bookmark inactive')),
     ('l', 'list', False, _('list existing bookmarks')),
     ] + formatteropts,
-    _('hg bookmarks [OPTIONS]... [NAME]...'))
+    _('hg bookmarks [OPTIONS]... [NAME]...'),
+    helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def bookmark(ui, repo, *names, **opts):
     '''create a new bookmark or list existing bookmarks
 
@@ -1046,7 +1053,8 @@
      ('C', 'clean', None, _('reset branch name to parent branch name')),
      ('r', 'rev', [], _('change branches of the given revs (EXPERIMENTAL)')),
     ],
-    _('[-fC] [NAME]'))
+    _('[-fC] [NAME]'),
+    helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def branch(ui, repo, label=None, **opts):
     """set or show the current branch name
 
@@ -1121,6 +1129,7 @@
      ('c', 'closed', False, _('show normal and closed branches')),
     ] + formatteropts,
     _('[-c]'),
+    helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
     intents={INTENT_READONLY})
 def branches(ui, repo, active=False, closed=False, **opts):
     """list repository named branches
@@ -1206,7 +1215,8 @@
     ('a', 'all', None, _('bundle all changesets in the repository')),
     ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
     ] + remoteopts,
-    _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
+    _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'),
+    helpcategory=command.CATEGORY_IMPORT_EXPORT)
 def bundle(ui, repo, fname, dest=None, **opts):
     """create a bundle file
 
@@ -1333,6 +1343,7 @@
     ('', 'decode', None, _('apply any matching decode filter')),
     ] + walkopts + formatteropts,
     _('[OPTION]... FILE...'),
+    helpcategory=command.CATEGORY_FILE_CONTENTS,
     inferrepo=True,
     intents={INTENT_READONLY})
 def cat(ui, repo, file1, *pats, **opts):
@@ -1404,6 +1415,7 @@
        _('clone with minimal data processing')),
     ] + remoteopts,
     _('[OPTION]... SOURCE [DEST]'),
+    helpcategory=command.CATEGORY_REPO_CREATION,
     norepo=True)
 def clone(ui, source, dest=None, **opts):
     """make a copy of an existing repository
@@ -1554,6 +1566,7 @@
     ('i', 'interactive', None, _('use interactive mode')),
     ] + walkopts + commitopts + commitopts2 + subrepoopts,
     _('[OPTION]... [FILE]...'),
+    helpcategory=command.CATEGORY_COMMITTING,
     inferrepo=True)
 def commit(ui, repo, *pats, **opts):
     """commit the specified files or all outstanding changes
@@ -1706,6 +1719,7 @@
      ('l', 'local', None, _('edit repository config')),
      ('g', 'global', None, _('edit global config'))] + formatteropts,
     _('[-u] [NAME]...'),
+    helpcategory=command.CATEGORY_HELP,
     optionalrepo=True,
     intents={INTENT_READONLY})
 def config(ui, repo, *values, **opts):
@@ -1824,7 +1838,8 @@
     [('A', 'after', None, _('record a copy that has already occurred')),
     ('f', 'force', None, _('forcibly copy over an existing managed file')),
     ] + walkopts + dryrunopts,
-    _('[OPTION]... [SOURCE]... DEST'))
+    _('[OPTION]... [SOURCE]... DEST'),
+    helpcategory=command.CATEGORY_FILE_CONTENTS)
 def copy(ui, repo, *pats, **opts):
     """mark files as copied for the next commit
 
@@ -1845,7 +1860,10 @@
     with repo.wlock(False):
         return cmdutil.copy(ui, repo, pats, opts)
 
-@command('debugcommands', [], _('[COMMAND]'), norepo=True)
+@command(
+    'debugcommands', [], _('[COMMAND]'),
+    helpcategory=command.CATEGORY_HELP,
+    norepo=True)
 def debugcommands(ui, cmd='', *args):
     """list all available commands and options"""
     for cmd, vals in sorted(table.iteritems()):
@@ -1856,6 +1874,7 @@
 @command('debugcomplete',
     [('o', 'options', None, _('show the command options'))],
     _('[-o] CMD'),
+    helpcategory=command.CATEGORY_HELP,
     norepo=True)
 def debugcomplete(ui, cmd='', **opts):
     """returns the completion list associated with the given command"""
@@ -1886,6 +1905,7 @@
     ('c', 'change', '', _('change made by revision'), _('REV'))
     ] + diffopts + diffopts2 + walkopts + subrepoopts,
     _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
+    helpcategory=command.CATEGORY_FILE_CONTENTS,
     inferrepo=True,
     intents={INTENT_READONLY})
 def diff(ui, repo, *pats, **opts):
@@ -1984,6 +2004,7 @@
     ('r', 'rev', [], _('revisions to export'), _('REV')),
     ] + diffopts + formatteropts,
     _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
+    helpcategory=command.CATEGORY_IMPORT_EXPORT,
     intents={INTENT_READONLY})
 def export(ui, repo, *changesets, **opts):
     """dump the header and diffs for one or more changesets
@@ -2104,6 +2125,7 @@
      ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
     ] + walkopts + formatteropts + subrepoopts,
     _('[OPTION]... [FILE]...'),
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY,
     intents={INTENT_READONLY})
 def files(ui, repo, *pats, **opts):
     """list tracked files
@@ -2179,7 +2201,9 @@
     '^forget',
     [('i', 'interactive', None, _('use interactive mode')),
     ] + walkopts + dryrunopts,
-    _('[OPTION]... FILE...'), inferrepo=True)
+    _('[OPTION]... FILE...'),
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY,
+    inferrepo=True)
 def forget(ui, repo, *pats, **opts):
     """forget the specified files on the next commit
 
@@ -2236,7 +2260,8 @@
      ('U', 'currentuser', False,
       _('record the current user as committer'), _('DATE'))]
     + commitopts2 + mergetoolopts  + dryrunopts,
-    _('[OPTION]... [-r REV]... REV...'))
+    _('[OPTION]... [-r REV]... REV...'),
+    helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
 def graft(ui, repo, *revs, **opts):
     '''copy changes from other branches onto the current branch
 
@@ -2624,6 +2649,7 @@
     ('d', 'date', None, _('list the date (short with -q)')),
     ] + formatteropts + walkopts,
     _('[OPTION]... PATTERN [FILE]...'),
+    helpcategory=command.CATEGORY_FILE_CONTENTS,
     inferrepo=True,
     intents={INTENT_READONLY})
 def grep(ui, repo, pattern, *pats, **opts):
@@ -2917,6 +2943,7 @@
     ('c', 'closed', False, _('show normal and closed branch heads')),
     ] + templateopts,
     _('[-ct] [-r STARTREV] [REV]...'),
+    helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
     intents={INTENT_READONLY})
 def heads(ui, repo, *branchrevs, **opts):
     """show branch heads
@@ -2993,6 +3020,7 @@
      ('s', 'system', [], _('show help for specific platform(s)')),
      ],
     _('[-ecks] [TOPIC]'),
+    helpcategory=command.CATEGORY_HELP,
     norepo=True,
     intents={INTENT_READONLY})
 def help_(ui, name=None, **opts):
@@ -3036,6 +3064,7 @@
     ('B', 'bookmarks', None, _('show bookmarks')),
     ] + remoteopts + formatteropts,
     _('[-nibtB] [-r REV] [SOURCE]'),
+    helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
     optionalrepo=True,
     intents={INTENT_READONLY})
 def identify(ui, repo, source=None, rev=None,
@@ -3234,7 +3263,8 @@
     ('', 'import-branch', None,
      _('use any branch information in patch (implied by --exact)'))] +
     commitopts + commitopts2 + similarityopts,
-    _('[OPTION]... PATCH...'))
+    _('[OPTION]... PATCH...'),
+    helpcategory=command.CATEGORY_IMPORT_EXPORT)
 def import_(ui, repo, patch1=None, *patches, **opts):
     """import an ordered set of patches
 
@@ -3431,7 +3461,8 @@
     ('b', 'branch', [],
      _('a specific branch you would like to pull'), _('BRANCH')),
     ] + logopts + remoteopts + subrepoopts,
-    _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
+    _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'),
+    helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
 def incoming(ui, repo, source="default", **opts):
     """show new changesets found in source
 
@@ -3519,6 +3550,7 @@
 
 
 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
+        helpcategory=command.CATEGORY_REPO_CREATION,
          norepo=True)
 def init(ui, dest=".", **opts):
     """create a new repository in the given directory
@@ -3541,7 +3573,8 @@
     ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
     ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
     ] + walkopts,
-    _('[OPTION]... [PATTERN]...'))
+    _('[OPTION]... [PATTERN]...'),
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY)
 def locate(ui, repo, *pats, **opts):
     """locate files matching specific patterns (DEPRECATED)
 
@@ -3616,6 +3649,7 @@
      _('do not display revision or any of its ancestors'), _('REV')),
     ] + logopts + walkopts,
     _('[OPTION]... [FILE]'),
+    helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
     inferrepo=True,
     intents={INTENT_READONLY})
 def log(ui, repo, *pats, **opts):
@@ -3786,6 +3820,7 @@
      ('', 'all', False, _("list files from all revisions"))]
          + formatteropts,
     _('[-r REV]'),
+    helpcategory=command.CATEGORY_MAINTENANCE,
     intents={INTENT_READONLY})
 def manifest(ui, repo, node=None, rev=None, **opts):
     """output the current or given revision of the project manifest
@@ -3851,7 +3886,8 @@
      _('review revisions to merge (no merge is performed)')),
     ('', 'abort', None, _('abort the ongoing merge')),
      ] + mergetoolopts,
-    _('[-P] [[-r] REV]'))
+    _('[-P] [[-r] REV]'),
+    helpcategory=command.CATEGORY_CHANGE_MANAGEMENT)
 def merge(ui, repo, node=None, **opts):
     """merge another revision into working directory
 
@@ -3932,7 +3968,8 @@
     ('b', 'branch', [], _('a specific branch you would like to push'),
      _('BRANCH')),
     ] + logopts + remoteopts + subrepoopts,
-    _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
+    _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'),
+    helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
 def outgoing(ui, repo, dest=None, **opts):
     """show changesets not found in the destination
 
@@ -4012,6 +4049,7 @@
     [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
     ] + templateopts,
     _('[-r REV] [FILE]'),
+    helpcategory=command.CATEGORY_CHANGE_NAVIGATION,
     inferrepo=True)
 def parents(ui, repo, file_=None, **opts):
     """show the parents of the working directory or revision (DEPRECATED)
@@ -4068,8 +4106,9 @@
             displayer.show(repo[n])
     displayer.close()
 
-@command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
-    intents={INTENT_READONLY})
+@command('paths', formatteropts, _('[NAME]'),
+    helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
+    optionalrepo=True, intents={INTENT_READONLY})
 def paths(ui, repo, search=None, **opts):
     """show aliases for remote repositories
 
@@ -4157,7 +4196,8 @@
      ('f', 'force', False, _('allow to move boundary backward')),
      ('r', 'rev', [], _('target revision'), _('REV')),
     ],
-    _('[-p|-d|-s] [-f] [-r] [REV...]'))
+    _('[-p|-d|-s] [-f] [-r] [REV...]'),
+    helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def phase(ui, repo, *revs, **opts):
     """set or show the current phase name
 
@@ -4274,7 +4314,8 @@
     ('b', 'branch', [], _('a specific branch you would like to pull'),
      _('BRANCH')),
     ] + remoteopts,
-    _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
+    _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'),
+    helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
 def pull(ui, repo, source="default", **opts):
     """pull changes from the specified source
 
@@ -4405,7 +4446,8 @@
     ('', 'new-branch', False, _('allow pushing a new branch')),
     ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
     ] + remoteopts,
-    _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
+    _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'),
+    helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT)
 def push(ui, repo, dest=None, **opts):
     """push changes to the specified destination
 
@@ -4531,7 +4573,7 @@
 
     return result
 
-@command('recover', [])
+@command('recover', [], helpcategory=command.CATEGORY_MAINTENANCE)
 def recover(ui, repo):
     """roll back an interrupted transaction
 
@@ -4553,6 +4595,7 @@
      _('forget added files, delete modified files')),
     ] + subrepoopts + walkopts + dryrunopts,
     _('[OPTION]... FILE...'),
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY,
     inferrepo=True)
 def remove(ui, repo, *pats, **opts):
     """remove the specified files on the next commit
@@ -4608,7 +4651,8 @@
     [('A', 'after', None, _('record a rename that has already occurred')),
     ('f', 'force', None, _('forcibly copy over an existing managed file')),
     ] + walkopts + dryrunopts,
-    _('[OPTION]... SOURCE... DEST'))
+    _('[OPTION]... SOURCE... DEST'),
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY)
 def rename(ui, repo, *pats, **opts):
     """rename files; equivalent of copy + remove
 
@@ -4638,6 +4682,7 @@
     ('', 're-merge', None, _('re-merge files'))]
     + mergetoolopts + walkopts + formatteropts,
     _('[OPTION]... [FILE]...'),
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY,
     inferrepo=True)
 def resolve(ui, repo, *pats, **opts):
     """redo merges or set/view the merge status of files
@@ -4939,7 +4984,8 @@
     ('C', 'no-backup', None, _('do not save backup copies of files')),
     ('i', 'interactive', None, _('interactively select the changes')),
     ] + walkopts + dryrunopts,
-    _('[OPTION]... [-r REV] [NAME]...'))
+    _('[OPTION]... [-r REV] [NAME]...'),
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY)
 def revert(ui, repo, *pats, **opts):
     """restore files to their checkout state
 
@@ -5019,8 +5065,10 @@
     return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
                           **pycompat.strkwargs(opts))
 
-@command('rollback', dryrunopts +
-         [('f', 'force', False, _('ignore safety measures'))])
+@command(
+    'rollback',
+    dryrunopts + [('f', 'force', False, _('ignore safety measures'))],
+    helpcategory=command.CATEGORY_MAINTENANCE)
 def rollback(ui, repo, **opts):
     """roll back the last transaction (DANGEROUS) (DEPRECATED)
 
@@ -5072,7 +5120,9 @@
     return repo.rollback(dryrun=opts.get(r'dry_run'),
                          force=opts.get(r'force'))
 
-@command('root', [], intents={INTENT_READONLY})
+@command(
+    'root', [], intents={INTENT_READONLY},
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY)
 def root(ui, repo):
     """print the root (top) of the current working directory
 
@@ -5110,6 +5160,7 @@
     ('', 'print-url', None, _('start and print only the URL'))]
      + subrepoopts,
     _('[OPTION]...'),
+    helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT,
     optionalrepo=True)
 def serve(ui, repo, **opts):
     """start stand-alone webserver
@@ -5171,6 +5222,7 @@
     ('', 'change', '', _('list the changed files of a revision'), _('REV')),
     ] + walkopts + subrepoopts + formatteropts,
     _('[OPTION]... [FILE]...'),
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY,
     inferrepo=True,
     intents={INTENT_READONLY})
 def status(ui, repo, *pats, **opts):
@@ -5360,6 +5412,7 @@
 @command('^summary|sum',
     [('', 'remote', None, _('check for push and pull'))],
     '[--remote]',
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY,
     intents={INTENT_READONLY})
 def summary(ui, repo, **opts):
     """summarize working directory state
@@ -5650,7 +5703,8 @@
     ('e', 'edit', None, _('invoke editor on commit messages')),
     ('m', 'message', '', _('use text as commit message'), _('TEXT')),
     ] + commitopts2,
-    _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
+    _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'),
+    helpcategory=command.CATEGORY_CHANGE_ORGANIZATION)
 def tag(ui, repo, name1, *names, **opts):
     """add one or more tags for the current or given revision
 
@@ -5756,7 +5810,10 @@
         tagsmod.tag(repo, names, node, message, opts.get('local'),
                     opts.get('user'), date, editor=editor)
 
-@command('tags', formatteropts, '', intents={INTENT_READONLY})
+@command(
+    'tags', formatteropts, '',
+    helpcategory=command.CATEGORY_CHANGE_ORGANIZATION,
+    intents={INTENT_READONLY})
 def tags(ui, repo, **opts):
     """list repository tags
 
@@ -5806,7 +5863,8 @@
     [('p', 'patch', None, _('show patch')),
     ('g', 'git', None, _('use git extended diff format')),
     ] + templateopts,
-    _('[-p] [-g]'))
+    _('[-p] [-g]'),
+    helpcategory=command.CATEGORY_CHANGE_NAVIGATION)
 def tip(ui, repo, **opts):
     """show the tip revision (DEPRECATED)
 
@@ -5831,7 +5889,8 @@
 @command('unbundle',
     [('u', 'update', None,
      _('update to new branch head if changesets were unbundled'))],
-    _('[-u] FILE...'))
+    _('[-u] FILE...'),
+    helpcategory=command.CATEGORY_IMPORT_EXPORT)
 def unbundle(ui, repo, fname1, *fnames, **opts):
     """apply one or more bundle files
 
@@ -5875,7 +5934,8 @@
     ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
     ('r', 'rev', '', _('revision'), _('REV'))
      ] + mergetoolopts,
-    _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
+    _('[-C|-c|-m] [-d DATE] [[-r] REV]'),
+    helpcategory=command.CATEGORY_WORKING_DIRECTORY)
 def update(ui, repo, node=None, **opts):
     """update working directory (or switch revisions)
 
@@ -5986,7 +6046,7 @@
                 ui.warn("(%s)\n" % obsfatemsg)
         return ret
 
-@command('verify', [])
+@command('verify', [], helpcategory=command.CATEGORY_MAINTENANCE)
 def verify(ui, repo):
     """verify the integrity of the repository
 
@@ -6005,8 +6065,9 @@
     """
     return hg.verify(repo)
 
-@command('version', [] + formatteropts, norepo=True,
-         intents={INTENT_READONLY})
+@command(
+    'version', [] + formatteropts, helpcategory=command.CATEGORY_HELP,
+    norepo=True, intents={INTENT_READONLY})
 def version_(ui, **opts):
     """output version and copyright information
 
--- a/mercurial/help.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/mercurial/help.py	Sat Oct 13 02:17:41 2018 -0700
@@ -53,12 +53,38 @@
 # after/before the appropriate item, rather than replacing the list or
 # assuming absolute positions.
 CATEGORY_ORDER = [
+    registrar.command.CATEGORY_REPO_CREATION,
+    registrar.command.CATEGORY_REMOTE_REPO_MANAGEMENT,
+    registrar.command.CATEGORY_COMMITTING,
+    registrar.command.CATEGORY_CHANGE_MANAGEMENT,
+    registrar.command.CATEGORY_CHANGE_ORGANIZATION,
+    registrar.command.CATEGORY_FILE_CONTENTS,
+    registrar.command.CATEGORY_CHANGE_NAVIGATION ,
+    registrar.command.CATEGORY_WORKING_DIRECTORY,
+    registrar.command.CATEGORY_IMPORT_EXPORT,
+    registrar.command.CATEGORY_MAINTENANCE,
+    registrar.command.CATEGORY_HELP,
+    registrar.command.CATEGORY_MISC,
     registrar.command.CATEGORY_NONE,
 ]
 
 # Human-readable category names. These are translated.
 # Extensions with custom categories should add their names here.
 CATEGORY_NAMES = {
+    registrar.command.CATEGORY_REPO_CREATION: 'Repository creation',
+    registrar.command.CATEGORY_REMOTE_REPO_MANAGEMENT:
+        'Remote repository management',
+    registrar.command.CATEGORY_COMMITTING: 'Change creation',
+    registrar.command.CATEGORY_CHANGE_NAVIGATION: 'Change navigation',
+    registrar.command.CATEGORY_CHANGE_MANAGEMENT: 'Change manipulation',
+    registrar.command.CATEGORY_CHANGE_ORGANIZATION: 'Change organization',
+    registrar.command.CATEGORY_WORKING_DIRECTORY:
+        'Working directory management',
+    registrar.command.CATEGORY_FILE_CONTENTS: 'File content management',
+    registrar.command.CATEGORY_IMPORT_EXPORT: 'Change import/export',
+    registrar.command.CATEGORY_MAINTENANCE: 'Repository maintenance',
+    registrar.command.CATEGORY_HELP: 'Help',
+    registrar.command.CATEGORY_MISC: 'Miscellaneous commands',
     registrar.command.CATEGORY_NONE: 'Uncategorized commands',
 }
 
--- a/mercurial/registrar.py	Fri Oct 12 17:57:36 2018 +0200
+++ b/mercurial/registrar.py	Sat Oct 13 02:17:41 2018 -0700
@@ -169,6 +169,18 @@
     """
 
     # Command categories for grouping them in help output.
+    CATEGORY_REPO_CREATION = 'repo'
+    CATEGORY_REMOTE_REPO_MANAGEMENT = 'remote'
+    CATEGORY_COMMITTING = 'commit'
+    CATEGORY_CHANGE_MANAGEMENT = 'management'
+    CATEGORY_CHANGE_ORGANIZATION = 'organization'
+    CATEGORY_FILE_CONTENTS = 'files'
+    CATEGORY_CHANGE_NAVIGATION  = 'navigation'
+    CATEGORY_WORKING_DIRECTORY = 'wdir'
+    CATEGORY_IMPORT_EXPORT = 'import'
+    CATEGORY_MAINTENANCE = 'maintenance'
+    CATEGORY_HELP = 'help'
+    CATEGORY_MISC = 'misc'
     CATEGORY_NONE = 'none'
 
     def _doregister(self, func, name, options=(), synopsis=None,
--- a/tests/test-globalopts.t	Fri Oct 12 17:57:36 2018 +0200
+++ b/tests/test-globalopts.t	Sat Oct 13 02:17:41 2018 -0700
@@ -297,55 +297,87 @@
   
   list of commands:
   
-   add           add the specified files on the next commit
-   addremove     add all new files, delete all missing files
-   annotate      show changeset information by line for each file
-   archive       create an unversioned archive of a repository revision
+  Repository creation:
+  
+   clone         make a copy of an existing repository
+   init          create a new repository in the given directory
+  
+  Remote repository management:
+  
+   incoming      show new changesets found in source
+   outgoing      show changesets not found in the destination
+   paths         show aliases for remote repositories
+   pull          pull changes from the specified source
+   push          push changes to the specified destination
+   serve         start stand-alone webserver
+  
+  Change creation:
+  
+   commit        commit the specified files or all outstanding changes
+  
+  Change manipulation:
+  
    backout       reverse effect of earlier changeset
-   bisect        subdivision search of changesets
+   graft         copy changes from other branches onto the current branch
+   merge         merge another revision into working directory
+  
+  Change organization:
+  
    bookmarks     create a new bookmark or list existing bookmarks
    branch        set or show the current branch name
    branches      list repository named branches
-   bundle        create a bundle file
+   phase         set or show the current phase name
+   tag           add one or more tags for the current or given revision
+   tags          list repository tags
+  
+  File content management:
+  
+   annotate      show changeset information by line for each file
    cat           output the current or given revision of files
-   clone         make a copy of an existing repository
-   commit        commit the specified files or all outstanding changes
-   config        show combined config settings from all hgrc files
    copy          mark files as copied for the next commit
    diff          diff repository (or selected files)
-   export        dump the header and diffs for one or more changesets
+   grep          search revision history for a pattern in specified files
+  
+  Change navigation:
+  
+   bisect        subdivision search of changesets
+   heads         show branch heads
+   identify      identify the working directory or specified revision
+   log           show revision history of entire repository or files
+  
+  Working directory management:
+  
+   add           add the specified files on the next commit
+   addremove     add all new files, delete all missing files
    files         list tracked files
    forget        forget the specified files on the next commit
-   graft         copy changes from other branches onto the current branch
-   grep          search revision history for a pattern in specified files
-   heads         show branch heads
-   help          show help for a given topic or a help overview
-   identify      identify the working directory or specified revision
-   import        import an ordered set of patches
-   incoming      show new changesets found in source
-   init          create a new repository in the given directory
-   log           show revision history of entire repository or files
-   manifest      output the current or given revision of the project manifest
-   merge         merge another revision into working directory
-   outgoing      show changesets not found in the destination
-   paths         show aliases for remote repositories
-   phase         set or show the current phase name
-   pull          pull changes from the specified source
-   push          push changes to the specified destination
-   recover       roll back an interrupted transaction
    remove        remove the specified files on the next commit
    rename        rename files; equivalent of copy + remove
    resolve       redo merges or set/view the merge status of files
    revert        restore files to their checkout state
    root          print the root (top) of the current working directory
-   serve         start stand-alone webserver
    status        show changed files in the working directory
    summary       summarize working directory state
-   tag           add one or more tags for the current or given revision
-   tags          list repository tags
+   update        update working directory (or switch revisions)
+  
+  Change import/export:
+  
+   archive       create an unversioned archive of a repository revision
+   bundle        create a bundle file
+   export        dump the header and diffs for one or more changesets
+   import        import an ordered set of patches
    unbundle      apply one or more bundle files
-   update        update working directory (or switch revisions)
+  
+  Repository maintenance:
+  
+   manifest      output the current or given revision of the project manifest
+   recover       roll back an interrupted transaction
    verify        verify the integrity of the repository
+  
+  Help:
+  
+   config        show combined config settings from all hgrc files
+   help          show help for a given topic or a help overview
    version       output version and copyright information
   
   additional help topics:
@@ -381,55 +413,87 @@
   
   list of commands:
   
-   add           add the specified files on the next commit
-   addremove     add all new files, delete all missing files
-   annotate      show changeset information by line for each file
-   archive       create an unversioned archive of a repository revision
+  Repository creation:
+  
+   clone         make a copy of an existing repository
+   init          create a new repository in the given directory
+  
+  Remote repository management:
+  
+   incoming      show new changesets found in source
+   outgoing      show changesets not found in the destination
+   paths         show aliases for remote repositories
+   pull          pull changes from the specified source
+   push          push changes to the specified destination
+   serve         start stand-alone webserver
+  
+  Change creation:
+  
+   commit        commit the specified files or all outstanding changes
+  
+  Change manipulation:
+  
    backout       reverse effect of earlier changeset
-   bisect        subdivision search of changesets
+   graft         copy changes from other branches onto the current branch
+   merge         merge another revision into working directory
+  
+  Change organization:
+  
    bookmarks     create a new bookmark or list existing bookmarks
    branch        set or show the current branch name
    branches      list repository named branches
-   bundle        create a bundle file
+   phase         set or show the current phase name
+   tag           add one or more tags for the current or given revision
+   tags          list repository tags
+  
+  File content management:
+  
+   annotate      show changeset information by line for each file
    cat           output the current or given revision of files
-   clone         make a copy of an existing repository
-   commit        commit the specified files or all outstanding changes
-   config        show combined config settings from all hgrc files
    copy          mark files as copied for the next commit
    diff          diff repository (or selected files)
-   export        dump the header and diffs for one or more changesets
+   grep          search revision history for a pattern in specified files
+  
+  Change navigation:
+  
+   bisect        subdivision search of changesets
+   heads         show branch heads
+   identify      identify the working directory or specified revision
+   log           show revision history of entire repository or files
+  
+  Working directory management:
+  
+   add           add the specified files on the next commit
+   addremove     add all new files, delete all missing files
    files         list tracked files
    forget        forget the specified files on the next commit
-   graft         copy changes from other branches onto the current branch
-   grep          search revision history for a pattern in specified files
-   heads         show branch heads
-   help          show help for a given topic or a help overview
-   identify      identify the working directory or specified revision
-   import        import an ordered set of patches
-   incoming      show new changesets found in source
-   init          create a new repository in the given directory
-   log           show revision history of entire repository or files
-   manifest      output the current or given revision of the project manifest
-   merge         merge another revision into working directory
-   outgoing      show changesets not found in the destination
-   paths         show aliases for remote repositories
-   phase         set or show the current phase name
-   pull          pull changes from the specified source
-   push          push changes to the specified destination
-   recover       roll back an interrupted transaction
    remove        remove the specified files on the next commit
    rename        rename files; equivalent of copy + remove
    resolve       redo merges or set/view the merge status of files
    revert        restore files to their checkout state
    root          print the root (top) of the current working directory
-   serve         start stand-alone webserver
    status        show changed files in the working directory
    summary       summarize working directory state
-   tag           add one or more tags for the current or given revision
-   tags          list repository tags
+   update        update working directory (or switch revisions)
+  
+  Change import/export:
+  
+   archive       create an unversioned archive of a repository revision
+   bundle        create a bundle file
+   export        dump the header and diffs for one or more changesets
+   import        import an ordered set of patches
    unbundle      apply one or more bundle files
-   update        update working directory (or switch revisions)
+  
+  Repository maintenance:
+  
+   manifest      output the current or given revision of the project manifest
+   recover       roll back an interrupted transaction
    verify        verify the integrity of the repository
+  
+  Help:
+  
+   config        show combined config settings from all hgrc files
+   help          show help for a given topic or a help overview
    version       output version and copyright information
   
   additional help topics:
--- a/tests/test-help.t	Fri Oct 12 17:57:36 2018 +0200
+++ b/tests/test-help.t	Sat Oct 13 02:17:41 2018 -0700
@@ -53,55 +53,87 @@
   
   list of commands:
   
-   add           add the specified files on the next commit
-   addremove     add all new files, delete all missing files
-   annotate      show changeset information by line for each file
-   archive       create an unversioned archive of a repository revision
+  Repository creation:
+  
+   clone         make a copy of an existing repository
+   init          create a new repository in the given directory
+  
+  Remote repository management:
+  
+   incoming      show new changesets found in source
+   outgoing      show changesets not found in the destination
+   paths         show aliases for remote repositories
+   pull          pull changes from the specified source
+   push          push changes to the specified destination
+   serve         start stand-alone webserver
+  
+  Change creation:
+  
+   commit        commit the specified files or all outstanding changes
+  
+  Change manipulation:
+  
    backout       reverse effect of earlier changeset
-   bisect        subdivision search of changesets
+   graft         copy changes from other branches onto the current branch
+   merge         merge another revision into working directory
+  
+  Change organization:
+  
    bookmarks     create a new bookmark or list existing bookmarks
    branch        set or show the current branch name
    branches      list repository named branches
-   bundle        create a bundle file
+   phase         set or show the current phase name
+   tag           add one or more tags for the current or given revision
+   tags          list repository tags
+  
+  File content management:
+  
+   annotate      show changeset information by line for each file
    cat           output the current or given revision of files
-   clone         make a copy of an existing repository
-   commit        commit the specified files or all outstanding changes
-   config        show combined config settings from all hgrc files
    copy          mark files as copied for the next commit
    diff          diff repository (or selected files)
-   export        dump the header and diffs for one or more changesets
+   grep          search revision history for a pattern in specified files
+  
+  Change navigation:
+  
+   bisect        subdivision search of changesets
+   heads         show branch heads
+   identify      identify the working directory or specified revision
+   log           show revision history of entire repository or files
+  
+  Working directory management:
+  
+   add           add the specified files on the next commit
+   addremove     add all new files, delete all missing files
    files         list tracked files
    forget        forget the specified files on the next commit
-   graft         copy changes from other branches onto the current branch
-   grep          search revision history for a pattern in specified files
-   heads         show branch heads
-   help          show help for a given topic or a help overview
-   identify      identify the working directory or specified revision
-   import        import an ordered set of patches
-   incoming      show new changesets found in source
-   init          create a new repository in the given directory
-   log           show revision history of entire repository or files
-   manifest      output the current or given revision of the project manifest
-   merge         merge another revision into working directory
-   outgoing      show changesets not found in the destination
-   paths         show aliases for remote repositories
-   phase         set or show the current phase name
-   pull          pull changes from the specified source
-   push          push changes to the specified destination
-   recover       roll back an interrupted transaction
    remove        remove the specified files on the next commit
    rename        rename files; equivalent of copy + remove
    resolve       redo merges or set/view the merge status of files
    revert        restore files to their checkout state
    root          print the root (top) of the current working directory
-   serve         start stand-alone webserver
    status        show changed files in the working directory
    summary       summarize working directory state
-   tag           add one or more tags for the current or given revision
-   tags          list repository tags
+   update        update working directory (or switch revisions)
+  
+  Change import/export:
+  
+   archive       create an unversioned archive of a repository revision
+   bundle        create a bundle file
+   export        dump the header and diffs for one or more changesets
+   import        import an ordered set of patches
    unbundle      apply one or more bundle files
-   update        update working directory (or switch revisions)
+  
+  Repository maintenance:
+  
+   manifest      output the current or given revision of the project manifest
+   recover       roll back an interrupted transaction
    verify        verify the integrity of the repository
+  
+  Help:
+  
+   config        show combined config settings from all hgrc files
+   help          show help for a given topic or a help overview
    version       output version and copyright information
   
   additional help topics:
@@ -133,55 +165,87 @@
   (use 'hg help -v' to show built-in aliases and global options)
 
   $ hg -q help
-   add           add the specified files on the next commit
-   addremove     add all new files, delete all missing files
-   annotate      show changeset information by line for each file
-   archive       create an unversioned archive of a repository revision
+  Repository creation:
+  
+   clone         make a copy of an existing repository
+   init          create a new repository in the given directory
+  
+  Remote repository management:
+  
+   incoming      show new changesets found in source
+   outgoing      show changesets not found in the destination
+   paths         show aliases for remote repositories
+   pull          pull changes from the specified source
+   push          push changes to the specified destination
+   serve         start stand-alone webserver
+  
+  Change creation:
+  
+   commit        commit the specified files or all outstanding changes
+  
+  Change manipulation:
+  
    backout       reverse effect of earlier changeset
-   bisect        subdivision search of changesets
+   graft         copy changes from other branches onto the current branch
+   merge         merge another revision into working directory
+  
+  Change organization:
+  
    bookmarks     create a new bookmark or list existing bookmarks
    branch        set or show the current branch name
    branches      list repository named branches
-   bundle        create a bundle file
+   phase         set or show the current phase name
+   tag           add one or more tags for the current or given revision
+   tags          list repository tags
+  
+  File content management:
+  
+   annotate      show changeset information by line for each file
    cat           output the current or given revision of files
-   clone         make a copy of an existing repository
-   commit        commit the specified files or all outstanding changes
-   config        show combined config settings from all hgrc files
    copy          mark files as copied for the next commit
    diff          diff repository (or selected files)
-   export        dump the header and diffs for one or more changesets
+   grep          search revision history for a pattern in specified files
+  
+  Change navigation:
+  
+   bisect        subdivision search of changesets
+   heads         show branch heads
+   identify      identify the working directory or specified revision
+   log           show revision history of entire repository or files
+  
+  Working directory management:
+  
+   add           add the specified files on the next commit
+   addremove     add all new files, delete all missing files
    files         list tracked files
    forget        forget the specified files on the next commit
-   graft         copy changes from other branches onto the current branch
-   grep          search revision history for a pattern in specified files
-   heads         show branch heads
-   help          show help for a given topic or a help overview
-   identify      identify the working directory or specified revision
-   import        import an ordered set of patches
-   incoming      show new changesets found in source
-   init          create a new repository in the given directory
-   log           show revision history of entire repository or files
-   manifest      output the current or given revision of the project manifest
-   merge         merge another revision into working directory
-   outgoing      show changesets not found in the destination
-   paths         show aliases for remote repositories
-   phase         set or show the current phase name
-   pull          pull changes from the specified source
-   push          push changes to the specified destination
-   recover       roll back an interrupted transaction
    remove        remove the specified files on the next commit
    rename        rename files; equivalent of copy + remove
    resolve       redo merges or set/view the merge status of files
    revert        restore files to their checkout state
    root          print the root (top) of the current working directory
-   serve         start stand-alone webserver
    status        show changed files in the working directory
    summary       summarize working directory state
-   tag           add one or more tags for the current or given revision
-   tags          list repository tags
+   update        update working directory (or switch revisions)
+  
+  Change import/export:
+  
+   archive       create an unversioned archive of a repository revision
+   bundle        create a bundle file
+   export        dump the header and diffs for one or more changesets
+   import        import an ordered set of patches
    unbundle      apply one or more bundle files
-   update        update working directory (or switch revisions)
+  
+  Repository maintenance:
+  
+   manifest      output the current or given revision of the project manifest
+   recover       roll back an interrupted transaction
    verify        verify the integrity of the repository
+  
+  Help:
+  
+   config        show combined config settings from all hgrc files
+   help          show help for a given topic or a help overview
    version       output version and copyright information
   
   additional help topics:
@@ -810,55 +874,87 @@
   
   list of commands:
   
-   add           add the specified files on the next commit
-   addremove     add all new files, delete all missing files
-   annotate      show changeset information by line for each file
-   archive       create an unversioned archive of a repository revision
+  Repository creation:
+  
+   clone         make a copy of an existing repository
+   init          create a new repository in the given directory
+  
+  Remote repository management:
+  
+   incoming      show new changesets found in source
+   outgoing      show changesets not found in the destination
+   paths         show aliases for remote repositories
+   pull          pull changes from the specified source
+   push          push changes to the specified destination
+   serve         start stand-alone webserver
+  
+  Change creation:
+  
+   commit        commit the specified files or all outstanding changes
+  
+  Change manipulation:
+  
    backout       reverse effect of earlier changeset
-   bisect        subdivision search of changesets
+   graft         copy changes from other branches onto the current branch
+   merge         merge another revision into working directory
+  
+  Change organization:
+  
    bookmarks     create a new bookmark or list existing bookmarks
    branch        set or show the current branch name
    branches      list repository named branches
-   bundle        create a bundle file
+   phase         set or show the current phase name
+   tag           add one or more tags for the current or given revision
+   tags          list repository tags
+  
+  File content management:
+  
+   annotate      show changeset information by line for each file
    cat           output the current or given revision of files
-   clone         make a copy of an existing repository
-   commit        commit the specified files or all outstanding changes
-   config        show combined config settings from all hgrc files
    copy          mark files as copied for the next commit
    diff          diff repository (or selected files)
-   export        dump the header and diffs for one or more changesets
+   grep          search revision history for a pattern in specified files
+  
+  Change navigation:
+  
+   bisect        subdivision search of changesets
+   heads         show branch heads
+   identify      identify the working directory or specified revision
+   log           show revision history of entire repository or files
+  
+  Working directory management:
+  
+   add           add the specified files on the next commit
+   addremove     add all new files, delete all missing files
    files         list tracked files
    forget        forget the specified files on the next commit
-   graft         copy changes from other branches onto the current branch
-   grep          search revision history for a pattern in specified files
-   heads         show branch heads
-   help          show help for a given topic or a help overview
-   identify      identify the working directory or specified revision
-   import        import an ordered set of patches
-   incoming      show new changesets found in source
-   init          create a new repository in the given directory
-   log           show revision history of entire repository or files
-   manifest      output the current or given revision of the project manifest
-   merge         merge another revision into working directory
-   outgoing      show changesets not found in the destination
-   paths         show aliases for remote repositories
-   phase         set or show the current phase name
-   pull          pull changes from the specified source
-   push          push changes to the specified destination
-   recover       roll back an interrupted transaction
    remove        remove the specified files on the next commit
    rename        rename files; equivalent of copy + remove
    resolve       redo merges or set/view the merge status of files
    revert        restore files to their checkout state
    root          print the root (top) of the current working directory
-   serve         start stand-alone webserver
    status        show changed files in the working directory
    summary       summarize working directory state
-   tag           add one or more tags for the current or given revision
-   tags          list repository tags
+   update        update working directory (or switch revisions)
+  
+  Change import/export:
+  
+   archive       create an unversioned archive of a repository revision
+   bundle        create a bundle file
+   export        dump the header and diffs for one or more changesets
+   import        import an ordered set of patches
    unbundle      apply one or more bundle files
-   update        update working directory (or switch revisions)
+  
+  Repository maintenance:
+  
+   manifest      output the current or given revision of the project manifest
+   recover       roll back an interrupted transaction
    verify        verify the integrity of the repository
+  
+  Help:
+  
+   config        show combined config settings from all hgrc files
+   help          show help for a given topic or a help overview
    version       output version and copyright information
   
   enabled extensions:
--- a/tests/test-mq.t	Fri Oct 12 17:57:36 2018 +0200
+++ b/tests/test-mq.t	Sat Oct 13 02:17:41 2018 -0700
@@ -73,29 +73,46 @@
   
   list of commands:
   
+  Repository creation:
+  
+   qclone        clone main and patch repository at same time
+  
+  Change creation:
+  
+   qnew          create a new patch
+   qrefresh      update the current patch
+  
+  Change manipulation:
+  
+   qfold         fold the named patches into the current patch
+  
+  Change organization:
+  
    qapplied      print the patches already applied
-   qclone        clone main and patch repository at same time
    qdelete       remove patches from queue
-   qdiff         diff of the current patch and subsequent modifications
    qfinish       move applied patches into repository history
-   qfold         fold the named patches into the current patch
    qgoto         push or pop patches until named patch is at top of stack
    qguard        set or print guards for a patch
    qheader       print the header of the topmost or specified patch
-   qimport       import a patch or existing changeset
-   qnew          create a new patch
    qnext         print the name of the next pushable patch
    qpop          pop the current patch off the stack
    qprev         print the name of the preceding applied patch
    qpush         push the next patch onto the stack
    qqueue        manage multiple patch queues
-   qrefresh      update the current patch
    qrename       rename a patch
    qselect       set or print guarded patches to push
    qseries       print the entire series file
    qtop          print the name of the current patch
    qunapplied    print the patches not yet applied
   
+  File content management:
+  
+   qdiff         diff of the current patch and subsequent modifications
+  
+  Change import/export:
+  
+   qimport       import a patch or existing changeset
+  
   (use 'hg help -v mq' to show built-in aliases and global options)
 
   $ hg init a