mirror of
				https://github.com/nvbn/thefuck.git
				synced 2025-11-04 09:02:08 +00:00 
			
		
		
		
	Compare commits
	
		
			13 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					36a0a669b0 | ||
| 
						 | 
					b16de9c7c2 | ||
| 
						 | 
					43fead02d3 | ||
| 
						 | 
					de513cacb1 | ||
| 
						 | 
					e4b97af73e | ||
| 
						 | 
					0a40e7f0a9 | ||
| 
						 | 
					9c649c05a9 | ||
| 
						 | 
					4fc18cb4e7 | ||
| 
						 | 
					5d1dd70652 | ||
| 
						 | 
					65a25d5448 | ||
| 
						 | 
					4e854a575e | ||
| 
						 | 
					742200a500 | ||
| 
						 | 
					44cd1fd7e1 | 
@@ -12,6 +12,7 @@ addons:
 | 
			
		||||
      - zsh
 | 
			
		||||
      - fish
 | 
			
		||||
      - tcsh
 | 
			
		||||
      - pandoc
 | 
			
		||||
env:
 | 
			
		||||
  - FUNCTIONAL=true BARE=true
 | 
			
		||||
install:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
# The Fuck [](https://travis-ci.org/nvbn/thefuck) 
 | 
			
		||||
# The Fuck [](https://travis-ci.org/nvbn/thefuck) 
 | 
			
		||||
 | 
			
		||||
Magnificent app which corrects your previous console command,
 | 
			
		||||
inspired by a [@liamosaur](https://twitter.com/liamosaur/)
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -188,6 +189,7 @@ using the matched rule and runs it. Rules enabled by default are as follows:
 | 
			
		||||
* `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;
 | 
			
		||||
* `tsuru_not_command` – fixes wrong tsuru commands like `tsuru shell`;
 | 
			
		||||
* `tmux` – fixes `tmux` commands;
 | 
			
		||||
* `whois` – fixes `whois` command.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
from subprocess import call
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -28,4 +29,7 @@ call('git commit -am "Bump to {}"'.format(version), shell=True)
 | 
			
		||||
call('git tag {}'.format(version), shell=True)
 | 
			
		||||
call('git push', shell=True)
 | 
			
		||||
call('git push --tags', shell=True)
 | 
			
		||||
call('python setup.py sdist bdist_wheel upload', shell=True)
 | 
			
		||||
 | 
			
		||||
env = os.environ
 | 
			
		||||
env['CONVERT_README'] = 'true'
 | 
			
		||||
call('python setup.py sdist bdist_wheel upload', shell=True, env=env)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								setup.py
									
									
									
									
									
								
							@@ -1,13 +1,14 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
from setuptools import setup, find_packages
 | 
			
		||||
import sys
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
if os.environ.get('CONVERT_README'):
 | 
			
		||||
    import pypandoc
 | 
			
		||||
 | 
			
		||||
    long_description = pypandoc.convert('README.md', 'rst')
 | 
			
		||||
except:
 | 
			
		||||
    long_description = open('README.md').read()
 | 
			
		||||
else:
 | 
			
		||||
    long_description = ''
 | 
			
		||||
 | 
			
		||||
version = sys.version_info[:2]
 | 
			
		||||
if version < (2, 7):
 | 
			
		||||
@@ -19,7 +20,7 @@ elif (3, 0) < version < (3, 3):
 | 
			
		||||
          ' ({}.{} detected).'.format(*version))
 | 
			
		||||
    sys.exit(-1)
 | 
			
		||||
 | 
			
		||||
VERSION = '2.5.4'
 | 
			
		||||
VERSION = '2.6'
 | 
			
		||||
 | 
			
		||||
install_requires = ['psutil', 'colorama', 'six']
 | 
			
		||||
extras_require = {':python_version<"3.4"': ['pathlib']}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										188
									
								
								tests/rules/test_fix_file.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								tests/rules/test_fix_file.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,188 @@
 | 
			
		||||
import pytest
 | 
			
		||||
import os
 | 
			
		||||
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(mocker, monkeypatch, test):
 | 
			
		||||
    mocker.patch('os.path.isfile', return_value=True)
 | 
			
		||||
    monkeypatch.setenv('EDITOR', 'dummy_editor')
 | 
			
		||||
    assert match(Command(stderr=test[4]), None)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('test', tests)
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('test', tests)
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('test', tests)
 | 
			
		||||
def test_get_new_command(monkeypatch, test):
 | 
			
		||||
    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]))
 | 
			
		||||
							
								
								
									
										90
									
								
								tests/rules/test_tsuru_not_command.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								tests/rules/test_tsuru_not_command.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
from tests.utils import Command
 | 
			
		||||
from thefuck.rules.tsuru_not_command import match, get_new_command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command', [
 | 
			
		||||
    Command('tsuru log', stderr=(
 | 
			
		||||
        'tsuru: "tchururu" is not a tsuru command. See "tsuru help".\n'
 | 
			
		||||
        '\nDid you mean?\n'
 | 
			
		||||
        '\tapp-log\n'
 | 
			
		||||
        '\tlogin\n'
 | 
			
		||||
        '\tlogout\n'
 | 
			
		||||
    )),
 | 
			
		||||
    Command('tsuru app-l', stderr=(
 | 
			
		||||
        'tsuru: "tchururu" is not a tsuru command. See "tsuru help".\n'
 | 
			
		||||
        '\nDid you mean?\n'
 | 
			
		||||
        '\tapp-list\n'
 | 
			
		||||
        '\tapp-log\n'
 | 
			
		||||
    )),
 | 
			
		||||
    Command('tsuru user-list', stderr=(
 | 
			
		||||
        'tsuru: "tchururu" is not a tsuru command. See "tsuru help".\n'
 | 
			
		||||
        '\nDid you mean?\n'
 | 
			
		||||
        '\tteam-user-list\n'
 | 
			
		||||
    )),
 | 
			
		||||
    Command('tsuru targetlist', stderr=(
 | 
			
		||||
        'tsuru: "tchururu" is not a tsuru command. See "tsuru help".\n'
 | 
			
		||||
        '\nDid you mean?\n'
 | 
			
		||||
        '\ttarget-list\n'
 | 
			
		||||
    )),
 | 
			
		||||
])
 | 
			
		||||
def test_match(command):
 | 
			
		||||
    assert match(command, None)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command', [
 | 
			
		||||
    Command('tsuru tchururu', stderr=(
 | 
			
		||||
        'tsuru: "tchururu" is not a tsuru command. See "tsuru help".\n'
 | 
			
		||||
        '\nDid you mean?\n'
 | 
			
		||||
    )),
 | 
			
		||||
    Command('tsuru version', stderr='tsuru version 0.16.0.'),
 | 
			
		||||
    Command('tsuru help', stderr=(
 | 
			
		||||
        'tsuru version 0.16.0.\n'
 | 
			
		||||
        '\nUsage: tsuru command [args]\n'
 | 
			
		||||
    )),
 | 
			
		||||
    Command('tsuru platform-list', stderr=(
 | 
			
		||||
        '- java\n'
 | 
			
		||||
        '- logstashgiro\n'
 | 
			
		||||
        '- newnode\n'
 | 
			
		||||
        '- nodejs\n'
 | 
			
		||||
        '- php\n'
 | 
			
		||||
        '- python\n'
 | 
			
		||||
        '- python3\n'
 | 
			
		||||
        '- ruby\n'
 | 
			
		||||
        '- ruby20\n'
 | 
			
		||||
        '- static\n'
 | 
			
		||||
    )),
 | 
			
		||||
    Command('tsuru env-get', stderr='Error: App thefuck not found.'),
 | 
			
		||||
])
 | 
			
		||||
def test_not_match(command):
 | 
			
		||||
    assert not match(command, None)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('command, new_command', [
 | 
			
		||||
    (Command('tsuru log', stderr=(
 | 
			
		||||
        'tsuru: "log" is not a tsuru command. See "tsuru help".\n'
 | 
			
		||||
        '\nDid you mean?\n'
 | 
			
		||||
        '\tapp-log\n'
 | 
			
		||||
        '\tlogin\n'
 | 
			
		||||
        '\tlogout\n'
 | 
			
		||||
    )), 'tsuru login'),
 | 
			
		||||
    (Command('tsuru app-l', stderr=(
 | 
			
		||||
        'tsuru: "app-l" is not a tsuru command. See "tsuru help".\n'
 | 
			
		||||
        '\nDid you mean?\n'
 | 
			
		||||
        '\tapp-list\n'
 | 
			
		||||
        '\tapp-log\n'
 | 
			
		||||
    )), 'tsuru app-log'),
 | 
			
		||||
    (Command('tsuru user-list', stderr=(
 | 
			
		||||
        'tsuru: "user-list" is not a tsuru command. See "tsuru help".\n'
 | 
			
		||||
        '\nDid you mean?\n'
 | 
			
		||||
        '\tteam-user-list\n'
 | 
			
		||||
    )), 'tsuru team-user-list'),
 | 
			
		||||
    (Command('tsuru targetlist', stderr=(
 | 
			
		||||
        'tsuru: "targetlist" is not a tsuru command. See "tsuru help".\n'
 | 
			
		||||
        '\nDid you mean?\n'
 | 
			
		||||
        '\ttarget-list\n'
 | 
			
		||||
    )), 'tsuru target-list'),
 | 
			
		||||
])
 | 
			
		||||
def test_get_new_command(command, new_command):
 | 
			
		||||
    assert get_new_command(command, None) == new_command
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
import pytest
 | 
			
		||||
from mock import Mock
 | 
			
		||||
from thefuck.utils import git_support, sudo_support, wrap_settings,\
 | 
			
		||||
    memoize, get_closest, get_all_executables, replace_argument
 | 
			
		||||
    memoize, get_closest, get_all_executables, replace_argument, \
 | 
			
		||||
    get_all_matched_commands
 | 
			
		||||
from thefuck.types import Settings
 | 
			
		||||
from tests.utils import Command
 | 
			
		||||
 | 
			
		||||
@@ -99,3 +100,32 @@ def test_get_all_callables():
 | 
			
		||||
    (('git brnch', 'brnch', 'branch'), 'git branch')])
 | 
			
		||||
def test_replace_argument(args, result):
 | 
			
		||||
    assert replace_argument(*args) == result
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('stderr, result', [
 | 
			
		||||
    (("git: 'cone' is not a git command. See 'git --help'.\n"
 | 
			
		||||
      '\n'
 | 
			
		||||
      'Did you mean one of these?\n'
 | 
			
		||||
      '\tclone'), ['clone']),
 | 
			
		||||
    (("git: 're' is not a git command. See 'git --help'.\n"
 | 
			
		||||
      '\n'
 | 
			
		||||
      'Did you mean one of these?\n'
 | 
			
		||||
      '\trebase\n'
 | 
			
		||||
      '\treset\n'
 | 
			
		||||
      '\tgrep\n'
 | 
			
		||||
      '\trm'), ['rebase', 'reset', 'grep', 'rm']),
 | 
			
		||||
    (('tsuru: "target" is not a tsuru command. See "tsuru help".\n'
 | 
			
		||||
      '\n'
 | 
			
		||||
      'Did you mean one of these?\n'
 | 
			
		||||
      '\tservice-add\n'
 | 
			
		||||
      '\tservice-bind\n'
 | 
			
		||||
      '\tservice-doc\n'
 | 
			
		||||
      '\tservice-info\n'
 | 
			
		||||
      '\tservice-list\n'
 | 
			
		||||
      '\tservice-remove\n'
 | 
			
		||||
      '\tservice-status\n'
 | 
			
		||||
      '\tservice-unbind'), ['service-add', 'service-bind', 'service-doc',
 | 
			
		||||
                            'service-info', 'service-list', 'service-remove',
 | 
			
		||||
                            'service-status', 'service-unbind'])])
 | 
			
		||||
def test_get_all_matched_commands(stderr, result):
 | 
			
		||||
    assert list(get_all_matched_commands(stderr)) == result
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										67
									
								
								thefuck/rules/fix_file.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								thefuck/rules/fix_file.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
import re
 | 
			
		||||
import os
 | 
			
		||||
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):
 | 
			
		||||
    if 'EDITOR' not in os.environ:
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    m = _search(command.stderr)
 | 
			
		||||
 | 
			
		||||
    return m and os.path.isfile(m.group('file'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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_('{} {} +{}'.format(os.environ['EDITOR'], m.group('file'), m.group('line')),
 | 
			
		||||
                       command.script)
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import re
 | 
			
		||||
from thefuck.utils import get_closest, git_support, replace_argument
 | 
			
		||||
from thefuck.utils import (get_closest, git_support, replace_argument,
 | 
			
		||||
                           get_all_matched_commands)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@git_support
 | 
			
		||||
@@ -8,20 +9,11 @@ def match(command, settings):
 | 
			
		||||
            and 'Did you mean' in command.stderr)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _get_all_git_matched_commands(stderr):
 | 
			
		||||
    should_yield = False
 | 
			
		||||
    for line in stderr.split('\n'):
 | 
			
		||||
        if 'Did you mean' in line:
 | 
			
		||||
            should_yield = True
 | 
			
		||||
        elif should_yield and line:
 | 
			
		||||
            yield line.strip()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@git_support
 | 
			
		||||
def get_new_command(command, settings):
 | 
			
		||||
    broken_cmd = re.findall(r"git: '([^']*)' is not a git command",
 | 
			
		||||
                            command.stderr)[0]
 | 
			
		||||
    new_cmd = get_closest(broken_cmd,
 | 
			
		||||
                          _get_all_git_matched_commands(command.stderr))
 | 
			
		||||
                          get_all_matched_commands(command.stderr))
 | 
			
		||||
    return replace_argument(command.script, broken_cmd, new_cmd)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								thefuck/rules/tsuru_not_command.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								thefuck/rules/tsuru_not_command.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
import re
 | 
			
		||||
from thefuck.utils import (get_closest, replace_argument,
 | 
			
		||||
                           get_all_matched_commands)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def match(command, settings):
 | 
			
		||||
    return (command.script.startswith('tsuru ')
 | 
			
		||||
            and ' is not a tsuru command. See "tsuru help".' in command.stderr
 | 
			
		||||
            and '\nDid you mean?\n\t' in command.stderr)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_new_command(command, settings):
 | 
			
		||||
    broken_cmd = re.findall(r'tsuru: "([^"]*)" is not a tsuru command',
 | 
			
		||||
                            command.stderr)[0]
 | 
			
		||||
    new_cmd = get_closest(broken_cmd,
 | 
			
		||||
                          get_all_matched_commands(command.stderr))
 | 
			
		||||
    return replace_argument(command.script, broken_cmd, new_cmd)
 | 
			
		||||
 | 
			
		||||
@@ -224,6 +224,7 @@ shells = defaultdict(lambda: Generic(), {
 | 
			
		||||
    'tcsh': Tcsh()})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@memoize
 | 
			
		||||
def _get_shell():
 | 
			
		||||
    try:
 | 
			
		||||
        shell = Process(os.getpid()).parent().name()
 | 
			
		||||
 
 | 
			
		||||
@@ -159,3 +159,12 @@ def replace_argument(script, from_, to):
 | 
			
		||||
    else:
 | 
			
		||||
        return script.replace(
 | 
			
		||||
            u' {} '.format(from_), u' {} '.format(to), 1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_all_matched_commands(stderr, separator='Did you mean'):
 | 
			
		||||
    should_yield = False
 | 
			
		||||
    for line in stderr.split('\n'):
 | 
			
		||||
        if separator in line:
 | 
			
		||||
            should_yield = True
 | 
			
		||||
        elif should_yield and line:
 | 
			
		||||
            yield line.strip()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user