Config update and cleanup

This commit is contained in:
Florian Bruhin 2014-02-25 21:43:58 +01:00
parent 4b3ae3f013
commit 062e385028
3 changed files with 155 additions and 81 deletions

View File

@ -27,6 +27,7 @@ from configparser import (ConfigParser, ExtendedInterpolation, NoSectionError,
from qutebrowser.utils.misc import read_file from qutebrowser.utils.misc import read_file
import qutebrowser.config.options as opt import qutebrowser.config.options as opt
import qutebrowser.config.sections as sect
config = None config = None
state = None state = None
@ -54,7 +55,7 @@ class ConfigStructure:
def __init__(self): def __init__(self):
self.config = OrderedDict([ self.config = OrderedDict([
('general', KeyValueSection( ('general', sect.KeyValue(
('show_completion', opt.ShowCompletion()), ('show_completion', opt.ShowCompletion()),
('completion_height', opt.CompletionHeight()), ('completion_height', opt.CompletionHeight()),
('ignorecase', opt.IgnoreCase()), ('ignorecase', opt.IgnoreCase()),
@ -64,7 +65,7 @@ class ConfigStructure:
('zoomlevels', opt.ZoomLevels()), ('zoomlevels', opt.ZoomLevels()),
('defaultzoom', opt.DefaultZoom()), ('defaultzoom', opt.DefaultZoom()),
)), )),
('tabbar', KeyValueSection( ('tabbar', sect.KeyValue(
('movable', opt.Movable()), ('movable', opt.Movable()),
('closebuttons', opt.CloseButtons()), ('closebuttons', opt.CloseButtons()),
('scrollbuttons', opt.ScrollButtons()), ('scrollbuttons', opt.ScrollButtons()),
@ -72,16 +73,10 @@ class ConfigStructure:
('select_on_remove', opt.SelectOnRemove()), ('select_on_remove', opt.SelectOnRemove()),
('last_close', opt.LastClose()), ('last_close', opt.LastClose()),
)), )),
('searchengines', ValueListSection( ('searchengines', sect.SearchEngines()),
opt.SearchEngineKeyValue() ('keybind', sect.KeyBindings()),
)), ('aliases', sect.Aliases()),
('keybind', ValueListSection( ('colors', sect.KeyValue(
opt.KeybindKeyValue()
)),
('aliases', ValueListSection(
opt.AliasKeyValue()
)),
('colors', KeyValueSection(
('completion.fg', opt.CompletionFgColor()), ('completion.fg', opt.CompletionFgColor()),
('completion.item.bg', opt.CompletionItemBgColor()), ('completion.item.bg', opt.CompletionItemBgColor()),
('completion.category.bg', opt.CompletionCategoryBgColor()), ('completion.category.bg', opt.CompletionCategoryBgColor()),

View File

@ -33,17 +33,17 @@ class CompletionHeight(template.SettingValue):
default = "50%" default = "50%"
def validate(self, value): def validate(self):
if value.endswith('%'): if self.value.endswith('%'):
try: try:
intval = int(value.rstrip('%')) intval = int(self.value.rstrip('%'))
except ValueError: except ValueError:
return False return False
else: else:
return 0 <= intval <= 100 return 0 <= intval <= 100
else: else:
try: try:
intval = int(value) intval = int(self.value)
except ValueError: except ValueError:
return False return False
else: else:
@ -75,21 +75,21 @@ class AutoSearch(template.BoolSettingValue):
"""Whether to start a search when something else than an URL is entered.""" """Whether to start a search when something else than an URL is entered."""
values = [("naive", "Use simple/naive check."), valid_values = [("naive", "Use simple/naive check."),
("dns", "Use DNS requests (might be slow!)."), ("dns", "Use DNS requests (might be slow!)."),
("false", "Never search automatically.")] ("false", "Never search automatically.")]
default = "naive" default = "naive"
def validate(self, value): def validate(self):
if value.lower() in ["naive", "dns"]: if self.value.lower() in ["naive", "dns"]:
return True return True
else: else:
return super().validate(value) return super().validate(self.value)
def transform(self, value): def transform(self):
if value.lower() in ["naive", "dns"]: if self.value.lower() in ["naive", "dns"]:
return value.lower() return self.value.lower()
elif super().transform(value): elif super().transform(self.value):
# boolean true is an alias for naive matching # boolean true is an alias for naive matching
return "naive" return "naive"
else: else:
@ -137,7 +137,7 @@ class Position(template.SettingValue):
"""The position of the tab bar.""" """The position of the tab bar."""
values = ["north", "south", "east", "west"] valid_values = ["north", "south", "east", "west"]
default = "north" default = "north"
@ -145,9 +145,9 @@ class SelectOnRemove(template.SettingValue):
"""Which tab to select when the focused tab is removed.""" """Which tab to select when the focused tab is removed."""
values = [("left", "Select the tab on the left."), valid_values = [("left", "Select the tab on the left."),
("right", "Select the tab on the right."), ("right", "Select the tab on the right."),
("previous", "Select the previously selected tab.")] ("previous", "Select the previously selected tab.")]
default = "previous" default = "previous"
@ -155,9 +155,9 @@ class LastClose(template.SettingValue):
"""Behaviour when the last tab is closed.""" """Behaviour when the last tab is closed."""
values = [("ignore", "Don't do anything."), valid_values = [("ignore", "Don't do anything."),
("blank", "Load about:blank."), ("blank", "Load about:blank."),
("quit", "Quit qutebrowser.")] ("quit", "Quit qutebrowser.")]
default = "ignore" default = "ignore"
### FIXME what to do with list-style sections? ### FIXME what to do with list-style sections?
@ -167,8 +167,8 @@ class SearchEngine(template.SettingValue):
"""A search engine setting.""" """A search engine setting."""
def validate(self, value): def validate(self):
return "{}" in value return "{}" in self.value
class CompletionFgColor(template.ColorSettingValue): class CompletionFgColor(template.ColorSettingValue):
@ -260,7 +260,8 @@ class StatusbarFgErrorColor(template.ColorSettingValue):
"""Foreground color of the statusbar if there was an error.""" """Foreground color of the statusbar if there was an error."""
default = "${statusbar.fg}" default = StatusbarFgColor.default
default_conf = "${statusbar.fg}"
class StatusbarBgErrorColor(template.ColorSettingValue): class StatusbarBgErrorColor(template.ColorSettingValue):
@ -281,7 +282,8 @@ class StatusbarUrlFgColor(template.ColorSettingValue):
"""Default foreground color of the URL in the statusbar.""" """Default foreground color of the URL in the statusbar."""
default = "${statusbar.fg}" default = StatusbarFgColor.default
default_conf = "${statusbar.fg}"
class StatusbarUrlSuccessFgColor(template.ColorSettingValue): class StatusbarUrlSuccessFgColor(template.ColorSettingValue):
@ -353,18 +355,21 @@ class CompletionFont(template.FontSettingValue):
"""Font used in the completion widget.""" """Font used in the completion widget."""
default = "8pt ${_monospace}" default = MonospaceFonts.default
default_conf = "8pt ${_monospace}"
class TabbarFont(template.FontSettingValue): class TabbarFont(template.FontSettingValue):
"""Font used in the tabbar.""" """Font used in the tabbar."""
default = "8pt ${_monospace}" default = MonospaceFonts.default
default_conf = "8pt ${_monospace}"
class StatusbarFont(template.FontSettingValue): class StatusbarFont(template.FontSettingValue):
"""Font used in the statusbar.""" """Font used in the statusbar."""
default = "8pt ${_monospace}" default = MonospaceFonts.default
default_conf = "8pt ${_monospace}"

View File

@ -22,50 +22,84 @@ import qutebrowser.commands.utils as cmdutils
class SettingValue: class SettingValue:
"""Base class for settings. The docstring is used as a description.""" """Base class for setting values.
# Possible values, if they are fixed. Intended to be subclassed by config value "types".
# Either a list of strings, or a list of (value, desc) tuples.
values = None
# Default value if user has not overriden it, as a string. Attributes:
valid_values: Possible values if they can be expressed as a fixed
string. Either a list of strings, or a list of (value,
desc) tuples.
# FIXME actually handle tuples and stuff when validating
default: Default value if the user has not overridden it, as a string.
default_conf: Default value for the config, with interpolation.
value: (property) The currently valid, most important, transformed
value.
rawvalue: The current value as a raw string.
typestr: The name of the type to appear in the config.
"""
valid_values = None
default = None default = None
default_conf = None
typestr = None
rawvalue = None
def transform(self, value): def __init__(self, rawval=None):
"""Constructor.
Args:
rawval: Raw value to set.
"""
if rawval is not None:
self.rawvalue = rawval
def __str__(self):
"""Get raw string value."""
return self.rawvalue if self.rawvalue is not None else ''
@property
def value(self):
"""Get the currently valid value."""
# FIXME handle default properly
#if self._rawvalue is not None:
# val = self.rawvalue
#else:
# val = self.default
return self.transform()
def transform(self):
"""Transform the setting value. """Transform the setting value.
This method can assume the value is indeed a valid value. This method can assume the value is indeed a valid value.
The default implementation returns the original value. The default implementation returns the original value.
Args:
value: The value to transform.
Return: Return:
The transformed value. The transformed value.
""" """
return value return self.value
def validate(self, value): def validate(self):
"""Validate value against possible values. """Validate value against possible values.
The default implementation checks the value against self.values if it The default implementation checks the value against self.valid_values
was defined. if it was defined.
Args:
value: The value to validate.
Return: Return:
Ture if validation succeeded, False otherwise. Ture if validation succeeded, False otherwise.
Raise: Raise:
NotImplementedError if self.values is not defined and this method NotImplementedError if self.valid_values is not defined and this
should be overridden. method should be overridden.
""" """
if self.values is not None: if self.valid_values is not None:
return value in self.values return self.value in self.valid_values
else: else:
raise NotImplementedError raise NotImplementedError
@ -74,29 +108,32 @@ class BoolSettingValue(SettingValue):
"""Base class for a boolean setting.""" """Base class for a boolean setting."""
values = ['true', 'false'] valid_values = ['true', 'false']
typestr = 'bool'
# Taken from configparser # Taken from configparser
_BOOLEAN_STATES = {'1': True, 'yes': True, 'true': True, 'on': True, _BOOLEAN_STATES = {'1': True, 'yes': True, 'true': True, 'on': True,
'0': False, 'no': False, 'false': False, 'off': False} '0': False, 'no': False, 'false': False, 'off': False}
def transform(self, value): def transform(self):
return self._BOOLEAN_STATES[value.lower()] return self._BOOLEAN_STATES[self.value.lower()]
def validate(self, value): def validate(self):
return value.lower() in self._BOOLEAN_STATES return self.value.lower() in self._BOOLEAN_STATES
class IntSettingValue(SettingValue): class IntSettingValue(SettingValue):
"""Base class for an integer setting.""" """Base class for an integer setting."""
def transform(self, value): typestr = 'int'
return int(value)
def validate(self, value): def transform(self):
return int(self.value)
def validate(self):
try: try:
int(value) int(self.value)
except ValueError: except ValueError:
return False return False
else: else:
@ -107,10 +144,12 @@ class ListSettingValue(SettingValue):
"""Base class for a (string-)list setting.""" """Base class for a (string-)list setting."""
def transform(self, value): typestr = 'string-list'
return value.split(',')
def validate(self, value): def transform(self):
return self.value.split(',')
def validate(self):
return True return True
@ -118,13 +157,15 @@ class IntListSettingValue(ListSettingValue):
"""Base class for an int-list setting.""" """Base class for an int-list setting."""
def transform(self, value): typestr = 'int-list'
vals = super().transform(value)
def transform(self):
vals = super().transform(self.value)
return map(int, vals) return map(int, vals)
def validate(self, value): def validate(self):
try: try:
self.transform(value) self.transform(self.value)
except ValueError: except ValueError:
return False return False
else: else:
@ -135,15 +176,17 @@ class CommandSettingValue(SettingValue):
"""Base class for a command value with arguments.""" """Base class for a command value with arguments."""
values = cmdutils.cmd_dict.values() typestr = 'command'
def validate(self, value): valid_values = cmdutils.cmd_dict.items()
def validate(self):
# We need to import this here to avoid circular dependencies # We need to import this here to avoid circular dependencies
from qutebrowser.commands.parsers import (CommandParser, from qutebrowser.commands.parsers import (CommandParser,
NoSuchCommandError) NoSuchCommandError)
cp = CommandParser() cp = CommandParser()
try: try:
cp.parse(value) cp.parse(self.value)
except NoSuchCommandError: except NoSuchCommandError:
return False return False
else: else:
@ -154,7 +197,9 @@ class ColorSettingValue(SettingValue):
"""Base class for a color value.""" """Base class for a color value."""
def validate(self, value): typestr = 'color'
def validate(self):
# FIXME validate colors # FIXME validate colors
return True return True
@ -163,6 +208,35 @@ class FontSettingValue(SettingValue):
"""Base class for a font value.""" """Base class for a font value."""
def validate(self, value): typestr = 'font'
def validate(self):
# FIXME validate fonts # FIXME validate fonts
return True return True
class ValueListSection:
"""This class represents a section with a list key-value settings.
These are settings inside sections which don't have fixed keys, but instead
have a dynamic list of "key = value" pairs, like keybindings or
searchengines.
They basically consist of two different SettingValues and have no defaults.
Attributes:
values: An OrderedDict with key as index and value as value.
default: An OrderedDict with the default configuration as strings.
types: A tuple for (keytype, valuetype)
"""
values = None
default = None
types = None
def __str__(self):
"""Get the key = value pairs as a string."""
return '\n'.join('{} = {}'.format(key.rawvalue, val.rawvalue)
for key, val in self.values)