gendoc.py
240 lines
| 7.2 KiB
| text/x-python
|
PythonLexer
/ doc / gendoc.py
|
r27496 | #!/usr/bin/env python | ||
|
r19425 | """usage: %s DOC ... | ||
where DOC is the name of a document | ||||
""" | ||||
|
r28966 | from __future__ import absolute_import | ||
import os | ||||
import sys | ||||
import textwrap | ||||
|
r27330 | |||
|
r41040 | try: | ||
import msvcrt | ||||
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) | ||||
msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY) | ||||
except ImportError: | ||||
pass | ||||
|
r27330 | # This script is executed during installs and may not have C extensions | ||
# available. Relax C module requirements. | ||||
|
r41040 | os.environ[r'HGMODULEPOLICY'] = r'allow' | ||
|
r1814 | # import from the live mercurial repo | ||
|
r41040 | sys.path.insert(0, r"..") | ||
|
r5209 | from mercurial import demandimport; demandimport.enable() | ||
|
r32336 | # Load util so that the locale path is set by i18n.setdatapath() before | ||
# calling _(). | ||||
from mercurial import util | ||||
util.datapath | ||||
|
r28966 | from mercurial import ( | ||
commands, | ||||
|
r41059 | encoding, | ||
|
r28966 | extensions, | ||
help, | ||||
minirst, | ||||
|
r41040 | pycompat, | ||
|
r28966 | ui as uimod, | ||
) | ||||
from mercurial.i18n import ( | ||||
gettext, | ||||
_, | ||||
) | ||||
table = commands.table | ||||
globalopts = commands.globalopts | ||||
helptable = help.helptable | ||||
loaddoc = help.loaddoc | ||||
|
r1814 | |||
def get_desc(docstr): | ||||
if not docstr: | ||||
|
r41040 | return b"", b"" | ||
|
r1814 | # sanitize | ||
|
r41040 | docstr = docstr.strip(b"\n") | ||
|
r1814 | docstr = docstr.rstrip() | ||
shortdesc = docstr.splitlines()[0].strip() | ||||
|
r41040 | i = docstr.find(b"\n") | ||
|
r1814 | if i != -1: | ||
|
r10282 | desc = docstr[i + 2:] | ||
|
r1814 | else: | ||
|
r12780 | desc = shortdesc | ||
|
r41040 | desc = textwrap.dedent(desc.decode('latin1')).encode('latin1') | ||
|
r12780 | |||
|
r1814 | return (shortdesc, desc) | ||
def get_opts(opts): | ||||
|
r11321 | for opt in opts: | ||
if len(opt) == 5: | ||||
shortopt, longopt, default, desc, optlabel = opt | ||||
else: | ||||
shortopt, longopt, default, desc = opt | ||||
|
r41040 | optlabel = _(b"VALUE") | ||
|
r1814 | allopts = [] | ||
if shortopt: | ||||
|
r41040 | allopts.append(b"-%s" % shortopt) | ||
|
r1814 | if longopt: | ||
|
r41040 | allopts.append(b"--%s" % longopt) | ||
|
r20081 | if isinstance(default, list): | ||
|
r41040 | allopts[-1] += b" <%s[+]>" % optlabel | ||
|
r20081 | elif (default is not None) and not isinstance(default, bool): | ||
|
r41040 | allopts[-1] += b" <%s>" % optlabel | ||
if b'\n' in desc: | ||||
|
r20655 | # only remove line breaks and indentation | ||
|
r41040 | desc = b' '.join(l.lstrip() for l in desc.split(b'\n')) | ||
desc += default and _(b" (default: %s)") % bytes(default) or b"" | ||||
yield (b", ".join(allopts), desc) | ||||
|
r1814 | |||
|
r12756 | def get_cmd(cmd, cmdtable): | ||
|
r1814 | d = {} | ||
|
r12756 | attr = cmdtable[cmd] | ||
|
r41040 | cmds = cmd.lstrip(b"^").split(b"|") | ||
|
r1814 | |||
|
r41040 | d[b'cmd'] = cmds[0] | ||
d[b'aliases'] = cmd.split(b"|")[1:] | ||||
d[b'desc'] = get_desc(gettext(pycompat.getdoc(attr[0]))) | ||||
d[b'opts'] = list(get_opts(attr[1])) | ||||
|
r7376 | |||
|
r41040 | s = b'hg ' + cmds[0] | ||
|
r7376 | if len(attr) > 2: | ||
|
r41040 | if not attr[2].startswith(b'hg'): | ||
s += b' ' + attr[2] | ||||
|
r7376 | else: | ||
s = attr[2] | ||||
|
r41040 | d[b'synopsis'] = s.strip() | ||
|
r7376 | |||
|
r1814 | return d | ||
|
r19423 | def showdoc(ui): | ||
|
r1814 | # print options | ||
|
r41040 | ui.write(minirst.section(_(b"Options"))) | ||
|
r20081 | multioccur = False | ||
|
r1814 | for optstr, desc in get_opts(globalopts): | ||
|
r41040 | ui.write(b"%s\n %s\n\n" % (optstr, desc)) | ||
if optstr.endswith(b"[+]>"): | ||||
|
r20081 | multioccur = True | ||
if multioccur: | ||||
|
r41040 | ui.write(_(b"\n[+] marked option can be specified multiple times\n")) | ||
ui.write(b"\n") | ||||
|
r1814 | |||
# print cmds | ||||
|
r41040 | ui.write(minirst.section(_(b"Commands"))) | ||
|
r18748 | commandprinter(ui, table, minirst.subsection) | ||
|
r12756 | |||
|
r19233 | # print help topics | ||
# The config help topic is included in the hgrc.5 man page. | ||||
|
r41040 | helpprinter(ui, helptable, minirst.section, exclude=[b'config']) | ||
|
r12756 | |||
|
r41040 | ui.write(minirst.section(_(b"Extensions"))) | ||
ui.write(_(b"This section contains help for extensions that are " | ||||
b"distributed together with Mercurial. Help for other " | ||||
b"extensions is available in the help system.")) | ||||
ui.write((b"\n\n" | ||||
b".. contents::\n" | ||||
b" :class: htmlonly\n" | ||||
b" :local:\n" | ||||
b" :depth: 1\n\n")) | ||||
|
r12781 | |||
for extensionname in sorted(allextensionnames()): | ||||
|
r27660 | mod = extensions.load(ui, extensionname, None) | ||
|
r18748 | ui.write(minirst.subsection(extensionname)) | ||
|
r41040 | ui.write(b"%s\n\n" % gettext(pycompat.getdoc(mod))) | ||
|
r12781 | cmdtable = getattr(mod, 'cmdtable', None) | ||
if cmdtable: | ||||
|
r41040 | ui.write(minirst.subsubsection(_(b'Commands'))) | ||
|
r18748 | commandprinter(ui, cmdtable, minirst.subsubsubsection) | ||
|
r12781 | |||
|
r19424 | def showtopic(ui, topic): | ||
extrahelptable = [ | ||||
|
r41040 | ([b"common"], b'', loaddoc(b'common'), help.TOPIC_CATEGORY_MISC), | ||
([b"hg.1"], b'', loaddoc(b'hg.1'), help.TOPIC_CATEGORY_CONFIG), | ||||
([b"hg-ssh.8"], b'', loaddoc(b'hg-ssh.8'), help.TOPIC_CATEGORY_CONFIG), | ||||
([b"hgignore.5"], b'', loaddoc(b'hgignore.5'), | ||||
|
r40330 | help.TOPIC_CATEGORY_CONFIG), | ||
|
r41040 | ([b"hgrc.5"], b'', loaddoc(b'hgrc.5'), help.TOPIC_CATEGORY_CONFIG), | ||
([b"hgignore.5.gendoc"], b'', loaddoc(b'hgignore'), | ||||
help.TOPIC_CATEGORY_CONFIG), | ||||
([b"hgrc.5.gendoc"], b'', loaddoc(b'config'), | ||||
help.TOPIC_CATEGORY_CONFIG), | ||||
|
r19424 | ] | ||
helpprinter(ui, helptable + extrahelptable, None, include=[topic]) | ||||
|
r19233 | def helpprinter(ui, helptable, sectionfunc, include=[], exclude=[]): | ||
|
r40327 | for h in helptable: | ||
names, sec, doc = h[0:3] | ||||
|
r19233 | if exclude and names[0] in exclude: | ||
continue | ||||
if include and names[0] not in include: | ||||
continue | ||||
for name in names: | ||||
|
r41040 | ui.write(b".. _%s:\n" % name) | ||
ui.write(b"\n") | ||||
|
r19233 | if sectionfunc: | ||
ui.write(sectionfunc(sec)) | ||||
|
r21793 | if callable(doc): | ||
|
r26413 | doc = doc(ui) | ||
|
r19233 | ui.write(doc) | ||
|
r41040 | ui.write(b"\n") | ||
|
r19233 | |||
|
r12781 | def commandprinter(ui, cmdtable, sectionfunc): | ||
|
r1814 | h = {} | ||
|
r12756 | for c, attr in cmdtable.items(): | ||
|
r41040 | f = c.split(b"|")[0] | ||
f = f.lstrip(b"^") | ||||
|
r6488 | h[f] = c | ||
|
r1814 | cmds = h.keys() | ||
|
r41040 | for f in sorted(cmds): | ||
if f.startswith(b"debug"): | ||||
|
r10282 | continue | ||
|
r12756 | d = get_cmd(h[f], cmdtable) | ||
|
r41040 | ui.write(sectionfunc(d[b'cmd'])) | ||
|
r20689 | # short description | ||
|
r41040 | ui.write(d[b'desc'][0]) | ||
|
r6488 | # synopsis | ||
|
r41040 | ui.write(b"::\n\n") | ||
synopsislines = d[b'synopsis'].splitlines() | ||||
|
r12813 | for line in synopsislines: | ||
# some commands (such as rebase) have a multi-line | ||||
# synopsis | ||||
|
r41040 | ui.write(b" %s\n" % line) | ||
ui.write(b'\n') | ||||
|
r6488 | # description | ||
|
r41040 | ui.write(b"%s\n\n" % d[b'desc'][1]) | ||
|
r6488 | # options | ||
|
r41040 | opt_output = list(d[b'opts']) | ||
|
r6488 | if opt_output: | ||
opts_len = max([len(line[0]) for line in opt_output]) | ||||
|
r41040 | ui.write(_(b"Options:\n\n")) | ||
|
r20081 | multioccur = False | ||
|
r6488 | for optstr, desc in opt_output: | ||
if desc: | ||||
|
r41040 | s = b"%-*s %s" % (opts_len, optstr, desc) | ||
|
r6488 | else: | ||
s = optstr | ||||
|
r41040 | ui.write(b"%s\n" % s) | ||
if optstr.endswith(b"[+]>"): | ||||
|
r20081 | multioccur = True | ||
if multioccur: | ||||
|
r41040 | ui.write(_(b"\n[+] marked option can be specified" | ||
b" multiple times\n")) | ||||
ui.write(b"\n") | ||||
|
r6488 | # aliases | ||
|
r41040 | if d[b'aliases']: | ||
ui.write(_(b" aliases: %s\n\n") % b" ".join(d[b'aliases'])) | ||||
|
r1814 | |||
|
r3797 | |||
|
r12781 | def allextensionnames(): | ||
|
r41040 | return set(extensions.enabled().keys()) | set(extensions.disabled().keys()) | ||
|
r12781 | |||
|
r1814 | if __name__ == "__main__": | ||
|
r41040 | doc = b'hg.1.gendoc' | ||
|
r19425 | if len(sys.argv) > 1: | ||
|
r41059 | doc = encoding.strtolocal(sys.argv[1]) | ||
|
r19425 | |||
|
r30559 | ui = uimod.ui.load() | ||
|
r41040 | if doc == b'hg.1.gendoc': | ||
|
r26412 | showdoc(ui) | ||
|
r19425 | else: | ||
|
r26412 | showtopic(ui, sys.argv[1]) | ||