From cb248ac3572e4bc818ef0dacbb8a5666b159b88f Mon Sep 17 00:00:00 2001 From: Thomas Hurst Date: Sat, 1 Nov 2008 11:31:12 +0000 Subject: [PATCH] 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. --- terminatorlib/config.py | 6 +++- terminatorlib/configfile.py | 57 ++++++++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/terminatorlib/config.py b/terminatorlib/config.py index 4faa982e..8daef461 100755 --- a/terminatorlib/config.py +++ b/terminatorlib/config.py @@ -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)) diff --git a/terminatorlib/configfile.py b/terminatorlib/configfile.py index 81106787..03dcdc43 100644 --- a/terminatorlib/configfile.py +++ b/terminatorlib/configfile.py @@ -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: