mirror of
https://github.com/nvbn/thefuck.git
synced 2025-11-01 15:42:06 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0fc7c00e8d | ||
|
|
64318c09b7 | ||
|
|
5b6e17b5f1 | ||
|
|
6cdc2c27fb | ||
|
|
62c605d0ac | ||
|
|
8930d01601 | ||
|
|
c749615ad6 | ||
|
|
f03d8c54b1 | ||
|
|
20f1c76d27 | ||
|
|
f477cd69c2 | ||
|
|
690729d5a1 | ||
|
|
f082ba829f | ||
|
|
112e20d7c5 | ||
|
|
95007220fb | ||
|
|
56f636f3d8 | ||
|
|
932a7c5db5 | ||
|
|
1bed4d4e8d | ||
|
|
e0bba379ff | ||
|
|
045959ec47 | ||
|
|
65aeea857e | ||
|
|
793e883073 | ||
|
|
a395ac568c |
20
README.md
20
README.md
@@ -73,7 +73,7 @@ REPL-y 0.3.1
|
||||
...
|
||||
```
|
||||
|
||||
If you are scared to blindly run changed command, there's `require_confirmation`
|
||||
If you are scared to blindly run the changed command, there is a `require_confirmation`
|
||||
[settings](#settings) option:
|
||||
|
||||
```bash
|
||||
@@ -104,7 +104,7 @@ sudo pip install thefuck
|
||||
|
||||
[Or using an OS package manager (OS X, Ubuntu, Arch).](https://github.com/nvbn/thefuck/wiki/Installation)
|
||||
|
||||
And add to `.bashrc` or `.bash_profile`(for OSX):
|
||||
And add to the `.bashrc` or `.bash_profile`(for OSX):
|
||||
|
||||
```bash
|
||||
alias fuck='eval $(thefuck $(fc -ln -1)); history -r'
|
||||
@@ -137,21 +137,25 @@ sudo pip install thefuck --upgrade
|
||||
|
||||
## How it works
|
||||
|
||||
The Fuck tries to match rule for the previous command, create new command
|
||||
using matched rule and run it. Rules enabled by default:
|
||||
The Fuck tries to match a rule for the previous command, creates a new command
|
||||
using the matched rule and runs it. Rules enabled by default are as follows:
|
||||
|
||||
* `brew_unknown_command` – fixes wrong brew commands, for example `brew docto/brew doctor`;
|
||||
* `cpp11` – add missing `-std=c++11` to `g++` or `clang++`;
|
||||
* `cd_parent` – changes `cd..` to `cd ..`;
|
||||
* `cd_mkdir` – creates directories before cd'ing into them;
|
||||
* `cp_omitting_directory` – adds `-a` when you `cp` directory;
|
||||
* `dry` – fix repetitions like "git git push";
|
||||
* `fix_alt_space` – replaces Alt+Space with Space character;
|
||||
* `git_add` – fix *"Did you forget to 'git add'?"*;
|
||||
* `git_checkout` – creates the branch before checking-out;
|
||||
* `git_no_command` – fixes wrong git commands like `git brnch`;
|
||||
* `git_push` – adds `--set-upstream origin $branch` to previous failed `git push`;
|
||||
* `has_exists_script` – prepends `./` when script/binary exists;
|
||||
* `lein_not_task` – fixes wrong `lein` tasks like `lein rpl`;
|
||||
* `mkdir_p` – adds `-p` when you trying to create directory without parent;
|
||||
* `no_command` – fixes wrong console commands, for example `vom/vim`;
|
||||
* `man_no_space` – fixes man commands without spaces, for example `mandiff`;
|
||||
* `pacman` – installs app with `pacman` or `yaourt` if it is not installed;
|
||||
* `pip_unknown_command` – fixes wrong pip commands, for example `pip instatl/pip install`;
|
||||
* `python_command` – prepends `python` when you trying to run not executable/without `./` python script;
|
||||
@@ -193,13 +197,13 @@ def match(command, settings):
|
||||
|
||||
def get_new_command(command, settings):
|
||||
return 'sudo {}'.format(command.script)
|
||||
|
||||
|
||||
# Optional:
|
||||
enabled_by_default = True
|
||||
|
||||
def side_effect(command, settings):
|
||||
subprocess.call('chmod 777 .', shell=True)
|
||||
|
||||
|
||||
priority = 1000 # Lower first
|
||||
```
|
||||
|
||||
@@ -208,10 +212,10 @@ priority = 1000 # Lower first
|
||||
|
||||
## Settings
|
||||
|
||||
The Fuck has a few settings parameters, they can be changed in `~/.thefuck/settings.py`:
|
||||
The Fuck has a few settings parameters which can be changed in `~/.thefuck/settings.py`:
|
||||
|
||||
* `rules` – list of enabled rules, by default `thefuck.conf.DEFAULT_RULES`;
|
||||
* `require_confirmation` – require confirmation before running new command, by default `False`;
|
||||
* `require_confirmation` – requires confirmation before running new command, by default `False`;
|
||||
* `wait_command` – max amount of time in seconds for getting previous command output;
|
||||
* `no_colors` – disable colored output;
|
||||
* `priority` – dict with rules priorities, rule with lower `priority` will be matched first.
|
||||
|
||||
2
setup.py
2
setup.py
@@ -1,7 +1,7 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
|
||||
VERSION = '1.37'
|
||||
VERSION = '1.40'
|
||||
|
||||
|
||||
setup(name='thefuck',
|
||||
|
||||
17
tests/rules/test_dry.py
Normal file
17
tests/rules/test_dry.py
Normal file
@@ -0,0 +1,17 @@
|
||||
import pytest
|
||||
from thefuck.rules.dry import match, get_new_command
|
||||
from tests.utils import Command
|
||||
|
||||
|
||||
@pytest.mark.parametrize('command', [
|
||||
Command(script='cd cd foo'),
|
||||
Command(script='git git push origin/master')])
|
||||
def test_match(command):
|
||||
assert match(command, None)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('command, new_command', [
|
||||
(Command('cd cd foo'), 'cd foo'),
|
||||
(Command('git git push origin/master'), 'git push origin/master')])
|
||||
def test_get_new_command(command, new_command):
|
||||
assert get_new_command(command, None) == new_command
|
||||
12
tests/rules/test_man_no_space.py
Normal file
12
tests/rules/test_man_no_space.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from thefuck.rules.man_no_space import match, get_new_command
|
||||
from tests.utils import Command
|
||||
|
||||
|
||||
def test_match():
|
||||
assert match(Command('mandiff', stderr='mandiff: command not found'), None)
|
||||
assert not match(Command(), None)
|
||||
|
||||
|
||||
def test_get_new_command():
|
||||
assert get_new_command(
|
||||
Command('mandiff'), None) == 'man diff'
|
||||
9
thefuck/rules/cpp11.py
Normal file
9
thefuck/rules/cpp11.py
Normal file
@@ -0,0 +1,9 @@
|
||||
def match(command, settings):
|
||||
return (('g++' in command.script or 'clang++' in command.script) and
|
||||
('This file requires compiler and library support for the '
|
||||
'ISO C++ 2011 standard.' in command.stderr or
|
||||
'-Wc++11-extensions' in command.stderr))
|
||||
|
||||
|
||||
def get_new_command(command, settings):
|
||||
return command.script + ' -std=c++11'
|
||||
12
thefuck/rules/dry.py
Normal file
12
thefuck/rules/dry.py
Normal file
@@ -0,0 +1,12 @@
|
||||
def match(command, settings):
|
||||
split_command = command.script.split()
|
||||
|
||||
return len(split_command) >= 2 and split_command[0] == split_command[1]
|
||||
|
||||
|
||||
def get_new_command(command, settings):
|
||||
return command.script[command.script.find(' ')+1:]
|
||||
|
||||
# it should be rare enough to actually have to type twice the same word, so
|
||||
# this rule can have a higher priority to come before things like "cd cd foo"
|
||||
priority = 900
|
||||
15
thefuck/rules/git_checkout.py
Normal file
15
thefuck/rules/git_checkout.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import re
|
||||
|
||||
|
||||
def match(command, settings):
|
||||
return ('git' in command.script
|
||||
and 'did not match any file(s) known to git.' in command.stderr
|
||||
and "Did you forget to 'git add'?" not in command.stderr)
|
||||
|
||||
|
||||
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]
|
||||
|
||||
return 'git branch {} && {}'.format(missing_file, command.script)
|
||||
9
thefuck/rules/man_no_space.py
Normal file
9
thefuck/rules/man_no_space.py
Normal file
@@ -0,0 +1,9 @@
|
||||
def match(command, settings):
|
||||
return (command.script.startswith(u'man')
|
||||
and u'command not found' in command.stderr.lower())
|
||||
|
||||
|
||||
def get_new_command(command, settings):
|
||||
return u'man {}'.format(command.script[3:])
|
||||
|
||||
priority = 2000
|
||||
@@ -60,7 +60,7 @@ class Bash(Generic):
|
||||
return dict(
|
||||
self._parse_alias(alias)
|
||||
for alias in proc.stdout.read().decode('utf-8').split('\n')
|
||||
if alias)
|
||||
if alias and '=' in alias)
|
||||
|
||||
def _get_history_file_name(self):
|
||||
return os.environ.get("HISTFILE",
|
||||
@@ -82,7 +82,7 @@ class Zsh(Generic):
|
||||
return dict(
|
||||
self._parse_alias(alias)
|
||||
for alias in proc.stdout.read().decode('utf-8').split('\n')
|
||||
if alias)
|
||||
if alias and '=' in alias)
|
||||
|
||||
def _get_history_file_name(self):
|
||||
return os.environ.get("HISTFILE",
|
||||
@@ -98,7 +98,10 @@ shells = defaultdict(lambda: Generic(), {
|
||||
|
||||
|
||||
def _get_shell():
|
||||
shell = Process(os.getpid()).parent().cmdline()[0]
|
||||
try:
|
||||
shell = Process(os.getpid()).parent().cmdline()[0]
|
||||
except TypeError:
|
||||
shell = Process(os.getpid()).parent.cmdline[0]
|
||||
return shells[shell]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user