Start new config subsystem

This commit is contained in:
Florian Bruhin 2014-02-24 07:17:17 +01:00
parent dc18ec4e0d
commit 395acffdc4
3 changed files with 575 additions and 0 deletions

View File

@ -21,10 +21,12 @@ import os
import io import io
import os.path import os.path
import logging import logging
from collections import OrderedDict
from configparser import (ConfigParser, ExtendedInterpolation, NoSectionError, from configparser import (ConfigParser, ExtendedInterpolation, NoSectionError,
NoOptionError) NoOptionError)
from qutebrowser.utils.misc import read_file from qutebrowser.utils.misc import read_file
from qutebrowser.config.options import *
config = None config = None
state = None state = None
@ -46,6 +48,47 @@ def init(confdir):
state = Config(confdir, 'state', always_save=True) state = Config(confdir, 'state', always_save=True)
class ConfigStructure:
def __init__(self):
self.config = OrderedDict([
('general', KeyValueSection(
('show_completion', ShowCompletion()),
('completion_height', CompletionHeight()),
('ignorecase', IgnoreCase()),
('wrapsearch', WrapSearch()),
('startpage', StartPage()),
('auto_search', AutoSearch()),
('zoomlevels', ZoomLevels()),
('defaultzoom', DefaultZoom()),
)),
('tabbar', KeyValueSection(
('movable', Movable()),
('closebuttons', CloseButtons()),
('scrollbuttons', ScrollButtons()),
('position', Position()),
('select_on_remove', SelectOnRemove()),
('last_close', LastClose()),
)),
('searchengines', ValueListSection(
SearchEngineKeyValue()
)),
('keybind', ValueListSection(
KeybindKeyValue()
)),
('aliases', ValueListSection(
AliasKeyValue()
)),
('colors', KeyValueSection(
('completion.fg', CompletionFgColor()),
('completion.item.bg', CompletionItemBgColor()),
# FIXME ...
)),
('fonts', KeyValueSection(
)),
])
class Config(ConfigParser): class Config(ConfigParser):
"""Our own ConfigParser subclass. """Our own ConfigParser subclass.

View File

@ -0,0 +1,370 @@
# Copyright 2014 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Setting options used for qutebrowser."""
from qutebrowser.config.templates import *
class ShowCompletion(BoolSettingValue):
"""Whether to show the autocompletion window or not."""
default = "true"
class CompletionHeight(SettingValue):
"""The height of the completion, in px or as percentage of the window."""
default = "50%"
def validate(self, value):
if value.endswith('%'):
try:
intval = int(value.rstrip('%'))
except ValueError:
return False
else:
return 0 <= intval <= 100
else:
try:
intval = int(value)
except ValueError:
return False
else:
return intval > 0
class IgnoreCase(BoolSettingValue):
"""Whether to do case-insensitive searching."""
default = "true"
class WrapSearch(BoolSettingValue):
"""Whether to wrap search to the top when arriving at the end."""
default = "true"
class StartPage(ListSettingValue):
"""The default page(s) to open at the start, separated with commas."""
default = "http://www.duckduckgo.com/"
class AutoSearch(BoolSettingValue):
"""Whether to start a search when something else than an URL is entered."""
values = [("naive", "Use simple/naive check."),
("dns", "Use DNS requests (might be slow!)."),
("false": "Never search automatically.")]
default = "naive"
def validate(self, value):
if value.lower() in ["naive", "dns"]:
return True
else:
return super().validate(value)
return True
else:
return super().validate(value)
def transform(self, value):
if value.lower() in ["naive", "dns"]:
return value.lower()
elif super().transform(value):
# boolean true is an alias for naive matching
return "naive"
else:
return "false"
class ZoomLevels(IntListSettingValue):
"""The available zoom levels, separated by commas."""
default = "25,33,50,67,75,90,100,110,125,150,175,200,250,300,400,500"
class DefaultZoom(IntSettingValue):
"""The default zoom level."""
# FIXME we might want to validate if defaultzoom is in zoomlevels...
default = "100"
class Movable(BoolSettingValue):
"""Whether tabs should be movable."""
default = "true"
class CloseButtons(BoolSettingValue):
"""Whether tabs should have close-buttons."""
default = "false"
class ScrollButtons(BoolSettingValue):
"""Whether there should be scroll buttons if there are too many tabs."""
default = "true"
class Position(SettingValue):
"""The position of the tab bar."""
values = ["north", "south", "east", "west"]
default = "north"
class SelectOnRemove(SettingValue):
"""Which tab to select when the focused tab is removed."""
values = [("left", "Select the tab on the left."),
("right", "Select the tab on the right."),
("previous", "Select the previously selected tab.")]
default = "previous"
class LastClose(SettingValue):
"""Behaviour when the last tab is closed."""
values = [("ignore", "Don't do anything."),
("blank", "Load about:blank."),
("quit", "Quit qutebrowser.")]
default = "ignore"
### FIXME what to do with list-style sections?
class SearchEngine(SettingValue):
"""A search engine setting."""
def validate(self, value):
return "{}" in value
class CompletionFgColor(ColorSettingValue):
"""Text color of the completion widget."""
default = "#333333"
class CompletionItemBgColor(ColorSettingValue):
"""Background color of completion widget items."""
default = "white"
class CompletionCategoryBgColor(ColorSettingValue):
"""Background color of the completion widget category headers."""
default = ("completion.category.bg = qlineargradient("
"x1:0, y1:0, x2:0, y2:1, stop:0 #e4e4e4, stop:1 #dbdbdb")
class CompletionCategoryTopBorderColor(ColorSettingValue):
"""Top border color of the completion widget category headers."""
default = "#808080"
class CompletionCategoryBottomBorderColor(ColorSettingValue):
"""Bottom border color of the completion widget category headers."""
default = "#bbbbbb"
class CompletionItemSelectedFgColor(ColorSettingValue):
"""Foreground color of the selected completion item."""
default = "#333333"
class CompletionItemSelectedBgColor(ColorSettingValue):
"""Background color of the selected completion item."""
default = "#ffec8b"
class CompletionItemSelectedTopBorderColor(ColorSettingValue):
"""Top border color of the selected completion item."""
default = "#f2f2c0"
class CompletionItemSelectedBottomBorderColor(ColorSettingValue):
"""Bottom border color of the selected completion item."""
default = "#ffec8b"
class CompletionMatchFgColor(ColorSettingValue):
"""Foreground color of the matched text in the completion."""
default = "red"
class StatusbarBgColor(ColorSettingValue):
"""Background color of the statusbar."""
default = "black"
class StatusbarFgColor(ColorSettingValue):
"""Foreground color of the statusbar."""
default = "white"
class StatusbarFgErrorColor(ColorSettingValue):
"""Foreground color of the statusbar if there was an error."""
default = "${statusbar.fg}"
class StatusbarBgErrorColor(ColorSettingValue):
"""Background color of the statusbar if there was an error."""
default = "red"
class StatusbarProgressBgColor(ColorSettingValue):
"""Background color of the progress bar."""
default = "white"
class StatusbarUrlFgColor(ColorSettingValue):
"""Default foreground color of the URL in the statusbar."""
default = "${statusbar.fg}"
class StatusbarUrlSuccessFgColor(ColorSettingValue):
"""Foreground color of the URL in the statusbar on successful load."""
default = "lime"
class StatusbarUrlErrorFgColor(ColorSettingValue):
"""Foreground color of the URL in the statusbar on error."""
default = "orange"
class StatusbarUrlWarnFgColor(ColorSettingValue):
"""Foreground color of the URL in the statusbar when there's a warning."""
default = "yellow"
class StatusbarUrlHoverFgColor(ColorSettingValue):
"""Foreground color of the URL in the statusbar for hovered links."""
default = "aqua"
class TabFgColor(ColorSettingValue):
"""Foreground color of the tabbar."""
default = "white"
class TabBgColor(ColorSettingValue):
"""Background color of the tabbar."""
default = "grey"
class TabSelectedBgColor(ColorSettingValue):
"""Background color of the tabbar for the selected tab."""
default = "black"
class TabSeperatorColor(ColorSettingValue):
"""Color for the tab seperator."""
default = "white"
class MonospaceFonts(FontSettingValue):
"""Default monospace fonts."""
default = ('Monospace, "DejaVu Sans Mono", Consolas, Monaco, '
'"Bitstream Vera Sans Mono", "Andale Mono", "Liberation Mono", '
'"Courier New", Courier, monospace, Fixed, Terminal')
class CompletionFont(FontSettingValue):
"""Font used in the completion widget."""
default = "8pt ${_monospace}"
class TabbarFont(FontSettingValue):
"""Font used in the tabbar."""
default = "8pt ${_monospace}"
class StatusbarFont(FontSettingValue):
"""Font used in the statusbar."""
default = "8pt ${_monospace}"

View File

@ -0,0 +1,162 @@
# Copyright 2014 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Templates for setting options."""
import qutebrowser.commands.utils as cmdutils
class SettingValue:
"""Base class for settings. The docstring is used as a description."""
# Possible values, if they are fixed.
# 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.
default = None
def transform(self, value):
"""Transform the setting value.
This method can assume the value is indeed a valid value.
The default implementation returns the original value.
Args:
value: The value to transform.
Return:
The transformed value.
"""
return value
def validate(self, value):
"""Validate value against possible values.
The default implementation checks the value against self.values if it
was defined.
Args:
value: The value to validate.
Return:
Ture if validation succeeded, False otherwise.
Raise:
NotImplementedError if self.values is not defined and this method
should be overridden.
"""
if self.values is not None:
return value in self.values
else:
raise NotImplementedError
class BoolSettingValue(SettingValue):
"""Base class for a boolean setting."""
values = ['true', 'false']
# Taken from configparser
_BOOLEAN_STATES = {'1': True, 'yes': True, 'true': True, 'on': True,
'0': False, 'no': False, 'false': False, 'off': False}
def transform(self, value):
return self._BOOLEAN_STATES[value.lower()]
def validate(self, value):
return value.lower() in self._BOOLEAN_STATES
class IntSettingValue(SettingValue):
"""Base class for an integer setting."""
def transform(self, value):
return int(value)
def validate(self, value):
try:
int(value)
except ValueError:
return False
else:
return True
class ListSettingValue(SettingValue):
"""Base class for a (string-)list setting."""
def transform(self, value):
return value.split(',')
def validate(self, value):
return True
class IntListSettingValue(ListSettingValue):
"""Base class for an int-list setting."""
def transform(self, value):
vals = super().transform(value)
return map(int, vals)
def validate(self, value)
try:
self.transform(value)
except ValueError:
return False
else:
return True
class CommandSettingValue(SettingValue):
"""Base class for a command value with arguments."""
values = cmdutils.cmd_dict.values()
def validate(self, value):
cp = cmdutils.CommandParser()
try:
cp.parse(value)
except cmdutils.NoSuchCommandError:
return False
else:
return True
class ColorSettingValue(SettingValue):
"""Base class for a color value."""
def validate(self, value):
# FIXME validate colors
return True
class FontSettingValue(SettingValue):
"""Base class for a font value."""
def validate(self, value):
# FIXME validate fonts
return True