From 503ab8de493481355e8e8b0dc1fbe9fa049353bb Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 29 Nov 2021 16:38:37 +0100 Subject: buffers/search: allow displaying results in reverse Not hooked up to any commands, so not actually usable yet. Note that oldest_first and newest_first sort orders are not inverses of each other, because oldest_first uses the oldest message in the thread for sorting, while newest_first uses the newest one. This option applies on top of that sorting to display results from the end to the beginning. This requires reading the whole result list first, so can be slow for queries with many results. --- alot/buffers/search.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/alot/buffers/search.py b/alot/buffers/search.py index 3adce6ed..45d20b30 100644 --- a/alot/buffers/search.py +++ b/alot/buffers/search.py @@ -21,6 +21,7 @@ class IterWalker(urwid.ListWalker): _threads = None _wgt_factory = None + _reverse = None _iter_done = False @@ -31,9 +32,10 @@ class IterWalker(urwid.ListWalker): _focus = None - def __init__(self, threads, wgt_factory): + def __init__(self, threads, wgt_factory, reverse): self._threads = threads self._wgt_factory = wgt_factory + self._reverse = reverse self._tids = [] self._wgts = {} @@ -47,26 +49,33 @@ class IterWalker(urwid.ListWalker): self._get_next_item() return len(self._tids) + def _map_pos(self, pos): + if self._reverse: + pos = len(self) - 1 - pos + return pos + def __getitem__(self, pos): self._check_pos(pos) if not pos in self._wgts: # make sure an exception while constructing the widget does not get # swallowed by urwid try: - self._wgts[pos] = self._wgt_factory(self._tids[pos]) + self._wgts[pos] = self._wgt_factory(self._tids[self._map_pos(pos)]) except (KeyError, IndexError, TypeError) as e: raise ValueError('Exception while constructing threadline widget') from e return self._wgts[pos] def _check_pos(self, pos): - if pos < 0: + tgt_pos = self._map_pos(pos) + + if tgt_pos < 0: raise IndexError - while not self._iter_done and pos >= len(self._tids): + while not self._iter_done and tgt_pos >= len(self._tids): self._get_next_item() - if pos >= len(self._tids): + if tgt_pos >= len(self._tids): raise IndexError return pos @@ -98,15 +107,19 @@ class SearchBuffer(Buffer): modename = 'search' + sort_order = None + reverse = None + _message_count = None _thread_count = None - def __init__(self, ui, initialquery='', sort_order=None): + def __init__(self, ui, initialquery='', sort_order=None, reverse = False): self.dbman = ui.dbman self.ui = ui self.querystring = initialquery default_order = SORT_NAME[settings.get('search_threads_sort_order')] self.sort_order = sort_order or default_order + self.reverse = reverse self.rebuild() super().__init__() @@ -169,7 +182,7 @@ class SearchBuffer(Buffer): exclude_tags) wgt_factory = partial(ThreadlineWidget, dbman = self.dbman, query = self.querystring) - threadlist = IterWalker(threads, wgt_factory) + threadlist = IterWalker(threads, wgt_factory, self.reverse) # check that the query is well-formed try: -- cgit v1.2.3