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

#N/A: Use mmap for sharing output in instant mode

This commit is contained in:
Vladimir Iakovlev 2018-03-14 00:12:40 +01:00
parent 284d49da8d
commit 1508ecfeae
3 changed files with 26 additions and 20 deletions

View File

@ -76,8 +76,8 @@ CONFIGURATION_TIMEOUT = 60
USER_COMMAND_MARK = u'\u200B' * 10 USER_COMMAND_MARK = u'\u200B' * 10
LOG_SIZE = 1000
LOG_SIZE_IN_BYTES = 1024 * 1024 LOG_SIZE_IN_BYTES = 1024 * 1024
LOG_SIZE_TO_CLEAN = 10 * 1024
DIFF_WITH_ALIAS = 0.5 DIFF_WITH_ALIAS = 0.5

View File

@ -1,19 +1,24 @@
import array import array
import fcntl import fcntl
from functools import partial from functools import partial
import mmap
import os import os
import pty import pty
import signal import signal
import sys import sys
import termios import termios
import tty import tty
from ..logs import warn from .. import logs, const
def _read(f, fd): def _read(f, fd):
data = os.read(fd, 1024) data = os.read(fd, 1024)
f.write(data) try:
f.flush() f.write(data)
except ValueError:
f.move(0, const.LOG_SIZE_TO_CLEAN,
const.LOG_SIZE_IN_BYTES - const.LOG_SIZE_TO_CLEAN)
f.seek(const.LOG_SIZE_IN_BYTES - const.LOG_SIZE_TO_CLEAN)
return data return data
@ -61,10 +66,12 @@ def shell_logger(output):
""" """
if not os.environ.get('SHELL'): if not os.environ.get('SHELL'):
warn("Shell logger doesn't support your platform.") logs.warn("Shell logger doesn't support your platform.")
sys.exit(1) sys.exit(1)
with open(output, 'wb') as f: fd = os.open(output, os.O_CREAT | os.O_TRUNC | os.O_RDWR)
return_code = _spawn(os.environ['SHELL'], partial(_read, f)) os.write(fd, b'\x00' * const.LOG_SIZE_IN_BYTES)
buffer = mmap.mmap(fd, const.LOG_SIZE_IN_BYTES, mmap.MAP_SHARED, mmap.PROT_WRITE)
return_code = _spawn(os.environ['SHELL'], partial(_read, buffer))
sys.exit(return_code) sys.exit(return_code)

View File

@ -1,5 +1,7 @@
import os import os
import shlex import shlex
import mmap
import re
try: try:
from shutil import get_terminal_size from shutil import get_terminal_size
except ImportError: except ImportError:
@ -18,11 +20,6 @@ def _group_by_calls(log):
script_line = None script_line = None
lines = [] lines = []
for line in log: for line in log:
try:
line = line.decode()
except UnicodeDecodeError:
continue
if const.USER_COMMAND_MARK in line or ps1_counter > 0: if const.USER_COMMAND_MARK in line or ps1_counter > 0:
if script_line and ps1_counter == 0: if script_line and ps1_counter == 0:
yield script_line, lines yield script_line, lines
@ -53,13 +50,14 @@ def _get_script_group_lines(grouped, script):
def _get_output_lines(script, log_file): def _get_output_lines(script, log_file):
lines = log_file.readlines()[-const.LOG_SIZE:] data = log_file.read().decode()
data = re.sub(r'\x00+$', '', data)
lines = data.split('\n')
grouped = list(_group_by_calls(lines)) grouped = list(_group_by_calls(lines))
script_lines = _get_script_group_lines(grouped, script) script_lines = _get_script_group_lines(grouped, script)
screen = pyte.Screen(get_terminal_size().columns, len(script_lines)) screen = pyte.Screen(get_terminal_size().columns, len(script_lines))
stream = pyte.Stream(screen) stream = pyte.Stream(screen)
stream.feed(''.join(script_lines)) stream.feed('\n'.join(script_lines))
return screen.display return screen.display
@ -91,10 +89,11 @@ def get_output(script):
return None return None
try: try:
with logs.debug_time(u'Read output from log'), \ with logs.debug_time(u'Read output from log'):
open(os.environ['THEFUCK_OUTPUT_LOG'], 'rb') as log_file: fd = os.open(os.environ['THEFUCK_OUTPUT_LOG'], os.O_RDONLY)
_skip_old_lines(log_file) buffer = mmap.mmap(fd, const.LOG_SIZE_IN_BYTES, mmap.MAP_SHARED, mmap.PROT_READ)
lines = _get_output_lines(script, log_file) _skip_old_lines(buffer)
lines = _get_output_lines(script, buffer)
output = '\n'.join(lines).strip() output = '\n'.join(lines).strip()
logs.debug(u'Received output: {}'.format(output)) logs.debug(u'Received output: {}'.format(output))
return output return output