[PATCH v8] emacs: notmuch-tree-outline-mode

2022-12-12 Thread jao
With this mode, one can fold trees in the notmuch-tree buffer as if
they were outlines, using all the commands provided by
outline-minor-mode.  We also define a couple of movement commands
that, optional, will ensure that only the thread around point is
unfolded.

The implementation is based on registering a :level property in the
messages p-list, that is then used by outline-minor-mode to to
recognise headers.

---

This patch overrides v7 and fixes some issues pointed out by David:

  - clarify the meaningo of :level with a comment
  - cl-case instead of cumbersome cond+eq
  - fix the check for the id of the shown message, since relying on
  the buffer name is fragile.
  - move hook code to notmuch-mode body

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst |  23 ++
 emacs/notmuch-tree.el | 183 +-
 2 files changed, 204 insertions(+), 2 deletions(-)

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 846f5e67..b5f88a98 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -606,6 +606,29 @@ can be controlled by the variable 
``notmuch-search-oldest-first``.
See also :el:defcustom:`notmuch-search-result-format` and
:el:defcustom:`notmuch-unthreaded-result-format`.
 
+It is also possible to enable outlines in notmuch tree buffers, via
+``notmuch-tree-outline-mode``.
+
+|docstring::notmuch-tree-outline-mode|
+
+The behaviour of this minor mode is affected by the following
+customizable variables:
+
+.. el:defcustom:: notmuch-tree-outline-enabled
+
+   |docstring::notmuch-tree-outline-enabled|
+
+.. el:defcustom:: notmuch-tree-outline-visibility
+
+   |docstring::notmuch-tree-outline-visibility|
+
+.. el:defcustom:: notmuch-tree-outline-auto-close
+
+   |docstring::notmuch-tree-outline-auto-close|
+
+.. el:defcustom:: notmuch-tree-outline-open-on-next
+
+   |docstring::notmuch-tree-outline-open-on-next|
 
 .. _notmuch-unthreaded:
 
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index b3c2c992..063d9a1d 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1014,7 +1014,10 @@ unchanged ADDRESS if parsing fails."
 A message tree is another name for a single sub-thread: i.e., a
 message together with all its descendents."
   (let ((msg (car tree))
-   (replies (cadr tree)))
+   (replies (cadr tree))
+   ;; outline level, computed from the message's depth and
+   ;; wether or not it's the first message in the tree.
+   (level (1+ (if (and (eq 0 depth) (not first)) 1 depth
 (cond
  ((and (< 0 depth) (not last))
   (push (alist-get 'vertical-tee  notmuch-tree-thread-symbols) 
tree-status))
@@ -1034,6 +1037,7 @@ message together with all its descendents."
 (setq msg (plist-put msg :first (and first (eq 0 depth
 (setq msg (plist-put msg :tree-status tree-status))
 (setq msg (plist-put msg :orig-tags (plist-get msg :tags)))
+(setq msg (plist-put msg :level level))
 (notmuch-tree-goto-and-insert-msg msg)
 (pop tree-status)
 (pop tree-status)
@@ -1080,7 +1084,8 @@ Complete list of currently available key bindings:
   (setq notmuch-buffer-refresh-function #'notmuch-tree-refresh-view)
   (hl-line-mode 1)
   (setq buffer-read-only t)
-  (setq truncate-lines t))
+  (setq truncate-lines t)
+  (when notmuch-tree-outline-enabled (notmuch-tree-outline-mode 1)))
 
 (defvar notmuch-tree-process-exit-functions nil
   "Functions called when the process inserting a tree of results finishes.
@@ -1278,6 +1283,180 @@ search results and that are also tagged with the given 
TAG."
  nil
  notmuch-search-oldest-first)))
 
+;;; Tree outline mode
+ Custom variables
+(defcustom notmuch-tree-outline-enabled nil
+  "Whether to automatically activate `notmuch-tree-outline-mode' in tree 
views."
+  :type 'boolean)
+
+(defcustom notmuch-tree-outline-visibility 'hide-others
+  "Default state of the forest outline for `notmuch-tree-outline-mode'.
+
+This variable controls the state of a forest initially and after
+a movement command.  If set to nil, all trees are displayed while
+the symbol hide-all indicates that all trees in the forest should
+be folded and hide-other that only the first one should be
+unfolded."
+  :type '(choice (const :tag "Show all" nil)
+(const :tag "Hide others" hide-others)
+(const :tag "Hide all" hide-all)))
+
+(defcustom notmuch-tree-outline-auto-close nil
+  "Close message and tree windows when moving past the last message."
+  :type 'boolean)
+
+(defcustom notmuch-tree-outline-open-on-next nil
+  "Open new messages under point if they are closed when moving to next one.
+
+When this flag is set, using the command
+`notmuch-tree-outline-next' with point on a header for a new
+message that is not shown will open its `notmuch-show' buffer
+instead of moving point to next matching message."
+

Re: [PATCH v7 1/1] emacs: notmuch-tree-outline-mode

2022-12-11 Thread jao


Thanks for your comments, David.  Unfortunately, i won't be able to work
on this for quite a few months.  I am hoping someone else might perhaps
take the patch over and fix the issues you pinpoint below.  I'm adding
just a handful quick comments:

On Sun, Dec 11 2022, David Bremner wrote:

[...]

>> +(defcustom notmuch-tree-outline-open-on-next nil
>> +  "Open new messages under point if they are closed when moving to next one.
>> +
>> +When this flag is set, using the command
>> +`notmuch-tree-outline-next' with point on a header for a new
>> +message that is not shown will open its `notmuch-show' buffer
>> +instead of moving point to next matching message."
>> +  :type 'boolean)
>> +
>
> I'm curious about your choice of defaults here. At least the second
> seems like t might make more sense?

principle of least surprise: next-message in "normal" tree mode always
goes to the next message, regardless of whether the current one is on
display or not.  for personal use, i defined my own commands changing
that behaviour a long time ago, and, in that regard, yes, i agree
defaulting to t is more natural.  but i wasn't sure other users would
agree.

>> +(defun notmuch-tree-outline--set-visibility ()
>> +  (when (and notmuch-tree-outline-mode (> (point-max) (point-min)))
>> +(cond ((eq notmuch-tree-outline-visibility 'hide-others)
>> +   (notmuch-tree-outline-hide-others))
>> +  ((eq notmuch-tree-outline-visibility 'hide-all)
>> +   (outline-hide-body)
>
> I wouldn't insist, but cl-case (or even pcase) might be clearer here.

no opinion here (personally, i feel exactly the opposite, but i think
it's just a matter of taste or familiarity).

>> +(add-hook 'notmuch-tree-process-exit-functions 
>> #'notmuch-tree-outline--on-exit)
>
> Although it is relatively common in emacs code, I'm a bit skeptical of
> using hooks for things not intended to be customized by the user. Should
> we just be calling this directly somewhere?

i'm neutral on that.  with a hook, this package can almost be an
independent add-on (it would only need the :level property below).  but
it's true that doesn't matter if we merge in notmuch.

>> +(defsubst notmuch-tree-outline--level ( props)
>> +  (or (plist-get (or props (notmuch-tree-get-message-properties)) :level) 
>> 0))
>
> As mentioned in my previous reply, I'm still not 100% clear on why we
> need both depth and level.

i might be misremembering, but i think depth is just an auxiliarly
argument taken by that function to know whether it's inserting the tip
of a tree or not, not a real depth.  level is.  so a better way would be
to make 'depth' take the values 'level' is currently taking, but i
wasn't sure other code would be using depth with its old original
meaning (e.g. via and advice; i did at some point).

>> +(defsubst notmuch-tree-outline--message-open-p ()
>> +  (and (buffer-live-p notmuch-tree-message-buffer)
>> +   (get-buffer-window notmuch-tree-message-buffer)
>> +   (string-match-p (regexp-quote (or (notmuch-tree-get-message-id) ""))
>
> What's going with the 'or' here? Are we hiding errors?

just preventing errors if someone calls this function (via a user-level
command) in the "End of search" line or the blank line at the end of the
messages list.

>
>> +   (buffer-name notmuch-tree-message-buffer
>
> At first glance, depending on the buffer name seems fragile?

not sure why, or how to make it more robust...

>> + Mode definition
>> +(defvar notmuch-tree-outline-mode-lighter nil
>> +  "The lighter mark for notmuch-tree-outline mode.
>> +Usually empty since outline-minor-mode's lighter will be active.")
>
> I feel like I should know what a "lighter" is in this context, but alas,
> I don't

the string in the mode line used to show a minor mode is active.  aka
"minor mode lighter"

> Finally:
>
> According to a quick test, the folding does show up in
> (visible-buffer-string) (from test/test-lib.el). So it seems feasible to
> have a few tests with folded output?

indeed.  hope someone will find a bit of time for that! (fwiw, i've 
used variations of this code for almost a year, so it's relatively well
field-tested; but of course that doesn't obviate proper tests)

cheers,
jao
-- 
More people would learn from their mistakes if they weren't so busy
denying them - Harlod J. Smith
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


Re: [PATCH v7 0/1] emacs: notmuch-tree-outline-mode

2022-11-04 Thread jao
On Fri, Nov 04 2022, jao wrote:

> This is essentiall the same as the previously sent v 6, rebased over
> the current master branch.  Since that previous version has not
> elicited special enthusiasm, yet i use it all the time, so if you guys
> think it's not worth integrating into notmuch-emacs upstream, please
> just let me know and i'll create a separate ELPA package for it.

i am actually going to take that back: my patch modifies only one line
of existing code (notmuch-tree.el:1037), to set a new message property.
tiny as the change is, it'd be quite complicated to do the same
externally, from a package (barring very ugly hacks like an :override
advice)... so i guess i'll keep using my private version of
notmuch-tree.el if this patch cannot get in :)

cheers,
jao
-- 
Lower your voice and strengthen your argument. -Lebanese proverb
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v7 1/1] emacs: notmuch-tree-outline-mode

2022-11-04 Thread jao
With this mode, one can fold trees in the notmuch-tree buffer as if
they were outlines, using all the commands provided by
outline-minor-mode.  We also define a couple of movement commands
that, optional, will ensure that only the thread around point is
unfolded.

The implementation is based on registering a :level property in the
messages p-list, that is then used by outline-minor-mode to to
recognise headers.

---
Leftover in verson 5 removed, sorry!

This version supersedes v4 (id:20220923203449.3747562-1-...@gnu.org)
by dispensing with the use of invisible text.  Now, if desired,
notmuch-tree-outline-mode could live in its own
notmuch-tree-outline-mode.el without circular deps, but i don't see
a pressing need given that notmuch-tree.el is nicely outlined.

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst |  23 ++
 emacs/notmuch-tree.el | 180 ++
 2 files changed, 203 insertions(+)

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 846f5e67..b5f88a98 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -606,6 +606,29 @@ can be controlled by the variable 
``notmuch-search-oldest-first``.
See also :el:defcustom:`notmuch-search-result-format` and
:el:defcustom:`notmuch-unthreaded-result-format`.
 
+It is also possible to enable outlines in notmuch tree buffers, via
+``notmuch-tree-outline-mode``.
+
+|docstring::notmuch-tree-outline-mode|
+
+The behaviour of this minor mode is affected by the following
+customizable variables:
+
+.. el:defcustom:: notmuch-tree-outline-enabled
+
+   |docstring::notmuch-tree-outline-enabled|
+
+.. el:defcustom:: notmuch-tree-outline-visibility
+
+   |docstring::notmuch-tree-outline-visibility|
+
+.. el:defcustom:: notmuch-tree-outline-auto-close
+
+   |docstring::notmuch-tree-outline-auto-close|
+
+.. el:defcustom:: notmuch-tree-outline-open-on-next
+
+   |docstring::notmuch-tree-outline-open-on-next|
 
 .. _notmuch-unthreaded:
 
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index b3c2c992..47bd17bc 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1034,6 +1034,8 @@ message together with all its descendents."
 (setq msg (plist-put msg :first (and first (eq 0 depth
 (setq msg (plist-put msg :tree-status tree-status))
 (setq msg (plist-put msg :orig-tags (plist-get msg :tags)))
+(setq msg (plist-put msg
+:level (1+ (if (and (eq 0 depth) (not first)) 1 
depth
 (notmuch-tree-goto-and-insert-msg msg)
 (pop tree-status)
 (pop tree-status)
@@ -1278,6 +1280,184 @@ search results and that are also tagged with the given 
TAG."
  nil
  notmuch-search-oldest-first)))
 
+;;; Tree outline mode
+ Custom variables
+(defcustom notmuch-tree-outline-enabled nil
+  "Whether to automatically activate `notmuch-tree-outline-mode' in tree 
views."
+  :type 'boolean)
+
+(defcustom notmuch-tree-outline-visibility 'hide-others
+  "Default state of the forest outline for `notmuch-tree-outline-mode'.
+
+This variable controls the state of a forest initially and after
+a movement command.  If set to nil, all trees are displayed while
+the symbol hide-all indicates that all trees in the forest should
+be folded and hide-other that only the first one should be
+unfolded."
+  :type '(choice (const :tag "Show all" nil)
+(const :tag "Hide others" hide-others)
+(const :tag "Hide all" hide-all)))
+
+(defcustom notmuch-tree-outline-auto-close nil
+  "Close message and tree windows when moving past the last message."
+  :type 'boolean)
+
+(defcustom notmuch-tree-outline-open-on-next nil
+  "Open new messages under point if they are closed when moving to next one.
+
+When this flag is set, using the command
+`notmuch-tree-outline-next' with point on a header for a new
+message that is not shown will open its `notmuch-show' buffer
+instead of moving point to next matching message."
+  :type 'boolean)
+
+ Helper functions
+(defsubst notmuch-tree-outline--pop-at-end (pop-at-end)
+  (if notmuch-tree-outline-auto-close (not pop-at-end) pop-at-end))
+
+(defun notmuch-tree-outline--enable-mode ()
+  (when notmuch-tree-outline-enabled (notmuch-tree-outline-mode 1)))
+
+(add-hook 'notmuch-tree-mode-hook #'notmuch-tree-outline--enable-mode)
+
+(defun notmuch-tree-outline--set-visibility ()
+  (when (and notmuch-tree-outline-mode (> (point-max) (point-min)))
+(cond ((eq notmuch-tree-outline-visibility 'hide-others)
+  (notmuch-tree-outline-hide-others))
+ ((eq notmuch-tree-outline-visibility 'hide-all)
+  (outline-hide-body)
+
+(defun notmuch-tree-outline--on-exit (proc)
+  (when (eq (process-status proc) 'exit)
+(notmuch-tree-outline--set-visibility)))
+
+(add-hook 'notmuch-tree-process-exit-functions #'notmuch-tree-outline--on-exit)
+
+(defsubst notmuch-tree-outli

[PATCH v7 0/1] emacs: notmuch-tree-outline-mode

2022-11-04 Thread jao
This is essentiall the same as the previously sent v 6, rebased over
the current master branch.  Since that previous version has not
elicited special enthusiasm, yet i use it all the time, so if you guys
think it's not worth integrating into notmuch-emacs upstream, please
just let me know and i'll create a separate ELPA package for it.

Thanks!
jao

jao (1):
  emacs: notmuch-tree-outline-mode

 doc/notmuch-emacs.rst |  23 ++
 emacs/notmuch-tree.el | 180 ++
 2 files changed, 203 insertions(+)

--
2.38.1
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v6] emacs: notmuch-tree-outline-mode

2022-09-24 Thread jao
With this mode, one can fold trees in the notmuch-tree buffer as if
they were outlines, using all the commands provided by
outline-minor-mode.  We also define a couple of movement commands
that, optional, will ensure that only the thread around point is
unfolded.

The implementation is based on registering a :level property in the
messages p-list, that is then used by outline-minor-mode to to
recognise headers.

---
Leftover in verson 5 removed, sorry!

This version supersedes v4 (id:20220923203449.3747562-1-...@gnu.org)
by dispensing with the use of invisible text.  Now, if desired,
notmuch-tree-outline-mode could live in its own
notmuch-tree-outline-mode.el without circular deps, but i don't see
a pressing need given that notmuch-tree.el is nicely outlined.

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst |  23 ++
 emacs/notmuch-tree.el | 180 ++
 2 files changed, 203 insertions(+)

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 846f5e67..b5f88a98 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -606,6 +606,29 @@ can be controlled by the variable 
``notmuch-search-oldest-first``.
See also :el:defcustom:`notmuch-search-result-format` and
:el:defcustom:`notmuch-unthreaded-result-format`.
 
+It is also possible to enable outlines in notmuch tree buffers, via
+``notmuch-tree-outline-mode``.
+
+|docstring::notmuch-tree-outline-mode|
+
+The behaviour of this minor mode is affected by the following
+customizable variables:
+
+.. el:defcustom:: notmuch-tree-outline-enabled
+
+   |docstring::notmuch-tree-outline-enabled|
+
+.. el:defcustom:: notmuch-tree-outline-visibility
+
+   |docstring::notmuch-tree-outline-visibility|
+
+.. el:defcustom:: notmuch-tree-outline-auto-close
+
+   |docstring::notmuch-tree-outline-auto-close|
+
+.. el:defcustom:: notmuch-tree-outline-open-on-next
+
+   |docstring::notmuch-tree-outline-open-on-next|
 
 .. _notmuch-unthreaded:
 
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index b3c2c992..47bd17bc 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1034,6 +1034,8 @@ message together with all its descendents."
 (setq msg (plist-put msg :first (and first (eq 0 depth
 (setq msg (plist-put msg :tree-status tree-status))
 (setq msg (plist-put msg :orig-tags (plist-get msg :tags)))
+(setq msg (plist-put msg
+:level (1+ (if (and (eq 0 depth) (not first)) 1 
depth
 (notmuch-tree-goto-and-insert-msg msg)
 (pop tree-status)
 (pop tree-status)
@@ -1278,6 +1280,184 @@ search results and that are also tagged with the given 
TAG."
  nil
  notmuch-search-oldest-first)))
 
+;;; Tree outline mode
+ Custom variables
+(defcustom notmuch-tree-outline-enabled nil
+  "Whether to automatically activate `notmuch-tree-outline-mode' in tree 
views."
+  :type 'boolean)
+
+(defcustom notmuch-tree-outline-visibility 'hide-others
+  "Default state of the forest outline for `notmuch-tree-outline-mode'.
+
+This variable controls the state of a forest initially and after
+a movement command.  If set to nil, all trees are displayed while
+the symbol hide-all indicates that all trees in the forest should
+be folded and hide-other that only the first one should be
+unfolded."
+  :type '(choice (const :tag "Show all" nil)
+(const :tag "Hide others" hide-others)
+(const :tag "Hide all" hide-all)))
+
+(defcustom notmuch-tree-outline-auto-close nil
+  "Close message and tree windows when moving past the last message."
+  :type 'boolean)
+
+(defcustom notmuch-tree-outline-open-on-next nil
+  "Open new messages under point if they are closed when moving to next one.
+
+When this flag is set, using the command
+`notmuch-tree-outline-next' with point on a header for a new
+message that is not shown will open its `notmuch-show' buffer
+instead of moving point to next matching message."
+  :type 'boolean)
+
+ Helper functions
+(defsubst notmuch-tree-outline--pop-at-end (pop-at-end)
+  (if notmuch-tree-outline-auto-close (not pop-at-end) pop-at-end))
+
+(defun notmuch-tree-outline--enable-mode ()
+  (when notmuch-tree-outline-enabled (notmuch-tree-outline-mode 1)))
+
+(add-hook 'notmuch-tree-mode-hook #'notmuch-tree-outline--enable-mode)
+
+(defun notmuch-tree-outline--set-visibility ()
+  (when (and notmuch-tree-outline-mode (> (point-max) (point-min)))
+(cond ((eq notmuch-tree-outline-visibility 'hide-others)
+  (notmuch-tree-outline-hide-others))
+ ((eq notmuch-tree-outline-visibility 'hide-all)
+  (outline-hide-body)
+
+(defun notmuch-tree-outline--on-exit (proc)
+  (when (eq (process-status proc) 'exit)
+(notmuch-tree-outline--set-visibility)))
+
+(add-hook 'notmuch-tree-process-exit-functions #'notmuch-tree-outline--on-exit)
+
+(defsubst notmuch-tree-outli

[PATCH v5] emacs: notmuch-tree-outline-mode

2022-09-24 Thread jao
With this mode, one can fold trees in the notmuch-tree buffer as if
they were outlines, using all the commands provided by
outline-minor-mode.  We also define a couple of movement commands
that, optional, will ensure that only the thread around point is
unfolded.

The implementation is based on registering a :level property in the
messages p-list, that is then used by outline-minor-mode to to
recognise headers.

---
This version supersedes v4 (id:20220923203449.3747562-1-...@gnu.org)
by dispensing with the use of invisible text.  Now, if desired,
notmuch-tree-outline-mode could live in its own
notmuch-tree-outline-mode.el without circular deps, but i don't see
a pressing need given that notmuch-tree.el is nicely outlined.

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst |  23 ++
 emacs/notmuch-tree.el | 181 ++
 2 files changed, 204 insertions(+)

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 846f5e67..b5f88a98 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -606,6 +606,29 @@ can be controlled by the variable 
``notmuch-search-oldest-first``.
See also :el:defcustom:`notmuch-search-result-format` and
:el:defcustom:`notmuch-unthreaded-result-format`.
 
+It is also possible to enable outlines in notmuch tree buffers, via
+``notmuch-tree-outline-mode``.
+
+|docstring::notmuch-tree-outline-mode|
+
+The behaviour of this minor mode is affected by the following
+customizable variables:
+
+.. el:defcustom:: notmuch-tree-outline-enabled
+
+   |docstring::notmuch-tree-outline-enabled|
+
+.. el:defcustom:: notmuch-tree-outline-visibility
+
+   |docstring::notmuch-tree-outline-visibility|
+
+.. el:defcustom:: notmuch-tree-outline-auto-close
+
+   |docstring::notmuch-tree-outline-auto-close|
+
+.. el:defcustom:: notmuch-tree-outline-open-on-next
+
+   |docstring::notmuch-tree-outline-open-on-next|
 
 .. _notmuch-unthreaded:
 
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index b3c2c992..3c92b839 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1034,6 +1034,8 @@ message together with all its descendents."
 (setq msg (plist-put msg :first (and first (eq 0 depth
 (setq msg (plist-put msg :tree-status tree-status))
 (setq msg (plist-put msg :orig-tags (plist-get msg :tags)))
+(setq msg (plist-put msg
+:level (1+ (if (and (eq 0 depth) (not first)) 1 
depth
 (notmuch-tree-goto-and-insert-msg msg)
 (pop tree-status)
 (pop tree-status)
@@ -1278,6 +1280,185 @@ search results and that are also tagged with the given 
TAG."
  nil
  notmuch-search-oldest-first)))
 
+;;; Tree outline mode
+ Custom variables
+(defcustom notmuch-tree-outline-enabled nil
+  "Whether to automatically activate `notmuch-tree-outline-mode' in tree 
views."
+  :type 'boolean)
+
+(defcustom notmuch-tree-outline-visibility 'hide-others
+  "Default state of the forest outline for `notmuch-tree-outline-mode'.
+
+This variable controls the state of a forest initially and after
+a movement command.  If set to nil, all trees are displayed while
+the symbol hide-all indicates that all trees in the forest should
+be folded and hide-other that only the first one should be
+unfolded."
+  :type '(choice (const :tag "Show all" nil)
+(const :tag "Hide others" hide-others)
+(const :tag "Hide all" hide-all)))
+
+(defcustom notmuch-tree-outline-auto-close nil
+  "Close message and tree windows when moving past the last message."
+  :type 'boolean)
+
+(defcustom notmuch-tree-outline-open-on-next nil
+  "Open new messages under point if they are closed when moving to next one.
+
+When this flag is set, using the command
+`notmuch-tree-outline-next' with point on a header for a new
+message that is not shown will open its `notmuch-show' buffer
+instead of moving point to next matching message."
+  :type 'boolean)
+
+ Helper functions
+(defsubst notmuch-tree-outline--pop-at-end (pop-at-end)
+  (if notmuch-tree-outline-auto-close (not pop-at-end) pop-at-end))
+
+(defun notmuch-tree-outline--enable-mode ()
+  (when notmuch-tree-outline-enabled (notmuch-tree-outline-mode 1)))
+
+(add-hook 'notmuch-tree-mode-hook #'notmuch-tree-outline--enable-mode)
+
+(defun notmuch-tree-outline--set-visibility ()
+  (when (and notmuch-tree-outline-mode (> (point-max) (point-min)))
+(cond ((eq notmuch-tree-outline-visibility 'hide-others)
+  (notmuch-tree-outline-hide-others))
+ ((eq notmuch-tree-outline-visibility 'hide-all)
+  (outline-hide-body)
+
+(defun notmuch-tree-outline--on-exit (proc)
+  (when (eq (process-status proc) 'exit)
+(notmuch-tree-outline--set-visibility)))
+
+(add-hook 'notmuch-tree-process-exit-functions #'notmuch-tree-outline--on-exit)
+
+(defsubst notmuch-tree-outline--level ( props)
+  (or (plist-get (or

[PATCH v4] emacs: notmuch-tree-outline-mode

2022-09-23 Thread jao
With this mode, one can fold trees in the notmuch-tree buffer as if
they were outlines, using all the commands provided by
outline-minor-mode.  We also define a couple of movement commands
that, optional, will ensure that only the thread around point is
unfolded.

The implementation is based on the trick of inserting an invisible
prefix before each thread head that is then used as the regexp used by
outline-minor-mode to recognise headers.  The message plist is also
augmented with a :level property that provides a fast outline-level
function.

---
This version supesedes v3 (id:20220921225510.3159023-1-...@gnu.org)
by allowing notmuch-tree-ouline-mode to be enabled manually, not only
automatically via notmuch-tree-outline-enabled, which was misnamed in
the defcustom, by the way: we use now that name, as documented).

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst |  20 +
 emacs/notmuch-tree.el | 176 ++
 2 files changed, 196 insertions(+)

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 846f5e67..53e68c4d 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -606,6 +606,26 @@ can be controlled by the variable 
``notmuch-search-oldest-first``.
See also :el:defcustom:`notmuch-search-result-format` and
:el:defcustom:`notmuch-unthreaded-result-format`.
 
+It is also possible to enable outlines in notmuch tree buffers, via
+``notmuch-tree-outline-mode``.
+
+|docstring::notmuch-tree-outline-mode|
+
+The behaviour of this minor mode is affected by the following
+customizable variables:
+
+.. el:defcustom:: notmuch-tree-outline-enabled
+
+   |docstring::notmuch-tree-outline-enabled|
+
+.. el:defcustom:: notmuch-tree-outline-visibility
+
+   |docstring::notmuch-tree-outline-visibility|
+
+.. el:defcustom:: notmuch-tree-outline-auto-close
+
+   |docstring::notmuch-tree-outline-auto-close|
+
 
 .. _notmuch-unthreaded:
 
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index 7ceddee2..bff29351 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -989,6 +989,7 @@ unchanged ADDRESS if parsing fails."
   ;; We need to save the previous subject as it will get overwritten
   ;; by the insert-field calls.
   (let ((previous-subject notmuch-tree-previous-subject))
+(notmuch-tree-outline--insert-prefix msg)
 (insert (notmuch-tree-format-field-list (notmuch-tree-result-format) msg))
 (notmuch-tree-set-message-properties msg)
 (notmuch-tree-set-prop :previous-subject previous-subject)
@@ -1036,6 +1037,8 @@ message together with all its descendents."
 (setq msg (plist-put msg :first (and first (eq 0 depth
 (setq msg (plist-put msg :tree-status tree-status))
 (setq msg (plist-put msg :orig-tags (plist-get msg :tags)))
+(setq msg (plist-put msg
+:level (1+ (if (and (eq 0 depth) (not first)) 1 
depth
 (notmuch-tree-goto-and-insert-msg msg)
 (pop tree-status)
 (pop tree-status)
@@ -1265,6 +1268,179 @@ search results and that are also tagged with the given 
TAG."
  nil
  notmuch-search-oldest-first)))
 
+;;; Tree outline mode
+ Custom variables
+(defcustom notmuch-tree-outline-enabled nil
+  "Whether to automatically activate `notmuch-tree-outline-mode' in tree 
views."
+  :type 'boolean)
+
+(defcustom notmuch-tree-outline-visibility 'hide-others
+  "Default state of the forest outline for `notmuch-tree-outline-mode'.
+This variable controls the state of a forest initially and after
+a movement command.  If set to nil, all trees are displayed while
+the symbol hide-all indicates that all trees in the forest should
+be folded and hide-other that only the first one should be
+unfolded."
+  :type '(choice (const :tag "Show all" nil)
+(const :tag "Hide others" hide-others)
+(const :tag "Hide all" hide-all)))
+
+(defcustom notmuch-tree-outline-auto-close nil
+  "Close message and tree windows when moving past the last message."
+  :type 'boolean)
+
+ Helper functions
+(defsubst notmuch-tree-outline--pop-at-end (pop-at-end)
+  (if notmuch-tree-outline-auto-close (not pop-at-end) pop-at-end))
+
+(defun notmuch-tree-outline--enable-mode ()
+  (when notmuch-tree-outline-enabled (notmuch-tree-outline-mode 1)))
+
+(add-hook 'notmuch-tree-mode-hook #'notmuch-tree-outline--enable-mode)
+
+(defun notmuch-tree-outline--set-visibility ()
+  (when (and notmuch-tree-outline-mode (> (point-max) (point-min)))
+(cond ((eq notmuch-tree-outline-visibility 'hide-others)
+  (notmuch-tree-outline-hide-others))
+ ((eq notmuch-tree-outline-visibility 'hide-all)
+  (outline-hide-body)
+
+(defun notmuch-tree-outline--on-exit (proc)
+  (when (eq (process-status proc) 'exit)
+(notmuch-tree-outline--set-visibility)))
+
+(add-hook 'notmuch-tree-process-exit-functions #'notmuch-tree-outline--on-exit)
+
+(defs

[PATCH v3] emacs: notmuch-tree-outline-mode

2022-09-21 Thread jao
With this mode, one can fold trees in the notmuch-tree buffer as if
they were outlines, using all the commands provided by
outline-minor-mode.  We also define a couple of movement commands
that, optional, will ensure that only the thread around point is
unfolded.

The implementation is based on the trick of inserting an invisible
prefix before each thread head that is then used as the regexp used by
outline-minor-mode to recognise headers.  The message plist is also
augmented with a :level property that provides a fast outline-level
function.

---

This version supesedes v2 (id:87v8ta60w4@mail.jao.io) with a small
fix for one of the auxiliary
functions (notmuch-tree-outline--message-open-p).

This version supersedes id:20220918203658.1893065-1-...@gnu.org with:

It improves on the above by allowing folding operations for nested
subtrees, and fixing some glitches with (folded) thread navigation.

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst |  20 +
 emacs/notmuch-tree.el | 176 ++
 2 files changed, 196 insertions(+)

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 846f5e67..53e68c4d 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -606,6 +606,26 @@ can be controlled by the variable 
``notmuch-search-oldest-first``.
See also :el:defcustom:`notmuch-search-result-format` and
:el:defcustom:`notmuch-unthreaded-result-format`.
 
+It is also possible to enable outlines in notmuch tree buffers, via
+``notmuch-tree-outline-mode``.
+
+|docstring::notmuch-tree-outline-mode|
+
+The behaviour of this minor mode is affected by the following
+customizable variables:
+
+.. el:defcustom:: notmuch-tree-outline-enabled
+
+   |docstring::notmuch-tree-outline-enabled|
+
+.. el:defcustom:: notmuch-tree-outline-visibility
+
+   |docstring::notmuch-tree-outline-visibility|
+
+.. el:defcustom:: notmuch-tree-outline-auto-close
+
+   |docstring::notmuch-tree-outline-auto-close|
+
 
 .. _notmuch-unthreaded:
 
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index 7ceddee2..79de4c3d 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -989,6 +989,7 @@ unchanged ADDRESS if parsing fails."
   ;; We need to save the previous subject as it will get overwritten
   ;; by the insert-field calls.
   (let ((previous-subject notmuch-tree-previous-subject))
+(when notmuch-tree-outline-mode (notmuch-tree-outline--insert-prefix msg))
 (insert (notmuch-tree-format-field-list (notmuch-tree-result-format) msg))
 (notmuch-tree-set-message-properties msg)
 (notmuch-tree-set-prop :previous-subject previous-subject)
@@ -1036,6 +1037,8 @@ message together with all its descendents."
 (setq msg (plist-put msg :first (and first (eq 0 depth
 (setq msg (plist-put msg :tree-status tree-status))
 (setq msg (plist-put msg :orig-tags (plist-get msg :tags)))
+(setq msg (plist-put msg
+:level (1+ (if (and (eq 0 depth) (not first)) 1 
depth
 (notmuch-tree-goto-and-insert-msg msg)
 (pop tree-status)
 (pop tree-status)
@@ -1265,6 +1268,179 @@ search results and that are also tagged with the given 
TAG."
  nil
  notmuch-search-oldest-first)))
 
+;;; Tree outline mode
+ Custom variables
+(defcustom notmuch-tree-outline-mode-enabled nil
+  "Whether to automatically activate `notmuch-tree-outline-mode' in tree 
views."
+  :type 'boolean)
+
+(defcustom notmuch-tree-outline-visibility 'hide-others
+  "Default state of the forest outline for `notmuch-tree-outline-mode'.
+This variable controls the state of a forest initially and after
+a movement command.  If set to nil, all trees are displayed while
+the symbol hide-all indicates that all trees in the forest should
+be folded and hide-other that only the first one should be
+unfolded."
+  :type '(choice (const :tag "Show all" nil)
+(const :tag "Hide others" hide-others)
+(const :tag "Hide all" hide-all)))
+
+(defcustom notmuch-tree-outline-auto-close nil
+  "Close message and tree windows when moving past the last message."
+  :type 'boolean)
+
+ Helper functions
+(defsubst notmuch-tree-outline--pop-at-end (pop-at-end)
+  (if notmuch-tree-outline-auto-close (not pop-at-end) pop-at-end))
+
+(defun notmuch-tree-outline--enable-mode ()
+  (when notmuch-tree-outline-mode-enabled (notmuch-tree-outline-mode 1)))
+
+(add-hook 'notmuch-tree-mode-hook #'notmuch-tree-outline--enable-mode)
+
+(defun notmuch-tree-outline--set-visibility ()
+  (when (and notmuch-tree-outline-mode (> (point-max) (point-min)))
+(cond ((eq notmuch-tree-outline-visibility 'hide-others)
+  (notmuch-tree-outline-hide-others))
+ ((eq notmuch-tree-outline-visibility 'hide-all)
+  (outline-hide-body)
+
+(defun notmuch-tree-outline--on-exit (proc)
+  (when (eq (process-status proc) 'exit)
+(n

[PATCH v2] emacs: notmuch-tree-outline-mode

2022-09-19 Thread jao
With this mode, one can fold trees in the notmuch-tree buffer as if
they were outlines, using all the commands provided by
outline-minor-mode.  We also define a couple of movement commands
that, optional, will ensure that only the thread around point is
unfolded.

The implementation is based on the trick of inserting an invisible
prefix before each thread head that is then used as the regexp used by
outline-minor-mode to recognise headers.  The message plist is also
augmented with a :level property that provides a fast outline-level
function.

---

This version supersedes id:20220918203658.1893065-1-...@gnu.org

It improves on the above by allowing folding operations for nested
subtrees, and fixing some glitches with (folded) thread navigation.

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst |  20 +
 emacs/notmuch-tree.el | 174 ++
 2 files changed, 194 insertions(+)

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 846f5e67..53e68c4d 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -606,6 +606,26 @@ can be controlled by the variable 
``notmuch-search-oldest-first``.
See also :el:defcustom:`notmuch-search-result-format` and
:el:defcustom:`notmuch-unthreaded-result-format`.
 
+It is also possible to enable outlines in notmuch tree buffers, via
+``notmuch-tree-outline-mode``.
+
+|docstring::notmuch-tree-outline-mode|
+
+The behaviour of this minor mode is affected by the following
+customizable variables:
+
+.. el:defcustom:: notmuch-tree-outline-enabled
+
+   |docstring::notmuch-tree-outline-enabled|
+
+.. el:defcustom:: notmuch-tree-outline-visibility
+
+   |docstring::notmuch-tree-outline-visibility|
+
+.. el:defcustom:: notmuch-tree-outline-auto-close
+
+   |docstring::notmuch-tree-outline-auto-close|
+
 
 .. _notmuch-unthreaded:
 
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index 7ceddee2..c2b5dbf2 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -989,6 +989,7 @@ unchanged ADDRESS if parsing fails."
   ;; We need to save the previous subject as it will get overwritten
   ;; by the insert-field calls.
   (let ((previous-subject notmuch-tree-previous-subject))
+(when notmuch-tree-outline-mode (notmuch-tree-outline--insert-prefix msg))
 (insert (notmuch-tree-format-field-list (notmuch-tree-result-format) msg))
 (notmuch-tree-set-message-properties msg)
 (notmuch-tree-set-prop :previous-subject previous-subject)
@@ -1036,6 +1037,8 @@ message together with all its descendents."
 (setq msg (plist-put msg :first (and first (eq 0 depth
 (setq msg (plist-put msg :tree-status tree-status))
 (setq msg (plist-put msg :orig-tags (plist-get msg :tags)))
+(setq msg (plist-put msg
+:level (1+ (if (and (eq 0 depth) (not first)) 1 
depth
 (notmuch-tree-goto-and-insert-msg msg)
 (pop tree-status)
 (pop tree-status)
@@ -1265,6 +1268,177 @@ search results and that are also tagged with the given 
TAG."
  nil
  notmuch-search-oldest-first)))
 
+;;; Tree outline mode
+ Custom variables
+(defcustom notmuch-tree-outline-mode-enabled nil
+  "Whether to automatically activate `notmuch-tree-outline-mode' in tree 
views."
+  :type 'boolean)
+
+(defcustom notmuch-tree-outline-visibility 'hide-others
+  "Default state of the forest outline for `notmuch-tree-outline-mode'.
+This variable controls the state of a forest initially and after
+a movement command.  If set to nil, all trees are displayed while
+the symbol hide-all indicates that all trees in the forest should
+be folded and hide-other that only the first one should be
+unfolded."
+  :type '(choice (const :tag "Show all" nil)
+(const :tag "Hide others" hide-others)
+(const :tag "Hide all" hide-all)))
+
+(defcustom notmuch-tree-outline-auto-close nil
+  "Close message and tree windows when moving past the last message."
+  :type 'boolean)
+
+ Helper functions
+(defsubst notmuch-tree-outline--pop-at-end (pop-at-end)
+  (if notmuch-tree-outline-auto-close (not pop-at-end) pop-at-end))
+
+(defun notmuch-tree-outline--enable-mode ()
+  (when notmuch-tree-outline-mode-enabled (notmuch-tree-outline-mode 1)))
+
+(add-hook 'notmuch-tree-mode-hook #'notmuch-tree-outline--enable-mode)
+
+(defun notmuch-tree-outline--set-visibility ()
+  (when (and notmuch-tree-outline-mode (> (point-max) (point-min)))
+(cond ((eq notmuch-tree-outline-visibility 'hide-others)
+  (notmuch-tree-outline-hide-others))
+ ((eq notmuch-tree-outline-visibility 'hide-all)
+  (outline-hide-body)
+
+(defun notmuch-tree-outline--on-exit (proc)
+  (when (eq (process-status proc) 'exit)
+(notmuch-tree-outline--set-visibility)))
+
+(add-hook 'notmuch-tree-process-exit-functions #'notmuch-tree-outline--on-exit)
+
+(defsubst notmuch-tree-outline--l

[PATCH] emacs: notmuch-tree-outline-mode

2022-09-18 Thread jao
With this mode, one can fold trees in the notmuch-tree buffer as if
they were outlines, using all the commands provided by
outline-minor-mode.  We also define a couple of movement commands
that, optional, will ensure that only the thread around point is
unfolded.

The implementation is based on the trick of inserting an invisible
character before each thread head that is then used as the regexp used
by outline-minor-mode to recognise headers.

---

I've been using this mode for a while and seems to work well for my
needs, although every now and then navigation with commands other than
the ones it defines puts point in a bad place... usually it's very
easy to go back to where you were (e.g., a simple C-a), but maybe i'm
having stockholm syndrome :)

I think the same trick i'm playing could be used to allow folding of
subtrees at more than one level (just insert several hidden > instead
of just one), but i'm not sure it would be of much use or introduce
any problem, so i've not done it here.  Perhaps we could add it under
an opt-in option if people think it useful.

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst |  20 ++
 emacs/notmuch-tree.el | 157 ++
 2 files changed, 177 insertions(+)

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 846f5e67..53e68c4d 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -606,6 +606,26 @@ can be controlled by the variable 
``notmuch-search-oldest-first``.
See also :el:defcustom:`notmuch-search-result-format` and
:el:defcustom:`notmuch-unthreaded-result-format`.
 
+It is also possible to enable outlines in notmuch tree buffers, via
+``notmuch-tree-outline-mode``.
+
+|docstring::notmuch-tree-outline-mode|
+
+The behaviour of this minor mode is affected by the following
+customizable variables:
+
+.. el:defcustom:: notmuch-tree-outline-enabled
+
+   |docstring::notmuch-tree-outline-enabled|
+
+.. el:defcustom:: notmuch-tree-outline-visibility
+
+   |docstring::notmuch-tree-outline-visibility|
+
+.. el:defcustom:: notmuch-tree-outline-auto-close
+
+   |docstring::notmuch-tree-outline-auto-close|
+
 
 .. _notmuch-unthreaded:
 
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index 7ceddee2..50139589 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -984,11 +984,17 @@ unchanged ADDRESS if parsing fails."
(setq result-string (concat result-string field-string
 (notmuch-apply-face result-string face t)))
 
+(defvar notmuch-tree--insert-pre-fun nil
+  "Function called before every message header in the forest view.
+Mainly for internal use (e.g. by outline mode).")
+
 (defun notmuch-tree-insert-msg (msg)
   "Insert the message MSG according to notmuch-tree-result-format."
   ;; We need to save the previous subject as it will get overwritten
   ;; by the insert-field calls.
   (let ((previous-subject notmuch-tree-previous-subject))
+(when (functionp notmuch-tree--insert-pre-fun)
+  (funcall notmuch-tree--insert-pre-fun msg))
 (insert (notmuch-tree-format-field-list (notmuch-tree-result-format) msg))
 (notmuch-tree-set-message-properties msg)
 (notmuch-tree-set-prop :previous-subject previous-subject)
@@ -1265,6 +1271,157 @@ search results and that are also tagged with the given 
TAG."
  nil
  notmuch-search-oldest-first)))
 
+;;; Tree outline mode
+ Custom variables
+(defcustom notmuch-tree-outline-mode-enabled nil
+  "Whether to automatically activate `notmuch-tree-outline-mode' in tree 
views."
+  :type 'boolean)
+
+(defcustom notmuch-tree-outline-visibility 'hide-others
+  "Default state of the forest outline for `notmuch-tree-outline-mode'.
+This variable controls the state of a forest initially and after
+a movement command.  If set to nil, all trees are displayed while
+the symbol hide-all indicates that all trees in the forest should
+be folded and hide-other that only the first one should be
+unfolded."
+  :type '(choice (const :tag "Show all" nil)
+(const :tag "Hide others" hide-others)
+(const :tag "Hide all" hide-all)))
+
+(defcustom notmuch-tree-outline-auto-close nil
+  "Close window when moving past the last message or before the first one."
+  :type 'boolean)
+
+ Helper functions
+(defun notmuch-tree-outline--enable-mode ()
+  (when notmuch-tree-outline-mode-enabled (notmuch-tree-outline-mode 1)))
+
+(add-hook 'notmuch-tree-mode-hook #'notmuch-tree-outline--enable-mode)
+
+(defun notmuch-tree-outline--set-visibility ()
+  (when (and notmuch-tree-outline-mode (not (looking-at-p "^$")))
+(cond ((eq notmuch-tree-outline-visibility 'hide-others)
+  (notmuch-tree-outline-hide-others))
+ ((eq notmuch-tree-outline-visibility 'hide-all)
+  (outline-hide-body)
+
+(defun notmuch-tree-outline--on-exit (proc)
+  (when (eq (process-st

[PATCH] emacs: new notmuch-tree-process-exit-functions

2022-08-20 Thread jao
Hook run when the tree insertion process finishes its job.

--
This patch supersedes , but
changing the new variable name.

Right now, it can be used for silly things like removing or changing
the the "End of search." hardcoded message in the tree buffer.  But
also for more sophisticated things like folding all threads in add-ons
like my outline mode for tree buffers (to be submitted).

Signed-off-by: jao 
---
 emacs/notmuch-tree.el | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index f63ac9a5..7ceddee2 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1084,6 +1084,12 @@ Complete list of currently available key bindings:
   (setq buffer-read-only t)
   (setq truncate-lines t))
 
+(defvar notmuch-tree-process-exit-functions nil
+  "Functions called when the process inserting a tree of results finishes.
+
+Functions in this list are called with one argument, the process
+object, and with the tree results buffer as the current buffer.")
+
 (defun notmuch-tree-process-sentinel (proc _msg)
   "Add a message to let user know when \"notmuch tree\" exits."
   (let ((buffer (process-buffer proc))
@@ -1102,7 +1108,8 @@ Complete list of currently available key bindings:
(insert "End of search results.")
(unless (= exit-status 0)
  (insert (format " (process returned %d)" exit-status)))
-   (insert "\n")
+   (insert "\n"
+ (run-hook-with-args 'notmuch-tree-process-exit-functions proc))
 
 (defun notmuch-tree-process-filter (proc string)
   "Process and filter the output of \"notmuch show\" for tree view."
-- 
2.37.2

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


Re: [PATCH] emacs: new notmuch-tree-process-hook

2022-08-17 Thread jao
how about notmuch-tree-process-sentinel-functions, or perhaps, since it's only 
called on exit, notmuch-tree-process-exit-functions?

jao
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH] emacs: new notmuch-tree-process-hook

2022-08-16 Thread jao
Hook run when the tree insertion process finishes its job.

--

Right now, it can be used for silly things like removing or changing
the the "End of search." hardcoded message in the tree buffer.  But
also for more sophisticated things like folding all threads in add-ons
like my outline mode for tree buffers (to be submitted).

Signed-off-by: jao 
---
 emacs/notmuch-tree.el | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index f63ac9a5..265f7c1f 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1084,6 +1084,12 @@ Complete list of currently available key bindings:
   (setq buffer-read-only t)
   (setq truncate-lines t))
 
+(defvar notmuch-tree-process-hook nil
+  "Hook executed when the process inserting a tree of results finishes.
+
+Functions in this hook are called with one argument, the process
+object, with the tree results buffer as the current buffer.")
+
 (defun notmuch-tree-process-sentinel (proc _msg)
   "Add a message to let user know when \"notmuch tree\" exits."
   (let ((buffer (process-buffer proc))
@@ -1102,7 +1108,8 @@ Complete list of currently available key bindings:
(insert "End of search results.")
(unless (= exit-status 0)
  (insert (format " (process returned %d)" exit-status)))
-   (insert "\n")
+   (insert "\n"
+ (run-hook-with-args 'notmuch-tree-process-hook proc))
 
 (defun notmuch-tree-process-filter (proc string)
   "Process and filter the output of \"notmuch show\" for tree view."
-- 
2.37.2

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v3] emacs: use message-dont-reply-to-names when composing replies

2022-06-08 Thread jao
notmuch-mua functions for replies now use the built-in customizable
variable message-dont-reply-to-names with the same semantics as
message-mode.

---

This version of the patch addresses stylistic issues according to review

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst   |  9 
 emacs/notmuch-mua.el| 19 
 test/T454-emacs-dont-reply-names.sh | 76 +
 3 files changed, 104 insertions(+)
 create mode 100755 test/T454-emacs-dont-reply-names.sh

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 78528785..970cd7b7 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -493,6 +493,15 @@ Sending Mail
:code:`compose-mail`.  To use ``notmuch`` for this, customize this
variable to the symbol :code:`notmuch-user-agent`.
 
+:index:`message-dont-reply-to-names`
+
+   When composing mail replies, Emacs's message mode uses the
+   variable :code:`message-dont-reply-to-names` to exclude
+   recipients matching a given collection of regular expressions
+   or satisfying an arbitrary predicate.  Notmuch's MUA inherits
+   this standard mechanism and will honour your customization of
+   this variable.
+
 Init File
 -
 
diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 0ae33127..0f9ef3c2 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -21,7 +21,10 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'subr-x))
+
 (require 'message)
+(require 'gmm-utils)
 (require 'mm-view)
 (require 'format-spec)
 
@@ -382,6 +385,21 @@ instead of `message-mode' and SWITCH-FUNCTION is 
mandatory."
 (erase-buffer)
 (notmuch-message-mode)))
 
+(defun notmuch-mua--remove-dont-reply-to-names ()
+  (when-let* ((nr (if (functionp message-dont-reply-to-names)
+ message-dont-reply-to-names
+   (gmm-regexp-concat message-dont-reply-to-names)))
+ (nr-filter
+  (if (functionp nr)
+  (lambda (mail) (and (not (funcall nr mail)) mail))
+(lambda (mail) (and (not (string-match-p nr mail)) mail)
+(dolist (header '("To" "Cc"))
+  (when-let ((v (message-fetch-field header)))
+   (let* ((tokens (mapcar #'string-trim (message-tokenize-header v)))
+  (good-tokens (delq nil (mapcar nr-filter tokens)))
+  (addr (and good-tokens (mapconcat #'identity good-tokens ", "
+ (message-replace-header header addr))
+
 (defun notmuch-mua-mail ( to subject other-headers _continue
   switch-function yank-action send-actions
   return-action  ignored)
@@ -422,6 +440,7 @@ moved to the \"To:\" header."
(message-this-is-mail t))
 (message-setup-1 headers yank-action send-actions return-action))
   (notmuch-fcc-header-setup)
+  (notmuch-mua--remove-dont-reply-to-names)
   (message-sort-headers)
   (message-hide-headers)
   (set-buffer-modified-p nil)
diff --git a/test/T454-emacs-dont-reply-names.sh 
b/test/T454-emacs-dont-reply-names.sh
new file mode 100755
index ..3a770177
--- /dev/null
+++ b/test/T454-emacs-dont-reply-names.sh
@@ -0,0 +1,76 @@
+#!/usr/bin/env bash
+
+test_description="message-dont-reply-to-names in emacs replies"
+. $(dirname "$0")/test-lib.sh || exit 1
+. $NOTMUCH_SRCDIR/test/test-lib-emacs.sh || exit 1
+
+EXPECTED=$NOTMUCH_SRCDIR/test/emacs-show.expected-output
+
+test_require_emacs
+
+add_email_corpus default
+
+test_begin_subtest "regular expression"
+test_emacs '(let ((message-dont-reply-to-names 
"notmuchmail\\|noreply\\|harvard"))
+ (notmuch-mua-new-reply
+   "id:20091117203301.gv3...@dottiness.seas.harvard.edu" nil t)
+ (test-visible-output "OUTPUT-FULL.raw"))'
+
+notmuch_dir_sanitize < OUTPUT-FULL.raw > OUTPUT-FULL
+head -6 OUTPUT-FULL > OUTPUT
+
+cat < EXPECTED
+From: Notmuch Test Suite 
+To: Mikhail Gusarov 
+Subject: Re: [notmuch] Working with Maildir storage?
+In-Reply-To: <20091117203301.gv3...@dottiness.seas.harvard.edu>
+Fcc: MAIL_DIR/sent
+--text follows this line--
+EOF
+
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "predicate"
+test_emacs '(let ((message-dont-reply-to-names
+  (lambda (m) (string-prefix-p "Mikhail" m
+ (notmuch-mua-new-reply
+   "id:20091117203301.gv3...@dottiness.seas.harvard.edu" nil t)
+ (test-visible-output "OUTPUT-FULL-PRED.raw"))'
+
+notmuch_dir_sanitize < OUTPUT-FULL-PRED.raw > OUTPUT-FULL-PRED
+head -7 OUTPUT-FULL-PRED > OUTPUT-PRED
+
+cat < EXPECTED-PRED
+From: Notmuch Test Suite 
+To: Lars Kellogg-Stedman 
+Cc: notmuch@notmuchmail.org
+Subject: Re: [notmuch] Working with Maildir storage?
+In-Reply-To: <20091117203301.gv3...@dottiness.s

[PATCH v2] emacs: use message-dont-reply-to-names when composing replies

2022-06-04 Thread jao
notmuch-mua functions for replies now use the built-in customizable
variable message-dont-reply-to-names with the same semantics as
message-mode.

---

This version of the patch adds more testing and ensures predicate values work

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst   |  9 
 emacs/notmuch-mua.el| 13 +
 test/T454-emacs-dont-reply-names.sh | 76 +
 3 files changed, 98 insertions(+)
 create mode 100755 test/T454-emacs-dont-reply-names.sh

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 78528785..970cd7b7 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -493,6 +493,15 @@ Sending Mail
:code:`compose-mail`.  To use ``notmuch`` for this, customize this
variable to the symbol :code:`notmuch-user-agent`.
 
+:index:`message-dont-reply-to-names`
+
+   When composing mail replies, Emacs's message mode uses the
+   variable :code:`message-dont-reply-to-names` to exclude
+   recipients matching a given collection of regular expressions
+   or satisfying an arbitrary predicate.  Notmuch's MUA inherits
+   this standard mechanism and will honour your customization of
+   this variable.
+
 Init File
 -
 
diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 0ae33127..865f4bb2 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -382,6 +382,18 @@ instead of `message-mode' and SWITCH-FUNCTION is 
mandatory."
 (erase-buffer)
 (notmuch-message-mode)))
 
+(defun notmuch-mua--remove-dont-reply-to-names ()
+  (when-let ((nr (message-dont-reply-to-names)))
+(let ((nr-filter (if (functionp nr)
+(lambda (mail) (unless (funcall nr mail) mail))
+  (lambda (mail) (unless (string-match-p nr mail) mail)
+  (dolist (header '("To" "Cc"))
+   (when-let ((v (message-fetch-field header)))
+ (let* ((v (mapcar #'string-trim (message-tokenize-header v)))
+(vs (delq nil (mapcar nr-filter v)))
+(v (when vs (mapconcat #'identity vs ", "
+   (message-replace-header header v)))
+
 (defun notmuch-mua-mail ( to subject other-headers _continue
   switch-function yank-action send-actions
   return-action  ignored)
@@ -422,6 +434,7 @@ moved to the \"To:\" header."
(message-this-is-mail t))
 (message-setup-1 headers yank-action send-actions return-action))
   (notmuch-fcc-header-setup)
+  (notmuch-mua--remove-dont-reply-to-names)
   (message-sort-headers)
   (message-hide-headers)
   (set-buffer-modified-p nil)
diff --git a/test/T454-emacs-dont-reply-names.sh 
b/test/T454-emacs-dont-reply-names.sh
new file mode 100755
index ..e31141f9
--- /dev/null
+++ b/test/T454-emacs-dont-reply-names.sh
@@ -0,0 +1,76 @@
+#!/usr/bin/env bash
+
+test_description="emacs reply"
+. $(dirname "$0")/test-lib.sh || exit 1
+. $NOTMUCH_SRCDIR/test/test-lib-emacs.sh || exit 1
+
+EXPECTED=$NOTMUCH_SRCDIR/test/emacs-show.expected-output
+
+test_require_emacs
+
+add_email_corpus default
+
+test_begin_subtest "regular expression"
+test_emacs '(let ((message-dont-reply-to-names 
"notmuchmail\\|noreply\\|harvard"))
+ (notmuch-mua-new-reply
+   "id:20091117203301.gv3...@dottiness.seas.harvard.edu" nil t)
+ (test-visible-output "OUTPUT-FULL.raw"))'
+
+notmuch_dir_sanitize < OUTPUT-FULL.raw > OUTPUT-FULL
+head -6 OUTPUT-FULL > OUTPUT
+
+cat < EXPECTED
+From: Notmuch Test Suite 
+To: Mikhail Gusarov 
+Subject: Re: [notmuch] Working with Maildir storage?
+In-Reply-To: <20091117203301.gv3...@dottiness.seas.harvard.edu>
+Fcc: MAIL_DIR/sent
+--text follows this line--
+EOF
+
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "predicate"
+test_emacs '(let ((message-dont-reply-to-names
+  (lambda (m) (string-prefix-p "Mikhail" m
+ (notmuch-mua-new-reply
+   "id:20091117203301.gv3...@dottiness.seas.harvard.edu" nil t)
+ (test-visible-output "OUTPUT-FULL-PRED.raw"))'
+
+notmuch_dir_sanitize < OUTPUT-FULL-PRED.raw > OUTPUT-FULL-PRED
+head -7 OUTPUT-FULL-PRED > OUTPUT-PRED
+
+cat < EXPECTED-PRED
+From: Notmuch Test Suite 
+To: Lars Kellogg-Stedman 
+Cc: notmuch@notmuchmail.org
+Subject: Re: [notmuch] Working with Maildir storage?
+In-Reply-To: <20091117203301.gv3...@dottiness.seas.harvard.edu>
+Fcc: MAIL_DIR/sent
+--text follows this line--
+EOF
+
+test_expect_equal_file EXPECTED-PRED OUTPUT-PRED
+
+test_begin_subtest "nil value"
+test_emacs '(let ((message-dont-reply-to-names nil))
+ (notmuch-mua-new-reply
+   "id:20091117203301.gv3...@dottiness.seas.harvard.edu" nil t)
+ (test-vi

[PATCH] emacs: use message-dont-reply-to-names when composing replies

2022-06-04 Thread jao
notmuch-mua functions for replies now use the built-in customizable
variable message-dont-reply-to-names with the same semantics as
message-mode.

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst   |  9 
 emacs/notmuch-mua.el| 13 
 test/T454-emacs-dont-reply-names.sh | 33 +
 3 files changed, 55 insertions(+)
 create mode 100755 test/T454-emacs-dont-reply-names.sh

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 78528785..970cd7b7 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -493,6 +493,15 @@ Sending Mail
:code:`compose-mail`.  To use ``notmuch`` for this, customize this
variable to the symbol :code:`notmuch-user-agent`.
 
+:index:`message-dont-reply-to-names`
+
+   When composing mail replies, Emacs's message mode uses the
+   variable :code:`message-dont-reply-to-names` to exclude
+   recipients matching a given collection of regular expressions
+   or satisfying an arbitrary predicate.  Notmuch's MUA inherits
+   this standard mechanism and will honour your customization of
+   this variable.
+
 Init File
 -
 
diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 0ae33127..6f2b9789 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -382,6 +382,18 @@ instead of `message-mode' and SWITCH-FUNCTION is 
mandatory."
 (erase-buffer)
 (notmuch-message-mode)))
 
+(defun notmuch-mua--remove-dont-reply-to-names ()
+  (when-let ((nr (message-dont-reply-to-names)))
+(let ((nr-filter (if (functionp nr)
+nr
+  (lambda (mail) (unless (string-match-p nr mail) mail)
+  (dolist (header '("To" "Cc"))
+   (when-let ((v (message-fetch-field header)))
+ (let* ((v (message-tokenize-header v))
+(vs (delq nil (mapcar nr-filter v)))
+(v (when vs (mapconcat #'string-trim vs ", "
+   (message-replace-header header v)))
+
 (defun notmuch-mua-mail ( to subject other-headers _continue
   switch-function yank-action send-actions
   return-action  ignored)
@@ -422,6 +434,7 @@ moved to the \"To:\" header."
(message-this-is-mail t))
 (message-setup-1 headers yank-action send-actions return-action))
   (notmuch-fcc-header-setup)
+  (notmuch-mua--remove-dont-reply-to-names)
   (message-sort-headers)
   (message-hide-headers)
   (set-buffer-modified-p nil)
diff --git a/test/T454-emacs-dont-reply-names.sh 
b/test/T454-emacs-dont-reply-names.sh
new file mode 100755
index ..64ae74af
--- /dev/null
+++ b/test/T454-emacs-dont-reply-names.sh
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+
+test_description="emacs reply"
+. $(dirname "$0")/test-lib.sh || exit 1
+. $NOTMUCH_SRCDIR/test/test-lib-emacs.sh || exit 1
+
+EXPECTED=$NOTMUCH_SRCDIR/test/emacs-show.expected-output
+
+test_require_emacs
+
+add_email_corpus default
+
+test_begin_subtest "not replying"
+test_emacs '(let ((message-dont-reply-to-names 
"notmuchmail\\|noreply\\|harvard"))
+ (notmuch-mua-new-reply
+   "id:20091117203301.gv3...@dottiness.seas.harvard.edu" nil t)
+ (test-visible-output "OUTPUT-FULL.raw"))'
+
+notmuch_dir_sanitize < OUTPUT-FULL.raw > OUTPUT-FULL
+head -6 OUTPUT-FULL > OUTPUT
+
+cat < EXPECTED
+From: Notmuch Test Suite 
+To: Mikhail Gusarov 
+Subject: Re: [notmuch] Working with Maildir storage?
+In-Reply-To: <20091117203301.gv3...@dottiness.seas.harvard.edu>
+Fcc: MAIL_DIR/sent
+--text follows this line--
+EOF
+
+test_expect_equal_file EXPECTED OUTPUT
+
+test_done
-- 
2.36.1

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v4 1/1] emacs: notmuch-show-header-line: allow format strings and functions

2022-06-01 Thread jao
If a string value is assigned to notmuch-show-header-line, it's used
as a format string to be passed passed to format-spec with `%s`
substituted by the message's subject.  If a function is given, it's
called with the subject as argument, and its return value used as
header line.

As before, t means displaying the subject and nil not using any header
line.

Signed-off-by: jao 
---
 emacs/notmuch-show.el | 46 ++-
 1 file changed, 37 insertions(+), 9 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 69f6c845..51b916ea 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -85,8 +85,30 @@ visible for any given message."
   :group 'notmuch-show)
 
 (defcustom notmuch-show-header-line t
-  "Show a header line with the current message's subject."
-  :type 'boolean
+  "Show a header line in notmuch show buffers.
+
+If t (the default), the header line will contain the current
+message's subject.
+
+If a string, this value is interpreted as a format string to be
+passed to `format-spec` with `%s` as the substitution variable
+for the message's subject.  E.g., to display the subject trimmed
+to a maximum of 80 columns, you could use \"%>-80s\" as format.
+
+If you assign to this variable a function, it will be called with
+the subject as argument, and the return value will be used as the
+header line format.  Since the function is called with the
+message buffer as the current buffer, it is also possible to
+access any other properties of the message, using for instance
+notmuch-show functions such as
+`notmuch-show-get-message-properties'.
+
+Finally, if this variabale is set to nil, no header is
+displayed."
+  :type '(choice (const :tag "No header" ni)
+ (const :tag "Subject" t)
+ (string :tag "Format")
+(function :tag "Function"))
   :group 'notmuch-show)
 
 (defcustom notmuch-show-relative-dates t
@@ -1313,6 +1335,18 @@ fallback if the prior matches no messages."
   (push (list thread "and (" context ")") queries))
 queries))
 
+(defun notmuch-show--header-line-format ()
+  "Compute the header line format of a notmuch-show buffer."
+  (when notmuch-show-header-line
+(let* ((s (notmuch-sanitize
+  (notmuch-show-strip-re (notmuch-show-get-subject
+  (subject (replace-regexp-in-string "%" "%%" s)))
+  (cond ((stringp notmuch-show-header-line)
+ (format-spec notmuch-show-header-line `((?s . ,subject
+   ((functionp notmuch-show-header-line)
+(funcall notmuch-show-header-line subject))
+   (notmuch-show-header-line subject)
+
 (defun notmuch-show--build-buffer ( state)
   "Display messages matching the current buffer context.
 
@@ -1343,13 +1377,7 @@ If no messages match the query return NIL."
   ;; display changes.
   (notmuch-show-mapc
(lambda () (notmuch-show-set-prop :orig-tags (notmuch-show-get-tags
-  ;; Set the header line to the subject of the first message.
-  (when notmuch-show-header-line
-   (setq header-line-format
- (replace-regexp-in-string "%" "%%"
-   (notmuch-sanitize
-(notmuch-show-strip-re
- (notmuch-show-get-subject))
+  (setq header-line-format (notmuch-show--header-line-format))
   (run-hooks 'notmuch-show-hook)
   (if state
  (notmuch-show-apply-state state)
-- 
2.36.1

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v4 0/1] notmuch-show-header-line: allow format strings and functions

2022-06-01 Thread jao
This one overrides id:20220518192956.1440103-1-...@gnu.org, by
improving the docstring.

jao (1):
  emacs: notmuch-show-header-line: allow format strings and functions

 emacs/notmuch-show.el | 46 ++-
 1 file changed, 37 insertions(+), 9 deletions(-)

--
2.36.1
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


notmuch-show-header-line: allow format strings and functions

2022-05-18 Thread jao
This one overrides id:20220516022039.551596-1-...@gnu.org, hopefully
using proper indentation, and refactoring the new functionality in a
separate function for clarity.


___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH] emacs: notmuch-show-header-line: allow format strings and functions

2022-05-18 Thread jao
If a string value is assigned to notmuch-show-header-line, it's used
as a format string to be passed passed to format-spec with `%s`
substituted by the message's subject.  If a function is given, it's
called with the subject as argument, and its return value used as
header line.

As before, t means displaying the subject and nil not using any header
line.

Signed-off-by: jao 
---
 emacs/notmuch-show.el | 42 +-
 1 file changed, 33 insertions(+), 9 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 69f6c845..266afbaa 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -85,8 +85,26 @@ visible for any given message."
   :group 'notmuch-show)
 
 (defcustom notmuch-show-header-line t
-  "Show a header line with the current message's subject."
-  :type 'boolean
+  "Show a header line in notmuch show buffers.
+
+If t (the default), the header line will contain the current
+message's subject.
+
+If a string, this value is interpreted as a format string to be
+passed to `format-spec` with `%s` as the substitution variable
+for the message's subject.  E.g., to display the subject trimmed
+to a maximum of 80 columns, you could use \"%>-80s\" as format.
+
+If you assign to this variable a function, the function will be
+called with the subject as argument and its return value used as
+the header line.
+
+Finally, if this variabale is set to nil, no header is
+displayed."
+  :type '(choice (const :tag "No header" ni)
+ (const :tag "Subject" t)
+ (string :tag "Format")
+(function :tag "Function"))
   :group 'notmuch-show)
 
 (defcustom notmuch-show-relative-dates t
@@ -1313,6 +1331,18 @@ fallback if the prior matches no messages."
   (push (list thread "and (" context ")") queries))
 queries))
 
+(defun notmuch-show--header-line-format ()
+  "Compute the header line format of a notmuch-show buffer."
+  (when notmuch-show-header-line
+(let* ((s (notmuch-sanitize
+  (notmuch-show-strip-re (notmuch-show-get-subject
+  (subject (replace-regexp-in-string "%" "%%" s)))
+  (cond ((stringp notmuch-show-header-line)
+ (format-spec notmuch-show-header-line `((?s . ,subject
+   ((functionp notmuch-show-header-line)
+(funcall notmuch-show-header-line subject))
+   (notmuch-show-header-line subject)
+
 (defun notmuch-show--build-buffer ( state)
   "Display messages matching the current buffer context.
 
@@ -1343,13 +1373,7 @@ If no messages match the query return NIL."
   ;; display changes.
   (notmuch-show-mapc
(lambda () (notmuch-show-set-prop :orig-tags (notmuch-show-get-tags
-  ;; Set the header line to the subject of the first message.
-  (when notmuch-show-header-line
-   (setq header-line-format
- (replace-regexp-in-string "%" "%%"
-   (notmuch-sanitize
-(notmuch-show-strip-re
- (notmuch-show-get-subject))
+  (setq header-line-format (notmuch-show--header-line-format))
   (run-hooks 'notmuch-show-hook)
   (if state
  (notmuch-show-apply-state state)
-- 
2.36.1

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v2 1/1] emacs: notmuch-show-header-line: allow format strings and functions

2022-05-15 Thread jao
If a string value is assigned to notmuch-show-header-line, it's used
as a format string to be passed passed to format-spec with `%s`
substituted by the message's subject.  If a function is given, it's
called with the subject as argument, and its return value used as
header line.

As before, t means displaying the subject and nil not using any header
line.

Signed-off-by: jao 
---
 emacs/notmuch-show.el | 37 ++---
 1 file changed, 30 insertions(+), 7 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 7c1f02c9..79599480 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -85,8 +85,26 @@ visible for any given message."
   :group 'notmuch-show)
 
 (defcustom notmuch-show-header-line t
-  "Show a header line with the current message's subject."
-  :type 'boolean
+  "Show a header line in notmuch show buffers.
+
+If t (the default), the header line will contain the current
+message's subject.
+
+If a string, this value is interpreted as a format string to be
+passed to `format-spec` with `%s` as the substitution variable
+for the message's subject.  E.g., to display the subject trimmed
+to a maximum of 80 columns, you could use \"%>-80s\" as format.
+
+If you assign to this variable a function, the function will be
+called with the subject as argument and its return value used as
+the header line.
+
+Finally, if this variabale is set to nil, no header is
+displayed."
+  :type '(choice (const :tag "No header" ni)
+ (const :tag "Subject" t)
+ (string :tag "Format")
+(function :tag "Function"))
   :group 'notmuch-show)
 
 (defcustom notmuch-show-relative-dates t
@@ -1351,11 +1369,16 @@ If no messages match the query return NIL."
(lambda () (notmuch-show-set-prop :orig-tags (notmuch-show-get-tags
   ;; Set the header line to the subject of the first message.
   (when notmuch-show-header-line
-   (setq header-line-format
- (replace-regexp-in-string "%" "%%"
-   (notmuch-sanitize
-(notmuch-show-strip-re
- (notmuch-show-get-subject))
+(let* ((s (replace-regexp-in-string "%" "%%"
+(notmuch-sanitize
+ (notmuch-show-strip-re
+  (notmuch-show-get-subject)
+   (h (cond ((stringp notmuch-show-header-line)
+ (format-spec notmuch-show-header-line `((?s . ,s
+   ((functionp notmuch-show-header-line)
+(funcall notmuch-show-header-line s))
+   (notmuch-show-header-line s
+  (setq header-line-format h)))
   (run-hooks 'notmuch-show-hook)
   (if state
  (notmuch-show-apply-state state)
-- 
2.36.1

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v2 0/1] notmuch-show-header-line: allow format strings and functions

2022-05-15 Thread jao
This one extends the previous version that accepted a format string by
also accepting an arbitrary function.

jao (1):
  emacs: notmuch-show-header-line: allow format strings and functions

 emacs/notmuch-show.el | 37 ++---
 1 file changed, 30 insertions(+), 7 deletions(-)

--
2.36.1
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH] emacs: notmuch-show-header-line: allow format-spec format

2022-04-25 Thread jao
If a string value is assigned to notmuch-show-header-line, it's used
as a format string to be passed passed to format-spec with `%s`
substituted by the message's subject.  As before, t means displaying
the subject and nil not using any header line.

Signed-off-by: jao 
---
 emacs/notmuch-show.el | 27 ---
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 7c1f02c9..f31c15e6 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -85,8 +85,18 @@ visible for any given message."
   :group 'notmuch-show)
 
 (defcustom notmuch-show-header-line t
-  "Show a header line with the current message's subject."
-  :type 'boolean
+  "Show a header line in notmuch show buffers.
+
+If t (the default), the header line will contain the current
+message's subject. If a string, this value is interpreted as a
+format string to be passed to `format-spec` with `%s` as the
+substitution variable for the message's subject.  E.g., to
+display the subject trimmed to a maximum of 80 columns, you could
+use \"%>-80s\" as format.  If this variabale is set to nil, no
+header is displayed."
+  :type '(choice (const :tag "No header" ni)
+ (const :tag "Subject" t)
+ (string :tag "Format"))
   :group 'notmuch-show)
 
 (defcustom notmuch-show-relative-dates t
@@ -1351,11 +1361,14 @@ If no messages match the query return NIL."
(lambda () (notmuch-show-set-prop :orig-tags (notmuch-show-get-tags
   ;; Set the header line to the subject of the first message.
   (when notmuch-show-header-line
-   (setq header-line-format
- (replace-regexp-in-string "%" "%%"
-   (notmuch-sanitize
-(notmuch-show-strip-re
- (notmuch-show-get-subject))
+(let* ((s (replace-regexp-in-string "%" "%%"
+(notmuch-sanitize
+ (notmuch-show-strip-re
+  (notmuch-show-get-subject)
+   (h (cond ((stringp notmuch-show-header-line)
+ (format-spec notmuch-show-header-line `((?s . ,s
+   (notmuch-show-header-line s
+  (setq header-line-format h)))
   (run-hooks 'notmuch-show-hook)
   (if state
  (notmuch-show-apply-state state)
-- 
2.36.0

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v7] emacs: customizable names for search buffers

2022-01-23 Thread jao
Customizable names for buffers presenting search results, via two
custom variables (notmuch-search-buffer-name-format and
notmuch-saved-search-buffer-name-format), defaulting to values
currently used for plain searches and including too tree and
unthreaded search buffers.

---

This is a much improved version of the patch in
id:20220108204121.1053932-1-...@gnu.org, according to discussion on
that thread.

This version includes documentation in notmuch-emacs.rst for the new
customizable variables (id:87v8yafe1a@tethera.net).

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst  | 10 
 emacs/notmuch-hello.el | 11 +
 emacs/notmuch-tree.el  | 10 
 emacs/notmuch.el   | 53 ++
 4 files changed, 65 insertions(+), 19 deletions(-)

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index fed619b7..049c7551 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -175,6 +175,16 @@ variables.
 :index:`notmuch-search-oldest-first`
 Display the oldest threads at the top of the buffer
 
+It is also possible to costumize how the name of buffers containing
+search results is formatted using the following variables:
+
+:index:`notmuch-search-buffer-name-format`
+   |docstring::notmuch-search-buffer-name-format|
+
+:index:`notmuch-saved-search-buffer-name-format`
+   |docstring::notmuch-saved-search-buffer-name-format|
+
+
 .. _notmuch-show:
 
 notmuch-show
diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 581e7f3a..beb25382 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -486,11 +486,14 @@ diagonal."
 (defun notmuch-hello-widget-search (widget  _ignore)
   (cl-case (widget-get widget :notmuch-search-type)
(tree
-(notmuch-tree (widget-get widget :notmuch-search-terms)
- nil nil nil nil nil nil
- (widget-get widget :notmuch-search-oldest-first)))
+(let ((n (notmuch-search-format-buffer-name (widget-value widget) "tree" 
t)))
+  (notmuch-tree (widget-get widget :notmuch-search-terms)
+   nil nil n nil nil nil
+   (widget-get widget :notmuch-search-oldest-first
(unthreaded
-(notmuch-unthreaded (widget-get widget :notmuch-search-terms)))
+(let ((n (notmuch-search-format-buffer-name (widget-value widget)
+   "unthreaded" t)))
+  (notmuch-unthreaded (widget-get widget :notmuch-search-terms) nil nil 
n)))
(t
 (notmuch-search (widget-get widget :notmuch-search-terms)
(widget-get widget :notmuch-search-oldest-first)
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index d7486904..303c6fad 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1191,11 +1191,11 @@ The arguments are:
 (setq query (notmuch-read-query (concat "Notmuch "
(if unthreaded "unthreaded " "tree 
")
"view search: "
-  (let ((buffer (get-buffer-create (generate-new-buffer-name
-   (or buffer-name
-   (concat "*notmuch-"
-   (if unthreaded "unthreaded-" 
"tree-")
-   query "*")
+  (let* ((name
+ (or buffer-name
+ (notmuch-search-buffer-title query
+  (if unthreaded "unthreaded" 
"tree"
+(buffer (get-buffer-create (generate-new-buffer-name name)))
(inhibit-read-only t))
 (pop-to-buffer-same-window buffer))
   ;; Don't track undo information for this buffer
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 85a54706..6abb17ff 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -915,7 +915,39 @@ See `notmuch-tag' for information on the format of 
TAG-CHANGES."
  (notmuch-search-get-tags-region (point-min) (point-max)) "Tag all")))
   (notmuch-search-tag tag-changes (point-min) (point-max) t))
 
-(defun notmuch-search-buffer-title (query)
+(defcustom notmuch-search-buffer-name-format "*notmuch-%t-%s*"
+  "Format for the name of search results buffers.
+
+In this spec, %s will be replaced by a description of the search
+query and %t by its type (search, tree or unthreaded).  The
+buffer name is formatted using `format-spec': see its docstring
+for additional parameters for the s and t format specifiers.
+
+See also `notmuch-saved-search-buffer-name-format'"
+  :type 'string
+  :group 'notmuch-search)
+
+(defcustom notmuch-saved-search-buffer-name-format "*notmuch-saved-%t-%s*"
+  "Format for the name of search results buffers for saved searches.
+
+In this spec, %s will be replaced by the saved search name and %t
+by it

[PATCH v6] emacs: customizable names for search buffers

2022-01-16 Thread jao
Customizable names for buffers presenting search results, via two
custom variables (notmuch-search-buffer-name-format and
notmuch-saved-search-buffer-name-format), defaulting to values
currently used for plain searches and including too tree and
unthreaded search buffers.

---

This is a much improved version of the patch in
id:20220108204121.1053932-1-...@gnu.org, according to discussion on
that thread.

This version always uses format-spec, since it's available since
ancient times (see discussion in id:875yqjmgaq@kyleam.com).

Signed-off-by: jao 
---
 emacs/notmuch-hello.el | 11 +
 emacs/notmuch-tree.el  | 10 
 emacs/notmuch.el   | 53 ++
 3 files changed, 55 insertions(+), 19 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index fc007c4c..44341dd6 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -486,11 +486,14 @@ diagonal."
 (defun notmuch-hello-widget-search (widget  _ignore)
   (cl-case (widget-get widget :notmuch-search-type)
(tree
-(notmuch-tree (widget-get widget :notmuch-search-terms)
- nil nil nil nil nil nil
- (widget-get widget :notmuch-search-oldest-first)))
+(let ((n (notmuch-search-format-buffer-name (widget-value widget) "tree" 
t)))
+  (notmuch-tree (widget-get widget :notmuch-search-terms)
+   nil nil n nil nil nil
+   (widget-get widget :notmuch-search-oldest-first
(unthreaded
-(notmuch-unthreaded (widget-get widget :notmuch-search-terms)))
+(let ((n (notmuch-search-format-buffer-name (widget-value widget)
+   "unthreaded" t)))
+  (notmuch-unthreaded (widget-get widget :notmuch-search-terms) nil nil 
n)))
(t
 (notmuch-search (widget-get widget :notmuch-search-terms)
(widget-get widget :notmuch-search-oldest-first)
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index d7486904..303c6fad 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1191,11 +1191,11 @@ The arguments are:
 (setq query (notmuch-read-query (concat "Notmuch "
(if unthreaded "unthreaded " "tree 
")
"view search: "
-  (let ((buffer (get-buffer-create (generate-new-buffer-name
-   (or buffer-name
-   (concat "*notmuch-"
-   (if unthreaded "unthreaded-" 
"tree-")
-   query "*")
+  (let* ((name
+ (or buffer-name
+ (notmuch-search-buffer-title query
+  (if unthreaded "unthreaded" 
"tree"
+(buffer (get-buffer-create (generate-new-buffer-name name)))
(inhibit-read-only t))
 (pop-to-buffer-same-window buffer))
   ;; Don't track undo information for this buffer
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 85a54706..ef3af899 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -915,7 +915,39 @@ See `notmuch-tag' for information on the format of 
TAG-CHANGES."
  (notmuch-search-get-tags-region (point-min) (point-max)) "Tag all")))
   (notmuch-search-tag tag-changes (point-min) (point-max) t))
 
-(defun notmuch-search-buffer-title (query)
+(defcustom notmuch-search-buffer-name-format "*notmuch-%t-%s*"
+  "Format for the name of search results buffers.
+
+In this spec, %s will be replaced by a description of the search
+query and %t by its type (search, tree or unthreaded).  The
+buffer name is formatted using `format-spec': see its docstring
+for additional parameters for the s and t format specifiers.
+
+See also `notmuch-saved-search-buffer-name-format'"
+  :type 'string
+  :group 'notmuch-search)
+
+(defcustom notmuch-saved-search-buffer-name-format "*notmuch-saved-%t-%s*"
+  "Format for the name of search results buffers.
+
+In this spec, %s will be replaced by the saved search name and %t
+by its type (search, tree or unthreaded).  The buffer name is
+formatted using `format-spec': see its docstring for additional
+parameters for the s and t format specifiers.
+
+See also `notmuch-search-buffer-name-format'"
+  :type 'string
+  :group 'notmuch-search)
+
+(defun notmuch-search-format-buffer-name (query type saved)
+  "Compose a buffer name for the given QUERY, TYPE (search, tree,
+unthreaded) and whether it's SAVED (t or nil)."
+  (let ((fmt (if saved
+notmuch-saved-search-buffer-name-format
+  notmuch-search-buffer-name-format)))
+(format-spec fmt `((?t . ,(or type "search")) (?s . ,query)
+
+(defun notmuch-search-buffer-title (que

[PATCH v5] emacs: customizable names for search buffers

2022-01-14 Thread jao
Customizable names for buffers presenting search results, via two
custom variables (notmuch-search-buffer-name-format and
notmuch-saved-search-buffer-name-format), defaulting to values
currently used for plain searches and including too tree and
unthreaded search buffers.

---

This is a much improved version of the patch in
id:20220108204121.1053932-1-...@gnu.org, according to discussion on
that thread.

This version fixes the regexp for detecting %t in emacs < 27, skipping
word boundary checks.

Signed-off-by: jao 
---
 emacs/notmuch-hello.el | 11 +
 emacs/notmuch-tree.el  | 10 -
 emacs/notmuch.el   | 51 +-
 3 files changed, 53 insertions(+), 19 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index fc007c4c..44341dd6 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -486,11 +486,14 @@ diagonal."
 (defun notmuch-hello-widget-search (widget  _ignore)
   (cl-case (widget-get widget :notmuch-search-type)
(tree
-(notmuch-tree (widget-get widget :notmuch-search-terms)
- nil nil nil nil nil nil
- (widget-get widget :notmuch-search-oldest-first)))
+(let ((n (notmuch-search-format-buffer-name (widget-value widget) "tree" 
t)))
+  (notmuch-tree (widget-get widget :notmuch-search-terms)
+   nil nil n nil nil nil
+   (widget-get widget :notmuch-search-oldest-first
(unthreaded
-(notmuch-unthreaded (widget-get widget :notmuch-search-terms)))
+(let ((n (notmuch-search-format-buffer-name (widget-value widget)
+   "unthreaded" t)))
+  (notmuch-unthreaded (widget-get widget :notmuch-search-terms) nil nil 
n)))
(t
 (notmuch-search (widget-get widget :notmuch-search-terms)
(widget-get widget :notmuch-search-oldest-first)
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index d7486904..303c6fad 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1191,11 +1191,11 @@ The arguments are:
 (setq query (notmuch-read-query (concat "Notmuch "
(if unthreaded "unthreaded " "tree 
")
"view search: "
-  (let ((buffer (get-buffer-create (generate-new-buffer-name
-   (or buffer-name
-   (concat "*notmuch-"
-   (if unthreaded "unthreaded-" 
"tree-")
-   query "*")
+  (let* ((name
+ (or buffer-name
+ (notmuch-search-buffer-title query
+  (if unthreaded "unthreaded" 
"tree"
+(buffer (get-buffer-create (generate-new-buffer-name name)))
(inhibit-read-only t))
 (pop-to-buffer-same-window buffer))
   ;; Don't track undo information for this buffer
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 85a54706..8c7eb519 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -915,7 +915,37 @@ See `notmuch-tag' for information on the format of 
TAG-CHANGES."
  (notmuch-search-get-tags-region (point-min) (point-max)) "Tag all")))
   (notmuch-search-tag tag-changes (point-min) (point-max) t))
 
-(defun notmuch-search-buffer-title (query)
+(defcustom notmuch-search-buffer-name-format "*notmuch-%t-%s*"
+  "Format for the name of search results buffers.
+
+In this spec, %s will be replaced by a description of the search
+query and %t by its type (search, tree or unthreaded).
+
+See also `notmuch-saved-search-buffer-name-format'"
+  :type 'string
+  :group 'notmuch-search)
+
+(defcustom notmuch-saved-search-buffer-name-format "*notmuch-saved-%t-%s*"
+  "Format for the name of search results buffers.
+
+In this spec, %s will be replaced by the saved search name and %t
+by its type (search, tree or unthreaded).
+
+See also `notmuch-search-buffer-name-format'"
+  :type 'string
+  :group 'notmuch-search)
+
+(defun notmuch-search-format-buffer-name (query type saved)
+  "Compose a buffer name for the given QUERY, TYPE (search, tree,
+unthreaded) and whether it's SAVED (t or nil)."
+  (let ((fmt (if saved
+notmuch-saved-search-buffer-name-format
+  notmuch-search-buffer-name-format)))
+(if (fboundp 'format-spec)
+   (format-spec fmt `((?t . ,(or type "search")) (?s . ,query
+(format (replace-regexp-in-string "%t" (or type "search") fmt) query)))
+
+(defun notmuch-search-buffer-title (query  type)
   "Returns the title for a buffer with notmuch search results."
   (let* ((saved-search
  (let (longest
@@ -930,19 +960,20 @@ See `notmuch

Re: FYI: emacs / notmuch-search-edit-search

2022-01-12 Thread jao
hi,

On Wed, Jan 12 2022, Tomi Ollila wrote:

> Hi all
> I've had this for a while in .emacs.d/notmuch-config.el
>
> ---
>
> (defun notmuch-search-edit-search ()
>   "Edit current search"
>   (interactive)
>   (notmuch-search (read-from-minibuffer
>  "Edit search: " notmuch-search-query-string)
> notmuch-search-oldest-first))
>
> (define-key notmuch-search-mode-map "e" #'notmuch-search-edit-search)
>
> ---

this looks useful indeed.  if added, please consider adding also a
notmuch-tree counterpart.  in notmuch-tree-mode-map, "e" is taken for
notmuch-tree-resume-message, so perhaps "E" could be used instead,
possibly in both maps for consistency.

untested:

--8<---cut here---start->8---
(defun notmuch-tree-edit-search (query)
  "Edit the current search"
  (interactive (list (read-from-minibuffer "Edit search: "
   notmuch-search-query-string)))
  (let ((notmuch-show-process-crypto (notmuch-tree--message-process-crypto)))
(notmuch-tree-close-message-window)
(notmuch-tree query
  notmuch-tree-query-context
  nil
  nil
  nil
  notmuch-tree-unthreaded
  nil
  notmuch-search-oldest-first)))

(define-key notmuch-tree-mode-map "E" #'notmuch-tree-edit-search)
--8<---cut here---end--->8---

cheers,
jao
-- 
Configuring Emacs is more of a lifestyle choice than a task that one
completes.  – Stephen A. Ramsey
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v4] emacs: customizable names for search buffers

2022-01-10 Thread jao
Customizable names for buffers presenting search results, via two
custom variables (notmuch-search-buffer-name-format and
notmuch-saved-search-buffer-name-format), defaulting to values
currently used for plain searches and including too tree and
unthreaded search buffers.

---

This is a much improved version of the patch in
id:20220108204121.1053932-1-...@gnu.org, according to discussion on
that thread.

This version fixes a doc string.

Signed-off-by: jao 
---
 emacs/notmuch-hello.el | 11 +
 emacs/notmuch-tree.el  | 10 -
 emacs/notmuch.el   | 51 +-
 3 files changed, 53 insertions(+), 19 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index fc007c4c..44341dd6 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -486,11 +486,14 @@ diagonal."
 (defun notmuch-hello-widget-search (widget  _ignore)
   (cl-case (widget-get widget :notmuch-search-type)
(tree
-(notmuch-tree (widget-get widget :notmuch-search-terms)
- nil nil nil nil nil nil
- (widget-get widget :notmuch-search-oldest-first)))
+(let ((n (notmuch-search-format-buffer-name (widget-value widget) "tree" 
t)))
+  (notmuch-tree (widget-get widget :notmuch-search-terms)
+   nil nil n nil nil nil
+   (widget-get widget :notmuch-search-oldest-first
(unthreaded
-(notmuch-unthreaded (widget-get widget :notmuch-search-terms)))
+(let ((n (notmuch-search-format-buffer-name (widget-value widget)
+   "unthreaded" t)))
+  (notmuch-unthreaded (widget-get widget :notmuch-search-terms) nil nil 
n)))
(t
 (notmuch-search (widget-get widget :notmuch-search-terms)
(widget-get widget :notmuch-search-oldest-first)
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index d7486904..303c6fad 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1191,11 +1191,11 @@ The arguments are:
 (setq query (notmuch-read-query (concat "Notmuch "
(if unthreaded "unthreaded " "tree 
")
"view search: "
-  (let ((buffer (get-buffer-create (generate-new-buffer-name
-   (or buffer-name
-   (concat "*notmuch-"
-   (if unthreaded "unthreaded-" 
"tree-")
-   query "*")
+  (let* ((name
+ (or buffer-name
+ (notmuch-search-buffer-title query
+  (if unthreaded "unthreaded" 
"tree"
+(buffer (get-buffer-create (generate-new-buffer-name name)))
(inhibit-read-only t))
 (pop-to-buffer-same-window buffer))
   ;; Don't track undo information for this buffer
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 85a54706..afb0a115 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -915,7 +915,37 @@ See `notmuch-tag' for information on the format of 
TAG-CHANGES."
  (notmuch-search-get-tags-region (point-min) (point-max)) "Tag all")))
   (notmuch-search-tag tag-changes (point-min) (point-max) t))
 
-(defun notmuch-search-buffer-title (query)
+(defcustom notmuch-search-buffer-name-format "*notmuch-%t-%s*"
+  "Format for the name of search results buffers.
+
+In this spec, %s will be replaced by a description of the search
+query and %t by its type (search, tree or unthreaded).
+
+See also `notmuch-saved-search-buffer-name-format'"
+  :type 'string
+  :group 'notmuch-search)
+
+(defcustom notmuch-saved-search-buffer-name-format "*notmuch-saved-%t-%s*"
+  "Format for the name of search results buffers.
+
+In this spec, %s will be replaced by the saved search name and %t
+by its type (search, tree or unthreaded).
+
+See also `notmuch-search-buffer-name-format'"
+  :type 'string
+  :group 'notmuch-search)
+
+(defun notmuch-search-format-buffer-name (query type saved)
+  "Compose a buffer name for the given QUERY, TYPE (search, tree,
+unthreaded) and whether it's SAVED (t or nil)."
+  (let ((fmt (if saved
+notmuch-saved-search-buffer-name-format
+  notmuch-search-buffer-name-format)))
+(if (fboundp 'format-spec)
+   (format-spec fmt `((?t . ,(or type "search")) (?s . ,query
+(format (replace-regexp-in-string "\\b%t\\b" (or type "search") fmt) 
query)))
+
+(defun notmuch-search-buffer-title (query  type)
   "Returns the title for a buffer with notmuch search results."
   (let* ((saved-search
  (let (longest
@@ -930,19 +960,20 @@ See `notmuch-tag' for information on the format of 
TAG-CHA

[PATCH v3] emacs: customizable names for search buffers

2022-01-10 Thread jao
Customizable names for buffers presenting search results, via two
custom variables (notmuch-search-buffer-name-format and
notmuch-saved-search-buffer-name-format), defaulting to values
currently used for plain searches and including too tree and
unthreaded search buffers.

---

This is a much improved version of the patch in
id:20220108204121.1053932-1-...@gnu.org, according to discussion on
that thread.  This version just squashes together the two patches in v2.

Signed-off-by: jao 
---
 emacs/notmuch-hello.el | 11 ++
 emacs/notmuch-tree.el  | 10 -
 emacs/notmuch.el   | 50 +-
 3 files changed, 52 insertions(+), 19 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index fc007c4c..44341dd6 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -486,11 +486,14 @@ diagonal."
 (defun notmuch-hello-widget-search (widget  _ignore)
   (cl-case (widget-get widget :notmuch-search-type)
(tree
-(notmuch-tree (widget-get widget :notmuch-search-terms)
- nil nil nil nil nil nil
- (widget-get widget :notmuch-search-oldest-first)))
+(let ((n (notmuch-search-format-buffer-name (widget-value widget) "tree" 
t)))
+  (notmuch-tree (widget-get widget :notmuch-search-terms)
+   nil nil n nil nil nil
+   (widget-get widget :notmuch-search-oldest-first
(unthreaded
-(notmuch-unthreaded (widget-get widget :notmuch-search-terms)))
+(let ((n (notmuch-search-format-buffer-name (widget-value widget)
+   "unthreaded" t)))
+  (notmuch-unthreaded (widget-get widget :notmuch-search-terms) nil nil 
n)))
(t
 (notmuch-search (widget-get widget :notmuch-search-terms)
(widget-get widget :notmuch-search-oldest-first)
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index d7486904..303c6fad 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1191,11 +1191,11 @@ The arguments are:
 (setq query (notmuch-read-query (concat "Notmuch "
(if unthreaded "unthreaded " "tree 
")
"view search: "
-  (let ((buffer (get-buffer-create (generate-new-buffer-name
-   (or buffer-name
-   (concat "*notmuch-"
-   (if unthreaded "unthreaded-" 
"tree-")
-   query "*")
+  (let* ((name
+ (or buffer-name
+ (notmuch-search-buffer-title query
+  (if unthreaded "unthreaded" 
"tree"
+(buffer (get-buffer-create (generate-new-buffer-name name)))
(inhibit-read-only t))
 (pop-to-buffer-same-window buffer))
   ;; Don't track undo information for this buffer
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 85a54706..a30e3334 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -915,7 +915,36 @@ See `notmuch-tag' for information on the format of 
TAG-CHANGES."
  (notmuch-search-get-tags-region (point-min) (point-max)) "Tag all")))
   (notmuch-search-tag tag-changes (point-min) (point-max) t))
 
-(defun notmuch-search-buffer-title (query)
+(defcustom notmuch-search-buffer-name-format "*notmuch-%t-%s*"
+  "Format for the name of search results buffers.
+
+In this spec, %s will be replaced by a description of the search
+query and %t by its type (search, tree or unthreaded).
+
+See also `notmuch-saved-search-buffer-name-format'"
+  :type 'string
+  :group 'notmuch-search)
+
+(defcustom notmuch-saved-search-buffer-name-format "*notmuch-saved-%t-%s*"
+  "Format for the name of search results buffers.
+
+In this spec, %s will be replaced by the saved search name and %t
+by its type (search, tree or unthreaded).
+
+See also `notmuch-search-buffer-name-format'"
+  :type 'string
+  :group 'notmuch-search)
+
+(defun notmuch-search-format-buffer-name (query type saved)
+  "Use the FMT spec to provide a query buffer name."
+  (let ((fmt (if saved
+notmuch-saved-search-buffer-name-format
+  notmuch-search-buffer-name-format)))
+(if (fboundp 'format-spec)
+   (format-spec fmt `((?t . ,(or type "search")) (?s . ,query
+(format (replace-regexp-in-string "\\b%t\\b" (or type "search") fmt) 
query)))
+
+(defun notmuch-search-buffer-title (query  type)
   "Returns the title for a buffer with notmuch search results."
   (let* ((saved-search
  (let (longest
@@ -930,19 +959,20 @@ See `notmuch-tag' for information on the format of 
TAG-CHANGES."
 do (setq long

[PATCH v2 2/2] emacs: customizable names for search buffers

2022-01-10 Thread jao
Customizable names for buffers presenting search results, via two
custom variables (notmuch-search-buffer-name-format and
notmuch-saved-search-buffer-name-format), defaulting to values
currently used for plain searches and including too tree and
unthreaded search buffers.

---

This is a much improved version of the patch in
id:20220108204121.1053932-1-...@gnu.org, according to discussion on
that thread.

Signed-off-by: jao 
---
 emacs/notmuch-hello.el | 11 ++
 emacs/notmuch-tree.el  | 10 -
 emacs/notmuch.el   | 50 +-
 3 files changed, 52 insertions(+), 19 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 9f42a90b..44341dd6 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -486,11 +486,14 @@ diagonal."
 (defun notmuch-hello-widget-search (widget  _ignore)
   (cl-case (widget-get widget :notmuch-search-type)
(tree
-(notmuch-tree (widget-get widget :notmuch-search-terms)
- nil nil (widget-value widget) nil nil nil
- (widget-get widget :notmuch-search-oldest-first)))
+(let ((n (notmuch-search-format-buffer-name (widget-value widget) "tree" 
t)))
+  (notmuch-tree (widget-get widget :notmuch-search-terms)
+   nil nil n nil nil nil
+   (widget-get widget :notmuch-search-oldest-first
(unthreaded
-(notmuch-unthreaded (widget-get widget :notmuch-search-terms)))
+(let ((n (notmuch-search-format-buffer-name (widget-value widget)
+   "unthreaded" t)))
+  (notmuch-unthreaded (widget-get widget :notmuch-search-terms) nil nil 
n)))
(t
 (notmuch-search (widget-get widget :notmuch-search-terms)
(widget-get widget :notmuch-search-oldest-first)
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index d7486904..303c6fad 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1191,11 +1191,11 @@ The arguments are:
 (setq query (notmuch-read-query (concat "Notmuch "
(if unthreaded "unthreaded " "tree 
")
"view search: "
-  (let ((buffer (get-buffer-create (generate-new-buffer-name
-   (or buffer-name
-   (concat "*notmuch-"
-   (if unthreaded "unthreaded-" 
"tree-")
-   query "*")
+  (let* ((name
+ (or buffer-name
+ (notmuch-search-buffer-title query
+  (if unthreaded "unthreaded" 
"tree"
+(buffer (get-buffer-create (generate-new-buffer-name name)))
(inhibit-read-only t))
 (pop-to-buffer-same-window buffer))
   ;; Don't track undo information for this buffer
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 85a54706..a30e3334 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -915,7 +915,36 @@ See `notmuch-tag' for information on the format of 
TAG-CHANGES."
  (notmuch-search-get-tags-region (point-min) (point-max)) "Tag all")))
   (notmuch-search-tag tag-changes (point-min) (point-max) t))
 
-(defun notmuch-search-buffer-title (query)
+(defcustom notmuch-search-buffer-name-format "*notmuch-%t-%s*"
+  "Format for the name of search results buffers.
+
+In this spec, %s will be replaced by a description of the search
+query and %t by its type (search, tree or unthreaded).
+
+See also `notmuch-saved-search-buffer-name-format'"
+  :type 'string
+  :group 'notmuch-search)
+
+(defcustom notmuch-saved-search-buffer-name-format "*notmuch-saved-%t-%s*"
+  "Format for the name of search results buffers.
+
+In this spec, %s will be replaced by the saved search name and %t
+by its type (search, tree or unthreaded).
+
+See also `notmuch-search-buffer-name-format'"
+  :type 'string
+  :group 'notmuch-search)
+
+(defun notmuch-search-format-buffer-name (query type saved)
+  "Use the FMT spec to provide a query buffer name."
+  (let ((fmt (if saved
+notmuch-saved-search-buffer-name-format
+  notmuch-search-buffer-name-format)))
+(if (fboundp 'format-spec)
+   (format-spec fmt `((?t . ,(or type "search")) (?s . ,query
+(format (replace-regexp-in-string "\\b%t\\b" (or type "search") fmt) 
query)))
+
+(defun notmuch-search-buffer-title (query  type)
   "Returns the title for a buffer with notmuch search results."
   (let* ((saved-search
  (let (longest
@@ -930,19 +959,20 @@ See `notmuch-tag' for information on the format of 
TAG-CHANGES."
 do (setq longest tuple))
longest

[PATCH v2 1/2] emacs: use query name for tree saved-search buffer names

2022-01-10 Thread jao
This simply mimics what we already do for non-tree searches, and makes
up for nicer buffer names.  Note that this patch only applies to
queries not coming from a search widget in the hello buffer.

Signed-off-by: jao 
---
 emacs/notmuch-hello.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index fc007c4c..9f42a90b 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -487,7 +487,7 @@ diagonal."
   (cl-case (widget-get widget :notmuch-search-type)
(tree
 (notmuch-tree (widget-get widget :notmuch-search-terms)
- nil nil nil nil nil nil
+ nil nil (widget-value widget) nil nil nil
  (widget-get widget :notmuch-search-oldest-first)))
(unthreaded
 (notmuch-unthreaded (widget-get widget :notmuch-search-terms)))
-- 
2.34.1

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v2] emacs: make header line in notmuch-show buffers optional

2022-01-09 Thread jao
New notmuch-show-header-line customizable boolean to allow inhibiting
a header line in notmuch-show-mode buffers (for instance, because one
prefers to just include Subject in notmuch-message-headers).

---

Second version: includes a link to the new variable's docstring in
notmuch-show section of notmuch-emacs.rst

Signed-off-by: jao 
---
 doc/notmuch-emacs.rst |  3 +++
 emacs/notmuch-show.el | 16 +++-
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 22aee340..fed619b7 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -222,6 +222,9 @@ Display of messages can be controlled by the following 
variables
 :index:`notmuch-message-headers-visible`
|docstring::notmuch-message-headers-visible|
 
+:index:`notmuch-show-header-line`
+   |docstring::notmuch-show-header-line|
+
 .. _show-copy:
 
 Copy to kill-ring
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 4de3e423..7c1f02c9 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -84,6 +84,11 @@ visible for any given message."
   :type 'boolean
   :group 'notmuch-show)
 
+(defcustom notmuch-show-header-line t
+  "Show a header line with the current message's subject."
+  :type 'boolean
+  :group 'notmuch-show)
+
 (defcustom notmuch-show-relative-dates t
   "Display relative dates in the message summary line."
   :type 'boolean
@@ -1345,11 +1350,12 @@ If no messages match the query return NIL."
   (notmuch-show-mapc
(lambda () (notmuch-show-set-prop :orig-tags (notmuch-show-get-tags
   ;; Set the header line to the subject of the first message.
-  (setq header-line-format
-   (replace-regexp-in-string "%" "%%"
- (notmuch-sanitize
-  (notmuch-show-strip-re
-   (notmuch-show-get-subject)
+  (when notmuch-show-header-line
+   (setq header-line-format
+ (replace-regexp-in-string "%" "%%"
+   (notmuch-sanitize
+(notmuch-show-strip-re
+ (notmuch-show-get-subject))
   (run-hooks 'notmuch-show-hook)
   (if state
  (notmuch-show-apply-state state)
-- 
2.34.1

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH] emacs: use query name for tree saved-search buffer names

2022-01-08 Thread jao
This simply mimics what we already do for non-tree searches, and makes
up for nicer buffer names.  Note that this patch only applies to
queries not coming from a search widget in the hello buffer.

Signed-off-by: jao 
---
 emacs/notmuch-hello.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index fc007c4c..9f42a90b 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -487,7 +487,7 @@ diagonal."
   (cl-case (widget-get widget :notmuch-search-type)
(tree
 (notmuch-tree (widget-get widget :notmuch-search-terms)
- nil nil nil nil nil nil
+ nil nil (widget-value widget) nil nil nil
  (widget-get widget :notmuch-search-oldest-first)))
(unthreaded
 (notmuch-unthreaded (widget-get widget :notmuch-search-terms)))
-- 
2.34.1

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH] emacs: make header line in notmuch-show buffers optional

2022-01-08 Thread jao
New notmuch-show-header-line customizable boolean to allow inhibiting
a header line in notmuch-show-mode buffers (for instance, because one
prefers to just include Subject in notmuch-message-headers).

Signed-off-by: jao 
---
 emacs/notmuch-show.el | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 4de3e423..7c1f02c9 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -84,6 +84,11 @@ visible for any given message."
   :type 'boolean
   :group 'notmuch-show)
 
+(defcustom notmuch-show-header-line t
+  "Show a header line with the current message's subject."
+  :type 'boolean
+  :group 'notmuch-show)
+
 (defcustom notmuch-show-relative-dates t
   "Display relative dates in the message summary line."
   :type 'boolean
@@ -1345,11 +1350,12 @@ If no messages match the query return NIL."
   (notmuch-show-mapc
(lambda () (notmuch-show-set-prop :orig-tags (notmuch-show-get-tags
   ;; Set the header line to the subject of the first message.
-  (setq header-line-format
-   (replace-regexp-in-string "%" "%%"
- (notmuch-sanitize
-  (notmuch-show-strip-re
-   (notmuch-show-get-subject)
+  (when notmuch-show-header-line
+   (setq header-line-format
+ (replace-regexp-in-string "%" "%%"
+   (notmuch-sanitize
+(notmuch-show-strip-re
+ (notmuch-show-get-subject))
   (run-hooks 'notmuch-show-hook)
   (if state
  (notmuch-show-apply-state state)
-- 
2.34.1

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v4] emacs: notmuch-tree: customizable strings for drawing trees

2021-08-30 Thread jao
New customizable variable, notmuch-tree-thread-symbols, that allows
tweaking of how trees in a forest are represented.  For instance, one
can now choose to use an hyphen rather than a white space as a prefix,
or replace the character(s) used to draw arrows.
---
 emacs/notmuch-tree.el | 44 +--
 1 file changed, 34 insertions(+), 10 deletions(-)

diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index b48a132d..485e89a8 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -74,6 +74,30 @@
   notmuch-unthreaded-show-out
 notmuch-tree-show-out))
 
+(defcustom notmuch-tree-thread-symbols
+  '((prefix . " ")
+(top . "─")
+(top-tee . "┬")
+(vertical . "│")
+(vertical-tee . "├")
+(bottom . "â•°")
+(arrow . "â–º"))
+  "Strings used to draw trees in notmuch tree results.
+Symbol keys denote where the corresponding string value is used:
+`prefix' is used at the top of the tree, followed by `top' if it
+has no children or `top-tee' if it does; `vertical' is a bar
+connecting with a response down the list skipping the current
+one, while `vertical-tee' marks the current message as a reply to
+the previous one; `bottom' is used at the bottom of threads.
+Finally, the `arrrow' string in the list is used as a pointer to
+every message.
+
+Common customizations include setting `prefix' to \"-\", to see
+equal-length prefixes, and `arrow' to an empty string or to a
+different kind of arrow point."
+  :type '(alist :key-type symbol :value-type string)
+  :group 'notmuch-tree)
+
 (defcustom notmuch-tree-result-format
   `(("date" . "%12s  ")
 ("authors" . "%-20s")
@@ -980,20 +1004,20 @@ message together with all its descendents."
(replies (cadr tree)))
 (cond
  ((and (< 0 depth) (not last))
-  (push "├" tree-status))
+  (push (alist-get 'vertical-tee  notmuch-tree-thread-symbols) 
tree-status))
  ((and (< 0 depth) last)
-  (push "â•°" tree-status))
+  (push (alist-get 'bottom notmuch-tree-thread-symbols) tree-status))
  ((and (eq 0 depth) first last)
-  ;; Choice between these two variants is a matter of taste.
-  ;; (push "─" tree-status))
-  (push " " tree-status))
+  (push (alist-get 'prefix notmuch-tree-thread-symbols) tree-status))
  ((and (eq 0 depth) first (not last))
-  (push "┬" tree-status))
+  (push (alist-get 'top-tee notmuch-tree-thread-symbols) tree-status))
  ((and (eq 0 depth) (not first) last)
-  (push "â•°" tree-status))
+  (push (alist-get 'bottom notmuch-tree-thread-symbols) tree-status))
  ((and (eq 0 depth) (not first) (not last))
-  (push "├" tree-status)))
-(push (concat (if replies "┬" "─") "►") tree-status)
+  (push (alist-get 'vertical-tee notmuch-tree-thread-symbols) 
tree-status)))
+(push (concat (alist-get (if replies 'top-tee 'top) 
notmuch-tree-thread-symbols)
+ (alist-get 'arrow notmuch-tree-thread-symbols))
+ tree-status)
 (setq msg (plist-put msg :first (and first (eq 0 depth
 (setq msg (plist-put msg :tree-status tree-status))
 (setq msg (plist-put msg :orig-tags (plist-get msg :tags)))
@@ -1002,7 +1026,7 @@ message together with all its descendents."
 (pop tree-status)
 (if last
(push " " tree-status)
-  (push "│" tree-status))
+  (push (alist-get 'vertical notmuch-tree-thread-symbols 3) tree-status))
 (notmuch-tree-insert-thread replies (1+ depth) tree-status)))
 
 (defun notmuch-tree-insert-thread (thread depth tree-status)
-- 
2.33.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH] emacs: notmuch-tree: customizable strings for drawing trees

2021-08-22 Thread jao
New customizable variable, notmuch-tree-thread-symbols, that allows
tweaking of how trees in a forest are represented.  For instance, one
can now choose to use an hyphen rather than a white space as a prefix,
or replace the character(s) used to draw arrows.
---
 emacs/notmuch-tree.el | 36 ++--
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index 2f508128..a1dfa7b1 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -74,6 +74,22 @@
   notmuch-unthreaded-show-out
 notmuch-tree-show-out))
 
+(defcustom notmuch-tree-thread-symbols '(" " "─" "┬" "│" "├" "╰" "►")
+  "List of strings used to draw trees in notmuch tree results.
+The first element is used at the top of the tree, followed by the
+second if it has no children or the third if it does.  The fourth
+is a bar connecting with a response down the list skipping the
+current one, while the fifth marks the current message as a reply
+to the previous.  The sixth string is used at the bottom of
+threads.  Finally, the last string in the list is used as a
+pointer to every message.
+
+Common customizations include setting the first element of the
+list to \"-\", to see equal-length prefixes, or the last to an
+empty string or to a different kind of arrow point."
+  :type '(list string)
+  :group 'notmuch-tree)
+
 (defcustom notmuch-tree-result-format
   `(("date" . "%12s  ")
 ("authors" . "%-20s")
@@ -968,20 +984,20 @@ message together with all its descendents."
(replies (cadr tree)))
 (cond
  ((and (< 0 depth) (not last))
-  (push "├" tree-status))
+  (push (elt notmuch-tree-thread-symbols 4) tree-status))
  ((and (< 0 depth) last)
-  (push "â•°" tree-status))
+  (push (elt notmuch-tree-thread-symbols 5) tree-status))
  ((and (eq 0 depth) first last)
-  ;; Choice between these two variants is a matter of taste.
-  ;; (push "─" tree-status))
-  (push " " tree-status))
+  (push (elt notmuch-tree-thread-symbols 0) tree-status))
  ((and (eq 0 depth) first (not last))
-  (push "┬" tree-status))
+  (push (elt notmuch-tree-thread-symbols 2) tree-status))
  ((and (eq 0 depth) (not first) last)
-  (push "â•°" tree-status))
+  (push (elt notmuch-tree-thread-symbols 5) tree-status))
  ((and (eq 0 depth) (not first) (not last))
-  (push "├" tree-status)))
-(push (concat (if replies "┬" "─") "►") tree-status)
+  (push (elt notmuch-tree-thread-symbols 4) tree-status)))
+(push (concat (elt notmuch-tree-thread-symbols (if replies 2 1))
+ (elt notmuch-tree-thread-symbols 6))
+ tree-status)
 (setq msg (plist-put msg :first (and first (eq 0 depth
 (setq msg (plist-put msg :tree-status tree-status))
 (setq msg (plist-put msg :orig-tags (plist-get msg :tags)))
@@ -990,7 +1006,7 @@ message together with all its descendents."
 (pop tree-status)
 (if last
(push " " tree-status)
-  (push "│" tree-status))
+  (push (elt notmuch-tree-thread-symbols 3) tree-status))
 (notmuch-tree-insert-thread replies (1+ depth) tree-status)))
 
 (defun notmuch-tree-insert-thread (thread depth tree-status)
-- 
2.33.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH] emacs: notmuch-tree: customizable strings for drawing trees

2021-08-20 Thread jao
New customizable variable, notmuch-tree-tread-symbols, that allows
tweaking how trees in a forest are represented.  For instance, one can
now choose to use an hyphen rather than a white space as a prefix, or
remove pointy arrows.
---
 emacs/notmuch-tree.el | 35 +--
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index 01a77b71..27e5ac3a 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -74,6 +74,21 @@
   notmuch-unthreaded-show-out
 notmuch-tree-show-out))
 
+(defcustom notmuch-tree-thread-symbols '(" " "─" "┬" "│" "├" "╰" "►")
+  "List of strings used to draw trees.
+The first element is used at the top of the tree, followed by the
+second if it has no direct children or the third if it does.  The
+fourth is a bar connecting with a response down the list skipping
+the current one, while the fifth does not skip.  The sixth and
+the bottom of the thread.  Finally, the last one is a pointer to
+every messages.
+
+Common customizations include setting the first element of the
+list to \"-\", to see equal-length prefixes, or the last and
+empty string or a different kind of arrow point."
+  :type '(list string)
+  :group 'notmuch-tree)
+
 (defcustom notmuch-tree-result-format
   `(("date" . "%12s  ")
 ("authors" . "%-20s")
@@ -968,20 +983,20 @@ message together with all its descendents."
(replies (cadr tree)))
 (cond
  ((and (< 0 depth) (not last))
-  (push "├" tree-status))
+  (push (elt notmuch-tree-thread-symbols 4) tree-status))
  ((and (< 0 depth) last)
-  (push "â•°" tree-status))
+  (push (elt notmuch-tree-thread-symbols 5) tree-status))
  ((and (eq 0 depth) first last)
-  ;; Choice between these two variants is a matter of taste.
-  ;; (push "─" tree-status))
-  (push " " tree-status))
+  (push (elt notmuch-tree-thread-symbols 0) tree-status))
  ((and (eq 0 depth) first (not last))
-  (push "┬" tree-status))
+  (push (elt notmuch-tree-thread-symbols 2) tree-status))
  ((and (eq 0 depth) (not first) last)
-  (push "â•°" tree-status))
+  (push (elt notmuch-tree-thread-symbols 5) tree-status))
  ((and (eq 0 depth) (not first) (not last))
-  (push "├" tree-status)))
-(push (concat (if replies "┬" "─") "►") tree-status)
+  (push (elt notmuch-tree-thread-symbols 4) tree-status)))
+(push (concat (elt notmuch-tree-thread-symbols (if replies 2 1))
+ (elt notmuch-tree-thread-symbols 6))
+ tree-status)
 (setq msg (plist-put msg :first (and first (eq 0 depth
 (setq msg (plist-put msg :tree-status tree-status))
 (setq msg (plist-put msg :orig-tags (plist-get msg :tags)))
@@ -990,7 +1005,7 @@ message together with all its descendents."
 (pop tree-status)
 (if last
(push " " tree-status)
-  (push "│" tree-status))
+  (push (elt notmuch-tree-thread-symbols 3) tree-status))
 (notmuch-tree-insert-thread replies (1+ depth) tree-status)))
 
 (defun notmuch-tree-insert-thread (thread depth tree-status)
-- 
2.33.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH] emacs: honour notmuch-show-text/html-blocked-images in w3m messages

2021-08-03 Thread jao
When mm-text-html-renderer is set to 'w3m, the variable playing the
role of a regular expression for blocked images is
w3m-ignored-image-url-regexp.  We bind it when the renderer is not
'shr.
---
 emacs/notmuch-show.el | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 9a95eb34..0f96c4fe 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -59,6 +59,7 @@
 (defvar shr-blocked-images)
 (defvar gnus-blocked-images)
 (defvar shr-content-function)
+(defvar w3m-ignored-image-url-regexp)
 
 ;;; Options
 
@@ -823,7 +824,8 @@ will return nil if the CID is unknown or cannot be 
retrieved."
 (let ((mm-inline-text-html-with-w3m-keymap nil)
  ;; FIXME: If we block an image, offer a button to load external
  ;; images.
- (gnus-blocked-images notmuch-show-text/html-blocked-images))
+ (gnus-blocked-images notmuch-show-text/html-blocked-images)
+ (w3m-ignored-image-url-regexp notmuch-show-text/html-blocked-images))
   (notmuch-show-insert-part-*/* msg part content-type nth depth button
 
 ;;; Functions used by notmuch-show--insert-part-text/html-shr
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v2] emacs: new command notmuch-tree-filter

2021-07-31 Thread jao
This command is analogous to notmuch-filter, but is defined on tree
mode buffers.
---
 doc/notmuch-emacs.rst |  3 +++
 emacs/notmuch-tree.el | 16 
 2 files changed, 19 insertions(+)

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 952fe2a5..5accfa60 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -302,6 +302,9 @@ tags.
 ``o`` ``notmuch-tree-toggle-order``
|docstring::notmuch-tree-toggle-order|
 
+``l`` ``notmuch-tree-filter``
+   Filter or LIMIT the current search results based on an additional query 
string
+
 ``g`` ``=``
 Refresh the buffer
 
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index ef1ca4c5..f2938330 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -349,6 +349,7 @@ then NAME behaves like CMD."
 (define-key map "r" 'notmuch-tree-reply-sender)
 (define-key map "R" 'notmuch-tree-reply)
 (define-key map "V" 'notmuch-tree-view-raw-message)
+(define-key map "l" 'notmuch-tree-filter)
 
 ;; The main tree view bindings
 (define-key map (kbd "RET") 'notmuch-tree-show-message)
@@ -1168,6 +1169,21 @@ The arguments are:
   (interactive)
   (notmuch-tree query query-context target buffer-name open-target t))
 
+(defun notmuch-tree-filter (query)
+  "Filter or LIMIT the current search results based on an additional query 
string.
+
+Runs a new tree search matching only messages that match both the
+current search results AND the additional query string provided."
+  (interactive (list (notmuch-read-query "Filter search: ")))
+  (let ((notmuch-show-process-crypto (notmuch-tree--message-process-crypto))
+   (grouped-query (notmuch-group-disjunctive-query-string query))
+   (grouped-original-query (notmuch-group-disjunctive-query-string
+(notmuch-tree-get-query
+(notmuch-tree-close-message-window)
+(notmuch-tree (if (string= grouped-original-query "*")
+ grouped-query
+   (concat grouped-original-query " and " grouped-query)
+
 ;;; _
 
 (provide 'notmuch-tree)
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


emacs: new command notmuch-tree-filter (alternative)

2021-07-31 Thread jao
The following patch is an alternative, shorter implementation of
notmuch-tree-filter that doesn't try to use the
notmuch-tree--define-close-message-window-and somewhat artificially.
Either version works for me.

___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH] emacs: new command notmuch-tree-filter

2021-07-31 Thread jao
This command is analogous to notmuch-filter, but is defined on tree
mode buffers.
---
 doc/notmuch-emacs.rst |  3 +++
 emacs/notmuch-tree.el | 19 +++
 2 files changed, 22 insertions(+)

diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 952fe2a5..5accfa60 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -302,6 +302,9 @@ tags.
 ``o`` ``notmuch-tree-toggle-order``
|docstring::notmuch-tree-toggle-order|
 
+``l`` ``notmuch-tree-filter``
+   Filter or LIMIT the current search results based on an additional query 
string
+
 ``g`` ``=``
 Refresh the buffer
 
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index ef1ca4c5..a18b47ff 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -349,6 +349,7 @@ then NAME behaves like CMD."
 (define-key map "r" 'notmuch-tree-reply-sender)
 (define-key map "R" 'notmuch-tree-reply)
 (define-key map "V" 'notmuch-tree-view-raw-message)
+(define-key map "l" 'notmuch-tree-filter)
 
 ;; The main tree view bindings
 (define-key map (kbd "RET") 'notmuch-tree-show-message)
@@ -1168,6 +1169,24 @@ The arguments are:
   (interactive)
   (notmuch-tree query query-context target buffer-name open-target t))
 
+(eval-when-compile
+  (defun notmuch-tree--filter (query)
+"Filter or LIMIT the current search results based on an additional query 
string.
+
+Runs a new tree search matching only messages that match both the
+current search results AND the additional query string provided."
+(interactive (list (notmuch-read-query "Filter search: ")))
+(let ((grouped-query (notmuch-group-disjunctive-query-string query))
+ (grouped-original-query (notmuch-group-disjunctive-query-string
+  (notmuch-tree-get-query
+  (notmuch-tree (if (string= grouped-original-query "*")
+   grouped-query
+ (concat grouped-original-query " and " grouped-query))
+
+(notmuch-tree--define-close-message-window-and
+ notmuch-tree-filter
+ notmuch-tree--filter)
+
 ;;; _
 
 (provide 'notmuch-tree)
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


Re: New --sort for notmuch show emacs notmuch-tree-mode (v3)

2021-07-03 Thread jao
On Sat, Jul 03 2021, David Bremner wrote:

> I have applied this version to master

Thanks, David.  Very much appreciated: i've been using it locally for
weeks now and have experience no problems, so i hope other people will
find it useful too.

Cheers,
jao
-- 
Don't be yourself. Be someone a little nicer.
  -Mignon McLaughlin, journalist and author (1913-1983)
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v3 5/5] doc: new notmuch show --sort and related emacs commands

2021-07-02 Thread jao
New --sort CLI option documented in notmuch-show's man page, and
notmuch-search-toggle-order mentioned in doc/notmuch-emacs.rst and
devel/emacs-keybindings.org (in the latter, there's also some
whitespace changes in a table introduced by org-mode).
---
 devel/emacs-keybindings.org | 10 +-
 doc/man1/notmuch-show.rst   | 13 +
 doc/notmuch-emacs.rst   |  7 +++
 3 files changed, 25 insertions(+), 5 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 

[PATCH v3 4/5] emacs/tree: command to toggle search sort order in tree mode

2021-07-02 Thread jao
New command notmuch-tree-toggle-order for switching the sort order (by
reissuing the search with a different flag) in a notmuch-tree buffer.
---
 emacs/notmuch-tree.el | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index 49d7659e..b288c05d 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)
@@ -751,7 +752,8 @@ nil otherwise."
 query-context
 target
 nil
-unthreaded)))
+unthreaded
+notmuch-search-oldest-first)))
 
 (defun notmuch-tree-thread-top ()
   (when (notmuch-tree-get-message-properties)
@@ -1073,6 +1075,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 "")
@@ -1117,6 +1120,15 @@ 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 ( query query-context target buffer-name
   open-target unthreaded parent-buffer 
oldest-first)
   "Display threads matching QUERY in tree view.
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v3 3/5] emacs/hello: honouring :sort-order in threaded queries

2021-07-02 Thread jao
Now that notmuch show accepts --sort, we can, on the emacs side, use
it according to the value of :sort-order in the definition of saved
queries.
---
 emacs/notmuch-hello.el |  4 +++-
 emacs/notmuch-tree.el  | 10 ++
 2 files changed, 9 insertions(+), 5 deletions(-)

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  _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 56863701..49d7659e 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1064,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  query-context target 
open-target unthreaded)
+(defun notmuch-tree-worker (basic-query  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
@@ -1090,6 +1091,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))
@@ -1097,7 +1099,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.
@@ -1116,7 +1118,7 @@ the same as for the function notmuch-tree."
 notmuch-tree-basic-query))
 
 (defun notmuch-tree ( 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:
@@ -1145,7 +1147,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))
 
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v3 1/5] CLI/show: accept --sort

2021-07-02 Thread jao
Add the command-line option --sort to the show command of the CLI
notmuch interface, with the same possible values as the same option in
notmuch search.
---
 notmuch-show.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/notmuch-show.c b/notmuch-show.c
index 232557d5..852afc8d 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -1249,8 +1249,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 = , .name = "sort", .keywords =
+ (notmuch_keyword_t []){ { "oldest-first", NOTMUCH_SORT_OLDEST_FIRST },
+ { "newest-first", NOTMUCH_SORT_NEWEST_FIRST },
+ { 0, 0 } } },
{ .opt_keyword = , .name = "format", .keywords =
  (notmuch_keyword_t []){ { "json", NOTMUCH_FORMAT_JSON },
  { "text", NOTMUCH_FORMAT_TEXT },
@@ -1367,6 +1372,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);
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH v3 2/5] CLI/show: tests for the new --sort option

2021-07-02 Thread jao
New unit tests for notmuch show --sort, covering the basic use cases.
---
 test/T520-show.sh | 17 +
 1 file changed, 17 insertions(+)

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@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
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


New --sort for notmuch show emacs notmuch-tree-mode (v3)

2021-07-02 Thread jao
version 3, rebased against master and superseding
20210626022846.233052-1-jao%40gnu.org and 20210626180650.342569-1-jao%40gnu.org

[PATCH v3 1/5] CLI/show: accept --sort
[PATCH v3 2/5] CLI/show: tests for the new --sort option
[PATCH v3 3/5] emacs/hello: honouring :sort-order in threaded queries
[PATCH v3 4/5] emacs/tree: command to toggle search sort order in
[PATCH v3 5/5] doc: new notmuch show --sort and related emacs
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 5/5] doc: new notmuch show --sort and related emacs commands

2021-06-26 Thread jao
New --sort CLI option documented in notmuch-show's man page, and
notmuch-search-toggle-order mentioned in doc/notmuch-emacs.rst and
devel/emacs-keybindings.org (in the latter, there's also some
whitespace changes in a table introduced by org-mode).
---
 devel/emacs-keybindings.org | 10 +-
 doc/man1/notmuch-show.rst   | 13 +
 doc/notmuch-emacs.rst   |  7 +++
 3 files changed, 25 insertions(+), 5 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 

[PATCH 4/5] emacs/tree: command to toggle search sort order in tree mode

2021-06-26 Thread jao
New command notmuch-tree-toggle-order for switching the sort order (by
reissuing the search with a different flag) in a notmuch-tree buffer.
---
 emacs/notmuch-tree.el | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index 6ef8e439..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)
@@ -1071,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 "")
@@ -1115,6 +1118,15 @@ 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 ( query query-context target buffer-name
   open-target unthreaded parent-buffer 
oldest-first)
   "Display threads matching QUERY in tree view.
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 3/5] emacs/hello: honouring :sort-order in threaded queries

2021-06-26 Thread jao
Now that notmuch show accepts --sort, we can, on the emacs side, use
it according to the value of :sort-order in the definition of saved
queries.
---
 emacs/notmuch-hello.el |  4 +++-
 emacs/notmuch-tree.el  | 10 ++
 2 files changed, 9 insertions(+), 5 deletions(-)

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  _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..6ef8e439 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1062,7 +1062,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  query-context target 
open-target unthreaded)
+(defun notmuch-tree-worker (basic-query  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
@@ -1088,6 +1089,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 +1097,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.
@@ -1114,7 +1116,7 @@ the same as for the function notmuch-tree."
 notmuch-tree-basic-query))
 
 (defun notmuch-tree ( 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 +1145,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))
 
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 1/5] CLI/show: accept --sort

2021-06-26 Thread jao
Add the command-line option --sort to the show command of the CLI
notmuch interface, with the same possible values as the same option in
notmuch search.
---
 notmuch-show.c | 7 +++
 1 file changed, 7 insertions(+)

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 = , .name = "sort", .keywords =
+ (notmuch_keyword_t []){ { "oldest-first", NOTMUCH_SORT_OLDEST_FIRST },
+ { "newest-first", NOTMUCH_SORT_NEWEST_FIRST },
+ { 0, 0 } } },
{ .opt_keyword = , .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);
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 2/5] CLI/show: tests for the new --sort option

2021-06-26 Thread jao
New unit tests for notmuch show --sort, covering the basic use cases.
---
 test/T520-show.sh | 17 +
 1 file changed, 17 insertions(+)

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@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
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


Here's a re-roll, with review comments so far addressed

2021-06-26 Thread jao
[PATCH 1/5] CLI/show: accept --sort
[PATCH 2/5] CLI/show: tests for the new --sort option
[PATCH 3/5] emacs/hello: honouring :sort-order in threaded queries
[PATCH 4/5] emacs/tree: command to toggle search sort order in tree
[PATCH 5/5] doc: new notmuch show --sort and related emacs commands
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 1/5] CLI/show: accept --sort

2021-06-26 Thread jao
Add the command-line option --sort to the show command of the CLI
notmuch interface, with the same possible values as the same option in
notmuch search.
---
 notmuch-show.c | 7 +++
 1 file changed, 7 insertions(+)

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 = , .name = "sort", .keywords =
+ (notmuch_keyword_t []){ { "oldest-first", NOTMUCH_SORT_OLDEST_FIRST },
+ { "newest-first", NOTMUCH_SORT_NEWEST_FIRST },
+ { 0, 0 } } },
{ .opt_keyword = , .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);
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 7/7] emacs: fix notmuch-tree-toggle-order keybinding

2021-06-25 Thread jao
Really assign the new emacs command notmuch-tree-toggle-order to o, as
previously documented.
---
 emacs/notmuch-tree.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index c23dacfc..c421cf3f 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -322,11 +322,11 @@ then NAME behaves like CMD."
 ;; that additionally close the message window.
 (define-key map [remap notmuch-bury-or-kill-this-buffer] 
'notmuch-tree-quit)
 (define-key map [remap notmuch-search]   'notmuch-tree-to-search)
-(define-key map [remap notmuch-search]   'notmuch-tree-toggle-order)
 (define-key map [remap notmuch-help] 'notmuch-tree-help)
 (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)
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 6/7] doc: clarifications for the new --sort flag and emacs command

2021-06-25 Thread jao
Improvements to the notmuch show manpage regarding the behaviour of
--sort, and description in doc/notmuch-emacs.rst of the new
notmuch-tree-toggle-order command for notmuch-tree buffers.
---
 doc/man1/notmuch-show.rst | 4 
 doc/notmuch-emacs.rst | 7 +++
 2 files changed, 11 insertions(+)

diff --git a/doc/man1/notmuch-show.rst b/doc/man1/notmuch-show.rst
index 581d15b5..64639174 100644
--- a/doc/man1/notmuch-show.rst
+++ b/doc/man1/notmuch-show.rst
@@ -117,6 +117,10 @@ Supported options for **show** include
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).
 
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
 ===
 
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 5/7] CLI/show: tests for the new --sort option

2021-06-25 Thread jao
New unit tests for notmuch show --sort, covering the basic use cases.
---
 test/T520-show.sh | 17 +
 1 file changed, 17 insertions(+)

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@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
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 4/7] doc: updates for new --sort and related emacs commands

2021-06-25 Thread jao
New --sort CLI option documented in notmuch-show's man page, and
notmuch-search-toggle-order mentioned in devel/emacs-keybindings.org.
---
 devel/emacs-keybindings.org | 10 +-
 doc/man1/notmuch-show.rst   |  9 +
 2 files changed, 14 insertions(+), 5 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..581d15b5 100644
--- a/doc/man1/notmuch-show.rst
+++ b/doc/man1/notmuch-show.rst
@@ -111,6 +111,15 @@ 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**).
+
+   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
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 3/7] emacs/tree: command to toggle search sort order in tree mode

2021-06-25 Thread jao
New command notmuch-tree-toggle-order for switching the sort order (by
reissuing the search with a different flag) in a notmuch-tree buffer.
---
 emacs/notmuch-tree.el | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index 6ef8e439..c23dacfc 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -322,6 +322,7 @@ then NAME behaves like CMD."
 ;; that additionally close the message window.
 (define-key map [remap notmuch-bury-or-kill-this-buffer] 
'notmuch-tree-quit)
 (define-key map [remap notmuch-search]   'notmuch-tree-to-search)
+(define-key map [remap notmuch-search]   'notmuch-tree-toggle-order)
 (define-key map [remap notmuch-help] 'notmuch-tree-help)
 (define-key map [remap notmuch-mua-new-mail] 'notmuch-tree-new-mail)
 (define-key map [remap notmuch-jump-search]  'notmuch-tree-jump-search)
@@ -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)
@@ -1071,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 "")
@@ -1115,6 +1118,15 @@ 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 ( query query-context target buffer-name
   open-target unthreaded parent-buffer 
oldest-first)
   "Display threads matching QUERY in tree view.
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 1/7] CLI/show: accept --sort

2021-06-25 Thread jao
Add the command-line option --sort to the show command of the CLI
notmuch interface, with the same possible values as the same option in
notmuch search.
---
 notmuch-show.c | 7 +++
 1 file changed, 7 insertions(+)

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 = , .name = "sort", .keywords =
+ (notmuch_keyword_t []){ { "oldest-first", NOTMUCH_SORT_OLDEST_FIRST },
+ { "newest-first", NOTMUCH_SORT_NEWEST_FIRST },
+ { 0, 0 } } },
{ .opt_keyword = , .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);
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


[PATCH 2/7] emacs/hello: honouring :sort-order in threaded queries

2021-06-25 Thread jao
Now that notmuch show accepts --sort, we can, on the emacs side, use
it according to the value of :sort-order in the definition of saved
queries.
---
 emacs/notmuch-hello.el |  4 +++-
 emacs/notmuch-tree.el  | 10 ++
 2 files changed, 9 insertions(+), 5 deletions(-)

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  _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..6ef8e439 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -1062,7 +1062,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  query-context target 
open-target unthreaded)
+(defun notmuch-tree-worker (basic-query  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
@@ -1088,6 +1089,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 +1097,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.
@@ -1114,7 +1116,7 @@ the same as for the function notmuch-tree."
 notmuch-tree-basic-query))
 
 (defun notmuch-tree ( 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 +1145,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))
 
-- 
2.32.0
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org


New --sort for notmuch show and using it in emacs notmuch-tree-mode

2021-06-25 Thread jao
The accompanying patches implement the new --sort for notmuch show and
its use in emacs to honour :sort-order in saved queries of tree type.

[PATCH 1/7] CLI/show: accept --sort
[PATCH 2/7] emacs/hello: honouring :sort-order in threaded queries
[PATCH 3/7] emacs/tree: command to toggle search sort order in tree
[PATCH 4/7] doc: updates for new --sort and related emacs commands
[PATCH 5/7] CLI/show: tests for the new --sort option
[PATCH 6/7] doc: clarifications for the new --sort flag and emacs
[PATCH 7/7] emacs: fix notmuch-tree-toggle-order keybinding
___
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-le...@notmuchmail.org