From: Pierre Neidhardt <mail@ambrevar.xyz>
To: David Bremner <david@tethera.net>, notmuch@notmuchmail.org
Subject: Re: [PATCH 2/2] emacs: Allow tagging regions in notmuch-tree
Date: Tue, 14 May 2019 12:40:09 +0200 [thread overview]
Message-ID: <87d0klz5di.fsf@ambrevar.xyz> (raw)
In-Reply-To: <878svhfbx0.fsf@tethera.net>
[-- Attachment #1.1: Type: text/plain, Size: 2793 bytes --]
Hi!
Thanks for your review. I've submitted and updated patch.
> Thanks for contributing to Notmuch. Some generic comments:
>
> 1) Please consider a more comprehensive commit message [1]. The "why"
> here is maybe obvious, but consider pointing out whether this makes
> it more consistent with other parts of the UI (or not). Also, a (bit
> more extended) of the changes is always helpful, both to help read
> the diff and to warn of any potential breaking changes.
Done.
> 2) Please update doc/notmuch-emacs.rst. You can re-use docstrings; let
> me know if you need help doing that. We haven't been strict about
> this is in the past, but the emacs docs are really lagging.
I've documented +/-.
> 3) We generally want at least one test for a new
> feature. test/T460-emacs-tree.sh has the existing tree related
> tests. Again, if you need help with the test suite, let us know.
I've added a test, but I wasn't able to run it on Guix
(https://guix.info). It fails like this:
--8<---------------cut here---------------start------------->8---
> guix environment notmuch -- /home/ambrevar/.local/share/emacs/site-lisp/notmuch/test/T460-emacs-tree.sh
guix environment: error: execlp: No such file or directory: "/home/ambrevar/.local/share/emacs/site-lisp/notmuch/test/T460-emacs-tree.sh"
--8<---------------cut here---------------end--------------->8---
> 4) Please use notmuch-tree-- as a prefix for new private symbols that
> users should not rely on. I'm not sure about which symbols that applies
> to here.
I've mirrored the implementation of search-mode.
There are indeed a few functions that are only used locally, but so are
they in notmuch.el, so I guess this should be part of another patch.
>> +(defun notmuch-tree-foreach-result (beg end fn)
>
>> + (lexical-let ((pos (notmuch-tree-result-beginning beg))
>
> As an aside, I'm curious if we can profitably start to use
> file level lexical-binding for parts of notmuch-emacs.
Absolutely, lexical bindings are heavily recommended:
- It enforces better coding practice.
- It's more performent.
- It will spot bugs! :)
I believe this should be part of a different patch set though.
>> + (notmuch-tree-foreach-result beg end
>> + (lambda (pos)
>> + (save-mark-and-excursion
>
> I did wonder if notmuch-tree-foreach-result should be a macro. I'm not
> sure if the small gain in code compactness from just passing a "body" in
> the style of notmuch-show--with-currently-shown-message is worth it.
A macro could work here, but this would only save typing "(lambda".
Functions are preferable to macros if they can fit the bill, and I think
it's the case here.
Cheers!
--
Pierre Neidhardt
https://ambrevar.xyz/
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 487 bytes --]
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0002-emacs-Allow-tagging-regions-in-notmuch-tree.patch --]
[-- Type: text/x-patch, Size: 5920 bytes --]
From bb078dc42649a15c704185610ae15e566a161d7e Mon Sep 17 00:00:00 2001
From: Pierre Neidhardt <mail@ambrevar.xyz>
Date: Tue, 9 Apr 2019 18:37:48 +0200
Subject: [PATCH 2/4] emacs: Allow tagging regions in notmuch-tree
Primarily this allows the user to tag multiple emails at once.
This also enforces consistency with the search view.
The implementation mostly adapts the search-mode code to the
tree-mode.
---
emacs/notmuch-tree.el | 101 +++++++++++++++++++++++++++++++++++-------
1 file changed, 86 insertions(+), 15 deletions(-)
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index c00315e8..ff471c19 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -297,13 +297,15 @@ FUNC."
map))
(fset 'notmuch-tree-mode-map notmuch-tree-mode-map)
-(defun notmuch-tree-get-message-properties ()
+(defun notmuch-tree-get-message-properties (&optional pos)
"Return the properties of the current message as a plist.
Some useful entries are:
:headers - Property list containing the headers :Date, :Subject, :From, etc.
:tags - Tags for this message"
+ (setq pos (or pos (point)))
(save-excursion
+ (goto-char pos)
(beginning-of-line)
(get-text-property (point) :notmuch-message-properties)))
@@ -332,6 +334,13 @@ Some useful entries are:
"Return the tags of the current message."
(notmuch-tree-get-prop :tags))
+(defun notmuch-tree-get-tags-region (beg end)
+ (let (output)
+ (notmuch-tree-foreach-result beg end
+ (lambda (pos)
+ (setq output (append output (notmuch-tree-get-tags)))))
+ output))
+
(defun notmuch-tree-get-message-id (&optional bare)
"Return the message id of the current message."
(let ((id (notmuch-tree-get-prop :id)))
@@ -387,24 +396,86 @@ NOT change the database."
(when (string= tree-msg-id (notmuch-show-get-message-id))
(notmuch-show-update-tags new-tags)))))))
-(defun notmuch-tree-tag (tag-changes)
+(defun notmuch-tree-result-beginning (&optional pos)
+ "Return the point at the beginning of the message at POS (or point).
+
+If there is no thread at POS (or point), returns nil."
+ (when (notmuch-tree-get-message-properties pos)
+ ;; We pass 1+point because previous-single-property-change starts
+ ;; searching one before the position we give it.
+ (previous-single-property-change (1+ (or pos (point)))
+ :notmuch-message-properties nil (point-min))))
+
+(defun notmuch-tree-result-end (&optional pos)
+ "Return the point at the end of the message at POS (or point).
+
+The returned point will be just after the newline character that
+ends the result line. If there is no thread at POS (or point),
+returns nil"
+ (when (notmuch-tree-get-message-properties pos)
+ (next-single-property-change (or pos (point)) :notmuch-message-properties
+ nil (point-max))))
+
+(defun notmuch-tree-foreach-result (beg end fn)
+ "Invoke FN for each result between BEG and END.
+
+FN should take one argument. It will be applied to the
+character position of the beginning of each result that overlaps
+the region between points BEG and END. As a special case, if (=
+BEG END), FN will be applied to the result containing point
+BEG."
+
+ (lexical-let ((pos (notmuch-tree-result-beginning beg))
+ ;; End must be a marker in case fn changes the
+ ;; text.
+ (end (copy-marker end))
+ ;; Make sure we examine at least one result, even if
+ ;; (= beg end).
+ (first t))
+ ;; We have to be careful if the region extends beyond the results.
+ ;; In this case, pos could be null or there could be no result at
+ ;; pos.
+ (while (and pos (or (< pos end) first))
+ (when (notmuch-tree-get-message-properties pos)
+ (funcall fn pos))
+ (setq pos (notmuch-tree-result-end pos)
+ first nil))))
+(put 'notmuch-tree-foreach-result 'lisp-indent-function 2)
+
+(defun notmuch-tree-interactive-tag-changes (&optional initial-input)
+ "Prompt for tag changes for the current message or region.
+
+Returns (TAG-CHANGES REGION-BEGIN REGION-END)."
+ (let* ((region (notmuch-interactive-region))
+ (beg (first region)) (end (second region))
+ (prompt (if (= beg end) "Tag message" "Tag region")))
+ (cons (notmuch-read-tag-changes
+ (notmuch-tree-get-tags-region beg end) prompt initial-input)
+ region)))
+
+(defun notmuch-tree-tag (tag-changes &optional beg end)
"Change tags for the current message"
- (interactive
- (list (notmuch-read-tag-changes (notmuch-tree-get-tags) "Tag message")))
- (notmuch-tag (notmuch-tree-get-message-id) tag-changes)
- (notmuch-tree-tag-update-display tag-changes))
-
-(defun notmuch-tree-add-tag (tag-changes)
+ (interactive (notmuch-tree-interactive-tag-changes))
+ (unless (and beg end)
+ (setq beg (car (notmuch-interactive-region))
+ end (cadr (notmuch-interactive-region))))
+ (notmuch-tree-foreach-result beg end
+ (lambda (pos)
+ (save-mark-and-excursion
+ (goto-char pos)
+ (notmuch-tag (notmuch-tree-get-message-id)
+ tag-changes)
+ (notmuch-tree-tag-update-display tag-changes)))))
+
+(defun notmuch-tree-add-tag (tag-changes &optional beg end)
"Same as `notmuch-tree-tag' but sets initial input to '+'."
- (interactive
- (list (notmuch-read-tag-changes (notmuch-tree-get-tags) "Tag message" "+")))
- (notmuch-tree-tag tag-changes))
+ (interactive (notmuch-tree-interactive-tag-changes "+"))
+ (notmuch-tree-tag tag-changes beg end))
-(defun notmuch-tree-remove-tag (tag-changes)
+(defun notmuch-tree-remove-tag (tag-changes &optional beg end)
"Same as `notmuch-tree-tag' but sets initial input to '-'."
- (interactive
- (list (notmuch-read-tag-changes (notmuch-tree-get-tags) "Tag message" "-")))
- (notmuch-tree-tag tag-changes))
+ (interactive (notmuch-tree-interactive-tag-changes "-"))
+ (notmuch-tree-tag tag-changes beg end))
(defun notmuch-tree-resume-message ()
"Resume EDITING the current draft message."
--
2.21.0
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0003-doc-emacs-document-tagging-bindings-for-notmuch-sear.patch --]
[-- Type: text/x-patch, Size: 975 bytes --]
From 55cb33079a49697d2713a27c4375a2e83ff1d184 Mon Sep 17 00:00:00 2001
From: Pierre Neidhardt <mail@ambrevar.xyz>
Date: Tue, 14 May 2019 12:06:20 +0200
Subject: [PATCH 3/4] doc/emacs: document "+/-" tagging bindings for
notmuch-search and notmuch-tree
---
doc/notmuch-emacs.rst | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/doc/notmuch-emacs.rst b/doc/notmuch-emacs.rst
index 1655e2f0..a9357350 100644
--- a/doc/notmuch-emacs.rst
+++ b/doc/notmuch-emacs.rst
@@ -162,6 +162,10 @@ menu of results that the user can explore further by pressing
``g`` ``=``
Refresh the buffer
+``+,-``
+ Add or remove arbitrary tags from the current thread or the
+ threads in the region.
+
``?``
Display full set of key bindings
@@ -302,6 +306,10 @@ tags.
``g`` ``=``
Refresh the buffer
+``+,-``
+ Add or remove arbitrary tags from the current message or the
+ messages in the region.
+
``?``
Display full set of key bindings
--
2.21.0
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: 0004-T460-emacs-tree-test-tagging-on-region-in-tree-view.patch --]
[-- Type: text/x-patch, Size: 2310 bytes --]
From b4e594a6f5ed452d025641ee9e3f45ca8c48c229 Mon Sep 17 00:00:00 2001
From: Pierre Neidhardt <mail@ambrevar.xyz>
Date: Tue, 14 May 2019 12:29:33 +0200
Subject: [PATCH 4/4] T460-emacs-tree: test tagging on region in tree view
---
test/T460-emacs-tree.sh | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/test/T460-emacs-tree.sh b/test/T460-emacs-tree.sh
index cb2c90b8..b68b905e 100755
--- a/test/T460-emacs-tree.sh
+++ b/test/T460-emacs-tree.sh
@@ -88,6 +88,45 @@ test_begin_subtest "Untag message in notmuch tree view (database)"
output=$(notmuch search --output=messages 'tag:test_thread_tag')
test_expect_equal "$output" ""
+test_begin_subtest "Tag region in notmuch tree view"
+test_emacs '(notmuch-tree "tag:inbox")
+ (notmuch-test-wait)
+ ;; move to test thread above so that we can reuse the test output.
+ (forward-line 23)
+ (set-mark-command)
+ (forward-line 7)
+ (notmuch-tree-tag (list "+test_thread_tag"))
+ (test-output)
+ (delete-other-windows)'
+test_expect_equal_file $EXPECTED/notmuch-tree-tag-inbox-thread-tagged OUTPUT
+
+test_begin_subtest "Tag region in notmuch tree view (database)"
+output=$(notmuch search --output=messages 'tag:test_thread_tag')
+test_expect_equal "$output" \
+"id:87ocn0qh6d.fsf@yoom.home.cworth.org
+id:20091118005040.GA25380@dottiness.seas.harvard.edu
+id:yunaayketfm.fsf@aiko.keithp.com
+id:87fx8can9z.fsf@vertex.dottedmag
+id:20091117203301.GV3165@dottiness.seas.harvard.edu
+id:87iqd9rn3l.fsf@vertex.dottedmag
+id:20091117190054.GU3165@dottiness.seas.harvard.edu"
+
+test_begin_subtest "Untag region in notmuch tree view"
+test_emacs '(notmuch-tree "tag:inbox")
+ (notmuch-test-wait)
+ ;; mark the same region as above
+ (forward-line 23)
+ (set-mark-command)
+ (forward-line 7)
+ (notmuch-tree-tag-thread (list "-test_thread_tag"))
+ (test-output)
+ (delete-other-windows)'
+test_expect_equal_file $EXPECTED/notmuch-tree-tag-inbox OUTPUT
+
+test_begin_subtest "Untag region in notmuch tree view (database)"
+output=$(notmuch search --output=messages 'tag:test_thread_tag')
+test_expect_equal "$output" ""
+
test_begin_subtest "Navigation of notmuch-hello to search results"
test_emacs '(notmuch-hello)
(goto-char (point-min))
--
2.21.0
next prev parent reply other threads:[~2019-05-14 10:40 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-09 16:47 [PATCH 1/2] emacs: Move notmuch-search-interactive-region to notmuch-lib as notmuch-interactive-region Pierre Neidhardt
2019-04-09 16:47 ` [PATCH 2/2] emacs: Allow tagging regions in notmuch-tree Pierre Neidhardt
2019-05-08 11:00 ` David Bremner
2019-05-14 10:40 ` Pierre Neidhardt [this message]
2019-05-25 11:13 ` David Bremner
2019-05-25 11:41 ` Pierre Neidhardt
2019-05-25 13:42 ` David Bremner
2019-05-07 9:35 ` [PATCH 1/2] emacs: Move notmuch-search-interactive-region to notmuch-lib as notmuch-interactive-region David Bremner
2019-05-20 12:35 ` Leo Vivier
2019-05-20 17:11 ` Tomi Ollila
2019-05-22 14:56 ` Leo Vivier
2019-05-23 11:14 ` David Bremner
2019-05-23 11:19 ` Leo Vivier
2019-05-23 17:07 ` David Bremner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://notmuchmail.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87d0klz5di.fsf@ambrevar.xyz \
--to=mail@ambrevar.xyz \
--cc=david@tethera.net \
--cc=notmuch@notmuchmail.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://yhetil.org/notmuch.git/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).