3 # This script will check the documentation consistency against the code. It
4 # doesn't check the actual accuracy of the documentation, it just ensures that
5 # everything is documented and that nothing which doesn't exist in Conky
6 # appears in the documentation.
8 # This script also updates the vim and nano syntax files so it doesn't have to
11 # Requires the ElementTree Python module for the sorting stuff, see:
12 # http://effbot.org/zone/element-index.htm
14 # You should also install htmltidy, but it's not necessary.
21 from datetime import *
24 file_names["text_objects"] = "src/text_object.h"
25 file_names["conky"] = "src/conky.c"
26 file_names["vim_syntax"] = "extras/vim/syntax/conkyrc.vim"
27 file_names["nano_syntax"] = "extras/nano/conky.nanorc"
28 file_names["variables"] = "doc/variables.xml"
29 file_names["config_settings"] = "doc/config_settings.xml"
30 file_names["lua"] = "doc/lua.xml"
31 file_names["docs"] = "doc/docs.xml"
32 file_names["command_options"] = "doc/command_options.xml"
34 for fn in file_names.values():
35 if not os.path.exists(fn) or not os.path.isfile(fn):
36 print "'%s' doesn't exist, or isn't a file" % (fn)
39 print 'sorting/tidying docs...'
41 # sort the docs by variable/config setting
43 import xml.etree.ElementTree as ET
45 vars_xml = ET.parse(file_names['variables'])
46 config_xml = ET.parse(file_names['config_settings'])
48 getkey = lambda x: x.findtext('term/command/option')
50 vars = vars_xml.getroot()
51 vars[:] = sorted(vars, key=getkey)
53 configs = config_xml.getroot()
54 configs[:] = sorted(configs, key=getkey)
56 vars_xml.write(file_names['variables'])
57 config_xml.write(file_names['config_settings'])
60 command = ['tidy', '-qim', '-xml', '-utf8', '--indent-spaces', '4']
61 os.system('%s %s 2>/dev/null' % (string.join(command), file))
63 tidy(file_names['variables'])
64 tidy(file_names['config_settings'])
65 tidy(file_names['lua'])
66 tidy(file_names['command_options'])
69 # Do all the objects first
74 file = open(file_names["text_objects"], "r")
75 exp = re.compile("\s*OBJ_(\w*).*")
77 line = file.readline()
83 if not re.match("color\d", obj) and obj != "text":
84 # ignore colourN stuff
85 objects.append(res.group(1))
87 print 'counted %i text objects' % len(objects)
90 exp = re.compile("\s*<command><option>(\w*)</option></command>.*")
91 print "checking docs -> objs consistency (in %s)" % (file_names["text_objects"])
94 doc_objects.append(term)
95 if ['templaten', 'colorn'].count(doc_objects[len(doc_objects) - 1].lower()):
98 if doc_objects[len(doc_objects) - 1] not in objects:
99 print " '%s' is documented, but doesn't seem to be an object" % (doc_objects[len(doc_objects) - 1])
102 print "checking objs -> docs consistency (in %s)" % (file_names["variables"])
104 if obj not in doc_objects:
105 print " '%s' seems to be undocumented" % (obj)
109 # Now we'll do config settings
114 file = open(file_names["conky"], "r")
115 exp1 = re.compile('\s*CONF\("(\w*)".*')
116 exp2 = re.compile('\s*CONF2\("(\w*)".*')
117 exp3 = re.compile('\s*CONF3\("(\w*)".*')
119 line = file.readline()
122 res = exp1.match(line)
124 res = exp2.match(line)
126 res = exp3.match(line)
129 if re.match("color\d", conf):
131 if config_entries.count(conf) == 0:
132 config_entries.append(conf)
134 print 'counted %i config settings' % len(config_entries)
137 print "checking docs -> configs consistency (in %s)" % (file_names["conky"])
138 for config in configs:
139 term = getkey(config)
140 doc_configs.append(term)
141 if ['text', 'templaten'].count(doc_configs[len(doc_configs) - 1].lower()):
144 if doc_configs[len(doc_configs) - 1] not in config_entries:
145 print " '%s' is documented, but doesn't seem to be a config setting" % (doc_configs[len(doc_configs) - 1])
148 print "checking configs -> docs consistency (in %s)" % (file_names["config_settings"])
149 for obj in config_entries:
150 if obj != "text" and obj != "template" and obj not in doc_configs:
151 print " '%s' seems to be undocumented" % (obj)
156 # Cheat and add the colour/template stuff.
158 for i in range(0, 10):
159 objects.append("color" + str(i))
160 config_entries.append("color" + str(i))
161 objects.append("template" + str(i))
162 config_entries.append("template" + str(i))
164 # Finally, sort everything.
166 config_entries.sort()
169 # Update nano syntax stuff
172 print "updating nano syntax...",
174 file = open(file_names["nano_syntax"], "rw+")
177 line = file.readline()
182 # find the line we want to update
184 if re.match("color green ", line):
185 idx = lines.index(line)
186 lines.pop(idx) # remove old line
187 line = 'color green "\<('
188 for obj in config_entries:
189 line += "%s|" % (obj)
190 line = line[:len(line) - 1]
192 lines.insert(idx, line)
193 if re.match("color brightblue ", line):
194 idx = lines.index(line)
195 lines.pop(idx) # remove old line
196 line = 'color brightblue "\<('
198 line += "%s|" % (obj)
199 line = line[:len(line) - 1]
201 lines.insert(idx, line)
202 break # want to ignore everything after this line
205 file.writelines(lines)
210 # Update vim syntax stuff
213 print "updating vim syntax...",
215 file = open(file_names["vim_syntax"], "rw+")
218 line = file.readline()
223 # find the line we want to update
225 if re.match("syn keyword ConkyrcSetting ", line):
226 idx = lines.index(line)
227 lines.pop(idx) # remove old line
228 line = 'syn keyword ConkyrcSetting '
229 for obj in config_entries:
230 line += "%s " % (obj)
231 line = line[:len(line) - 1]
233 lines.insert(idx, line)
234 if re.match("syn keyword ConkyrcVarName contained nextgroup=ConkyrcNumber,ConkyrcColour skipwhite ", line):
235 idx = lines.index(line)
236 lines.pop(idx) # remove old line
237 line = 'syn keyword ConkyrcVarName contained nextgroup=ConkyrcNumber,ConkyrcColour skipwhite '
239 line += "%s " % (obj)
240 line = line[:len(line) - 1]
242 lines.insert(idx, line)
243 break # want to ignore everything after this line
246 file.writelines(lines)
249 # lastly, update the date in docs.xml
250 file = open(file_names["docs"], 'r+')
251 map = mmap.mmap(file.fileno(), os.path.getsize(file_names["docs"]))
252 d = map.find("<date>")
253 d += 6 # skip over first date stuff
254 map[d:d+10] = datetime.now().strftime("%F")