You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
4.9 KiB
121 lines
4.9 KiB
#!/usr/bin/env python |
|
''' |
|
simple templating system for mavlink generator |
|
|
|
Copyright Andrew Tridgell 2011 |
|
Released under GNU GPL version 3 or later |
|
''' |
|
|
|
from mavparse import MAVParseError |
|
|
|
class MAVTemplate(object): |
|
'''simple templating system''' |
|
def __init__(self, |
|
start_var_token="${", |
|
end_var_token="}", |
|
start_rep_token="${{", |
|
end_rep_token="}}", |
|
trim_leading_lf=True, |
|
checkmissing=True): |
|
self.start_var_token = start_var_token |
|
self.end_var_token = end_var_token |
|
self.start_rep_token = start_rep_token |
|
self.end_rep_token = end_rep_token |
|
self.trim_leading_lf = trim_leading_lf |
|
self.checkmissing = checkmissing |
|
|
|
def find_end(self, text, start_token, end_token): |
|
'''find the of a token. |
|
Returns the offset in the string immediately after the matching end_token''' |
|
if not text.startswith(start_token): |
|
raise MAVParseError("invalid token start") |
|
offset = len(start_token) |
|
nesting = 1 |
|
while nesting > 0: |
|
idx1 = text[offset:].find(start_token) |
|
idx2 = text[offset:].find(end_token) |
|
if idx1 == -1 and idx2 == -1: |
|
raise MAVParseError("token nesting error") |
|
if idx1 == -1 or idx1 > idx2: |
|
offset += idx2 + len(end_token) |
|
nesting -= 1 |
|
else: |
|
offset += idx1 + len(start_token) |
|
nesting += 1 |
|
return offset |
|
|
|
def find_var_end(self, text): |
|
'''find the of a variable''' |
|
return self.find_end(text, self.start_var_token, self.end_var_token) |
|
|
|
def find_rep_end(self, text): |
|
'''find the of a repitition''' |
|
return self.find_end(text, self.start_rep_token, self.end_rep_token) |
|
|
|
def substitute(self, text, subvars={}, |
|
trim_leading_lf=None, checkmissing=None): |
|
'''substitute variables in a string''' |
|
|
|
if trim_leading_lf is None: |
|
trim_leading_lf = self.trim_leading_lf |
|
if checkmissing is None: |
|
checkmissing = self.checkmissing |
|
|
|
# handle repititions |
|
while True: |
|
subidx = text.find(self.start_rep_token) |
|
if subidx == -1: |
|
break |
|
endidx = self.find_rep_end(text[subidx:]) |
|
if endidx == -1: |
|
raise MAVParseError("missing end macro in %s" % text[subidx:]) |
|
part1 = text[0:subidx] |
|
part2 = text[subidx+len(self.start_rep_token):subidx+(endidx-len(self.end_rep_token))] |
|
part3 = text[subidx+endidx:] |
|
a = part2.split(':') |
|
field_name = a[0] |
|
rest = ':'.join(a[1:]) |
|
v = getattr(subvars, field_name, None) |
|
if v is None: |
|
raise MAVParseError('unable to find field %s' % field_name) |
|
t1 = part1 |
|
for f in v: |
|
t1 += self.substitute(rest, f, trim_leading_lf=False, checkmissing=False) |
|
if len(v) != 0 and t1[-1] in ["\n", ","]: |
|
t1 = t1[:-1] |
|
t1 += part3 |
|
text = t1 |
|
|
|
if trim_leading_lf: |
|
if text[0] == '\n': |
|
text = text[1:] |
|
while True: |
|
idx = text.find(self.start_var_token) |
|
if idx == -1: |
|
return text |
|
endidx = text[idx:].find(self.end_var_token) |
|
if endidx == -1: |
|
raise MAVParseError('missing end of variable: %s' % text[idx:idx+10]) |
|
varname = text[idx+2:idx+endidx] |
|
if isinstance(subvars, dict): |
|
if not varname in subvars: |
|
if checkmissing: |
|
raise MAVParseError("unknown variable in '%s%s%s'" % ( |
|
self.start_var_token, varname, self.end_var_token)) |
|
return text[0:idx+endidx] + self.substitute(text[idx+endidx:], subvars, |
|
trim_leading_lf=False, checkmissing=False) |
|
value = subvars[varname] |
|
else: |
|
value = getattr(subvars, varname, None) |
|
if value is None: |
|
if checkmissing: |
|
raise MAVParseError("unknown variable in '%s%s%s'" % ( |
|
self.start_var_token, varname, self.end_var_token)) |
|
return text[0:idx+endidx] + self.substitute(text[idx+endidx:], subvars, |
|
trim_leading_lf=False, checkmissing=False) |
|
text = text.replace("%s%s%s" % (self.start_var_token, varname, self.end_var_token), str(value)) |
|
return text |
|
|
|
def write(self, file, text, subvars={}, trim_leading_lf=True): |
|
'''write to a file with variable substitution''' |
|
file.write(self.substitute(text, subvars=subvars, trim_leading_lf=trim_leading_lf))
|
|
|