[notmuch] [PATCH v2] notmuch.el: add functionality in notmuch search mode to add or remove tags by region

Jesse Rosenthal jrosenthal at jhu.edu
Tue Feb 16 16:07:40 PST 2010


This patch adds `-region' versions of the `notmuch-search-' commands to find
properties. It also splits up  `notmuch-add/remove-tags' into both a
`-thread' and a `-region' version. (This makes us modify
`notmuch-search-archive-thread' to use the
`notmuch-search-remove-tag-thread' function, instead of
`notmuch-search-remove-tag', for consistency.) The add/remove-tag command
called by pressing `+' or `-' will then choose accordingly, based on whether
region is active.

This version fixes a couple of errors in the first version, which led to
incorrect marking of some tags in the search view (though the actual
tagging was still correct). It's also based on current master.

I'm not sure any more if region selection is actually the correct way to
do this, or if a mutt-style message-marking method would be better. But
I didn't want a buggy incorrect version out there.
---
 notmuch.el |   98 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 0f4ea10..7d9a82f 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -1227,18 +1227,41 @@ Complete list of currently available key bindings:
   (set (make-local-variable 'font-lock-defaults)
          '(notmuch-search-font-lock-keywords t)))
 
+(defun notmuch-search-properties-in-region (property beg end)
+  (save-excursion
+    (let ((output nil)
+	  (last-line (line-number-at-pos end)))
+      (goto-char beg)
+      (beginning-of-line)
+      (while (<= (line-number-at-pos) last-line)
+	(setq output (cons (get-text-property (point) property) output))
+	(forward-line 1))
+      output)))
+
 (defun notmuch-search-find-thread-id ()
   "Return the thread for the current thread"
   (get-text-property (point) 'notmuch-search-thread-id))
 
+(defun notmuch-search-find-thread-id-region (beg end)
+  "Return a list of threads for the current region"
+  (notmuch-search-properties-in-region 'notmuch-search-thread-id beg end))
+
 (defun notmuch-search-find-authors ()
   "Return the authors for the current thread"
   (get-text-property (point) 'notmuch-search-authors))
 
+(defun notmuch-search-find-authors-region (beg end)
+  "Return a list of authors for the current region"
+  (notmuch-search-properties-in-region 'notmuch-search-authors beg end))
+
 (defun notmuch-search-find-subject ()
   "Return the subject for the current thread"
   (get-text-property (point) 'notmuch-search-subject))
 
+(defun notmuch-search-find-subject-region (beg end)
+  "Return a list of authors for the current region"
+  (notmuch-search-properties-in-region 'notmuch-search-subject beg end))
+
 (defun notmuch-search-show-thread ()
   "Display the currently selected thread."
   (interactive)
@@ -1292,32 +1315,85 @@ and will also appear in a buffer named \"*Notmuch errors*\"."
       (let ((end (- (point) 1)))
 	(split-string (buffer-substring beg end))))))
 
+(defun notmuch-search-get-tags-region (beg end)
+  (save-excursion
+    (let ((output nil)
+	  (last-line (line-number-at-pos end)))
+      (goto-char beg)
+      (while (<= (line-number-at-pos) last-line)
+	(setq output (append output (notmuch-search-get-tags)))
+	(forward-line 1))
+      output)))
+
+(defun notmuch-search-add-tag-thread (tag)
+  (notmuch-call-notmuch-process "tag" (concat "+" tag) (notmuch-search-find-thread-id))
+  (notmuch-search-set-tags (delete-dups (sort (cons tag (notmuch-search-get-tags)) 'string<))))
+
+(defun notmuch-search-add-tag-region (tag beg end)
+  (let ((search-id-string (mapconcat 'identity (notmuch-search-find-thread-id-region beg end) " or ")))
+    (notmuch-call-notmuch-process "tag" (concat "+" tag) search-id-string)
+    (save-excursion
+      (let ((last-line (line-number-at-pos end)))
+	(goto-char beg)
+	(while (<= (line-number-at-pos) last-line)
+	  (notmuch-search-set-tags (delete-dups (sort (cons tag (notmuch-search-get-tags)) 'string<)))
+	  (forward-line))))))
+
+(defun notmuch-search-remove-tag-thread (tag)
+  (notmuch-call-notmuch-process "tag" (concat "-" tag) (notmuch-search-find-thread-id))
+  (notmuch-search-set-tags (delete tag (notmuch-search-get-tags))))
+
+(defun notmuch-search-remove-tag-region (tag beg end)
+  (let ((search-id-string (mapconcat 'identity (notmuch-search-find-thread-id-region beg end) " or ")))
+    (notmuch-call-notmuch-process "tag" (concat "-" tag) search-id-string)
+    (save-excursion
+      (let ((last-line (line-number-at-pos end)))
+	(goto-char beg)
+	(while (<= (line-number-at-pos) last-line)
+	  (notmuch-search-set-tags (delete tag (notmuch-search-get-tags)))
+	  (forward-line))))))
+
+
 (defun notmuch-search-add-tag (tag)
-  "Add a tag to the currently selected thread.
+  "Add a tag to the currently selected thread or region.
 
-The tag is added to messages in the currently selected thread
-which match the current search terms."
+The tag is added to messages in the currently selected thread or
+region which match the current search terms."
   (interactive
    (list (notmuch-select-tag-with-completion "Tag to add: ")))
-  (notmuch-call-notmuch-process "tag" (concat "+" tag) (notmuch-search-find-thread-id))
-  (notmuch-search-set-tags (delete-dups (sort (cons tag (notmuch-search-get-tags)) 'string<))))
+  (save-excursion
+    (if (region-active-p)
+	(let* ((beg (region-beginning))
+	       (end (region-end)))
+	  (notmuch-search-add-tag-region tag beg end))
+      (notmuch-search-add-tag-thread tag))))
 
 (defun notmuch-search-remove-tag (tag)
-  "Remove a tag from the currently selected thread.
+  "Remove a tag from the currently selected thread or region.
 
 The tag is removed from messages in the currently selected thread
-which match the current search terms."
+or region which match the current search terms."
   (interactive
-   (list (notmuch-select-tag-with-completion "Tag to remove: " (notmuch-search-find-thread-id))))
-  (notmuch-call-notmuch-process "tag" (concat "-" tag) (notmuch-search-find-thread-id))
-  (notmuch-search-set-tags (delete tag (notmuch-search-get-tags))))
+   (list (notmuch-select-tag-with-completion
+	  "Tag to remove: "
+	  (if (region-active-p)
+	      (mapconcat 'identity
+			 (notmuch-search-find-thread-id-region (region-beginning) (region-end))
+			 " ")
+	    (notmuch-search-find-thread-id)))))
+  (save-excursion
+    (if (region-active-p)
+	(let* ((beg (region-beginning))
+	       (end (region-end)))
+	  (notmuch-search-remove-tag-region tag beg end))
+      (notmuch-search-remove-tag-thread tag))))
 
 (defun notmuch-search-archive-thread ()
   "Archive the currently selected thread (remove its \"inbox\" tag).
 
 This function advances the next thread when finished."
   (interactive)
-  (notmuch-search-remove-tag "inbox")
+  (notmuch-search-remove-tag-thread "inbox")
   (forward-line))
 
 (defun notmuch-search-process-sentinel (proc msg)
-- 
1.6.3.3



More information about the notmuch mailing list