mirror of
				https://github.com/nvbn/thefuck.git
				synced 2025-11-04 09:02:08 +00:00 
			
		
		
		
	#682: Use our own shell logger, fix experimental instant mode on macos
This commit is contained in:
		@@ -7,7 +7,8 @@ def _args(**override):
 | 
			
		||||
    args = {'alias': None, 'command': [], 'yes': False,
 | 
			
		||||
            'help': False, 'version': False, 'debug': False,
 | 
			
		||||
            'force_command': None, 'repeat': False,
 | 
			
		||||
            'enable_experimental_instant_mode': False}
 | 
			
		||||
            'enable_experimental_instant_mode': False,
 | 
			
		||||
            'shell_logger': None}
 | 
			
		||||
    args.update(override)
 | 
			
		||||
    return args
 | 
			
		||||
 | 
			
		||||
@@ -27,6 +28,9 @@ def _args(**override):
 | 
			
		||||
    (['thefuck', 'git', 'branch', '-a', ARGUMENT_PLACEHOLDER, '-y', '-d'],
 | 
			
		||||
     _args(command=['git', 'branch', '-a'], yes=True, debug=True)),
 | 
			
		||||
    (['thefuck', 'git', 'branch', '-a', ARGUMENT_PLACEHOLDER, '-r', '-d'],
 | 
			
		||||
     _args(command=['git', 'branch', '-a'], repeat=True, debug=True))])
 | 
			
		||||
     _args(command=['git', 'branch', '-a'], repeat=True, debug=True)),
 | 
			
		||||
    (['thefuck', '-l', '/tmp/log'], _args(shell_logger='/tmp/log')),
 | 
			
		||||
    (['thefuck', '--shell-logger', '/tmp/log'],
 | 
			
		||||
     _args(shell_logger='/tmp/log'))])
 | 
			
		||||
def test_parse(argv, result):
 | 
			
		||||
    assert vars(Parser().parse(argv)) == result
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,10 @@ class Parser(object):
 | 
			
		||||
            nargs='?',
 | 
			
		||||
            const=get_alias(),
 | 
			
		||||
            help='[custom-alias-name] prints alias for current shell')
 | 
			
		||||
        self._parser.add_argument(
 | 
			
		||||
            '-l', '--shell-logger',
 | 
			
		||||
            action='store',
 | 
			
		||||
            help='log shell output to the file')
 | 
			
		||||
        self._parser.add_argument(
 | 
			
		||||
            '--enable-experimental-instant-mode',
 | 
			
		||||
            action='store_true',
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ from ..argument_parser import Parser  # noqa: E402
 | 
			
		||||
from ..utils import get_installation_info  # noqa: E402
 | 
			
		||||
from .alias import print_alias  # noqa: E402
 | 
			
		||||
from .fix_command import fix_command  # noqa: E402
 | 
			
		||||
from .shell_logger import shell_logger  # noqa: E402
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
@@ -25,5 +26,7 @@ def main():
 | 
			
		||||
        fix_command(known_args)
 | 
			
		||||
    elif known_args.alias:
 | 
			
		||||
        print_alias(known_args)
 | 
			
		||||
    elif known_args.shell_logger:
 | 
			
		||||
        shell_logger(known_args.shell_logger)
 | 
			
		||||
    else:
 | 
			
		||||
        parser.print_usage()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										70
									
								
								thefuck/entrypoints/shell_logger.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								thefuck/entrypoints/shell_logger.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
import array
 | 
			
		||||
import fcntl
 | 
			
		||||
from functools import partial
 | 
			
		||||
import os
 | 
			
		||||
import pty
 | 
			
		||||
import signal
 | 
			
		||||
import sys
 | 
			
		||||
import termios
 | 
			
		||||
import tty
 | 
			
		||||
from ..logs import warn
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _read(f, fd):
 | 
			
		||||
    data = os.read(fd, 1024)
 | 
			
		||||
    f.write(data)
 | 
			
		||||
    f.flush()
 | 
			
		||||
    return data
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _set_pty_size(master_fd):
 | 
			
		||||
    buf = array.array('h', [0, 0, 0, 0])
 | 
			
		||||
    fcntl.ioctl(pty.STDOUT_FILENO, termios.TIOCGWINSZ, buf, True)
 | 
			
		||||
    fcntl.ioctl(master_fd, termios.TIOCSWINSZ, buf)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _spawn(shell, master_read):
 | 
			
		||||
    """Create a spawned process.
 | 
			
		||||
 | 
			
		||||
    Modified version of pty.spawn with terminal size support.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    pid, master_fd = pty.fork()
 | 
			
		||||
 | 
			
		||||
    if pid == pty.CHILD:
 | 
			
		||||
        os.execlp(shell, shell)
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        mode = tty.tcgetattr(pty.STDIN_FILENO)
 | 
			
		||||
        tty.setraw(pty.STDIN_FILENO)
 | 
			
		||||
        restore = True
 | 
			
		||||
    except tty.error:    # This is the same as termios.error
 | 
			
		||||
        restore = False
 | 
			
		||||
 | 
			
		||||
    _set_pty_size(master_fd)
 | 
			
		||||
    signal.signal(signal.SIGWINCH, lambda *_: _set_pty_size(master_fd))
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        pty._copy(master_fd, master_read, pty._read)
 | 
			
		||||
    except OSError:
 | 
			
		||||
        if restore:
 | 
			
		||||
            tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode)
 | 
			
		||||
 | 
			
		||||
    os.close(master_fd)
 | 
			
		||||
    return os.waitpid(pid, 0)[1]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def shell_logger(output):
 | 
			
		||||
    """Logs shell output to the `output`.
 | 
			
		||||
 | 
			
		||||
    Works like unix script command with `-f` flag.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    if not os.environ.get('SHELL'):
 | 
			
		||||
        warn("Shell logger doesn't support your platform.")
 | 
			
		||||
        sys.exit(1)
 | 
			
		||||
 | 
			
		||||
    with open(output, 'wb') as f:
 | 
			
		||||
        return_code = _spawn(os.environ['SHELL'], partial(_read, f))
 | 
			
		||||
 | 
			
		||||
    sys.exit(return_code)
 | 
			
		||||
@@ -44,7 +44,7 @@ class Bash(Generic):
 | 
			
		||||
            return '''
 | 
			
		||||
                export THEFUCK_INSTANT_MODE=True;
 | 
			
		||||
                export THEFUCK_OUTPUT_LOG={log};
 | 
			
		||||
                script -feq {log};
 | 
			
		||||
                thefuck --shell-logger {log};
 | 
			
		||||
                rm {log};
 | 
			
		||||
                exit
 | 
			
		||||
            '''.format(log=log_path)
 | 
			
		||||
 
 | 
			
		||||
@@ -42,7 +42,7 @@ class Zsh(Generic):
 | 
			
		||||
            return '''
 | 
			
		||||
                export THEFUCK_INSTANT_MODE=True;
 | 
			
		||||
                export THEFUCK_OUTPUT_LOG={log};
 | 
			
		||||
                script -feq {log};
 | 
			
		||||
                thefuck --shell-logger {log};
 | 
			
		||||
                rm {log};
 | 
			
		||||
                exit
 | 
			
		||||
            '''.format(log=log_path)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user