diff --git a/qutebrowser/config/configcommands.py b/qutebrowser/config/configcommands.py index 6c5fa847e..01fd9950b 100644 --- a/qutebrowser/config/configcommands.py +++ b/qutebrowser/config/configcommands.py @@ -300,6 +300,59 @@ class ConfigCommands: option_value[key] = value self._config.update_mutables(save_yaml=not temp) + @cmdutils.register(instance='config-commands') + @cmdutils.argument('option', completion=configmodel.list_option) + def config_remove_list(self, option, value, temp=False): + """Remove a value from a list. + + Args: + option: The name of the option. + value: The value to remove from the list. + temp: Set value temporarily until qutebrowser is closed. + """ + opt = self._config.get_opt(option) + valid_list_types = (configtypes.List, configtypes.ListOrValue) + if not isinstance(opt.typ, valid_list_types): + raise cmdexc.CommandError(":config-remove-list can only be used " + "for lists") + + with self._handle_config_error(): + option_value = self._config.get_mutable_obj(option) + + if value not in option_value: + raise cmdexc.CommandError("{} is not in {}!".format(value, + option)) + + option_value.remove(value) + + self._config.update_mutables(save_yaml=not temp) + + @cmdutils.register(instance='config-commands') + @cmdutils.argument('option', completion=configmodel.dict_option) + def config_remove_dict(self, option, key, temp=False): + """Remove a key from a dict. + + Args: + option: The name of the option. + key: The key to remove from the dict. + temp: Set value temporarily until qutebrowser is closed. + """ + opt = self._config.get_opt(option) + if not isinstance(opt.typ, configtypes.Dict): + raise cmdexc.CommandError(":config-remove-dict can only be used " + "for dicts") + + with self._handle_config_error(): + option_value = self._config.get_mutable_obj(option) + + if key not in option_value: + raise cmdexc.CommandError("{} is not in {}!".format(key, + option)) + + del option_value[key] + + self._config.update_mutables(save_yaml=not temp) + @cmdutils.register(instance='config-commands') def config_clear(self, save=False): """Set all settings back to their default. diff --git a/tests/unit/config/test_configcommands.py b/tests/unit/config/test_configcommands.py index 249357010..4bf3b7691 100644 --- a/tests/unit/config/test_configcommands.py +++ b/tests/unit/config/test_configcommands.py @@ -355,6 +355,61 @@ class TestAdd: commands.config_add_dict('aliases', 'missingkey', value) +class TestRemove: + + """Test :config-add-list and :config-add-dict.""" + + @pytest.mark.parametrize('value', ['25%', '50%']) + @pytest.mark.parametrize('temp', [True, False]) + def test_remove_list(self, commands, config_stub, yaml_value, value, temp): + name = 'zoom.levels' + commands.config_remove_list(name, value, temp=temp) + + assert value not in config_stub.get(name) + if temp: + assert yaml_value(name) == configutils.UNSET + else: + assert value not in yaml_value(name) + + def test_remove_list_non_list(self, commands): + with pytest.raises( + cmdexc.CommandError, + match=":config-remove-list can only be used for lists"): + commands.config_remove_list('content.javascript.enabled', + 'never') + + def test_remove_list_no_value(self, commands): + with pytest.raises( + cmdexc.CommandError, + match="never is not in colors.completion.fg!"): + commands.config_remove_list('colors.completion.fg', 'never') + + @pytest.mark.parametrize('key', ['w', 'q']) + @pytest.mark.parametrize('temp', [True, False]) + def test_remove_dict(self, commands, config_stub, yaml_value, key, temp): + name = 'aliases' + commands.config_remove_dict(name, key, temp=temp) + + assert key not in config_stub.get(name) + if temp: + assert yaml_value(name) == configutils.UNSET + else: + assert key not in yaml_value(name) + + def test_remove_dict_non_dict(self, commands): + with pytest.raises( + cmdexc.CommandError, + match=":config-remove-dict can only be used for dicts"): + commands.config_remove_dict('content.javascript.enabled', + 'never') + + def test_remove_dict_no_value(self, commands): + with pytest.raises( + cmdexc.CommandError, + match="never is not in aliases!"): + commands.config_remove_dict('aliases', 'never') + + class TestUnsetAndClear: """Test :config-unset and :config-clear."""