1
0
mirror of https://github.com/nvbn/thefuck.git synced 2024-10-05 18:31:10 +01:00
Go to file
2016-04-24 17:56:06 +03:00
tests Merge branch 'fish-put-to-history' of https://github.com/scorphus/thefuck into scorphus-fish-put-to-history 2016-04-22 03:14:31 +03:00
thefuck #495: Add comment in put_to_history 2016-04-22 03:16:16 +03:00
.gitignore added temporary vim files to gitignore 2015-04-17 22:15:48 +02:00
.travis.yml Fix travis builds 2016-01-29 12:03:47 +03:00
appveyor.yml #486: Run tests on AppVeyor 2016-03-29 23:39:53 -03:00
CONTRIBUTING.md Add a CONTRIBUTING file 2015-10-17 15:45:13 +02:00
example.gif #N/A Update readme 2015-07-19 21:53:08 +03:00
install.sh #438: Replace [[ with [ in install script 2016-01-23 23:48:51 +03:00
LICENSE.md Add a copy of the MIT license 2015-04-18 17:29:21 +02:00
MANIFEST.in include LICENSE.md in source distribution 2015-04-19 12:47:12 +08:00
README.md #N/A Add a new rule brew_update_formula 2016-04-20 22:27:39 -03:00
release.py #311 Fix installation without pandoc 2015-07-27 23:31:06 +03:00
requirements.txt #444: Check pip version in setup.py 2016-02-12 20:11:08 +03:00
setup.cfg #311 Use setuptools-markdown 2015-07-27 22:23:20 +03:00
setup.py Bump to 3.9 2016-04-24 17:56:06 +03:00
tox.ini Test python 3.5 with tox 2015-10-28 13:32:37 +01:00

The Fuck Version Build Status Windows Build Status Coverage MIT License

Magnificent app which corrects your previous console command, inspired by a @liamosaur tweet.

gif with examples

Few more examples:

➜ apt-get install vim
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?

➜ fuck
sudo apt-get install vim [enter/↑/↓/ctrl+c]
[sudo] password for nvbn:
Reading package lists... Done
...
➜ git push
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin master


➜ fuck
git push --set-upstream origin master [enter/↑/↓/ctrl+c]
Counting objects: 9, done.
...
➜ puthon
No command 'puthon' found, did you mean:
 Command 'python' from package 'python-minimal' (main)
 Command 'python' from package 'python3' (main)
zsh: command not found: puthon

➜ fuck
python [enter/↑/↓/ctrl+c]
Python 3.4.2 (default, Oct  8 2014, 13:08:17)
...
➜ git brnch
git: 'brnch' is not a git command. See 'git --help'.

Did you mean this?
    branch

➜ fuck
git branch [enter/↑/↓/ctrl+c]
* master
➜ lein rpl
'rpl' is not a task. See 'lein help'.

Did you mean this?
         repl

➜ fuck
lein repl [enter/↑/↓/ctrl+c]
nREPL server started on port 54848 on host 127.0.0.1 - nrepl://127.0.0.1:54848
REPL-y 0.3.1
...

If you are not scared to blindly run the changed command, there is a require_confirmation settings option:

➜ apt-get install vim
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?

➜ fuck
sudo apt-get install vim
[sudo] password for nvbn:
Reading package lists... Done
...

Requirements

  • python (2.7+ or 3.3+)
  • pip
  • python-dev

Installation [experimental]

On Ubuntu and OS X you can install The Fuck with installation script:

wget -O - https://raw.githubusercontent.com/nvbn/thefuck/master/install.sh | sh - && $0

Manual installation

Install The Fuck with pip:

sudo -H pip install thefuck

Or using an OS package manager (OS X, Ubuntu, Arch).

You should place this command in your .bash_profile, .bashrc, .zshrc or other startup script:

eval "$(thefuck --alias)"
# You can use whatever you want as an alias, like for Mondays:
eval "$(thefuck --alias FUCK)"

Or in your shell config (Bash, Zsh, Fish, Powershell, tcsh).

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).

Update

sudo pip install thefuck --upgrade

Aliases changed in 1.34.

How it works

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:

  • cargo runs cargo build instead of cargo;
  • cargo_no_command fixes wrongs commands like cargo buid;
  • cd_correction spellchecks and correct failed cd commands;
  • cd_mkdir creates directories before cd'ing into them;
  • cd_parent changes cd.. to cd ..;
  • chmod_x add execution bit;
  • composer_not_command fixes composer command name;
  • cp_omitting_directory adds -a when you cp directory;
  • cpp11 adds missing -std=c++11 to g++ or clang++;
  • dirty_untar fixes tar x command that untarred in the current directory;
  • dirty_unzip fixes unzip command that unzipped in the current directory;
  • django_south_ghost adds --delete-ghost-migrations to failed because ghosts django south migration;
  • django_south_merge adds --merge to inconsistent django south migration;
  • 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 "pathspec 'foo' did not match any file(s) known to git.";
  • git_branch_delete changes git branch -d to git branch -D;
  • git_branch_exists offers git branch -d foo, git branch -D foo or git checkout foo when creating a branch that already exists;
  • 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_diff_staged adds --staged to previous git diff with unexpected output;
  • git_fix_stash fixes git stash commands (misspelled subcommand and missing save);
  • git_help_aliased fixes git help <alias> commands replacing with the aliased command;
  • git_not_command fixes wrong git commands like git brnch;
  • git_pull sets upstream before executing previous git pull;
  • 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_pull runs git pull when push was rejected;
  • git_rm_recursive adds -r when you try to rm a directory;
  • git_remote_seturl_add runs git remote add when git remote set_url on nonexistant remote;
  • git_stash stashes you local modifications before rebasing or switching branch;
  • git_two_dashes adds a missing dash to commands like git commit -amend or git rebase -continue;
  • go_run appends .go extension when compiling/running Go programs;
  • grep_arguments_order fixes grep arguments order for situations like grep -lir . test;
  • 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_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;
  • lein_not_task fixes wrong lein tasks like lein rpl;
  • ln_no_hard_link catches hard link creation on directories, suggest symbolic link;
  • ls_lah adds -lah to ls;
  • man changes manual section;
  • man_no_space fixes man commands without spaces, for example mandiff;
  • mercurial fixes wrong hg commands;
  • mkdir_p adds -p when you trying to create directory without parent;
  • mvn_no_command adds clean package to mvn;
  • mvn_unknown_lifecycle_phase fixes misspelled lifecycle phases with mvn;
  • npm_wrong_command fixes wrong npm commands like npm urgrade;
  • no_command fixes wrong console commands, for example vom/vim;
  • no_such_file creates missing directories with mv and cp commands;
  • open prepends http to address passed to open;
  • 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;
  • python_execute appends missing .py when executing Python files;
  • quotation_marks fixes uneven usage of ' and " when containing args';
  • rm_dir adds -rf when you trying to remove directory;
  • sed_unterminated_s adds missing '/' to sed's s commands;
  • 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_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;
  • touch creates missing directories before "touching";
  • 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;
  • unknown_command fixes hadoop hdfs-style "unknown command", for example adds missing '-' to the command on hdfs dfs ls;
  • vagrant_up starts up the vagrant instance;
  • whois fixes whois command.

Enabled by default only on specific platforms:

  • apt_get installs app from apt if it not installed (requires python-commandnotfound / python3-commandnotfound);
  • apt_get_search changes trying to search using apt-get with searching using apt-cache;
  • apt_invalid_operation fixes invalid apt and apt-get calls, like apt-get isntall vim;
  • brew_install fixes formula name for brew install;
  • brew_unknown_command fixes wrong brew commands, for example brew docto/brew doctor;
  • brew_update_formula turns brew update <formula> into brew upgrade <formula>;
  • 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 fixes package name with pacman or yaourt.

Bundled, but not enabled by default:

  • git_push_force adds --force-with-lease to a git push (may conflict with git_push_pull);
  • rm_root adds --no-preserve-root to rm -rf / command.

Creating your own rules

For adding your own rule you should create your-rule-name.py in ~/.config/thefuck/rules. The rule should contain two functions:

match(command: Command) -> bool
get_new_command(command: Command) -> str | list[str]

Also the rule can contain an optional function

side_effect(old_command: Command, fixed_command: str) -> None

and optional enabled_by_default, requires_output and priority variables.

Command has three attributes: script, stdout and stderr.

Rules api changed in 3.0: For accessing settings in rule you need to import it with from thefuck.conf import settings. settings is a special object filled with ~/.config/thefuck/settings.py and values from env (see more below).

Simple example of the rule for running script with sudo:

def match(command):
    return ('permission denied' in command.stderr.lower()
            or 'EACCES' in command.stderr)


def get_new_command(command):
    return 'sudo {}'.format(command.script)

# Optional:
enabled_by_default = True

def side_effect(command, fixed_command):
    subprocess.call('chmod 777 .', shell=True)

priority = 1000  # Lower first, default is 1000

requires_output = True

More examples of rules, utility functions for rules, app/os-specific helpers.

Settings

The Fuck has a few settings parameters which can be changed in $XDG_CONFIG_HOME/thefuck/settings.py ($XDG_CONFIG_HOME defaults to ~/.config):

  • rules list of enabled rules, by default thefuck.conf.DEFAULT_RULES;
  • exclude_rules list of disabled rules, by default [];
  • require_confirmation requires confirmation before running new command, by default True;
  • 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;
  • debug enables debug output, by default False;
  • history_limit numeric value of how many history commands will be scanned, like 2000;
  • alter_history push fixed command to history, by default True.

Example of settings.py:

rules = ['sudo', 'no_command']
exclude_rules = ['git_push']
require_confirmation = True
wait_command = 10
no_colors = False
priority = {'sudo': 100, 'no_command': 9999}
debug = False

Or via environment variables:

  • THEFUCK_RULES list of enabled rules, like DEFAULT_RULES:rm_root or sudo:no_command;
  • THEFUCK_EXCLUDE_RULES list of disabled rules, like git_pull:git_push;
  • THEFUCK_REQUIRE_CONFIRMATION require confirmation before running new command, true/false;
  • THEFUCK_WAIT_COMMAND max amount of time in seconds for getting previous command output;
  • THEFUCK_NO_COLORS disable colored output, true/false;
  • THEFUCK_PRIORITY priority of the rules, like no_command=9999:apt_get=100, rule with lower priority will be matched first;
  • THEFUCK_DEBUG enables debug output, true/false;
  • THEFUCK_HISTORY_LIMIT how many history commands will be scanned, like 2000;
  • THEFUCK_ALTER_HISTORY push fixed command to history true/false.

For example:

export THEFUCK_RULES='sudo:no_command'
export THEFUCK_EXCLUDE_RULES='git_pull:git_push'
export THEFUCK_REQUIRE_CONFIRMATION='true'
export THEFUCK_WAIT_COMMAND=10
export THEFUCK_NO_COLORS='false'
export THEFUCK_PRIORITY='no_command=9999:apt_get=100'
export THEFUCK_HISTORY_LIMIT='2000'

Developing

Install The Fuck for development:

pip install -r requirements.txt
python setup.py develop

Run unit tests:

py.test

Run unit and functional tests (requires docker):

py.test --enable-functional

For sending package to pypi:

sudo apt-get install pandoc
./release.py

License MIT

Project License can be found here.