##// END OF EJS Templates
check-seclevel: use ui to show status and error messages...
Yuya Nishihara -
r26411:dd62eaa8 default
parent child Browse files
Show More
@@ -1,173 +1,165 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # checkseclevel - checking section title levels in each online help document
3 # checkseclevel - checking section title levels in each online help document
4
4
5 import sys, os
5 import sys, os
6 import optparse
6 import optparse
7
7
8 # import from the live mercurial repo
8 # import from the live mercurial repo
9 sys.path.insert(0, "..")
9 sys.path.insert(0, "..")
10 # fall back to pure modules if required C extensions are not available
10 # fall back to pure modules if required C extensions are not available
11 sys.path.append(os.path.join('..', 'mercurial', 'pure'))
11 sys.path.append(os.path.join('..', 'mercurial', 'pure'))
12 from mercurial import demandimport; demandimport.enable()
12 from mercurial import demandimport; demandimport.enable()
13 from mercurial.commands import table
13 from mercurial.commands import table
14 from mercurial.help import helptable
14 from mercurial.help import helptable
15 from mercurial import extensions
15 from mercurial import extensions
16 from mercurial import minirst
16 from mercurial import minirst
17
17 from mercurial import ui as uimod
18 _verbose = False
19
20 def verbose(msg):
21 if _verbose:
22 print msg
23
24 def error(msg):
25 sys.stderr.write('%s\n' % msg)
26
18
27 level2mark = ['"', '=', '-', '.', '#']
19 level2mark = ['"', '=', '-', '.', '#']
28 reservedmarks = ['"']
20 reservedmarks = ['"']
29
21
30 mark2level = {}
22 mark2level = {}
31 for m, l in zip(level2mark, xrange(len(level2mark))):
23 for m, l in zip(level2mark, xrange(len(level2mark))):
32 if m not in reservedmarks:
24 if m not in reservedmarks:
33 mark2level[m] = l
25 mark2level[m] = l
34
26
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()
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 def 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.
135 """)
127 """)
136 optparser.add_option("-v", "--verbose",
128 optparser.add_option("-v", "--verbose",
137 help="enable additional output",
129 help="enable additional output",
138 action="store_true")
130 action="store_true")
139 optparser.add_option("-f", "--file",
131 optparser.add_option("-f", "--file",
140 help="filename to read in (or '-' for stdin)",
132 help="filename to read in (or '-' for stdin)",
141 action="store", default="")
133 action="store", default="")
142
134
143 optparser.add_option("-t", "--topic",
135 optparser.add_option("-t", "--topic",
144 help="parse file as help topic",
136 help="parse file as help topic",
145 action="store_const", dest="initlevel", const=0)
137 action="store_const", dest="initlevel", const=0)
146 optparser.add_option("-c", "--command",
138 optparser.add_option("-c", "--command",
147 help="parse file as help of core command",
139 help="parse file as help of core command",
148 action="store_const", dest="initlevel", const=1)
140 action="store_const", dest="initlevel", const=1)
149 optparser.add_option("-e", "--extension",
141 optparser.add_option("-e", "--extension",
150 help="parse file as help of extension",
142 help="parse file as help of extension",
151 action="store_const", dest="initlevel", const=1)
143 action="store_const", dest="initlevel", const=1)
152 optparser.add_option("-C", "--extension-command",
144 optparser.add_option("-C", "--extension-command",
153 help="parse file as help of extension command",
145 help="parse file as help of extension command",
154 action="store_const", dest="initlevel", const=3)
146 action="store_const", dest="initlevel", const=3)
155
147
156 optparser.add_option("-l", "--initlevel",
148 optparser.add_option("-l", "--initlevel",
157 help="set initial section level manually",
149 help="set initial section level manually",
158 action="store", type="int", default=0)
150 action="store", type="int", default=0)
159
151
160 (options, args) = optparser.parse_args()
152 (options, args) = optparser.parse_args()
161
153
162 global _verbose
154 ui = uimod.ui()
163 _verbose = options.verbose
155 ui.setconfig('ui', 'verbose', options.verbose, '--verbose')
164
156
165 if options.file:
157 if options.file:
166 if checkfile(options.file, options.initlevel):
158 if checkfile(ui, options.file, options.initlevel):
167 sys.exit(1)
159 sys.exit(1)
168 else:
160 else:
169 if checkhghelps():
161 if checkhghelps(ui):
170 sys.exit(1)
162 sys.exit(1)
171
163
172 if __name__ == "__main__":
164 if __name__ == "__main__":
173 main()
165 main()
General Comments 0
You need to be logged in to leave comments. Login now