[PATCH REVIEW] help: Consistent use of minirst to format console and HTML help

Olav Reinert seroton10 at gmail.com
Sun May 13 08:50:04 CDT 2012


# HG changeset patch
# User Olav Reinert <seroton10 at gmail.com>
# Date 1336916920 -7200
# Node ID d1baea8535e408f5b7f0315273abe745bbc08257
# Parent  76c744e0c5bbd0900beba49787b7e04ba862939b
help: Consistent use of minirst to format console and HTML help

This patch changes the existing help system just enough to enable formatting of
all help text to use minirst. It exposes several shortcomings of the reST
parser and formatters which need to be fixed. Also, there are several
opportunities for cleanup (such as moving many or all of the inner functions of
helprst to help.py).

diff -r 76c744e0c5bb -r d1baea8535e4 mercurial/commands.py
--- a/mercurial/commands.py	Sat May 12 13:20:26 2012 +0200
+++ b/mercurial/commands.py	Sun May 13 15:48:40 2012 +0200
@@ -3052,12 +3052,8 @@
         displayer.show(ctx)
     displayer.close()
 
- at command('help',
-    [('e', 'extension', None, _('show only help for extensions')),
-     ('c', 'command', None, _('show only help for commands'))],
-    _('[-ec] [TOPIC]'))
-def help_(ui, name=None, unknowncmd=False, full=True, **opts):
-    """show help for a given topic or a help overview
+def helprst(ui, name=None, unknowncmd=False, full=True, **opts):
+    """generates RST-formatted help for a given topic or a help overview
 
     With no arguments, print a list of commands with short help messages.
 
@@ -3105,19 +3101,15 @@
         return rst
 
     # list all option lists
-    def opttext(optlist, width):
+    def opttext(optlist):
         rst = ''
-        if not optlist:
-            return ''
-
-        for title, options in optlist:
-            rst += '\n%s\n' % title
-            if options:
-                rst += "\n"
-                rst += optrst(options)
-                rst += '\n'
-
-        return '\n' + minirst.format(rst, width)
+        if optlist:
+            for title, options in optlist:
+                rst += '\n%s\n' % title
+                if options:
+                    rst += '\n' + optrst(options) + '\n'
+
+        return rst
 
     def addglobalopts(optlist, aliases):
         if ui.quiet:
@@ -3149,8 +3141,7 @@
             # except block, nor can be used inside a lambda. python issue4617
             prefix = inst.args[0]
             select = lambda c: c.lstrip('^').startswith(prefix)
-            helplist(select)
-            return
+            return helplist(select)
 
         # check if it's an invalid alias and display its error if it is
         if getattr(entry[0], 'badalias', False):
@@ -3158,20 +3149,21 @@
                 entry[0](ui)
             return
 
-        rst = ""
+        rst = []
 
         # synopsis
         if len(entry) > 2:
             if entry[2].startswith('hg'):
-                rst += "%s\n" % entry[2]
+                title = "%s\n" % entry[2]
             else:
-                rst += 'hg %s %s\n' % (aliases[0], entry[2])
+                title = 'hg %s %s\n' % (aliases[0], entry[2])
         else:
-            rst += 'hg %s\n' % aliases[0]
+            title = 'hg %s\n' % aliases[0]
+        rst.append('*%s*' % title)
 
         # aliases
         if full and not ui.quiet and len(aliases) > 1:
-            rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
+            rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
 
         # description
         doc = gettext(entry[0].__doc__)
@@ -3184,7 +3176,7 @@
                 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
         if ui.quiet or not full:
             doc = doc.splitlines()[0]
-        rst += "\n" + doc + "\n"
+        rst.append("\n" + doc + "\n")
 
         # check if this command shadows a non-trivial (multi-line)
         # extension help text
@@ -3194,42 +3186,35 @@
             if '\n' in doc.strip():
                 msg = _('use "hg help -e %s" to show help for '
                         'the %s extension') % (name, name)
-                rst += '\n%s\n' % msg
+                rst.append('\n%s\n' % msg)
         except KeyError:
             pass
 
         # options
         if not ui.quiet and entry[1]:
-            rst += '\n'
-            rst += _("options:")
-            rst += '\n\n'
-            rst += optrst(entry[1])
+            rst.append('\n%s\n' % _("options:"))
+            rst.append(optrst(entry[1]))
 
         if ui.verbose:
-            rst += '\n'
-            rst += _("global options:")
-            rst += '\n\n'
-            rst += optrst(globalopts)
-
-        keep = ui.verbose and ['verbose'] or []
-        formatted, pruned = minirst.format(rst, textwidth, keep=keep)
-        ui.write(formatted)
+            rst.append('\n%s\n' % _("global options:"))
+            rst.append(optrst(globalopts))
+
+        #keep = ui.verbose and ['verbose'] or []
+        #formatted, pruned = minirst.format(rst, textwidth, keep=keep)
+        #ui.write(formatted)
 
         if not ui.verbose:
             if not full:
-                ui.write(_('\nuse "hg help %s" to show the full help text\n')
+                rst.append(_('\nuse "hg help %s" to show the full help text\n')
                            % name)
             elif not ui.quiet:
-                ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
+                rst.append(_('\nuse "hg -v help %s" to show more info\n') % name)
+
+        return rst
 
 
     def helplist(select=None):
         # list of commands
-        if name == "shortlist":
-            header = _('basic commands:\n\n')
-        else:
-            header = _('list of commands:\n\n')
-
         h = {}
         cmds = {}
         for c, e in table.iteritems():
@@ -3254,37 +3239,47 @@
             cmds[f] = c.lstrip("^")
 
         if not h:
-            ui.status(_('no commands defined\n'))
-            return
-
-        ui.status(header)
+            rst = ".. note:: " + _('no commands defined\n')
+            return rst
+
+        if name == "shortlist":
+            header = _('basic commands:\n\n')
+        else:
+            header = _('list of commands:\n\n')
+
+        rst = [ header ]
+
         fns = sorted(h)
         m = max(map(len, fns))
         for f in fns:
             if ui.verbose:
                 commands = cmds[f].replace("|",", ")
-                ui.write(" %s:\n      %s\n"%(commands, h[f]))
+                rst.append(" %s" % commands)
+                rst.append("      %s" % h[f])
+                #ui.write(" %s:\n      %s\n"%(commands, h[f]))
             else:
-                ui.write('%s\n' % (util.wrap(h[f], textwidth,
-                                             initindent=' %-*s    ' % (m, f),
-                                             hangindent=' ' * (m + 4))))
+                rst.append(" :%s: %s" % (f, h[f]))
+                #ui.write('%s\n' % (util.wrap(h[f], textwidth,
+                #                             initindent=' %-*s    ' % (m, f),
+                #                             hangindent=' ' * (m + 4))))
 
         if not name:
-            text = help.listexts(_('enabled extensions:'), extensions.enabled())
+            text = extensions.enabled()
             if text:
-                ui.write("\n%s" % minirst.format(text, textwidth))
-
-            ui.write(_("\nadditional help topics:\n\n"))
+                rst.extend(help.listexts(_('enabled extensions:'), text))
+
+            rst.append(_("\nadditional help topics:\n\n"))
             topics = []
             for names, header, doc in help.helptable:
                 topics.append((sorted(names, key=len, reverse=True)[0], header))
-            topics_len = max([len(s[0]) for s in topics])
+            #topics_len = max([len(s[0]) for s in topics])
             for t, desc in topics:
-                ui.write(" %-*s   %s\n" % (topics_len, t, desc))
+                rst.append(" :%s: %s" % (t, desc))
 
         optlist = []
         addglobalopts(optlist, True)
-        ui.write(opttext(optlist, textwidth))
+        rst.append(opttext(optlist))
+        return rst
 
     def helptopic(name):
         for names, header, doc in help.helptable:
@@ -3299,14 +3294,15 @@
         if util.safehasattr(doc, '__call__'):
             doc = doc()
 
-        ui.write("%s\n\n" % header)
-        ui.write("%s" % minirst.format(doc, textwidth, indent=4))
+        rst = [ "%s\n\n" % header ]
+        rst.append("%s" % minirst.format(doc, textwidth, indent=4))
         try:
             cmdutil.findcmd(name, table)
-            ui.write(_('\nuse "hg help -c %s" to see help for '
+            rst.append(_('\nuse "hg help -c %s" to see help for '
                        'the %s command\n') % (name, name))
         except error.UnknownCommand:
             pass
+        return rst
 
     def helpext(name):
         try:
@@ -3322,10 +3318,10 @@
             head, tail = doc, ""
         else:
             head, tail = doc.split('\n', 1)
-        ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
+        rst = [ _('%s extension - %s\n\n') % (name.split('.')[-1], head) ]
         if tail:
-            ui.write(minirst.format(tail, textwidth))
-            ui.status('\n')
+            rst.append(tail)
+            rst.append('')
 
         if mod:
             try:
@@ -3333,47 +3329,80 @@
             except AttributeError:
                 ct = {}
             modcmds = set([c.split('|', 1)[0] for c in ct])
-            helplist(modcmds.__contains__)
+            rst.extend(helplist(modcmds.__contains__))
         else:
-            ui.write(_('use "hg help extensions" for information on enabling '
+            rst.append(_('use "hg help extensions" for information on enabling '
                        'extensions\n'))
+        return rst
 
     def helpextcmd(name):
         cmd, ext, mod = extensions.disabledcmd(ui, name,
                                                ui.configbool('ui', 'strict'))
         doc = gettext(mod.__doc__).splitlines()[0]
 
-        msg = help.listexts(_("'%s' is provided by the following "
+        rst = help.listexts(_("'%s' is provided by the following "
                               "extension:") % cmd, {ext: doc}, indent=4)
-        ui.write(minirst.format(msg, textwidth))
-        ui.write('\n')
-        ui.write(_('use "hg help extensions" for information on enabling '
+        rst.append('')
+        rst.append(_('use "hg help extensions" for information on enabling '
                    'extensions\n'))
+        return rst
 
     if name and name != 'shortlist':
         i = None
         if unknowncmd:
+            print 'unknowncmd'
             queries = (helpextcmd,)
         elif opts.get('extension'):
+            print 'extension'
             queries = (helpext,)
         elif opts.get('command'):
+            print 'command'
             queries = (helpcmd,)
         else:
+            print 'scan'
             queries = (helptopic, helpcmd, helpext, helpextcmd)
         for f in queries:
             try:
-                f(name)
+                rst = f(name)
+                print f
                 i = None
-                break
+                return rst
             except error.UnknownCommand, inst:
                 i = inst
         if i:
             raise i
     else:
         # program name
-        ui.status(_("Mercurial Distributed SCM\n"))
-        ui.status('\n')
-        helplist()
+        rst = [ _("Mercurial Distributed SCM\n") ]
+        rst.extend(helplist())
+        return rst
+
+
+ at command('help',
+    [('e', 'extension', None, _('show only help for extensions')),
+     ('c', 'command', None, _('show only help for commands'))],
+    _('[-ec] [TOPIC]'))
+def help_(ui, name=None, unknowncmd=False, full=True, **opts):
+    """show help for a given topic or a help overview
+
+    With no arguments, print a list of commands with short help messages.
+
+    Given a topic, extension, or command name, print help for that
+    topic.
+
+    Returns 0 if successful.
+    """
+
+    rst = helprst(ui, name, unknowncmd, full, **opts)
+    textwidth = min(ui.termwidth(), 80) - 2
+    rst = '\n'.join(rst)
+    ui.write(minirst.format(rst, textwidth))
+
+
+def helphtml(ui, name):
+    rst = helprst(ui, name)
+    rst = '\n'.join(rst)
+    ui.write(minirst.format(rst, style='html'))
 
 
 @command('identify|id',
diff -r 76c744e0c5bb -r d1baea8535e4 mercurial/help.py
--- a/mercurial/help.py	Sat May 12 13:20:26 2012 +0200
+++ b/mercurial/help.py	Sun May 13 15:48:40 2012 +0200
@@ -14,11 +14,9 @@
     '''return a text listing of the given extensions'''
     if not exts:
         return ''
-    maxlength = max(len(e) for e in exts)
-    result = '\n%s\n\n' % header
+    result = [ '\n%s\n' % header ]
     for name, desc in sorted(exts.iteritems()):
-        result += '%s%-*s %s\n' % (' ' * indent, maxlength + 2,
-                                   ':%s:' % name, desc)
+        result.append('%s:%s: %s' % (' ' * indent, name, desc))
     return result
 
 def extshelp():
diff -r 76c744e0c5bb -r d1baea8535e4 mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py	Sat May 12 13:20:26 2012 +0200
+++ b/mercurial/hgweb/webcommands.py	Sun May 13 15:48:40 2012 +0200
@@ -850,7 +850,7 @@
     u = webutil.wsgiui()
     u.pushbuffer()
     try:
-        commands.help_(u, topicname)
+        commands.helphtml(u, topicname)
     except error.UnknownCommand:
         raise ErrorResponse(HTTP_NOT_FOUND)
     doc = u.popbuffer()
diff -r 76c744e0c5bb -r d1baea8535e4 mercurial/templates/paper/help.tmpl
--- a/mercurial/templates/paper/help.tmpl	Sat May 12 13:20:26 2012 +0200
+++ b/mercurial/templates/paper/help.tmpl	Sun May 13 15:48:40 2012 +0200
@@ -35,9 +35,7 @@
 <div id="hint">find changesets by author, revision,
 files, or words in the commit message</div>
 </form>
-<pre>
-{doc|escape}
-</pre>
+{doc}
 </div>
 </div>
 


More information about the Mercurial-devel mailing list