Fix for reverse and forward incremental search

This commit is contained in:
Jorgen Stenarson
2011-04-14 18:52:22 +02:00
parent 75dcc77771
commit 1d71dec2a0
4 changed files with 107 additions and 51 deletions
+48 -24
View File
@@ -22,7 +22,6 @@ class EscapeHistory(exceptions.Exception):
from pyreadline.logger import log
_ignore_leading_spaces = False
class LineHistory(object):
def __init__(self):
@@ -32,6 +31,7 @@ class LineHistory(object):
self.history_filename = os.path.expanduser('~/.history') #Cannot expand unicode strings correctly on python2.4
self.lastcommand = None
self.query = u""
self.last_search_for = u""
def get_current_history_length(self):
u'''Return the number of lines currently in the history.
@@ -140,34 +140,58 @@ class LineHistory(object):
def reverse_search_history(self, searchfor, startpos=None):
if startpos is None:
startpos = self.history_cursor
if _ignore_leading_spaces:
res = [(idx, line.lstrip())
for idx, line in enumerate(self.history[startpos:0:-1])
if line.lstrip().startswith(searchfor.lstrip())]
else:
res = [(idx, line)
for idx, line in enumerate(self.history[startpos:0:-1])
if line.startswith(searchfor)]
if res:
self.history_cursor -= res[0][0]
return res[0][1].get_line_text()
return u""
result = lineobj.ReadLineTextBuffer("")
for idx, line in list(enumerate(self.history))[startpos:0:-1]:
if searchfor in line:
startpos = idx
break
#If we get a new search without change in search term it means
#someone pushed ctrl-r and we should find the next match
if self.last_search_for == searchfor:
startpos -= 1
for idx, line in list(enumerate(self.history))[startpos:0:-1]:
if searchfor in line:
startpos = idx
break
result = self.history[startpos]
self.history_cursor = startpos
self.last_search_for = searchfor
return result.get_line_text()
def forward_search_history(self, searchfor, startpos=None):
if startpos is None:
startpos = self.history_cursor
if _ignore_leading_spaces:
res = [(idx, line.lstrip())
for idx, line in enumerate(self.history[startpos:])
if line.lstrip().startswith(searchfor.lstrip())]
origpos = startpos
result = lineobj.ReadLineTextBuffer("")
for idx, line in list(enumerate(self.history))[startpos:]:
if searchfor in line:
startpos = idx
break
#If we get a new search without change in search term it means
#someone pushed ctrl-r and we should find the next match
if self.last_search_for == searchfor:
startpos += 1
for idx, line in list(enumerate(self.history))[startpos:]:
if searchfor in line:
startpos = idx
break
if len(self.history) == startpos:
if origpos == len(self.history):
return u""
else:
return self.history[origpos]
else:
res = [(idx, line)
for idx, line in enumerate(self.history[startpos:])
if line.startswith(searchfor)]
if res:
self.history_cursor += res[0][0]
return res[0][1].get_line_text()
return u""
result = self.history[startpos]
self.history_cursor = startpos
self.last_search_for = searchfor
return result.get_line_text()
def _search(self, direction, partial):
try:
+1 -1
View File
@@ -133,7 +133,7 @@ class BaseMode(object):
u"""Every bindable command should call this function for cleanup.
Except those that want to set argument to a non-zero value.
"""
self.argument=0
self.argument = 0
def add_history(self, text):
+2 -2
View File
@@ -75,8 +75,8 @@ class IncrementalSearchPromptMode(object):
self.subsearch_oldprompt = self.prompt
if (self.previous_func != self.history_search_forward and
self.previous_func != self.history_search_backward):
if (self.previous_func != self.reverse_search_history and
self.previous_func != self.forward_search_history):
self.subsearch_query = self.l_buffer[0:Point].get_line_text()
if self.subsearch_direction < 0:
+56 -24
View File
@@ -18,37 +18,34 @@ from pyreadline.logger import log
#----------------------------------------------------------------------
RL=lineobj.ReadLineTextBuffer
class Test_linepos (unittest.TestCase):
t=u"test text"
class Test_prev_next_history(unittest.TestCase):
t = u"test text"
def init_test(self):
history._ignore_leading_spaces=False
self.q=q=LineHistory()
for x in [u"aaaa",u"aaba",u"aaca",u"akca",u"bbb",u"ako"]:
def setUp(self):
self.q = q = LineHistory()
for x in [u"aaaa", u"aaba", u"aaca", u"akca", u"bbb", u"ako"]:
q.add_history(RL(x))
def test_previous_history (self):
self.init_test()
hist=self.q
assert hist.history_cursor==6
l=RL(u"")
hist = self.q
assert hist.history_cursor == 6
l = RL(u"")
hist.previous_history(l)
assert l.get_line_text()==u"ako"
assert l.get_line_text() == u"ako"
hist.previous_history(l)
assert l.get_line_text()==u"bbb"
assert l.get_line_text() == u"bbb"
hist.previous_history(l)
assert l.get_line_text()==u"akca"
assert l.get_line_text() == u"akca"
hist.previous_history(l)
assert l.get_line_text()==u"aaca"
assert l.get_line_text() == u"aaca"
hist.previous_history(l)
assert l.get_line_text()==u"aaba"
assert l.get_line_text() == u"aaba"
hist.previous_history(l)
assert l.get_line_text()==u"aaaa"
assert l.get_line_text() == u"aaaa"
hist.previous_history(l)
assert l.get_line_text()==u"aaaa"
assert l.get_line_text() == u"aaaa"
def test_next_history (self):
self.init_test()
hist=self.q
hist.beginning_of_history()
assert hist.history_cursor==0
@@ -66,14 +63,16 @@ class Test_linepos (unittest.TestCase):
hist.next_history(l)
assert l.get_line_text()==u"ako"
def init_test2(self):
self.q=q=LineHistory()
class Test_prev_next_history(unittest.TestCase):
t = u"test text"
def setUp(self):
self.q = q = LineHistory()
for x in [u"aaaa",u"aaba",u"aaca",u"akca",u"bbb",u"ako"]:
q.add_history(RL(x))
def test_history_search_backward (self):
history._ignore_leading_spaces=False
q=LineHistory()
q = LineHistory()
for x in [u"aaaa",u"aaba",u"aaca",u" aacax",u"akca",u"bbb",u"ako"]:
q.add_history(RL(x))
a=RL(u"aa",point=2)
@@ -82,8 +81,7 @@ class Test_linepos (unittest.TestCase):
assert res.get_line_text()==x
def test_history_search_forward (self):
history._ignore_leading_spaces=False
q=LineHistory()
q = LineHistory()
for x in [u"aaaa",u"aaba",u"aaca",u" aacax",u"akca",u"bbb",u"ako"]:
q.add_history(RL(x))
q.beginning_of_history()
@@ -92,6 +90,40 @@ class Test_linepos (unittest.TestCase):
res=q.history_search_forward(a)
assert res.get_line_text()==x
class Test_history_search_incr_fwd_backwd(unittest.TestCase):
def setUp(self):
self.q = q = LineHistory()
for x in [u"aaaa",u"aaba",u"aaca",u"akca",u"bbb",u"ako"]:
q.add_history(RL(x))
def test_backward_1(self):
q = self.q
self.assertEqual(q.reverse_search_history(u"b"), u"bbb")
self.assertEqual(q.reverse_search_history(u"b"), u"aaba")
self.assertEqual(q.reverse_search_history(u"bb"), u"aaba")
def test_backward_2(self):
q = self.q
self.assertEqual(q.reverse_search_history(u"a"), u"ako")
self.assertEqual(q.reverse_search_history(u"aa"), u"aaca")
self.assertEqual(q.reverse_search_history(u"a"), u"aaca")
self.assertEqual(q.reverse_search_history(u"ab"), u"aaba")
def test_forward_1(self):
q = self.q
self.assertEqual(q.forward_search_history(u"a"), u"")
def test_forward_2(self):
q = self.q
q.history_cursor = 0
self.assertEqual(q.forward_search_history(u"a"), u"aaaa")
self.assertEqual(q.forward_search_history(u"a"), u"aaba")
self.assertEqual(q.forward_search_history(u"ak"), u"akca")
self.assertEqual(q.forward_search_history(u"akl"), u"akca")
self.assertEqual(q.forward_search_history(u"ak"), u"akca")
self.assertEqual(q.forward_search_history(u"ako"), u"ako")
#----------------------------------------------------------------------
# utility functions