From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0 ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms0.migadu.com with LMTPS id ZQCVHLYC1mCg9AAAgWs5BA (envelope-from ) for ; Fri, 25 Jun 2021 18:22:14 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0 with LMTPS id QOXMF7YC1mCrOAAA1q6Kng (envelope-from ) for ; Fri, 25 Jun 2021 16:22:14 +0000 Received: from mail.notmuchmail.org (nmbug.tethera.net [144.217.243.247]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 960BA215A6 for ; Fri, 25 Jun 2021 18:22:13 +0200 (CEST) Received: from nmbug.tethera.net (localhost [127.0.0.1]) by mail.notmuchmail.org (Postfix) with ESMTP id 636B5290AA; Fri, 25 Jun 2021 12:22:10 -0400 (EDT) Received: from eggs.gnu.org (eggs.gnu.org [IPv6:2001:470:142:3::10]) by mail.notmuchmail.org (Postfix) with ESMTPS id 28B8D290A4 for ; Fri, 25 Jun 2021 12:22:08 -0400 (EDT) Received: from fencepost.gnu.org ([2001:470:142:3::e]:50708) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lwoal-00059U-6G for notmuch@notmuchmail.org; Fri, 25 Jun 2021 12:22:07 -0400 Received: from cpc103048-sgyl39-2-0-cust502.18-2.cable.virginm.net ([92.233.85.247]:39848 helo=osgiliath.local) by fencepost.gnu.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lwoal-00068X-13 for notmuch@notmuchmail.org; Fri, 25 Jun 2021 12:22:07 -0400 Received: by osgiliath.local (Postfix, from userid 1000) id F0BFD41A7A; Fri, 25 Jun 2021 17:22:04 +0100 (BST) From: Jose Antonio Ortega Ruiz To: notmuch@notmuchmail.org Subject: Re: sorting in show tree In-Reply-To: <87h7hmhz6a.fsf@tethera.net> References: <87im2l5gxh.fsf@gnus.jao.io> <874kdnf33t.fsf@gnus.jao.io> <87h7hmhz6a.fsf@tethera.net> X-Attribution: jao X-Clacks-Overhead: GNU Terry Pratchett X-URL: Date: Fri, 25 Jun 2021 17:22:04 +0100 Message-ID: <87v961nccz.fsf@gnus.jao.io> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Message-ID-Hash: KJC7BE3IPKEKV5VTMP47SHHRAK43F6CO X-Message-ID-Hash: KJC7BE3IPKEKV5VTMP47SHHRAK43F6CO X-MailFrom: jao@gnu.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-notmuch.notmuchmail.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.1 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-Migadu-Flow: FLOW_IN ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1624638134; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=4TLS8CtOZ2zqYk/mpnIbj84xM9cGOg5tpy5s/4zt1UY=; b=Ww/5Nd3vnqdfPQo3/RvZH2Ve2UWhULBHEllBMxRywQuesCY/vif6ixN5u0nVomRh/PTMW7 FeGFt5Xg1I43t1SJtRKUVQqIlEVSk2he8mA82Zd1/UMDmR3bVsY5vqPePK8zFVWkbaHUI4 ls26r1cyKJ3umINQDkzvjPGpEFzrlcgdwl1yO/pMmEwv3ENbyyHltuvT694gbK0zmzcjeB FjuKwaL4LUIOXwIv3mxHBDE2uezSK9AUqIhzJm39p8nWNL8JKb4QNuKJN7Sr3/y1wi+hWN w3JTp78gUL2DndhQ07w2hFh26rApNbm8xokCMdoqht5wE0Ma6fC+vPnp2Devbw== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1624638134; a=rsa-sha256; cv=none; b=j9dQ5kgA1QV/ixf2J7ONH6LWXqPfGcCj1uLjHNGFy0QgRwW0vJLNLh0ZVGoFG9ySq0Im84 uI8Fr3wwpfJL5bV4CeDVvM4a+/CRcEM4KHtz2k1J64WUm+QmBlMpVrXerJxQSoL9Kh3L23 X3e3yLT1dxSl6pOrcKsRQEb5PodBwF5296a5tzeaJFexRk9EnBtyC7iCiVgLQ2rVlc9H5E hMzPXbisyReZNtAU7Yp6TMkNADSzkqHhrNfYug23b46h0FKIdyASEPFwkPKZzqYBI9YKy0 XGsZmiR9CdT1XPCSUMKhFpnqO3/PvzxleGhyoXNhl4LBzNTUtMqsEmtVik9jkQ== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=none; dmarc=fail reason="SPF not aligned (relaxed), No valid DKIM" header.from=gnu.org (policy=none); spf=pass (aspmx1.migadu.com: domain of notmuch-bounces@notmuchmail.org designates 144.217.243.247 as permitted sender) smtp.mailfrom=notmuch-bounces@notmuchmail.org X-Migadu-Spam-Score: -1.96 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=fail reason="SPF not aligned (relaxed), No valid DKIM" header.from=gnu.org (policy=none); spf=pass (aspmx1.migadu.com: domain of notmuch-bounces@notmuchmail.org designates 144.217.243.247 as permitted sender) smtp.mailfrom=notmuch-bounces@notmuchmail.org X-Migadu-Queue-Id: 960BA215A6 X-Spam-Score: -1.96 X-Migadu-Scanner: scn0.migadu.com X-TUID: zi+5uCh8kZ7f --=-=-= Content-Type: text/plain On Fri, Jun 25 2021, David Bremner wrote: [...] > Unless the series is really huge (thousands of lines of diff) we prefer > sending it to the list with git-send-email for review. So I guess that's > the other thing you should do ;). okay, i'm attaching to this mail the single patch produced by git after rebasing and squashing all my modifications (i don't think it's particularly interesting keeping the story of the 7 individual patches, but they can still be retrieved from my tree-sort branch if you like). thanks, jao --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=0001-Allow-sorting-in-notmuch-tree-search-buffers.patch >From 735366a138a301fb86f83b8434ecff8c8da35d16 Mon Sep 17 00:00:00 2001 From: jao Date: Thu, 10 Jun 2021 22:32:45 +0100 Subject: [PATCH] Allow sorting in notmuch-tree search buffers. - CLI/show: accept --sort - emacs/hello: honouring :sort-order in threaded queries - emacs/tree: command to toggle search sort order in tree mode --- devel/emacs-keybindings.org | 10 +++++----- doc/man1/notmuch-show.rst | 13 +++++++++++++ doc/notmuch-emacs.rst | 7 +++++++ emacs/notmuch-hello.el | 4 +++- emacs/notmuch-tree.el | 24 +++++++++++++++++++----- notmuch-show.c | 7 +++++++ test/T520-show.sh | 17 +++++++++++++++++ 7 files changed, 71 insertions(+), 11 deletions(-) diff --git a/devel/emacs-keybindings.org b/devel/emacs-keybindings.org index 65dfe0eb..f7df3040 100644 --- a/devel/emacs-keybindings.org +++ b/devel/emacs-keybindings.org @@ -15,7 +15,7 @@ | l | notmuch-search-filter | notmuch-show-filter-thread | | | m | notmuch-mua-new-mail | notmuch-mua-new-mail | notmuch-mua-new-mail | | n | notmuch-search-next-thread | notmuch-show-next-open-message | notmuch-tree-next-matching-message | -| o | notmuch-search-toggle-order | | | +| o | notmuch-search-toggle-order | | notmuch-tree-toggle-order | | p | notmuch-search-previous-thread | notmuch-show-previous-open-message | notmuch-tree-prev-matching-message | | q | notmuch-bury-or-kill-this-buffer | notmuch-bury-or-kill-this-buffer | notmuch-bury-or-kill-this-buffer | | r | notmuch-search-reply-to-thread-sender | notmuch-show-reply-sender | notmuch-show-reply-sender | @@ -38,10 +38,10 @@ | V | | notmuch-show-view-raw-message | notmuch-show-view-raw-message | | X | | notmuch-show-archive-thread-then-exit | | | Z | notmuch-tree-from-search-current-query | notmuch-tree-from-show-current-query | | -| =!= | | notmuch-show-toggle-elide-non-matching | | -| =#= | | notmuch-show-print-message | | -| =$= | | notmuch-show-toggle-process-crypto | | -| =*= | notmuch-search-tag-all | notmuch-show-tag-all | notmuch-tree-tag-thread | +| =!= | | notmuch-show-toggle-elide-non-matching | | +| =#= | | notmuch-show-print-message | | +| =$= | | notmuch-show-toggle-process-crypto | | +| =*= | notmuch-search-tag-all | notmuch-show-tag-all | notmuch-tree-tag-thread | | + | notmuch-search-add-tag | notmuch-show-add-tag | notmuch-tree-add-tag | | - | notmuch-search-remove-tag | notmuch-show-remove-tag | notmuch-tree-remove-tag | | . | | notmuch-show-part-map | | diff --git a/doc/man1/notmuch-show.rst b/doc/man1/notmuch-show.rst index fc6bec62..64639174 100644 --- a/doc/man1/notmuch-show.rst +++ b/doc/man1/notmuch-show.rst @@ -111,6 +111,19 @@ Supported options for **show** include part still has two MIME parts: part 0 is the whole message (headers and body) and part 1 is just the body. +.. option:: --sort=(newest-first|oldest-first) + + This option can be used to present results in either chronological + order (**oldest-first**) or reverse chronological order + (**newest-first**). + + Only threads as a whole are reordered. Ordering of messages within + each thread will not be affected by this flag, since that order is + always determined by the thread's replies. + + By default, results will be displayed in reverse chronological + order, (that is, the newest results will be displayed first). + .. option:: --verify Compute and report the validity of any MIME cryptographic diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst index 7772871b..952fe2a5 100644 --- a/doc/notmuch-emacs.rst +++ b/doc/notmuch-emacs.rst @@ -299,12 +299,19 @@ tags. ``p`` Move to previous matching message +``o`` ``notmuch-tree-toggle-order`` + |docstring::notmuch-tree-toggle-order| + ``g`` ``=`` Refresh the buffer ``?`` Display full set of key bindings +As is the case with :ref:`notmuch-search`, the presentation of results +can be controlled by the variable ``notmuch-search-oldest-first``. + + Global key bindings =================== diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 531f209d..5e1ff5fe 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -484,7 +484,9 @@ diagonal." (defun notmuch-hello-widget-search (widget &rest _ignore) (cl-case (widget-get widget :notmuch-search-type) (tree - (notmuch-tree (widget-get widget :notmuch-search-terms))) + (notmuch-tree (widget-get widget :notmuch-search-terms) + nil nil nil nil nil nil + (widget-get widget :notmuch-search-oldest-first))) (unthreaded (notmuch-unthreaded (widget-get widget :notmuch-search-terms))) (t diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index 00ee78d6..c421cf3f 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -326,6 +326,7 @@ then NAME behaves like CMD." (define-key map [remap notmuch-mua-new-mail] 'notmuch-tree-new-mail) (define-key map [remap notmuch-jump-search] 'notmuch-tree-jump-search) + (define-key map "o" 'notmuch-tree-toggle-order) (define-key map "S" 'notmuch-search-from-tree-current-query) (define-key map "U" 'notmuch-unthreaded-from-tree-current-query) (define-key map "Z" 'notmuch-tree-from-unthreaded-current-query) @@ -749,7 +750,8 @@ nil otherwise." query-context target nil - unthreaded))) + unthreaded + notmuch-search-oldest-first))) (defun notmuch-tree-thread-top () (when (notmuch-tree-get-message-properties) @@ -1062,7 +1064,8 @@ Complete list of currently available key bindings: (notmuch-sexp-parse-partial-list 'notmuch-tree-insert-forest-thread results-buf))))) -(defun notmuch-tree-worker (basic-query &optional query-context target open-target unthreaded) +(defun notmuch-tree-worker (basic-query &optional query-context target + open-target unthreaded oldest-first) "Insert the tree view of the search in the current buffer. This is is a helper function for notmuch-tree. The arguments are @@ -1070,6 +1073,7 @@ the same as for the function notmuch-tree." (interactive) (notmuch-tree-mode) (add-hook 'post-command-hook #'notmuch-tree-command-hook t t) + (setq notmuch-search-oldest-first oldest-first) (setq notmuch-tree-unthreaded unthreaded) (setq notmuch-tree-basic-query basic-query) (setq notmuch-tree-query-context (if (or (string= query-context "") @@ -1088,6 +1092,7 @@ the same as for the function notmuch-tree." (let* ((search-args (concat basic-query (and query-context (concat " and (" query-context ")")))) + (sort-arg (if oldest-first "--sort=oldest-first" "--sort=newest-first")) (message-arg (if unthreaded "--unthreaded" "--entire-thread"))) (when (equal (car (process-lines notmuch-command "count" search-args)) "0") (setq search-args basic-query)) @@ -1095,7 +1100,7 @@ the same as for the function notmuch-tree." (let ((proc (notmuch-start-notmuch "notmuch-tree" (current-buffer) #'notmuch-tree-process-sentinel "show" "--body=false" "--format=sexp" "--format-version=4" - message-arg search-args)) + sort-arg message-arg search-args)) ;; Use a scratch buffer to accumulate partial output. ;; This buffer will be killed by the sentinel, which ;; should be called no matter how the process dies. @@ -1113,8 +1118,17 @@ the same as for the function notmuch-tree." ")") notmuch-tree-basic-query)) +(defun notmuch-tree-toggle-order () + "Toggle the current search order. + +This command toggles the sort order for the current search. The +default sort order is defined by `notmuch-search-oldest-first'." + (interactive) + (setq notmuch-search-oldest-first (not notmuch-search-oldest-first)) + (notmuch-tree-refresh-view)) + (defun notmuch-tree (&optional query query-context target buffer-name - open-target unthreaded parent-buffer) + open-target unthreaded parent-buffer oldest-first) "Display threads matching QUERY in tree view. The arguments are: @@ -1143,7 +1157,7 @@ The arguments are: (pop-to-buffer-same-window buffer)) ;; Don't track undo information for this buffer (setq buffer-undo-list t) - (notmuch-tree-worker query query-context target open-target unthreaded) + (notmuch-tree-worker query query-context target open-target unthreaded oldest-first) (setq notmuch-tree-parent-buffer parent-buffer) (setq truncate-lines t)) diff --git a/notmuch-show.c b/notmuch-show.c index bdb87321..947ffa8d 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -1244,8 +1244,13 @@ notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[]) bool single_message; bool unthreaded = FALSE; notmuch_status_t status; + int sort = NOTMUCH_SORT_NEWEST_FIRST; notmuch_opt_desc_t options[] = { + { .opt_keyword = &sort, .name = "sort", .keywords = + (notmuch_keyword_t []){ { "oldest-first", NOTMUCH_SORT_OLDEST_FIRST }, + { "newest-first", NOTMUCH_SORT_NEWEST_FIRST }, + { 0, 0 } } }, { .opt_keyword = &format, .name = "format", .keywords = (notmuch_keyword_t []){ { "json", NOTMUCH_FORMAT_JSON }, { "text", NOTMUCH_FORMAT_TEXT }, @@ -1362,6 +1367,8 @@ notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[]) return EXIT_FAILURE; } + notmuch_query_set_sort (query, sort); + /* Create structure printer. */ formatter = formatters[format]; sprinter = formatter->new_sprinter (notmuch, stdout); diff --git a/test/T520-show.sh b/test/T520-show.sh index 16222650..6f42ca12 100755 --- a/test/T520-show.sh +++ b/test/T520-show.sh @@ -10,4 +10,21 @@ notmuch show foo.. exit_code=$? test_expect_equal 1 $exit_code +test_begin_subtest "notmuch show --sort=newest-first" +notmuch show --entire-thread=true '*' > EXPECTED +notmuch show --entire-thread=true --sort=newest-first '*' > OUTPUT +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "notmuch show --sort=oldest-first" +notmuch show --entire-thread=true '*' | grep ^depth:0 > EXPECTED +notmuch show --entire-thread=true --sort=oldest-first '*' | grep ^depth:0 > OLDEST +perl -e 'print reverse<>' OLDEST > OUTPUT +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "notmuch show --sort for single thread" +QUERY="id:yun1vjwegii.fsf@aiko.keithp.com" +notmuch show --entire-thread=true --sort=newest-first $QUERY > EXPECTED +notmuch show --entire-thread=true --sort=oldest-first $QUERY > OUTPUT +test_expect_equal_file EXPECTED OUTPUT + test_done -- 2.32.0 --=-=-= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline --=-=-=--