Introduce indented config file handling code, disabled for now since nothing uses it, and it has the potential for breaking currently working configs, since indent errors are difficult to recover from sensibly.

This commit is contained in:
Thomas Hurst 2008-11-01 11:31:12 +00:00
parent c3c6e3713d
commit cb248ac357
2 changed files with 58 additions and 5 deletions

View File

@ -290,7 +290,11 @@ Errors were encountered while parsing terminator_config(5) file:
dbg("ConfigFile settings are: %s" % repr(self.values))
def _rc_set_callback(self):
def callback(section, key, value):
def callback(sections, key, value):
dbg("Setting: section=%s with %s => %s" % (repr(sections), repr(key), repr(value)))
section = None
if len(sections) > 0:
section = sections[0]
if section is None:
if not Defaults.has_key (key):
raise ValueError("Unknown configuration option %s" % repr(key))

View File

@ -27,6 +27,7 @@ Colourvalue = re.compile(group(PaletteColours, SingleColour))
Barevalue = re.compile(r'((?:[^\r\n# \f\t]+|[^\r\n#]+(?!' + Ignore.pattern +'))+)')
Tabsize = 8
HandleIndents = False
class ConfigSyntaxError(Exception):
def __init__(self, message, cf):
@ -45,6 +46,9 @@ class ConfigSyntaxError(Exception):
return fmt % {'message': self.message, 'file': self.file, 'lnum': self.lnum,
'line': self.line.rstrip(), 'pad': '-' * self.pos}
class ConfigIndentError(ConfigSyntaxError):
pass
class ParsedWithErrors(Exception):
def __init__(self, filename, errors):
self.file = filename
@ -113,7 +117,7 @@ class ConfigFile:
self._lnum = 0
self._line = ''
self._currsection = None
self._sections = {}
self._currsetting = None
self._currvalue = None
self.errors = []
@ -125,7 +129,10 @@ class ConfigFile:
self._max = len(self._line)
dbg("Line %d: %s" % (self._lnum, repr(self._line)))
self._call_if_match(WhitespaceRE, None)
if HandleIndents:
self._find_indent()
else:
self._call_if_match(WhitespaceRE, None)
# [Section]
self._call_if_match(Section, self._section, 1)
@ -146,13 +153,55 @@ class ConfigFile:
self._line_ok()
except ConfigSyntaxError, e:
self._line_error(e)
except ConfigIndentError, e:
self.errors.append(e)
break
if self.errors:
raise ParsedWithErrors(self.filename, self.errors)
def _find_indent(self):
# Based on tokenizer.py in the base Python standard library
column = 0
while self._pos < self._max:
chr = self._line[self._pos]
if chr == ' ': column += 1
elif chr == '\t': column = (column / Tabsize + 1) * Tabsize
elif chr == '\f': column = 0
else: break
self._pos += 1
if self._pos == self._max: return
if column > self._indents[-1]:
self._indents.append(column)
self._indent() # self._line[:self._pos])
while column < self._indents[-1]:
if column not in self._indents:
raise ConfigSyntaxError("Unindent does not match a previous indent, config parsing aborted", self)
self._indents.pop()
self._deindent()
def _indent(self):
dbg(" -> Indent %d" % len(self._indents))
def _deindent(self):
dbg(" -> Deindent %d" % len(self._indents))
def _get_section(self):
i = 1
sections = []
while i <= len(self._indents):
sname = self._sections.get(i, None)
if not sname:
break
sections.append(str(sname))
i += 1
return tuple(sections)
def _section(self, section):
dbg("Section %s" % repr(section))
self._currsection = section.lower()
self._sections[len(self._indents)] = section.lower()
def _setting(self, setting):
dbg("Setting %s" % repr(setting))
@ -167,7 +216,7 @@ class ConfigFile:
else:
try: # *glares at 2.4 users*
try:
self.callback(self._currsection, self._currsetting, self._currvalue)
self.callback(self._get_section(), self._currsetting, self._currvalue)
except ValueError, e:
raise ConfigSyntaxError(str(e), self)
finally: