1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-01-18 12:06:04 +00:00

#682: Use our own shell logger, fix experimental instant mode on macos

This commit is contained in:
Vladimir Iakovlev 2017-10-08 16:17:41 +02:00
parent edac010a7b
commit d2c70bd8b8
6 changed files with 85 additions and 4 deletions

View File

@ -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

View File

@ -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',

View File

@ -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()

View 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)

View File

@ -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)

View File

@ -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)