mirror of
https://github.com/nvbn/thefuck.git
synced 2025-11-01 23:51:59 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f74bbb7a9a | ||
|
|
d6c2c7266d | ||
|
|
51839e65cd | ||
|
|
d5ae3a6b41 | ||
|
|
9f421a17e5 | ||
|
|
9d9820676a | ||
|
|
5ec4909d2f | ||
|
|
c6d2766553 |
@@ -144,6 +144,7 @@ using the matched rule and runs it. Rules enabled by default are as follows:
|
||||
* `cd_correction` – spellchecks and correct failed cd commands;
|
||||
* `cd_mkdir` – creates directories before cd'ing into them;
|
||||
* `cd_parent` – changes `cd..` to `cd ..`;
|
||||
* `chmod_x` – add execution bit;
|
||||
* `composer_not_command` – fixes composer command name;
|
||||
* `cp_omitting_directory` – adds `-a` when you `cp` directory;
|
||||
* `cpp11` – adds missing `-std=c++11` to `g++` or `clang++`;
|
||||
@@ -221,6 +222,7 @@ Enabled by default only on specific platforms:
|
||||
* `apt_invalid_operation` – fixes invalid `apt` and `apt-get` calls, like `apt-get isntall vim`;
|
||||
* `brew_install` – fixes formula name for `brew install`;
|
||||
* `brew_unknown_command` – fixes wrong brew commands, for example `brew docto/brew doctor`;
|
||||
* `brew_update_formula` – turns `brew update <formula>` into `brew upgrade <formula>`;
|
||||
* `brew_upgrade` – appends `--all` to `brew upgrade` as per Homebrew's new behaviour;
|
||||
* `pacman` – installs app with `pacman` if it is not installed (uses `yaourt` if available);
|
||||
* `pacman_not_found` – fixes package name with `pacman` or `yaourt`.
|
||||
|
||||
2
setup.py
2
setup.py
@@ -26,7 +26,7 @@ elif (3, 0) < version < (3, 3):
|
||||
' ({}.{} detected).'.format(*version))
|
||||
sys.exit(-1)
|
||||
|
||||
VERSION = '3.8'
|
||||
VERSION = '3.9'
|
||||
|
||||
install_requires = ['psutil', 'colorama', 'six', 'decorator']
|
||||
extras_require = {':python_version<"3.4"': ['pathlib'],
|
||||
|
||||
30
tests/rules/test_brew_update_formula.py
Normal file
30
tests/rules/test_brew_update_formula.py
Normal file
@@ -0,0 +1,30 @@
|
||||
import pytest
|
||||
from tests.utils import Command
|
||||
from thefuck.rules.brew_update_formula import get_new_command, match
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def stderr():
|
||||
return ("Error: This command updates brew itself, and does not take formula"
|
||||
" names.\nUse 'brew upgrade <formula>'.")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def new_command(formula):
|
||||
return 'brew upgrade {}'.format(formula)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('script', ['brew update foo', 'brew update bar zap'])
|
||||
def test_match(stderr, script):
|
||||
assert match(Command(script=script, stderr=stderr))
|
||||
|
||||
|
||||
@pytest.mark.parametrize('script', ['brew upgrade foo', 'brew update'])
|
||||
def test_not_match(script):
|
||||
assert not match(Command(script=script, stderr=''))
|
||||
|
||||
|
||||
@pytest.mark.parametrize('script, formula, ', [
|
||||
('brew update foo', 'foo'), ('brew update bar zap', 'bar zap')])
|
||||
def test_get_new_command(stderr, new_command, script, formula):
|
||||
assert get_new_command(Command(script=script, stderr=stderr)) == new_command
|
||||
39
tests/rules/test_chmod_x.py
Normal file
39
tests/rules/test_chmod_x.py
Normal file
@@ -0,0 +1,39 @@
|
||||
import pytest
|
||||
from tests.utils import Command
|
||||
from thefuck.rules.chmod_x import match, get_new_command
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def file_exists(mocker):
|
||||
return mocker.patch('os.path.exists', return_value=True)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def file_access(mocker):
|
||||
return mocker.patch('os.access', return_value=False)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('file_exists', 'file_access')
|
||||
@pytest.mark.parametrize('script, stderr', [
|
||||
('./gradlew build', 'gradlew: Permission denied'),
|
||||
('./install.sh --help', 'install.sh: permission denied')])
|
||||
def test_match(script, stderr):
|
||||
assert match(Command(script, stderr=stderr))
|
||||
|
||||
|
||||
@pytest.mark.parametrize('script, stderr, exists, callable', [
|
||||
('./gradlew build', 'gradlew: Permission denied', True, True),
|
||||
('./gradlew build', 'gradlew: Permission denied', False, False),
|
||||
('./gradlew build', 'gradlew: error', True, False),
|
||||
('gradlew build', 'gradlew: Permission denied', True, False)])
|
||||
def test_not_match(file_exists, file_access, script, stderr, exists, callable):
|
||||
file_exists.return_value = exists
|
||||
file_access.return_value = callable
|
||||
assert not match(Command(script, stderr=stderr))
|
||||
|
||||
|
||||
@pytest.mark.parametrize('script, result', [
|
||||
('./gradlew build', 'chmod +x gradlew && ./gradlew build'),
|
||||
('./install.sh --help', 'chmod +x install.sh && ./install.sh --help')])
|
||||
def test_get_new_command(script, result):
|
||||
assert get_new_command(Command(script)) == result
|
||||
@@ -78,3 +78,12 @@ class TestFish(object):
|
||||
history_lines(['- cmd: ls', ' when: 1432613911',
|
||||
'- cmd: rm', ' when: 1432613916'])
|
||||
assert list(shell.get_history()) == ['ls', 'rm']
|
||||
|
||||
@pytest.mark.parametrize('entry, entry_utf8', [
|
||||
('ls', '- cmd: ls\n when: 1430707243\n'),
|
||||
(u'echo café', '- cmd: echo café\n when: 1430707243\n')])
|
||||
def test_put_to_history(self, entry, entry_utf8, builtins_open, mocker, shell):
|
||||
mocker.patch('thefuck.shells.fish.time', return_value=1430707243.3517463)
|
||||
shell.put_to_history(entry)
|
||||
builtins_open.return_value.__enter__.return_value. \
|
||||
write.assert_called_once_with(entry_utf8)
|
||||
|
||||
12
thefuck/rules/brew_update_formula.py
Normal file
12
thefuck/rules/brew_update_formula.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from thefuck.utils import for_app
|
||||
|
||||
|
||||
@for_app('brew', at_least=2)
|
||||
def match(command):
|
||||
return ('update' in command.script
|
||||
and "Error: This command updates brew itself" in command.stderr
|
||||
and "Use 'brew upgrade <formula>'" in command.stderr)
|
||||
|
||||
|
||||
def get_new_command(command):
|
||||
return command.script.replace('update', 'upgrade')
|
||||
15
thefuck/rules/chmod_x.py
Normal file
15
thefuck/rules/chmod_x.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import os
|
||||
from thefuck.shells import shell
|
||||
|
||||
|
||||
def match(command):
|
||||
return (command.script.startswith('./')
|
||||
and 'permission denied' in command.stderr.lower()
|
||||
and os.path.exists(command.script_parts[0])
|
||||
and not os.access(command.script_parts[0], os.X_OK))
|
||||
|
||||
|
||||
def get_new_command(command):
|
||||
return shell.and_(
|
||||
'chmod +x {}'.format(command.script_parts[0][2:]),
|
||||
command.script)
|
||||
@@ -22,8 +22,7 @@ shells = {'bash': Bash,
|
||||
def _get_shell():
|
||||
proc = Process(os.getpid())
|
||||
|
||||
while (proc is not None):
|
||||
name = None
|
||||
while proc is not None:
|
||||
try:
|
||||
name = proc.name()
|
||||
except TypeError:
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from subprocess import Popen, PIPE
|
||||
from time import time
|
||||
import os
|
||||
import sys
|
||||
import six
|
||||
from .. import logs
|
||||
from ..utils import DEVNULL, memoize, cache
|
||||
from .generic import Generic
|
||||
|
||||
@@ -65,3 +68,20 @@ class Fish(Generic):
|
||||
def how_to_configure(self):
|
||||
return (r"eval (thefuck --alias | tr '\n' ';')",
|
||||
'~/.config/fish/config.fish')
|
||||
|
||||
def put_to_history(self, command):
|
||||
try:
|
||||
return self._put_to_history(command)
|
||||
except IOError:
|
||||
logs.exception("Can't update history", sys.exc_info())
|
||||
|
||||
def _put_to_history(self, command_script):
|
||||
"""Puts command script to shell history."""
|
||||
history_file_name = self._get_history_file_name()
|
||||
if os.path.isfile(history_file_name):
|
||||
with open(history_file_name, 'a') as history:
|
||||
entry = self._get_history_line(command_script)
|
||||
if six.PY2:
|
||||
history.write(entry.encode('utf-8'))
|
||||
else:
|
||||
history.write(entry)
|
||||
|
||||
@@ -81,3 +81,11 @@ class Generic(object):
|
||||
|
||||
def _script_from_history(self, line):
|
||||
return line
|
||||
|
||||
def put_to_history(self, command):
|
||||
"""Adds fixed command to shell history.
|
||||
|
||||
In most of shells we change history on shell-level, but not
|
||||
all shells support it (Fish).
|
||||
|
||||
"""
|
||||
|
||||
@@ -280,6 +280,8 @@ class CorrectedCommand(object):
|
||||
"""
|
||||
if self.side_effect:
|
||||
compatibility_call(self.side_effect, old_cmd, self.script)
|
||||
if settings.alter_history:
|
||||
shell.put_to_history(self.script)
|
||||
# This depends on correct setting of PYTHONIOENCODING by the alias:
|
||||
logs.debug(u'PYTHONIOENCODING: {}'.format(
|
||||
os.environ.get('PYTHONIOENCODING', '!!not-set!!')))
|
||||
|
||||
Reference in New Issue
Block a user