* Re: [PATCH] Support for deletion (patch included) [not found] <829811857.5353531267112884804.JavaMail.root@zimbra1-e1.priv.proxad.net> @ 2010-02-25 15:51 ` racin 0 siblings, 0 replies; 7+ messages in thread From: racin @ 2010-02-25 15:51 UTC (permalink / raw To: Carl Worth; +Cc: notmuch Carl: The patch in the mail has problems; apparently I have to manually add scissorlines to the mail for it to be processed by git-am. I thought this was automatically added. (I hate the git UI -- nothing is consistent, concepts have different names, the definition of scissor lines is as precise as "A line that mainly consists of scissors (either ">8" or "8<") and perforation (dash "-") --, but I guess we can get used to it after a while...) I'll send you a proper patch as soon as I can. Meanwhile, I'm sure you have comments on this updated patch! Matthieu À: "Carl Worth" <cworth@cworth.org> Cc: notmuch@notmuchmail.org Envoyé: Jeudi 25 Février 2010 00h00:04 GMT +00:00 GMT - Grande-Bretagne, Irlande, Portugal Objet: Re: [notmuch] [PATCH] Support for deletion (patch included) Hi Carl, > Could you also write a commit message describing what the patch does? > The easiest way for me to apply that would be if you would create a git > commit, then run "git format-patch origin/master" and mail the resulting > files, (the "git send-email" command can be used here, or you can insert > the files into a mail-composition buffer and modify them as needed). > OK, here it is (comments below). I had trouble splitting the patches into a patch series; I found git add -p, but isn't there a better interface for selecting patches? From bdee9558d93bffb97c80632f522288e059deb7c2 Mon Sep 17 00:00:00 2001 From: Matthieu Lemerre <racin@racin.rez-gif.supelec.fr> Date: Thu, 25 Feb 2010 00:24:24 +0100 Subject: [PATCH 1/2] Add and use notmuch-show-forall-in-thread macro --- notmuch.el | 17 +++++++++++------ 1 files changed, 11 insertions(+), 6 deletions(-) diff --git a/notmuch.el b/notmuch.el index 6482170..5d7342a 100644 --- a/notmuch.el +++ b/notmuch.el @@ -321,17 +321,22 @@ pseudoheader summary" (cons (notmuch-show-get-message-id) nil))) (notmuch-show-set-tags (sort (set-difference tags toremove :test 'string=) 'string<)))))) -(defun notmuch-show-archive-thread-maybe-mark-read (markread) - (save-excursion +(defmacro notmuch-show-forall-in-thread (&rest body) + "Executes BODY with point in all messages of the current thread." + `(save-excursion (goto-char (point-min)) (while (not (eobp)) - (if markread - (notmuch-show-remove-tag "unread" "inbox") - (notmuch-show-remove-tag "inbox")) + ,@body (if (not (eobp)) (forward-char)) (if (not (re-search-forward notmuch-show-message-begin-regexp nil t)) - (goto-char (point-max))))) + (goto-char (point-max)))))) + +(defun notmuch-show-archive-thread-maybe-mark-read (markread) + (notmuch-show-forall-in-thread + (if markread + (notmuch-show-remove-tag "unread" "inbox") + (notmuch-show-remove-tag "inbox"))) (let ((parent-buffer notmuch-show-parent-buffer)) (kill-this-buffer) (if parent-buffer -- 1.6.5 This first patch is helpful for factorizing out code. Basically, it allows to apply a "message-only" command to all the thread. From 0073152e3fa7dd11d88de28e87eec7762cdbbbeb Mon Sep 17 00:00:00 2001 From: Matthieu Lemerre <racin@racin.rez-gif.supelec.fr> Date: Thu, 25 Feb 2010 00:25:51 +0100 Subject: [PATCH 2/2] Add support for deletion in the emacs interface --- notmuch.el | 56 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 49 insertions(+), 7 deletions(-) diff --git a/notmuch.el b/notmuch.el index 5d7342a..0285573 100644 --- a/notmuch.el +++ b/notmuch.el @@ -92,6 +92,8 @@ (define-key map "x" 'notmuch-show-archive-thread-then-exit) (define-key map "A" 'notmuch-show-mark-read-then-archive-thread) (define-key map "a" 'notmuch-show-archive-thread) + (define-key map "d" 'notmuch-show-delete-thread) + (define-key map "D" 'notmuch-show-delete-message) (define-key map "p" 'notmuch-show-previous-message) (define-key map "N" 'notmuch-show-mark-read-then-next-open-message) (define-key map "n" 'notmuch-show-next-message) @@ -380,6 +382,23 @@ buffer." (notmuch-show-archive-thread) (kill-this-buffer)) +(defun notmuch-show-delete-message () + "Delete current message (sets its deleted tag)." + (interactive) + (notmuch-show-add-tag "deleted")) + +(defun notmuch-show-delete-thread() + "Delete each message in thread." + (interactive) + (notmuch-show-forall-in-thread + (notmuch-show-delete-message))) + +(defun notmuch-show-delete-thread-and-exit() + "Delete each message in thread, then exit back to search results." + (interactive) + (notmuch-show-delete-thread) + (kill-this-buffer)) + (defun notmuch-show-mark-read-then-archive-then-exit () "Remove unread tags from thread, then archive and exit to search results." (interactive) @@ -1227,6 +1246,7 @@ matching this search term are shown if non-nil. " (define-key map [mouse-1] 'notmuch-search-show-thread) (define-key map "*" 'notmuch-search-operate-all) (define-key map "a" 'notmuch-search-archive-thread) + (define-key map "d" 'notmuch-search-delete-thread) (define-key map "-" 'notmuch-search-remove-tag) (define-key map "+" 'notmuch-search-add-tag) (define-key map (kbd "RET") 'notmuch-search-show-thread) @@ -1235,6 +1255,7 @@ matching this search term are shown if non-nil. " (fset 'notmuch-search-mode-map notmuch-search-mode-map) (defvar notmuch-search-query-string) +(defvar notmuch-search-history nil) (defvar notmuch-search-oldest-first t "Show the oldest mail first in the search-mode") @@ -1446,6 +1467,13 @@ This function advances the next thread when finished." (notmuch-search-remove-tag "inbox") (forward-line)) +(defun notmuch-search-delete-thread () + "Mark the currently selected thread as deleted (set its \"deleted\" tag). +This function advances the next thread when finished." + (interactive) + (notmuch-search-add-tag "deleted") + (forward-line)) + (defun notmuch-search-process-sentinel (proc msg) "Add a message to let user know when \"notmuch search\" exits" (let ((buffer (process-buffer proc)) @@ -1520,10 +1548,22 @@ characters as well as `_.+-'. (append action-split (list notmuch-search-query-string) nil)))) ;;;###autoload -(defun notmuch-search (query &optional oldest-first) - "Run \"notmuch search\" with the given query string and display results." - (interactive "sNotmuch search: ") - (let ((buffer (get-buffer-create (concat "*notmuch-search-" query "*")))) +(defun notmuch-search (query &optional oldest-first include-deleted) + "Run \"notmuch search\" with the given query string and display results. + +With prefix argument, include deleted items. +" + (interactive (let* ((prefix current-prefix-arg) + (query (if prefix + (read-string "Notmuch search (including deleted): " + notmuch-search-query-string + 'notmuch-search-history) + (read-string "Notmuch search: " nil + 'notmuch-search-history)))) + (list query nil prefix))) + (let ((real-query (if include-deleted query + (concat "not tag:deleted and (" query ")"))) + (buffer (get-buffer-create (concat "*notmuch-search-" query "*")))) (switch-to-buffer buffer) (notmuch-search-mode) (set 'notmuch-search-query-string query) @@ -1539,7 +1579,7 @@ characters as well as `_.+-'. (let ((proc (start-process-shell-command "notmuch-search" buffer notmuch-command "search" (if oldest-first "--sort=oldest-first" "--sort=newest-first") - (shell-quote-argument query)))) + (shell-quote-argument real-query)))) (set-process-sentinel proc 'notmuch-search-process-sentinel) (set-process-filter proc 'notmuch-search-process-filter)))) (run-hooks 'notmuch-search-hook))) @@ -1587,7 +1627,7 @@ search." Runs a new search matching only messages that match both the current search results AND the additional query string provided." - (interactive "sFilter search: ") + (interactive "sFilter search:") (let ((grouped-query (if (string-match-p notmuch-search-disjunctive-regexp query) (concat "( " query " )") query))) (notmuch-search (concat notmuch-search-query-string " and " grouped-query) notmuch-search-oldest-first))) @@ -1630,7 +1670,9 @@ current search results AND that are tagged with the given tag." (fset 'notmuch-folder-mode-map notmuch-folder-mode-map) -(defcustom notmuch-folders (quote (("inbox" . "tag:inbox") ("unread" . "tag:unread"))) +(defcustom notmuch-folders (quote (("inbox" . "tag:inbox") + ("unread" . "tag:unread") + ("deleted" . "tag:deleted"))) "List of searches for the notmuch folder view" :type '(alist :key-type (string) :value-type (string)) :group 'notmuch) -- 1.6.5 This second patch is the reworked patch, after your comments. > A couple of minor comments on the patch: > > > (define-key map "a" 'notmuch-search-archive-thread) > > + (define-key map "d" 'notmuch-search-mark-as-deleted) > > For consistency, let's name this notmuch-search-delete-thread. > > And we'll probably want a notmuch-show-delete-message function as well, > no? Did both. I have however a question: how to handle in the UI the thread/message distinction? For now, I set "d" in notmuch-show buffer to act as "delete the current thread", and "D" as "delete the current message". I thought that as "d" meant in notmuch summary "delete the current thread", the bindings would be more consistent. But now I wonder if this may be counter intuitive, and if we should use "d" for "delete current message" and "D" for "delete current thread". What do people think? It would be nice to have, in general a convenient way to handle the thread/message distinction in the UI (e.g. for applying other tags). > > > +(defvar notmuch-search-history nil) > > Excellent! I've wanted custom search history for a while, and just > didn't know how to do it with (interactive "s"). It looks easy enough > with read-string as you're doing here. But this is independent > functionality, so would be preferred as an independent patch/commit. In fact I needed this; that way when you do "C-u s", the previous search is shown, and to include deleted items you just have to do "C-u s RET". So I made them in a single commit; but I can split them if you really want to. > > > (forward-line)) > > > > + > > +(defun notmuch-search-mark-as-deleted () > > + "Mark the currently selected thread as deleted (set its \"deleted\" tag). > > +This function advances the next thread when finished." > > + (interactive) > > + (notmuch-search-add-tag "deleted") > > + (forward-line)) > > + > > + > > (defun notmuch-search-process-sentinel (proc msg) > > Watch that extra whitespace. The convention is a single line of > whitespace between each function. > My bad. I did not see this in my review. Corrected this in the updated patch. > And should we also archive the thread before removing the deleted tag? I don't understand this. Do you mean: should we also archive the thread before setting the deleted tag? I don't known why we should bother to do it, as the tag is not show by the next results. I would tend to think that archiving should be an explicit action, that should call a hook. For instance, I'd like my mailflow to be like this: - get mail with offlineimap => a maildir directory, indexed by notmuch - mails stay in inbox until I archive it. That way I can still access it with IMAP. - archiving puts an "archived" tag (and removes the inbox and unread tags), and move the mail to another directory (or uses git to archive the mail). - deleting puts a deleted tag (but the messages stays inbox as long as I do not explicitely remove this). The main reason is that many mail servers only allow small quotas, so you have to carefully select which mail should stay inbox (only the mail that you need external access). In brief, this mail flow needs to delete threads but not to archive it. I think that we could provide hooks, so that you can archive mails when you delete them if you like to. By the way in my patch commentary, you said that you planned to change the "inbox" and "unread" treatments to be more explicit. Do you still plan to do that? I can maybe also provide a patch. > > +With prefix argument, include deleted items. > > That's a pretty good interface I think. > > Another approach would be to do something like what sup does---that > would be to scan the search terms and if it contains "tag:deleted" and > all then don't prepend the "not tag:deleted and" to the search > string. The assumption there is that if the user is explicitly > mentioning the deleted tag, then we should just rely on the user to > explicitly describe how the tag should be treated. > > That's perhaps not an unreasonable heuristic, and might be done even in > addition to the prefix-argument approach. But that could be an > additional commit, and I won't require it. Hmm, that's what I did want to do initially. In that case, I think that notmuch should be able to output parse trees from notmuch search strings as JSON; this would help do the parsing in the various implementations. I also had this idea that may solve the "tag should be orthogonal/command-line UI problem". We observe that "archived" is contrary to "inbox", "read" contrary to "unread", "deleted" contrary to "undeleted", and so on. So it may be a good idea to have "pseudo-tags", that would help in the interface (searching archived mails with search not tag:inbox is not very intuitive...), as synonyms for "not tag:countrary-tag" Then for each "pseudo-tag", notmuch could hard-code which is included by default. Adding the other tags is easy: just add "and tag:deleted" or "and tag:read" or "and tag:archived". Moreover, this would simplify UI implementation as well, without requiring parsing of the strings. Another, even simpler possibility would be to add a "--all" flag to notmuch. Without it, it would omit some of the tags (like the deleted ones), which would be convenient as a text interface. With it, it would show all tags, which would be convenient for use with scripts and UI, and mor in the "tags are orthogonal" spirit. Again, this would not require to parse search strings, and imho would be much cleaner. > > + (interactive (let* ((prefix current-prefix-arg) > > + (query (if prefix > > + (read-string "Notmuch search (including deleted): " > > + notmuch-search-query-string > > + 'notmuch-search-history) > > + (read-string "Notmuch search: " nil > > + 'notmuch-search-history)))) > > Why is the second (initial-input) argument non-nil in one case, but nil > in the other? The documentation for `read-string' says the argument is > deprecated and should be nil in all new code. The idea is that you do not have default search terms if you do regular searchs. But if you want to include deleted items, then you have the last search string. This way, you handle the common case when you serach for a term, do not find it, then decide to try again with deleted items. Now, maybe the C-u interface is not such a good idea, and a toggle button would be better. Don't know, but I find this interface convenient. > > > + (list query nil prefix))) > > + (let ((real-query (if include-deleted query > > + (concat "not tag:deleted and (" query ")"))) > > + (buffer (get-buffer-create (concat "*notmuch-search-" query > > "*")))) > > Does the include-deleted case actually work? I don't see anything in the > code that sets this variable. (I'm just reviewing here--I haven't tested > it manually). This is the way interactive work. (defun notmuch-search (query &optional oldest-first include-deleted) ... + (interactive (let* ((prefix current-prefix-arg) ... + (list query nil prefix))) The (list query nil prefix) at the end of the (interactive) form will set query to query, nil to oldest-first, and prefix to include-deleted. > > > @@ -1351,7 +1374,6 @@ search." > > > > Runs a new search matching only messages that match both the > > current search results AND the additional query string provided." > > - (interactive "sFilter search: ") > > (let ((grouped-query (if (string-match-p notmuch-search-disjunctive-regexp query) (concat "( " query " )") query))) > > (notmuch-search (concat notmuch-search-query-string " and " grouped-query) notmuch-search-oldest-first))) > > Is this just an accidental chunk in the patch? I don't see why this > function should become non-interactive now. My bad, corrected that also. Matthieu _______________________________________________ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch ^ permalink raw reply related [flat|nested] 7+ messages in thread
[parent not found: <1427711643.5760731267266834921.JavaMail.root@zimbra1-e1.priv.proxad.net>]
* Re: [PATCH] Support for deletion (patch included) [not found] <1427711643.5760731267266834921.JavaMail.root@zimbra1-e1.priv.proxad.net> @ 2010-02-27 10:34 ` racin 0 siblings, 0 replies; 7+ messages in thread From: racin @ 2010-02-27 10:34 UTC (permalink / raw To: Carl Worth; +Cc: notmuch [-- Attachment #1: Type: text/plain, Size: 804 bytes --] Here they are; as I don't know how to include them in the body, I put the patches as attachments. I hope this will be convienient enough for you. Matthieu ----- racin@free.fr a écrit : > Carl: The patch in the mail has problems; apparently I have to > manually add scissorlines to the mail for it > to be processed by git-am. I thought this was automatically added. (I > hate the git UI -- nothing is consistent, > concepts have different names, the definition of scissor lines is as > precise as "A line that mainly consists of scissors (either ">8" or > "8<") and perforation (dash "-") --, but I guess we can get used to it > after a while...) > > I'll send you a proper patch as soon as I can. Meanwhile, I'm sure you > have comments on this updated patch! > > Matthieu > [-- Attachment #2: 0002-Add-support-for-deletion-in-the-emacs-interface.patch --] [-- Type: text/x-diff, Size: 5933 bytes --] From 0073152e3fa7dd11d88de28e87eec7762cdbbbeb Mon Sep 17 00:00:00 2001 From: Matthieu Lemerre <racin@free.fr> Date: Thu, 25 Feb 2010 00:25:51 +0100 Subject: [PATCH 2/2] Add support for deletion in the emacs interface Add "d" keybinding in notmuch-show and notmuch-summary to delete the current thread. Adds "D" keybinding to delete the current message in notmuch-show. Adds a "deleted" folder. Omit deleted items from searchs if no prefix arg. Adds history management to make searching deleted items more convenient. --- notmuch.el | 56 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 49 insertions(+), 7 deletions(-) diff --git a/notmuch.el b/notmuch.el index 5d7342a..0285573 100644 --- a/notmuch.el +++ b/notmuch.el @@ -92,6 +92,8 @@ (define-key map "x" 'notmuch-show-archive-thread-then-exit) (define-key map "A" 'notmuch-show-mark-read-then-archive-thread) (define-key map "a" 'notmuch-show-archive-thread) + (define-key map "d" 'notmuch-show-delete-thread) + (define-key map "D" 'notmuch-show-delete-message) (define-key map "p" 'notmuch-show-previous-message) (define-key map "N" 'notmuch-show-mark-read-then-next-open-message) (define-key map "n" 'notmuch-show-next-message) @@ -380,6 +382,23 @@ buffer." (notmuch-show-archive-thread) (kill-this-buffer)) +(defun notmuch-show-delete-message () + "Delete current message (sets its deleted tag)." + (interactive) + (notmuch-show-add-tag "deleted")) + +(defun notmuch-show-delete-thread() + "Delete each message in thread." + (interactive) + (notmuch-show-forall-in-thread + (notmuch-show-delete-message))) + +(defun notmuch-show-delete-thread-and-exit() + "Delete each message in thread, then exit back to search results." + (interactive) + (notmuch-show-delete-thread) + (kill-this-buffer)) + (defun notmuch-show-mark-read-then-archive-then-exit () "Remove unread tags from thread, then archive and exit to search results." (interactive) @@ -1227,6 +1246,7 @@ matching this search term are shown if non-nil. " (define-key map [mouse-1] 'notmuch-search-show-thread) (define-key map "*" 'notmuch-search-operate-all) (define-key map "a" 'notmuch-search-archive-thread) + (define-key map "d" 'notmuch-search-delete-thread) (define-key map "-" 'notmuch-search-remove-tag) (define-key map "+" 'notmuch-search-add-tag) (define-key map (kbd "RET") 'notmuch-search-show-thread) @@ -1235,6 +1255,7 @@ matching this search term are shown if non-nil. " (fset 'notmuch-search-mode-map notmuch-search-mode-map) (defvar notmuch-search-query-string) +(defvar notmuch-search-history nil) (defvar notmuch-search-oldest-first t "Show the oldest mail first in the search-mode") @@ -1446,6 +1467,13 @@ This function advances the next thread when finished." (notmuch-search-remove-tag "inbox") (forward-line)) +(defun notmuch-search-delete-thread () + "Mark the currently selected thread as deleted (set its \"deleted\" tag). +This function advances the next thread when finished." + (interactive) + (notmuch-search-add-tag "deleted") + (forward-line)) + (defun notmuch-search-process-sentinel (proc msg) "Add a message to let user know when \"notmuch search\" exits" (let ((buffer (process-buffer proc)) @@ -1520,10 +1548,22 @@ characters as well as `_.+-'. (append action-split (list notmuch-search-query-string) nil)))) ;;;###autoload -(defun notmuch-search (query &optional oldest-first) - "Run \"notmuch search\" with the given query string and display results." - (interactive "sNotmuch search: ") - (let ((buffer (get-buffer-create (concat "*notmuch-search-" query "*")))) +(defun notmuch-search (query &optional oldest-first include-deleted) + "Run \"notmuch search\" with the given query string and display results. + +With prefix argument, include deleted items. +" + (interactive (let* ((prefix current-prefix-arg) + (query (if prefix + (read-string "Notmuch search (including deleted): " + notmuch-search-query-string + 'notmuch-search-history) + (read-string "Notmuch search: " nil + 'notmuch-search-history)))) + (list query nil prefix))) + (let ((real-query (if include-deleted query + (concat "not tag:deleted and (" query ")"))) + (buffer (get-buffer-create (concat "*notmuch-search-" query "*")))) (switch-to-buffer buffer) (notmuch-search-mode) (set 'notmuch-search-query-string query) @@ -1539,7 +1579,7 @@ characters as well as `_.+-'. (let ((proc (start-process-shell-command "notmuch-search" buffer notmuch-command "search" (if oldest-first "--sort=oldest-first" "--sort=newest-first") - (shell-quote-argument query)))) + (shell-quote-argument real-query)))) (set-process-sentinel proc 'notmuch-search-process-sentinel) (set-process-filter proc 'notmuch-search-process-filter)))) (run-hooks 'notmuch-search-hook))) @@ -1587,7 +1627,7 @@ search." Runs a new search matching only messages that match both the current search results AND the additional query string provided." - (interactive "sFilter search: ") + (interactive "sFilter search:") (let ((grouped-query (if (string-match-p notmuch-search-disjunctive-regexp query) (concat "( " query " )") query))) (notmuch-search (concat notmuch-search-query-string " and " grouped-query) notmuch-search-oldest-first))) @@ -1630,7 +1670,9 @@ current search results AND that are tagged with the given tag." (fset 'notmuch-folder-mode-map notmuch-folder-mode-map) -(defcustom notmuch-folders (quote (("inbox" . "tag:inbox") ("unread" . "tag:unread"))) +(defcustom notmuch-folders (quote (("inbox" . "tag:inbox") + ("unread" . "tag:unread") + ("deleted" . "tag:deleted"))) "List of searches for the notmuch folder view" :type '(alist :key-type (string) :value-type (string)) :group 'notmuch) -- 1.6.5 [-- Attachment #3: 0001-Add-and-use-notmuch-show-forall-in-thread-macro.patch --] [-- Type: text/x-diff, Size: 1580 bytes --] From bdee9558d93bffb97c80632f522288e059deb7c2 Mon Sep 17 00:00:00 2001 From: Matthieu Lemerre <racin@free.fr> Date: Thu, 25 Feb 2010 00:24:24 +0100 Subject: [PATCH 1/2] Add and use notmuch-show-forall-in-thread macro This macro allows to apply a message-related command to every message in a thread. --- notmuch.el | 17 +++++++++++------ 1 files changed, 11 insertions(+), 6 deletions(-) diff --git a/notmuch.el b/notmuch.el index 6482170..5d7342a 100644 --- a/notmuch.el +++ b/notmuch.el @@ -321,17 +321,22 @@ pseudoheader summary" (cons (notmuch-show-get-message-id) nil))) (notmuch-show-set-tags (sort (set-difference tags toremove :test 'string=) 'string<)))))) -(defun notmuch-show-archive-thread-maybe-mark-read (markread) - (save-excursion +(defmacro notmuch-show-forall-in-thread (&rest body) + "Executes BODY with point in all messages of the current thread." + `(save-excursion (goto-char (point-min)) (while (not (eobp)) - (if markread - (notmuch-show-remove-tag "unread" "inbox") - (notmuch-show-remove-tag "inbox")) + ,@body (if (not (eobp)) (forward-char)) (if (not (re-search-forward notmuch-show-message-begin-regexp nil t)) - (goto-char (point-max))))) + (goto-char (point-max)))))) + +(defun notmuch-show-archive-thread-maybe-mark-read (markread) + (notmuch-show-forall-in-thread + (if markread + (notmuch-show-remove-tag "unread" "inbox") + (notmuch-show-remove-tag "inbox"))) (let ((parent-buffer notmuch-show-parent-buffer)) (kill-this-buffer) (if parent-buffer -- 1.6.5 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH] Support for deletion (patch included) @ 2009-12-13 11:54 Matthieu Lemerre 2010-02-24 18:49 ` Carl Worth 0 siblings, 1 reply; 7+ messages in thread From: Matthieu Lemerre @ 2009-12-13 11:54 UTC (permalink / raw To: notmuch [-- Attachment #1: Type: text/plain, Size: 28 bytes --] I forgot the attachment.. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: notmuch-deletion.patch --] [-- Type: text/x-diff, Size: 4002 bytes --] diff --git a/notmuch.el b/notmuch.el index 97914f2..f770dd0 100644 --- a/notmuch.el +++ b/notmuch.el @@ -991,6 +991,7 @@ matching this search term are shown if non-nil. " (define-key map [mouse-1] 'notmuch-search-show-thread) (define-key map "*" 'notmuch-search-operate-all) (define-key map "a" 'notmuch-search-archive-thread) + (define-key map "d" 'notmuch-search-mark-as-deleted) (define-key map "-" 'notmuch-search-remove-tag) (define-key map "+" 'notmuch-search-add-tag) (define-key map (kbd "RET") 'notmuch-search-show-thread) @@ -999,6 +1000,7 @@ matching this search term are shown if non-nil. " (fset 'notmuch-search-mode-map notmuch-search-mode-map) (defvar notmuch-search-query-string) +(defvar notmuch-search-history nil) (defvar notmuch-search-oldest-first t "Show the oldest mail first in the search-mode") @@ -1210,6 +1212,15 @@ This function advances the next thread when finished." (notmuch-search-remove-tag "inbox") (forward-line)) + +(defun notmuch-search-mark-as-deleted () + "Mark the currently selected thread as deleted (set its \"deleted\" tag). +This function advances the next thread when finished." + (interactive) + (notmuch-search-add-tag "deleted") + (forward-line)) + + (defun notmuch-search-process-sentinel (proc msg) "Add a message to let user know when \"notmuch search\" exits" (let ((buffer (process-buffer proc)) @@ -1284,10 +1295,22 @@ characters as well as `_.+-'. (append action-split (list notmuch-search-query-string) nil)))) ;;;###autoload -(defun notmuch-search (query &optional oldest-first) - "Run \"notmuch search\" with the given query string and display results." - (interactive "sNotmuch search: ") - (let ((buffer (get-buffer-create (concat "*notmuch-search-" query "*")))) +(defun notmuch-search (query &optional oldest-first include-deleted) + "Run \"notmuch search\" with the given query string and display results. + +With prefix argument, include deleted items. +" + (interactive (let* ((prefix current-prefix-arg) + (query (if prefix + (read-string "Notmuch search (including deleted): " + notmuch-search-query-string + 'notmuch-search-history) + (read-string "Notmuch search: " nil + 'notmuch-search-history)))) + (list query nil prefix))) + (let ((real-query (if include-deleted query + (concat "not tag:deleted and (" query ")"))) + (buffer (get-buffer-create (concat "*notmuch-search-" query "*")))) (switch-to-buffer buffer) (notmuch-search-mode) (set 'notmuch-search-query-string query) @@ -1303,7 +1326,7 @@ characters as well as `_.+-'. (let ((proc (start-process-shell-command "notmuch-search" buffer notmuch-command "search" (if oldest-first "--sort=oldest-first" "--sort=newest-first") - (shell-quote-argument query)))) + (shell-quote-argument real-query)))) (set-process-sentinel proc 'notmuch-search-process-sentinel) (set-process-filter proc 'notmuch-search-process-filter)))) (run-hooks 'notmuch-search-hook))) @@ -1351,7 +1374,6 @@ search." Runs a new search matching only messages that match both the current search results AND the additional query string provided." - (interactive "sFilter search: ") (let ((grouped-query (if (string-match-p notmuch-search-disjunctive-regexp query) (concat "( " query " )") query))) (notmuch-search (concat notmuch-search-query-string " and " grouped-query) notmuch-search-oldest-first))) @@ -1391,7 +1413,9 @@ current search results AND that are tagged with the given tag." (fset 'notmuch-folder-mode-map notmuch-folder-mode-map) -(defcustom notmuch-folders (quote (("inbox" . "tag:inbox") ("unread" . "tag:unread"))) +(defcustom notmuch-folders (quote (("inbox" . "tag:inbox") + ("unread" . "tag:unread") + ("deleted" . "tag:deleted"))) "List of searches for the notmuch folder view" :type '(alist :key-type (string) :value-type (string)) :group 'notmuch) ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] Support for deletion (patch included) 2009-12-13 11:54 Matthieu Lemerre @ 2010-02-24 18:49 ` Carl Worth 2010-02-25 0:00 ` racin 0 siblings, 1 reply; 7+ messages in thread From: Carl Worth @ 2010-02-24 18:49 UTC (permalink / raw To: Matthieu Lemerre, notmuch [-- Attachment #1: Type: text/plain, Size: 3883 bytes --] On Sun, 13 Dec 2009 12:54:09 +0100, Matthieu Lemerre <racin@free.fr> wrote: > I forgot the attachment.. Hi Matthieu, This is a very interesting patch. Thanks for contributing it. Could you also write a commit message describing what the patch does? The easiest way for me to apply that would be if you would create a git commit, then run "git format-patch origin/master" and mail the resulting files, (the "git send-email" command can be used here, or you can insert the files into a mail-composition buffer and modify them as needed). A couple of minor comments on the patch: > (define-key map "a" 'notmuch-search-archive-thread) > + (define-key map "d" 'notmuch-search-mark-as-deleted) For consistency, let's name this notmuch-search-delete-thread. And we'll probably want a notmuch-show-delete-message function as well, no? > +(defvar notmuch-search-history nil) Excellent! I've wanted custom search history for a while, and just didn't know how to do it with (interactive "s"). It looks easy enough with read-string as you're doing here. But this is independent functionality, so would be preferred as an independent patch/commit. > (forward-line)) > > + > +(defun notmuch-search-mark-as-deleted () > + "Mark the currently selected thread as deleted (set its \"deleted\" tag). > +This function advances the next thread when finished." > + (interactive) > + (notmuch-search-add-tag "deleted") > + (forward-line)) > + > + > (defun notmuch-search-process-sentinel (proc msg) Watch that extra whitespace. The convention is a single line of whitespace between each function. And should we also archive the thread before removing the deleted tag? > +With prefix argument, include deleted items. That's a pretty good interface I think. Another approach would be to do something like what sup does---that would be to scan the search terms and if it contains "tag:deleted" and all then don't prepend the "not tag:deleted and" to the search string. The assumption there is that if the user is explicitly mentioning the deleted tag, then we should just rely on the user to explicitly describe how the tag should be treated. That's perhaps not an unreasonable heuristic, and might be done even in addition to the prefix-argument approach. But that could be an additional commit, and I won't require it. > + (interactive (let* ((prefix current-prefix-arg) > + (query (if prefix > + (read-string "Notmuch search (including deleted): " > + notmuch-search-query-string > + 'notmuch-search-history) > + (read-string "Notmuch search: " nil > + 'notmuch-search-history)))) Why is the second (initial-input) argument non-nil in one case, but nil in the other? The documentation for `read-string' says the argument is deprecated and should be nil in all new code. > + (list query nil prefix))) > + (let ((real-query (if include-deleted query > + (concat "not tag:deleted and (" query ")"))) > + (buffer (get-buffer-create (concat "*notmuch-search-" query > "*")))) Does the include-deleted case actually work? I don't see anything in the code that sets this variable. (I'm just reviewing here--I haven't tested it manually). > @@ -1351,7 +1374,6 @@ search." > > Runs a new search matching only messages that match both the > current search results AND the additional query string provided." > - (interactive "sFilter search: ") > (let ((grouped-query (if (string-match-p notmuch-search-disjunctive-regexp query) (concat "( " query " )") query))) > (notmuch-search (concat notmuch-search-query-string " and " grouped-query) notmuch-search-oldest-first))) Is this just an accidental chunk in the patch? I don't see why this function should become non-interactive now. Thanks again, -Carl [-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Support for deletion (patch included) 2010-02-24 18:49 ` Carl Worth @ 2010-02-25 0:00 ` racin 2010-02-25 10:49 ` Sebastian Spaeth 2010-03-01 9:09 ` Michal Sojka 0 siblings, 2 replies; 7+ messages in thread From: racin @ 2010-02-25 0:00 UTC (permalink / raw To: Carl Worth; +Cc: notmuch Hi Carl, > Could you also write a commit message describing what the patch does? > The easiest way for me to apply that would be if you would create a git > commit, then run "git format-patch origin/master" and mail the resulting > files, (the "git send-email" command can be used here, or you can insert > the files into a mail-composition buffer and modify them as needed). > OK, here it is (comments below). I had trouble splitting the patches into a patch series; I found git add -p, but isn't there a better interface for selecting patches? From bdee9558d93bffb97c80632f522288e059deb7c2 Mon Sep 17 00:00:00 2001 From: Matthieu Lemerre <racin@racin.rez-gif.supelec.fr> Date: Thu, 25 Feb 2010 00:24:24 +0100 Subject: [PATCH 1/2] Add and use notmuch-show-forall-in-thread macro --- notmuch.el | 17 +++++++++++------ 1 files changed, 11 insertions(+), 6 deletions(-) diff --git a/notmuch.el b/notmuch.el index 6482170..5d7342a 100644 --- a/notmuch.el +++ b/notmuch.el @@ -321,17 +321,22 @@ pseudoheader summary" (cons (notmuch-show-get-message-id) nil))) (notmuch-show-set-tags (sort (set-difference tags toremove :test 'string=) 'string<)))))) -(defun notmuch-show-archive-thread-maybe-mark-read (markread) - (save-excursion +(defmacro notmuch-show-forall-in-thread (&rest body) + "Executes BODY with point in all messages of the current thread." + `(save-excursion (goto-char (point-min)) (while (not (eobp)) - (if markread - (notmuch-show-remove-tag "unread" "inbox") - (notmuch-show-remove-tag "inbox")) + ,@body (if (not (eobp)) (forward-char)) (if (not (re-search-forward notmuch-show-message-begin-regexp nil t)) - (goto-char (point-max))))) + (goto-char (point-max)))))) + +(defun notmuch-show-archive-thread-maybe-mark-read (markread) + (notmuch-show-forall-in-thread + (if markread + (notmuch-show-remove-tag "unread" "inbox") + (notmuch-show-remove-tag "inbox"))) (let ((parent-buffer notmuch-show-parent-buffer)) (kill-this-buffer) (if parent-buffer -- 1.6.5 This first patch is helpful for factorizing out code. Basically, it allows to apply a "message-only" command to all the thread. From 0073152e3fa7dd11d88de28e87eec7762cdbbbeb Mon Sep 17 00:00:00 2001 From: Matthieu Lemerre <racin@racin.rez-gif.supelec.fr> Date: Thu, 25 Feb 2010 00:25:51 +0100 Subject: [PATCH 2/2] Add support for deletion in the emacs interface --- notmuch.el | 56 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 49 insertions(+), 7 deletions(-) diff --git a/notmuch.el b/notmuch.el index 5d7342a..0285573 100644 --- a/notmuch.el +++ b/notmuch.el @@ -92,6 +92,8 @@ (define-key map "x" 'notmuch-show-archive-thread-then-exit) (define-key map "A" 'notmuch-show-mark-read-then-archive-thread) (define-key map "a" 'notmuch-show-archive-thread) + (define-key map "d" 'notmuch-show-delete-thread) + (define-key map "D" 'notmuch-show-delete-message) (define-key map "p" 'notmuch-show-previous-message) (define-key map "N" 'notmuch-show-mark-read-then-next-open-message) (define-key map "n" 'notmuch-show-next-message) @@ -380,6 +382,23 @@ buffer." (notmuch-show-archive-thread) (kill-this-buffer)) +(defun notmuch-show-delete-message () + "Delete current message (sets its deleted tag)." + (interactive) + (notmuch-show-add-tag "deleted")) + +(defun notmuch-show-delete-thread() + "Delete each message in thread." + (interactive) + (notmuch-show-forall-in-thread + (notmuch-show-delete-message))) + +(defun notmuch-show-delete-thread-and-exit() + "Delete each message in thread, then exit back to search results." + (interactive) + (notmuch-show-delete-thread) + (kill-this-buffer)) + (defun notmuch-show-mark-read-then-archive-then-exit () "Remove unread tags from thread, then archive and exit to search results." (interactive) @@ -1227,6 +1246,7 @@ matching this search term are shown if non-nil. " (define-key map [mouse-1] 'notmuch-search-show-thread) (define-key map "*" 'notmuch-search-operate-all) (define-key map "a" 'notmuch-search-archive-thread) + (define-key map "d" 'notmuch-search-delete-thread) (define-key map "-" 'notmuch-search-remove-tag) (define-key map "+" 'notmuch-search-add-tag) (define-key map (kbd "RET") 'notmuch-search-show-thread) @@ -1235,6 +1255,7 @@ matching this search term are shown if non-nil. " (fset 'notmuch-search-mode-map notmuch-search-mode-map) (defvar notmuch-search-query-string) +(defvar notmuch-search-history nil) (defvar notmuch-search-oldest-first t "Show the oldest mail first in the search-mode") @@ -1446,6 +1467,13 @@ This function advances the next thread when finished." (notmuch-search-remove-tag "inbox") (forward-line)) +(defun notmuch-search-delete-thread () + "Mark the currently selected thread as deleted (set its \"deleted\" tag). +This function advances the next thread when finished." + (interactive) + (notmuch-search-add-tag "deleted") + (forward-line)) + (defun notmuch-search-process-sentinel (proc msg) "Add a message to let user know when \"notmuch search\" exits" (let ((buffer (process-buffer proc)) @@ -1520,10 +1548,22 @@ characters as well as `_.+-'. (append action-split (list notmuch-search-query-string) nil)))) ;;;###autoload -(defun notmuch-search (query &optional oldest-first) - "Run \"notmuch search\" with the given query string and display results." - (interactive "sNotmuch search: ") - (let ((buffer (get-buffer-create (concat "*notmuch-search-" query "*")))) +(defun notmuch-search (query &optional oldest-first include-deleted) + "Run \"notmuch search\" with the given query string and display results. + +With prefix argument, include deleted items. +" + (interactive (let* ((prefix current-prefix-arg) + (query (if prefix + (read-string "Notmuch search (including deleted): " + notmuch-search-query-string + 'notmuch-search-history) + (read-string "Notmuch search: " nil + 'notmuch-search-history)))) + (list query nil prefix))) + (let ((real-query (if include-deleted query + (concat "not tag:deleted and (" query ")"))) + (buffer (get-buffer-create (concat "*notmuch-search-" query "*")))) (switch-to-buffer buffer) (notmuch-search-mode) (set 'notmuch-search-query-string query) @@ -1539,7 +1579,7 @@ characters as well as `_.+-'. (let ((proc (start-process-shell-command "notmuch-search" buffer notmuch-command "search" (if oldest-first "--sort=oldest-first" "--sort=newest-first") - (shell-quote-argument query)))) + (shell-quote-argument real-query)))) (set-process-sentinel proc 'notmuch-search-process-sentinel) (set-process-filter proc 'notmuch-search-process-filter)))) (run-hooks 'notmuch-search-hook))) @@ -1587,7 +1627,7 @@ search." Runs a new search matching only messages that match both the current search results AND the additional query string provided." - (interactive "sFilter search: ") + (interactive "sFilter search:") (let ((grouped-query (if (string-match-p notmuch-search-disjunctive-regexp query) (concat "( " query " )") query))) (notmuch-search (concat notmuch-search-query-string " and " grouped-query) notmuch-search-oldest-first))) @@ -1630,7 +1670,9 @@ current search results AND that are tagged with the given tag." (fset 'notmuch-folder-mode-map notmuch-folder-mode-map) -(defcustom notmuch-folders (quote (("inbox" . "tag:inbox") ("unread" . "tag:unread"))) +(defcustom notmuch-folders (quote (("inbox" . "tag:inbox") + ("unread" . "tag:unread") + ("deleted" . "tag:deleted"))) "List of searches for the notmuch folder view" :type '(alist :key-type (string) :value-type (string)) :group 'notmuch) -- 1.6.5 This second patch is the reworked patch, after your comments. > A couple of minor comments on the patch: > > > (define-key map "a" 'notmuch-search-archive-thread) > > + (define-key map "d" 'notmuch-search-mark-as-deleted) > > For consistency, let's name this notmuch-search-delete-thread. > > And we'll probably want a notmuch-show-delete-message function as well, > no? Did both. I have however a question: how to handle in the UI the thread/message distinction? For now, I set "d" in notmuch-show buffer to act as "delete the current thread", and "D" as "delete the current message". I thought that as "d" meant in notmuch summary "delete the current thread", the bindings would be more consistent. But now I wonder if this may be counter intuitive, and if we should use "d" for "delete current message" and "D" for "delete current thread". What do people think? It would be nice to have, in general a convenient way to handle the thread/message distinction in the UI (e.g. for applying other tags). > > > +(defvar notmuch-search-history nil) > > Excellent! I've wanted custom search history for a while, and just > didn't know how to do it with (interactive "s"). It looks easy enough > with read-string as you're doing here. But this is independent > functionality, so would be preferred as an independent patch/commit. In fact I needed this; that way when you do "C-u s", the previous search is shown, and to include deleted items you just have to do "C-u s RET". So I made them in a single commit; but I can split them if you really want to. > > > (forward-line)) > > > > + > > +(defun notmuch-search-mark-as-deleted () > > + "Mark the currently selected thread as deleted (set its \"deleted\" tag). > > +This function advances the next thread when finished." > > + (interactive) > > + (notmuch-search-add-tag "deleted") > > + (forward-line)) > > + > > + > > (defun notmuch-search-process-sentinel (proc msg) > > Watch that extra whitespace. The convention is a single line of > whitespace between each function. > My bad. I did not see this in my review. Corrected this in the updated patch. > And should we also archive the thread before removing the deleted tag? I don't understand this. Do you mean: should we also archive the thread before setting the deleted tag? I don't known why we should bother to do it, as the tag is not show by the next results. I would tend to think that archiving should be an explicit action, that should call a hook. For instance, I'd like my mailflow to be like this: - get mail with offlineimap => a maildir directory, indexed by notmuch - mails stay in inbox until I archive it. That way I can still access it with IMAP. - archiving puts an "archived" tag (and removes the inbox and unread tags), and move the mail to another directory (or uses git to archive the mail). - deleting puts a deleted tag (but the messages stays inbox as long as I do not explicitely remove this). The main reason is that many mail servers only allow small quotas, so you have to carefully select which mail should stay inbox (only the mail that you need external access). In brief, this mail flow needs to delete threads but not to archive it. I think that we could provide hooks, so that you can archive mails when you delete them if you like to. By the way in my patch commentary, you said that you planned to change the "inbox" and "unread" treatments to be more explicit. Do you still plan to do that? I can maybe also provide a patch. > > +With prefix argument, include deleted items. > > That's a pretty good interface I think. > > Another approach would be to do something like what sup does---that > would be to scan the search terms and if it contains "tag:deleted" and > all then don't prepend the "not tag:deleted and" to the search > string. The assumption there is that if the user is explicitly > mentioning the deleted tag, then we should just rely on the user to > explicitly describe how the tag should be treated. > > That's perhaps not an unreasonable heuristic, and might be done even in > addition to the prefix-argument approach. But that could be an > additional commit, and I won't require it. Hmm, that's what I did want to do initially. In that case, I think that notmuch should be able to output parse trees from notmuch search strings as JSON; this would help do the parsing in the various implementations. I also had this idea that may solve the "tag should be orthogonal/command-line UI problem". We observe that "archived" is contrary to "inbox", "read" contrary to "unread", "deleted" contrary to "undeleted", and so on. So it may be a good idea to have "pseudo-tags", that would help in the interface (searching archived mails with search not tag:inbox is not very intuitive...), as synonyms for "not tag:countrary-tag" Then for each "pseudo-tag", notmuch could hard-code which is included by default. Adding the other tags is easy: just add "and tag:deleted" or "and tag:read" or "and tag:archived". Moreover, this would simplify UI implementation as well, without requiring parsing of the strings. Another, even simpler possibility would be to add a "--all" flag to notmuch. Without it, it would omit some of the tags (like the deleted ones), which would be convenient as a text interface. With it, it would show all tags, which would be convenient for use with scripts and UI, and mor in the "tags are orthogonal" spirit. Again, this would not require to parse search strings, and imho would be much cleaner. > > + (interactive (let* ((prefix current-prefix-arg) > > + (query (if prefix > > + (read-string "Notmuch search (including deleted): " > > + notmuch-search-query-string > > + 'notmuch-search-history) > > + (read-string "Notmuch search: " nil > > + 'notmuch-search-history)))) > > Why is the second (initial-input) argument non-nil in one case, but nil > in the other? The documentation for `read-string' says the argument is > deprecated and should be nil in all new code. The idea is that you do not have default search terms if you do regular searchs. But if you want to include deleted items, then you have the last search string. This way, you handle the common case when you serach for a term, do not find it, then decide to try again with deleted items. Now, maybe the C-u interface is not such a good idea, and a toggle button would be better. Don't know, but I find this interface convenient. > > > + (list query nil prefix))) > > + (let ((real-query (if include-deleted query > > + (concat "not tag:deleted and (" query ")"))) > > + (buffer (get-buffer-create (concat "*notmuch-search-" query > > "*")))) > > Does the include-deleted case actually work? I don't see anything in the > code that sets this variable. (I'm just reviewing here--I haven't tested > it manually). This is the way interactive work. (defun notmuch-search (query &optional oldest-first include-deleted) ... + (interactive (let* ((prefix current-prefix-arg) ... + (list query nil prefix))) The (list query nil prefix) at the end of the (interactive) form will set query to query, nil to oldest-first, and prefix to include-deleted. > > > @@ -1351,7 +1374,6 @@ search." > > > > Runs a new search matching only messages that match both the > > current search results AND the additional query string provided." > > - (interactive "sFilter search: ") > > (let ((grouped-query (if (string-match-p notmuch-search-disjunctive-regexp query) (concat "( " query " )") query))) > > (notmuch-search (concat notmuch-search-query-string " and " grouped-query) notmuch-search-oldest-first))) > > Is this just an accidental chunk in the patch? I don't see why this > function should become non-interactive now. My bad, corrected that also. Matthieu ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] Support for deletion (patch included) 2010-02-25 0:00 ` racin @ 2010-02-25 10:49 ` Sebastian Spaeth 2010-03-01 9:09 ` Michal Sojka 1 sibling, 0 replies; 7+ messages in thread From: Sebastian Spaeth @ 2010-02-25 10:49 UTC (permalink / raw To: racin, Carl Worth; +Cc: notmuch I cannot comment on this patch, I just want to state that this functionality can also be achieved with (id:87sk90ragj.fsf@jhu.edu) "add functionality in notmuch search mode to add or remove tags by region" and (id:1266408746-28549-1-git-send-email-Sebastian@SSpaeth.de) "bind 'd' to new function notmuch-search-delete-thread-or-region" I think that "add functionality in notmuch search mode to add or remove tags by region" might be wanted functionality anyway. Sebastian ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Support for deletion (patch included) 2010-02-25 0:00 ` racin 2010-02-25 10:49 ` Sebastian Spaeth @ 2010-03-01 9:09 ` Michal Sojka 1 sibling, 0 replies; 7+ messages in thread From: Michal Sojka @ 2010-03-01 9:09 UTC (permalink / raw To: racin, Carl Worth; +Cc: notmuch On Thu, 25 Feb 2010 01:00:04 +0100 (CET), racin@free.fr wrote: > Hi Carl, > > > Could you also write a commit message describing what the patch does? > > The easiest way for me to apply that would be if you would create a git > > commit, then run "git format-patch origin/master" and mail the resulting > > files, (the "git send-email" command can be used here, or you can insert > > the files into a mail-composition buffer and modify them as needed). > > > > OK, here it is (comments below). I had trouble splitting the patches into a patch series; I > found git add -p, but isn't there a better interface for selecting > patches? What about "git gui"? Michal ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2010-03-01 9:09 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <829811857.5353531267112884804.JavaMail.root@zimbra1-e1.priv.proxad.net> 2010-02-25 15:51 ` [PATCH] Support for deletion (patch included) racin [not found] <1427711643.5760731267266834921.JavaMail.root@zimbra1-e1.priv.proxad.net> 2010-02-27 10:34 ` racin 2009-12-13 11:54 Matthieu Lemerre 2010-02-24 18:49 ` Carl Worth 2010-02-25 0:00 ` racin 2010-02-25 10:49 ` Sebastian Spaeth 2010-03-01 9:09 ` Michal Sojka
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).