Start new config subsystem
This commit is contained in:
parent
dc18ec4e0d
commit
395acffdc4
@ -21,10 +21,12 @@ import os
|
||||
import io
|
||||
import os.path
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
from configparser import (ConfigParser, ExtendedInterpolation, NoSectionError,
|
||||
NoOptionError)
|
||||
|
||||
from qutebrowser.utils.misc import read_file
|
||||
from qutebrowser.config.options import *
|
||||
|
||||
config = None
|
||||
state = None
|
||||
@ -46,6 +48,47 @@ def init(confdir):
|
||||
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):
|
||||
|
||||
"""Our own ConfigParser subclass.
|
||||
|
370
qutebrowser/config/options.py
Normal file
370
qutebrowser/config/options.py
Normal 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}"
|
162
qutebrowser/config/templates.py
Normal file
162
qutebrowser/config/templates.py
Normal 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
|
Loading…
Reference in New Issue
Block a user