Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New command 'append': Append results of another (notmuch) query to search buffer #1542

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 27 additions & 16 deletions alot/buffers/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ class SearchBuffer(Buffer):
def __init__(self, ui, initialquery='', sort_order=None):
self.dbman = ui.dbman
self.ui = ui
self.querystring = initialquery
# We store a list of notmuch query strings and this buffer will
# display the results for each query one after the other
self.querystrings = [initialquery]
default_order = settings.get('search_threads_sort_order')
self.sort_order = sort_order or default_order
self.result_count = 0
Expand All @@ -36,12 +38,13 @@ def __init__(self, ui, initialquery='', sort_order=None):

def __str__(self):
formatstring = '[search] for "%s" (%d message%s)'
return formatstring % (self.querystring, self.result_count,
return formatstring % ('" + "'.join(self.querystrings),
self.result_count,
's' if self.result_count > 1 else '')

def get_info(self):
info = {}
info['querystring'] = self.querystring
info['querystring'] = '" + "'.join(self.querystrings)
info['result_count'] = self.result_count
info['result_count_positive'] = 's' if self.result_count > 1 else ''
return info
Expand All @@ -59,19 +62,27 @@ def rebuild(self, reverse=False, restore_focus=True):
if restore_focus and self.threadlist:
selected_thread = self.get_selected_thread()

try:
self.result_count = self.dbman.count_messages(self.querystring)
threads = self.dbman.get_threads(self.querystring, order)
except NotmuchError:
self.ui.notify('malformed query string: %s' % self.querystring,
'error')
self.listbox = urwid.ListBox([])
self.body = self.listbox
return

self.threadlist = IterableWalker(threads, ThreadlineWidget,
dbman=self.dbman,
reverse=reverse)
self.result_count = 0
self.threadlist = None
for query in self.querystrings:
try:
self.result_count += self.dbman.count_messages(query)
threads = self.dbman.get_threads(
query, order)
except NotmuchError:
self.ui.notify('malformed query string: %s' % query,
'error')
self.listbox = urwid.ListBox([])
self.body = self.listbox
return

iterablewalker = IterableWalker(threads, ThreadlineWidget,
dbman=self.dbman,
reverse=reverse)
if self.threadlist:
self.threadlist.append(iterablewalker)
else:
self.threadlist = iterablewalker

self.listbox = urwid.ListBox(self.threadlist)
self.body = self.listbox
Expand Down
2 changes: 1 addition & 1 deletion alot/commands/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def apply(self, ui):
open_searches = ui.get_buffers_of_type(buffers.SearchBuffer)
to_be_focused = None
for sb in open_searches:
if sb.querystring == self.query:
if sb.querystrings == [self.query]:
to_be_focused = sb
if to_be_focused:
if ui.current_buffer != to_be_focused:
Expand Down
50 changes: 42 additions & 8 deletions alot/commands/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,13 @@ def apply(self, ui):
if not self.thread:
self.thread = ui.current_buffer.get_selected_thread()
if self.thread:
query = ui.current_buffer.querystring
query_list = ui.current_buffer.querystrings
logging.info('open thread view for %s', self.thread)

tb = buffers.ThreadBuffer(ui, self.thread)
ui.buffer_open(tb)
tb.unfold_matching(query)
for query in query_list:
tb.unfold_matching(query)


@registerCommand(MODE, 'refine', help='refine query', arguments=[
Expand Down Expand Up @@ -70,9 +71,9 @@ def __init__(self, query=None, sort=None, **kwargs):
def apply(self, ui):
if self.querystring or self.sort_order:
sbuffer = ui.current_buffer
oldquery = sbuffer.querystring
oldquery = sbuffer.querystrings[-1]
if self.querystring not in [None, oldquery]:
sbuffer.querystring = self.querystring
sbuffer.querystrings[-1] = self.querystring
sbuffer = ui.current_buffer
if self.sort_order:
sbuffer.sort_order = self.sort_order
Expand All @@ -90,13 +91,46 @@ class RefinePromptCommand(Command):

async def apply(self, ui):
sbuffer = ui.current_buffer
oldquery = sbuffer.querystring
oldquery = sbuffer.querystrings[-1]
return await ui.apply_command(PromptCommand('refine ' + oldquery))


RetagPromptCommand = registerCommand(MODE, 'retagprompt')(RetagPromptCommand)


@registerCommand(MODE, 'append', usage='append query', arguments=[
(['--sort'], {'help': 'sort order', 'choices': [
'oldest_first', 'newest_first', 'message_id', 'unsorted']}),
(['query'], {'nargs': argparse.REMAINDER, 'help': 'search string'})])
class AppendCommand(Command):

"""append the results of a new query to this buffer. Search obeys the notmuch
:ref:`search.exclude_tags <search.exclude_tags>` setting."""
repeatable = True

def __init__(self, query, sort=None, **kwargs):
"""
:param query: notmuch querystring
:type query: str
:param sort: how to order results. Must be one of
'oldest_first', 'newest_first', 'message_id' or
'unsorted'.
:type sort: str
"""
self.query = ' '.join(query)
self.order = sort
Command.__init__(self, **kwargs)

def apply(self, ui):
if self.query:
sbuffer = ui.current_buffer
sbuffer.querystrings.append(self.query)
sbuffer.rebuild()
ui.update()
else:
ui.notify('empty query string')


@registerCommand(
MODE, 'tag', forced={'action': 'add'},
arguments=[
Expand Down Expand Up @@ -176,7 +210,7 @@ async def apply(self, ui):
if threadline_widget is None:
return

testquery = searchbuffer.querystring
testquery = searchbuffer.querystrings[-1]
thread = threadline_widget.get_thread()
if not self.allm:
testquery = "(%s) AND thread:%s" % (testquery,
Expand All @@ -198,7 +232,7 @@ def refresh():
else:
threadline_widget.rebuild()
searchbuffer.result_count = searchbuffer.dbman.count_messages(
searchbuffer.querystring)
searchbuffer.querystrings[-1])
else:
searchbuffer.rebuild()

Expand Down Expand Up @@ -257,5 +291,5 @@ class SaveQueryCommand(GlobalSaveQueryCommand):
def apply(self, ui):
searchbuffer = ui.current_buffer
if not self.query:
self.query = searchbuffer.querystring
self.query = searchbuffer.querystrings[-1]
GlobalSaveQueryCommand.apply(self, ui)
4 changes: 4 additions & 0 deletions alot/walker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Copyright © 2018 Dylan Baker
# This file is released under the GNU GPL, version 3 or a later revision.
# For further details see the COPYING file
import itertools
import logging
import urwid

Expand Down Expand Up @@ -92,3 +93,6 @@ def _get_next_item(self):

def get_lines(self):
return self.lines

def append(self, iterableWalker):
self.iterable = itertools.chain(self.iterable, iterableWalker.iterable)