1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-11-05 09:32:09 +00:00

Compare commits

..

23 Commits
2.1 ... 2.3

Author SHA1 Message Date
nvbn
6c534c52bc Bump to 2.3 2015-07-22 04:45:04 +03:00
nvbn
b4392ba706 #N/A Add heroku_not_command rule 2015-07-22 04:44:37 +03:00
Vladimir Iakovlev
46f918718f Merge pull request #307 from evverx/lc_all
Force LC_ALL to C
2015-07-21 17:11:16 +03:00
Vladimir Iakovlev
d71ce76ae4 Merge pull request #306 from mcarton/hub
Support GitHub's hub command
2015-07-21 16:43:24 +03:00
nvbn
355505a0a8 #N/A Make git_checkout test less dependent on get_closest 2015-07-21 16:40:45 +03:00
Evgeny Vereshchagin
3d425ce831 Force LC_ALL to C
See: http://unix.stackexchange.com/a/87763/120177
2015-07-21 13:39:34 +00:00
mcarton
98a9fb3d7d Remove now redundant checks in git_* rules 2015-07-21 15:35:39 +02:00
nvbn
c8d748e095 Bump to 2.2 2015-07-21 16:31:17 +03:00
nvbn
e0af35819d Merge branch 'master' of github.com:nvbn/thefuck 2015-07-21 16:19:11 +03:00
nvbn
9e4c250e4e #301 Fix bash support on non-eng systems 2015-07-21 16:19:01 +03:00
Vladimir Iakovlev
8c395377f8 Merge pull request #299 from evverx/dnf-history
Add `dnf history` error for the sudo rule
2015-07-21 16:15:08 +03:00
Vladimir Iakovlev
f165523247 Merge pull request #304 from mcarton/fix-git_diff_staged
Fix the `git_diff_staged` rule
2015-07-21 16:12:19 +03:00
mcarton
903abff77e Support hub as well as git in @git_support 2015-07-21 15:06:04 +02:00
Evgeny Vereshchagin
6d39b78824 Add dnf history error for the sudo rule
$ dnf history
You don't have access to the history DB.
2015-07-21 12:56:25 +00:00
mcarton
1285303363 Fix the git_diff_staged rule
The problem was:
```
% git add foo
% git diff foo
% fuck
git diff foo --staged [enter/ctrl+c]
fatal: bad flag '--staged' used after filename
```
2015-07-21 14:06:37 +02:00
nvbn
66e2ec7e3f Merge branch 'mcarton-fix-readme' 2015-07-20 22:49:31 +03:00
nvbn
92cca7b641 #296 Fix [enter/ctrl+c] case in the readme 2015-07-20 22:49:21 +03:00
mcarton
e572cab1f3 Have the README look better 2015-07-20 21:12:39 +02:00
mcarton
33b1536c28 Move misplaced rule in README 2015-07-20 21:07:56 +02:00
mcarton
d4fada8e4c Reflect the new default for require_confirmation 2015-07-20 21:06:59 +02:00
mcarton
afc089bc3c Be more consistent in README 2015-07-20 20:49:21 +02:00
nvbn
300c8f528a #N/A Mention tcsh in readme 2015-07-20 21:27:19 +03:00
nvbn
7b011a504d #N/A Fix tests in travis 2015-07-20 21:24:00 +03:00
26 changed files with 131 additions and 56 deletions

View File

@@ -7,6 +7,7 @@ install:
- pip install -r requirements.txt - pip install -r requirements.txt
- python setup.py develop - python setup.py develop
- pip install coveralls - pip install coveralls
- rm -rf build
script: script:
- export COVERAGE_PYTHON_VERSION=python-${TRAVIS_PYTHON_VERSION:0:1} - export COVERAGE_PYTHON_VERSION=python-${TRAVIS_PYTHON_VERSION:0:1}
- coverage run --source=thefuck,tests -m py.test -v - coverage run --source=thefuck,tests -m py.test -v

View File

@@ -14,7 +14,7 @@ E: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied)
E: Unable to lock the administration directory (/var/lib/dpkg/), are you root? E: Unable to lock the administration directory (/var/lib/dpkg/), are you root?
➜ fuck ➜ fuck
sudo apt-get install vim sudo apt-get install vim [enter/ctrl+c]
[sudo] password for nvbn: [sudo] password for nvbn:
Reading package lists... Done Reading package lists... Done
... ...
@@ -29,7 +29,7 @@ To push the current branch and set the remote as upstream, use
➜ fuck ➜ fuck
git push --set-upstream origin master git push --set-upstream origin master [enter/ctrl+c]
Counting objects: 9, done. Counting objects: 9, done.
... ...
``` ```
@@ -42,7 +42,7 @@ No command 'puthon' found, did you mean:
zsh: command not found: puthon zsh: command not found: puthon
➜ fuck ➜ fuck
python python [enter/ctrl+c]
Python 3.4.2 (default, Oct 8 2014, 13:08:17) Python 3.4.2 (default, Oct 8 2014, 13:08:17)
... ...
``` ```
@@ -55,7 +55,7 @@ Did you mean this?
branch branch
➜ fuck ➜ fuck
git branch git branch [enter/ctrl+c]
* master * master
``` ```
@@ -67,13 +67,13 @@ Did you mean this?
repl repl
➜ fuck ➜ fuck
lein repl lein repl [enter/ctrl+c]
nREPL server started on port 54848 on host 127.0.0.1 - nrepl://127.0.0.1:54848 nREPL server started on port 54848 on host 127.0.0.1 - nrepl://127.0.0.1:54848
REPL-y 0.3.1 REPL-y 0.3.1
... ...
``` ```
If you are scared to blindly run the changed command, there is a `require_confirmation` If you are not scared to blindly run the changed command, there is a `require_confirmation`
[settings](#settings) option: [settings](#settings) option:
```bash ```bash
@@ -82,7 +82,7 @@ E: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied)
E: Unable to lock the administration directory (/var/lib/dpkg/), are you root? E: Unable to lock the administration directory (/var/lib/dpkg/), are you root?
➜ fuck ➜ fuck
sudo apt-get install vim [Enter/Ctrl+C] sudo apt-get install vim
[sudo] password for nvbn: [sudo] password for nvbn:
Reading package lists... Done Reading package lists... Done
... ...
@@ -112,7 +112,7 @@ eval "$(thefuck-alias)"
eval "$(thefuck-alias FUCK)" eval "$(thefuck-alias FUCK)"
``` ```
[Or in your shell config (Bash, Zsh, Fish, Powershell).](https://github.com/nvbn/thefuck/wiki/Shell-aliases) [Or in your shell config (Bash, Zsh, Fish, Powershell, tcsh).](https://github.com/nvbn/thefuck/wiki/Shell-aliases)
Changes will be available only in a new shell session. Changes will be available only in a new shell session.
To make them available immediately, run `source ~/.bashrc` (or your shell config file like `.zshrc`). To make them available immediately, run `source ~/.bashrc` (or your shell config file like `.zshrc`).
@@ -138,17 +138,17 @@ using the matched rule and runs it. Rules enabled by default are as follows:
* `cd_parent` – changes `cd..` to `cd ..`; * `cd_parent` – changes `cd..` to `cd ..`;
* `composer_not_command` – fixes composer command name; * `composer_not_command` – fixes composer command name;
* `cp_omitting_directory` – adds `-a` when you `cp` directory; * `cp_omitting_directory` – adds `-a` when you `cp` directory;
* `cpp11` – add missing `-std=c++11` to `g++` or `clang++`; * `cpp11` – adds missing `-std=c++11` to `g++` or `clang++`;
* `django_south_ghost` – adds `--delete-ghost-migrations` to failed because ghosts django south migration; * `django_south_ghost` – adds `--delete-ghost-migrations` to failed because ghosts django south migration;
* `django_south_merge` – adds `--merge` to inconsistent django south migration; * `django_south_merge` – adds `--merge` to inconsistent django south migration;
* `dry` – fix repetitions like "git git push"; * `dry` – fixes repetitions like "git git push";
* `fix_alt_space` – replaces Alt+Space with Space character; * `fix_alt_space` – replaces Alt+Space with Space character;
* `git_add` – fix *"Did you forget to 'git add'?"*; * `git_add` – fixes *"Did you forget to 'git add'?"*;
* `git_branch_delete` – changes `git branch -d` to `git branch -D`; * `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; * `git_branch_list` – catches `git branch list` in place of `git branch` and removes created branch;
* `git_checkout` – fixes branch name or creates new branch; * `git_checkout` – fixes branch name or creates new branch;
* `git_diff_staged` – adds `--staged` to previous `git diff` with unexpected output; * `git_diff_staged` – adds `--staged` to previous `git diff` with unexpected output;
* `git_no_command` – fixes wrong git commands like `git brnch`; * `git_not_command` – fixes wrong git commands like `git brnch`;
* `git_pull` – sets upstream before executing previous `git pull`; * `git_pull` – sets upstream before executing previous `git pull`;
* `git_pull_clone` – clones instead of pulling when the repo does not exist; * `git_pull_clone` – clones instead of pulling when the repo does not exist;
* `git_push` – adds `--set-upstream origin $branch` to previous failed `git push`; * `git_push` – adds `--set-upstream origin $branch` to previous failed `git push`;
@@ -157,12 +157,13 @@ using the matched rule and runs it. Rules enabled by default are as follows:
* `go_run` – appends `.go` extension when compiling/running Go programs * `go_run` – appends `.go` extension when compiling/running Go programs
* `grep_recursive` – adds `-r` when you trying to grep directory; * `grep_recursive` – adds `-r` when you trying to grep directory;
* `has_exists_script` – prepends `./` when script/binary exists; * `has_exists_script` – prepends `./` when script/binary exists;
* `heroku_no_command` – fixes wrong heroku commands like `heroku log`;
* `history` – tries to replace command with most similar command from history; * `history` – tries to replace command with most similar command from history;
* `java` – removes `.java` extension when running Java programs; * `java` – removes `.java` extension when running Java programs;
* `javac` – appends missing `.java` when compiling Java files; * `javac` – appends missing `.java` when compiling Java files;
* `lein_not_task` – fixes wrong `lein` tasks like `lein rpl`; * `lein_not_task` – fixes wrong `lein` tasks like `lein rpl`;
* `ls_lah` – adds -lah to ls; * `ls_lah` – adds -lah to ls;
* `man` – change manual section; * `man` – changes manual section;
* `man_no_space` – fixes man commands without spaces, for example `mandiff`; * `man_no_space` – fixes man commands without spaces, for example `mandiff`;
* `mercurial` – fixes wrong `hg` commands; * `mercurial` – fixes wrong `hg` commands;
* `mkdir_p` – adds `-p` when you trying to create directory without parent; * `mkdir_p` – adds `-p` when you trying to create directory without parent;
@@ -190,26 +191,29 @@ Enabled by default only on specific platforms:
* `brew_install` – fixes formula name for `brew install`; * `brew_install` – fixes formula name for `brew install`;
* `brew_unknown_command` – fixes wrong brew commands, for example `brew docto/brew doctor`; * `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; * `brew_upgrade` – appends `--all` to `brew upgrade` as per Homebrew's new behaviour;
* `git_push_force` – adds `--force` to a `git push` (may conflict with `git_push_pull`);
* `pacman` – installs app with `pacman` or `yaourt` if it is not installed. * `pacman` – installs app with `pacman` or `yaourt` if it is not installed.
Bundled, but not enabled by default: Bundled, but not enabled by default:
* `git_push_force` – adds `--force` to a `git push` (may conflict with `git_push_pull`);
* `rm_root` – adds `--no-preserve-root` to `rm -rf /` command. * `rm_root` – adds `--no-preserve-root` to `rm -rf /` command.
## Creating your own rules ## Creating your own rules
For adding your own rule you should create `your-rule-name.py` For adding your own rule you should create `your-rule-name.py`
in `~/.thefuck/rules`. Rule should contain two functions: in `~/.thefuck/rules`. The rule should contain two functions:
`match(command: Command, settings: Settings) -> bool` ```python
and `get_new_command(command: Command, settings: Settings) -> str`. match(command: Command, settings: Settings) -> bool
Also the rule can contain optional function get_new_command(command: Command, settings: Settings) -> str
`side_effect(command: Command, settings: Settings) -> None` and ```
Also the rule can contain an optional function
`side_effect(command: Command, settings: Settings) -> None` and an
optional boolean `enabled_by_default`. optional boolean `enabled_by_default`.
`Command` has three attributes: `script`, `stdout` and `stderr`. `Command` has three attributes: `script`, `stdout` and `stderr`.
`Settings` is a special object filled with `~/.thefuck/settings.py` and values from env, [more](#settings). `Settings` is a special object filled with `~/.thefuck/settings.py` and values from env ([see more below](#settings)).
Simple example of the rule for running script with `sudo`: Simple example of the rule for running script with `sudo`:
@@ -243,7 +247,7 @@ The Fuck has a few settings parameters which can be changed in `~/.thefuck/setti
* `wait_command` – max amount of time in seconds for getting previous command output; * `wait_command` – max amount of time in seconds for getting previous command output;
* `no_colors` – disable colored output; * `no_colors` – disable colored output;
* `priority` – dict with rules priorities, rule with lower `priority` will be matched first; * `priority` – dict with rules priorities, rule with lower `priority` will be matched first;
* `debug` – enables debug output, by default `False`; * `debug` – enables debug output, by default `False`.
Example of `settings.py`: Example of `settings.py`:

View File

@@ -11,7 +11,7 @@ elif (3, 0) < sys.version_info < (3, 3):
' ({}.{} detected).'.format(*sys.version_info[:2])) ' ({}.{} detected).'.format(*sys.version_info[:2]))
sys.exit(-1) sys.exit(-1)
VERSION = '2.1' VERSION = '2.3'
install_requires = ['psutil', 'colorama', 'six'] install_requires = ['psutil', 'colorama', 'six']
extras_require = {':python_version<"3.4"': ['pathlib']} extras_require = {':python_version<"3.4"': ['pathlib']}

View File

@@ -41,10 +41,10 @@ def test_not_match(command):
Command('git commit unknown', stderr=did_not_match('unknown')), Command('git commit unknown', stderr=did_not_match('unknown')),
'git branch unknown && git commit unknown'), 'git branch unknown && git commit unknown'),
(['master'], (['master'],
Command(script='git checkout amster', stderr=did_not_match('amster')), Command(script='git checkout mster', stderr=did_not_match('mster')),
'git checkout master'), 'git checkout master'),
(['master'], (['master'],
Command(script='git commit amster', stderr=did_not_match('amster')), Command(script='git commit mster', stderr=did_not_match('mster')),
'git commit master')]) 'git commit master')])
def test_get_new_command(branches, command, new_command, get_branches): def test_get_new_command(branches, command, new_command, get_branches):
get_branches.return_value = branches get_branches.return_value = branches

View File

@@ -3,7 +3,9 @@ from thefuck.rules.git_diff_staged import match, get_new_command
from tests.utils import Command from tests.utils import Command
@pytest.mark.parametrize('command', [Command(script='git diff')]) @pytest.mark.parametrize('command', [
Command(script='git diff foo'),
Command(script='git diff')])
def test_match(command): def test_match(command):
assert match(command, None) assert match(command, None)
@@ -18,6 +20,7 @@ def test_not_match(command):
@pytest.mark.parametrize('command, new_command', [ @pytest.mark.parametrize('command, new_command', [
(Command('git diff'), 'git diff --staged')]) (Command('git diff'), 'git diff --staged'),
(Command('git diff foo'), 'git diff --staged foo')])
def test_get_new_command(command, new_command): def test_get_new_command(command, new_command):
assert get_new_command(command, None) == new_command assert get_new_command(command, None) == new_command

View File

@@ -20,5 +20,5 @@ def test_match(stderr):
def test_get_new_command(stderr): def test_get_new_command(stderr):
assert get_new_command(Command(stderr=stderr), None)\ assert get_new_command(Command('git push', stderr=stderr), None)\
== "git push --set-upstream origin master" == "git push --set-upstream origin master"

View File

@@ -0,0 +1,34 @@
import pytest
from tests.utils import Command
from thefuck.rules.heroku_not_command import match, get_new_command
def suggest_stderr(cmd):
return ''' ! `{}` is not a heroku command.
! Perhaps you meant `logs`, `pg`.
! See `heroku help` for a list of available commands.'''.format(cmd)
no_suggest_stderr = ''' ! `aaaaa` is not a heroku command.
! See `heroku help` for a list of available commands.'''
@pytest.mark.parametrize('cmd', ['log', 'pge'])
def test_match(cmd):
assert match(
Command('heroku {}'.format(cmd), stderr=suggest_stderr(cmd)), None)
@pytest.mark.parametrize('script, stderr', [
('cat log', suggest_stderr('log')),
('heroku aaa', no_suggest_stderr)])
def test_not_match(script, stderr):
assert not match(Command(script, stderr=stderr), None)
@pytest.mark.parametrize('cmd, result', [
('log', 'heroku logs'),
('pge', 'heroku pg')])
def test_get_new_command(cmd, result):
command = Command('heroku {}'.format(cmd), stderr=suggest_stderr(cmd))
assert get_new_command(command, None) == result

View File

@@ -11,6 +11,7 @@ from tests.utils import Command
('need to be root', ''), ('need to be root', ''),
('need root', ''), ('need root', ''),
('must be root', ''), ('must be root', ''),
('You don\'t have access to the history DB.', ''),
('', "error: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/ipaddr.py'")]) ('', "error: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/ipaddr.py'")])
def test_match(stderr, stdout): def test_match(stderr, stdout):
assert match(Command(stderr=stderr, stdout=stdout), None) assert match(Command(stderr=stderr, stdout=stdout), None)

View File

@@ -36,6 +36,20 @@ def test_git_support(called, command, stderr):
assert fn(Command(script=called, stderr=stderr), None) == command assert fn(Command(script=called, stderr=stderr), None) == command
@pytest.mark.parametrize('command, is_git', [
('git pull', True),
('hub pull', True),
('git push --set-upstream origin foo', True),
('hub push --set-upstream origin foo', True),
('ls', False),
('cat git', False),
('cat hub', False)])
def test_git_support_match(command, is_git):
@git_support
def fn(command, settings): return True
assert fn(Command(script=command), None) == is_git
def test_memoize(): def test_memoize():
fn = Mock(__name__='fn') fn = Mock(__name__='fn')
memoized = memoize(fn) memoized = memoize(fn)

View File

@@ -31,7 +31,7 @@ DEFAULT_SETTINGS = {'rules': DEFAULT_RULES,
'no_colors': False, 'no_colors': False,
'debug': False, 'debug': False,
'priority': {}, 'priority': {},
'env': {'LANG': 'C', 'GIT_TRACE': '1'}} 'env': {'LC_ALL': 'C', 'LANG': 'C', 'GIT_TRACE': '1'}}
ENV_TO_ATTR = {'THEFUCK_RULES': 'rules', ENV_TO_ATTR = {'THEFUCK_RULES': 'rules',
'THEFUCK_WAIT_COMMAND': 'wait_command', 'THEFUCK_WAIT_COMMAND': 'wait_command',

View File

@@ -4,8 +4,7 @@ from thefuck import utils, shells
@utils.git_support @utils.git_support
def match(command, settings): def match(command, settings):
return ('git' in command.script return ('did not match any file(s) known to git.' in command.stderr
and 'did not match any file(s) known to git.' in command.stderr
and "Did you forget to 'git add'?" in command.stderr) and "Did you forget to 'git add'?" in command.stderr)

View File

@@ -3,7 +3,7 @@ from thefuck import utils
@utils.git_support @utils.git_support
def match(command, settings): def match(command, settings):
return ('git branch -d' in command.script return ('branch -d' in command.script
and 'If you are sure you want to delete it' in command.stderr) and 'If you are sure you want to delete it' in command.stderr)

View File

@@ -4,7 +4,7 @@ from thefuck import utils, shells
@utils.git_support @utils.git_support
def match(command, settings): def match(command, settings):
# catches "git branch list" in place of "git branch" # catches "git branch list" in place of "git branch"
return command.script.split() == 'git branch list'.split() return command.script.split()[1:] == 'branch list'.split()
@utils.git_support @utils.git_support

View File

@@ -5,8 +5,7 @@ from thefuck import shells, utils
@utils.git_support @utils.git_support
def match(command, settings): def match(command, settings):
return ('git' in command.script return ('did not match any file(s) known to git.' in command.stderr
and 'did not match any file(s) known to git.' in command.stderr
and "Did you forget to 'git add'?" not in command.stderr) and "Did you forget to 'git add'?" not in command.stderr)

View File

@@ -3,11 +3,10 @@ from thefuck import utils
@utils.git_support @utils.git_support
def match(command, settings): def match(command, settings):
return ('git' in command.script and return ('diff' in command.script and
'diff' in command.script and
'--staged' not in command.script) '--staged' not in command.script)
@utils.git_support @utils.git_support
def get_new_command(command, settings): def get_new_command(command, settings):
return '{} --staged'.format(command.script) return command.script.replace(' diff', ' diff --staged')

View File

@@ -4,8 +4,7 @@ from thefuck.utils import get_closest, git_support
@git_support @git_support
def match(command, settings): def match(command, settings):
return ('git' in command.script return (" is not a git command. See 'git --help'." in command.stderr
and " is not a git command. See 'git --help'." in command.stderr
and 'Did you mean' in command.stderr) and 'Did you mean' in command.stderr)

View File

@@ -3,8 +3,7 @@ from thefuck import shells, utils
@utils.git_support @utils.git_support
def match(command, settings): def match(command, settings):
return ('git' in command.script return ('pull' in command.script
and 'pull' in command.script
and 'set-upstream' in command.stderr) and 'set-upstream' in command.stderr)

View File

@@ -1,11 +1,9 @@
import re from thefuck import utils
from thefuck import utils, shells
@utils.git_support @utils.git_support
def match(command, settings): def match(command, settings):
return ('git pull' in command.script return ('fatal: Not a git repository' in command.stderr
and 'fatal: Not a git repository' in command.stderr
and "Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)." in command.stderr) and "Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)." in command.stderr)

View File

@@ -3,8 +3,7 @@ from thefuck import utils
@utils.git_support @utils.git_support
def match(command, settings): def match(command, settings):
return ('git' in command.script return ('push' in command.script
and 'push' in command.script
and 'set-upstream' in command.stderr) and 'set-upstream' in command.stderr)

View File

@@ -3,8 +3,7 @@ from thefuck import utils
@utils.git_support @utils.git_support
def match(command, settings): def match(command, settings):
return ('git' in command.script return ('push' in command.script
and 'push' in command.script
and '! [rejected]' in command.stderr and '! [rejected]' in command.stderr
and 'failed to push some refs to' in command.stderr and 'failed to push some refs to' in command.stderr
and 'Updates were rejected because the tip of your current branch is behind' in command.stderr) and 'Updates were rejected because the tip of your current branch is behind' in command.stderr)

View File

@@ -4,8 +4,7 @@ from thefuck.shells import and_
@utils.git_support @utils.git_support
def match(command, settings): def match(command, settings):
return ('git' in command.script return ('push' in command.script
and 'push' in command.script
and '! [rejected]' in command.stderr and '! [rejected]' in command.stderr
and 'failed to push some refs to' in command.stderr and 'failed to push some refs to' in command.stderr
and 'Updates were rejected because the tip of your current branch is behind' in command.stderr) and 'Updates were rejected because the tip of your current branch is behind' in command.stderr)

View File

@@ -5,7 +5,7 @@ from thefuck import shells, utils
def match(command, settings): def match(command, settings):
# catches "Please commit or stash them" and "Please, commit your changes or # catches "Please commit or stash them" and "Please, commit your changes or
# stash them before you can switch branches." # stash them before you can switch branches."
return 'git' in command.script and 'or stash them' in command.stderr return 'or stash them' in command.stderr
@utils.git_support @utils.git_support

View File

@@ -0,0 +1,20 @@
import re
from thefuck.utils import get_closest
def match(command, settings):
return command.script.startswith('heroku') and \
'is not a heroku command' in command.stderr and \
'Perhaps you meant' in command.stderr
def _get_suggests(stderr):
for line in stderr.split('\n'):
if 'Perhaps you meant' in line:
return re.findall(r'`([^`]+)`', line)
def get_new_command(command, settings):
wrong = re.findall(r'`(\w+)` is not a heroku command', command.stderr)[0]
correct = get_closest(wrong, _get_suggests(command.stderr))
return command.script.replace(' {}'.format(wrong), ' {}'.format(correct), 1)

View File

@@ -14,6 +14,7 @@ patterns = ['permission denied',
'need to be root', 'need to be root',
'need root', 'need root',
'only root can do that', 'only root can do that',
'You don\'t have access to the history DB.',
'authentication is required'] 'authentication is required']

View File

@@ -100,7 +100,6 @@ class Bash(Generic):
return u'{}\n'.format(command_script) return u'{}\n'.format(command_script)
def _script_from_history(self, line): def _script_from_history(self, line):
print(line)
return line return line

View File

@@ -75,12 +75,19 @@ def sudo_support(fn):
def git_support(fn): def git_support(fn):
"""Resolve git aliases.""" """Resolves git aliases and supports testing for both git and hub."""
@wraps(fn) @wraps(fn)
def wrapper(command, settings): def wrapper(command, settings):
if (command.script.startswith('git') and # supports GitHub's `hub` command
'trace: alias expansion:' in command.stderr): # which is recommended to be used with `alias git=hub`
# but at this point, shell aliases have already been resolved
is_git_cmd = command.script.startswith(('git', 'hub'))
if not is_git_cmd:
return False
# perform git aliases expansion
if 'trace: alias expansion:' in command.stderr:
search = re.search("trace: alias expansion: ([^ ]*) => ([^\n]*)", search = re.search("trace: alias expansion: ([^ ]*) => ([^\n]*)",
command.stderr) command.stderr)
alias = search.group(1) alias = search.group(1)
@@ -93,6 +100,7 @@ def git_support(fn):
new_script = command.script.replace(alias, expansion) new_script = command.script.replace(alias, expansion)
command = Command._replace(command, script=new_script) command = Command._replace(command, script=new_script)
return fn(command, settings) return fn(command, settings)
return wrapper return wrapper