#!/usr/bin/env python
"""
Convert
scintilla/include/Scintilla.iface
to an HTML document.
./iface-to-doc.py \
scintilla/include/Scintilla.iface \
> ScintillaLua.html
"""
import re
def Parse_comment(line):
return line
def Parse_cat(line):
return line
Parse_fun_reLine = re.compile(r'(\S+)\s+(\S+?)\s*=\s*\d+\s*\(\s*(.*?)\s*\)')
def Parse_fun(line):
ret,name,args = Parse_fun_reLine.match(line).groups()
if ret == 'void':
ret = []
else:
ret = [ret]
args = [ i.strip() for i in args.split(',') ]
args = [ i.split() for i in args if i and i != 'void' ]
temp = args
args = []
for i in temp:
if i == ["int", "length"]: continue
if i and i[0] == "stringresult":
ret.insert(0, "string")
continue
args.append(i)
return ret, name, args
def Parse_get(line):
return Parse_fun(line)
def Parse_set(line):
return Parse_fun(line)
Parse_val_reLine = re.compile(r'(\S+?)\s*=\s*(.+)')
def Parse_val(line):
name, value = Parse_val_reLine.match(line).groups()
return name, value
def Parse_evt(line):
return Parse_fun(line)
def Parse_enu(line):
name, prefixes = Parse_val_reLine.match(line).groups()
return name, prefixes.split()
def Parse_lex(line):
name, prefixes = Parse_val_reLine.match(line).groups()
prefixes = prefixes.split()
value = prefixes[0] ; prefixes = prefixes[1:]
return name, value, prefixes
Parse = \
{ "#" : Parse_comment
, "cat": Parse_cat
, "fun": Parse_fun
, "get": Parse_get
, "set": Parse_set
, "val": Parse_val
, "evt": Parse_evt
, "enu": Parse_enu
, "lex": Parse_lex
}
def Phase1(sFileIn):
"""
Load a file and parse each line
"""
lines = dict()
reLine = re.compile(r'(\S+)\s+(.*)')
iLine = 0
for line in open(sFileIn):
line = line.strip()
iLine += 1
if not line:
lines[iLine] = ["", None]
continue
if line.startswith('##' ): continue
if line.startswith('#!' ): continue
type, line = reLine.match(line).groups()
lines[iLine] = [type, Parse[type](line)]
return lines
def Phase2(input):
"""
Attribute comments to their next line
`Commented' null lines will remain
"""
lines = dict()
currentComment = []
for line in sorted(input):
type, contents = input[line]
if type == '#':
currentComment.append(contents)
continue
if not currentComment and not type:
continue
theComment = ' '.join(currentComment)
currentComment = []
lines[line] = [type, contents, theComment]
return lines
def Phase3(input):
"""
Getters and Setters are united
Impossible getters and setters are re-marked as 'fun'
"""
getsets = dict()
for line, (type, contents, comment) in input.items():
if type == "get":
prop = contents[1].replace('Get', '', 1)
index = 0
elif type == "set":
prop = contents[1].replace('Set', '', 1)
index = 1
else:
continue
if prop not in getsets:
getsets[prop] = [None, None]
getsets[prop][index] = (line, contents, comment)
properties = dict()
for prop, (g,s) in getsets.items():
bOK = True
if g:
gline, (gret, gname, gargs), gcomment = g
if len(gret) != 1 or gargs: bOK = False
if s:
sline, (sret, sname, sargs), scomment = s
if sret or len(sargs) != 1: bOK = False
if g and s and bOK:
if gret[0] != sargs[0][0]:
print >> sys.stderr, "Warning: property getter and setter has different type:", gname
formline = min(gline, sline)
lattline = max(gline, sline)
comment = []
if gcomment: comment.append('R: ' + gcomment)
if scomment: comment.append('W: ' + scomment)
comment = '\n'.join(comment)
input[formline] = ["get", ('RW', ' '.join(sargs[0]), prop), comment]
del input[lattline]
continue
if g and bOK:
input[gline] = ["get", ('R', gret[0], prop), gcomment]
continue
if s and bOK:
input[sline] = ["get", ('W', ' '.join(sargs[0]), prop), scomment]
continue
if g:
input[gline][0] = "fun"
if s:
input[sline][0] = "fun"
return input
def Phase4(input):
"""
Unite val to enu and lex
"""
vals = dict()
enus = []
lexs = []
for line, (type, contents, comment) in input.items():
if type == "val":
vals[line] = (contents, comment)
elif type == "enu":
enus.append((line, contents, comment))
elif type == "lex":
lexs.append((line, contents, comment))
deletedLines = set()
for line, (name, prefixes), comment in enus:
members = dict()
for vline, ((vname, vvalue), vcomment) in vals.items():
if any(vname.startswith(p) for p in prefixes):
members[vline] = (vname, vvalue, vcomment)
deletedLines.add(vline)
members = [members[k] for k in sorted(members)]
input[line] = ["enu", (name, members), comment]
for line, (name, value, prefixes), comment in lexs:
members = dict()
for vline, ((vname, vvalue), vcomment) in vals.items():
if any(vname.startswith(p) for p in prefixes):
members[vline] = (vname, vvalue, vcomment)
deletedLines.add(vline)
members = [members[k] for k in sorted(members)]
input[line] = ["lex", (name, value, members), comment]
for line in deletedLines:
del input[line]
return input
EscapeHTML_re = re.compile(r'[<>&\n]')
EscapeHTML_dict = {'<': '<', '>': '>', '&': '&', '\n': '
\n'}
def EscapeHTML(text):
"""
\n ->
<>& -> <>&
"""
return EscapeHTML_re.sub \
( lambda m: EscapeHTML_dict[m.group()]
, text
)
def ToHTML_comment(contents, comment):
return '
%s
' % EscapeHTML(comment) def ToHTML_cat(contents, comment): header = '%s
' % EscapeHTML(comment) return header def ToHTML_fun(contents, comment): ret, name, args = contents if ret: ret = ' : ' + ', '.join(ret) else: ret = '' args = [' '.join(i) for i in args] args = ', '.join(args) return '\n'.join \ ([ 'Those reddish are constants. They are global.
Those bluish are methods of the objects 'editor' and 'output'. They are called like 'editor:AddText("_")'
Those greenish are properties of 'editor' and 'output'; either 'R' (readable) or 'W' (writable) or both. They are accessed like 'editor.TabWidth = 20'
This document is a simple conversion of Scintilla's interface file, the license of which is noted in Scintilla License.
""" def Phase5(input): """ lines to to Html elements """ htmls = [] for line in sorted(input): type, contents, comment = input[line] elem = ToHTML[type](contents, comment) if elem: htmls.append(elem) return htmls def main(): import os import sys sSrcTopDir = sys.argv[1] sIFaceFile = os.path.join\ ( sSrcTopDir, "scintilla", "include", "Scintilla.iface" ) lines = Phase1(sIFaceFile) lines = Phase2(lines) lines = Phase3(lines) lines = Phase4(lines) htmls = Phase5(lines) print ToHTML_header for elem in htmls: print elem print ToHTML_footer main()