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)) dbg("ConfigFile settings are: %s" % repr(self.values))
def _rc_set_callback(self): 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 section is None:
if not Defaults.has_key (key): if not Defaults.has_key (key):
raise ValueError("Unknown configuration option %s" % repr(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 +'))+)') Barevalue = re.compile(r'((?:[^\r\n# \f\t]+|[^\r\n#]+(?!' + Ignore.pattern +'))+)')
Tabsize = 8 Tabsize = 8
HandleIndents = False
class ConfigSyntaxError(Exception): class ConfigSyntaxError(Exception):
def __init__(self, message, cf): def __init__(self, message, cf):
@ -45,6 +46,9 @@ class ConfigSyntaxError(Exception):
return fmt % {'message': self.message, 'file': self.file, 'lnum': self.lnum, return fmt % {'message': self.message, 'file': self.file, 'lnum': self.lnum,
'line': self.line.rstrip(), 'pad': '-' * self.pos} 'line': self.line.rstrip(), 'pad': '-' * self.pos}
class ConfigIndentError(ConfigSyntaxError):
pass
class ParsedWithErrors(Exception): class ParsedWithErrors(Exception):
def __init__(self, filename, errors): def __init__(self, filename, errors):
self.file = filename self.file = filename
@ -113,7 +117,7 @@ class ConfigFile:
self._lnum = 0 self._lnum = 0
self._line = '' self._line = ''
self._currsection = None self._sections = {}
self._currsetting = None self._currsetting = None
self._currvalue = None self._currvalue = None
self.errors = [] self.errors = []
@ -125,7 +129,10 @@ class ConfigFile:
self._max = len(self._line) self._max = len(self._line)
dbg("Line %d: %s" % (self._lnum, repr(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] # [Section]
self._call_if_match(Section, self._section, 1) self._call_if_match(Section, self._section, 1)
@ -146,13 +153,55 @@ class ConfigFile:
self._line_ok() self._line_ok()
except ConfigSyntaxError, e: except ConfigSyntaxError, e:
self._line_error(e) self._line_error(e)
except ConfigIndentError, e:
self.errors.append(e)
break
if self.errors: if self.errors:
raise ParsedWithErrors(self.filename, 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): def _section(self, section):
dbg("Section %s" % repr(section)) dbg("Section %s" % repr(section))
self._currsection = section.lower() self._sections[len(self._indents)] = section.lower()
def _setting(self, setting): def _setting(self, setting):
dbg("Setting %s" % repr(setting)) dbg("Setting %s" % repr(setting))
@ -167,7 +216,7 @@ class ConfigFile:
else: else:
try: # *glares at 2.4 users* try: # *glares at 2.4 users*
try: try:
self.callback(self._currsection, self._currsetting, self._currvalue) self.callback(self._get_section(), self._currsetting, self._currvalue)
except ValueError, e: except ValueError, e:
raise ConfigSyntaxError(str(e), self) raise ConfigSyntaxError(str(e), self)
finally: finally: