forked from brndnmtthws/conky
-
Notifications
You must be signed in to change notification settings - Fork 0
/
check_docs.py
executable file
·258 lines (223 loc) · 6.88 KB
/
check_docs.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
#!/usr/bin/python
#
# This script will check the documentation consistency against the code. It
# doesn't check the actual accuracy of the documentation, it just ensures that
# everything is documented and that nothing which doesn't exist in Conky
# appears in the documentation.
#
# This script also updates the vim and nano syntax files so it doesn't have to
# be done manually.
#
# Requires the ElementTree Python module for the sorting stuff, see:
# http://effbot.org/zone/element-index.htm
#
# You should also install htmltidy, but it's not necessary.
#
import os.path
import re
import sys
import mmap
from datetime import *
file_names = dict()
file_names["text_objects"] = "src/text_object.h"
file_names["conky"] = "src/conky.c"
file_names["vim_syntax"] = "extras/vim/syntax/conkyrc.vim"
file_names["nano_syntax"] = "extras/nano/conky.nanorc"
file_names["variables"] = "doc/variables.xml"
file_names["config_settings"] = "doc/config_settings.xml"
file_names["lua"] = "doc/lua.xml"
file_names["docs"] = "doc/docs.xml"
file_names["command_options"] = "doc/command_options.xml"
for fn in file_names.values():
if not os.path.exists(fn) or not os.path.isfile(fn):
print "'%s' doesn't exist, or isn't a file" % (fn)
exit(1)
print 'sorting/tidying docs...'
# sort the docs by variable/config setting
import string
import xml.etree.ElementTree as ET
vars_xml = ET.parse(file_names['variables'])
config_xml = ET.parse(file_names['config_settings'])
getkey = lambda x: x.findtext('term/command/option')
vars = vars_xml.getroot()
vars[:] = sorted(vars, key=getkey)
configs = config_xml.getroot()
configs[:] = sorted(configs, key=getkey)
vars_xml.write(file_names['variables'])
config_xml.write(file_names['config_settings'])
def tidy(file):
command = ['tidy', '-qim', '-xml', '-utf8', '--indent-spaces', '4']
os.system('%s %s 2>/dev/null' % (string.join(command), file))
tidy(file_names['variables'])
tidy(file_names['config_settings'])
tidy(file_names['lua'])
tidy(file_names['command_options'])
#
# Do all the objects first
#
objects = []
file = open(file_names["text_objects"], "r")
exp = re.compile("\s*OBJ_(\w*).*")
while file:
line = file.readline()
if len(line) == 0:
break
res = exp.match(line)
if res:
obj = res.group(1)
if not re.match("color\d", obj) and obj != "text":
# ignore colourN stuff
objects.append(res.group(1))
file.close()
print 'counted %i text objects' % len(objects)
doc_objects = []
exp = re.compile("\s*<command><option>(\w*)</option></command>.*")
print "checking docs -> objs consistency (in %s)" % (file_names["text_objects"])
for var in vars:
term = getkey(var)
doc_objects.append(term)
if ['templaten', 'colorn'].count(doc_objects[len(doc_objects) - 1].lower()):
# ignore these
continue
if doc_objects[len(doc_objects) - 1] not in objects:
print " '%s' is documented, but doesn't seem to be an object" % (doc_objects[len(doc_objects) - 1])
print "done\n"
print "checking objs -> docs consistency (in %s)" % (file_names["variables"])
for obj in objects:
if obj not in doc_objects:
print " '%s' seems to be undocumented" % (obj)
print "done\n"
#
# Now we'll do config settings
#
config_entries = []
file = open(file_names["conky"], "r")
exp1 = re.compile('\s*CONF\("(\w*)".*')
exp2 = re.compile('\s*CONF2\("(\w*)".*')
exp3 = re.compile('\s*CONF3\("(\w*)".*')
while file:
line = file.readline()
if len(line) == 0:
break
res = exp1.match(line)
if not res:
res = exp2.match(line)
if not res:
res = exp3.match(line)
if res:
conf = res.group(1)
if re.match("color\d", conf):
conf = "colorN"
if config_entries.count(conf) == 0:
config_entries.append(conf)
file.close()
print 'counted %i config settings' % len(config_entries)
doc_configs = []
print "checking docs -> configs consistency (in %s)" % (file_names["conky"])
for config in configs:
term = getkey(config)
doc_configs.append(term)
if ['text', 'templaten'].count(doc_configs[len(doc_configs) - 1].lower()):
# ignore these
continue
if doc_configs[len(doc_configs) - 1] not in config_entries:
print " '%s' is documented, but doesn't seem to be a config setting" % (doc_configs[len(doc_configs) - 1])
print "done\n"
print "checking configs -> docs consistency (in %s)" % (file_names["config_settings"])
for obj in config_entries:
if obj != "text" and obj != "template" and obj not in doc_configs:
print " '%s' seems to be undocumented" % (obj)
print "done\n"
# Cheat and add the colour/template stuff.
for i in range(0, 10):
objects.append("color" + str(i))
config_entries.append("color" + str(i))
objects.append("template" + str(i))
config_entries.append("template" + str(i))
# Finally, sort everything.
objects.sort()
config_entries.sort()
#
# Update nano syntax stuff
#
print "updating nano syntax...",
sys.stdout.flush()
file = open(file_names["nano_syntax"], "rw+")
lines = []
while file:
line = file.readline()
if len(line) == 0:
break
lines.append(line)
# find the line we want to update
for line in lines:
if re.match("color green ", line):
idx = lines.index(line)
lines.pop(idx) # remove old line
line = 'color green "\<('
for obj in config_entries:
line += "%s|" % (obj)
line = line[:len(line) - 1]
line += ')\>"\n'
lines.insert(idx, line)
if re.match("color brightblue ", line):
idx = lines.index(line)
lines.pop(idx) # remove old line
line = 'color brightblue "\<('
for obj in objects:
line += "%s|" % (obj)
line = line[:len(line) - 1]
line += ')\>"\n'
lines.insert(idx, line)
break # want to ignore everything after this line
file.truncate(0)
file.seek(0)
file.writelines(lines)
file.close()
print "done."
#
# Update vim syntax stuff
#
print "updating vim syntax...",
sys.stdout.flush()
file = open(file_names["vim_syntax"], "rw+")
lines = []
while file:
line = file.readline()
if len(line) == 0:
break
lines.append(line)
# find the line we want to update
for line in lines:
if re.match("syn keyword ConkyrcSetting ", line):
idx = lines.index(line)
lines.pop(idx) # remove old line
line = 'syn keyword ConkyrcSetting '
for obj in config_entries:
line += "%s " % (obj)
line = line[:len(line) - 1]
line += '\n'
lines.insert(idx, line)
if re.match("syn keyword ConkyrcVarName contained nextgroup=ConkyrcNumber,ConkyrcColour skipwhite ", line):
idx = lines.index(line)
lines.pop(idx) # remove old line
line = 'syn keyword ConkyrcVarName contained nextgroup=ConkyrcNumber,ConkyrcColour skipwhite '
for obj in objects:
line += "%s " % (obj)
line = line[:len(line) - 1]
line += '\n'
lines.insert(idx, line)
break # want to ignore everything after this line
file.truncate(0)
file.seek(0)
file.writelines(lines)
file.close()
# lastly, update the date in docs.xml
file = open(file_names["docs"], 'r+')
map = mmap.mmap(file.fileno(), os.path.getsize(file_names["docs"]))
d = map.find("<date>")
d += 6 # skip over first date stuff
map[d:d+10] = datetime.now().strftime("%F")
map.close()
file.close()
print "done."