Bring back :set

This commit is contained in:
Florian Bruhin 2017-06-16 14:31:56 +02:00
parent 30f1970850
commit 46d0fee11b
2 changed files with 103 additions and 140 deletions

View File

@ -669,137 +669,6 @@ class ConfigManager(QObject):
self.get.cache_clear()
return existed
@functools.lru_cache()
def get(self, sectname, optname, raw=False, transformed=True,
fallback=UNSET):
"""Get the value from a section/option.
We don't support the vars argument from configparser.get as it's not
hashable.
Args:
sectname: The section to get the option from.
optname: The option name
raw: Whether to get the uninterpolated, untransformed value.
transformed: Whether the value should be transformed.
Return:
The value of the option.
"""
if not self._initialized:
raise Exception("get got called before initialization was "
"complete!")
try:
sect = self.sections[sectname]
except KeyError:
if fallback is not UNSET:
return fallback
raise configexc.NoSectionError(sectname)
try:
val = sect[optname]
except KeyError:
if fallback is not UNSET:
return fallback
raise configexc.NoOptionError(optname, sectname)
if raw:
return val.value()
mapping = {key: val.value() for key, val in sect.values.items()}
newval = self._interpolation.before_get(self, sectname, optname,
val.value(), mapping)
if transformed:
newval = val.typ.transform(newval)
return newval
@contextlib.contextmanager
def _handle_config_error(self):
"""Catch errors in set_command and raise CommandError."""
try:
yield
except (configexc.NoOptionError, configexc.NoSectionError,
configexc.ValidationError) as e:
raise cmdexc.CommandError("set: {}".format(e))
except (configexc.Error, configparser.Error) as e:
raise cmdexc.CommandError("set: {} - {}".format(
e.__class__.__name__, e))
@cmdutils.register(name='set', instance='config', star_args_optional=True)
@cmdutils.argument('win_id', win_id=True)
def set_command(self, win_id, section_=None, option=None, *values,
temp=False, print_=False):
"""Set an option.
If the option name ends with '?', the value of the option is shown
instead.
If the option name ends with '!' and it is a boolean value, toggle it.
//
Wrapper for self.set() to output exceptions in the status bar.
Args:
section_: The section where the option is in.
option: The name of the option.
values: The value to set, or the values to cycle through.
temp: Set value temporarily.
print_: Print the value after setting.
"""
if section_ is not None and option is None:
raise cmdexc.CommandError(
"set: Either both section and option have to be given, or "
"neither!")
if section_ is None and option is None:
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
tabbed_browser.openurl(QUrl('qute://settings'), newtab=False)
return
if option.endswith('?') and option != '?':
option = option[:-1]
print_ = True
else:
with self._handle_config_error():
if option.endswith('!') and option != '!' and not values:
# Handle inversion as special cases of the cycle code path
option = option[:-1]
val = self.get(section_, option)
if isinstance(val, bool):
values = ['false', 'true']
else:
raise cmdexc.CommandError(
"set: Attempted inversion of non-boolean value.")
elif not values:
raise cmdexc.CommandError("set: The following arguments "
"are required: value")
layer = 'temp' if temp else 'conf'
self._set_next(layer, section_, option, values)
if print_:
with self._handle_config_error():
val = self.get(section_, option, transformed=False)
message.info("{} {} = {}".format(section_, option, val))
def _set_next(self, layer, section_, option, values):
"""Set the next value out of a list of 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.set(layer, section_, option, values[0])
else:
# Otherwise, use the next valid value from values, or the
# first if the current value does not appear in the list
assert len(values) > 1
val = self.get(section_, option, transformed=False)
try:
idx = values.index(str(val))
idx = (idx + 1) % len(values)
value = values[idx]
except ValueError:
value = values[0]
self.set(layer, section_, option, value)
def set(self, layer, sectname, optname, value, validate=True):
"""Set an option.

View File

@ -19,12 +19,14 @@
"""New qutebrowser configuration code."""
import contextlib
import functools
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtCore import pyqtSignal, QObject, QUrl
from qutebrowser.config import configdata, configexc
from qutebrowser.utils import utils, objreg
from qutebrowser.config import configdata, configexc, configtypes
from qutebrowser.utils import utils, objreg, message
from qutebrowser.commands import cmdexc, cmdutils
# An easy way to access the config from other code via config.val.foo
val = None
@ -130,6 +132,95 @@ class NewKeyConfig:
return cmd_to_keys
class ConfigCommands:
def __init__(self, config):
self._config = config
@cmdutils.register(instance='config-commands', star_args_optional=True)
@cmdutils.argument('win_id', win_id=True)
def set(self, win_id, option=None, *values, temp=False, print_=False):
"""Set an option.
If the option name ends with '?', the value of the option is shown
instead.
If the option name ends with '!' and it is a boolean value, toggle it.
//
Args:
option: The name of the option.
values: The value to set, or the values to cycle through.
temp: Set value temporarily.
print_: Print the value after setting.
"""
# FIXME:conf write to YAML if temp isn't used!
if option is None:
tabbed_browser = objreg.get('tabbed-browser', scope='window',
window=win_id)
tabbed_browser.openurl(QUrl('qute://settings'), newtab=False)
return
if option.endswith('?') and option != '?':
self._print_value(option[:-1])
return
with self._handle_config_error():
if option.endswith('!') and option != '!' and not values:
# Handle inversion as special cases of the cycle code path
option = option[:-1]
opt = self._config.get_opt(option)
if opt.typ is configtypes.Bool:
values = ['false', 'true']
else:
raise cmdexc.CommandError(
"set: Attempted inversion of non-boolean value.")
elif not values:
raise cmdexc.CommandError("set: The following arguments "
"are required: value")
self._set_next(option, values)
if print_:
self._print_value(option)
def _print_value(self, option):
"""Print the value of the given option."""
with self._handle_config_error():
val = self._config.get_str(option)
message.info("{} = {}".format(option, val))
def _set_next(self, option, values):
"""Set the next value out of a list of 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(option, values[0])
return
# Use the next valid value from values, or the first if the current
# value does not appear in the list
val = self._config.get_str(option)
try:
idx = values.index(str(val))
idx = (idx + 1) % len(values)
value = values[idx]
except ValueError:
value = values[0]
self._config.set(option, value)
@contextlib.contextmanager
def _handle_config_error(self):
"""Catch errors in set_command and raise CommandError."""
try:
yield
except (configexc.NoOptionError, configexc.ValidationError) as e:
raise cmdexc.CommandError("set: {}".format(e))
except configexc.Error as e:
raise cmdexc.CommandError("set: {} - {}".format(
e.__class__.__name__, e))
class NewConfigManager(QObject):
changed = pyqtSignal(str) # FIXME:conf stub...
@ -143,19 +234,19 @@ class NewConfigManager(QObject):
for name, option in configdata.DATA.items():
self.options[name] = option
def get(self, name):
def get_opt(self, name):
try:
opt = self.options[name]
return self.options[name]
except KeyError:
raise configexc.NoOptionError(name)
def get(self, name):
opt = self.get_opt(name)
value = self._values.get(name, opt.default)
return opt.typ.to_py(value)
def get_str(self, name):
try:
opt = self.options[name]
except KeyError:
raise configexc.NoOptionError(name)
opt = self.get_opt(name)
return opt.typ.to_str(opt.default)
def set(self, name, value):
@ -220,6 +311,9 @@ def init(parent):
new_config.read_defaults()
objreg.register('config', new_config)
config_commands = ConfigCommands(new_config)
objreg.register('config-commands', config_commands)
global val, instance, key_instance
val = ConfigContainer(new_config)
instance = new_config