check-seclevel.py
168 lines
| 5.8 KiB
| text/x-python
|
PythonLexer
/ doc / check-seclevel.py
|
r17648 | #!/usr/bin/env python | ||
# | ||||
|
r26192 | # checkseclevel - checking section title levels in each online help document | ||
|
r17648 | |||
import sys, os | ||||
import optparse | ||||
# import from the live mercurial repo | ||||
|
r27221 | os.environ['HGMODULEPOLICY'] = 'py' | ||
|
r17648 | sys.path.insert(0, "..") | ||
from mercurial import demandimport; demandimport.enable() | ||||
from mercurial.commands import table | ||||
from mercurial.help import helptable | ||||
from mercurial import extensions | ||||
from mercurial import minirst | ||||
|
r26411 | from mercurial import ui as uimod | ||
|
r17648 | |||
level2mark = ['"', '=', '-', '.', '#'] | ||||
reservedmarks = ['"'] | ||||
mark2level = {} | ||||
for m, l in zip(level2mark, xrange(len(level2mark))): | ||||
if m not in reservedmarks: | ||||
mark2level[m] = l | ||||
initlevel_topic = 0 | ||||
initlevel_cmd = 1 | ||||
initlevel_ext = 1 | ||||
initlevel_ext_cmd = 3 | ||||
|
r26411 | def showavailables(ui, initlevel): | ||
ui.warn((' available marks and order of them in this help: %s\n') % | ||||
(', '.join(['%r' % (m * 4) for m in level2mark[initlevel + 1:]]))) | ||||
|
r17648 | |||
|
r26411 | def checkseclevel(ui, doc, name, initlevel): | ||
ui.note(('checking "%s"\n') % name) | ||||
|
r17648 | blocks, pruned = minirst.parse(doc, 0, ['verbose']) | ||
errorcnt = 0 | ||||
curlevel = initlevel | ||||
for block in blocks: | ||||
if block['type'] != 'section': | ||||
continue | ||||
mark = block['underline'] | ||||
title = block['lines'][0] | ||||
if (mark not in mark2level) or (mark2level[mark] <= initlevel): | ||||
|
r26411 | ui.warn(('invalid section mark %r for "%s" of %s\n') % | ||
(mark * 4, title, name)) | ||||
showavailables(ui, initlevel) | ||||
|
r17648 | errorcnt += 1 | ||
continue | ||||
nextlevel = mark2level[mark] | ||||
if curlevel < nextlevel and curlevel + 1 != nextlevel: | ||||
|
r26411 | ui.warn(('gap of section level at "%s" of %s\n') % | ||
(title, name)) | ||||
showavailables(ui, initlevel) | ||||
|
r17648 | errorcnt += 1 | ||
continue | ||||
|
r26411 | ui.note(('appropriate section level for "%s %s"\n') % | ||
|
r17648 | (mark * (nextlevel * 2), title)) | ||
curlevel = nextlevel | ||||
return errorcnt | ||||
|
r26411 | def checkcmdtable(ui, cmdtable, namefmt, initlevel): | ||
|
r17648 | errorcnt = 0 | ||
for k, entry in cmdtable.items(): | ||||
name = k.split("|")[0].lstrip("^") | ||||
if not entry[0].__doc__: | ||||
|
r26411 | ui.note(('skip checking %s: no help document\n') % | ||
|
r17648 | (namefmt % name)) | ||
continue | ||||
|
r26411 | errorcnt += checkseclevel(ui, entry[0].__doc__, | ||
|
r17648 | namefmt % name, | ||
initlevel) | ||||
return errorcnt | ||||
|
r26411 | def checkhghelps(ui): | ||
|
r17648 | errorcnt = 0 | ||
for names, sec, doc in helptable: | ||||
|
r21792 | if callable(doc): | ||
|
r26413 | doc = doc(ui) | ||
|
r26411 | errorcnt += checkseclevel(ui, doc, | ||
|
r17648 | '%s help topic' % names[0], | ||
initlevel_topic) | ||||
|
r26411 | errorcnt += checkcmdtable(ui, table, '%s command', initlevel_cmd) | ||
|
r17648 | |||
for name in sorted(extensions.enabled().keys() + | ||||
extensions.disabled().keys()): | ||||
mod = extensions.load(None, name, None) | ||||
if not mod.__doc__: | ||||
|
r26411 | ui.note(('skip checking %s extension: no help document\n') % name) | ||
|
r17648 | continue | ||
|
r26411 | errorcnt += checkseclevel(ui, mod.__doc__, | ||
|
r17648 | '%s extension' % name, | ||
initlevel_ext) | ||||
cmdtable = getattr(mod, 'cmdtable', None) | ||||
if cmdtable: | ||||
|
r26411 | errorcnt += checkcmdtable(ui, cmdtable, | ||
|
r17648 | '%s command of ' + name + ' extension', | ||
initlevel_ext_cmd) | ||||
return errorcnt | ||||
|
r26411 | def checkfile(ui, filename, initlevel): | ||
|
r17648 | if filename == '-': | ||
filename = 'stdin' | ||||
doc = sys.stdin.read() | ||||
else: | ||||
fp = open(filename) | ||||
try: | ||||
doc = fp.read() | ||||
finally: | ||||
fp.close() | ||||
|
r26411 | ui.note(('checking input from %s with initlevel %d\n') % | ||
|
r17648 | (filename, initlevel)) | ||
|
r26411 | return checkseclevel(ui, doc, 'input from %s' % filename, initlevel) | ||
|
r17648 | |||
|
r26398 | def main(): | ||
|
r17648 | optparser = optparse.OptionParser("""%prog [options] | ||
This checks all help documents of Mercurial (topics, commands, | ||||
extensions and commands of them), if no file is specified by --file | ||||
option. | ||||
""") | ||||
optparser.add_option("-v", "--verbose", | ||||
help="enable additional output", | ||||
action="store_true") | ||||
|
r27510 | optparser.add_option("-d", "--debug", | ||
help="debug mode", | ||||
action="store_true") | ||||
|
r17648 | optparser.add_option("-f", "--file", | ||
help="filename to read in (or '-' for stdin)", | ||||
action="store", default="") | ||||
optparser.add_option("-t", "--topic", | ||||
help="parse file as help topic", | ||||
action="store_const", dest="initlevel", const=0) | ||||
optparser.add_option("-c", "--command", | ||||
help="parse file as help of core command", | ||||
action="store_const", dest="initlevel", const=1) | ||||
optparser.add_option("-e", "--extension", | ||||
help="parse file as help of extension", | ||||
action="store_const", dest="initlevel", const=1) | ||||
optparser.add_option("-C", "--extension-command", | ||||
help="parse file as help of extension command", | ||||
action="store_const", dest="initlevel", const=3) | ||||
optparser.add_option("-l", "--initlevel", | ||||
help="set initial section level manually", | ||||
action="store", type="int", default=0) | ||||
(options, args) = optparser.parse_args() | ||||
|
r26411 | ui = uimod.ui() | ||
ui.setconfig('ui', 'verbose', options.verbose, '--verbose') | ||||
|
r27510 | ui.setconfig('ui', 'debug', options.debug, '--debug') | ||
|
r17648 | |||
if options.file: | ||||
|
r26411 | if checkfile(ui, options.file, options.initlevel): | ||
|
r17648 | sys.exit(1) | ||
else: | ||||
|
r26411 | if checkhghelps(ui): | ||
|
r17648 | sys.exit(1) | ||
|
r26398 | |||
if __name__ == "__main__": | ||||
main() | ||||