thefuck-leeguoo 3.41__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- thefuck/__init__.py +0 -0
- thefuck/ai.py +765 -0
- thefuck/argument_parser.py +96 -0
- thefuck/conf.py +141 -0
- thefuck/const.py +111 -0
- thefuck/corrector.py +92 -0
- thefuck/entrypoints/__init__.py +0 -0
- thefuck/entrypoints/alias.py +28 -0
- thefuck/entrypoints/fix_command.py +105 -0
- thefuck/entrypoints/main.py +50 -0
- thefuck/entrypoints/not_configured.py +201 -0
- thefuck/entrypoints/setup.py +227 -0
- thefuck/entrypoints/shell_logger.py +79 -0
- thefuck/exceptions.py +10 -0
- thefuck/logs.py +255 -0
- thefuck/output_readers/__init__.py +20 -0
- thefuck/output_readers/read_log.py +108 -0
- thefuck/output_readers/rerun.py +72 -0
- thefuck/output_readers/shell_logger.py +60 -0
- thefuck/rules/__init__.py +0 -0
- thefuck/rules/adb_unknown_command.py +54 -0
- thefuck/rules/ag_literal.py +10 -0
- thefuck/rules/apt_get.py +50 -0
- thefuck/rules/apt_get_search.py +14 -0
- thefuck/rules/apt_invalid_operation.py +63 -0
- thefuck/rules/apt_list_upgradable.py +16 -0
- thefuck/rules/apt_upgrade.py +16 -0
- thefuck/rules/aws_cli.py +17 -0
- thefuck/rules/az_cli.py +17 -0
- thefuck/rules/brew_cask_dependency.py +33 -0
- thefuck/rules/brew_install.py +24 -0
- thefuck/rules/brew_link.py +15 -0
- thefuck/rules/brew_reinstall.py +19 -0
- thefuck/rules/brew_uninstall.py +14 -0
- thefuck/rules/brew_unknown_command.py +82 -0
- thefuck/rules/brew_update_formula.py +12 -0
- thefuck/rules/cargo.py +6 -0
- thefuck/rules/cargo_no_command.py +15 -0
- thefuck/rules/cat_dir.py +14 -0
- thefuck/rules/cd_correction.py +61 -0
- thefuck/rules/cd_cs.py +21 -0
- thefuck/rules/cd_mkdir.py +21 -0
- thefuck/rules/cd_parent.py +16 -0
- thefuck/rules/chmod_x.py +15 -0
- thefuck/rules/choco_install.py +25 -0
- thefuck/rules/composer_not_command.py +22 -0
- thefuck/rules/conda_mistype.py +17 -0
- thefuck/rules/cp_create_destination.py +15 -0
- thefuck/rules/cp_omitting_directory.py +15 -0
- thefuck/rules/cpp11.py +12 -0
- thefuck/rules/dirty_untar.py +53 -0
- thefuck/rules/dirty_unzip.py +60 -0
- thefuck/rules/django_south_ghost.py +8 -0
- thefuck/rules/django_south_merge.py +8 -0
- thefuck/rules/dnf_no_such_command.py +37 -0
- thefuck/rules/docker_image_being_used_by_container.py +20 -0
- thefuck/rules/docker_login.py +13 -0
- thefuck/rules/docker_not_command.py +49 -0
- thefuck/rules/dry.py +15 -0
- thefuck/rules/fab_command_not_found.py +38 -0
- thefuck/rules/fix_alt_space.py +15 -0
- thefuck/rules/fix_file.py +80 -0
- thefuck/rules/gem_unknown_command.py +36 -0
- thefuck/rules/git_add.py +27 -0
- thefuck/rules/git_add_force.py +13 -0
- thefuck/rules/git_bisect_usage.py +16 -0
- thefuck/rules/git_branch_0flag.py +24 -0
- thefuck/rules/git_branch_delete.py +13 -0
- thefuck/rules/git_branch_delete_checked_out.py +19 -0
- thefuck/rules/git_branch_exists.py +25 -0
- thefuck/rules/git_branch_list.py +14 -0
- thefuck/rules/git_checkout.py +49 -0
- thefuck/rules/git_clone_git_clone.py +12 -0
- thefuck/rules/git_clone_missing.py +42 -0
- thefuck/rules/git_commit_add.py +17 -0
- thefuck/rules/git_commit_amend.py +11 -0
- thefuck/rules/git_commit_reset.py +11 -0
- thefuck/rules/git_diff_no_index.py +16 -0
- thefuck/rules/git_diff_staged.py +13 -0
- thefuck/rules/git_fix_stash.py +37 -0
- thefuck/rules/git_flag_after_filename.py +31 -0
- thefuck/rules/git_help_aliased.py +12 -0
- thefuck/rules/git_hook_bypass.py +27 -0
- thefuck/rules/git_lfs_mistype.py +18 -0
- thefuck/rules/git_main_master.py +16 -0
- thefuck/rules/git_merge.py +18 -0
- thefuck/rules/git_merge_unrelated.py +12 -0
- thefuck/rules/git_not_command.py +18 -0
- thefuck/rules/git_pull.py +16 -0
- thefuck/rules/git_pull_clone.py +13 -0
- thefuck/rules/git_pull_uncommitted_changes.py +14 -0
- thefuck/rules/git_push.py +44 -0
- thefuck/rules/git_push_different_branch_names.py +12 -0
- thefuck/rules/git_push_force.py +18 -0
- thefuck/rules/git_push_pull.py +20 -0
- thefuck/rules/git_push_without_commits.py +12 -0
- thefuck/rules/git_rebase_merge_dir.py +17 -0
- thefuck/rules/git_rebase_no_changes.py +13 -0
- thefuck/rules/git_remote_delete.py +13 -0
- thefuck/rules/git_remote_seturl_add.py +12 -0
- thefuck/rules/git_rm_local_modifications.py +19 -0
- thefuck/rules/git_rm_recursive.py +16 -0
- thefuck/rules/git_rm_staged.py +19 -0
- thefuck/rules/git_stash.py +15 -0
- thefuck/rules/git_stash_pop.py +18 -0
- thefuck/rules/git_tag_force.py +13 -0
- thefuck/rules/git_two_dashes.py +14 -0
- thefuck/rules/go_run.py +16 -0
- thefuck/rules/go_unknown_command.py +28 -0
- thefuck/rules/gradle_no_task.py +34 -0
- thefuck/rules/gradle_wrapper.py +13 -0
- thefuck/rules/grep_arguments_order.py +23 -0
- thefuck/rules/grep_recursive.py +10 -0
- thefuck/rules/grunt_task_not_found.py +37 -0
- thefuck/rules/gulp_not_task.py +22 -0
- thefuck/rules/has_exists_script.py +13 -0
- thefuck/rules/heroku_multiple_apps.py +12 -0
- thefuck/rules/heroku_not_command.py +11 -0
- thefuck/rules/history.py +15 -0
- thefuck/rules/hostscli.py +27 -0
- thefuck/rules/ifconfig_device_not_found.py +23 -0
- thefuck/rules/java.py +17 -0
- thefuck/rules/javac.py +18 -0
- thefuck/rules/lein_not_task.py +19 -0
- thefuck/rules/ln_no_hard_link.py +23 -0
- thefuck/rules/ln_s_order.py +26 -0
- thefuck/rules/long_form_help.py +27 -0
- thefuck/rules/ls_all.py +10 -0
- thefuck/rules/ls_lah.py +12 -0
- thefuck/rules/man.py +33 -0
- thefuck/rules/man_no_space.py +10 -0
- thefuck/rules/mercurial.py +27 -0
- thefuck/rules/missing_space_before_subcommand.py +21 -0
- thefuck/rules/mkdir_p.py +13 -0
- thefuck/rules/mvn_no_command.py +11 -0
- thefuck/rules/mvn_unknown_lifecycle_phase.py +30 -0
- thefuck/rules/nixos_cmd_not_found.py +15 -0
- thefuck/rules/no_command.py +41 -0
- thefuck/rules/no_such_file.py +30 -0
- thefuck/rules/npm_missing_script.py +17 -0
- thefuck/rules/npm_run_script.py +17 -0
- thefuck/rules/npm_wrong_command.py +42 -0
- thefuck/rules/omnienv_no_such_command.py +35 -0
- thefuck/rules/open.py +40 -0
- thefuck/rules/pacman.py +17 -0
- thefuck/rules/pacman_invalid_option.py +20 -0
- thefuck/rules/pacman_not_found.py +26 -0
- thefuck/rules/path_from_history.py +53 -0
- thefuck/rules/php_s.py +11 -0
- thefuck/rules/pip_install.py +15 -0
- thefuck/rules/pip_unknown_command.py +19 -0
- thefuck/rules/port_already_in_use.py +40 -0
- thefuck/rules/prove_recursively.py +27 -0
- thefuck/rules/python_command.py +17 -0
- thefuck/rules/python_execute.py +15 -0
- thefuck/rules/python_module_error.py +13 -0
- thefuck/rules/quotation_marks.py +12 -0
- thefuck/rules/rails_migrations_pending.py +14 -0
- thefuck/rules/react_native_command_unrecognized.py +34 -0
- thefuck/rules/remove_shell_prompt_literal.py +23 -0
- thefuck/rules/remove_trailing_cedilla.py +11 -0
- thefuck/rules/rm_dir.py +16 -0
- thefuck/rules/rm_root.py +16 -0
- thefuck/rules/scm_correction.py +32 -0
- thefuck/rules/sed_unterminated_s.py +18 -0
- thefuck/rules/sl_ls.py +14 -0
- thefuck/rules/ssh_known_hosts.py +37 -0
- thefuck/rules/sudo.py +47 -0
- thefuck/rules/sudo_command_from_user_path.py +21 -0
- thefuck/rules/switch_lang.py +117 -0
- thefuck/rules/systemctl.py +22 -0
- thefuck/rules/terraform_init.py +13 -0
- thefuck/rules/terraform_no_command.py +16 -0
- thefuck/rules/test.py.py +10 -0
- thefuck/rules/tmux.py +18 -0
- thefuck/rules/touch.py +14 -0
- thefuck/rules/tsuru_login.py +12 -0
- thefuck/rules/tsuru_not_command.py +15 -0
- thefuck/rules/unknown_command.py +13 -0
- thefuck/rules/unsudo.py +15 -0
- thefuck/rules/vagrant_up.py +21 -0
- thefuck/rules/whois.py +34 -0
- thefuck/rules/workon_doesnt_exists.py +32 -0
- thefuck/rules/wrong_hyphen_before_subcommand.py +20 -0
- thefuck/rules/yarn_alias.py +14 -0
- thefuck/rules/yarn_command_not_found.py +43 -0
- thefuck/rules/yarn_command_replaced.py +13 -0
- thefuck/rules/yarn_help.py +17 -0
- thefuck/rules/yum_invalid_operation.py +39 -0
- thefuck/shells/__init__.py +52 -0
- thefuck/shells/bash.py +94 -0
- thefuck/shells/fish.py +131 -0
- thefuck/shells/generic.py +154 -0
- thefuck/shells/powershell.py +43 -0
- thefuck/shells/tcsh.py +44 -0
- thefuck/shells/zsh.py +98 -0
- thefuck/specific/__init__.py +0 -0
- thefuck/specific/apt.py +3 -0
- thefuck/specific/archlinux.py +48 -0
- thefuck/specific/brew.py +15 -0
- thefuck/specific/dnf.py +3 -0
- thefuck/specific/git.py +32 -0
- thefuck/specific/nix.py +3 -0
- thefuck/specific/npm.py +21 -0
- thefuck/specific/sudo.py +18 -0
- thefuck/specific/yum.py +3 -0
- thefuck/system/__init__.py +7 -0
- thefuck/system/unix.py +57 -0
- thefuck/system/win32.py +43 -0
- thefuck/types.py +261 -0
- thefuck/ui.py +116 -0
- thefuck/utils.py +385 -0
- thefuck_leeguoo-3.41.dist-info/METADATA +681 -0
- thefuck_leeguoo-3.41.dist-info/RECORD +218 -0
- thefuck_leeguoo-3.41.dist-info/WHEEL +6 -0
- thefuck_leeguoo-3.41.dist-info/entry_points.txt +3 -0
- thefuck_leeguoo-3.41.dist-info/licenses/LICENSE.md +22 -0
- thefuck_leeguoo-3.41.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from thefuck.utils import get_all_executables, get_close_matches, \
|
|
2
|
+
get_valid_history_without_current, get_closest, which
|
|
3
|
+
from thefuck.specific.sudo import sudo_support
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@sudo_support
|
|
7
|
+
def match(command):
|
|
8
|
+
return (not which(command.script_parts[0])
|
|
9
|
+
and ('not found' in command.output
|
|
10
|
+
or 'is not recognized as' in command.output)
|
|
11
|
+
and bool(get_close_matches(command.script_parts[0],
|
|
12
|
+
get_all_executables())))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _get_used_executables(command):
|
|
16
|
+
for script in get_valid_history_without_current(command):
|
|
17
|
+
yield script.split(' ')[0]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@sudo_support
|
|
21
|
+
def get_new_command(command):
|
|
22
|
+
old_command = command.script_parts[0]
|
|
23
|
+
|
|
24
|
+
# One from history:
|
|
25
|
+
already_used = get_closest(
|
|
26
|
+
old_command, _get_used_executables(command),
|
|
27
|
+
fallback_to_first=False)
|
|
28
|
+
if already_used:
|
|
29
|
+
new_cmds = [already_used]
|
|
30
|
+
else:
|
|
31
|
+
new_cmds = []
|
|
32
|
+
|
|
33
|
+
# Other from all executables:
|
|
34
|
+
new_cmds += [cmd for cmd in get_close_matches(old_command,
|
|
35
|
+
get_all_executables())
|
|
36
|
+
if cmd not in new_cmds]
|
|
37
|
+
|
|
38
|
+
return [command.script.replace(old_command, cmd, 1) for cmd in new_cmds]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
priority = 3000
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.shells import shell
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
patterns = (
|
|
6
|
+
r"mv: cannot move '[^']*' to '([^']*)': No such file or directory",
|
|
7
|
+
r"mv: cannot move '[^']*' to '([^']*)': Not a directory",
|
|
8
|
+
r"cp: cannot create regular file '([^']*)': No such file or directory",
|
|
9
|
+
r"cp: cannot create regular file '([^']*)': Not a directory",
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def match(command):
|
|
14
|
+
for pattern in patterns:
|
|
15
|
+
if re.search(pattern, command.output):
|
|
16
|
+
return True
|
|
17
|
+
|
|
18
|
+
return False
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_new_command(command):
|
|
22
|
+
for pattern in patterns:
|
|
23
|
+
file = re.findall(pattern, command.output)
|
|
24
|
+
|
|
25
|
+
if file:
|
|
26
|
+
file = file[0]
|
|
27
|
+
dir = file[0:file.rfind('/')]
|
|
28
|
+
|
|
29
|
+
formatme = shell.and_('mkdir -p {}', '{}')
|
|
30
|
+
return formatme.format(dir, command.script)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.utils import for_app, replace_command
|
|
3
|
+
from thefuck.specific.npm import get_scripts, npm_available
|
|
4
|
+
|
|
5
|
+
enabled_by_default = npm_available
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@for_app('npm')
|
|
9
|
+
def match(command):
|
|
10
|
+
return (any(part.startswith('ru') for part in command.script_parts)
|
|
11
|
+
and 'npm ERR! missing script: ' in command.output)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_new_command(command):
|
|
15
|
+
misspelled_script = re.findall(
|
|
16
|
+
r'.*missing script: (.*)\n', command.output)[0]
|
|
17
|
+
return replace_command(command, misspelled_script, get_scripts())
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from thefuck.specific.npm import npm_available, get_scripts
|
|
2
|
+
from thefuck.utils import for_app
|
|
3
|
+
|
|
4
|
+
enabled_by_default = npm_available
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@for_app('npm')
|
|
8
|
+
def match(command):
|
|
9
|
+
return ('Usage: npm <command>' in command.output
|
|
10
|
+
and not any(part.startswith('ru') for part in command.script_parts)
|
|
11
|
+
and command.script_parts[1] in get_scripts())
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_new_command(command):
|
|
15
|
+
parts = command.script_parts[:]
|
|
16
|
+
parts.insert(1, 'run-script')
|
|
17
|
+
return ' '.join(parts)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from thefuck.specific.npm import npm_available
|
|
2
|
+
from thefuck.utils import replace_argument, for_app, eager, get_closest
|
|
3
|
+
from thefuck.specific.sudo import sudo_support
|
|
4
|
+
|
|
5
|
+
enabled_by_default = npm_available
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _get_wrong_command(script_parts):
|
|
9
|
+
commands = [part for part in script_parts[1:] if not part.startswith('-')]
|
|
10
|
+
if commands:
|
|
11
|
+
return commands[0]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@sudo_support
|
|
15
|
+
@for_app('npm')
|
|
16
|
+
def match(command):
|
|
17
|
+
return (command.script_parts[0] == 'npm' and
|
|
18
|
+
'where <command> is one of:' in command.output and
|
|
19
|
+
_get_wrong_command(command.script_parts))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@eager
|
|
23
|
+
def _get_available_commands(stdout):
|
|
24
|
+
commands_listing = False
|
|
25
|
+
for line in stdout.split('\n'):
|
|
26
|
+
if line.startswith('where <command> is one of:'):
|
|
27
|
+
commands_listing = True
|
|
28
|
+
elif commands_listing:
|
|
29
|
+
if not line:
|
|
30
|
+
break
|
|
31
|
+
|
|
32
|
+
for command in line.split(', '):
|
|
33
|
+
stripped = command.strip()
|
|
34
|
+
if stripped:
|
|
35
|
+
yield stripped
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_new_command(command):
|
|
39
|
+
npm_commands = _get_available_commands(command.output)
|
|
40
|
+
wrong_command = _get_wrong_command(command.script_parts)
|
|
41
|
+
fixed = get_closest(wrong_command, npm_commands)
|
|
42
|
+
return replace_argument(command.script, wrong_command, fixed)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.utils import (cache, for_app, replace_argument, replace_command,
|
|
3
|
+
which)
|
|
4
|
+
from subprocess import PIPE, Popen
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
supported_apps = 'goenv', 'nodenv', 'pyenv', 'rbenv'
|
|
8
|
+
enabled_by_default = any(which(a) for a in supported_apps)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
COMMON_TYPOS = {
|
|
12
|
+
'list': ['versions', 'install --list'],
|
|
13
|
+
'remove': ['uninstall'],
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@for_app(*supported_apps, at_least=1)
|
|
18
|
+
def match(command):
|
|
19
|
+
return 'env: no such command ' in command.output
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_app_commands(app):
|
|
23
|
+
proc = Popen([app, 'commands'], stdout=PIPE)
|
|
24
|
+
return [line.decode('utf-8').strip() for line in proc.stdout.readlines()]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_new_command(command):
|
|
28
|
+
broken = re.findall(r"env: no such command ['`]([^']*)'", command.output)[0]
|
|
29
|
+
matched = [replace_argument(command.script, broken, common_typo)
|
|
30
|
+
for common_typo in COMMON_TYPOS.get(broken, [])]
|
|
31
|
+
|
|
32
|
+
app = command.script_parts[0]
|
|
33
|
+
app_commands = cache(which(app))(get_app_commands)(app)
|
|
34
|
+
matched.extend(replace_command(command, broken, app_commands))
|
|
35
|
+
return matched
|
thefuck/rules/open.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Opens URL's in the default web browser
|
|
2
|
+
#
|
|
3
|
+
# Example:
|
|
4
|
+
# > open github.com
|
|
5
|
+
# The file ~/github.com does not exist.
|
|
6
|
+
# Perhaps you meant 'http://github.com'?
|
|
7
|
+
#
|
|
8
|
+
from thefuck.shells import shell
|
|
9
|
+
from thefuck.utils import eager, for_app
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def is_arg_url(command):
|
|
13
|
+
return ('.com' in command.script or
|
|
14
|
+
'.edu' in command.script or
|
|
15
|
+
'.info' in command.script or
|
|
16
|
+
'.io' in command.script or
|
|
17
|
+
'.ly' in command.script or
|
|
18
|
+
'.me' in command.script or
|
|
19
|
+
'.net' in command.script or
|
|
20
|
+
'.org' in command.script or
|
|
21
|
+
'.se' in command.script or
|
|
22
|
+
'www.' in command.script)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@for_app('open', 'xdg-open', 'gnome-open', 'kde-open')
|
|
26
|
+
def match(command):
|
|
27
|
+
return (is_arg_url(command) or
|
|
28
|
+
command.output.strip().startswith('The file ') and
|
|
29
|
+
command.output.strip().endswith(' does not exist.'))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@eager
|
|
33
|
+
def get_new_command(command):
|
|
34
|
+
output = command.output.strip()
|
|
35
|
+
if is_arg_url(command):
|
|
36
|
+
yield command.script.replace('open ', 'open http://')
|
|
37
|
+
elif output.startswith('The file ') and output.endswith(' does not exist.'):
|
|
38
|
+
arg = command.script.split(' ', 1)[1]
|
|
39
|
+
for option in ['touch', 'mkdir']:
|
|
40
|
+
yield shell.and_(u'{} {}'.format(option, arg), command.script)
|
thefuck/rules/pacman.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from thefuck.specific.archlinux import get_pkgfile, archlinux_env
|
|
2
|
+
from thefuck.shells import shell
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def match(command):
|
|
6
|
+
return 'not found' in command.output and get_pkgfile(command.script)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_new_command(command):
|
|
10
|
+
packages = get_pkgfile(command.script)
|
|
11
|
+
|
|
12
|
+
formatme = shell.and_('{} -S {}', '{}')
|
|
13
|
+
return [formatme.format(pacman, package, command.script)
|
|
14
|
+
for package in packages]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
enabled_by_default, pacman = archlinux_env()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from thefuck.specific.archlinux import archlinux_env
|
|
2
|
+
from thefuck.specific.sudo import sudo_support
|
|
3
|
+
from thefuck.utils import for_app
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@sudo_support
|
|
8
|
+
@for_app("pacman")
|
|
9
|
+
def match(command):
|
|
10
|
+
return command.output.startswith("error: invalid option '-") and any(
|
|
11
|
+
" -{}".format(option) in command.script for option in "surqfdvt"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_new_command(command):
|
|
16
|
+
option = re.findall(r" -[dfqrstuv]", command.script)[0]
|
|
17
|
+
return re.sub(option, option.upper(), command.script)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
enabled_by_default = archlinux_env()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
""" Fixes wrong package names with pacman or yaourt.
|
|
2
|
+
|
|
3
|
+
For example the `llc` program is in package `llvm` so this:
|
|
4
|
+
yay -S llc
|
|
5
|
+
should be:
|
|
6
|
+
yay -S llvm
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from thefuck.utils import replace_command
|
|
10
|
+
from thefuck.specific.archlinux import get_pkgfile, archlinux_env
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def match(command):
|
|
14
|
+
return (command.script_parts
|
|
15
|
+
and (command.script_parts[0] in ('pacman', 'yay', 'pikaur', 'yaourt')
|
|
16
|
+
or command.script_parts[0:2] == ['sudo', 'pacman'])
|
|
17
|
+
and 'error: target not found:' in command.output)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_new_command(command):
|
|
21
|
+
pgr = command.script_parts[-1]
|
|
22
|
+
|
|
23
|
+
return replace_command(command, pgr, get_pkgfile(pgr))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
enabled_by_default, _ = archlinux_env()
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from collections import Counter
|
|
2
|
+
import re
|
|
3
|
+
from thefuck.system import Path
|
|
4
|
+
from thefuck.utils import (get_valid_history_without_current,
|
|
5
|
+
memoize, replace_argument)
|
|
6
|
+
from thefuck.shells import shell
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
patterns = [r'no such file or directory: (.*)$',
|
|
10
|
+
r"cannot access '(.*)': No such file or directory",
|
|
11
|
+
r': (.*): No such file or directory',
|
|
12
|
+
r"can't cd to (.*)$"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@memoize
|
|
16
|
+
def _get_destination(command):
|
|
17
|
+
for pattern in patterns:
|
|
18
|
+
found = re.findall(pattern, command.output)
|
|
19
|
+
if found:
|
|
20
|
+
if found[0] in command.script_parts:
|
|
21
|
+
return found[0]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def match(command):
|
|
25
|
+
return bool(_get_destination(command))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _get_all_absolute_paths_from_history(command):
|
|
29
|
+
counter = Counter()
|
|
30
|
+
|
|
31
|
+
for line in get_valid_history_without_current(command):
|
|
32
|
+
splitted = shell.split_command(line)
|
|
33
|
+
|
|
34
|
+
for param in splitted[1:]:
|
|
35
|
+
if param.startswith('/') or param.startswith('~'):
|
|
36
|
+
if param.endswith('/'):
|
|
37
|
+
param = param[:-1]
|
|
38
|
+
|
|
39
|
+
counter[param] += 1
|
|
40
|
+
|
|
41
|
+
return (path for path, _ in counter.most_common(None))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def get_new_command(command):
|
|
45
|
+
destination = _get_destination(command)
|
|
46
|
+
paths = _get_all_absolute_paths_from_history(command)
|
|
47
|
+
|
|
48
|
+
return [replace_argument(command.script, destination, path)
|
|
49
|
+
for path in paths if path.endswith(destination)
|
|
50
|
+
and Path(path).expanduser().exists()]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
priority = 800
|
thefuck/rules/php_s.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from thefuck.utils import replace_argument, for_app
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@for_app('php', at_least=2)
|
|
5
|
+
def match(command):
|
|
6
|
+
return ('-s' in command.script_parts
|
|
7
|
+
and command.script_parts[-1] != '-s')
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_new_command(command):
|
|
11
|
+
return replace_argument(command.script, "-s", "-S")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from thefuck.utils import for_app
|
|
2
|
+
from thefuck.specific.sudo import sudo_support
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@sudo_support
|
|
6
|
+
@for_app('pip')
|
|
7
|
+
def match(command):
|
|
8
|
+
return ('pip install' in command.script and 'Permission denied' in command.output)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_new_command(command):
|
|
12
|
+
if '--user' not in command.script: # add --user (attempt 1)
|
|
13
|
+
return command.script.replace(' install ', ' install --user ')
|
|
14
|
+
|
|
15
|
+
return 'sudo {}'.format(command.script.replace(' --user', '')) # since --user didn't fix things, let's try sudo (attempt 2)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.utils import replace_argument, for_app
|
|
3
|
+
from thefuck.specific.sudo import sudo_support
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@sudo_support
|
|
7
|
+
@for_app('pip', 'pip2', 'pip3')
|
|
8
|
+
def match(command):
|
|
9
|
+
return ('pip' in command.script and
|
|
10
|
+
'unknown command' in command.output and
|
|
11
|
+
'maybe you meant' in command.output)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_new_command(command):
|
|
15
|
+
broken_cmd = re.findall(r'ERROR: unknown command "([^"]+)"',
|
|
16
|
+
command.output)[0]
|
|
17
|
+
new_cmd = re.findall(r'maybe you meant "([^"]+)"', command.output)[0]
|
|
18
|
+
|
|
19
|
+
return replace_argument(command.script, broken_cmd, new_cmd)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from subprocess import Popen, PIPE
|
|
3
|
+
from thefuck.utils import memoize, which
|
|
4
|
+
from thefuck.shells import shell
|
|
5
|
+
|
|
6
|
+
enabled_by_default = bool(which('lsof'))
|
|
7
|
+
|
|
8
|
+
patterns = [r"bind on address \('.*', (?P<port>\d+)\)",
|
|
9
|
+
r'Unable to bind [^ ]*:(?P<port>\d+)',
|
|
10
|
+
r"can't listen on port (?P<port>\d+)",
|
|
11
|
+
r'listen EADDRINUSE [^ ]*:(?P<port>\d+)']
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@memoize
|
|
15
|
+
def _get_pid_by_port(port):
|
|
16
|
+
proc = Popen(['lsof', '-i', ':{}'.format(port)], stdout=PIPE)
|
|
17
|
+
lines = proc.stdout.read().decode().split('\n')
|
|
18
|
+
if len(lines) > 1:
|
|
19
|
+
return lines[1].split()[1]
|
|
20
|
+
else:
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@memoize
|
|
25
|
+
def _get_used_port(command):
|
|
26
|
+
for pattern in patterns:
|
|
27
|
+
matched = re.search(pattern, command.output)
|
|
28
|
+
if matched:
|
|
29
|
+
return matched.group('port')
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def match(command):
|
|
33
|
+
port = _get_used_port(command)
|
|
34
|
+
return port and _get_pid_by_port(port)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_new_command(command):
|
|
38
|
+
port = _get_used_port(command)
|
|
39
|
+
pid = _get_pid_by_port(port)
|
|
40
|
+
return shell.and_(u'kill {}'.format(pid), command.script)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from thefuck.utils import for_app
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _is_recursive(part):
|
|
6
|
+
if part == '--recurse':
|
|
7
|
+
return True
|
|
8
|
+
elif not part.startswith('--') and part.startswith('-') and 'r' in part:
|
|
9
|
+
return True
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _isdir(part):
|
|
13
|
+
return not part.startswith('-') and os.path.isdir(part)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@for_app('prove')
|
|
17
|
+
def match(command):
|
|
18
|
+
return (
|
|
19
|
+
'NOTESTS' in command.output
|
|
20
|
+
and not any(_is_recursive(part) for part in command.script_parts[1:])
|
|
21
|
+
and any(_isdir(part) for part in command.script_parts[1:]))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_new_command(command):
|
|
25
|
+
parts = command.script_parts[:]
|
|
26
|
+
parts.insert(1, '-r')
|
|
27
|
+
return u' '.join(parts)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from thefuck.specific.sudo import sudo_support
|
|
2
|
+
# add 'python' suffix to the command if
|
|
3
|
+
# 1) The script does not have execute permission or
|
|
4
|
+
# 2) is interpreted as shell script
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@sudo_support
|
|
8
|
+
def match(command):
|
|
9
|
+
return (command.script_parts
|
|
10
|
+
and command.script_parts[0].endswith('.py')
|
|
11
|
+
and ('Permission denied' in command.output or
|
|
12
|
+
'command not found' in command.output))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@sudo_support
|
|
16
|
+
def get_new_command(command):
|
|
17
|
+
return 'python ' + command.script
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Appends .py when executing python files
|
|
2
|
+
#
|
|
3
|
+
# Example:
|
|
4
|
+
# > python foo
|
|
5
|
+
# error: python: can't open file 'foo': [Errno 2] No such file or directory
|
|
6
|
+
from thefuck.utils import for_app
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@for_app('python')
|
|
10
|
+
def match(command):
|
|
11
|
+
return not command.script.endswith('.py')
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_new_command(command):
|
|
15
|
+
return command.script + '.py'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.shells import shell
|
|
3
|
+
|
|
4
|
+
MISSING_MODULE = r"ModuleNotFoundError: No module named '([^']+)'"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def match(command):
|
|
8
|
+
return "ModuleNotFoundError: No module named '" in command.output
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_new_command(command):
|
|
12
|
+
missing_module = re.findall(MISSING_MODULE, command.output)[0]
|
|
13
|
+
return shell.and_("pip install {}".format(missing_module), command.script)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.shells import shell
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
SUGGESTION_REGEX = r"To resolve this issue, run:\s+(.*?)\n"
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def match(command):
|
|
9
|
+
return "Migrations are pending. To resolve this issue, run:" in command.output
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_new_command(command):
|
|
13
|
+
migration_script = re.search(SUGGESTION_REGEX, command.output).group(1)
|
|
14
|
+
return shell.and_(migration_script, command.script)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from subprocess import Popen, PIPE
|
|
3
|
+
from thefuck.utils import for_app, replace_command, cache, eager
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@for_app('react-native')
|
|
7
|
+
def match(command):
|
|
8
|
+
return re.findall(r"Unrecognized command '.*'", command.output)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@cache('package.json')
|
|
12
|
+
@eager
|
|
13
|
+
def _get_commands():
|
|
14
|
+
proc = Popen(['react-native', '--help'], stdout=PIPE)
|
|
15
|
+
should_yield = False
|
|
16
|
+
for line in proc.stdout.readlines():
|
|
17
|
+
line = line.decode().strip()
|
|
18
|
+
|
|
19
|
+
if not line:
|
|
20
|
+
continue
|
|
21
|
+
|
|
22
|
+
if 'Commands:' in line:
|
|
23
|
+
should_yield = True
|
|
24
|
+
continue
|
|
25
|
+
|
|
26
|
+
if should_yield:
|
|
27
|
+
yield line.split(' ')[0]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_new_command(command):
|
|
31
|
+
misspelled_command = re.findall(r"Unrecognized command '(.*)'",
|
|
32
|
+
command.output)[0]
|
|
33
|
+
commands = _get_commands()
|
|
34
|
+
return replace_command(command, misspelled_command, commands)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Fixes error for commands containing one or more occurrences of the shell
|
|
2
|
+
prompt symbol '$'.
|
|
3
|
+
|
|
4
|
+
This usually happens when commands are copied from documentations
|
|
5
|
+
including them in their code blocks.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
> $ git clone https://github.com/nvbn/thefuck.git
|
|
9
|
+
bash: $: command not found...
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import re
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def match(command):
|
|
16
|
+
return (
|
|
17
|
+
"$: command not found" in command.output
|
|
18
|
+
and re.search(r"^[\s]*\$ [\S]+", command.script) is not None
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_new_command(command):
|
|
23
|
+
return command.script.lstrip("$ ")
|
thefuck/rules/rm_dir.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.specific.sudo import sudo_support
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@sudo_support
|
|
6
|
+
def match(command):
|
|
7
|
+
return ('rm' in command.script
|
|
8
|
+
and 'is a directory' in command.output.lower())
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@sudo_support
|
|
12
|
+
def get_new_command(command):
|
|
13
|
+
arguments = '-rf'
|
|
14
|
+
if 'hdfs' in command.script:
|
|
15
|
+
arguments = '-r'
|
|
16
|
+
return re.sub('\\brm (.*)', 'rm ' + arguments + ' \\1', command.script)
|
thefuck/rules/rm_root.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from thefuck.specific.sudo import sudo_support
|
|
2
|
+
|
|
3
|
+
enabled_by_default = False
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@sudo_support
|
|
7
|
+
def match(command):
|
|
8
|
+
return (command.script_parts
|
|
9
|
+
and {'rm', '/'}.issubset(command.script_parts)
|
|
10
|
+
and '--no-preserve-root' not in command.script
|
|
11
|
+
and '--no-preserve-root' in command.output)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@sudo_support
|
|
15
|
+
def get_new_command(command):
|
|
16
|
+
return u'{} --no-preserve-root'.format(command.script)
|