mirror of
https://github.com/nvbn/thefuck.git
synced 2025-01-31 02:01:13 +00:00
#357 Add exclude_rules
settings option
This commit is contained in:
parent
4ae2e9bbc4
commit
2f9db24ed1
@ -271,6 +271,7 @@ requires_output = True
|
|||||||
The Fuck has a few settings parameters which can be changed in `~/.thefuck/settings.py`:
|
The Fuck has a few settings parameters which can be changed in `~/.thefuck/settings.py`:
|
||||||
|
|
||||||
* `rules` – list of enabled rules, by default `thefuck.conf.DEFAULT_RULES`;
|
* `rules` – list of enabled rules, by default `thefuck.conf.DEFAULT_RULES`;
|
||||||
|
* `exclude_rules` – list of disabled rules, by default `[]`;
|
||||||
* `require_confirmation` – requires confirmation before running new command, by default `True`;
|
* `require_confirmation` – requires confirmation before running new command, by default `True`;
|
||||||
* `wait_command` – max amount of time in seconds for getting previous command output;
|
* `wait_command` – max amount of time in seconds for getting previous command output;
|
||||||
* `no_colors` – disable colored output;
|
* `no_colors` – disable colored output;
|
||||||
@ -281,6 +282,7 @@ Example of `settings.py`:
|
|||||||
|
|
||||||
```python
|
```python
|
||||||
rules = ['sudo', 'no_command']
|
rules = ['sudo', 'no_command']
|
||||||
|
exclude_rules = ['git_push']
|
||||||
require_confirmation = True
|
require_confirmation = True
|
||||||
wait_command = 10
|
wait_command = 10
|
||||||
no_colors = False
|
no_colors = False
|
||||||
@ -291,6 +293,7 @@ debug = False
|
|||||||
Or via environment variables:
|
Or via environment variables:
|
||||||
|
|
||||||
* `THEFUCK_RULES` – list of enabled rules, like `DEFAULT_RULES:rm_root` or `sudo:no_command`;
|
* `THEFUCK_RULES` – list of enabled rules, like `DEFAULT_RULES:rm_root` or `sudo:no_command`;
|
||||||
|
* `THEFUCK_EXCLUDE_RULES` – list of disabled rules, like `git_pull:git_push`;
|
||||||
* `THEFUCK_REQUIRE_CONFIRMATION` – require confirmation before running new command, `true/false`;
|
* `THEFUCK_REQUIRE_CONFIRMATION` – require confirmation before running new command, `true/false`;
|
||||||
* `THEFUCK_WAIT_COMMAND` – max amount of time in seconds for getting previous command output;
|
* `THEFUCK_WAIT_COMMAND` – max amount of time in seconds for getting previous command output;
|
||||||
* `THEFUCK_NO_COLORS` – disable colored output, `true/false`;
|
* `THEFUCK_NO_COLORS` – disable colored output, `true/false`;
|
||||||
@ -302,6 +305,7 @@ For example:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
export THEFUCK_RULES='sudo:no_command'
|
export THEFUCK_RULES='sudo:no_command'
|
||||||
|
export THEFUCK_EXCLUDE_RULES='git_pull:git_push'
|
||||||
export THEFUCK_REQUIRE_CONFIRMATION='true'
|
export THEFUCK_REQUIRE_CONFIRMATION='true'
|
||||||
export THEFUCK_WAIT_COMMAND=10
|
export THEFUCK_WAIT_COMMAND=10
|
||||||
export THEFUCK_NO_COLORS='false'
|
export THEFUCK_NO_COLORS='false'
|
||||||
|
@ -39,17 +39,20 @@ class TestSettingsFromFile(object):
|
|||||||
wait_command=10,
|
wait_command=10,
|
||||||
require_confirmation=True,
|
require_confirmation=True,
|
||||||
no_colors=True,
|
no_colors=True,
|
||||||
priority={'vim': 100})
|
priority={'vim': 100},
|
||||||
|
exclude_rules=['git'])
|
||||||
settings = conf.get_settings(Mock())
|
settings = conf.get_settings(Mock())
|
||||||
assert settings.rules == ['test']
|
assert settings.rules == ['test']
|
||||||
assert settings.wait_command == 10
|
assert settings.wait_command == 10
|
||||||
assert settings.require_confirmation is True
|
assert settings.require_confirmation is True
|
||||||
assert settings.no_colors is True
|
assert settings.no_colors is True
|
||||||
assert settings.priority == {'vim': 100}
|
assert settings.priority == {'vim': 100}
|
||||||
|
assert settings.exclude_rules == ['git']
|
||||||
|
|
||||||
def test_from_file_with_DEFAULT(self, load_source):
|
def test_from_file_with_DEFAULT(self, load_source):
|
||||||
load_source.return_value = Mock(rules=conf.DEFAULT_RULES + ['test'],
|
load_source.return_value = Mock(rules=conf.DEFAULT_RULES + ['test'],
|
||||||
wait_command=10,
|
wait_command=10,
|
||||||
|
exclude_rules=[],
|
||||||
require_confirmation=True,
|
require_confirmation=True,
|
||||||
no_colors=True)
|
no_colors=True)
|
||||||
settings = conf.get_settings(Mock())
|
settings = conf.get_settings(Mock())
|
||||||
@ -60,12 +63,14 @@ class TestSettingsFromFile(object):
|
|||||||
class TestSettingsFromEnv(object):
|
class TestSettingsFromEnv(object):
|
||||||
def test_from_env(self, environ):
|
def test_from_env(self, environ):
|
||||||
environ.update({'THEFUCK_RULES': 'bash:lisp',
|
environ.update({'THEFUCK_RULES': 'bash:lisp',
|
||||||
|
'THEFUCK_EXCLUDE_RULES': 'git:vim',
|
||||||
'THEFUCK_WAIT_COMMAND': '55',
|
'THEFUCK_WAIT_COMMAND': '55',
|
||||||
'THEFUCK_REQUIRE_CONFIRMATION': 'true',
|
'THEFUCK_REQUIRE_CONFIRMATION': 'true',
|
||||||
'THEFUCK_NO_COLORS': 'false',
|
'THEFUCK_NO_COLORS': 'false',
|
||||||
'THEFUCK_PRIORITY': 'bash=10:lisp=wrong:vim=15'})
|
'THEFUCK_PRIORITY': 'bash=10:lisp=wrong:vim=15'})
|
||||||
settings = conf.get_settings(Mock())
|
settings = conf.get_settings(Mock())
|
||||||
assert settings.rules == ['bash', 'lisp']
|
assert settings.rules == ['bash', 'lisp']
|
||||||
|
assert settings.exclude_rules == ['git', 'vim']
|
||||||
assert settings.wait_command == 55
|
assert settings.wait_command == 55
|
||||||
assert settings.require_confirmation is True
|
assert settings.require_confirmation is True
|
||||||
assert settings.no_colors is False
|
assert settings.no_colors is False
|
||||||
|
@ -22,23 +22,39 @@ def test_load_rule(mocker):
|
|||||||
|
|
||||||
|
|
||||||
class TestGetRules(object):
|
class TestGetRules(object):
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture
|
||||||
def glob(self, mocker):
|
def glob(self, mocker):
|
||||||
return mocker.patch('thefuck.corrector.Path.glob', return_value=[])
|
results = {}
|
||||||
|
mocker.patch('thefuck.corrector.Path.glob',
|
||||||
|
new_callable=lambda: lambda *_: results.pop('value', []))
|
||||||
|
return lambda value: results.update({'value': value})
|
||||||
|
|
||||||
def _compare_names(self, rules, names):
|
@pytest.fixture(autouse=True)
|
||||||
return [r.name for r in rules] == names
|
def load_source(self, monkeypatch):
|
||||||
|
|
||||||
@pytest.mark.parametrize('conf_rules, rules', [
|
|
||||||
(conf.DEFAULT_RULES, ['bash', 'lisp', 'bash', 'lisp']),
|
|
||||||
(types.RulesNamesList(['bash']), ['bash', 'bash'])])
|
|
||||||
def test_get(self, monkeypatch, glob, conf_rules, rules):
|
|
||||||
glob.return_value = [PosixPath('bash.py'), PosixPath('lisp.py')]
|
|
||||||
monkeypatch.setattr('thefuck.corrector.load_source',
|
monkeypatch.setattr('thefuck.corrector.load_source',
|
||||||
lambda x, _: Rule(x))
|
lambda x, _: Rule(x))
|
||||||
assert self._compare_names(
|
|
||||||
corrector.get_rules(Path('~'), Mock(rules=conf_rules, priority={})),
|
def _compare_names(self, rules, names):
|
||||||
rules)
|
assert {r.name for r in rules} == set(names)
|
||||||
|
|
||||||
|
def _prepare_rules(self, rules):
|
||||||
|
if rules == conf.DEFAULT_RULES:
|
||||||
|
return rules
|
||||||
|
else:
|
||||||
|
return types.RulesNamesList(rules)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('paths, conf_rules, exclude_rules, loaded_rules', [
|
||||||
|
(['git.py', 'bash.py'], conf.DEFAULT_RULES, [], ['git', 'bash']),
|
||||||
|
(['git.py', 'bash.py'], ['git'], [], ['git']),
|
||||||
|
(['git.py', 'bash.py'], conf.DEFAULT_RULES, ['git'], ['bash']),
|
||||||
|
(['git.py', 'bash.py'], ['git'], ['git'], [])])
|
||||||
|
def test_get_rules(self, glob, paths, conf_rules, exclude_rules, loaded_rules):
|
||||||
|
glob([PosixPath(path) for path in paths])
|
||||||
|
settings = Mock(rules=self._prepare_rules(conf_rules),
|
||||||
|
priority={},
|
||||||
|
exclude_rules=self._prepare_rules(exclude_rules))
|
||||||
|
rules = corrector.get_rules(Path('~'), settings)
|
||||||
|
self._compare_names(rules, loaded_rules)
|
||||||
|
|
||||||
|
|
||||||
class TestIsRuleMatch(object):
|
class TestIsRuleMatch(object):
|
||||||
|
@ -26,6 +26,7 @@ DEFAULT_PRIORITY = 1000
|
|||||||
|
|
||||||
|
|
||||||
DEFAULT_SETTINGS = {'rules': DEFAULT_RULES,
|
DEFAULT_SETTINGS = {'rules': DEFAULT_RULES,
|
||||||
|
'exclude_rules': [],
|
||||||
'wait_command': 3,
|
'wait_command': 3,
|
||||||
'require_confirmation': True,
|
'require_confirmation': True,
|
||||||
'no_colors': False,
|
'no_colors': False,
|
||||||
@ -34,6 +35,7 @@ DEFAULT_SETTINGS = {'rules': DEFAULT_RULES,
|
|||||||
'env': {'LC_ALL': 'C', 'LANG': 'C', 'GIT_TRACE': '1'}}
|
'env': {'LC_ALL': 'C', 'LANG': 'C', 'GIT_TRACE': '1'}}
|
||||||
|
|
||||||
ENV_TO_ATTR = {'THEFUCK_RULES': 'rules',
|
ENV_TO_ATTR = {'THEFUCK_RULES': 'rules',
|
||||||
|
'THEFUCK_EXCLUDE_RULES': 'exclude_rules',
|
||||||
'THEFUCK_WAIT_COMMAND': 'wait_command',
|
'THEFUCK_WAIT_COMMAND': 'wait_command',
|
||||||
'THEFUCK_REQUIRE_CONFIRMATION': 'require_confirmation',
|
'THEFUCK_REQUIRE_CONFIRMATION': 'require_confirmation',
|
||||||
'THEFUCK_NO_COLORS': 'no_colors',
|
'THEFUCK_NO_COLORS': 'no_colors',
|
||||||
@ -84,7 +86,7 @@ def _priority_from_env(val):
|
|||||||
def _val_from_env(env, attr):
|
def _val_from_env(env, attr):
|
||||||
"""Transforms env-strings to python."""
|
"""Transforms env-strings to python."""
|
||||||
val = os.environ[env]
|
val = os.environ[env]
|
||||||
if attr == 'rules':
|
if attr in ('rules', 'exclude_rules'):
|
||||||
return _rules_from_env(val)
|
return _rules_from_env(val)
|
||||||
elif attr == 'priority':
|
elif attr == 'priority':
|
||||||
return dict(_priority_from_env(val))
|
return dict(_priority_from_env(val))
|
||||||
@ -123,6 +125,9 @@ def get_settings(user_dir):
|
|||||||
if not isinstance(conf['rules'], types.RulesNamesList):
|
if not isinstance(conf['rules'], types.RulesNamesList):
|
||||||
conf['rules'] = types.RulesNamesList(conf['rules'])
|
conf['rules'] = types.RulesNamesList(conf['rules'])
|
||||||
|
|
||||||
|
if not isinstance(conf['exclude_rules'], types.RulesNamesList):
|
||||||
|
conf['exclude_rules'] = types.RulesNamesList(conf['exclude_rules'])
|
||||||
|
|
||||||
return types.Settings(conf)
|
return types.Settings(conf)
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@ def get_loaded_rules(rules, settings):
|
|||||||
for rule in rules:
|
for rule in rules:
|
||||||
if rule.name != '__init__.py':
|
if rule.name != '__init__.py':
|
||||||
loaded_rule = load_rule(rule, settings)
|
loaded_rule = load_rule(rule, settings)
|
||||||
if loaded_rule in settings.rules:
|
if loaded_rule in settings.rules and \
|
||||||
|
loaded_rule not in settings.exclude_rules:
|
||||||
yield loaded_rule
|
yield loaded_rule
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user