From 643ce61c1babf6e73ca7e03fb907282e7ee3b176 Mon Sep 17 00:00:00 2001 From: Pieter Praet Date: Mon, 16 Jan 2012 11:38:33 +0100 Subject: emacs: logically group def{custom,face}s To allow for expansion whilst keeping everything tidy and organized, move all defcustom/defface variables to the following subgroups, defined in notmuch-lib.el: - Hello - Search - Show - Send - Crypto - Hooks - External Commands - Appearance As an added benefit, defcustom keyword args are now consistently ordered as they appear @ defcustom's docstring (OCD much?). Proper defgroup docstrings and various other improvements by courtesy of Austin Clements. --- emacs/notmuch-message.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'emacs/notmuch-message.el') diff --git a/emacs/notmuch-message.el b/emacs/notmuch-message.el index 08e5b17..264a5b9 100644 --- a/emacs/notmuch-message.el +++ b/emacs/notmuch-message.el @@ -31,7 +31,7 @@ For example, if you wanted to add a \"replied\" tag and remove the \"inbox\" and \"todo\", you would set (\"replied\" \"-inbox\" \"-todo\"\)" :type 'list - :group 'notmuch) + :group 'notmuch-send) (defun notmuch-message-mark-replied () ;; get the in-reply-to header and parse it for the message id. -- cgit v1.2.3 From ee1180018ee3c772d7ac769222ff9c6940f3c838 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 26 Mar 2012 21:37:16 -0400 Subject: emacs: Escape all message ID queries This adds a lib function to turn a message ID into a properly escaped message ID query and uses this function wherever we previously hand-constructed ID queries. Wherever this new function is used, documentation has been clarified to refer to "id: queries" instead of "message IDs". This fixes the broken test introduced by the previous patch. --- emacs/notmuch-lib.el | 6 +++++- emacs/notmuch-message.el | 2 +- emacs/notmuch-show.el | 14 +++++++------- test/emacs | 1 - 4 files changed, 13 insertions(+), 10 deletions(-) (limited to 'emacs/notmuch-message.el') diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index a754de7..2492b80 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -144,6 +144,10 @@ the user hasn't set this variable with the old or new value." "[No Subject]" subject))) +(defun notmuch-id-to-query (id) + "Return a query that matches the message with id ID." + (concat "id:\"" (replace-regexp-in-string "\"" "\"\"" id t t) "\"")) + ;; (defun notmuch-common-do-stash (text) @@ -231,7 +235,7 @@ the given type." (defun notmuch-get-bodypart-content (msg part nth process-crypto) (or (plist-get part :content) - (notmuch-get-bodypart-internal (concat "id:" (plist-get msg :id)) nth process-crypto))) + (notmuch-get-bodypart-internal (notmuch-id-to-query (plist-get msg :id)) nth process-crypto))) (defun notmuch-plist-to-alist (plist) (loop for (key value . rest) on plist by #'cddr diff --git a/emacs/notmuch-message.el b/emacs/notmuch-message.el index 264a5b9..3010281 100644 --- a/emacs/notmuch-message.el +++ b/emacs/notmuch-message.el @@ -44,7 +44,7 @@ the \"inbox\" and \"todo\", you would set (concat "+" str) str)) notmuch-message-replied-tags))) - (apply 'notmuch-tag (concat "id:" (car (car rep))) tags))))) + (apply 'notmuch-tag (notmuch-id-to-query (car (car rep))) tags))))) (add-hook 'message-send-hook 'notmuch-message-mark-replied) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 0cd7d82..6d3fe62 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -613,7 +613,7 @@ current buffer, if possible." ;; times (hundreds!), which results in many calls to ;; `notmuch part'. (unless content - (setq content (notmuch-get-bodypart-internal (concat "id:" message-id) + (setq content (notmuch-get-bodypart-internal (notmuch-id-to-query message-id) part-number notmuch-show-process-crypto)) (with-current-buffer w3m-current-buffer (notmuch-show-w3m-cid-store-internal url @@ -1325,16 +1325,16 @@ Some useful entries are: (plist-get props prop))) (defun notmuch-show-get-message-id (&optional bare) - "Return the Message-Id of the current message. + "Return an id: query for the Message-Id of the current message. If optional argument BARE is non-nil, return -the Message-Id without prefix and quotes." +the Message-Id without id: prefix and escaping." (if bare (notmuch-show-get-prop :id) - (concat "id:\"" (notmuch-show-get-prop :id) "\""))) + (notmuch-id-to-query (notmuch-show-get-prop :id)))) (defun notmuch-show-get-messages-ids () - "Return all message ids of messages in the current thread." + "Return all id: queries of messages in the current thread." (let ((message-ids)) (notmuch-show-mapc (lambda () (push (notmuch-show-get-message-id) message-ids))) @@ -1401,7 +1401,7 @@ current thread." ;; thread. (defun notmuch-show-get-message-ids-for-open-messages () - "Return a list of all message IDs for open messages in the current thread." + "Return a list of all id: queries for open messages in the current thread." (save-excursion (let (message-ids done) (goto-char (point-min)) @@ -1805,7 +1805,7 @@ thread from search." (notmuch-common-do-stash (notmuch-show-get-from))) (defun notmuch-show-stash-message-id () - "Copy message ID of current message to kill-ring." + "Copy id: query matching the current message to kill-ring." (interactive) (notmuch-common-do-stash (notmuch-show-get-message-id))) diff --git a/test/emacs b/test/emacs index 62eaedb..8b92d0a 100755 --- a/test/emacs +++ b/test/emacs @@ -140,7 +140,6 @@ output=$(notmuch search 'id:"123..456@example"' | notmuch_search_sanitize) test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Message with .. in Message-Id (inbox search-add show-add)" test_begin_subtest "Message with quote in Message-Id:" -test_subtest_known_broken add_message '[id]="\"quote\"@example"' '[subject]="Message with quote in Message-Id"' test_emacs '(notmuch-search "subject:\"Message with quote\"") (notmuch-test-wait) -- cgit v1.2.3 From eb8feb16664fd0296ea0e07f4924c2a87a5b3bc3 Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Sat, 14 Apr 2012 11:52:50 -0700 Subject: emacs: create notmuch-tag.el, and move appropriate functions from notmuch.el Tagging functions are used in notmuch.el, notmuch-show.el, and notmuch-message.el. There are enough common functions for tagging that it makes sense to put them all in their own library. No code is modified, just moved around. --- emacs/Makefile.local | 1 + emacs/notmuch-message.el | 1 + emacs/notmuch-show.el | 3 +- emacs/notmuch-tag.el | 135 +++++++++++++++++++++++++++++++++++++++++++++++ emacs/notmuch.el | 109 +------------------------------------- 5 files changed, 139 insertions(+), 110 deletions(-) create mode 100644 emacs/notmuch-tag.el (limited to 'emacs/notmuch-message.el') diff --git a/emacs/Makefile.local b/emacs/Makefile.local index 4fee0e8..fb82247 100644 --- a/emacs/Makefile.local +++ b/emacs/Makefile.local @@ -13,6 +13,7 @@ emacs_sources := \ $(dir)/notmuch-maildir-fcc.el \ $(dir)/notmuch-message.el \ $(dir)/notmuch-crypto.el \ + $(dir)/notmuch-tag.el \ $(dir)/coolj.el \ $(dir)/notmuch-print.el diff --git a/emacs/notmuch-message.el b/emacs/notmuch-message.el index 3010281..5964caa 100644 --- a/emacs/notmuch-message.el +++ b/emacs/notmuch-message.el @@ -20,6 +20,7 @@ ;; Authors: Jesse Rosenthal (require 'message) +(require 'notmuch-tag) (require 'notmuch-mua) (defcustom notmuch-message-replied-tags '("replied") diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index c11af66..79fa5c5 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -30,6 +30,7 @@ (require 'goto-addr) (require 'notmuch-lib) +(require 'notmuch-tag) (require 'notmuch-query) (require 'notmuch-wash) (require 'notmuch-mua) @@ -38,10 +39,8 @@ (declare-function notmuch-call-notmuch-process "notmuch" (&rest args)) (declare-function notmuch-fontify-headers "notmuch" nil) -(declare-function notmuch-read-tag-changes "notmuch" (&optional initial-input &rest search-terms)) (declare-function notmuch-search-next-thread "notmuch" nil) (declare-function notmuch-search-show-thread "notmuch" nil) -(declare-function notmuch-update-tags "notmuch" (current-tags tag-changes)) (defcustom notmuch-message-headers '("Subject" "To" "Cc" "Date") "Headers that should be shown in a message, in this order. diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el new file mode 100644 index 0000000..c25cff8 --- /dev/null +++ b/emacs/notmuch-tag.el @@ -0,0 +1,135 @@ +;; notmuch-tag.el --- tag messages within emacs +;; +;; Copyright © Carl Worth +;; +;; This file is part of Notmuch. +;; +;; Notmuch is free software: you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; Notmuch is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Notmuch. If not, see . +;; +;; Authors: Carl Worth + +(eval-when-compile (require 'cl)) +(require 'crm) +(require 'notmuch-lib) + +(defcustom notmuch-before-tag-hook nil + "Hooks that are run before tags of a message are modified. + +'tags' will contain the tags that are about to be added or removed as +a list of strings of the form \"+TAG\" or \"-TAG\". +'query' will be a string containing the search query that determines +the messages that are about to be tagged" + + :type 'hook + :options '(notmuch-hl-line-mode) + :group 'notmuch-hooks) + +(defcustom notmuch-after-tag-hook nil + "Hooks that are run after tags of a message are modified. + +'tags' will contain the tags that were added or removed as +a list of strings of the form \"+TAG\" or \"-TAG\". +'query' will be a string containing the search query that determines +the messages that were tagged" + :type 'hook + :options '(notmuch-hl-line-mode) + :group 'notmuch-hooks) + +(defvar notmuch-select-tag-history nil + "Variable to store minibuffer history for +`notmuch-select-tag-with-completion' function.") + +(defvar notmuch-read-tag-changes-history nil + "Variable to store minibuffer history for +`notmuch-read-tag-changes' function.") + +(defun notmuch-tag-completions (&optional search-terms) + (if (null search-terms) + (setq search-terms (list "*"))) + (split-string + (with-output-to-string + (with-current-buffer standard-output + (apply 'call-process notmuch-command nil t + nil "search" "--output=tags" "--exclude=false" search-terms))) + "\n+" t)) + +(defun notmuch-select-tag-with-completion (prompt &rest search-terms) + (let ((tag-list (notmuch-tag-completions search-terms))) + (completing-read prompt tag-list nil nil nil 'notmuch-select-tag-history))) + +(defun notmuch-read-tag-changes (&optional initial-input &rest search-terms) + (let* ((all-tag-list (notmuch-tag-completions)) + (add-tag-list (mapcar (apply-partially 'concat "+") all-tag-list)) + (remove-tag-list (mapcar (apply-partially 'concat "-") + (if (null search-terms) + all-tag-list + (notmuch-tag-completions search-terms)))) + (tag-list (append add-tag-list remove-tag-list)) + (crm-separator " ") + ;; By default, space is bound to "complete word" function. + ;; Re-bind it to insert a space instead. Note that + ;; still does the completion. + (crm-local-completion-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map crm-local-completion-map) + (define-key map " " 'self-insert-command) + map))) + (delete "" (completing-read-multiple "Tags (+add -drop): " + tag-list nil nil initial-input + 'notmuch-read-tag-changes-history)))) + +(defun notmuch-update-tags (tags tag-changes) + "Return a copy of TAGS with additions and removals from TAG-CHANGES. + +TAG-CHANGES must be a list of tags names, each prefixed with +either a \"+\" to indicate the tag should be added to TAGS if not +present or a \"-\" to indicate that the tag should be removed +from TAGS if present." + (let ((result-tags (copy-sequence tags))) + (dolist (tag-change tag-changes) + (let ((op (string-to-char tag-change)) + (tag (unless (string= tag-change "") (substring tag-change 1)))) + (case op + (?+ (unless (member tag result-tags) + (push tag result-tags))) + (?- (setq result-tags (delete tag result-tags))) + (otherwise + (error "Changed tag must be of the form `+this_tag' or `-that_tag'"))))) + (sort result-tags 'string<))) + +(defun notmuch-tag (query &rest tag-changes) + "Add/remove tags in TAG-CHANGES to messages matching QUERY. + +TAG-CHANGES should be a list of strings of the form \"+tag\" or +\"-tag\" and QUERY should be a string containing the +search-query. + +Note: Other code should always use this function alter tags of +messages instead of running (notmuch-call-notmuch-process \"tag\" ..) +directly, so that hooks specified in notmuch-before-tag-hook and +notmuch-after-tag-hook will be run." + ;; Perform some validation + (mapc (lambda (tag-change) + (unless (string-match-p "^[-+]\\S-+$" tag-change) + (error "Tag must be of the form `+this_tag' or `-that_tag'"))) + tag-changes) + (unless (null tag-changes) + (run-hooks 'notmuch-before-tag-hook) + (apply 'notmuch-call-notmuch-process "tag" + (append tag-changes (list "--" query))) + (run-hooks 'notmuch-after-tag-hook))) + +;; + +(provide 'notmuch-tag) diff --git a/emacs/notmuch.el b/emacs/notmuch.el index a6724fa..03a882e 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -48,11 +48,11 @@ ;; required, but is available from http://notmuchmail.org). (eval-when-compile (require 'cl)) -(require 'crm) (require 'mm-view) (require 'message) (require 'notmuch-lib) +(require 'notmuch-tag) (require 'notmuch-show) (require 'notmuch-mua) (require 'notmuch-hello) @@ -76,68 +76,6 @@ For example: (defvar notmuch-query-history nil "Variable to store minibuffer history for notmuch queries") -(defvar notmuch-select-tag-history nil - "Variable to store minibuffer history for -`notmuch-select-tag-with-completion' function.") - -(defvar notmuch-read-tag-changes-history nil - "Variable to store minibuffer history for -`notmuch-read-tag-changes' function.") - -(defun notmuch-tag-completions (&optional search-terms) - (if (null search-terms) - (setq search-terms (list "*"))) - (split-string - (with-output-to-string - (with-current-buffer standard-output - (apply 'call-process notmuch-command nil t - nil "search" "--output=tags" "--exclude=false" search-terms))) - "\n+" t)) - -(defun notmuch-select-tag-with-completion (prompt &rest search-terms) - (let ((tag-list (notmuch-tag-completions search-terms))) - (completing-read prompt tag-list nil nil nil 'notmuch-select-tag-history))) - -(defun notmuch-read-tag-changes (&optional initial-input &rest search-terms) - (let* ((all-tag-list (notmuch-tag-completions)) - (add-tag-list (mapcar (apply-partially 'concat "+") all-tag-list)) - (remove-tag-list (mapcar (apply-partially 'concat "-") - (if (null search-terms) - all-tag-list - (notmuch-tag-completions search-terms)))) - (tag-list (append add-tag-list remove-tag-list)) - (crm-separator " ") - ;; By default, space is bound to "complete word" function. - ;; Re-bind it to insert a space instead. Note that - ;; still does the completion. - (crm-local-completion-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map crm-local-completion-map) - (define-key map " " 'self-insert-command) - map))) - (delete "" (completing-read-multiple "Tags (+add -drop): " - tag-list nil nil initial-input - 'notmuch-read-tag-changes-history)))) - -(defun notmuch-update-tags (tags tag-changes) - "Return a copy of TAGS with additions and removals from TAG-CHANGES. - -TAG-CHANGES must be a list of tags names, each prefixed with -either a \"+\" to indicate the tag should be added to TAGS if not -present or a \"-\" to indicate that the tag should be removed -from TAGS if present." - (let ((result-tags (copy-sequence tags))) - (dolist (tag-change tag-changes) - (let ((op (string-to-char tag-change)) - (tag (unless (string= tag-change "") (substring tag-change 1)))) - (case op - (?+ (unless (member tag result-tags) - (push tag result-tags))) - (?- (setq result-tags (delete tag result-tags))) - (otherwise - (error "Changed tag must be of the form `+this_tag' or `-that_tag'"))))) - (sort result-tags 'string<))) - (defun notmuch-foreach-mime-part (function mm-handle) (cond ((stringp (car mm-handle)) (dolist (part (cdr mm-handle)) @@ -545,51 +483,6 @@ and will also appear in a buffer named \"*Notmuch errors*\"." (error (buffer-substring beg end)) )))))) -(defun notmuch-tag (query &rest tag-changes) - "Add/remove tags in TAG-CHANGES to messages matching QUERY. - -TAG-CHANGES should be a list of strings of the form \"+tag\" or -\"-tag\" and QUERY should be a string containing the -search-query. - -Note: Other code should always use this function alter tags of -messages instead of running (notmuch-call-notmuch-process \"tag\" ..) -directly, so that hooks specified in notmuch-before-tag-hook and -notmuch-after-tag-hook will be run." - ;; Perform some validation - (mapc (lambda (tag-change) - (unless (string-match-p "^[-+]\\S-+$" tag-change) - (error "Tag must be of the form `+this_tag' or `-that_tag'"))) - tag-changes) - (unless (null tag-changes) - (run-hooks 'notmuch-before-tag-hook) - (apply 'notmuch-call-notmuch-process "tag" - (append tag-changes (list "--" query))) - (run-hooks 'notmuch-after-tag-hook))) - -(defcustom notmuch-before-tag-hook nil - "Hooks that are run before tags of a message are modified. - -'tags' will contain the tags that are about to be added or removed as -a list of strings of the form \"+TAG\" or \"-TAG\". -'query' will be a string containing the search query that determines -the messages that are about to be tagged" - - :type 'hook - :options '(notmuch-hl-line-mode) - :group 'notmuch-hooks) - -(defcustom notmuch-after-tag-hook nil - "Hooks that are run after tags of a message are modified. - -'tags' will contain the tags that were added or removed as -a list of strings of the form \"+TAG\" or \"-TAG\". -'query' will be a string containing the search query that determines -the messages that were tagged" - :type 'hook - :options '(notmuch-hl-line-mode) - :group 'notmuch-hooks) - (defun notmuch-search-set-tags (tags) (save-excursion (end-of-line) -- cgit v1.2.3 From bcdfff4f3a7a373851f08b22b56c58a25370b1fe Mon Sep 17 00:00:00 2001 From: Ingo Lohmar Date: Sun, 3 Jun 2012 21:23:57 +0300 Subject: emacs: Fix notmuch-message-mark-replied. notmuch-message-mark-replied used "apply" to change message tags according to notmuch-message-replied-tags after sending a reply. This works if the latter is a single-element list. But with the recently changed format of tag changes, it breaks for multiple-element lists. Use "funcall" to properly pass the list of tag changes as a single argument. --- emacs/notmuch-message.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'emacs/notmuch-message.el') diff --git a/emacs/notmuch-message.el b/emacs/notmuch-message.el index 5964caa..d3738bf 100644 --- a/emacs/notmuch-message.el +++ b/emacs/notmuch-message.el @@ -45,7 +45,7 @@ the \"inbox\" and \"todo\", you would set (concat "+" str) str)) notmuch-message-replied-tags))) - (apply 'notmuch-tag (notmuch-id-to-query (car (car rep))) tags))))) + (funcall 'notmuch-tag (notmuch-id-to-query (car (car rep))) tags))))) (add-hook 'message-send-hook 'notmuch-message-mark-replied) -- cgit v1.2.3