parent
8a60855b88
commit
34815f5cf8
@ -71,6 +71,8 @@ Changed
|
||||
* Yes/no prompts don't use keybindings from the `prompt` section anymore, they
|
||||
have their own `yesno` section instead.
|
||||
* Trying to bind invalid keys now shows an error.
|
||||
* The `bindings.default` setting can now only be set in a `config.py`, and
|
||||
existing values in `autoconfig.yml` are ignored.
|
||||
- Improvements for GreaseMonkey support:
|
||||
* `@include` and `@exclude` now support regex matches. With QtWebEngine and Qt
|
||||
5.8 and newer, Qt handles the matching, but similar functionality will be
|
||||
|
@ -376,6 +376,8 @@ Default keybindings. If you want to add bindings, modify `bindings.commands` ins
|
||||
The main purpose of this setting is that you can set it to an empty dictionary if you want to load no default keybindings at all.
|
||||
If you want to preserve default bindings (and get new bindings when there is an update), use `config.bind()` in `config.py` or the `:bind` command, and leave this setting alone.
|
||||
|
||||
This setting can only be set in config.py.
|
||||
|
||||
Type: <<types,Dict>>
|
||||
|
||||
Default:
|
||||
|
@ -29,7 +29,8 @@ def option(*, info):
|
||||
"""A CompletionModel filled with settings and their descriptions."""
|
||||
model = completionmodel.CompletionModel(column_widths=(20, 70, 10))
|
||||
options = ((opt.name, opt.description, info.config.get_str(opt.name))
|
||||
for opt in configdata.DATA.values())
|
||||
for opt in configdata.DATA.values()
|
||||
if not opt.no_autoconfig)
|
||||
model.add_category(listcategory.ListCategory("Options", options))
|
||||
return model
|
||||
|
||||
|
@ -286,6 +286,11 @@ class Config(QObject):
|
||||
log.config.debug("Config option changed: {} = {}".format(
|
||||
opt.name, value))
|
||||
|
||||
def _check_yaml(self, opt, save_yaml):
|
||||
"""Make sure the given option may be set in autoconfig.yml."""
|
||||
if save_yaml and opt.no_autoconfig:
|
||||
raise configexc.NoAutoconfigError(opt.name)
|
||||
|
||||
def read_yaml(self):
|
||||
"""Read the YAML settings from self._yaml."""
|
||||
self._yaml.load()
|
||||
@ -383,7 +388,9 @@ class Config(QObject):
|
||||
|
||||
If save_yaml=True is given, store the new value to YAML.
|
||||
"""
|
||||
self._set_value(self.get_opt(name), value, pattern=pattern)
|
||||
opt = self.get_opt(name)
|
||||
self._check_yaml(opt, save_yaml)
|
||||
self._set_value(opt, value, pattern=pattern)
|
||||
if save_yaml:
|
||||
self._yaml.set_obj(name, value, pattern=pattern)
|
||||
|
||||
@ -393,6 +400,7 @@ class Config(QObject):
|
||||
If save_yaml=True is given, store the new value to YAML.
|
||||
"""
|
||||
opt = self.get_opt(name)
|
||||
self._check_yaml(opt, save_yaml)
|
||||
converted = opt.typ.from_str(value)
|
||||
log.config.debug("Setting {} (type {}) to {!r} (converted from {!r})"
|
||||
.format(name, opt.typ.__class__.__name__, converted,
|
||||
@ -403,7 +411,8 @@ class Config(QObject):
|
||||
|
||||
def unset(self, name, *, save_yaml=False, pattern=None):
|
||||
"""Set the given setting back to its default."""
|
||||
self.get_opt(name) # To check whether it exists
|
||||
opt = self.get_opt(name)
|
||||
self._check_yaml(opt, save_yaml)
|
||||
changed = self._values[name].remove(pattern)
|
||||
if changed:
|
||||
self.changed.emit(name)
|
||||
|
@ -50,6 +50,7 @@ class Option:
|
||||
description = attr.ib()
|
||||
supports_pattern = attr.ib(default=False)
|
||||
restart = attr.ib(default=False)
|
||||
no_autoconfig = attr.ib(default=False)
|
||||
|
||||
|
||||
@attr.s
|
||||
@ -199,7 +200,7 @@ def _read_yaml(yaml_data):
|
||||
data = utils.yaml_load(yaml_data)
|
||||
|
||||
keys = {'type', 'default', 'desc', 'backend', 'restart',
|
||||
'supports_pattern'}
|
||||
'supports_pattern', 'no_autoconfig'}
|
||||
|
||||
for name, option in data.items():
|
||||
if set(option.keys()) == {'renamed'}:
|
||||
@ -227,6 +228,7 @@ def _read_yaml(yaml_data):
|
||||
description=option['desc'],
|
||||
restart=option.get('restart', False),
|
||||
supports_pattern=option.get('supports_pattern', False),
|
||||
no_autoconfig=option.get('no_autoconfig', False),
|
||||
)
|
||||
|
||||
# Make sure no key shadows another.
|
||||
|
@ -2177,6 +2177,7 @@ bindings.key_mappings:
|
||||
`bindings.commands`), the mapping is ignored.
|
||||
|
||||
bindings.default:
|
||||
no_autoconfig: true
|
||||
default:
|
||||
normal:
|
||||
<Escape>: clear-keychain ;; search ;; fullscreen --leave
|
||||
|
@ -31,6 +31,15 @@ class Error(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class NoAutoconfigError(Error):
|
||||
|
||||
"""Raised when this option can't be set in autoconfig.yml."""
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__("The {} setting can only be set in config.py!"
|
||||
.format(name))
|
||||
|
||||
|
||||
class BackendError(Error):
|
||||
|
||||
"""Raised when this setting is unavailable with the current backend."""
|
||||
|
@ -262,6 +262,12 @@ class YamlConfig(QObject):
|
||||
del settings[old]
|
||||
self._mark_changed()
|
||||
|
||||
# bindings.default can't be set in autoconfig.yml anymore, so ignore
|
||||
# old values.
|
||||
if 'bindings.default' in settings:
|
||||
del settings['bindings.default']
|
||||
self._mark_changed()
|
||||
|
||||
return settings
|
||||
|
||||
def _validate(self, settings):
|
||||
|
@ -33,7 +33,7 @@ input { width: 98%; }
|
||||
<th>Setting</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
{% for option in configdata.DATA.values() %}
|
||||
{% for option in configdata.DATA.values() if not option.no_autoconfig %}
|
||||
<tr>
|
||||
<!-- FIXME: convert to string properly -->
|
||||
<td class="setting">{{ option.name }} (Current: {{ confget(option.name) | string |truncate(100) }})
|
||||
|
@ -421,6 +421,8 @@ def _generate_setting_option(f, opt):
|
||||
f.write("This setting requires a restart.\n")
|
||||
if opt.supports_pattern:
|
||||
f.write("\nThis setting supports URL patterns.\n")
|
||||
if opt.no_autoconfig:
|
||||
f.write("\nThis setting can only be set in config.py.\n")
|
||||
f.write("\n")
|
||||
typ = opt.typ.get_name().replace(',', ',')
|
||||
f.write('Type: <<types,{typ}>>\n'.format(typ=typ))
|
||||
|
@ -111,7 +111,8 @@ def configdata_stub(config_stub, monkeypatch, configdata_init):
|
||||
])
|
||||
},
|
||||
backends=[],
|
||||
raw_backends=None)),
|
||||
raw_backends=None,
|
||||
no_autoconfig=True)),
|
||||
('bindings.commands', configdata.Option(
|
||||
name='bindings.commands',
|
||||
description='Default keybindings',
|
||||
@ -655,8 +656,6 @@ def test_setting_option_completion(qtmodeltester, config_stub,
|
||||
('bindings.commands', 'Default keybindings', (
|
||||
'{"normal": {"<Ctrl+q>": "quit", "ZQ": "quit", '
|
||||
'"I": "invalid", "d": "scroll down"}}')),
|
||||
('bindings.default', 'Default keybindings',
|
||||
'{"normal": {"<Ctrl+q>": "quit", "d": "tab-close"}}'),
|
||||
('content.javascript.enabled', 'Enable/Disable JavaScript',
|
||||
'true'),
|
||||
]
|
||||
|
@ -621,6 +621,34 @@ class TestConfig:
|
||||
meth('content.cookies.accept', 'all')
|
||||
assert not conf._values['content.cookies.accept']
|
||||
|
||||
@pytest.mark.parametrize('method, value', [
|
||||
('set_obj', {}),
|
||||
('set_str', '{}'),
|
||||
])
|
||||
def test_set_no_autoconfig_save(self, conf, qtbot, yaml_value,
|
||||
method, value):
|
||||
meth = getattr(conf, method)
|
||||
option = 'bindings.default'
|
||||
with pytest.raises(configexc.NoAutoconfigError):
|
||||
with qtbot.assert_not_emitted(conf.changed):
|
||||
meth(option, value, save_yaml=True)
|
||||
|
||||
assert not conf._values[option]
|
||||
assert yaml_value(option) is configutils.UNSET
|
||||
|
||||
@pytest.mark.parametrize('method, value', [
|
||||
('set_obj', {}),
|
||||
('set_str', '{}'),
|
||||
])
|
||||
def test_set_no_autoconfig_no_save(self, conf, qtbot, yaml_value,
|
||||
method, value):
|
||||
meth = getattr(conf, method)
|
||||
option = 'bindings.default'
|
||||
with qtbot.wait_signal(conf.changed):
|
||||
meth(option, value)
|
||||
|
||||
assert conf._values[option]
|
||||
|
||||
@pytest.mark.parametrize('method', ['set_obj', 'set_str'])
|
||||
def test_set_no_pattern(self, conf, method, qtbot):
|
||||
meth = getattr(conf, method)
|
||||
|
@ -48,6 +48,12 @@ def test_no_option_error_clash():
|
||||
configexc.NoOptionError('opt', deleted=True, renamed='foo')
|
||||
|
||||
|
||||
def test_no_autoconfig_error():
|
||||
e = configexc.NoAutoconfigError('opt')
|
||||
expected = "The opt setting can only be set in config.py!"
|
||||
assert str(e) == expected
|
||||
|
||||
|
||||
def test_backend_error():
|
||||
e = configexc.BackendError('foo', usertypes.Backend.QtWebKit)
|
||||
expected = "The foo setting is not available with the QtWebKit backend!"
|
||||
|
@ -223,6 +223,16 @@ class TestYaml:
|
||||
mode = 'persist' if persist else 'normal'
|
||||
assert data['tabs.mode_on_change']['global'] == mode
|
||||
|
||||
def test_bindings_default(self, yaml, autoconfig):
|
||||
"""Make sure bindings.default gets removed from autoconfig.yml."""
|
||||
autoconfig.write({'bindings.default': {'global': '{}'}})
|
||||
|
||||
yaml.load()
|
||||
yaml._save()
|
||||
|
||||
data = autoconfig.read()
|
||||
assert 'bindings.default' not in data
|
||||
|
||||
def test_renamed_key_unknown_target(self, monkeypatch, yaml,
|
||||
autoconfig):
|
||||
"""A key marked as renamed with invalid name should raise an error."""
|
||||
|
Loading…
Reference in New Issue
Block a user