2015-03-29 01:32:36 +00:00
|
|
|
import urwid
|
|
|
|
|
|
|
|
from . import signals
|
|
|
|
|
|
|
|
|
|
|
|
class Highlight(urwid.AttrMap):
|
|
|
|
def __init__(self, t):
|
|
|
|
urwid.AttrMap.__init__(
|
|
|
|
self,
|
|
|
|
urwid.Text(t.text),
|
|
|
|
"focusfield",
|
|
|
|
)
|
|
|
|
self.backup = t
|
|
|
|
|
|
|
|
|
|
|
|
class Searchable(urwid.ListBox):
|
2015-03-29 02:14:56 +00:00
|
|
|
def __init__(self, state, contents):
|
2015-03-29 01:32:36 +00:00
|
|
|
urwid.ListBox.__init__(
|
|
|
|
self,
|
|
|
|
urwid.SimpleFocusListWalker(contents)
|
|
|
|
)
|
2015-03-29 02:14:56 +00:00
|
|
|
self.state = state
|
2015-03-29 01:32:36 +00:00
|
|
|
self.search_offset = 0
|
|
|
|
self.current_highlight = None
|
|
|
|
self.search_term = None
|
|
|
|
|
|
|
|
def keypress(self, size, key):
|
|
|
|
if key == "/":
|
|
|
|
signals.status_prompt.send(
|
|
|
|
prompt = "Search for",
|
2015-03-29 02:16:20 +00:00
|
|
|
text = "",
|
2015-03-29 01:32:36 +00:00
|
|
|
callback = self.set_search
|
|
|
|
)
|
|
|
|
if key == "n":
|
|
|
|
self.find_next(False)
|
|
|
|
if key == "N":
|
|
|
|
self.find_next(True)
|
|
|
|
else:
|
2015-03-31 20:25:50 +00:00
|
|
|
return super(self.__class__, self).keypress(size, key)
|
2015-03-29 01:32:36 +00:00
|
|
|
|
|
|
|
def set_search(self, text):
|
2015-03-29 02:14:56 +00:00
|
|
|
self.state.last_search = text
|
2015-03-29 01:32:36 +00:00
|
|
|
self.search_term = text or None
|
|
|
|
self.find_next(False)
|
|
|
|
|
|
|
|
def set_highlight(self, offset):
|
|
|
|
if self.current_highlight is not None:
|
|
|
|
old = self.body[self.current_highlight]
|
|
|
|
self.body[self.current_highlight] = old.backup
|
|
|
|
if offset is None:
|
|
|
|
self.current_highlight = None
|
|
|
|
else:
|
|
|
|
self.body[offset] = Highlight(self.body[offset])
|
|
|
|
self.current_highlight = offset
|
|
|
|
|
|
|
|
def get_text(self, w):
|
|
|
|
if isinstance(w, urwid.Text):
|
|
|
|
return w.text
|
|
|
|
elif isinstance(w, Highlight):
|
|
|
|
return w.backup.text
|
|
|
|
else:
|
|
|
|
return None
|
|
|
|
|
|
|
|
def find_next(self, backwards):
|
|
|
|
if not self.search_term:
|
2015-03-29 02:14:56 +00:00
|
|
|
if self.state.last_search:
|
|
|
|
self.search_term = self.state.last_search
|
|
|
|
else:
|
|
|
|
self.set_highlight(None)
|
|
|
|
return
|
2015-03-29 01:32:36 +00:00
|
|
|
# Start search at focus + 1
|
|
|
|
if backwards:
|
|
|
|
rng = xrange(len(self.body)-1, -1, -1)
|
|
|
|
else:
|
2015-03-29 01:39:47 +00:00
|
|
|
rng = xrange(1, len(self.body) + 1)
|
2015-03-29 01:32:36 +00:00
|
|
|
for i in rng:
|
|
|
|
off = (self.focus_position + i)%len(self.body)
|
|
|
|
w = self.body[off]
|
|
|
|
txt = self.get_text(w)
|
|
|
|
if txt and self.search_term in txt:
|
|
|
|
self.set_highlight(off)
|
|
|
|
self.set_focus(off, coming_from="above")
|
|
|
|
self.body._modified()
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
self.set_highlight(None)
|
|
|
|
signals.status_message.send(message="Search not found.", expire=1)
|