1
0
mirror of https://github.com/nvbn/thefuck.git synced 2024-10-05 18:31:10 +01:00

#320 Add the fix_file rule

This commit is contained in:
mcarton 2015-07-29 16:05:46 +02:00
parent 4fc18cb4e7
commit e4b97af73e
3 changed files with 229 additions and 0 deletions

View File

@ -146,6 +146,7 @@ using the matched rule and runs it. Rules enabled by default are as follows:
* `docker_not_command` – fixes wrong docker commands like `docker tags`;
* `dry` – fixes repetitions like `git git push`;
* `fix_alt_space` – replaces Alt+Space with Space character;
* `fix_file` – opens a file with an error in your `$EDITOR`;
* `git_add` – fixes *"Did you forget to 'git add'?"*;
* `git_branch_delete` – changes `git branch -d` to `git branch -D`;
* `git_branch_list` – catches `git branch list` in place of `git branch` and removes created branch;

View File

@ -0,0 +1,167 @@
import pytest
from thefuck.rules.fix_file import match, get_new_command
from tests.utils import Command
# (script, file, line, col (or None), stderr)
tests = (
('gcc a.c', 'a.c', 3, 1,
"""
a.c: In function 'main':
a.c:3:1: error: expected expression before '}' token
}
^
"""),
('clang a.c', 'a.c', 3, 1,
"""
a.c:3:1: error: expected expression
}
^
"""),
('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,
"""
Search pattern not terminated at a.pl line 2.
"""),
('sh a.sh', 'a.sh', 2, None,
"""
a.sh: line 2: foo: command not found
"""),
('zsh a.sh', 'a.sh', 2, None,
"""
a.sh:2: command not found: foo
"""),
('bash a.sh', 'a.sh', 2, None,
"""
a.sh: line 2: foo: command not found
"""),
('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,
"""
Compiling test v0.1.0 (file:///tmp/fix-error/test)
src/lib.rs:3:5: 3:6 error: unexpected token: `+`
src/lib.rs:3 +
^
Could not compile `test`.
To learn more, run the command again with --verbose.
"""),
('python a.py', 'a.py', 2, None,
"""
File "a.py", line 2
+
^
SyntaxError: invalid syntax
"""),
('python a.py', 'a.py', 8, None,
"""
Traceback (most recent call last):
File "a.py", line 8, in <module>
match("foo")
File "a.py", line 5, in match
m = re.search(None, command)
File "/usr/lib/python3.4/re.py", line 170, in search
return _compile(pattern, flags).search(string)
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,
"""
a.rb:3: syntax error, unexpected keyword_end
"""),
('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: Unknown command 'foo'
/tmp/fix-error/a.sh (line 2): foo
^
"""),
('./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:1:1: error: expected top-level entity
+
^
"""),
('go build a.go', 'a.go', 1, None,
"""
can't load package:
a.go:1:1: expected 'package', found '+'
"""),
('make', 'Makefile', 2, None,
"""
bidule
make: bidule: Command not found
Makefile:2: recipe for target 'target' failed
make: *** [target] Error 127
"""),
('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,
"""
/Users/pablo/Workspace/barebones/fuck.js:2
conole.log(arg); // this should read console.log(arg);
^
ReferenceError: conole is not defined
at /Users/pablo/Workspace/barebones/fuck.js:2:5
at Array.forEach (native)
at Object.<anonymous> (/Users/pablo/Workspace/barebones/fuck.js:1:85)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)
at node.js:814:3
"""),
)
@pytest.mark.parametrize('test', tests)
def test_match(test):
assert match(Command(stderr=test[4]), None)
@pytest.mark.parametrize('test', tests)
def test_get_new_command(monkeypatch, test):
assert (get_new_command(Command(script=test[0], stderr=test[4]), None) ==
'$EDITOR {} +{} && {}'.format(test[1], test[2], test[0]))

61
thefuck/rules/fix_file.py Normal file
View File

@ -0,0 +1,61 @@
import re
from thefuck.utils import memoize
from thefuck import shells
patterns = (
# js, node:
'^ at {file}:{line}:{col}',
# cargo:
'^ {file}:{line}:{col}',
# python, thefuck:
'^ File "{file}", line {line}',
# awk:
'^awk: {file}:{line}:',
# git
'^fatal: bad config file line {line} in {file}',
# llc:
'^llc: {file}:{line}:{col}:',
# lua:
'^lua: {file}:{line}:',
# fish:
'^{file} \(line {line}\):',
# bash, sh, ssh:
'^{file}: line {line}: ',
# ghc, make, ruby, zsh:
'^{file}:{line}:',
# cargo, clang, gcc, go, rustc:
'^{file}:{line}:{col}',
# perl:
'at {file} line {line}',
)
# for the sake of readability do not use named groups above
def _make_pattern(pattern):
pattern = pattern.replace('{file}', '(?P<file>[^:\n]+)')
pattern = pattern.replace('{line}', '(?P<line>[0-9]+)')
pattern = pattern.replace('{col}', '(?P<col>[0-9]+)')
return re.compile(pattern, re.MULTILINE)
patterns = [_make_pattern(p) for p in patterns]
@memoize
def _search(stderr):
for pattern in patterns:
m = re.search(pattern, stderr)
if m:
return m
def match(command, settings):
return _search(command.stderr)
def get_new_command(command, settings):
m = _search(command.stderr)
# Note: there does not seem to be a standard for columns, so they are just
# ignored for now
return shells.and_('$EDITOR {} +{}'.format(m.group('file'), m.group('line')),
command.script)