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:
parent
c3c6e3713d
commit
cb248ac357
|
@ -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))
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue