2009-05-01 22:20:06 +00:00
|
|
|
#!/usr/bin/python
|
|
|
|
#
|
2009-05-10 05:25:11 +00:00
|
|
|
# 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.
|
2009-05-01 22:20:06 +00:00
|
|
|
#
|
2009-06-06 22:56:35 +00:00
|
|
|
# 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.
|
|
|
|
#
|
2009-05-01 22:20:06 +00:00
|
|
|
|
|
|
|
import os.path
|
|
|
|
import re
|
2009-05-10 05:25:11 +00:00
|
|
|
import sys
|
2009-07-20 23:32:56 +00:00
|
|
|
import mmap
|
|
|
|
from datetime import *
|
2009-05-01 22:20:06 +00:00
|
|
|
|
|
|
|
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"
|
2009-07-08 08:09:06 +00:00
|
|
|
file_names["lua"] = "doc/lua.xml"
|
|
|
|
file_names["docs"] = "doc/docs.xml"
|
|
|
|
file_names["command_options"] = "doc/command_options.xml"
|
2009-05-01 22:20:06 +00:00
|
|
|
|
|
|
|
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)
|
2009-06-08 03:23:35 +00:00
|
|
|
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'])
|
2009-07-08 08:09:06 +00:00
|
|
|
tidy(file_names['lua'])
|
|
|
|
tidy(file_names['command_options'])
|
2009-05-01 22:20:06 +00:00
|
|
|
|
2009-05-10 05:25:11 +00:00
|
|
|
#
|
|
|
|
# Do all the objects first
|
|
|
|
#
|
|
|
|
|
2009-05-01 22:20:06 +00:00
|
|
|
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))
|
2009-05-10 05:25:11 +00:00
|
|
|
file.close()
|
2009-06-13 21:05:06 +00:00
|
|
|
print 'counted %i text objects' % len(objects)
|
2009-05-01 22:20:06 +00:00
|
|
|
|
|
|
|
doc_objects = []
|
|
|
|
exp = re.compile("\s*<command><option>(\w*)</option></command>.*")
|
2009-05-10 05:25:11 +00:00
|
|
|
print "checking docs -> objs consistency (in %s)" % (file_names["text_objects"])
|
2009-06-08 03:23:35 +00:00
|
|
|
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])
|
2009-05-10 05:25:11 +00:00
|
|
|
print "done\n"
|
2009-05-01 22:20:06 +00:00
|
|
|
|
2009-05-10 05:25:11 +00:00
|
|
|
print "checking objs -> docs consistency (in %s)" % (file_names["variables"])
|
2009-05-01 22:20:06 +00:00
|
|
|
for obj in objects:
|
|
|
|
if obj not in doc_objects:
|
2009-05-10 05:25:11 +00:00
|
|
|
print " '%s' seems to be undocumented" % (obj)
|
|
|
|
print "done\n"
|
|
|
|
|
|
|
|
#
|
|
|
|
# Now we'll do config settings
|
|
|
|
#
|
|
|
|
|
2009-06-08 03:23:35 +00:00
|
|
|
config_entries = []
|
2009-05-10 05:25:11 +00:00
|
|
|
|
|
|
|
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"
|
2009-06-08 03:23:35 +00:00
|
|
|
if config_entries.count(conf) == 0:
|
|
|
|
config_entries.append(conf)
|
2009-05-10 05:25:11 +00:00
|
|
|
file.close()
|
2009-06-13 21:05:06 +00:00
|
|
|
print 'counted %i config settings' % len(config_entries)
|
2009-05-10 05:25:11 +00:00
|
|
|
|
|
|
|
doc_configs = []
|
|
|
|
print "checking docs -> configs consistency (in %s)" % (file_names["conky"])
|
2009-06-08 03:23:35 +00:00
|
|
|
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])
|
2009-05-10 05:25:11 +00:00
|
|
|
print "done\n"
|
|
|
|
|
|
|
|
print "checking configs -> docs consistency (in %s)" % (file_names["config_settings"])
|
2009-06-08 03:23:35 +00:00
|
|
|
for obj in config_entries:
|
2009-05-10 05:25:11 +00:00
|
|
|
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))
|
2009-06-08 03:23:35 +00:00
|
|
|
config_entries.append("color" + str(i))
|
2009-05-10 05:25:11 +00:00
|
|
|
objects.append("template" + str(i))
|
2009-06-08 03:23:35 +00:00
|
|
|
config_entries.append("template" + str(i))
|
2009-05-10 05:25:11 +00:00
|
|
|
|
|
|
|
# Finally, sort everything.
|
|
|
|
objects.sort()
|
2009-06-08 03:23:35 +00:00
|
|
|
config_entries.sort()
|
2009-05-10 05:25:11 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# 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 "\<('
|
2009-06-08 03:23:35 +00:00
|
|
|
for obj in config_entries:
|
2009-05-10 05:25:11 +00:00
|
|
|
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 '
|
2009-06-08 03:23:35 +00:00
|
|
|
for obj in config_entries:
|
2009-05-10 05:25:11 +00:00
|
|
|
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()
|
2009-06-06 22:56:35 +00:00
|
|
|
|
2009-07-20 23:32:56 +00:00
|
|
|
# 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()
|
|
|
|
|
2009-05-10 05:25:11 +00:00
|
|
|
print "done."
|