mirror of
				https://github.com/nvbn/thefuck.git
				synced 2025-10-31 07:04:12 +00:00 
			
		
		
		
	#620: Add support of arguments to fuck, like fuck -y on zsh
				
					
				
			This commit is contained in:
		| @@ -40,17 +40,17 @@ class TestZsh(object): | ||||
|             'll': 'ls -alF'} | ||||
|  | ||||
|     def test_app_alias(self, shell): | ||||
|         assert 'alias fuck' in shell.app_alias('fuck') | ||||
|         assert 'alias FUCK' in shell.app_alias('FUCK') | ||||
|         assert 'fuck () {' in shell.app_alias('fuck') | ||||
|         assert 'FUCK () {' in shell.app_alias('FUCK') | ||||
|         assert 'thefuck' in shell.app_alias('fuck') | ||||
|         assert 'PYTHONIOENCODING' in shell.app_alias('fuck') | ||||
|  | ||||
|     def test_app_alias_variables_correctly_set(self, shell): | ||||
|         alias = shell.app_alias('fuck') | ||||
|         assert "alias fuck='TF_CMD=$(TF_ALIAS" in alias | ||||
|         assert '$(TF_ALIAS=fuck PYTHONIOENCODING' in alias | ||||
|         assert 'PYTHONIOENCODING=utf-8 TF_SHELL_ALIASES' in alias | ||||
|         assert 'ALIASES=$(alias) thefuck' in alias | ||||
|         assert "fuck () {" in alias | ||||
|         assert "TF_ALIAS=fuck" in alias | ||||
|         assert 'PYTHONIOENCODING=utf-8' in alias | ||||
|         assert 'TF_SHELL_ALIASES=$(alias)' in alias | ||||
|  | ||||
|     def test_get_history(self, history_lines, shell): | ||||
|         history_lines([': 1432613911:0;ls', ': 1432613916:0;rm']) | ||||
|   | ||||
							
								
								
									
										26
									
								
								tests/test_argument_parser.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								tests/test_argument_parser.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| import pytest | ||||
| from thefuck.argument_parser import Parser | ||||
| from thefuck.const import ARGUMENT_PLACEHOLDER | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize('argv, result', [ | ||||
|     (['thefuck'], {'alias': None, 'command': [], 'yes': False, | ||||
|                    'help': False, 'version': False}), | ||||
|     (['thefuck', '-a'], {'alias': 'fuck', 'command': [], 'yes': False, | ||||
|                          'help': False, 'version': False}), | ||||
|     (['thefuck', '-a', 'fix'], {'alias': 'fix', 'command': [], 'yes': False, | ||||
|                                 'help': False, 'version': False}), | ||||
|     (['thefuck', 'git', 'branch', ARGUMENT_PLACEHOLDER, '-y'], | ||||
|      {'alias': None, 'command': ['git', 'branch'], 'yes': True, | ||||
|       'help': False, 'version': False}), | ||||
|     (['thefuck', 'git', 'branch', '-a', ARGUMENT_PLACEHOLDER, '-y'], | ||||
|      {'alias': None, 'command': ['git', 'branch', '-a'], 'yes': True, | ||||
|       'help': False, 'version': False}), | ||||
|     (['thefuck', ARGUMENT_PLACEHOLDER, '-v'], | ||||
|      {'alias': None, 'command': [], 'yes': False, 'help': False, | ||||
|       'version': True}), | ||||
|     (['thefuck', ARGUMENT_PLACEHOLDER, '--help'], | ||||
|      {'alias': None, 'command': [], 'yes': False, 'help': True, | ||||
|       'version': False})]) | ||||
| def test_parse(argv, result): | ||||
|     assert vars(Parser().parse(argv)) == result | ||||
							
								
								
									
										48
									
								
								thefuck/argument_parser.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								thefuck/argument_parser.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| import sys | ||||
| from argparse import ArgumentParser | ||||
| from .const import ARGUMENT_PLACEHOLDER | ||||
| from .utils import get_alias | ||||
|  | ||||
|  | ||||
| class Parser(object): | ||||
|     def __init__(self): | ||||
|         self._parser = ArgumentParser(prog='thefuck', add_help=False) | ||||
|         self._parser.add_argument( | ||||
|             '-v', '--version', | ||||
|             action='store_true', | ||||
|             help="show program's version number and exit") | ||||
|         self._parser.add_argument( | ||||
|             '-a', '--alias', | ||||
|             nargs='?', | ||||
|             const=get_alias(), | ||||
|             help='[custom-alias-name] prints alias for current shell') | ||||
|         self._parser.add_argument( | ||||
|             '-h', '--help', | ||||
|             action='store_true', | ||||
|             help='show this help message and exit') | ||||
|         self._parser.add_argument( | ||||
|             '-y', '--yes', | ||||
|             action='store_true', | ||||
|             help='execute fixed command without confirmation') | ||||
|         self._parser.add_argument('command', | ||||
|                                   nargs='*', | ||||
|                                   help='command that should be fixed') | ||||
|  | ||||
|     def _get_arguments(self, argv): | ||||
|         if ARGUMENT_PLACEHOLDER in argv: | ||||
|             index = argv.index(ARGUMENT_PLACEHOLDER) | ||||
|             return argv[index + 1:] + ['--'] + argv[:index] | ||||
|         elif argv and not argv[0].startswith('-') and argv[0] != '--': | ||||
|             return ['--'] + argv | ||||
|         else: | ||||
|             return argv | ||||
|  | ||||
|     def parse(self, argv): | ||||
|         arguments = self._get_arguments(argv[1:]) | ||||
|         return self._parser.parse_args(arguments) | ||||
|  | ||||
|     def print_usage(self): | ||||
|         self._parser.print_usage(sys.stderr) | ||||
|  | ||||
|     def print_help(self): | ||||
|         self._parser.print_help(sys.stderr) | ||||
| @@ -14,7 +14,7 @@ class Settings(dict): | ||||
|     def __setattr__(self, key, value): | ||||
|         self[key] = value | ||||
|  | ||||
|     def init(self): | ||||
|     def init(self, args=None): | ||||
|         """Fills `settings` with values from `settings.py` and env.""" | ||||
|         from .logs import exception | ||||
|  | ||||
| @@ -31,6 +31,8 @@ class Settings(dict): | ||||
|         except Exception: | ||||
|             exception("Can't load settings from env", sys.exc_info()) | ||||
|  | ||||
|         self.update(self._settings_from_args(args)) | ||||
|  | ||||
|     def _init_settings_file(self): | ||||
|         settings_path = self.user_dir.joinpath('settings.py') | ||||
|         if not settings_path.is_file(): | ||||
| @@ -109,5 +111,12 @@ class Settings(dict): | ||||
|                 for env, attr in const.ENV_TO_ATTR.items() | ||||
|                 if env in os.environ} | ||||
|  | ||||
|     def _settings_from_args(self, args): | ||||
|         """Loads settings from args.""" | ||||
|         if args and args.yes: | ||||
|             return {'require_confirmation': False} | ||||
|         else: | ||||
|             return {} | ||||
|  | ||||
|  | ||||
| settings = Settings(const.DEFAULT_SETTINGS) | ||||
|   | ||||
| @@ -59,3 +59,5 @@ SETTINGS_HEADER = u"""# The Fuck settings file | ||||
| # | ||||
|  | ||||
| """ | ||||
|  | ||||
| ARGUMENT_PLACEHOLDER = 'THEFUCK_ARGUMENT_PLACEHOLDER' | ||||
|   | ||||
| @@ -121,3 +121,9 @@ def configured_successfully(configuration_details): | ||||
|             bold=color(colorama.Style.BRIGHT), | ||||
|             reset=color(colorama.Style.RESET_ALL), | ||||
|             reload=configuration_details.reload)) | ||||
|  | ||||
|  | ||||
| def version(thefuck_version, python_version): | ||||
|     print(u'The Fuck {} using Python {}'.format(thefuck_version, | ||||
|                                                 python_version), | ||||
|           file=sys.stderr) | ||||
|   | ||||
| @@ -3,7 +3,6 @@ from .system import init_output | ||||
|  | ||||
| init_output() | ||||
|  | ||||
| from argparse import ArgumentParser  # noqa: E402 | ||||
| from pprint import pformat  # noqa: E402 | ||||
| import sys  # noqa: E402 | ||||
| from . import logs, types  # noqa: E402 | ||||
| @@ -11,18 +10,19 @@ from .shells import shell  # noqa: E402 | ||||
| from .conf import settings  # noqa: E402 | ||||
| from .corrector import get_corrected_commands  # noqa: E402 | ||||
| from .exceptions import EmptyCommand  # noqa: E402 | ||||
| from .utils import get_installation_info, get_alias  # noqa: E402 | ||||
| from .ui import select_command  # noqa: E402 | ||||
| from .argument_parser import Parser  # noqa: E402 | ||||
| from .utils import get_installation_info  # noqa: E402 | ||||
|  | ||||
|  | ||||
| def fix_command(): | ||||
| def fix_command(known_args): | ||||
|     """Fixes previous command. Used when `thefuck` called without arguments.""" | ||||
|     settings.init() | ||||
|     settings.init(known_args) | ||||
|     with logs.debug_time('Total'): | ||||
|         logs.debug(u'Run with settings: {}'.format(pformat(settings))) | ||||
|  | ||||
|         try: | ||||
|             command = types.Command.from_raw_script(sys.argv[1:]) | ||||
|             command = types.Command.from_raw_script(known_args.command) | ||||
|         except EmptyCommand: | ||||
|             logs.debug('Empty command, nothing to do') | ||||
|             return | ||||
| @@ -36,34 +36,18 @@ def fix_command(): | ||||
|             sys.exit(1) | ||||
|  | ||||
|  | ||||
| def print_alias(): | ||||
|     """Prints alias for current shell.""" | ||||
|     try: | ||||
|         alias = sys.argv[2] | ||||
|     except IndexError: | ||||
|         alias = get_alias() | ||||
|  | ||||
|     print(shell.app_alias(alias)) | ||||
|  | ||||
|  | ||||
| def main(): | ||||
|     parser = ArgumentParser(prog='thefuck') | ||||
|     version = get_installation_info().version | ||||
|     parser.add_argument('-v', '--version', | ||||
|                         action='version', | ||||
|                         version='The Fuck {} using Python {}'.format( | ||||
|                             version, sys.version.split()[0])) | ||||
|     parser.add_argument('-a', '--alias', | ||||
|                         action='store_true', | ||||
|                         help='[custom-alias-name] prints alias for current shell') | ||||
|     parser.add_argument('command', | ||||
|                         nargs='*', | ||||
|                         help='command that should be fixed') | ||||
|     known_args = parser.parse_args(sys.argv[1:2]) | ||||
|     parser = Parser() | ||||
|     known_args = parser.parse(sys.argv) | ||||
|  | ||||
|     if known_args.alias: | ||||
|         print_alias() | ||||
|     if known_args.help: | ||||
|         parser.print_help() | ||||
|     elif known_args.version: | ||||
|         logs.version(get_installation_info().version, | ||||
|                      sys.version.split()[0]) | ||||
|     elif known_args.command: | ||||
|         fix_command() | ||||
|         fix_command(known_args) | ||||
|     elif known_args.alias: | ||||
|         print(shell.app_alias(known_args.alias)) | ||||
|     else: | ||||
|         parser.print_usage() | ||||
|   | ||||
| @@ -1,23 +1,28 @@ | ||||
| from time import time | ||||
| import os | ||||
| from ..conf import settings | ||||
| from ..const import ARGUMENT_PLACEHOLDER | ||||
| from ..utils import memoize | ||||
| from .generic import Generic | ||||
|  | ||||
|  | ||||
| class Zsh(Generic): | ||||
|     def app_alias(self, alias_name): | ||||
|         # It is VERY important to have the variables declared WITHIN the alias | ||||
|         alias = "alias {0}='TF_CMD=$(TF_ALIAS={0}" \ | ||||
|                 " PYTHONIOENCODING=utf-8" \ | ||||
|                 " TF_SHELL_ALIASES=$(alias)" \ | ||||
|                 " thefuck $(fc -ln -1 | tail -n 1)) &&" \ | ||||
|                 " eval $TF_CMD".format(alias_name) | ||||
|  | ||||
|         if settings.alter_history: | ||||
|             return alias + " ; test -n \"$TF_CMD\" && print -s $TF_CMD'" | ||||
|         else: | ||||
|             return alias + "'" | ||||
|         # It is VERY important to have the variables declared WITHIN the function | ||||
|         return ''' | ||||
|             {name} () {{ | ||||
|                 TF_ALIAS={name}; | ||||
|                 PYTHONIOENCODING=utf-8; | ||||
|                 TF_SHELL_ALIASES=$(alias); | ||||
|                 TF_PREVIOUS=$(fc -ln -1 | tail -n 1); | ||||
|                 TF_CMD=$(thefuck $TF_PREVIOUS {argument_placeholder} $*) && eval $TF_CMD; | ||||
|                 {alter_history} | ||||
|             }} | ||||
|         '''.format( | ||||
|             name=alias_name, | ||||
|             argument_placeholder=ARGUMENT_PLACEHOLDER, | ||||
|             alter_history=('test -n "$TF_CMD" && print -s $TF_CMD' | ||||
|                            if settings.alter_history else '')) | ||||
|  | ||||
|     def _parse_alias(self, alias): | ||||
|         name, value = alias.split('=', 1) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user