1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-02-20 20:09:07 +00:00

#N/A Add ability to get shell history

This commit is contained in:
nvbn 2015-07-10 16:42:21 +03:00
parent c7071763a3
commit 4b4e7acc0f
2 changed files with 62 additions and 4 deletions

View File

@ -12,6 +12,16 @@ def isfile(mocker):
return mocker.patch('os.path.isfile', return_value=True)
@pytest.fixture
@pytest.mark.usefixtures('isfile')
def history_lines(mocker):
def aux(lines):
mock = mocker.patch('io.open')
mock.return_value.__enter__\
.return_value.__iter__.return_value = lines
return aux
class TestGeneric(object):
@pytest.fixture
def shell(self):
@ -38,6 +48,12 @@ class TestGeneric(object):
assert 'thefuck' in shell.app_alias()
assert 'TF_ALIAS' in shell.app_alias()
def test_get_history(self, history_lines, shell):
history_lines(['ls', 'rm'])
# We don't know what to do in generic shell with history lines,
# so just ignore them:
assert list(shell.get_history()) == []
@pytest.mark.usefixtures('isfile')
class TestBash(object):
@ -85,6 +101,10 @@ class TestBash(object):
assert 'thefuck' in shell.app_alias()
assert 'TF_ALIAS' in shell.app_alias()
def test_get_history(self, history_lines, shell):
history_lines(['ls', 'rm'])
assert list(shell.get_history()) == ['ls', 'rm']
@pytest.mark.usefixtures('isfile')
class TestFish(object):
@ -187,3 +207,7 @@ class TestZsh(object):
assert 'alias fuck' in shell.app_alias()
assert 'thefuck' in shell.app_alias()
assert 'TF_ALIAS' in shell.app_alias()
def test_get_history(self, history_lines, shell):
history_lines([': 1432613911:0;ls', ': 1432613916:0;rm'])
assert list(shell.get_history()) == ['ls', 'rm']

View File

@ -7,7 +7,9 @@ from collections import defaultdict
from subprocess import Popen, PIPE
from time import time
import os
import io
from psutil import Process
import six
from .utils import DEVNULL, memoize
@ -48,6 +50,26 @@ class Generic(object):
with open(history_file_name, 'a') as history:
history.write(self._get_history_line(command_script))
def _script_from_history(self, line):
"""Returns prepared history line.
Should return a blank line if history line is corrupted or empty.
"""
return ''
def get_history(self):
"""Returns list of history entries."""
history_file_name = self._get_history_file_name()
if os.path.isfile(history_file_name):
with io.open(history_file_name, 'r',
encoding='utf-8', errors='ignore') as history:
for line in history:
prepared = self._script_from_history(line)\
.strip()
if prepared:
yield prepared
def and_(self, *commands):
return u' && '.join(commands)
@ -63,7 +85,6 @@ class Bash(Generic):
value = value[1:-1]
return name, value
@memoize
def get_aliases(self):
proc = Popen('bash -ic alias', stdout=PIPE, stderr=DEVNULL,
shell=True)
@ -79,6 +100,10 @@ class Bash(Generic):
def _get_history_line(self, command_script):
return u'{}\n'.format(command_script)
def _script_from_history(self, line):
print(line)
return line
class Fish(Generic):
def app_alias(self):
@ -96,7 +121,6 @@ class Fish(Generic):
" end\n"
"end")
@memoize
def get_aliases(self):
proc = Popen('fish -ic functions', stdout=PIPE, stderr=DEVNULL,
shell=True)
@ -137,7 +161,6 @@ class Zsh(Generic):
value = value[1:-1]
return name, value
@memoize
def get_aliases(self):
proc = Popen('zsh -ic alias', stdout=PIPE, stderr=DEVNULL,
shell=True)
@ -153,6 +176,12 @@ class Zsh(Generic):
def _get_history_line(self, command_script):
return u': {}:0;{}\n'.format(int(time()), command_script)
def _script_from_history(self, line):
if ';' in line:
return line.split(';', 1)[1]
else:
return ''
class Tcsh(Generic):
def app_alias(self):
@ -162,7 +191,6 @@ class Tcsh(Generic):
name, value = alias.split("\t", 1)
return name, value
@memoize
def get_aliases(self):
proc = Popen('tcsh -ic alias', stdout=PIPE, stderr=DEVNULL,
shell=True)
@ -219,5 +247,11 @@ def and_(*commands):
return _get_shell().and_(*commands)
@memoize
def get_aliases():
return list(_get_shell().get_aliases().keys())
@memoize
def get_history():
return list(_get_shell().get_history())