diff --git a/README.md b/README.md index 3b3f098..f0618c3 100644 --- a/README.md +++ b/README.md @@ -227,7 +227,8 @@ using the matched rule and runs it. Rules enabled by default are as follows: * `tmux` – fixes `tmux` commands; * `unknown_command` – fixes hadoop hdfs-style "unknown command", for example adds missing '-' to the command on `hdfs dfs ls`; * `vagrant_up` – starts up the vagrant instance; -* `whois` – fixes `whois` command. +* `whois` – fixes `whois` command; +* `workon_doesnt_exists` – fixes `virtualenvwrapper` env name os suggests to create new. Enabled by default only on specific platforms: diff --git a/tests/rules/test_workon_doesnt_exists.py b/tests/rules/test_workon_doesnt_exists.py new file mode 100644 index 0000000..da86302 --- /dev/null +++ b/tests/rules/test_workon_doesnt_exists.py @@ -0,0 +1,30 @@ +import pytest +from thefuck.rules.workon_doesnt_exists import match, get_new_command +from tests.utils import Command + + +@pytest.fixture(autouse=True) +def envs(mocker): + return mocker.patch( + 'thefuck.rules.workon_doesnt_exists._get_all_environments', + return_value=['thefuck', 'code_view']) + + +@pytest.mark.parametrize('script', [ + 'workon tehfuck', 'workon code-view', 'workon new-env']) +def test_match(script): + assert match(Command(script)) + + +@pytest.mark.parametrize('script', [ + 'workon thefuck', 'workon code_view', 'work on tehfuck']) +def test_not_match(script): + assert not match(Command(script)) + + +@pytest.mark.parametrize('script, result', [ + ('workon tehfuck', 'workon thefuck'), + ('workon code-view', 'workon code_view'), + ('workon zzzz', 'mkvirtualenv zzzz')]) +def test_get_new_command(script, result): + assert get_new_command(Command(script))[0] == result diff --git a/thefuck/rules/workon_doesnt_exists.py b/thefuck/rules/workon_doesnt_exists.py new file mode 100644 index 0000000..e8c4df0 --- /dev/null +++ b/thefuck/rules/workon_doesnt_exists.py @@ -0,0 +1,36 @@ +try: + from pathlib import Path +except ImportError: + from pathlib2 import Path + +from thefuck.utils import for_app, replace_command, eager, memoize + + +@memoize +@eager +def _get_all_environments(): + root = Path('~/.virtualenvs').expanduser() + if not root.is_dir(): + return + + for child in root.iterdir(): + if child.is_dir(): + yield child.name + + +@for_app('workon') +def match(command): + return (len(command.script_parts) >= 2 + and command.script_parts[1] not in _get_all_environments()) + + +def get_new_command(command): + misspelled_env = command.script_parts[1] + create_new = u'mkvirtualenv {}'.format(misspelled_env) + + available = _get_all_environments() + if available: + return replace_command(command, misspelled_env, available) \ + + [create_new] + else: + return create_new