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,63 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
from thefuck.specific.apt import apt_available
|
|
3
|
+
from thefuck.specific.sudo import sudo_support
|
|
4
|
+
from thefuck.utils import for_app, eager, replace_command
|
|
5
|
+
|
|
6
|
+
enabled_by_default = apt_available
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@sudo_support
|
|
10
|
+
@for_app('apt', 'apt-get', 'apt-cache')
|
|
11
|
+
def match(command):
|
|
12
|
+
return 'E: Invalid operation' in command.output
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@eager
|
|
16
|
+
def _parse_apt_operations(help_text_lines):
|
|
17
|
+
is_commands_list = False
|
|
18
|
+
for line in help_text_lines:
|
|
19
|
+
line = line.decode().strip()
|
|
20
|
+
if is_commands_list and line:
|
|
21
|
+
yield line.split()[0]
|
|
22
|
+
elif line.startswith('Basic commands:') \
|
|
23
|
+
or line.startswith('Most used commands:'):
|
|
24
|
+
is_commands_list = True
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@eager
|
|
28
|
+
def _parse_apt_get_and_cache_operations(help_text_lines):
|
|
29
|
+
is_commands_list = False
|
|
30
|
+
for line in help_text_lines:
|
|
31
|
+
line = line.decode().strip()
|
|
32
|
+
if is_commands_list:
|
|
33
|
+
if not line:
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
yield line.split()[0]
|
|
37
|
+
elif line.startswith('Commands:') \
|
|
38
|
+
or line.startswith('Most used commands:'):
|
|
39
|
+
is_commands_list = True
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _get_operations(app):
|
|
43
|
+
proc = subprocess.Popen([app, '--help'],
|
|
44
|
+
stdout=subprocess.PIPE,
|
|
45
|
+
stderr=subprocess.PIPE)
|
|
46
|
+
lines = proc.stdout.readlines()
|
|
47
|
+
|
|
48
|
+
if app == 'apt':
|
|
49
|
+
return _parse_apt_operations(lines)
|
|
50
|
+
else:
|
|
51
|
+
return _parse_apt_get_and_cache_operations(lines)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@sudo_support
|
|
55
|
+
def get_new_command(command):
|
|
56
|
+
invalid_operation = command.output.split()[-1]
|
|
57
|
+
|
|
58
|
+
if invalid_operation == 'uninstall':
|
|
59
|
+
return [command.script.replace('uninstall', 'remove')]
|
|
60
|
+
|
|
61
|
+
else:
|
|
62
|
+
operations = _get_operations(command.script_parts[0])
|
|
63
|
+
return replace_command(command, invalid_operation, operations)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from thefuck.specific.apt import apt_available
|
|
2
|
+
from thefuck.specific.sudo import sudo_support
|
|
3
|
+
from thefuck.utils import for_app
|
|
4
|
+
|
|
5
|
+
enabled_by_default = apt_available
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@sudo_support
|
|
9
|
+
@for_app('apt')
|
|
10
|
+
def match(command):
|
|
11
|
+
return 'apt list --upgradable' in command.output
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@sudo_support
|
|
15
|
+
def get_new_command(command):
|
|
16
|
+
return 'apt list --upgradable'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from thefuck.specific.apt import apt_available
|
|
2
|
+
from thefuck.specific.sudo import sudo_support
|
|
3
|
+
from thefuck.utils import for_app
|
|
4
|
+
|
|
5
|
+
enabled_by_default = apt_available
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@sudo_support
|
|
9
|
+
@for_app('apt')
|
|
10
|
+
def match(command):
|
|
11
|
+
return command.script == "apt list --upgradable" and len(command.output.strip().split('\n')) > 1
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@sudo_support
|
|
15
|
+
def get_new_command(command):
|
|
16
|
+
return 'apt upgrade'
|
thefuck/rules/aws_cli.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
from thefuck.utils import for_app, replace_argument
|
|
4
|
+
|
|
5
|
+
INVALID_CHOICE = "(?<=Invalid choice: ')(.*)(?=', maybe you meant:)"
|
|
6
|
+
OPTIONS = "^\\s*\\*\\s(.*)"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@for_app('aws')
|
|
10
|
+
def match(command):
|
|
11
|
+
return "usage:" in command.output and "maybe you meant:" in command.output
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_new_command(command):
|
|
15
|
+
mistake = re.search(INVALID_CHOICE, command.output).group(0)
|
|
16
|
+
options = re.findall(OPTIONS, command.output, flags=re.MULTILINE)
|
|
17
|
+
return [replace_argument(command.script, mistake, o) for o in options]
|
thefuck/rules/az_cli.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
from thefuck.utils import for_app, replace_argument
|
|
4
|
+
|
|
5
|
+
INVALID_CHOICE = "(?=az)(?:.*): '(.*)' is not in the '.*' command group."
|
|
6
|
+
OPTIONS = "^The most similar choice to '.*' is:\n\\s*(.*)$"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@for_app('az')
|
|
10
|
+
def match(command):
|
|
11
|
+
return "is not in the" in command.output and "command group" in command.output
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_new_command(command):
|
|
15
|
+
mistake = re.search(INVALID_CHOICE, command.output).group(1)
|
|
16
|
+
options = re.findall(OPTIONS, command.output, flags=re.MULTILINE)
|
|
17
|
+
return [replace_argument(command.script, mistake, o) for o in options]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from thefuck.utils import for_app, eager
|
|
2
|
+
from thefuck.shells import shell
|
|
3
|
+
from thefuck.specific.brew import brew_available
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@for_app('brew')
|
|
7
|
+
def match(command):
|
|
8
|
+
return (u'install' in command.script_parts
|
|
9
|
+
and u'brew cask install' in command.output)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@eager
|
|
13
|
+
def _get_cask_install_lines(output):
|
|
14
|
+
for line in output.split('\n'):
|
|
15
|
+
line = line.strip()
|
|
16
|
+
if line.startswith('brew cask install'):
|
|
17
|
+
yield line
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _get_script_for_brew_cask(output):
|
|
21
|
+
cask_install_lines = _get_cask_install_lines(output)
|
|
22
|
+
if len(cask_install_lines) > 1:
|
|
23
|
+
return shell.and_(*cask_install_lines)
|
|
24
|
+
else:
|
|
25
|
+
return cask_install_lines[0]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_new_command(command):
|
|
29
|
+
brew_cask_script = _get_script_for_brew_cask(command.output)
|
|
30
|
+
return shell.and_(brew_cask_script, command.script)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
enabled_by_default = brew_available
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.utils import for_app
|
|
3
|
+
from thefuck.specific.brew import brew_available
|
|
4
|
+
|
|
5
|
+
enabled_by_default = brew_available
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _get_suggestions(str):
|
|
9
|
+
suggestions = str.replace(" or ", ", ").split(", ")
|
|
10
|
+
return suggestions
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@for_app('brew', at_least=2)
|
|
14
|
+
def match(command):
|
|
15
|
+
is_proper_command = ('install' in command.script and
|
|
16
|
+
'No available formula' in command.output and
|
|
17
|
+
'Did you mean' in command.output)
|
|
18
|
+
return is_proper_command
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_new_command(command):
|
|
22
|
+
matcher = re.search('Warning: No available formula with the name "(?:[^"]+)". Did you mean (.+)\\?', command.output)
|
|
23
|
+
suggestions = _get_suggestions(matcher.group(1))
|
|
24
|
+
return ["brew install " + formula for formula in suggestions]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from thefuck.utils import for_app
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@for_app('brew', at_least=2)
|
|
5
|
+
def match(command):
|
|
6
|
+
return (command.script_parts[1] in ['ln', 'link']
|
|
7
|
+
and "brew link --overwrite --dry-run" in command.output)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_new_command(command):
|
|
11
|
+
command_parts = command.script_parts[:]
|
|
12
|
+
command_parts[1] = 'link'
|
|
13
|
+
command_parts.insert(2, '--overwrite')
|
|
14
|
+
command_parts.insert(3, '--dry-run')
|
|
15
|
+
return ' '.join(command_parts)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.utils import for_app
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
warning_regex = re.compile(r'Warning: (?:.(?!is ))+ is already installed and '
|
|
6
|
+
r'up-to-date')
|
|
7
|
+
message_regex = re.compile(r'To reinstall (?:(?!, ).)+, run `brew reinstall '
|
|
8
|
+
r'[^`]+`')
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@for_app('brew', at_least=2)
|
|
12
|
+
def match(command):
|
|
13
|
+
return ('install' in command.script
|
|
14
|
+
and warning_regex.search(command.output)
|
|
15
|
+
and message_regex.search(command.output))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_new_command(command):
|
|
19
|
+
return command.script.replace('install', 'reinstall')
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from thefuck.utils import for_app
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@for_app('brew', at_least=2)
|
|
5
|
+
def match(command):
|
|
6
|
+
return (command.script_parts[1] in ['uninstall', 'rm', 'remove']
|
|
7
|
+
and "brew uninstall --force" in command.output)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_new_command(command):
|
|
11
|
+
command_parts = command.script_parts[:]
|
|
12
|
+
command_parts[1] = 'uninstall'
|
|
13
|
+
command_parts.insert(2, '--force')
|
|
14
|
+
return ' '.join(command_parts)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
from thefuck.utils import get_closest, replace_command
|
|
4
|
+
from thefuck.specific.brew import get_brew_path_prefix, brew_available
|
|
5
|
+
|
|
6
|
+
BREW_CMD_PATH = '/Homebrew/Library/Homebrew/cmd'
|
|
7
|
+
TAP_PATH = '/Homebrew/Library/Taps'
|
|
8
|
+
TAP_CMD_PATH = '/%s/%s/cmd'
|
|
9
|
+
|
|
10
|
+
enabled_by_default = brew_available
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _get_brew_commands(brew_path_prefix):
|
|
14
|
+
"""To get brew default commands on local environment"""
|
|
15
|
+
brew_cmd_path = brew_path_prefix + BREW_CMD_PATH
|
|
16
|
+
|
|
17
|
+
return [name[:-3] for name in os.listdir(brew_cmd_path)
|
|
18
|
+
if name.endswith(('.rb', '.sh'))]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _get_brew_tap_specific_commands(brew_path_prefix):
|
|
22
|
+
"""To get tap's specific commands
|
|
23
|
+
https://github.com/Homebrew/homebrew/blob/master/Library/brew.rb#L115"""
|
|
24
|
+
commands = []
|
|
25
|
+
brew_taps_path = brew_path_prefix + TAP_PATH
|
|
26
|
+
|
|
27
|
+
for user in _get_directory_names_only(brew_taps_path):
|
|
28
|
+
taps = _get_directory_names_only(brew_taps_path + '/%s' % user)
|
|
29
|
+
|
|
30
|
+
# Brew Taps's naming rule
|
|
31
|
+
# https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/brew-tap.md#naming-conventions-and-limitations
|
|
32
|
+
taps = (tap for tap in taps if tap.startswith('homebrew-'))
|
|
33
|
+
for tap in taps:
|
|
34
|
+
tap_cmd_path = brew_taps_path + TAP_CMD_PATH % (user, tap)
|
|
35
|
+
|
|
36
|
+
if os.path.isdir(tap_cmd_path):
|
|
37
|
+
commands += (name.replace('brew-', '').replace('.rb', '')
|
|
38
|
+
for name in os.listdir(tap_cmd_path)
|
|
39
|
+
if _is_brew_tap_cmd_naming(name))
|
|
40
|
+
|
|
41
|
+
return commands
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _is_brew_tap_cmd_naming(name):
|
|
45
|
+
return name.startswith('brew-') and name.endswith('.rb')
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _get_directory_names_only(path):
|
|
49
|
+
return [d for d in os.listdir(path)
|
|
50
|
+
if os.path.isdir(os.path.join(path, d))]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _brew_commands():
|
|
54
|
+
brew_path_prefix = get_brew_path_prefix()
|
|
55
|
+
if brew_path_prefix:
|
|
56
|
+
try:
|
|
57
|
+
return (_get_brew_commands(brew_path_prefix)
|
|
58
|
+
+ _get_brew_tap_specific_commands(brew_path_prefix))
|
|
59
|
+
except OSError:
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
# Failback commands for testing (Based on Homebrew 0.9.5)
|
|
63
|
+
return ['info', 'home', 'options', 'install', 'uninstall',
|
|
64
|
+
'search', 'list', 'update', 'upgrade', 'pin', 'unpin',
|
|
65
|
+
'doctor', 'create', 'edit', 'cask']
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def match(command):
|
|
69
|
+
is_proper_command = ('brew' in command.script and
|
|
70
|
+
'Unknown command' in command.output)
|
|
71
|
+
|
|
72
|
+
if is_proper_command:
|
|
73
|
+
broken_cmd = re.findall(r'Error: Unknown command: ([a-z]+)',
|
|
74
|
+
command.output)[0]
|
|
75
|
+
return bool(get_closest(broken_cmd, _brew_commands()))
|
|
76
|
+
return False
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def get_new_command(command):
|
|
80
|
+
broken_cmd = re.findall(r'Error: Unknown command: ([a-z]+)',
|
|
81
|
+
command.output)[0]
|
|
82
|
+
return replace_command(command, broken_cmd, _brew_commands())
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from thefuck.utils import for_app
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@for_app('brew', at_least=2)
|
|
5
|
+
def match(command):
|
|
6
|
+
return ('update' in command.script
|
|
7
|
+
and "Error: This command updates brew itself" in command.output
|
|
8
|
+
and "Use `brew upgrade" in command.output)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_new_command(command):
|
|
12
|
+
return command.script.replace('update', 'upgrade')
|
thefuck/rules/cargo.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.utils import replace_argument, for_app
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@for_app('cargo', at_least=1)
|
|
6
|
+
def match(command):
|
|
7
|
+
return ('no such subcommand' in command.output.lower()
|
|
8
|
+
and 'Did you mean' in command.output)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_new_command(command):
|
|
12
|
+
broken = command.script_parts[1]
|
|
13
|
+
fix = re.findall(r'Did you mean `([^`]*)`', command.output)[0]
|
|
14
|
+
|
|
15
|
+
return replace_argument(command.script, broken, fix)
|
thefuck/rules/cat_dir.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from thefuck.utils import for_app
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@for_app('cat', at_least=1)
|
|
6
|
+
def match(command):
|
|
7
|
+
return (
|
|
8
|
+
command.output.startswith('cat: ') and
|
|
9
|
+
os.path.isdir(command.script_parts[1])
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_new_command(command):
|
|
14
|
+
return command.script.replace('cat', 'ls', 1)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Attempts to spellcheck and correct failed cd commands"""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import six
|
|
5
|
+
from thefuck.specific.sudo import sudo_support
|
|
6
|
+
from thefuck.rules import cd_mkdir
|
|
7
|
+
from thefuck.utils import for_app, get_close_matches
|
|
8
|
+
|
|
9
|
+
__author__ = "mmussomele"
|
|
10
|
+
|
|
11
|
+
MAX_ALLOWED_DIFF = 0.6
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _get_sub_dirs(parent):
|
|
15
|
+
"""Returns a list of the child directories of the given parent directory"""
|
|
16
|
+
return [child for child in os.listdir(parent) if os.path.isdir(os.path.join(parent, child))]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@sudo_support
|
|
20
|
+
@for_app('cd')
|
|
21
|
+
def match(command):
|
|
22
|
+
"""Match function copied from cd_mkdir.py"""
|
|
23
|
+
return (
|
|
24
|
+
command.script.startswith('cd ') and any((
|
|
25
|
+
'no such file or directory' in command.output.lower(),
|
|
26
|
+
'cd: can\'t cd to' in command.output.lower(),
|
|
27
|
+
'does not exist' in command.output.lower()
|
|
28
|
+
)))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@sudo_support
|
|
32
|
+
def get_new_command(command):
|
|
33
|
+
"""
|
|
34
|
+
Attempt to rebuild the path string by spellchecking the directories.
|
|
35
|
+
If it fails (i.e. no directories are a close enough match), then it
|
|
36
|
+
defaults to the rules of cd_mkdir.
|
|
37
|
+
Change sensitivity by changing MAX_ALLOWED_DIFF. Default value is 0.6
|
|
38
|
+
"""
|
|
39
|
+
dest = command.script_parts[1].split(os.sep)
|
|
40
|
+
if dest[-1] == '':
|
|
41
|
+
dest = dest[:-1]
|
|
42
|
+
|
|
43
|
+
if dest[0] == '':
|
|
44
|
+
cwd = os.sep
|
|
45
|
+
dest = dest[1:]
|
|
46
|
+
elif six.PY2:
|
|
47
|
+
cwd = os.getcwdu()
|
|
48
|
+
else:
|
|
49
|
+
cwd = os.getcwd()
|
|
50
|
+
for directory in dest:
|
|
51
|
+
if directory == ".":
|
|
52
|
+
continue
|
|
53
|
+
elif directory == "..":
|
|
54
|
+
cwd = os.path.split(cwd)[0]
|
|
55
|
+
continue
|
|
56
|
+
best_matches = get_close_matches(directory, _get_sub_dirs(cwd), cutoff=MAX_ALLOWED_DIFF)
|
|
57
|
+
if best_matches:
|
|
58
|
+
cwd = os.path.join(cwd, best_matches[0])
|
|
59
|
+
else:
|
|
60
|
+
return cd_mkdir.get_new_command(command)
|
|
61
|
+
return u'cd "{0}"'.format(cwd)
|
thefuck/rules/cd_cs.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
# Redirects cs to cd when there is a typo
|
|
4
|
+
# Due to the proximity of the keys - d and s - this seems like a common typo
|
|
5
|
+
# ~ > cs /etc/
|
|
6
|
+
# cs: command not found
|
|
7
|
+
# ~ > fuck
|
|
8
|
+
# cd /etc/ [enter/↑/↓/ctrl+c]
|
|
9
|
+
# /etc >
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def match(command):
|
|
13
|
+
if command.script_parts[0] == 'cs':
|
|
14
|
+
return True
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_new_command(command):
|
|
18
|
+
return 'cd' + ''.join(command.script[2:])
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
priority = 900
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.utils import for_app
|
|
3
|
+
from thefuck.specific.sudo import sudo_support
|
|
4
|
+
from thefuck.shells import shell
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@sudo_support
|
|
8
|
+
@for_app('cd')
|
|
9
|
+
def match(command):
|
|
10
|
+
return (
|
|
11
|
+
command.script.startswith('cd ') and any((
|
|
12
|
+
'no such file or directory' in command.output.lower(),
|
|
13
|
+
'cd: can\'t cd to' in command.output.lower(),
|
|
14
|
+
'does not exist' in command.output.lower()
|
|
15
|
+
)))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@sudo_support
|
|
19
|
+
def get_new_command(command):
|
|
20
|
+
repl = shell.and_('mkdir -p \\1', 'cd \\1')
|
|
21
|
+
return re.sub(r'^cd (.*)', repl, command.script)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Adds the missing space between the cd command and the target directory
|
|
2
|
+
# when trying to cd to the parent directory.
|
|
3
|
+
#
|
|
4
|
+
# Does not really save chars, but is fun :D
|
|
5
|
+
#
|
|
6
|
+
# Example:
|
|
7
|
+
# > cd..
|
|
8
|
+
# cd..: command not found
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def match(command):
|
|
12
|
+
return command.script == 'cd..'
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_new_command(command):
|
|
16
|
+
return 'cd ..'
|
thefuck/rules/chmod_x.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from thefuck.shells import shell
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def match(command):
|
|
6
|
+
return (command.script.startswith('./')
|
|
7
|
+
and 'permission denied' in command.output.lower()
|
|
8
|
+
and os.path.exists(command.script_parts[0])
|
|
9
|
+
and not os.access(command.script_parts[0], os.X_OK))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_new_command(command):
|
|
13
|
+
return shell.and_(
|
|
14
|
+
'chmod +x {}'.format(command.script_parts[0][2:]),
|
|
15
|
+
command.script)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from thefuck.utils import for_app, which
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@for_app("choco", "cinst")
|
|
5
|
+
def match(command):
|
|
6
|
+
return ((command.script.startswith('choco install') or 'cinst' in command.script_parts)
|
|
7
|
+
and 'Installing the following packages' in command.output)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_new_command(command):
|
|
11
|
+
# Find the argument that is the package name
|
|
12
|
+
for script_part in command.script_parts:
|
|
13
|
+
if (
|
|
14
|
+
script_part not in ["choco", "cinst", "install"]
|
|
15
|
+
# Need exact match (bc chocolatey is a package)
|
|
16
|
+
and not script_part.startswith('-')
|
|
17
|
+
# Leading hyphens are parameters; some packages contain them though
|
|
18
|
+
and '=' not in script_part and '/' not in script_part
|
|
19
|
+
# These are certainly parameters
|
|
20
|
+
):
|
|
21
|
+
return command.script.replace(script_part, script_part + ".install")
|
|
22
|
+
return []
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
enabled_by_default = bool(which("choco")) or bool(which("cinst"))
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.utils import replace_argument, for_app
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@for_app('composer')
|
|
6
|
+
def match(command):
|
|
7
|
+
return (('did you mean this?' in command.output.lower()
|
|
8
|
+
or 'did you mean one of these?' in command.output.lower())) or (
|
|
9
|
+
"install" in command.script_parts and "composer require" in command.output.lower()
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_new_command(command):
|
|
14
|
+
if "install" in command.script_parts and "composer require" in command.output.lower():
|
|
15
|
+
broken_cmd, new_cmd = "install", "require"
|
|
16
|
+
else:
|
|
17
|
+
broken_cmd = re.findall(r"Command \"([^']*)\" is not defined", command.output)[0]
|
|
18
|
+
new_cmd = re.findall(r'Did you mean this\?[^\n]*\n\s*([^\n]*)', command.output)
|
|
19
|
+
if not new_cmd:
|
|
20
|
+
new_cmd = re.findall(r'Did you mean one of these\?[^\n]*\n\s*([^\n]*)', command.output)
|
|
21
|
+
new_cmd = new_cmd[0].strip()
|
|
22
|
+
return replace_argument(command.script, broken_cmd, new_cmd)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.utils import replace_command, for_app
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@for_app("conda")
|
|
6
|
+
def match(command):
|
|
7
|
+
"""
|
|
8
|
+
Match a mistyped command
|
|
9
|
+
"""
|
|
10
|
+
return "Did you mean 'conda" in command.output
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_new_command(command):
|
|
14
|
+
match = re.findall(r"'conda ([^']*)'", command.output)
|
|
15
|
+
broken_cmd = match[0]
|
|
16
|
+
correct_cmd = match[1]
|
|
17
|
+
return replace_command(command, broken_cmd, [correct_cmd])
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from thefuck.shells import shell
|
|
2
|
+
from thefuck.utils import for_app
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@for_app("cp", "mv")
|
|
6
|
+
def match(command):
|
|
7
|
+
return (
|
|
8
|
+
"No such file or directory" in command.output
|
|
9
|
+
or command.output.startswith("cp: directory")
|
|
10
|
+
and command.output.rstrip().endswith("does not exist")
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_new_command(command):
|
|
15
|
+
return shell.and_(u"mkdir -p {}".format(command.script_parts[-1]), command.script)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from thefuck.specific.sudo import sudo_support
|
|
3
|
+
from thefuck.utils import for_app
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@sudo_support
|
|
7
|
+
@for_app('cp')
|
|
8
|
+
def match(command):
|
|
9
|
+
output = command.output.lower()
|
|
10
|
+
return 'omitting directory' in output or 'is a directory' in output
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@sudo_support
|
|
14
|
+
def get_new_command(command):
|
|
15
|
+
return re.sub(r'^cp', 'cp -a', command.script)
|
thefuck/rules/cpp11.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from thefuck.utils import for_app
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@for_app('g++', 'clang++')
|
|
5
|
+
def match(command):
|
|
6
|
+
return ('This file requires compiler and library support for the '
|
|
7
|
+
'ISO C++ 2011 standard.' in command.output or
|
|
8
|
+
'-Wc++11-extensions' in command.output)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_new_command(command):
|
|
12
|
+
return command.script + ' -std=c++11'
|