Skip to content

Commit

Permalink
Merge cf47db8 into 875d3f1
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartleeks committed Apr 17, 2021
2 parents 875d3f1 + cf47db8 commit b05c8ab
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 4 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -434,6 +434,7 @@ Several *The Fuck* parameters can be changed in the file `$XDG_CONFIG_HOME/thefu
* `wait_slow_command` – max amount of time in seconds for getting previous command output if it in `slow_commands` list;
* `slow_commands` – list of slow commands;
* `num_close_matches` – maximum number of close matches to suggest, by default `3`.
* `excluded_search_path_prefixes` – path prefixes to ignore when searching for commands, by default `[]`.

An example of `settings.py`:

Expand Down Expand Up @@ -466,6 +467,7 @@ rule with lower `priority` will be matched first;
* `THEFUCK_WAIT_SLOW_COMMAND` – max amount of time in seconds for getting previous command output if it in `slow_commands` list;
* `THEFUCK_SLOW_COMMANDS` – list of slow commands, like `lein:gradle`;
* `THEFUCK_NUM_CLOSE_MATCHES` – maximum number of close matches to suggest, like `5`.
* `THEFUCK_EXCLUDED_SEARCH_PATH_PREFIXES` – path prefixes to ignore when searching for commands, by default `[]`.

For example:

Expand Down
4 changes: 3 additions & 1 deletion tests/test_conf.py
Expand Up @@ -54,7 +54,8 @@ def test_from_env(self, os_environ, settings):
'THEFUCK_PRIORITY': 'bash=10:lisp=wrong:vim=15',
'THEFUCK_WAIT_SLOW_COMMAND': '999',
'THEFUCK_SLOW_COMMANDS': 'lein:react-native:./gradlew',
'THEFUCK_NUM_CLOSE_MATCHES': '359'})
'THEFUCK_NUM_CLOSE_MATCHES': '359',
'THEFUCK_EXCLUDED_SEARCH_PATH_PREFIXES': '/media/:/mnt/'})
settings.init()
assert settings.rules == ['bash', 'lisp']
assert settings.exclude_rules == ['git', 'vim']
Expand All @@ -65,6 +66,7 @@ def test_from_env(self, os_environ, settings):
assert settings.wait_slow_command == 999
assert settings.slow_commands == ['lein', 'react-native', './gradlew']
assert settings.num_close_matches == 359
assert settings.excluded_search_path_prefixes == ['/media/', '/mnt/']

def test_from_env_with_DEFAULT(self, os_environ, settings):
os_environ.update({'THEFUCK_RULES': 'DEFAULT_RULES:bash:lisp'})
Expand Down
14 changes: 14 additions & 0 deletions tests/test_utils.py
Expand Up @@ -94,6 +94,20 @@ def test_get_all_executables_pathsep(path, pathsep):
Path_mock.assert_has_calls([call(p) for p in path.split(pathsep)], True)


@pytest.mark.usefixtures('no_memoize', 'os_environ_pathsep')
@pytest.mark.parametrize('path, pathsep, excluded', [
('/foo:/bar:/baz:/foo/bar:/mnt/foo', ':', '/mnt/foo'),
(r'C:\\foo;C:\\bar;C:\\baz;C:\\foo\\bar;Z:\\foo', ';', r'Z:\\foo')])
def test_get_all_executables_exclude_paths(path, pathsep, excluded, settings):
settings.init()
settings.excluded_search_path_prefixes = [excluded]
with patch('thefuck.utils.Path') as Path_mock:
get_all_executables()
path_list = path.split(pathsep)
assert call(path_list[-1]) not in Path_mock.mock_calls
assert all(call(p) in Path_mock.mock_calls for p in path_list[:-1])


@pytest.mark.parametrize('args, result', [
(('apt-get instol vim', 'instol', 'install'), 'apt-get install vim'),
(('git brnch', 'brnch', 'branch'), 'git branch')])
Expand Down
2 changes: 1 addition & 1 deletion thefuck/conf.py
Expand Up @@ -101,7 +101,7 @@ def _val_from_env(self, env, attr):
elif attr in ('require_confirmation', 'no_colors', 'debug',
'alter_history', 'instant_mode'):
return val.lower() == 'true'
elif attr == 'slow_commands':
elif attr in ('slow_commands', 'excluded_search_path_prefixes'):
return val.split(':')
else:
return val
Expand Down
6 changes: 4 additions & 2 deletions thefuck/const.py
Expand Up @@ -43,7 +43,8 @@ def __repr__(self):
'repeat': False,
'instant_mode': False,
'num_close_matches': 3,
'env': {'LC_ALL': 'C', 'LANG': 'C', 'GIT_TRACE': '1'}}
'env': {'LC_ALL': 'C', 'LANG': 'C', 'GIT_TRACE': '1'},
'excluded_search_path_prefixes': []}

ENV_TO_ATTR = {'THEFUCK_RULES': 'rules',
'THEFUCK_EXCLUDE_RULES': 'exclude_rules',
Expand All @@ -58,7 +59,8 @@ def __repr__(self):
'THEFUCK_SLOW_COMMANDS': 'slow_commands',
'THEFUCK_REPEAT': 'repeat',
'THEFUCK_INSTANT_MODE': 'instant_mode',
'THEFUCK_NUM_CLOSE_MATCHES': 'num_close_matches'}
'THEFUCK_NUM_CLOSE_MATCHES': 'num_close_matches',
'THEFUCK_EXCLUDED_SEARCH_PATH_PREFIXES': 'excluded_search_path_prefixes'}

SETTINGS_HEADER = u"""# The Fuck settings file
#
Expand Down
5 changes: 5 additions & 0 deletions thefuck/utils.py
Expand Up @@ -104,6 +104,10 @@ def get_close_matches(word, possibilities, n=None, cutoff=0.6):
return difflib_get_close_matches(word, possibilities, n, cutoff)


def include_path_in_search(path):
return not any(path.startswith(x) for x in settings.excluded_search_path_prefixes)


@memoize
def get_all_executables():
from thefuck.shells import shell
Expand All @@ -119,6 +123,7 @@ def _safe(fn, fallback):

bins = [exe.name.decode('utf8') if six.PY2 else exe.name
for path in os.environ.get('PATH', '').split(os.pathsep)
if include_path_in_search(path)
for exe in _safe(lambda: list(Path(path).iterdir()), [])
if not _safe(exe.is_dir, True)
and exe.name not in tf_entry_points]
Expand Down

0 comments on commit b05c8ab

Please sign in to comment.