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
thefuck/utils.py ADDED
@@ -0,0 +1,385 @@
1
+ import atexit
2
+ import os
3
+ import pickle
4
+ import re
5
+ import shelve
6
+ import sys
7
+ import six
8
+ from decorator import decorator
9
+ from difflib import get_close_matches as difflib_get_close_matches
10
+ from functools import wraps
11
+ from .logs import warn, exception
12
+ from .conf import settings
13
+ from .system import Path
14
+
15
+ DEVNULL = open(os.devnull, 'w')
16
+
17
+ if six.PY2:
18
+ import anydbm
19
+ shelve_open_error = anydbm.error
20
+ else:
21
+ import dbm
22
+ shelve_open_error = dbm.error
23
+
24
+
25
+ def memoize(fn):
26
+ """Caches previous calls to the function."""
27
+ memo = {}
28
+
29
+ @wraps(fn)
30
+ def wrapper(*args, **kwargs):
31
+ if not memoize.disabled:
32
+ key = pickle.dumps((args, kwargs))
33
+ if key not in memo:
34
+ memo[key] = fn(*args, **kwargs)
35
+ value = memo[key]
36
+ else:
37
+ # Memoize is disabled, call the function
38
+ value = fn(*args, **kwargs)
39
+
40
+ return value
41
+
42
+ return wrapper
43
+
44
+
45
+ memoize.disabled = False
46
+
47
+
48
+ @memoize
49
+ def which(program):
50
+ """Returns `program` path or `None`."""
51
+ try:
52
+ from shutil import which
53
+
54
+ return which(program)
55
+ except ImportError:
56
+ def is_exe(fpath):
57
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
58
+
59
+ fpath, fname = os.path.split(program)
60
+ if fpath:
61
+ if is_exe(program):
62
+ return program
63
+ else:
64
+ for path in os.environ["PATH"].split(os.pathsep):
65
+ path = path.strip('"')
66
+ exe_file = os.path.join(path, program)
67
+ if is_exe(exe_file):
68
+ return exe_file
69
+
70
+ return None
71
+
72
+
73
+ def default_settings(params):
74
+ """Adds default values to settings if it not presented.
75
+
76
+ Usage:
77
+
78
+ @default_settings({'apt': '/usr/bin/apt'})
79
+ def match(command):
80
+ print(settings.apt)
81
+
82
+ """
83
+ def _default_settings(fn, command):
84
+ for k, w in params.items():
85
+ settings.setdefault(k, w)
86
+ return fn(command)
87
+ return decorator(_default_settings)
88
+
89
+
90
+ def get_closest(word, possibilities, cutoff=0.6, fallback_to_first=True):
91
+ """Returns closest match or just first from possibilities."""
92
+ possibilities = list(possibilities)
93
+ try:
94
+ return difflib_get_close_matches(word, possibilities, 1, cutoff)[0]
95
+ except IndexError:
96
+ if fallback_to_first:
97
+ return possibilities[0]
98
+
99
+
100
+ def get_close_matches(word, possibilities, n=None, cutoff=0.6):
101
+ """Overrides `difflib.get_close_match` to control argument `n`."""
102
+ if n is None:
103
+ n = settings.num_close_matches
104
+ return difflib_get_close_matches(word, possibilities, n, cutoff)
105
+
106
+
107
+ def include_path_in_search(path):
108
+ return not any(path.startswith(x) for x in settings.excluded_search_path_prefixes)
109
+
110
+
111
+ @memoize
112
+ def get_all_executables():
113
+ from thefuck.shells import shell
114
+
115
+ def _safe(fn, fallback):
116
+ try:
117
+ return fn()
118
+ except OSError:
119
+ return fallback
120
+
121
+ tf_alias = get_alias()
122
+ tf_entry_points = ['thefuck', 'fuck']
123
+
124
+ bins = [exe.name.decode('utf8') if six.PY2 else exe.name
125
+ for path in os.environ.get('PATH', '').split(os.pathsep)
126
+ if include_path_in_search(path)
127
+ for exe in _safe(lambda: list(Path(path).iterdir()), [])
128
+ if not _safe(exe.is_dir, True)
129
+ and exe.name not in tf_entry_points]
130
+ aliases = [alias.decode('utf8') if six.PY2 else alias
131
+ for alias in shell.get_aliases() if alias != tf_alias]
132
+
133
+ return bins + aliases
134
+
135
+
136
+ def replace_argument(script, from_, to):
137
+ """Replaces command line argument."""
138
+ replaced_in_the_end = re.sub(u' {}$'.format(re.escape(from_)), u' {}'.format(to),
139
+ script, count=1)
140
+ if replaced_in_the_end != script:
141
+ return replaced_in_the_end
142
+ else:
143
+ return script.replace(
144
+ u' {} '.format(from_), u' {} '.format(to), 1)
145
+
146
+
147
+ @decorator
148
+ def eager(fn, *args, **kwargs):
149
+ return list(fn(*args, **kwargs))
150
+
151
+
152
+ @eager
153
+ def get_all_matched_commands(stderr, separator='Did you mean'):
154
+ if not isinstance(separator, list):
155
+ separator = [separator]
156
+ should_yield = False
157
+ for line in stderr.split('\n'):
158
+ for sep in separator:
159
+ if sep in line:
160
+ should_yield = True
161
+ break
162
+ else:
163
+ if should_yield and line:
164
+ yield line.strip()
165
+
166
+
167
+ def replace_command(command, broken, matched):
168
+ """Helper for *_no_command rules."""
169
+ new_cmds = get_close_matches(broken, matched, cutoff=0.1)
170
+ return [replace_argument(command.script, broken, new_cmd.strip())
171
+ for new_cmd in new_cmds]
172
+
173
+
174
+ @memoize
175
+ def is_app(command, *app_names, **kwargs):
176
+ """Returns `True` if command is call to one of passed app names."""
177
+
178
+ at_least = kwargs.pop('at_least', 0)
179
+ if kwargs:
180
+ raise TypeError("got an unexpected keyword argument '{}'".format(kwargs.keys()))
181
+
182
+ if len(command.script_parts) > at_least:
183
+ return os.path.basename(command.script_parts[0]) in app_names
184
+
185
+ return False
186
+
187
+
188
+ def for_app(*app_names, **kwargs):
189
+ """Specifies that matching script is for one of app names."""
190
+ def _for_app(fn, command):
191
+ if is_app(command, *app_names, **kwargs):
192
+ return fn(command)
193
+ else:
194
+ return False
195
+
196
+ return decorator(_for_app)
197
+
198
+
199
+ class Cache(object):
200
+ """Lazy read cache and save changes at exit."""
201
+
202
+ def __init__(self):
203
+ self._db = None
204
+
205
+ def _init_db(self):
206
+ try:
207
+ self._setup_db()
208
+ except Exception:
209
+ exception("Unable to init cache", sys.exc_info())
210
+ self._db = {}
211
+
212
+ def _setup_db(self):
213
+ cache_dir = self._get_cache_dir()
214
+ cache_path = Path(cache_dir).joinpath('thefuck').as_posix()
215
+
216
+ try:
217
+ self._db = shelve.open(cache_path)
218
+ except shelve_open_error + (ImportError,):
219
+ # Caused when switching between Python versions
220
+ warn("Removing possibly out-dated cache")
221
+ os.remove(cache_path)
222
+ self._db = shelve.open(cache_path)
223
+
224
+ atexit.register(self._db.close)
225
+
226
+ def _get_cache_dir(self):
227
+ default_xdg_cache_dir = os.path.expanduser("~/.cache")
228
+ cache_dir = os.getenv("XDG_CACHE_HOME", default_xdg_cache_dir)
229
+
230
+ # Ensure the cache_path exists, Python 2 does not have the exist_ok
231
+ # parameter
232
+ try:
233
+ os.makedirs(cache_dir)
234
+ except OSError:
235
+ if not os.path.isdir(cache_dir):
236
+ raise
237
+
238
+ return cache_dir
239
+
240
+ def _get_mtime(self, path):
241
+ try:
242
+ return str(os.path.getmtime(path))
243
+ except OSError:
244
+ return '0'
245
+
246
+ def _get_key(self, fn, depends_on, args, kwargs):
247
+ parts = (fn.__module__, repr(fn).split('at')[0],
248
+ depends_on, args, kwargs)
249
+ return str(pickle.dumps(parts))
250
+
251
+ def get_value(self, fn, depends_on, args, kwargs):
252
+ if self._db is None:
253
+ self._init_db()
254
+
255
+ depends_on = [Path(name).expanduser().absolute().as_posix()
256
+ for name in depends_on]
257
+ key = self._get_key(fn, depends_on, args, kwargs)
258
+ etag = '.'.join(self._get_mtime(path) for path in depends_on)
259
+
260
+ if self._db.get(key, {}).get('etag') == etag:
261
+ return self._db[key]['value']
262
+ else:
263
+ value = fn(*args, **kwargs)
264
+ self._db[key] = {'etag': etag, 'value': value}
265
+ return value
266
+
267
+
268
+ _cache = Cache()
269
+
270
+
271
+ def cache(*depends_on):
272
+ """Caches function result in temporary file.
273
+
274
+ Cache will be expired when modification date of files from `depends_on`
275
+ will be changed.
276
+
277
+ Only functions should be wrapped in `cache`, not methods.
278
+
279
+ """
280
+ def cache_decorator(fn):
281
+ @memoize
282
+ @wraps(fn)
283
+ def wrapper(*args, **kwargs):
284
+ if cache.disabled:
285
+ return fn(*args, **kwargs)
286
+ else:
287
+ return _cache.get_value(fn, depends_on, args, kwargs)
288
+
289
+ return wrapper
290
+
291
+ return cache_decorator
292
+
293
+
294
+ cache.disabled = False
295
+
296
+
297
+ def get_installation_version():
298
+ def _from_importlib():
299
+ try:
300
+ from importlib.metadata import ( # py3.8+
301
+ version, PackageNotFoundError, packages_distributions)
302
+ except Exception:
303
+ return
304
+
305
+ for name in ('thefuck',):
306
+ try:
307
+ return version(name)
308
+ except PackageNotFoundError:
309
+ pass
310
+
311
+ try:
312
+ dist_names = packages_distributions().get('thefuck', [])
313
+ except Exception:
314
+ dist_names = []
315
+ for name in dist_names:
316
+ try:
317
+ return version(name)
318
+ except PackageNotFoundError:
319
+ pass
320
+
321
+ for name in ('thefuck-leeguoo',):
322
+ try:
323
+ return version(name)
324
+ except PackageNotFoundError:
325
+ pass
326
+ return
327
+
328
+ result = _from_importlib()
329
+ if result:
330
+ return result
331
+
332
+ try:
333
+ import pkg_resources
334
+ except Exception:
335
+ return 'unknown'
336
+
337
+ try:
338
+ return pkg_resources.require('thefuck')[0].version
339
+ except Exception:
340
+ try:
341
+ return pkg_resources.require('thefuck-leeguoo')[0].version
342
+ except Exception:
343
+ return 'unknown'
344
+
345
+
346
+ def get_alias():
347
+ return os.environ.get('TF_ALIAS', 'fuck')
348
+
349
+
350
+ @memoize
351
+ def get_valid_history_without_current(command):
352
+ def _not_corrected(history, tf_alias):
353
+ """Returns all lines from history except that comes before `fuck`."""
354
+ previous = None
355
+ for line in history:
356
+ if previous is not None and line != tf_alias:
357
+ yield previous
358
+ previous = line
359
+ if history:
360
+ yield history[-1]
361
+
362
+ from thefuck.shells import shell
363
+ history = shell.get_history()
364
+ tf_alias = get_alias()
365
+ executables = set(get_all_executables())\
366
+ .union(shell.get_builtin_commands())
367
+
368
+ return [line for line in _not_corrected(history, tf_alias)
369
+ if not line.startswith(tf_alias) and not line == command.script
370
+ and line.split(' ')[0] in executables]
371
+
372
+
373
+ def format_raw_script(raw_script):
374
+ """Creates single script from a list of script parts.
375
+
376
+ :type raw_script: [basestring]
377
+ :rtype: basestring
378
+
379
+ """
380
+ if six.PY2:
381
+ script = ' '.join(arg.decode('utf-8') for arg in raw_script)
382
+ else:
383
+ script = ' '.join(raw_script)
384
+
385
+ return script.lstrip()