35 initlevel_topic = 0 |
27 initlevel_topic = 0 |
36 initlevel_cmd = 1 |
28 initlevel_cmd = 1 |
37 initlevel_ext = 1 |
29 initlevel_ext = 1 |
38 initlevel_ext_cmd = 3 |
30 initlevel_ext_cmd = 3 |
39 |
31 |
40 def showavailables(initlevel): |
32 def showavailables(ui, initlevel): |
41 error(' available marks and order of them in this help: %s' % |
33 ui.warn((' available marks and order of them in this help: %s\n') % |
42 (', '.join(['%r' % (m * 4) for m in level2mark[initlevel + 1:]]))) |
34 (', '.join(['%r' % (m * 4) for m in level2mark[initlevel + 1:]]))) |
43 |
35 |
44 def checkseclevel(doc, name, initlevel): |
36 def checkseclevel(ui, doc, name, initlevel): |
45 verbose('checking "%s"' % name) |
37 ui.note(('checking "%s"\n') % name) |
46 blocks, pruned = minirst.parse(doc, 0, ['verbose']) |
38 blocks, pruned = minirst.parse(doc, 0, ['verbose']) |
47 errorcnt = 0 |
39 errorcnt = 0 |
48 curlevel = initlevel |
40 curlevel = initlevel |
49 for block in blocks: |
41 for block in blocks: |
50 if block['type'] != 'section': |
42 if block['type'] != 'section': |
51 continue |
43 continue |
52 mark = block['underline'] |
44 mark = block['underline'] |
53 title = block['lines'][0] |
45 title = block['lines'][0] |
54 if (mark not in mark2level) or (mark2level[mark] <= initlevel): |
46 if (mark not in mark2level) or (mark2level[mark] <= initlevel): |
55 error('invalid section mark %r for "%s" of %s' % |
47 ui.warn(('invalid section mark %r for "%s" of %s\n') % |
56 (mark * 4, title, name)) |
48 (mark * 4, title, name)) |
57 showavailables(initlevel) |
49 showavailables(ui, initlevel) |
58 errorcnt += 1 |
50 errorcnt += 1 |
59 continue |
51 continue |
60 nextlevel = mark2level[mark] |
52 nextlevel = mark2level[mark] |
61 if curlevel < nextlevel and curlevel + 1 != nextlevel: |
53 if curlevel < nextlevel and curlevel + 1 != nextlevel: |
62 error('gap of section level at "%s" of %s' % |
54 ui.warn(('gap of section level at "%s" of %s\n') % |
63 (title, name)) |
55 (title, name)) |
64 showavailables(initlevel) |
56 showavailables(ui, initlevel) |
65 errorcnt += 1 |
57 errorcnt += 1 |
66 continue |
58 continue |
67 verbose('appropriate section level for "%s %s"' % |
59 ui.note(('appropriate section level for "%s %s"\n') % |
68 (mark * (nextlevel * 2), title)) |
60 (mark * (nextlevel * 2), title)) |
69 curlevel = nextlevel |
61 curlevel = nextlevel |
70 |
62 |
71 return errorcnt |
63 return errorcnt |
72 |
64 |
73 def checkcmdtable(cmdtable, namefmt, initlevel): |
65 def checkcmdtable(ui, cmdtable, namefmt, initlevel): |
74 errorcnt = 0 |
66 errorcnt = 0 |
75 for k, entry in cmdtable.items(): |
67 for k, entry in cmdtable.items(): |
76 name = k.split("|")[0].lstrip("^") |
68 name = k.split("|")[0].lstrip("^") |
77 if not entry[0].__doc__: |
69 if not entry[0].__doc__: |
78 verbose('skip checking %s: no help document' % |
70 ui.note(('skip checking %s: no help document\n') % |
79 (namefmt % name)) |
71 (namefmt % name)) |
80 continue |
72 continue |
81 errorcnt += checkseclevel(entry[0].__doc__, |
73 errorcnt += checkseclevel(ui, entry[0].__doc__, |
82 namefmt % name, |
74 namefmt % name, |
83 initlevel) |
75 initlevel) |
84 return errorcnt |
76 return errorcnt |
85 |
77 |
86 def checkhghelps(): |
78 def checkhghelps(ui): |
87 errorcnt = 0 |
79 errorcnt = 0 |
88 for names, sec, doc in helptable: |
80 for names, sec, doc in helptable: |
89 if callable(doc): |
81 if callable(doc): |
90 doc = doc() |
82 doc = doc(ui) |
91 errorcnt += checkseclevel(doc, |
83 errorcnt += checkseclevel(ui, doc, |
92 '%s help topic' % names[0], |
84 '%s help topic' % names[0], |
93 initlevel_topic) |
85 initlevel_topic) |
94 |
86 |
95 errorcnt += checkcmdtable(table, '%s command', initlevel_cmd) |
87 errorcnt += checkcmdtable(ui, table, '%s command', initlevel_cmd) |
96 |
88 |
97 for name in sorted(extensions.enabled().keys() + |
89 for name in sorted(extensions.enabled().keys() + |
98 extensions.disabled().keys()): |
90 extensions.disabled().keys()): |
99 mod = extensions.load(None, name, None) |
91 mod = extensions.load(None, name, None) |
100 if not mod.__doc__: |
92 if not mod.__doc__: |
101 verbose('skip checking %s extension: no help document' % name) |
93 ui.note(('skip checking %s extension: no help document\n') % name) |
102 continue |
94 continue |
103 errorcnt += checkseclevel(mod.__doc__, |
95 errorcnt += checkseclevel(ui, mod.__doc__, |
104 '%s extension' % name, |
96 '%s extension' % name, |
105 initlevel_ext) |
97 initlevel_ext) |
106 |
98 |
107 cmdtable = getattr(mod, 'cmdtable', None) |
99 cmdtable = getattr(mod, 'cmdtable', None) |
108 if cmdtable: |
100 if cmdtable: |
109 errorcnt += checkcmdtable(cmdtable, |
101 errorcnt += checkcmdtable(ui, cmdtable, |
110 '%s command of ' + name + ' extension', |
102 '%s command of ' + name + ' extension', |
111 initlevel_ext_cmd) |
103 initlevel_ext_cmd) |
112 return errorcnt |
104 return errorcnt |
113 |
105 |
114 def checkfile(filename, initlevel): |
106 def checkfile(ui, filename, initlevel): |
115 if filename == '-': |
107 if filename == '-': |
116 filename = 'stdin' |
108 filename = 'stdin' |
117 doc = sys.stdin.read() |
109 doc = sys.stdin.read() |
118 else: |
110 else: |
119 fp = open(filename) |
111 fp = open(filename) |
120 try: |
112 try: |
121 doc = fp.read() |
113 doc = fp.read() |
122 finally: |
114 finally: |
123 fp.close() |
115 fp.close() |
124 |
116 |
125 verbose('checking input from %s with initlevel %d' % |
117 ui.note(('checking input from %s with initlevel %d\n') % |
126 (filename, initlevel)) |
118 (filename, initlevel)) |
127 return checkseclevel(doc, 'input from %s' % filename, initlevel) |
119 return checkseclevel(ui, doc, 'input from %s' % filename, initlevel) |
128 |
120 |
129 if __name__ == "__main__": |
121 def main(): |
130 optparser = optparse.OptionParser("""%prog [options] |
122 optparser = optparse.OptionParser("""%prog [options] |
131 |
123 |
132 This checks all help documents of Mercurial (topics, commands, |
124 This checks all help documents of Mercurial (topics, commands, |
133 extensions and commands of them), if no file is specified by --file |
125 extensions and commands of them), if no file is specified by --file |
134 option. |
126 option. |