summaryrefslogtreecommitdiff
path: root/alot/buffers
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2020-04-19 18:27:49 +0200
committerAnton Khirnov <anton@khirnov.net>2020-04-19 18:27:49 +0200
commit708f33e83c9cf8a128f0765d49cc38ee6ca0066d (patch)
tree37c04f318187d59e0b336e4a1ac597a850a59448 /alot/buffers
parentab5af955801972f313f6b7fb541d790b7a1a22bb (diff)
buffers/search: with walker.py
It is only ever called from here, separating them makes little sense.
Diffstat (limited to 'alot/buffers')
-rw-r--r--alot/buffers/search.py90
1 files changed, 81 insertions, 9 deletions
diff --git a/alot/buffers/search.py b/alot/buffers/search.py
index b078b109..17023c16 100644
--- a/alot/buffers/search.py
+++ b/alot/buffers/search.py
@@ -2,13 +2,92 @@
# This file is released under the GNU GPL, version 3 or a later revision.
# For further details see the COPYING file
import urwid
+import logging
from notmuch import NotmuchError
from .buffer import Buffer
from ..settings.const import settings
-from ..walker import PipeWalker
from ..widgets.search import ThreadlineWidget
+class PipeWalker(urwid.ListWalker):
+ """urwid.ListWalker that reads next items from a pipe and wraps them in
+ `containerclass` widgets for displaying
+
+ Attributes that should be considered publicly readable:
+ :attr lines: the lines obtained from the pipe
+ :type lines: list(`containerclass`)
+ """
+ def __init__(self, pipe, containerclass, reverse=False, **kwargs):
+ self.pipe = pipe
+ self.kwargs = kwargs
+ self.containerclass = containerclass
+ self.lines = []
+ self.focus = 0
+ self.empty = False
+ self.direction = -1 if reverse else 1
+
+ def __len__(self):
+ while not self.empty:
+ self._get_next_item()
+ return len(self.lines)
+
+ def get_focus(self):
+ return self._get_at_pos(self.focus)
+
+ def set_focus(self, focus):
+ self.focus = focus
+ self._modified()
+
+ def get_next(self, start_from):
+ return self._get_at_pos(start_from + self.direction)
+
+ def get_prev(self, start_from):
+ return self._get_at_pos(start_from - self.direction)
+
+ def remove(self, obj):
+ next_focus = self.focus % len(self.lines)
+ if self.focus == len(self.lines) - 1 and self.empty:
+ next_focus = self.focus - 1
+
+ self.lines.remove(obj)
+ if self.lines:
+ self.set_focus(next_focus)
+ self._modified()
+
+ def _get_at_pos(self, pos):
+ if pos < 0: # pos too low
+ return (None, None)
+ elif pos > len(self.lines): # pos too high
+ return (None, None)
+ elif len(self.lines) > pos: # pos already cached
+ return (self.lines[pos], pos)
+ else: # pos not cached yet, look at next item from iterator
+ if self.empty: # iterator is empty
+ return (None, None)
+ else:
+ widget = self._get_next_item()
+ if widget:
+ return (widget, pos)
+ else:
+ return (None, None)
+
+ def _get_next_item(self):
+ if self.empty:
+ return None
+ try:
+ # the next line blocks until it can read from the pipe or
+ # EOFError is raised. No races here.
+ next_obj = self.pipe.recv()
+ next_widget = self.containerclass(next_obj, **self.kwargs)
+ self.lines.append(next_widget)
+ except EOFError:
+ logging.debug('EMPTY PIPE')
+ next_widget = None
+ self.empty = True
+ return next_widget
+
+ def get_lines(self):
+ return self.lines
class SearchBuffer(Buffer):
"""shows a result list of threads for a query"""
@@ -98,14 +177,7 @@ class SearchBuffer(Buffer):
thread = threadlinewidget.get_thread()
return thread
- def consume_pipe(self):
- while not self.threadlist.empty:
- self.threadlist._get_next_item()
-
def focus_first(self):
self.body.set_focus(0)
-
def focus_last(self):
- self.consume_pipe()
- num_lines = len(self.threadlist.get_lines())
- self.body.set_focus(num_lines - 1)
+ self.body.set_focus(len(self.threadlist) - 1)