hgbook

annotate en/cmdref.py @ 307:fb5c0d56d7f1

Fix test 'tour'.

Executing 'tour' test now creates some files in /tmp to store the
revision numbers as they are created on the fly and appear in the output
files. When SVG files are to be converted to PNG or EPS files within the
Makefile, a tool 'fixsvg' will be invoked to substitute some placeholder
markup by the real version number which fits to the test output, before
the final conversion takes place.
author Guido Ostkamp <hg@ostkamp.fastmail.fm>
date Wed Aug 20 22:15:35 2008 +0200 (2008-08-20)
parents
children
rev   line source
bos@133 1 #!/usr/bin/env python
bos@133 2
bos@133 3 import getopt
bos@133 4 import itertools
bos@133 5 import os
bos@133 6 import re
bos@133 7 import sys
bos@133 8
bos@133 9 def usage(exitcode):
bos@133 10 print >> sys.stderr, ('usage: %s [-H|--hidden] hg_repo' %
bos@133 11 os.path.basename(sys.argv[0]))
bos@133 12 sys.exit(exitcode)
bos@133 13
bos@133 14 try:
bos@133 15 opts, args = getopt.getopt(sys.argv[1:], 'AHh?', ['all', 'help', 'hidden'])
bos@133 16 opt_all = False
bos@133 17 opt_hidden = False
bos@133 18 for o, a in opts:
bos@133 19 if o in ('-h', '-?', '--help'):
bos@133 20 usage(0)
bos@133 21 if o in ('-A', '--all'):
bos@133 22 opt_all = True
bos@133 23 if o in ('-H', '--hidden'):
bos@133 24 opt_hidden = True
bos@133 25 except getopt.GetoptError, err:
bos@133 26 print >> sys.stderr, 'error:', err
bos@133 27 usage(1)
bos@133 28
bos@133 29 try:
bos@133 30 hg_repo, ltx_file = args
bos@133 31 except ValueError:
bos@133 32 usage(1)
bos@133 33
bos@133 34 if not os.path.isfile(os.path.join(hg_repo, 'mercurial', 'commands.py')):
bos@133 35 print >> sys.stderr, ('error: %r does not contain mercurial code' %
bos@133 36 hg_repo)
bos@133 37 sys.exit(1)
bos@133 38
bos@133 39 sys.path.insert(0, hg_repo)
bos@133 40
bos@133 41 from mercurial import commands
bos@133 42
bos@133 43 def get_commands():
bos@133 44 seen = {}
bos@133 45 for name, info in sorted(commands.table.iteritems()):
bos@133 46 aliases = name.split('|', 1)
bos@133 47 name = aliases.pop(0).lstrip('^')
bos@133 48 function, options, synopsis = info
bos@133 49 seen[name] = {}
bos@133 50 for shortopt, longopt, arg, desc in options:
bos@133 51 seen[name][longopt] = shortopt
bos@133 52 return seen
bos@133 53
bos@133 54 def cmd_filter((name, aliases, options)):
bos@133 55 if opt_all:
bos@133 56 return True
bos@133 57 if opt_hidden:
bos@133 58 return name.startswith('debug')
bos@133 59 return not name.startswith('debug')
bos@133 60
bos@133 61 def scan(ltx_file):
bos@133 62 cmdref_re = re.compile(r'^\\cmdref{(?P<cmd>\w+)}')
bos@133 63 optref_re = re.compile(r'^\\l?optref{(?P<cmd>\w+)}'
bos@133 64 r'(?:{(?P<short>[^}])})?'
bos@133 65 r'{(?P<long>[^}]+)}')
bos@133 66
bos@133 67 seen = {}
bos@133 68 locs = {}
bos@133 69 for lnum, line in enumerate(open(ltx_file)):
bos@133 70 m = cmdref_re.match(line)
bos@133 71 if m:
bos@133 72 d = m.groupdict()
bos@133 73 cmd = d['cmd']
bos@133 74 seen[cmd] = {}
bos@133 75 locs[cmd] = lnum + 1
bos@133 76 continue
bos@133 77 m = optref_re.match(line)
bos@133 78 if m:
bos@133 79 d = m.groupdict()
bos@133 80 seen[d['cmd']][d['long']] = d['short']
bos@133 81 continue
bos@133 82 return seen, locs
bos@133 83
bos@133 84 documented, locs = scan(ltx_file)
bos@133 85 known = get_commands()
bos@133 86
bos@133 87 doc_set = set(documented)
bos@133 88 known_set = set(known)
bos@133 89
bos@133 90 errors = 0
bos@133 91
bos@133 92 for nonexistent in sorted(doc_set.difference(known_set)):
bos@133 93 print >> sys.stderr, ('%s:%d: %r command does not exist' %
bos@133 94 (ltx_file, locs[nonexistent], nonexistent))
bos@133 95 errors += 1
bos@133 96
bos@133 97 def optcmp(a, b):
bos@133 98 la, sa = a
bos@133 99 lb, sb = b
bos@133 100 sc = cmp(sa, sb)
bos@133 101 if sc:
bos@133 102 return sc
bos@133 103 return cmp(la, lb)
bos@133 104
bos@133 105 for cmd in doc_set.intersection(known_set):
bos@133 106 doc_opts = documented[cmd]
bos@133 107 known_opts = known[cmd]
bos@133 108
bos@133 109 do_set = set(doc_opts)
bos@133 110 ko_set = set(known_opts)
bos@133 111
bos@133 112 for nonexistent in sorted(do_set.difference(ko_set)):
bos@133 113 print >> sys.stderr, ('%s:%d: %r option to %r command does not exist' %
bos@133 114 (ltx_file, locs[cmd], nonexistent, cmd))
bos@133 115 errors += 1
bos@133 116
bos@133 117 def mycmp(la, lb):
bos@133 118 sa = known_opts[la]
bos@133 119 sb = known_opts[lb]
bos@133 120 return optcmp((la, sa), (lb, sb))
bos@133 121
bos@133 122 for undocumented in sorted(ko_set.difference(do_set), cmp=mycmp):
bos@133 123 print >> sys.stderr, ('%s:%d: %r option to %r command not documented' %
bos@133 124 (ltx_file, locs[cmd], undocumented, cmd))
bos@133 125 shortopt = known_opts[undocumented]
bos@133 126 if shortopt:
bos@133 127 print '\optref{%s}{%s}{%s}' % (cmd, shortopt, undocumented)
bos@133 128 else:
bos@133 129 print '\loptref{%s}{%s}' % (cmd, undocumented)
bos@133 130 errors += 1
bos@133 131 sys.stdout.flush()
bos@133 132
bos@133 133 if errors:
bos@133 134 sys.exit(1)
bos@133 135
bos@133 136 sorted_locs = sorted(locs.iteritems(), key=lambda x:x[1])
bos@133 137
bos@133 138 def next_loc(cmd):
bos@133 139 for i, (name, loc) in enumerate(sorted_locs):
bos@133 140 if name >= cmd:
bos@133 141 return sorted_locs[i-1][1] + 1
bos@133 142 return loc
bos@133 143
bos@133 144 for undocumented in sorted(known_set.difference(doc_set)):
bos@133 145 print >> sys.stderr, ('%s:%d: %r command not documented' %
bos@133 146 (ltx_file, next_loc(undocumented), undocumented))
bos@133 147 print '\cmdref{%s}' % undocumented
bos@133 148 for longopt, shortopt in sorted(known[undocumented].items(), cmp=optcmp):
bos@133 149 if shortopt:
bos@133 150 print '\optref{%s}{%s}{%s}' % (undocumented, shortopt, longopt)
bos@133 151 else:
bos@133 152 print '\loptref{%s}{%s}' % (undocumented, longopt)
bos@133 153 sys.stdout.flush()
bos@133 154 errors += 1
bos@133 155
bos@133 156 sys.exit(errors and 1 or 0)