Skip to content
Browse files

Implement initial reading from YAML

  • Loading branch information...
The-Compiler committed Jun 20, 2017
1 parent f990681 commit 6375530bfad5daee5789d3308851e809e491ae5c
Showing with 62 additions and 15 deletions.
  1. +29 −14 qutebrowser/config/
  2. +33 −1 qutebrowser/config/
@@ -149,7 +149,7 @@ def _prepare(self, key, mode):
return utils.normalize_keystr(key)
return key

def bind(self, key, command, *, mode, force=False):
def bind(self, key, command, *, mode, force=False, save_yaml=False):
"""Add a new binding from key to command."""
key = self._prepare(key, mode)

@@ -172,9 +172,9 @@ def bind(self, key, command, *, mode, force=False):
if key in bindings and not force:
raise configexc.DuplicateKeyError(key)
bindings[key] = command

def unbind(self, key, *, mode='normal'):
def unbind(self, key, *, mode='normal', save_yaml=False):
"""Unbind the given key in the given mode."""
key = self._prepare(key, mode)
bindings = instance.get_obj('bindings.commands')[mode]
@@ -183,7 +183,7 @@ def unbind(self, key, *, mode='normal'):
except KeyError:
raise configexc.KeybindingError("Can't find binding '{}' in section '{}'!"
.format(key, mode))

def get_command(self, key, mode):
"""Get the command for a given key (or None)."""
@@ -254,7 +254,7 @@ def _set_next(self, option, values):
if len(values) == 1:
# If we have only one value, just set it directly (avoid
# breaking stuff like aliases or other pseudo-settings)
self._config.set_str(option, values[0])
self._config.set_str(option, values[0], save_yaml=True)

# Use the next valid value from values, or the first if the current
@@ -266,7 +266,7 @@ def _set_next(self, option, values):
value = values[idx]
except ValueError:
value = values[0]
self._config.set_str(option, value)
self._config.set_str(option, value, save_yaml=True)

def _handle_config_error(self):
@@ -310,7 +310,8 @@ def bind(self, key, command=None, *, mode='normal', force=False):

key_instance.bind(key, command, mode=mode, force=force)
key_instance.bind(key, command, mode=mode, force=force,
except configexc.DuplicateKeyError as e:
raise cmdexc.CommandError(str(e) + " - use --force to override!")
except configexc.KeybindingError as e:
@@ -325,7 +326,7 @@ def unbind(self, key, mode='normal'):
mode: A mode to unbind the key in (default: `normal`).
key_instance.unbind(key, mode=mode)
key_instance.unbind(key, mode=mode, save_yaml=True)
except configexc.KeybindingError as e:
raise cmdexc.CommandError(str(e))

@@ -339,6 +340,7 @@ def __init__(self, parent=None):
self.options = {}
self._values = {}
self._mutables = []
self._yaml = configfiles.YamlConfig()

def _changed(self, name, value):
@@ -348,6 +350,13 @@ def read_defaults(self):
for name, option in configdata.DATA.items():
self.options[name] = option

def read_yaml(self):
for name, value in self._yaml.values.items():
opt = self.get_opt(name)
opt.typ.to_py(value) # for validation
self._values[name] = value

def get_opt(self, name):
return self.options[name]
@@ -375,22 +384,27 @@ def get_str(self, name):
value = self._values.get(name, opt.default)
return opt.typ.to_str(value)

def set_obj(self, name, value):
def set_obj(self, name, value, *, save_yaml=False):
opt = self.get_opt(name)
opt.typ.to_py(value) # for validation
self._values[name] = value
self._changed(name, value)
if save_yaml:
self._yaml.values[name] = value

def set_str(self, name, value):
def set_str(self, name, value, *, save_yaml=False):
opt = self.get_opt(name)
self._values[name] = opt.typ.from_str(value)
self._changed(name, value)
converted = opt.typ.from_str(value)
self._values[name] = converted
self._changed(name, converted)
if save_yaml:
self._yaml.values[name] = converted

def update_mutables(self):
def update_mutables(self, *, save_yaml=False):
for name, old_value, new_value in self._mutables:
if old_value != new_value:
log.config.debug("{} was mutated, updating".format(name))
self.set_obj(name, new_value)
self.set_obj(name, new_value, save_yaml=save_yaml)
self._mutables = []

def dump_userconfig(self):
@@ -467,6 +481,7 @@ def init(parent=None):

new_config = NewConfigManager(parent)
objreg.register('config', new_config)

config_commands = ConfigCommands(new_config)
@@ -20,11 +20,12 @@
"""Configuration files residing on disk."""

import os.path
import textwrap
import configparser

from PyQt5.QtCore import QSettings

from qutebrowser.utils import objreg, standarddir
from qutebrowser.utils import objreg, standarddir, utils, qtutils

class StateConfig(configparser.ConfigParser):
@@ -51,6 +52,37 @@ def _save(self):

class YamlConfig:

"""A config stored on disk as YAML file."""

def __init__(self):
save_manager = objreg.get('save-manager')
self._filename = os.path.join(standarddir.config(), 'autoconfig.yml')
save_manager.add_saveable('yaml-config', self._save)
self.values = {}

def _save(self):
"""Save the changed settings to the YAML file."""
data = {'global': self.values}
with qtutils.savefile_open(self._filename) as f:
# DO NOT edit this file by hand, qutebrowser will overwrite it.
# Instead, create a - see :help for details.
utils.yaml_dump(data, f)

def load(self):
"""Load self.values from the configured YAML file."""
# FIXME:conf error handling
with open(self._filename, 'r', encoding='utf-8') as f:
self.values = utils.yaml_load(f)['global']
except FileNotFoundError:

def init(config):
"""Initialize config storage not related to the main config."""
state = StateConfig()

0 comments on commit 6375530

Please sign in to comment.
You can’t perform that action at this time.