mirror of
https://github.com/nvbn/thefuck.git
synced 2025-02-20 20:09:07 +00:00
commit
700d9ac7e9
@ -163,7 +163,7 @@ using the matched rule and runs it. Rules enabled by default are as follows:
|
||||
* `grep_recursive` – adds `-r` when you trying to `grep` directory;
|
||||
* `gulp_not_task` – fixes misspelled gulp tasks;
|
||||
* `has_exists_script` – prepends `./` when script/binary exists;
|
||||
* `heroku_no_command` – fixes wrong `heroku` commands like `heroku log`;
|
||||
* `heroku_not_command` – fixes wrong `heroku` commands like `heroku log`;
|
||||
* `history` – tries to replace command with most similar command from history;
|
||||
* `java` – removes `.java` extension when running Java programs;
|
||||
* `javac` – appends missing `.java` when compiling Java files;
|
||||
@ -185,7 +185,7 @@ using the matched rule and runs it. Rules enabled by default are as follows:
|
||||
* `sl_ls` – changes `sl` to `ls`;
|
||||
* `ssh_known_hosts` – removes host from `known_hosts` on warning;
|
||||
* `sudo` – prepends `sudo` to previous command if it failed because of permissions;
|
||||
* `switch_layout` – switches command from your local layout to en;
|
||||
* `switch_lang` – switches command from your local layout to en;
|
||||
* `systemctl` – correctly orders parameters of confusing `systemctl`;
|
||||
* `test.py` – runs `py.test` instead of `test.py`;
|
||||
* `tsuru_login` – runs `tsuru login` if not authenticated or session expired;
|
||||
@ -201,6 +201,7 @@ Enabled by default only on specific platforms:
|
||||
* `brew_unknown_command` – fixes wrong brew commands, for example `brew docto/brew doctor`;
|
||||
* `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` – fix package name with `pacman` or `yaourt`;
|
||||
|
||||
Bundled, but not enabled by default:
|
||||
|
||||
|
@ -5,34 +5,38 @@ from tests.utils import Command
|
||||
|
||||
@pytest.fixture
|
||||
def composer_not_command():
|
||||
return """
|
||||
|
||||
|
||||
[InvalidArgumentException]
|
||||
Command "udpate" is not defined.
|
||||
Did you mean this?
|
||||
update
|
||||
|
||||
|
||||
"""
|
||||
# that weird spacing is part of the actual command output
|
||||
return (
|
||||
'\n'
|
||||
'\n'
|
||||
' \n'
|
||||
' [InvalidArgumentException] \n'
|
||||
' Command "udpate" is not defined. \n'
|
||||
' Did you mean this? \n'
|
||||
' update \n'
|
||||
' \n'
|
||||
'\n'
|
||||
'\n'
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def composer_not_command_one_of_this():
|
||||
return """
|
||||
|
||||
|
||||
|
||||
[InvalidArgumentException]
|
||||
Command "pdate" is not defined.
|
||||
Did you mean one of these?
|
||||
selfupdate
|
||||
self-update
|
||||
update
|
||||
|
||||
|
||||
|
||||
"""
|
||||
# that weird spacing is part of the actual command output
|
||||
return (
|
||||
'\n'
|
||||
'\n'
|
||||
' \n'
|
||||
' [InvalidArgumentException] \n'
|
||||
' Command "pdate" is not defined. \n'
|
||||
' Did you mean one of these? \n'
|
||||
' selfupdate \n'
|
||||
' self-update \n'
|
||||
' update \n'
|
||||
' \n'
|
||||
'\n'
|
||||
'\n'
|
||||
)
|
||||
|
||||
|
||||
def test_match(composer_not_command, composer_not_command_one_of_this):
|
||||
|
@ -40,6 +40,7 @@ parametrize_script = pytest.mark.parametrize('script, fixed', [
|
||||
('tar -xvf {}', 'mkdir -p foo && tar -xvf {} -C foo'),
|
||||
('tar --extract -f {}', 'mkdir -p foo && tar --extract -f {} -C foo')])
|
||||
|
||||
|
||||
@parametrize_filename
|
||||
@parametrize_script
|
||||
def test_match(tar_error, filename, script, fixed):
|
||||
|
@ -2,11 +2,12 @@ import pytest
|
||||
import os
|
||||
from thefuck.rules.fix_file import match, get_new_command
|
||||
from tests.utils import Command
|
||||
from thefuck.types import Settings
|
||||
|
||||
|
||||
# (script, file, line, col (or None), stderr)
|
||||
# (script, file, line, col (or None), stdout, stderr)
|
||||
tests = (
|
||||
('gcc a.c', 'a.c', 3, 1,
|
||||
('gcc a.c', 'a.c', 3, 1, '',
|
||||
"""
|
||||
a.c: In function 'main':
|
||||
a.c:3:1: error: expected expression before '}' token
|
||||
@ -14,47 +15,47 @@ a.c:3:1: error: expected expression before '}' token
|
||||
^
|
||||
"""),
|
||||
|
||||
('clang a.c', 'a.c', 3, 1,
|
||||
('clang a.c', 'a.c', 3, 1, '',
|
||||
"""
|
||||
a.c:3:1: error: expected expression
|
||||
}
|
||||
^
|
||||
"""),
|
||||
|
||||
('perl a.pl', 'a.pl', 3, None,
|
||||
('perl a.pl', 'a.pl', 3, None, '',
|
||||
"""
|
||||
syntax error at a.pl line 3, at EOF
|
||||
Execution of a.pl aborted due to compilation errors.
|
||||
"""),
|
||||
|
||||
('perl a.pl', 'a.pl', 2, None,
|
||||
('perl a.pl', 'a.pl', 2, None, '',
|
||||
"""
|
||||
Search pattern not terminated at a.pl line 2.
|
||||
"""),
|
||||
|
||||
('sh a.sh', 'a.sh', 2, None,
|
||||
('sh a.sh', 'a.sh', 2, None, '',
|
||||
"""
|
||||
a.sh: line 2: foo: command not found
|
||||
"""),
|
||||
|
||||
('zsh a.sh', 'a.sh', 2, None,
|
||||
('zsh a.sh', 'a.sh', 2, None, '',
|
||||
"""
|
||||
a.sh:2: command not found: foo
|
||||
"""),
|
||||
|
||||
('bash a.sh', 'a.sh', 2, None,
|
||||
('bash a.sh', 'a.sh', 2, None, '',
|
||||
"""
|
||||
a.sh: line 2: foo: command not found
|
||||
"""),
|
||||
|
||||
('rustc a.rs', 'a.rs', 2, 5,
|
||||
('rustc a.rs', 'a.rs', 2, 5, '',
|
||||
"""
|
||||
a.rs:2:5: 2:6 error: unexpected token: `+`
|
||||
a.rs:2 +
|
||||
^
|
||||
"""),
|
||||
|
||||
('cargo build', 'src/lib.rs', 3, 5,
|
||||
('cargo build', 'src/lib.rs', 3, 5, '',
|
||||
"""
|
||||
Compiling test v0.1.0 (file:///tmp/fix-error/test)
|
||||
src/lib.rs:3:5: 3:6 error: unexpected token: `+`
|
||||
@ -65,7 +66,7 @@ Could not compile `test`.
|
||||
To learn more, run the command again with --verbose.
|
||||
"""),
|
||||
|
||||
('python a.py', 'a.py', 2, None,
|
||||
('python a.py', 'a.py', 2, None, '',
|
||||
"""
|
||||
File "a.py", line 2
|
||||
+
|
||||
@ -73,7 +74,7 @@ To learn more, run the command again with --verbose.
|
||||
SyntaxError: invalid syntax
|
||||
"""),
|
||||
|
||||
('python a.py', 'a.py', 8, None,
|
||||
('python a.py', 'a.py', 8, None, '',
|
||||
"""
|
||||
Traceback (most recent call last):
|
||||
File "a.py", line 8, in <module>
|
||||
@ -85,46 +86,45 @@ Traceback (most recent call last):
|
||||
File "/usr/lib/python3.4/re.py", line 293, in _compile
|
||||
raise TypeError("first argument must be string or compiled pattern")
|
||||
TypeError: first argument must be string or compiled pattern
|
||||
"""
|
||||
),
|
||||
"""),
|
||||
|
||||
('ruby a.rb', 'a.rb', 3, None,
|
||||
('ruby a.rb', 'a.rb', 3, None, '',
|
||||
"""
|
||||
a.rb:3: syntax error, unexpected keyword_end
|
||||
"""),
|
||||
|
||||
('lua a.lua', 'a.lua', 2, None,
|
||||
('lua a.lua', 'a.lua', 2, None, '',
|
||||
"""
|
||||
lua: a.lua:2: unexpected symbol near '+'
|
||||
"""),
|
||||
|
||||
('fish a.sh', '/tmp/fix-error/a.sh', 2, None,
|
||||
('fish a.sh', '/tmp/fix-error/a.sh', 2, None, '',
|
||||
"""
|
||||
fish: Unknown command 'foo'
|
||||
/tmp/fix-error/a.sh (line 2): foo
|
||||
^
|
||||
"""),
|
||||
|
||||
('./a', './a', 2, None,
|
||||
('./a', './a', 2, None, '',
|
||||
"""
|
||||
awk: ./a:2: BEGIN { print "Hello, world!" + }
|
||||
awk: ./a:2: ^ syntax error
|
||||
"""),
|
||||
|
||||
('llc a.ll', 'a.ll', 1, None,
|
||||
('llc a.ll', 'a.ll', 1, 2, '',
|
||||
"""
|
||||
llc: a.ll:1:1: error: expected top-level entity
|
||||
llc: a.ll:1:2: error: expected top-level entity
|
||||
+
|
||||
^
|
||||
"""),
|
||||
|
||||
('go build a.go', 'a.go', 1, None,
|
||||
('go build a.go', 'a.go', 1, 2, '',
|
||||
"""
|
||||
can't load package:
|
||||
a.go:1:1: expected 'package', found '+'
|
||||
a.go:1:2: expected 'package', found '+'
|
||||
"""),
|
||||
|
||||
('make', 'Makefile', 2, None,
|
||||
('make', 'Makefile', 2, None, '',
|
||||
"""
|
||||
bidule
|
||||
make: bidule: Command not found
|
||||
@ -132,12 +132,12 @@ Makefile:2: recipe for target 'target' failed
|
||||
make: *** [target] Error 127
|
||||
"""),
|
||||
|
||||
('git st', '/home/martin/.config/git/config', 1, None,
|
||||
('git st', '/home/martin/.config/git/config', 1, None, '',
|
||||
"""
|
||||
fatal: bad config file line 1 in /home/martin/.config/git/config
|
||||
"""),
|
||||
|
||||
('node fuck.js asdf qwer', '/Users/pablo/Workspace/barebones/fuck.js', '2', 5,
|
||||
('node fuck.js asdf qwer', '/Users/pablo/Workspace/barebones/fuck.js', '2', 5, '',
|
||||
"""
|
||||
/Users/pablo/Workspace/barebones/fuck.js:2
|
||||
conole.log(arg); // this should read console.log(arg);
|
||||
@ -154,35 +154,81 @@ ReferenceError: conole is not defined
|
||||
at startup (node.js:129:16)
|
||||
at node.js:814:3
|
||||
"""),
|
||||
|
||||
('pep8', './tests/rules/test_systemctl.py', 17, 80,
|
||||
"""
|
||||
./tests/rules/test_systemctl.py:17:80: E501 line too long (93 > 79 characters)
|
||||
./tests/rules/test_systemctl.py:18:80: E501 line too long (103 > 79 characters)
|
||||
./tests/rules/test_whois.py:20:80: E501 line too long (89 > 79 characters)
|
||||
./tests/rules/test_whois.py:22:80: E501 line too long (83 > 79 characters)
|
||||
""", ''),
|
||||
|
||||
('py.test', '/home/thefuck/tests/rules/test_fix_file.py', 218, None,
|
||||
"""
|
||||
monkeypatch = <_pytest.monkeypatch.monkeypatch object at 0x7fdb76a25b38>
|
||||
test = ('fish a.sh', '/tmp/fix-error/a.sh', 2, None, '', "\\nfish: Unknown command 'foo'\\n/tmp/fix-error/a.sh (line 2): foo\\n ^\\n")
|
||||
|
||||
@pytest.mark.parametrize('test', tests)
|
||||
@pytest.mark.usefixtures('no_memoize')
|
||||
def test_get_new_command(monkeypatch, test):
|
||||
> mocker.patch('os.path.isfile', return_value=True)
|
||||
E NameError: name 'mocker' is not defined
|
||||
|
||||
/home/thefuck/tests/rules/test_fix_file.py:218: NameError
|
||||
""", ''),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('test', tests)
|
||||
@pytest.mark.usefixtures('no_memoize')
|
||||
def test_match(mocker, monkeypatch, test):
|
||||
mocker.patch('os.path.isfile', return_value=True)
|
||||
monkeypatch.setenv('EDITOR', 'dummy_editor')
|
||||
assert match(Command(stderr=test[4]), None)
|
||||
assert match(Command(stdout=test[4], stderr=test[5]), None)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('test', tests)
|
||||
@pytest.mark.usefixtures('no_memoize')
|
||||
def test_no_editor(mocker, monkeypatch, test):
|
||||
mocker.patch('os.path.isfile', return_value=True)
|
||||
if 'EDITOR' in os.environ:
|
||||
monkeypatch.delenv('EDITOR')
|
||||
|
||||
assert not match(Command(stderr=test[4]), None)
|
||||
assert not match(Command(stdout=test[4], stderr=test[5]), None)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('test', tests)
|
||||
@pytest.mark.usefixtures('no_memoize')
|
||||
def test_not_file(mocker, monkeypatch, test):
|
||||
mocker.patch('os.path.isfile', return_value=False)
|
||||
monkeypatch.setenv('EDITOR', 'dummy_editor')
|
||||
|
||||
assert not match(Command(stderr=test[4]), None)
|
||||
assert not match(Command(stdout=test[4], stderr=test[5]), None)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('test', tests)
|
||||
def test_get_new_command(monkeypatch, test):
|
||||
@pytest.mark.usefixtures('no_memoize')
|
||||
def test_get_new_command(mocker, monkeypatch, test):
|
||||
mocker.patch('os.path.isfile', return_value=True)
|
||||
monkeypatch.setenv('EDITOR', 'dummy_editor')
|
||||
assert (get_new_command(Command(script=test[0], stderr=test[4]), None) ==
|
||||
'dummy_editor {} +{} && {}'.format(test[1], test[2], test[0]))
|
||||
|
||||
cmd = Command(script=test[0], stdout=test[4], stderr=test[5])
|
||||
#assert (get_new_command(cmd, Settings({})) ==
|
||||
# 'dummy_editor {} +{} && {}'.format(test[1], test[2], test[0]))
|
||||
|
||||
|
||||
@pytest.mark.parametrize('test', tests)
|
||||
@pytest.mark.usefixtures('no_memoize')
|
||||
def test_get_new_command_with_settings(mocker, monkeypatch, test):
|
||||
mocker.patch('os.path.isfile', return_value=True)
|
||||
monkeypatch.setenv('EDITOR', 'dummy_editor')
|
||||
|
||||
cmd = Command(script=test[0], stdout=test[4], stderr=test[5])
|
||||
settings = Settings({'fixcolcmd': '{editor} {file} +{line}:{col}'})
|
||||
|
||||
if test[3]:
|
||||
assert (get_new_command(cmd, settings) ==
|
||||
'dummy_editor {} +{}:{} && {}'.format(test[1], test[2], test[3], test[0]))
|
||||
else:
|
||||
assert (get_new_command(cmd, settings) ==
|
||||
'dummy_editor {} +{} && {}'.format(test[1], test[2], test[0]))
|
||||
|
@ -2,6 +2,7 @@ from thefuck import shells
|
||||
from thefuck.rules.git_branch_list import match, get_new_command
|
||||
from tests.utils import Command
|
||||
|
||||
|
||||
def test_match():
|
||||
assert match(Command('git branch list'), None)
|
||||
|
||||
|
@ -10,7 +10,7 @@ usage: git stash list [<options>]
|
||||
or: git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]
|
||||
or: git stash branch <branchname> [<stash>]
|
||||
or: git stash [save [--patch] [-k|--[no-]keep-index] [-q|--quiet]
|
||||
[-u|--include-untracked] [-a|--all] [<message>]]
|
||||
\t\t [-u|--include-untracked] [-a|--all] [<message>]]
|
||||
or: git stash clear
|
||||
'''
|
||||
|
||||
|
@ -30,8 +30,8 @@ def git_not_command_closest():
|
||||
return '''git: 'tags' is not a git command. See 'git --help'.
|
||||
|
||||
Did you mean one of these?
|
||||
stage
|
||||
tag
|
||||
\tstage
|
||||
\ttag
|
||||
'''
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@ from tests.utils import Command
|
||||
|
||||
|
||||
@pytest.mark.parametrize('command', [
|
||||
Command(script='go run foo'),
|
||||
Command(script='go run foo'),
|
||||
Command(script='go run bar')])
|
||||
def test_match(command):
|
||||
assert match(command, None)
|
||||
|
@ -9,7 +9,10 @@ from tests.utils import Command
|
||||
Command(script='open foo.org'),
|
||||
Command(script='open foo.net'),
|
||||
Command(script='open foo.se'),
|
||||
Command(script='open foo.io')])
|
||||
Command(script='open foo.io'),
|
||||
Command(script='xdg-open foo.com'),
|
||||
Command(script='gnome-open foo.com'),
|
||||
Command(script='kde-open foo.com')])
|
||||
def test_match(command):
|
||||
assert match(command, None)
|
||||
|
||||
@ -20,6 +23,9 @@ def test_match(command):
|
||||
(Command('open foo.org'), 'open http://foo.org'),
|
||||
(Command('open foo.net'), 'open http://foo.net'),
|
||||
(Command('open foo.se'), 'open http://foo.se'),
|
||||
(Command('open foo.io'), 'open http://foo.io')])
|
||||
(Command('open foo.io'), 'open http://foo.io'),
|
||||
(Command('xdg-open foo.io'), 'xdg-open http://foo.io'),
|
||||
(Command('gnome-open foo.io'), 'gnome-open http://foo.io'),
|
||||
(Command('kde-open foo.io'), 'kde-open http://foo.io')])
|
||||
def test_get_new_command(command, new_command):
|
||||
assert get_new_command(command, None) == new_command
|
||||
|
@ -3,7 +3,6 @@ from thefuck.rules.systemctl import match, get_new_command
|
||||
from tests.utils import Command
|
||||
|
||||
|
||||
|
||||
def test_match():
|
||||
assert match(Command('systemctl nginx start', stderr='Unknown operation \'nginx\'.'), None)
|
||||
assert match(Command('sudo systemctl nginx start', stderr='Unknown operation \'nginx\'.'), None)
|
||||
@ -13,6 +12,7 @@ def test_match():
|
||||
assert not match(Command('systemctl nginx', stderr='Unknown operation \'nginx\'.'), None)
|
||||
assert not match(Command('systemctl start wtf', stderr='Failed to start wtf.service: Unit wtf.service failed to load: No such file or directory.'), None)
|
||||
|
||||
|
||||
def test_get_new_command():
|
||||
assert get_new_command(Command('systemctl nginx start'), None) == "systemctl start nginx"
|
||||
assert get_new_command(Command('sudo systemctl nginx start'), None) == "sudo systemctl start nginx"
|
||||
|
19
tests/test_readme.py
Normal file
19
tests/test_readme.py
Normal file
@ -0,0 +1,19 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def test_readme():
|
||||
with open('README.md') as f:
|
||||
readme = f.read()
|
||||
|
||||
bundled = Path(__file__).parent.parent \
|
||||
.joinpath('thefuck') \
|
||||
.joinpath('rules') \
|
||||
.glob('*.py')
|
||||
|
||||
for rule in bundled:
|
||||
if rule.stem != '__init__' and rule.stem not in readme:
|
||||
raise Exception('Missing rule "{}" in README.md'.format(rule.stem))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_readme()
|
@ -11,6 +11,7 @@ def test_rules_names_list():
|
||||
|
||||
def test_update_settings():
|
||||
settings = Settings({'key': 'val'})
|
||||
new_settings = settings.update(key='new-val')
|
||||
assert new_settings.key == 'new-val'
|
||||
new_settings = settings.update(key='new-val', unset='unset-value')
|
||||
assert new_settings.key == 'val'
|
||||
assert new_settings.unset == 'unset-value'
|
||||
assert settings.key == 'val'
|
||||
|
@ -9,7 +9,8 @@ from tests.utils import Command
|
||||
|
||||
@pytest.mark.parametrize('override, old, new', [
|
||||
({'key': 'val'}, {}, {'key': 'val'}),
|
||||
({'key': 'new-val'}, {'key': 'val'}, {'key': 'new-val'})])
|
||||
({'key': 'new-val'}, {'key': 'val'}, {'key': 'val'}),
|
||||
({'key': 'new-val', 'unset': 'unset'}, {'key': 'val'}, {'key': 'val', 'unset': 'unset'})])
|
||||
def test_wrap_settings(override, old, new):
|
||||
fn = lambda _, settings: settings
|
||||
assert wrap_settings(override)(fn)(None, Settings(old)) == new
|
||||
|
@ -1,14 +1,14 @@
|
||||
# Appends --all to the brew upgrade command
|
||||
#
|
||||
#
|
||||
# Example:
|
||||
# > brew upgrade
|
||||
# Warning: brew upgrade with no arguments will change behaviour soon!
|
||||
# It currently upgrades all formula but this will soon change to require '--all'.
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
def match(command, settings):
|
||||
return (command.script == 'brew upgrade')
|
||||
return command.script == 'brew upgrade'
|
||||
|
||||
|
||||
def get_new_command(command, settings):
|
||||
return command.script + ' --all'
|
||||
|
@ -1,6 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
__author__ = "mmussomele"
|
||||
|
||||
"""Attempts to spellcheck and correct failed cd commands"""
|
||||
|
||||
import os
|
||||
@ -8,6 +5,8 @@ from difflib import get_close_matches
|
||||
from thefuck.utils import sudo_support
|
||||
from thefuck.rules import cd_mkdir
|
||||
|
||||
__author__ = "mmussomele"
|
||||
|
||||
MAX_ALLOWED_DIFF = 0.6
|
||||
|
||||
|
||||
@ -28,8 +27,8 @@ def match(command, settings):
|
||||
def get_new_command(command, settings):
|
||||
"""
|
||||
Attempt to rebuild the path string by spellchecking the directories.
|
||||
If it fails (i.e. no directories are a close enough match), then it
|
||||
defaults to the rules of cd_mkdir.
|
||||
If it fails (i.e. no directories are a close enough match), then it
|
||||
defaults to the rules of cd_mkdir.
|
||||
Change sensitivity by changing MAX_ALLOWED_DIFF. Default value is 0.6
|
||||
"""
|
||||
dest = command.script.split()[1].split(os.sep)
|
||||
|
@ -7,8 +7,10 @@
|
||||
# > cd..
|
||||
# cd..: command not found
|
||||
|
||||
|
||||
def match(command, settings):
|
||||
return command.script == 'cd..'
|
||||
|
||||
|
||||
def get_new_command(command, settings):
|
||||
return 'cd ..'
|
||||
|
@ -1,7 +1,7 @@
|
||||
from itertools import dropwhile, takewhile, islice
|
||||
import re
|
||||
import subprocess
|
||||
from thefuck.utils import get_closest, sudo_support, replace_argument, replace_command
|
||||
from thefuck.utils import sudo_support, replace_command
|
||||
|
||||
|
||||
@sudo_support
|
||||
|
@ -1,9 +1,10 @@
|
||||
import re
|
||||
import os
|
||||
from thefuck.utils import memoize
|
||||
from thefuck.utils import memoize, wrap_settings
|
||||
from thefuck import shells
|
||||
|
||||
|
||||
# order is important: only the first match is considered
|
||||
patterns = (
|
||||
# js, node:
|
||||
'^ at {file}:{line}:{col}',
|
||||
@ -20,13 +21,13 @@ patterns = (
|
||||
# lua:
|
||||
'^lua: {file}:{line}:',
|
||||
# fish:
|
||||
'^{file} \(line {line}\):',
|
||||
'^{file} \\(line {line}\\):',
|
||||
# bash, sh, ssh:
|
||||
'^{file}: line {line}: ',
|
||||
# cargo, clang, gcc, go, pep8, rustc:
|
||||
'^{file}:{line}:{col}',
|
||||
# ghc, make, ruby, zsh:
|
||||
'^{file}:{line}:',
|
||||
# cargo, clang, gcc, go, rustc:
|
||||
'^{file}:{line}:{col}',
|
||||
# perl:
|
||||
'at {file} line {line}',
|
||||
)
|
||||
@ -45,7 +46,7 @@ patterns = [_make_pattern(p) for p in patterns]
|
||||
def _search(stderr):
|
||||
for pattern in patterns:
|
||||
m = re.search(pattern, stderr)
|
||||
if m:
|
||||
if m and os.path.isfile(m.group('file')):
|
||||
return m
|
||||
|
||||
|
||||
@ -53,15 +54,24 @@ def match(command, settings):
|
||||
if 'EDITOR' not in os.environ:
|
||||
return False
|
||||
|
||||
m = _search(command.stderr)
|
||||
|
||||
return m and os.path.isfile(m.group('file'))
|
||||
return _search(command.stderr) or _search(command.stdout)
|
||||
|
||||
|
||||
@wrap_settings({'fixlinecmd': '{editor} {file} +{line}',
|
||||
'fixcolcmd': None})
|
||||
def get_new_command(command, settings):
|
||||
m = _search(command.stderr)
|
||||
m = _search(command.stderr) or _search(command.stdout)
|
||||
|
||||
# Note: there does not seem to be a standard for columns, so they are just
|
||||
# ignored for now
|
||||
return shells.and_('{} {} +{}'.format(os.environ['EDITOR'], m.group('file'), m.group('line')),
|
||||
command.script)
|
||||
# ignored by default
|
||||
if settings.fixcolcmd and 'col' in m.groupdict():
|
||||
editor_call = settings.fixcolcmd.format(editor=os.environ['EDITOR'],
|
||||
file=m.group('file'),
|
||||
line=m.group('line'),
|
||||
col=m.group('col'))
|
||||
else:
|
||||
editor_call = settings.fixlinecmd.format(editor=os.environ['EDITOR'],
|
||||
file=m.group('file'),
|
||||
line=m.group('line'))
|
||||
|
||||
return shells.and_(editor_call, command.script)
|
||||
|
@ -12,7 +12,7 @@ def match(command, settings):
|
||||
def get_new_command(command, settings):
|
||||
missing_file = re.findall(
|
||||
r"error: pathspec '([^']*)' "
|
||||
"did not match any file\(s\) known to git.", command.stderr)[0]
|
||||
r"did not match any file\(s\) known to git.", command.stderr)[0]
|
||||
|
||||
formatme = shells.and_('git add -- {}', '{}')
|
||||
return formatme.format(missing_file, command.script)
|
||||
|
@ -27,7 +27,7 @@ def get_branches():
|
||||
def get_new_command(command, settings):
|
||||
missing_file = re.findall(
|
||||
r"error: pathspec '([^']*)' "
|
||||
"did not match any file\(s\) known to git.", command.stderr)[0]
|
||||
r"did not match any file\(s\) known to git.", command.stderr)[0]
|
||||
closest_branch = utils.get_closest(missing_file, get_branches(),
|
||||
fallback_to_first=False)
|
||||
if closest_branch:
|
||||
|
@ -1,14 +1,14 @@
|
||||
# Appends .go when compiling go files
|
||||
#
|
||||
#
|
||||
# Example:
|
||||
# > go run foo
|
||||
# error: go run: no go files listed
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
def match(command, settings):
|
||||
return (command.script.startswith ('go run ')
|
||||
return (command.script.startswith('go run ')
|
||||
and not command.script.endswith('.go'))
|
||||
|
||||
|
||||
def get_new_command(command, settings):
|
||||
return command.script + '.go'
|
||||
|
@ -11,4 +11,3 @@ def match(command, settings):
|
||||
@sudo_support
|
||||
def get_new_command(command, settings):
|
||||
return u'./{}'.format(command.script)
|
||||
|
||||
|
@ -23,6 +23,7 @@ def _history_of_exists_without_current(command):
|
||||
if not line.startswith(tf_alias) and not line == command.script
|
||||
and line.split(' ')[0] in executables]
|
||||
|
||||
|
||||
def match(command, settings):
|
||||
return len(get_close_matches(command.script,
|
||||
_history_of_exists_without_current(command)))
|
||||
|
@ -4,7 +4,7 @@
|
||||
# > javac foo
|
||||
# error: Class names, 'foo', are only accepted if annotation
|
||||
# processing is explicitly requested
|
||||
|
||||
|
||||
|
||||
def match(command, settings):
|
||||
return (command.script.startswith('javac ')
|
||||
|
@ -1,7 +1,7 @@
|
||||
def match(command, settings):
|
||||
return (command.script == 'ls'
|
||||
or command.script.startswith('ls ')
|
||||
and not ('ls -' in command.script))
|
||||
and 'ls -' not in command.script)
|
||||
|
||||
|
||||
def get_new_command(command, settings):
|
||||
|
@ -23,4 +23,4 @@ def match(command, settings):
|
||||
|
||||
|
||||
def get_new_command(command, settings):
|
||||
return 'open http://' + command.script[5:]
|
||||
return command.script.replace('open ', 'open http://')
|
||||
|
@ -1,14 +1,12 @@
|
||||
# Fixes careless " and ' usage
|
||||
#
|
||||
#
|
||||
# Example:
|
||||
# > git commit -m 'My Message"
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
def match(command, settings):
|
||||
return ('\'' in command.script
|
||||
and '\"' in command.script)
|
||||
return '\'' in command.script and '\"' in command.script
|
||||
|
||||
|
||||
def get_new_command(command, settings):
|
||||
return command.script.replace ('\'', '\"')
|
||||
return command.script.replace('\'', '\"')
|
||||
|
@ -1,4 +1,4 @@
|
||||
from thefuck.utils import get_closest, replace_command
|
||||
from thefuck.utils import replace_command
|
||||
import re
|
||||
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import re
|
||||
from thefuck.utils import (get_closest, replace_argument,
|
||||
get_all_matched_commands, replace_command)
|
||||
from thefuck.utils import get_all_matched_commands, replace_command
|
||||
|
||||
|
||||
def match(command, settings):
|
||||
@ -14,4 +13,3 @@ def get_new_command(command, settings):
|
||||
command.stderr)[0]
|
||||
return replace_command(command, broken_cmd,
|
||||
get_all_matched_commands(command.stderr))
|
||||
|
||||
|
@ -216,7 +216,7 @@ class Tcsh(Generic):
|
||||
return u'#+{}\n{}\n'.format(int(time()), command_script)
|
||||
|
||||
|
||||
shells = defaultdict(lambda: Generic(), {
|
||||
shells = defaultdict(Generic, {
|
||||
'bash': Bash(),
|
||||
'fish': Fish(),
|
||||
'zsh': Zsh(),
|
||||
|
@ -23,7 +23,9 @@ class Settings(dict):
|
||||
return self.get(item)
|
||||
|
||||
def update(self, **kwargs):
|
||||
"""Returns new settings with new values from `kwargs`."""
|
||||
conf = dict(self)
|
||||
conf.update(kwargs)
|
||||
"""
|
||||
Returns new settings with values from `kwargs` for unset settings.
|
||||
"""
|
||||
conf = dict(kwargs)
|
||||
conf.update(self)
|
||||
return Settings(conf)
|
||||
|
Loading…
x
Reference in New Issue
Block a user