[PATCH 6 of 6] highlight: use docutils for generating help if possible

Dan Villiom Podlaski Christiansen danchr at gmail.com
Sat Feb 9 07:00:40 CST 2013


# HG changeset patch
# User Dan Villiom Podlaski Christiansen  <danchr at gmail.com>
# Date 1360414108 0
# Node ID 40da011562a84f69cd3c198e9c44cd4545bdeedb
# Parent  45b34ea40358b6f8fe14ef874ebbc5de5556f23c
highlight: use docutils for generating help if possible

diff --git a/hgext/highlight/__init__.py b/hgext/highlight/__init__.py
--- a/hgext/highlight/__init__.py
+++ b/hgext/highlight/__init__.py
@@ -21,9 +21,13 @@ There is a single configuration option::
 The default is 'colorful'.
 """
 
-import highlight
+import highlight, rst
+
 from mercurial.hgweb import webcommands, webutil, common
-from mercurial import extensions, encoding
+from mercurial import extensions, encoding, minirst
+
+import cgi, traceback
+
 testedwith = 'internal'
 
 def filerevision_highlight(orig, web, tmpl, fctx):
@@ -48,6 +52,24 @@ def annotate_highlight(orig, web, req, t
         highlight.pygmentize('annotateline', fctx, style, tmpl)
     return orig(web, req, tmpl)
 
+def format_docutils(orig, *args, **opts):
+    if opts.get('style') == 'html':
+        try:
+            return rst.publish(args[0])
+        except Exception:
+            # silently fallback to minirst
+            tb = traceback.format_exc()
+
+            return '\n'.join(['<!--',
+                              'docutils error:',
+                              '',
+                              cgi.escape(tb),
+                              '-->',
+                              '',
+                              orig(*args, **opts)])
+    else:
+        return orig(*args, **opts)
+
 def generate_css(web, req, tmpl):
     pg_style = web.config('web', 'pygments_style', 'colorful')
     fmter = highlight.HtmlFormatter(style = pg_style)
@@ -60,5 +82,6 @@ def extsetup():
     extensions.wrapfunction(webcommands, '_filerevision',
                             filerevision_highlight)
     extensions.wrapfunction(webcommands, 'annotate', annotate_highlight)
+    extensions.wrapfunction(minirst, 'format', format_docutils)
     webcommands.highlightcss = generate_css
     webcommands.__all__.append('highlightcss')
diff --git a/hgext/highlight/rst.py b/hgext/highlight/rst.py
new file mode 100644
--- /dev/null
+++ b/hgext/highlight/rst.py
@@ -0,0 +1,32 @@
+# rst.py - generate HTML from docutils source
+#
+# Copyright 2010-2013 Matt Mackall <mpm at selenic.com> and others
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+#
+# The original module was split in an interface and an implementation
+# file to defer pygments loading and speedup extension setup.
+
+from docutils.parsers.rst import roles
+from docutils import core, nodes, utils
+
+def role_hg(name, rawtext, text, lineno, inliner,
+            options={}, content=[]):
+    text = "hg " + utils.unescape(text)
+    linktext = nodes.literal(rawtext, text)
+    parts = text.split()
+    cmd, args = parts[1], parts[2:]
+    if cmd == 'help' and args:
+        cmd = args[0] # link to 'dates' for 'hg help dates'
+    node = nodes.reference(rawtext, '', linktext,
+                           refuri="%s" % cmd)
+    return [node], []
+
+roles.register_local_role("hg", role_hg)
+
+def publish(text, **opts):
+    parts = core.publish_parts(text, writer_name='html',
+                               enable_exit_status=True, **opts)
+
+    return parts['body']
diff --git a/tests/test-hgweb-help.t b/tests/test-highlight-help.t
copy from tests/test-hgweb-help.t
copy to tests/test-highlight-help.t
--- a/tests/test-hgweb-help.t
+++ b/tests/test-highlight-help.t
@@ -1,11 +1,11 @@
-  $ "$TESTDIR/hghave" serve || exit 80
-
-Test the help pages in hgweb.
-
-Dish up an empty repo; serve it cold.
-
+  $ "$TESTDIR/hghave" docutils serve || exit 80
+  $ cat <<EOF >> $HGRCPATH
+  > [extensions]
+  > highlight =
+  > EOF
   $ hg init test
   $ cd test
+
   $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid
   $ cat hg.pid >> $DAEMON_PIDS
 
@@ -53,102 +53,114 @@ Dish up an empty repo; serve it cold.
   files, or words in the commit message</div>
   </form>
   <div id="doc">
-  <p>
-  hg add [OPTION]... [FILE]...
-  </p>
-  <p>
-  add the specified files on the next commit
-  </p>
-  <p>
-  Schedule files to be version controlled and added to the
-  repository.
-  </p>
-  <p>
-  The files will be added to the repository at the next commit. To
-  undo an add before that, see "hg forget".
-  </p>
-  <p>
-  If no names are given, add all files to the repository.
-  </p>
-  <p>
-  Returns 0 if all files are successfully added.
-  </p>
-  <p>
-  options:
-  </p>
-  <table>
-   <tr><td>-I</td>
+  <p>hg add [OPTION]... [FILE]...</p>
+  <p>add the specified files on the next commit</p>
+  <blockquote>
+  <p>Schedule files to be version controlled and added to the
+  repository.</p>
+  <p>The files will be added to the repository at the next commit. To
+  undo an add before that, see <a class="reference external" href="forget"><tt class="docutils literal">hg forget</tt></a>.</p>
+  <p>If no names are given, add all files to the repository.</p>
+  <div class="verbose container">
+  <p>An example showing how new (unknown) files are added
+  automatically by <a class="reference external" href="add"><tt class="docutils literal">hg add</tt></a>:</p>
+  <pre class="literal-block">
+  \x24 ls (esc)
+  foo.c
+  \x24 hg status (esc)
+  ? foo.c
+  \x24 hg add (esc)
+  adding foo.c
+  \x24 hg status (esc)
+  A foo.c
+  </pre>
+  </div>
+  <p>Returns 0 if all files are successfully added.</p>
+  </blockquote>
+  <p>options:</p>
+  <blockquote>
+  <table border="1" class="docutils">
+  <colgroup>
+  <col width="3%" />
+  <col width="33%" />
+  <col width="64%" />
+  </colgroup>
+  <tbody valign="top">
+  <tr><td>-I</td>
   <td>--include PATTERN [+]</td>
-  <td>include names matching the given patterns</td></tr>
-   <tr><td>-X</td>
+  <td>include names matching the given patterns</td>
+  </tr>
+  <tr><td>-X</td>
   <td>--exclude PATTERN [+]</td>
-  <td>exclude names matching the given patterns</td></tr>
-   <tr><td>-S</td>
+  <td>exclude names matching the given patterns</td>
+  </tr>
+  <tr><td>-S</td>
   <td>--subrepos</td>
-  <td>recurse into subrepositories</td></tr>
-   <tr><td>-n</td>
+  <td>recurse into subrepositories</td>
+  </tr>
+  <tr><td>-n</td>
   <td>--dry-run</td>
-  <td>do not perform actions, just print output</td></tr>
+  <td>do not perform actions, just print output</td>
+  </tr>
+  </tbody>
   </table>
-  <p>
-  [+] marked option can be specified multiple times
-  </p>
-  <p>
-  global options:
-  </p>
-  <table>
-   <tr><td>-R</td>
-  <td>--repository REPO</td>
-  <td>repository root directory or name of overlay bundle file</td></tr>
-   <tr><td></td>
-  <td>--cwd DIR</td>
-  <td>change working directory</td></tr>
-   <tr><td>-y</td>
+  </blockquote>
+  <p>[+] marked option can be specified multiple times</p>
+  <p>global options:</p>
+  <blockquote>
+  <table border="1" class="docutils">
+  <colgroup>
+  <col width="2%" />
+  <col width="22%" />
+  <col width="76%" />
+  </colgroup>
+  <tbody valign="top">
+  <tr><td>-R</td>
+  <td>--repository REPO
+  --cwd DIR</td>
+  <td>repository root directory or name of overlay bundle file
+  change working directory</td>
+  </tr>
+  <tr><td>-y</td>
   <td>--noninteractive</td>
-  <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
-   <tr><td>-q</td>
+  <td>do not prompt, automatically pick the first choice for all prompts</td>
+  </tr>
+  <tr><td>-q</td>
   <td>--quiet</td>
-  <td>suppress output</td></tr>
-   <tr><td>-v</td>
-  <td>--verbose</td>
-  <td>enable additional output</td></tr>
-   <tr><td></td>
-  <td>--config CONFIG [+]</td>
-  <td>set/override config option (use 'section.name=value')</td></tr>
-   <tr><td></td>
-  <td>--debug</td>
-  <td>enable debugging output</td></tr>
-   <tr><td></td>
-  <td>--debugger</td>
-  <td>start debugger</td></tr>
-   <tr><td></td>
-  <td>--encoding ENCODE</td>
-  <td>set the charset encoding (default: ascii)</td></tr>
-   <tr><td></td>
-  <td>--encodingmode MODE</td>
-  <td>set the charset encoding mode (default: strict)</td></tr>
-   <tr><td></td>
-  <td>--traceback</td>
-  <td>always print a traceback on exception</td></tr>
-   <tr><td></td>
-  <td>--time</td>
-  <td>time how long the command takes</td></tr>
-   <tr><td></td>
-  <td>--profile</td>
-  <td>print command execution profile</td></tr>
-   <tr><td></td>
-  <td>--version</td>
-  <td>output version information and exit</td></tr>
-   <tr><td>-h</td>
-  <td>--help</td>
-  <td>display help and exit</td></tr>
-   <tr><td></td>
-  <td>--hidden</td>
-  <td>consider hidden changesets</td></tr>
+  <td>suppress output</td>
+  </tr>
+  <tr><td>-v</td>
+  <td>--verbose
+  --config CONFIG [+]
+  --debug
+  --debugger
+  --encoding ENCODE
+  --encodingmode MODE
+  --traceback
+  --time
+  --profile
+  --version</td>
+  <td>enable additional output
+  set/override config option (use 'section.name=value')
+  enable debugging output
+  start debugger
+  set the charset encoding (default: ascii)
+  set the charset encoding mode (default: strict)
+  always print a traceback on exception
+  time how long the command takes
+  print command execution profile
+  output version information and exit</td>
+  </tr>
+  <tr><td>-h</td>
+  <td>--help
+  --hidden</td>
+  <td>display help and exit
+  consider hidden changesets</td>
+  </tr>
+  </tbody>
   </table>
-  <p>
-  [+] marked option can be specified multiple times
-  </p>
+  </blockquote>
+  <p>[+] marked option can be specified multiple times</p>
   
   </div>
   </div>
@@ -205,102 +217,156 @@ Dish up an empty repo; serve it cold.
   files, or words in the commit message</div>
   </form>
   <div id="doc">
-  <p>
-  hg remove [OPTION]... FILE...
-  </p>
-  <p>
-  aliases: rm
-  </p>
-  <p>
-  remove the specified files on the next commit
-  </p>
-  <p>
-  Schedule the indicated files for removal from the current branch.
-  </p>
-  <p>
-  This command schedules the files to be removed at the next commit.
-  To undo a remove before that, see "hg revert". To undo added
-  files, see "hg forget".
-  </p>
-  <p>
-  Returns 0 on success, 1 if any warnings encountered.
-  </p>
-  <p>
-  options:
-  </p>
-  <table>
-   <tr><td>-A</td>
+  <p>hg remove [OPTION]... FILE...</p>
+  <p>aliases: rm</p>
+  <p>remove the specified files on the next commit</p>
+  <blockquote>
+  <p>Schedule the indicated files for removal from the current branch.</p>
+  <p>This command schedules the files to be removed at the next commit.
+  To undo a remove before that, see <a class="reference external" href="revert"><tt class="docutils literal">hg revert</tt></a>. To undo added
+  files, see <a class="reference external" href="forget"><tt class="docutils literal">hg forget</tt></a>.</p>
+  <div class="verbose container">
+  <p>-A/--after can be used to remove only files that have already
+  been deleted, -f/--force can be used to force deletion, and -Af
+  can be used to remove files from the next revision without
+  deleting them from the working directory.</p>
+  <p>The following table details the behavior of remove for different
+  file states (columns) and option combinations (rows). The file
+  states are Added [A], Clean [C], Modified [M] and Missing [!]
+  (as reported by <a class="reference external" href="status"><tt class="docutils literal">hg status</tt></a>). The actions are Warn, Remove
+  (from branch) and Delete (from disk):</p>
+  <table border="1" class="docutils">
+  <colgroup>
+  <col width="47%" />
+  <col width="13%" />
+  <col width="13%" />
+  <col width="13%" />
+  <col width="13%" />
+  </colgroup>
+  <thead valign="bottom">
+  <tr><th class="head"> </th>
+  <th class="head"> </th>
+  <th class="head"> </th>
+  <th class="head"> </th>
+  <th class="head"> </th>
+  </tr>
+  </thead>
+  <tbody valign="top">
+  <tr><td>none</td>
+  <td>W</td>
+  <td>RD</td>
+  <td>W</td>
+  <td>R</td>
+  </tr>
+  <tr><td>-f</td>
+  <td>R</td>
+  <td>RD</td>
+  <td>RD</td>
+  <td>R</td>
+  </tr>
+  <tr><td>-A</td>
+  <td>W</td>
+  <td>W</td>
+  <td>W</td>
+  <td>R</td>
+  </tr>
+  <tr><td>-Af</td>
+  <td>R</td>
+  <td>R</td>
+  <td>R</td>
+  <td>R</td>
+  </tr>
+  </tbody>
+  </table>
+  <p>Note that remove never deletes files in Added [A] state from the
+  working directory, not even if option --force is specified.</p>
+  </div>
+  <p>Returns 0 on success, 1 if any warnings encountered.</p>
+  </blockquote>
+  <p>options:</p>
+  <blockquote>
+  <table border="1" class="docutils">
+  <colgroup>
+  <col width="3%" />
+  <col width="29%" />
+  <col width="68%" />
+  </colgroup>
+  <tbody valign="top">
+  <tr><td>-A</td>
   <td>--after</td>
-  <td>record delete for missing files</td></tr>
-   <tr><td>-f</td>
+  <td>record delete for missing files</td>
+  </tr>
+  <tr><td>-f</td>
   <td>--force</td>
-  <td>remove (and delete) file even if added or modified</td></tr>
-   <tr><td>-I</td>
+  <td>remove (and delete) file even if added or modified</td>
+  </tr>
+  <tr><td>-I</td>
   <td>--include PATTERN [+]</td>
-  <td>include names matching the given patterns</td></tr>
-   <tr><td>-X</td>
+  <td>include names matching the given patterns</td>
+  </tr>
+  <tr><td>-X</td>
   <td>--exclude PATTERN [+]</td>
-  <td>exclude names matching the given patterns</td></tr>
+  <td>exclude names matching the given patterns</td>
+  </tr>
+  </tbody>
   </table>
-  <p>
-  [+] marked option can be specified multiple times
-  </p>
-  <p>
-  global options:
-  </p>
-  <table>
-   <tr><td>-R</td>
-  <td>--repository REPO</td>
-  <td>repository root directory or name of overlay bundle file</td></tr>
-   <tr><td></td>
-  <td>--cwd DIR</td>
-  <td>change working directory</td></tr>
-   <tr><td>-y</td>
+  </blockquote>
+  <p>[+] marked option can be specified multiple times</p>
+  <p>global options:</p>
+  <blockquote>
+  <table border="1" class="docutils">
+  <colgroup>
+  <col width="2%" />
+  <col width="22%" />
+  <col width="76%" />
+  </colgroup>
+  <tbody valign="top">
+  <tr><td>-R</td>
+  <td>--repository REPO
+  --cwd DIR</td>
+  <td>repository root directory or name of overlay bundle file
+  change working directory</td>
+  </tr>
+  <tr><td>-y</td>
   <td>--noninteractive</td>
-  <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
-   <tr><td>-q</td>
+  <td>do not prompt, automatically pick the first choice for all prompts</td>
+  </tr>
+  <tr><td>-q</td>
   <td>--quiet</td>
-  <td>suppress output</td></tr>
-   <tr><td>-v</td>
-  <td>--verbose</td>
-  <td>enable additional output</td></tr>
-   <tr><td></td>
-  <td>--config CONFIG [+]</td>
-  <td>set/override config option (use 'section.name=value')</td></tr>
-   <tr><td></td>
-  <td>--debug</td>
-  <td>enable debugging output</td></tr>
-   <tr><td></td>
-  <td>--debugger</td>
-  <td>start debugger</td></tr>
-   <tr><td></td>
-  <td>--encoding ENCODE</td>
-  <td>set the charset encoding (default: ascii)</td></tr>
-   <tr><td></td>
-  <td>--encodingmode MODE</td>
-  <td>set the charset encoding mode (default: strict)</td></tr>
-   <tr><td></td>
-  <td>--traceback</td>
-  <td>always print a traceback on exception</td></tr>
-   <tr><td></td>
-  <td>--time</td>
-  <td>time how long the command takes</td></tr>
-   <tr><td></td>
-  <td>--profile</td>
-  <td>print command execution profile</td></tr>
-   <tr><td></td>
-  <td>--version</td>
-  <td>output version information and exit</td></tr>
-   <tr><td>-h</td>
-  <td>--help</td>
-  <td>display help and exit</td></tr>
-   <tr><td></td>
-  <td>--hidden</td>
-  <td>consider hidden changesets</td></tr>
+  <td>suppress output</td>
+  </tr>
+  <tr><td>-v</td>
+  <td>--verbose
+  --config CONFIG [+]
+  --debug
+  --debugger
+  --encoding ENCODE
+  --encodingmode MODE
+  --traceback
+  --time
+  --profile
+  --version</td>
+  <td>enable additional output
+  set/override config option (use 'section.name=value')
+  enable debugging output
+  start debugger
+  set the charset encoding (default: ascii)
+  set the charset encoding mode (default: strict)
+  always print a traceback on exception
+  time how long the command takes
+  print command execution profile
+  output version information and exit</td>
+  </tr>
+  <tr><td>-h</td>
+  <td>--help
+  --hidden</td>
+  <td>display help and exit
+  consider hidden changesets</td>
+  </tr>
+  </tbody>
   </table>
-  <p>
-  [+] marked option can be specified multiple times
-  </p>
+  </blockquote>
+  <p>[+] marked option can be specified multiple times</p>
   
   </div>
   </div>
@@ -357,47 +423,28 @@ Dish up an empty repo; serve it cold.
   files, or words in the commit message</div>
   </form>
   <div id="doc">
-  <table>
-   <tr><td>Specifying Single Revisions</td></tr>
-  </table>
-  <p>
-  Mercurial supports several ways to specify individual revisions.
-  </p>
-  <p>
-  A plain integer is treated as a revision number. Negative integers are
+  <p>Mercurial supports several ways to specify individual revisions.</p>
+  <p>A plain integer is treated as a revision number. Negative integers are
   treated as sequential offsets from the tip, with -1 denoting the tip,
-  -2 denoting the revision prior to the tip, and so forth.
-  </p>
-  <p>
-  A 40-digit hexadecimal string is treated as a unique revision
-  identifier.
-  </p>
-  <p>
-  A hexadecimal string less than 40 characters long is treated as a
+  -2 denoting the revision prior to the tip, and so forth.</p>
+  <p>A 40-digit hexadecimal string is treated as a unique revision
+  identifier.</p>
+  <p>A hexadecimal string less than 40 characters long is treated as a
   unique revision identifier and is referred to as a short-form
   identifier. A short-form identifier is only valid if it is the prefix
-  of exactly one full-length identifier.
-  </p>
-  <p>
-  Any other string is treated as a bookmark, tag, or branch name. A
+  of exactly one full-length identifier.</p>
+  <p>Any other string is treated as a bookmark, tag, or branch name. A
   bookmark is a movable pointer to a revision. A tag is a permanent name
   associated with a revision. A branch name denotes the tipmost revision
-  of that branch. Bookmark, tag, and branch names must not contain the ":"
-  character.
-  </p>
-  <p>
-  The reserved name "tip" always identifies the most recent revision.
-  </p>
-  <p>
-  The reserved name "null" indicates the null revision. This is the
-  revision of an empty repository, and the parent of revision 0.
-  </p>
-  <p>
-  The reserved name "." indicates the working directory parent. If no
+  of that branch. Bookmark, tag, and branch names must not contain the ":"
+  character.</p>
+  <p>The reserved name "tip" always identifies the most recent revision.</p>
+  <p>The reserved name "null" indicates the null revision. This is the
+  revision of an empty repository, and the parent of revision 0.</p>
+  <p>The reserved name "." indicates the working directory parent. If no
   working directory is checked out, it is equivalent to null. If an
-  uncommitted merge is in progress, "." is the revision of the first
-  parent.
-  </p>
+  uncommitted merge is in progress, "." is the revision of the first
+  parent.</p>
   
   </div>
   </div>


More information about the Mercurial-devel mailing list