From 708f33e83c9cf8a128f0765d49cc38ee6ca0066d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 19 Apr 2020 18:27:49 +0200 Subject: buffers/search: with walker.py It is only ever called from here, separating them makes little sense. --- alot/buffers/search.py | 90 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 9 deletions(-) (limited to 'alot/buffers') 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) -- cgit v1.2.3