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.
Files changed (218) hide show
  1. thefuck/__init__.py +0 -0
  2. thefuck/ai.py +765 -0
  3. thefuck/argument_parser.py +96 -0
  4. thefuck/conf.py +141 -0
  5. thefuck/const.py +111 -0
  6. thefuck/corrector.py +92 -0
  7. thefuck/entrypoints/__init__.py +0 -0
  8. thefuck/entrypoints/alias.py +28 -0
  9. thefuck/entrypoints/fix_command.py +105 -0
  10. thefuck/entrypoints/main.py +50 -0
  11. thefuck/entrypoints/not_configured.py +201 -0
  12. thefuck/entrypoints/setup.py +227 -0
  13. thefuck/entrypoints/shell_logger.py +79 -0
  14. thefuck/exceptions.py +10 -0
  15. thefuck/logs.py +255 -0
  16. thefuck/output_readers/__init__.py +20 -0
  17. thefuck/output_readers/read_log.py +108 -0
  18. thefuck/output_readers/rerun.py +72 -0
  19. thefuck/output_readers/shell_logger.py +60 -0
  20. thefuck/rules/__init__.py +0 -0
  21. thefuck/rules/adb_unknown_command.py +54 -0
  22. thefuck/rules/ag_literal.py +10 -0
  23. thefuck/rules/apt_get.py +50 -0
  24. thefuck/rules/apt_get_search.py +14 -0
  25. thefuck/rules/apt_invalid_operation.py +63 -0
  26. thefuck/rules/apt_list_upgradable.py +16 -0
  27. thefuck/rules/apt_upgrade.py +16 -0
  28. thefuck/rules/aws_cli.py +17 -0
  29. thefuck/rules/az_cli.py +17 -0
  30. thefuck/rules/brew_cask_dependency.py +33 -0
  31. thefuck/rules/brew_install.py +24 -0
  32. thefuck/rules/brew_link.py +15 -0
  33. thefuck/rules/brew_reinstall.py +19 -0
  34. thefuck/rules/brew_uninstall.py +14 -0
  35. thefuck/rules/brew_unknown_command.py +82 -0
  36. thefuck/rules/brew_update_formula.py +12 -0
  37. thefuck/rules/cargo.py +6 -0
  38. thefuck/rules/cargo_no_command.py +15 -0
  39. thefuck/rules/cat_dir.py +14 -0
  40. thefuck/rules/cd_correction.py +61 -0
  41. thefuck/rules/cd_cs.py +21 -0
  42. thefuck/rules/cd_mkdir.py +21 -0
  43. thefuck/rules/cd_parent.py +16 -0
  44. thefuck/rules/chmod_x.py +15 -0
  45. thefuck/rules/choco_install.py +25 -0
  46. thefuck/rules/composer_not_command.py +22 -0
  47. thefuck/rules/conda_mistype.py +17 -0
  48. thefuck/rules/cp_create_destination.py +15 -0
  49. thefuck/rules/cp_omitting_directory.py +15 -0
  50. thefuck/rules/cpp11.py +12 -0
  51. thefuck/rules/dirty_untar.py +53 -0
  52. thefuck/rules/dirty_unzip.py +60 -0
  53. thefuck/rules/django_south_ghost.py +8 -0
  54. thefuck/rules/django_south_merge.py +8 -0
  55. thefuck/rules/dnf_no_such_command.py +37 -0
  56. thefuck/rules/docker_image_being_used_by_container.py +20 -0
  57. thefuck/rules/docker_login.py +13 -0
  58. thefuck/rules/docker_not_command.py +49 -0
  59. thefuck/rules/dry.py +15 -0
  60. thefuck/rules/fab_command_not_found.py +38 -0
  61. thefuck/rules/fix_alt_space.py +15 -0
  62. thefuck/rules/fix_file.py +80 -0
  63. thefuck/rules/gem_unknown_command.py +36 -0
  64. thefuck/rules/git_add.py +27 -0
  65. thefuck/rules/git_add_force.py +13 -0
  66. thefuck/rules/git_bisect_usage.py +16 -0
  67. thefuck/rules/git_branch_0flag.py +24 -0
  68. thefuck/rules/git_branch_delete.py +13 -0
  69. thefuck/rules/git_branch_delete_checked_out.py +19 -0
  70. thefuck/rules/git_branch_exists.py +25 -0
  71. thefuck/rules/git_branch_list.py +14 -0
  72. thefuck/rules/git_checkout.py +49 -0
  73. thefuck/rules/git_clone_git_clone.py +12 -0
  74. thefuck/rules/git_clone_missing.py +42 -0
  75. thefuck/rules/git_commit_add.py +17 -0
  76. thefuck/rules/git_commit_amend.py +11 -0
  77. thefuck/rules/git_commit_reset.py +11 -0
  78. thefuck/rules/git_diff_no_index.py +16 -0
  79. thefuck/rules/git_diff_staged.py +13 -0
  80. thefuck/rules/git_fix_stash.py +37 -0
  81. thefuck/rules/git_flag_after_filename.py +31 -0
  82. thefuck/rules/git_help_aliased.py +12 -0
  83. thefuck/rules/git_hook_bypass.py +27 -0
  84. thefuck/rules/git_lfs_mistype.py +18 -0
  85. thefuck/rules/git_main_master.py +16 -0
  86. thefuck/rules/git_merge.py +18 -0
  87. thefuck/rules/git_merge_unrelated.py +12 -0
  88. thefuck/rules/git_not_command.py +18 -0
  89. thefuck/rules/git_pull.py +16 -0
  90. thefuck/rules/git_pull_clone.py +13 -0
  91. thefuck/rules/git_pull_uncommitted_changes.py +14 -0
  92. thefuck/rules/git_push.py +44 -0
  93. thefuck/rules/git_push_different_branch_names.py +12 -0
  94. thefuck/rules/git_push_force.py +18 -0
  95. thefuck/rules/git_push_pull.py +20 -0
  96. thefuck/rules/git_push_without_commits.py +12 -0
  97. thefuck/rules/git_rebase_merge_dir.py +17 -0
  98. thefuck/rules/git_rebase_no_changes.py +13 -0
  99. thefuck/rules/git_remote_delete.py +13 -0
  100. thefuck/rules/git_remote_seturl_add.py +12 -0
  101. thefuck/rules/git_rm_local_modifications.py +19 -0
  102. thefuck/rules/git_rm_recursive.py +16 -0
  103. thefuck/rules/git_rm_staged.py +19 -0
  104. thefuck/rules/git_stash.py +15 -0
  105. thefuck/rules/git_stash_pop.py +18 -0
  106. thefuck/rules/git_tag_force.py +13 -0
  107. thefuck/rules/git_two_dashes.py +14 -0
  108. thefuck/rules/go_run.py +16 -0
  109. thefuck/rules/go_unknown_command.py +28 -0
  110. thefuck/rules/gradle_no_task.py +34 -0
  111. thefuck/rules/gradle_wrapper.py +13 -0
  112. thefuck/rules/grep_arguments_order.py +23 -0
  113. thefuck/rules/grep_recursive.py +10 -0
  114. thefuck/rules/grunt_task_not_found.py +37 -0
  115. thefuck/rules/gulp_not_task.py +22 -0
  116. thefuck/rules/has_exists_script.py +13 -0
  117. thefuck/rules/heroku_multiple_apps.py +12 -0
  118. thefuck/rules/heroku_not_command.py +11 -0
  119. thefuck/rules/history.py +15 -0
  120. thefuck/rules/hostscli.py +27 -0
  121. thefuck/rules/ifconfig_device_not_found.py +23 -0
  122. thefuck/rules/java.py +17 -0
  123. thefuck/rules/javac.py +18 -0
  124. thefuck/rules/lein_not_task.py +19 -0
  125. thefuck/rules/ln_no_hard_link.py +23 -0
  126. thefuck/rules/ln_s_order.py +26 -0
  127. thefuck/rules/long_form_help.py +27 -0
  128. thefuck/rules/ls_all.py +10 -0
  129. thefuck/rules/ls_lah.py +12 -0
  130. thefuck/rules/man.py +33 -0
  131. thefuck/rules/man_no_space.py +10 -0
  132. thefuck/rules/mercurial.py +27 -0
  133. thefuck/rules/missing_space_before_subcommand.py +21 -0
  134. thefuck/rules/mkdir_p.py +13 -0
  135. thefuck/rules/mvn_no_command.py +11 -0
  136. thefuck/rules/mvn_unknown_lifecycle_phase.py +30 -0
  137. thefuck/rules/nixos_cmd_not_found.py +15 -0
  138. thefuck/rules/no_command.py +41 -0
  139. thefuck/rules/no_such_file.py +30 -0
  140. thefuck/rules/npm_missing_script.py +17 -0
  141. thefuck/rules/npm_run_script.py +17 -0
  142. thefuck/rules/npm_wrong_command.py +42 -0
  143. thefuck/rules/omnienv_no_such_command.py +35 -0
  144. thefuck/rules/open.py +40 -0
  145. thefuck/rules/pacman.py +17 -0
  146. thefuck/rules/pacman_invalid_option.py +20 -0
  147. thefuck/rules/pacman_not_found.py +26 -0
  148. thefuck/rules/path_from_history.py +53 -0
  149. thefuck/rules/php_s.py +11 -0
  150. thefuck/rules/pip_install.py +15 -0
  151. thefuck/rules/pip_unknown_command.py +19 -0
  152. thefuck/rules/port_already_in_use.py +40 -0
  153. thefuck/rules/prove_recursively.py +27 -0
  154. thefuck/rules/python_command.py +17 -0
  155. thefuck/rules/python_execute.py +15 -0
  156. thefuck/rules/python_module_error.py +13 -0
  157. thefuck/rules/quotation_marks.py +12 -0
  158. thefuck/rules/rails_migrations_pending.py +14 -0
  159. thefuck/rules/react_native_command_unrecognized.py +34 -0
  160. thefuck/rules/remove_shell_prompt_literal.py +23 -0
  161. thefuck/rules/remove_trailing_cedilla.py +11 -0
  162. thefuck/rules/rm_dir.py +16 -0
  163. thefuck/rules/rm_root.py +16 -0
  164. thefuck/rules/scm_correction.py +32 -0
  165. thefuck/rules/sed_unterminated_s.py +18 -0
  166. thefuck/rules/sl_ls.py +14 -0
  167. thefuck/rules/ssh_known_hosts.py +37 -0
  168. thefuck/rules/sudo.py +47 -0
  169. thefuck/rules/sudo_command_from_user_path.py +21 -0
  170. thefuck/rules/switch_lang.py +117 -0
  171. thefuck/rules/systemctl.py +22 -0
  172. thefuck/rules/terraform_init.py +13 -0
  173. thefuck/rules/terraform_no_command.py +16 -0
  174. thefuck/rules/test.py.py +10 -0
  175. thefuck/rules/tmux.py +18 -0
  176. thefuck/rules/touch.py +14 -0
  177. thefuck/rules/tsuru_login.py +12 -0
  178. thefuck/rules/tsuru_not_command.py +15 -0
  179. thefuck/rules/unknown_command.py +13 -0
  180. thefuck/rules/unsudo.py +15 -0
  181. thefuck/rules/vagrant_up.py +21 -0
  182. thefuck/rules/whois.py +34 -0
  183. thefuck/rules/workon_doesnt_exists.py +32 -0
  184. thefuck/rules/wrong_hyphen_before_subcommand.py +20 -0
  185. thefuck/rules/yarn_alias.py +14 -0
  186. thefuck/rules/yarn_command_not_found.py +43 -0
  187. thefuck/rules/yarn_command_replaced.py +13 -0
  188. thefuck/rules/yarn_help.py +17 -0
  189. thefuck/rules/yum_invalid_operation.py +39 -0
  190. thefuck/shells/__init__.py +52 -0
  191. thefuck/shells/bash.py +94 -0
  192. thefuck/shells/fish.py +131 -0
  193. thefuck/shells/generic.py +154 -0
  194. thefuck/shells/powershell.py +43 -0
  195. thefuck/shells/tcsh.py +44 -0
  196. thefuck/shells/zsh.py +98 -0
  197. thefuck/specific/__init__.py +0 -0
  198. thefuck/specific/apt.py +3 -0
  199. thefuck/specific/archlinux.py +48 -0
  200. thefuck/specific/brew.py +15 -0
  201. thefuck/specific/dnf.py +3 -0
  202. thefuck/specific/git.py +32 -0
  203. thefuck/specific/nix.py +3 -0
  204. thefuck/specific/npm.py +21 -0
  205. thefuck/specific/sudo.py +18 -0
  206. thefuck/specific/yum.py +3 -0
  207. thefuck/system/__init__.py +7 -0
  208. thefuck/system/unix.py +57 -0
  209. thefuck/system/win32.py +43 -0
  210. thefuck/types.py +261 -0
  211. thefuck/ui.py +116 -0
  212. thefuck/utils.py +385 -0
  213. thefuck_leeguoo-3.41.dist-info/METADATA +681 -0
  214. thefuck_leeguoo-3.41.dist-info/RECORD +218 -0
  215. thefuck_leeguoo-3.41.dist-info/WHEEL +6 -0
  216. thefuck_leeguoo-3.41.dist-info/entry_points.txt +3 -0
  217. thefuck_leeguoo-3.41.dist-info/licenses/LICENSE.md +22 -0
  218. thefuck_leeguoo-3.41.dist-info/top_level.txt +1 -0
@@ -0,0 +1,32 @@
1
+ from thefuck.utils import for_app, memoize
2
+ from thefuck.system import Path
3
+
4
+ path_to_scm = {
5
+ '.git': 'git',
6
+ '.hg': 'hg',
7
+ }
8
+
9
+ wrong_scm_patterns = {
10
+ 'git': 'fatal: Not a git repository',
11
+ 'hg': 'abort: no repository found',
12
+ }
13
+
14
+
15
+ @memoize
16
+ def _get_actual_scm():
17
+ for path, scm in path_to_scm.items():
18
+ if Path(path).is_dir():
19
+ return scm
20
+
21
+
22
+ @for_app(*wrong_scm_patterns.keys())
23
+ def match(command):
24
+ scm = command.script_parts[0]
25
+ pattern = wrong_scm_patterns[scm]
26
+
27
+ return pattern in command.output and _get_actual_scm()
28
+
29
+
30
+ def get_new_command(command):
31
+ scm = _get_actual_scm()
32
+ return u' '.join([scm] + command.script_parts[1:])
@@ -0,0 +1,18 @@
1
+ import shlex
2
+ from thefuck.shells import shell
3
+ from thefuck.utils import for_app
4
+
5
+
6
+ @for_app('sed')
7
+ def match(command):
8
+ return "unterminated `s' command" in command.output
9
+
10
+
11
+ def get_new_command(command):
12
+ script = shlex.split(command.script)
13
+
14
+ for (i, e) in enumerate(script):
15
+ if e.startswith(('s/', '-es/')) and e[-1] != '/':
16
+ script[i] += '/'
17
+
18
+ return ' '.join(map(shell.quote, script))
thefuck/rules/sl_ls.py ADDED
@@ -0,0 +1,14 @@
1
+ """
2
+ This happens way too often
3
+
4
+ When typing really fast cause I'm a 1337 H4X0R,
5
+ I often fuck up 'ls' and type 'sl'. No more!
6
+ """
7
+
8
+
9
+ def match(command):
10
+ return command.script == 'sl'
11
+
12
+
13
+ def get_new_command(command):
14
+ return 'ls'
@@ -0,0 +1,37 @@
1
+ import re
2
+ from thefuck.utils import for_app
3
+
4
+ commands = ('ssh', 'scp')
5
+
6
+
7
+ @for_app(*commands)
8
+ def match(command):
9
+ if not command.script:
10
+ return False
11
+ if not command.script.startswith(commands):
12
+ return False
13
+
14
+ patterns = (
15
+ r'WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!',
16
+ r'WARNING: POSSIBLE DNS SPOOFING DETECTED!',
17
+ r"Warning: the \S+ host key for '([^']+)' differs from the key for the IP address '([^']+)'",
18
+ )
19
+
20
+ return any(re.findall(pattern, command.output) for pattern in patterns)
21
+
22
+
23
+ def get_new_command(command):
24
+ return command.script
25
+
26
+
27
+ def side_effect(old_cmd, command):
28
+ offending_pattern = re.compile(
29
+ r'(?:Offending (?:key for IP|\S+ key)|Matching host key) in ([^:]+):(\d+)',
30
+ re.MULTILINE)
31
+ offending = offending_pattern.findall(old_cmd.output)
32
+ for filepath, lineno in offending:
33
+ with open(filepath, 'r') as fh:
34
+ lines = fh.readlines()
35
+ del lines[int(lineno) - 1]
36
+ with open(filepath, 'w') as fh:
37
+ fh.writelines(lines)
thefuck/rules/sudo.py ADDED
@@ -0,0 +1,47 @@
1
+ patterns = ['permission denied',
2
+ 'eacces',
3
+ 'pkg: insufficient privileges',
4
+ 'you cannot perform this operation unless you are root',
5
+ 'non-root users cannot',
6
+ 'operation not permitted',
7
+ 'not super-user',
8
+ 'superuser privilege',
9
+ 'root privilege',
10
+ 'this command has to be run under the root user.',
11
+ 'this operation requires root.',
12
+ 'requested operation requires superuser privilege',
13
+ 'must be run as root',
14
+ 'must run as root',
15
+ 'must be superuser',
16
+ 'must be root',
17
+ 'need to be root',
18
+ 'need root',
19
+ 'needs to be run as root',
20
+ 'only root can ',
21
+ 'you don\'t have access to the history db.',
22
+ 'authentication is required',
23
+ 'edspermissionerror',
24
+ 'you don\'t have write permissions',
25
+ 'use `sudo`',
26
+ 'sudorequirederror',
27
+ 'error: insufficient privileges',
28
+ 'updatedb: can not open a temporary file']
29
+
30
+
31
+ def match(command):
32
+ if command.script_parts and '&&' not in command.script_parts and command.script_parts[0] == 'sudo':
33
+ return False
34
+
35
+ for pattern in patterns:
36
+ if pattern in command.output.lower():
37
+ return True
38
+ return False
39
+
40
+
41
+ def get_new_command(command):
42
+ if '&&' in command.script:
43
+ return u'sudo sh -c "{}"'.format(" ".join([part for part in command.script_parts if part != "sudo"]))
44
+ elif '>' in command.script:
45
+ return u'sudo sh -c "{}"'.format(command.script.replace('"', '\\"'))
46
+ else:
47
+ return u'sudo {}'.format(command.script)
@@ -0,0 +1,21 @@
1
+ import re
2
+ from thefuck.utils import for_app, which, replace_argument
3
+
4
+
5
+ def _get_command_name(command):
6
+ found = re.findall(r'sudo: (.*): command not found', command.output)
7
+ if found:
8
+ return found[0]
9
+
10
+
11
+ @for_app('sudo')
12
+ def match(command):
13
+ if 'command not found' in command.output:
14
+ command_name = _get_command_name(command)
15
+ return which(command_name)
16
+
17
+
18
+ def get_new_command(command):
19
+ command_name = _get_command_name(command)
20
+ return replace_argument(command.script, command_name,
21
+ u'env "PATH=$PATH" {}'.format(command_name))
@@ -0,0 +1,117 @@
1
+ # -*- encoding: utf-8 -*-
2
+ from thefuck.utils import memoize, get_alias
3
+
4
+ target_layout = '''qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>?'''
5
+ # any new keyboard layout must be appended
6
+
7
+ greek = u''';ςερτυθιοπ[]ασδφγηξκλ΄ζχψωβνμ,./:΅ΕΡΤΥΘΙΟΠ{}ΑΣΔΦΓΗΞΚΛ¨"ΖΧΨΩΒΝΜ<>?'''
8
+ korean = u'''ㅂㅈㄷㄱㅅㅛㅕㅑㅐㅔ[]ㅁㄴㅇㄹㅎㅗㅓㅏㅣ;'ㅋㅌㅊㅍㅠㅜㅡ,./ㅃㅉㄸㄲㅆㅛㅕㅑㅒㅖ{}ㅁㄴㅇㄹㅎㅗㅓㅏㅣ:"ㅋㅌㅊㅍㅠㅜㅡ<>?'''
9
+
10
+ source_layouts = [u'''йцукенгшщзхъфывапролджэячсмитьбю.ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,''',
11
+ u'''йцукенгшщзхїфівапролджєячсмитьбю.ЙЦУКЕНГШЩЗХЇФІВАПРОЛДЖЄЯЧСМИТЬБЮ,''',
12
+ u'''ضصثقفغعهخحجچشسیبلاتنمکگظطزرذدپو./ًٌٍَُِّْ][}{ؤئيإأآة»«:؛كٓژٰ‌ٔء><؟''',
13
+ u'''/'קראטוןםפ][שדגכעיחלךף,זסבהנמצתץ.QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>?''',
14
+ greek,
15
+ korean]
16
+
17
+ source_to_target = {
18
+ greek: {u';': "q", u'ς': "w", u'ε': "e", u'ρ': "r", u'τ': "t", u'υ': "y",
19
+ u'θ': "u", u'ι': "i", u'ο': "o", u'π': "p", u'[': "[", u']': "]",
20
+ u'α': "a", u'σ': "s", u'δ': "d", u'φ': "f", u'γ': "g", u'η': "h",
21
+ u'ξ': "j", u'κ': "k", u'λ': "l", u'΄': "'", u'ζ': "z", u'χ': "x",
22
+ u'ψ': "c", u'ω': "v", u'β': "b", u'ν': "n", u'μ': "m", u',': ",",
23
+ u'.': ".", u'/': "/", u':': "Q", u'΅': "W", u'Ε': "E", u'Ρ': "R",
24
+ u'Τ': "T", u'Υ': "Y", u'Θ': "U", u'Ι': "I", u'Ο': "O", u'Π': "P",
25
+ u'{': "{", u'}': "}", u'Α': "A", u'Σ': "S", u'Δ': "D", u'Φ': "F",
26
+ u'Γ': "G", u'Η': "H", u'Ξ': "J", u'Κ': "K", u'Λ': "L", u'¨': ":",
27
+ u'"': '"', u'Ζ': "Z", u'Χ': "X", u'Ψ': "C", u'Ω': "V", u'Β': "B",
28
+ u'Ν': "N", u'Μ': "M", u'<': "<", u'>': ">", u'?': "?", u'ά': "a",
29
+ u'έ': "e", u'ύ': "y", u'ί': "i", u'ό': "o", u'ή': 'h', u'ώ': u"v",
30
+ u'Ά': "A", u'Έ': "E", u'Ύ': "Y", u'Ί': "I", u'Ό': "O", u'Ή': "H",
31
+ u'Ώ': "V"},
32
+ }
33
+
34
+ '''Lists used for decomposing korean letters.'''
35
+ HEAD_LIST = [u'ㄱ', u'ㄲ', u'ㄴ', u'ㄷ', u'ㄸ', u'ㄹ', u'ㅁ', u'ㅂ', u'ㅃ', u'ㅅ', u'ㅆ',
36
+ u'ㅇ', u'ㅈ', u'ㅉ', u'ㅊ', u'ㅋ', u'ㅌ', u'ㅍ', u'ㅎ']
37
+ BODY_LIST = [u'ㅏ', u'ㅐ', u'ㅑ', u'ㅒ', u'ㅓ', u'ㅔ', u'ㅕ', u'ㅖ', u'ㅗ', u'ㅘ', u'ㅙ',
38
+ u'ㅚ', u'ㅛ', u'ㅜ', u'ㅝ', u'ㅞ', u'ㅟ', u'ㅠ', u'ㅡ', u'ㅢ', u'ㅣ']
39
+ TAIL_LIST = [u' ', u'ㄱ', u'ㄲ', u'ㄳ', u'ㄴ', u'ㄵ', u'ㄶ', u'ㄷ', u'ㄹ', u'ㄺ', u'ㄻ',
40
+ u'ㄼ', u'ㄽ', u'ㄾ', u'ㄿ', u'ㅀ', u'ㅁ', u'ㅂ', u'ㅄ', u'ㅅ', u'ㅆ', u'ㅇ', u'ㅈ',
41
+ u'ㅊ', u'ㅋ', u'ㅌ', u'ㅍ', u'ㅎ']
42
+ DOUBLE_LIST = [u'ㅘ', u'ㅙ', u'ㅚ', u'ㅝ', u'ㅞ', u'ㅟ', u'ㅢ', u'ㄳ', u'ㄵ', u'ㄶ', u'ㄺ',
43
+ u'ㄻ', u'ㄼ', u'ㄽ', u'ㄾ', u'ㅀ', u'ㅄ']
44
+ DOUBLE_MOD_LIST = [u'ㅗㅏ', u'ㅗㅐ', u'ㅗㅣ', u'ㅜㅓ', u'ㅜㅔ', u'ㅜㅣ', u'ㅡㅣ', u'ㄱㅅ',
45
+ u'ㄴㅈ', u'ㄴㅎ', u'ㄹㄱ', u'ㄹㅁ', u'ㄹㅂ', u'ㄹㅅ', u'ㄹㅌ', u'ㄹㅎ', u'ㅂㅅ']
46
+
47
+
48
+ @memoize
49
+ def _get_matched_layout(command):
50
+ # don't use command.split_script here because a layout mismatch will likely
51
+ # result in a non-splitable script as per shlex
52
+ cmd = command.script.split(' ')
53
+ for source_layout in source_layouts:
54
+ is_all_match = True
55
+ for cmd_part in cmd:
56
+ if not all([ch in source_layout or ch in '-_' for ch in cmd_part]):
57
+ is_all_match = False
58
+ break
59
+
60
+ if is_all_match:
61
+ return source_layout
62
+
63
+
64
+ def _switch(ch, layout):
65
+ if ch in layout:
66
+ return target_layout[layout.index(ch)]
67
+ return ch
68
+
69
+
70
+ def _switch_command(command, layout):
71
+ # Layouts with different amount of characters than English
72
+ if layout in source_to_target:
73
+ return ''.join(source_to_target[layout].get(ch, ch)
74
+ for ch in command.script)
75
+
76
+ return ''.join(_switch(ch, layout) for ch in command.script)
77
+
78
+
79
+ def _decompose_korean(command):
80
+ def _change_double(ch):
81
+ if ch in DOUBLE_LIST:
82
+ return DOUBLE_MOD_LIST[DOUBLE_LIST.index(ch)]
83
+ return ch
84
+
85
+ hg_str = u''
86
+ for ch in command.script:
87
+ if u'가' <= ch <= u'힣':
88
+ ord_ch = ord(ch) - ord(u'가')
89
+ hd = ord_ch // 588
90
+ bd = (ord_ch - 588 * hd) // 28
91
+ tl = ord_ch - 588 * hd - 28 * bd
92
+ for ch in [HEAD_LIST[hd], BODY_LIST[bd], TAIL_LIST[tl]]:
93
+ if ch != ' ':
94
+ hg_str += _change_double(ch)
95
+ else:
96
+ hg_str += _change_double(ch)
97
+ return hg_str
98
+
99
+
100
+ def match(command):
101
+ if 'not found' not in command.output:
102
+ return False
103
+ if any(u'ㄱ' <= ch <= u'ㅎ' or u'ㅏ' <= ch <= u'ㅣ' or u'가' <= ch <= u'힣'
104
+ for ch in command.script):
105
+ return True
106
+
107
+ matched_layout = _get_matched_layout(command)
108
+ return (matched_layout and
109
+ _switch_command(command, matched_layout) != get_alias())
110
+
111
+
112
+ def get_new_command(command):
113
+ if any(u'ㄱ' <= ch <= u'ㅎ' or u'ㅏ' <= ch <= u'ㅣ' or u'가' <= ch <= u'힣'
114
+ for ch in command.script):
115
+ command.script = _decompose_korean(command)
116
+ matched_layout = _get_matched_layout(command)
117
+ return _switch_command(command, matched_layout)
@@ -0,0 +1,22 @@
1
+ """
2
+ The confusion in systemctl's param order is massive.
3
+ """
4
+ from thefuck.specific.sudo import sudo_support
5
+ from thefuck.utils import for_app
6
+
7
+
8
+ @sudo_support
9
+ @for_app('systemctl')
10
+ def match(command):
11
+ # Catches "Unknown operation 'service'." when executing systemctl with
12
+ # misordered arguments
13
+ cmd = command.script_parts
14
+ return (cmd and 'Unknown operation \'' in command.output and
15
+ len(cmd) - cmd.index('systemctl') == 3)
16
+
17
+
18
+ @sudo_support
19
+ def get_new_command(command):
20
+ cmd = command.script_parts[:]
21
+ cmd[-1], cmd[-2] = cmd[-2], cmd[-1]
22
+ return ' '.join(cmd)
@@ -0,0 +1,13 @@
1
+ from thefuck.shells import shell
2
+ from thefuck.utils import for_app
3
+
4
+
5
+ @for_app('terraform')
6
+ def match(command):
7
+ return ('this module is not yet installed' in command.output.lower() or
8
+ 'initialization required' in command.output.lower()
9
+ )
10
+
11
+
12
+ def get_new_command(command):
13
+ return shell.and_('terraform init', command.script)
@@ -0,0 +1,16 @@
1
+ import re
2
+ from thefuck.utils import for_app
3
+
4
+ MISTAKE = r'(?<=Terraform has no command named ")([^"]+)(?="\.)'
5
+ FIX = r'(?<=Did you mean ")([^"]+)(?="\?)'
6
+
7
+
8
+ @for_app('terraform')
9
+ def match(command):
10
+ return re.search(MISTAKE, command.output) and re.search(FIX, command.output)
11
+
12
+
13
+ def get_new_command(command):
14
+ mistake = re.search(MISTAKE, command.output).group(0)
15
+ fix = re.search(FIX, command.output).group(0)
16
+ return command.script.replace(mistake, fix)
@@ -0,0 +1,10 @@
1
+ def match(command):
2
+ return command.script == 'test.py' and 'not found' in command.output
3
+
4
+
5
+ def get_new_command(command):
6
+ return 'pytest'
7
+
8
+
9
+ # make it come before the python_command rule
10
+ priority = 900
thefuck/rules/tmux.py ADDED
@@ -0,0 +1,18 @@
1
+ import re
2
+ from thefuck.utils import replace_command, for_app
3
+
4
+
5
+ @for_app('tmux')
6
+ def match(command):
7
+ return ('ambiguous command:' in command.output
8
+ and 'could be:' in command.output)
9
+
10
+
11
+ def get_new_command(command):
12
+ cmd = re.match(r"ambiguous command: (.*), could be: (.*)",
13
+ command.output)
14
+
15
+ old_cmd = cmd.group(1)
16
+ suggestions = [c.strip() for c in cmd.group(2).split(',')]
17
+
18
+ return replace_command(command, old_cmd, suggestions)
thefuck/rules/touch.py ADDED
@@ -0,0 +1,14 @@
1
+ import re
2
+ from thefuck.shells import shell
3
+ from thefuck.utils import for_app
4
+
5
+
6
+ @for_app('touch')
7
+ def match(command):
8
+ return 'No such file or directory' in command.output
9
+
10
+
11
+ def get_new_command(command):
12
+ path = re.findall(
13
+ r"touch: (?:cannot touch ')?(.+)/.+'?:", command.output)[0]
14
+ return shell.and_(u'mkdir -p {}'.format(path), command.script)
@@ -0,0 +1,12 @@
1
+ from thefuck.shells import shell
2
+ from thefuck.utils import for_app
3
+
4
+
5
+ @for_app('tsuru')
6
+ def match(command):
7
+ return ('not authenticated' in command.output
8
+ and 'session has expired' in command.output)
9
+
10
+
11
+ def get_new_command(command):
12
+ return shell.and_('tsuru login', command.script)
@@ -0,0 +1,15 @@
1
+ import re
2
+ from thefuck.utils import get_all_matched_commands, replace_command, for_app
3
+
4
+
5
+ @for_app('tsuru')
6
+ def match(command):
7
+ return (' is not a tsuru command. See "tsuru help".' in command.output
8
+ and '\nDid you mean?\n\t' in command.output)
9
+
10
+
11
+ def get_new_command(command):
12
+ broken_cmd = re.findall(r'tsuru: "([^"]*)" is not a tsuru command',
13
+ command.output)[0]
14
+ return replace_command(command, broken_cmd,
15
+ get_all_matched_commands(command.output))
@@ -0,0 +1,13 @@
1
+ import re
2
+ from thefuck.utils import replace_command
3
+
4
+
5
+ def match(command):
6
+ return (re.search(r"([^:]*): Unknown command.*", command.output) is not None
7
+ and re.search(r"Did you mean ([^?]*)?", command.output) is not None)
8
+
9
+
10
+ def get_new_command(command):
11
+ broken_cmd = re.findall(r"([^:]*): Unknown command.*", command.output)[0]
12
+ matched = re.findall(r"Did you mean ([^?]*)?", command.output)
13
+ return replace_command(command, broken_cmd, matched)
@@ -0,0 +1,15 @@
1
+ patterns = ['you cannot perform this operation as root']
2
+
3
+
4
+ def match(command):
5
+ if command.script_parts and command.script_parts[0] != 'sudo':
6
+ return False
7
+
8
+ for pattern in patterns:
9
+ if pattern in command.output.lower():
10
+ return True
11
+ return False
12
+
13
+
14
+ def get_new_command(command):
15
+ return ' '.join(command.script_parts[1:])
@@ -0,0 +1,21 @@
1
+ from thefuck.shells import shell
2
+ from thefuck.utils import for_app
3
+
4
+
5
+ @for_app('vagrant')
6
+ def match(command):
7
+ return 'run `vagrant up`' in command.output.lower()
8
+
9
+
10
+ def get_new_command(command):
11
+ cmds = command.script_parts
12
+ machine = None
13
+ if len(cmds) >= 3:
14
+ machine = cmds[2]
15
+
16
+ start_all_instances = shell.and_(u"vagrant up", command.script)
17
+ if machine is None:
18
+ return start_all_instances
19
+ else:
20
+ return [shell.and_(u"vagrant up {}".format(machine), command.script),
21
+ start_all_instances]
thefuck/rules/whois.py ADDED
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ from six.moves.urllib.parse import urlparse
3
+ from thefuck.utils import for_app
4
+
5
+
6
+ @for_app('whois', at_least=1)
7
+ def match(command):
8
+ """
9
+ What the `whois` command returns depends on the 'Whois server' it contacted
10
+ and is not consistent through different servers. But there can be only two
11
+ types of errors I can think of with `whois`:
12
+ - `whois https://en.wikipedia.org/` → `whois en.wikipedia.org`;
13
+ - `whois en.wikipedia.org` → `whois wikipedia.org`.
14
+ So we match any `whois` command and then:
15
+ - if there is a slash: keep only the FQDN;
16
+ - if there is no slash but there is a point: removes the left-most
17
+ subdomain.
18
+
19
+ We cannot either remove all subdomains because we cannot know which part is
20
+ the subdomains and which is the domain, consider:
21
+ - www.google.fr → subdomain: www, domain: 'google.fr';
22
+ - google.co.uk → subdomain: None, domain; 'google.co.uk'.
23
+ """
24
+ return True
25
+
26
+
27
+ def get_new_command(command):
28
+ url = command.script_parts[1]
29
+
30
+ if '/' in command.script:
31
+ return 'whois ' + urlparse(url).netloc
32
+ elif '.' in command.script:
33
+ path = urlparse(url).path.split('.')
34
+ return ['whois ' + '.'.join(path[n:]) for n in range(1, len(path))]
@@ -0,0 +1,32 @@
1
+ from thefuck.utils import for_app, replace_command, eager, memoize
2
+ from thefuck.system import Path
3
+
4
+
5
+ @memoize
6
+ @eager
7
+ def _get_all_environments():
8
+ root = Path('~/.virtualenvs').expanduser()
9
+ if not root.is_dir():
10
+ return
11
+
12
+ for child in root.iterdir():
13
+ if child.is_dir():
14
+ yield child.name
15
+
16
+
17
+ @for_app('workon')
18
+ def match(command):
19
+ return (len(command.script_parts) >= 2
20
+ and command.script_parts[1] not in _get_all_environments())
21
+
22
+
23
+ def get_new_command(command):
24
+ misspelled_env = command.script_parts[1]
25
+ create_new = u'mkvirtualenv {}'.format(misspelled_env)
26
+
27
+ available = _get_all_environments()
28
+ if available:
29
+ return (replace_command(command, misspelled_env, available)
30
+ + [create_new])
31
+ else:
32
+ return create_new
@@ -0,0 +1,20 @@
1
+ from thefuck.utils import get_all_executables
2
+ from thefuck.specific.sudo import sudo_support
3
+
4
+
5
+ @sudo_support
6
+ def match(command):
7
+ first_part = command.script_parts[0]
8
+ if "-" not in first_part or first_part in get_all_executables():
9
+ return False
10
+ cmd, _ = first_part.split("-", 1)
11
+ return cmd in get_all_executables()
12
+
13
+
14
+ @sudo_support
15
+ def get_new_command(command):
16
+ return command.script.replace("-", " ", 1)
17
+
18
+
19
+ priority = 4500
20
+ requires_output = False
@@ -0,0 +1,14 @@
1
+ import re
2
+ from thefuck.utils import replace_argument, for_app
3
+
4
+
5
+ @for_app('yarn', at_least=1)
6
+ def match(command):
7
+ return 'Did you mean' in command.output
8
+
9
+
10
+ def get_new_command(command):
11
+ broken = command.script_parts[1]
12
+ fix = re.findall(r'Did you mean [`"](?:yarn )?([^`"]*)[`"]', command.output)[0]
13
+
14
+ return replace_argument(command.script, broken, fix)
@@ -0,0 +1,43 @@
1
+ import re
2
+ from subprocess import Popen, PIPE
3
+ from thefuck.utils import (for_app, eager, replace_command, replace_argument,
4
+ cache, which)
5
+
6
+ regex = re.compile(r'error Command "(.*)" not found.')
7
+
8
+
9
+ @for_app('yarn')
10
+ def match(command):
11
+ return regex.findall(command.output)
12
+
13
+
14
+ npm_commands = {'require': 'add'}
15
+
16
+
17
+ @eager
18
+ def _get_all_tasks():
19
+ proc = Popen(['yarn', '--help'], stdout=PIPE)
20
+ should_yield = False
21
+ for line in proc.stdout.readlines():
22
+ line = line.decode().strip()
23
+
24
+ if 'Commands:' in line:
25
+ should_yield = True
26
+ continue
27
+
28
+ if should_yield and '- ' in line:
29
+ yield line.split(' ')[-1]
30
+
31
+
32
+ if which('yarn'):
33
+ _get_all_tasks = cache(which('yarn'))(_get_all_tasks)
34
+
35
+
36
+ def get_new_command(command):
37
+ misspelled_task = regex.findall(command.output)[0]
38
+ if misspelled_task in npm_commands:
39
+ yarn_command = npm_commands[misspelled_task]
40
+ return replace_argument(command.script, misspelled_task, yarn_command)
41
+ else:
42
+ tasks = _get_all_tasks()
43
+ return replace_command(command, misspelled_task, tasks)
@@ -0,0 +1,13 @@
1
+ import re
2
+ from thefuck.utils import for_app
3
+
4
+ regex = re.compile(r'Run "(.*)" instead')
5
+
6
+
7
+ @for_app('yarn', at_least=1)
8
+ def match(command):
9
+ return regex.findall(command.output)
10
+
11
+
12
+ def get_new_command(command):
13
+ return regex.findall(command.output)[0]
@@ -0,0 +1,17 @@
1
+ import re
2
+ from thefuck.utils import for_app
3
+ from thefuck.system import open_command
4
+
5
+
6
+ @for_app('yarn', at_least=2)
7
+ def match(command):
8
+ return (command.script_parts[1] == 'help'
9
+ and 'for documentation about this command.' in command.output)
10
+
11
+
12
+ def get_new_command(command):
13
+ url = re.findall(
14
+ r'Visit ([^ ]*) for documentation about this command.',
15
+ command.output)[0]
16
+
17
+ return open_command(url)