[PATCH] News: add entry for unthreaded mode
A belated NEWS entry for the new un-threaded mode introduced in Notmuch 0.30. --- Sorry I didn't send this for the 0.30 release. I am not sure if the last sentence is appropriate for a NEWS item, so feel free to delete. I don't have a development item set up (I am still mainly using emacs 24) so I am not certain the markdown is correct. Best wishes Mark NEWS | 19 +++ 1 file changed, 19 insertions(+) diff --git a/NEWS b/NEWS index af903252..a04c0937 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,25 @@ The minimum supported major version of GNU Emacs is now 25.1. Add support for moving between threads after notmuch-tree-from-search-thread. +New `notmuch-unthreaded` mode (added in Notmuch 0.30) + + Unthreaded view is a mode where each matching message is shown on a + separate line. + + The main key entries to unthreaded view are + + 'u' enter a query to view in unthreaded mode (works in hello, + search, show and tree mode) + + 'U' view the current query in unthreaded mode (works from search, + show and tree) + + Saved searches can also specify that they should open in unthreaded + view. + + Currently it is not possible to specify the sort order: it will + always be newest first. + Notmuch-Mutt -- 2.11.0 ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: call for NEWS entries for 0.31
Hi > Here's a lightly edited output from git shortlog to jog your collective > memories. Please send patches for NEWS for any non-trivial user visible > changes. I think I should have sent a news patch for the "unthreaded mode" addition which went into the 0.30 release (sorry about that). What is the best way to add it now? Best wishes Mark ___ notmuch mailing list -- notmuch@notmuchmail.org To unsubscribe send an email to notmuch-le...@notmuchmail.org
Re: [PATCH] emacs: split-window-sensibly in tree mode with open message
Hi > For some historical context, split-window-sensibly was introduced in 2009 [1] > and the (split-window-vertically (/ (window-height) 4)) code in 2012 [2]. The > two functions seem pretty interchangeable. As far as I can see the split-window-sensibly version splits the window into two equal parts, whereas the split-window-vertically version (deliberately) makes the message pane bigger than the thread pane. I definitely prefer the current version (unsurprising as I chose the split back in 2012), but others may disagree. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 2/6] Introduce unthreaded mode
This commit introduces a new 'unthreaded' search mode where each matching message is shown on a separate line. It shares almost all of its code with tree view. Subsequent commits will allow it to diverge slightly in appearance. --- emacs/notmuch-hello.el | 2 +- emacs/notmuch-lib.el | 1 + emacs/notmuch-show.el | 2 +- emacs/notmuch-tree.el | 28 +--- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index aff8beb5..858446df 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -31,7 +31,7 @@ (declare-function notmuch-search "notmuch" (&optional query oldest-first target-thread target-line continuation)) (declare-function notmuch-poll "notmuch" ()) (declare-function notmuch-tree "notmuch-tree" - (&optional query query-context target buffer-name open-target)) + (&optional query query-context target buffer-name open-target unthreaded)) (defun notmuch-saved-search-get (saved-search field) "Get FIELD from SAVED-SEARCH. diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 8acad267..73b165e4 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -154,6 +154,7 @@ For example, if you wanted to remove an \"inbox\" tag and add an (define-key map "q" 'notmuch-bury-or-kill-this-buffer) (define-key map "s" 'notmuch-search) (define-key map "z" 'notmuch-tree) +(define-key map "u" 'notmuch-unthreaded) (define-key map "m" 'notmuch-mua-new-mail) (define-key map "g" 'notmuch-refresh-this-buffer) (define-key map "=" 'notmuch-refresh-this-buffer) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index ef2bf1e0..d4a1389b 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -48,7 +48,7 @@ (declare-function notmuch-count-attachments "notmuch" (mm-handle)) (declare-function notmuch-save-attachments "notmuch" (mm-handle &optional queryp)) (declare-function notmuch-tree "notmuch-tree" - (&optional query query-context target buffer-name open-target)) + (&optional query query-context target buffer-name open-target unthreaded)) (declare-function notmuch-tree-get-message-properties "notmuch-tree" nil) (declare-function notmuch-read-query "notmuch" (prompt)) (declare-function notmuch-draft-resume "notmuch-draft" (id)) diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index c00315e8..80b830dd 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -42,6 +42,11 @@ ;; the following variable is defined in notmuch.el (defvar notmuch-search-query-string) +;; this variable distinguishes the unthreaded display from the normal tree display +(defvar notmuch-tree-unthreaded nil + "A buffer local copy of argument unthreaded to the function notmuch-tree") +(make-variable-buffer-local 'notmuch-tree-unthreaded) + (defgroup notmuch-tree nil "Showing message and thread structure." :group 'notmuch) @@ -890,7 +895,7 @@ Complete list of currently available key bindings: (notmuch-sexp-parse-partial-list 'notmuch-tree-insert-forest-thread results-buf) -(defun notmuch-tree-worker (basic-query &optional query-context target open-target) +(defun notmuch-tree-worker (basic-query &optional query-context target open-target unthreaded) "Insert the tree view of the search in the current buffer. This is is a helper function for notmuch-tree. The arguments are @@ -898,6 +903,7 @@ the same as for the function notmuch-tree." (interactive) (notmuch-tree-mode) (add-hook 'post-command-hook #'notmuch-tree-command-hook t t) + (setq notmuch-tree-unthreaded unthreaded) (setq notmuch-tree-basic-query basic-query) (setq notmuch-tree-query-context (if (or (string= query-context "") (string= query-context "*")) @@ -915,7 +921,7 @@ the same as for the function notmuch-tree." (let* ((search-args (concat basic-query (if query-context (concat " and (" query-context ")")) )) -(message-arg "--entire-thread")) +(message-arg (if unthreaded "--unthreaded" "--entire-thread"))) (if (equal (car (process-lines notmuch-command "count" search-args)) "0") (setq search-args basic-query)) (notmuch-tag-clear-cache) @@ -940,7 +946,7 @@ the same as for the function notmuch-tree." ")") notmuch-tree-basic-query)) -(defun notmuch-tree (&optional query query-context target buffer-name open-target) +(defun notmuch-tree (&optional query query-context target buffer-name open-target unthreaded) "Display threads matching QUERY in Tree View. The arguments are: @@ -953,23 +959,31 @@ The arguments are: current if it appears in the tree view results. BUFFER-NAME: the name of the buffer to display the tree view. If it is nil \"*notmuch-tree\" followed by QUERY is used. - O
[PATCH 1/6] notmuch-show.c: add an option for messages to be returned unthreaded
This adds a --unthreaded option to notmuch show to tell it to return the matching messages in an unthreaded order (so just by date). To make it easier for users, in particular for notmuch-tree.el, we output each message with the same "nesting" as if it were an entire thread in its own right. --- notmuch-show.c | 61 -- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/notmuch-show.c b/notmuch-show.c index 21792a57..cf543ed9 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -1066,11 +1066,11 @@ do_show_single (void *ctx, /* Formatted output of threads */ static int -do_show (void *ctx, -notmuch_query_t *query, -const notmuch_show_format_t *format, -sprinter_t *sp, -notmuch_show_params_t *params) +do_show_threaded (void *ctx, + notmuch_query_t *query, + const notmuch_show_format_t *format, + sprinter_t *sp, + notmuch_show_params_t *params) { notmuch_threads_t *threads; notmuch_thread_t *thread; @@ -1107,6 +1107,50 @@ do_show (void *ctx, return res != NOTMUCH_STATUS_SUCCESS; } +static int +do_show_unthreaded (void *ctx, + notmuch_query_t *query, + const notmuch_show_format_t *format, + sprinter_t *sp, + notmuch_show_params_t *params) +{ +notmuch_messages_t *messages; +notmuch_message_t *message; +notmuch_status_t status, res = NOTMUCH_STATUS_SUCCESS; +notmuch_bool_t excluded; + +status= notmuch_query_search_messages (query, &messages); +if (print_status_query ("notmuch show", query, status)) + return 1; + +sp->begin_list (sp); + +for (; +notmuch_messages_valid (messages); +notmuch_messages_move_to_next (messages)) { + sp->begin_list (sp); + sp->begin_list (sp); + + message = notmuch_messages_get (messages); + + notmuch_message_set_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH, TRUE); + excluded = notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_EXCLUDED); + + if (!excluded || !params->omit_excluded) { + status = show_message (ctx, format, sp, message, 0, params); + if (status && !res) + res = status; + } else { + sp->null (sp); + } + notmuch_message_destroy (message); + sp->end (sp); + sp->end (sp); +} +sp->end (sp); +return res; +} + enum { NOTMUCH_FORMAT_NOT_SPECIFIED, NOTMUCH_FORMAT_JSON, @@ -1168,6 +1212,7 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[]) bool exclude = true; bool entire_thread_set = false; bool single_message; +bool unthreaded = FALSE; notmuch_opt_desc_t options[] = { { .opt_keyword = &format, .name = "format", .keywords = @@ -1181,6 +1226,7 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[]) { .opt_bool = &exclude, .name = "exclude" }, { .opt_bool = ¶ms.entire_thread, .name = "entire-thread", .present = &entire_thread_set }, + { .opt_bool = &unthreaded, .name = "unthreaded" }, { .opt_int = ¶ms.part, .name = "part" }, { .opt_keyword = (int *) (¶ms.crypto.decrypt), .name = "decrypt", .keyword_no_arg_value = "true", .keywords = @@ -1317,7 +1363,10 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[]) params.omit_excluded = false; } - ret = do_show (config, query, formatter, sprinter, ¶ms); + if (unthreaded) + ret = do_show_unthreaded (config, query, formatter, sprinter, ¶ms); + else + ret = do_show_threaded (config, query, formatter, sprinter, ¶ms); } DONE: -- 2.11.0 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 4/6] Unthreaded mode: allow user to choose different `show out' than tree
Tree mode allows the user to choose whether to use the split screen displaying just the current message or a full screen displaying the entire thread. As unthreaded mode is quite different in use the user may want a different customisation for this mode. --- emacs/notmuch-tree.el | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index 760eaaec..895c05f4 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -56,6 +56,16 @@ :type 'boolean :group 'notmuch-tree) +(defcustom notmuch-unthreaded-show-out t + "View selected messages in new window rather than split-pane." + :type 'boolean + :group 'notmuch-tree) + +(defun notmuch-tree-show-out () + (if notmuch-tree-unthreaded + notmuch-unthreaded-show-out +notmuch-tree-show-out)) + (defcustom notmuch-tree-result-format `(("date" . "%12s ") ("authors" . "%-20s") @@ -531,8 +541,8 @@ NOT change the database." Shows in split pane or whole window according to value of `notmuch-tree-show-out'. A prefix argument reverses the choice." (interactive "P") - (if (or (and notmuch-tree-show-out (not arg)) - (and (not notmuch-tree-show-out) arg)) + (if (or (and (notmuch-tree-show-out) (not arg)) + (and (not (notmuch-tree-show-out)) arg)) (notmuch-tree-show-message-out) (notmuch-tree-show-message-in))) -- 2.11.0 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 3/6] Unthreaded mode: allow different result format
It is likely that the user will want a different line format for unthreaded mode from tree mode; in particular the thread structure graphics are unnecessary in unthreaded mode. Add a new customisable variable and set it to something sensible. --- emacs/notmuch-tree.el | 27 ++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index 80b830dd..760eaaec 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -76,6 +76,31 @@ Note the author string should not contain :type '(alist :key-type (string) :value-type (string)) :group 'notmuch-tree) +(defcustom notmuch-unthreaded-result-format + `(("date" . "%12s ") +("authors" . "%-20s") +((("subject" . "%s")) ." %-54s ") +("tags" . "(%s)")) + "Result formatting for unthreaded Tree view. Supported fields are: date, +authors, subject, tree, tags. Tree means the thread tree +box graphics. The field may also be a list in which case +the formatting rules are applied recursively and then the +output of all the fields in the list is inserted +according to format-string. + +Note the author string should not contain +whitespace (put it in the neighbouring fields instead). +For example: +(setq notmuch-tree-result-format \(\(\"authors\" . \"%-40s\"\) + \(\"subject\" . \"%s\"\)\)\)" + :type '(alist :key-type (string) :value-type (string)) + :group 'notmuch-tree) + +(defun notmuch-tree-result-format () + (if notmuch-tree-unthreaded + notmuch-unthreaded-result-format +notmuch-tree-result-format)) + ;; Faces for messages that match the query. (defface notmuch-tree-match-face '((t :inherit default)) @@ -759,7 +784,7 @@ unchanged ADDRESS if parsing fails." ;; We need to save the previous subject as it will get overwritten ;; by the insert-field calls. (let ((previous-subject notmuch-tree-previous-subject)) -(insert (notmuch-tree-format-field-list notmuch-tree-result-format msg)) +(insert (notmuch-tree-format-field-list (notmuch-tree-result-format) msg)) (notmuch-tree-set-message-properties msg) (notmuch-tree-set-prop :previous-subject previous-subject) (insert "\n"))) -- 2.11.0 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 6/6] notmuch-hello/jump: allow saved searches to specify unthreaded mode
Saved searches in notmuch-hello and notmuch-jump can specify whether to use search mode or tree mode. This adds an option for them to specify unthreaded mode. --- emacs/notmuch-hello.el | 29 +++-- emacs/notmuch-jump.el | 10 +++--- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 858446df..ab6ee798 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -32,6 +32,9 @@ (declare-function notmuch-poll "notmuch" ()) (declare-function notmuch-tree "notmuch-tree" (&optional query query-context target buffer-name open-target unthreaded)) +(declare-function notmuch-unthreaded + (&optional query query-context target buffer-name open-target)) + (defun notmuch-saved-search-get (saved-search field) "Get FIELD from SAVED-SEARCH. @@ -99,7 +102,8 @@ searches so they still work in customize." (group :format "%v" :inline t (const :format "" :search-type) (choice :tag " Search Type" (const :tag "Search mode" nil) - (const :tag "Tree mode" tree)) + (const :tag "Tree mode" tree) + (const :tag "Unthreaded mode" unthreaded)) (defcustom notmuch-saved-searches `((:name "inbox" :query "tag:inbox" :key ,(kbd "i")) @@ -122,10 +126,10 @@ a plist. Supported properties are :sort-order Specify the sort order to be used for the search. Possible values are 'oldest-first 'newest-first or nil. Nil means use the default sort order. - :search-type Specify whether to run the search in search-mode - or tree mode. Set to 'tree to specify tree - mode, set to nil (or anything except tree) to - specify search mode. + :search-type Specify whether to run the search in search-mode, + tree mode or unthreaded mode. Set to 'tree to specify tree + mode, 'unthreaded to specify unthreaded mode, and set to nil + (or anything except tree and unthreaded) to specify search mode. Other accepted forms are a cons cell of the form (NAME . QUERY) or a list of the form (NAME QUERY COUNT-QUERY)." @@ -437,13 +441,18 @@ diagonal." append (notmuch-hello-reflect-generate-row ncols nrows row list (defun notmuch-hello-widget-search (widget &rest ignore) - (if (widget-get widget :notmuch-search-type) - (notmuch-tree (widget-get widget - :notmuch-search-terms)) + (cond + ((eq (widget-get widget :notmuch-search-type) 'tree) +(notmuch-tree (widget-get widget + :notmuch-search-terms))) + ((eq (widget-get widget :notmuch-search-type) 'unthreaded) +(notmuch-unthreaded (widget-get widget + :notmuch-search-terms))) + (t (notmuch-search (widget-get widget :notmuch-search-terms) (widget-get widget - :notmuch-search-oldest-first + :notmuch-search-oldest-first) (defun notmuch-saved-search-count (search) (car (process-lines notmuch-command "count" search))) @@ -579,7 +588,7 @@ with `notmuch-hello-query-counts'." (newest-first nil) (oldest-first t) (otherwise notmuch-search-oldest-first))) -(search-type (eq (plist-get elem :search-type) 'tree)) +(search-type (plist-get elem :search-type)) (msg-count (plist-get elem :count))) (widget-insert (format "%8s " (notmuch-hello-nice-number msg-count))) diff --git a/emacs/notmuch-jump.el b/emacs/notmuch-jump.el index 3e20b8c7..1cdf5b50 100644 --- a/emacs/notmuch-jump.el +++ b/emacs/notmuch-jump.el @@ -56,9 +56,13 @@ fast way to jump to a saved search from anywhere in Notmuch." (oldest-first t) (otherwise (default-value 'notmuch-search-oldest-first) (push (list key name - (if (eq (plist-get saved-search :search-type) 'tree) - `(lambda () (notmuch-tree ',query)) - `(lambda () (notmuch-search ',query ',oldest-first + (cond +((eq (plist-get saved-search :search-type) 'tree) + `(lambda () (notmuch-tree ',query))) +((eq (plist-get saved-search :search-type) 'unthreaded) + `(lambda () (notmuch-unthreaded ',query))) +(t + `(lambda () (notmuch-search ',query ',oldest
[PATCH 5/6] Add a U binding to switch to unthreaded from other views
We have shortcuts S and Z to let the user switch to Search view and Tree view with the current search. Add U to let the user switch to unthreaded view from the current search, and ensure that S and Z switch from unthreaded to search and tree veiew respectively. --- emacs/notmuch-show.el | 10 ++ emacs/notmuch-tree.el | 23 +-- emacs/notmuch.el | 6 ++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index d4a1389b..214e279f 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -50,6 +50,8 @@ (declare-function notmuch-tree "notmuch-tree" (&optional query query-context target buffer-name open-target unthreaded)) (declare-function notmuch-tree-get-message-properties "notmuch-tree" nil) +(declare-function notmuch-unthreaded + (&optional query query-context target buffer-name open-target)) (declare-function notmuch-read-query "notmuch" (prompt)) (declare-function notmuch-draft-resume "notmuch-draft" (id)) @@ -1471,6 +1473,7 @@ reset based on the original query." (let ((map (make-sparse-keymap))) (set-keymap-parent map notmuch-common-keymap) (define-key map "Z" 'notmuch-tree-from-show-current-query) +(define-key map "U" 'notmuch-unthreaded-from-show-current-query) (define-key map (kbd "") 'widget-backward) (define-key map (kbd "M-TAB") 'notmuch-show-previous-button) (define-key map (kbd "") 'notmuch-show-previous-button) @@ -1559,6 +1562,13 @@ All currently available key bindings: notmuch-show-query-context (notmuch-show-get-message-id))) +(defun notmuch-unthreaded-from-show-current-query () + "Call notmuch unthreaded with the current query" + (interactive) + (notmuch-unthreaded notmuch-show-thread-id + notmuch-show-query-context + (notmuch-show-get-message-id))) + (defun notmuch-show-move-to-message-top () (goto-char (notmuch-show-message-top))) diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index 895c05f4..9a83292c 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -294,6 +294,8 @@ FUNC." (define-key map [remap notmuch-jump-search] (notmuch-tree-close-message-pane-and #'notmuch-jump-search)) (define-key map "S" 'notmuch-search-from-tree-current-query) +(define-key map "U" 'notmuch-unthreaded-from-tree-current-query) +(define-key map "Z" 'notmuch-tree-from-unthreaded-current-query) ;; these use notmuch-show functions directly (define-key map "|" 'notmuch-show-pipe-message) @@ -474,6 +476,18 @@ NOT change the database." (notmuch-tree-close-message-window) (notmuch-tree query))) +(defun notmuch-unthreaded-from-tree-current-query () + "Switch from tree view to unthreaded view" + (interactive) + (unless notmuch-tree-unthreaded +(notmuch-tree-refresh-view 'unthreaded))) + +(defun notmuch-tree-from-unthreaded-current-query () + "Switch from unthreaded view to tree view" + (interactive) + (when notmuch-tree-unthreaded +(notmuch-tree-refresh-view 'tree))) + (defun notmuch-search-from-tree-current-query () "Call notmuch search with the current query" (interactive) @@ -635,19 +649,24 @@ message will be \"unarchived\", i.e. the tag changes in (when (window-live-p notmuch-tree-message-window) (notmuch-tree-show-message-in))) -(defun notmuch-tree-refresh-view () +(defun notmuch-tree-refresh-view (&optional view) "Refresh view." (interactive) (when (get-buffer-process (current-buffer)) (error "notmuch tree process already running for current buffer")) (let ((inhibit-read-only t) (basic-query notmuch-tree-basic-query) + (unthreaded (cond ((eq view 'unthreaded) t) + ((eq view 'tree) nil) + (t notmuch-tree-unthreaded))) (query-context notmuch-tree-query-context) (target (notmuch-tree-get-message-id))) (erase-buffer) (notmuch-tree-worker basic-query query-context -target))) +target +nil +unthreaded))) (defun notmuch-tree-thread-top () (when (notmuch-tree-get-message-properties) diff --git a/emacs/notmuch.el b/emacs/notmuch.el index 0d68d123..f4789b4f 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -190,6 +190,7 @@ there will be called at other points of notmuch execution." (define-key map (kbd "RET") 'notmuch-search-show-thread) (define-key map (kbd "M-RET") 'notmuch-tree-from-search-thread) (define-key map "Z" 'notmuch-tree-from-search-current-query) +(define-key map "U" 'notmuch-unthreaded-from-search-current-query) map) "Keymap for \"notmuch search\" buffers.") (fset 'notmuch-search-mode-map notmuch-search-mode-map) @@ -523,6 +524,11 @@ thread." (interactive) (notmuch-tree notmuch-search-quer
[PATCH 0/6] Add an unthreaded mode
This series adds an unthreaded mode. In this mode all messages matching the query are shown, one per line, in unthreaded (reverse) date order. For some discussion of such a mode see id:87mupcay3s@tethera.net and subsequent thread. The main key bindings are u to run an unthreaded search, and U to rerun the current query in unthreaded view. Most of the functionality comes from the existing notmuch-tree code so it is relatively simple. I have been running some very similar code for just over a year and finally found time to tidy and submit it. One note: --entire-thread=false outputs just the matching messages (not the entire threads) but still in threaded order, and this option can be used by pre-existing emacs functionality (depending on user settings); this is why I added a new --unthreaded option. Best wishes Mark Mark Walters (6): notmuch-show.c: add an option for messages to be returned unthreaded Introduce unthreaded mode Unthreaded mode: allow different result format Unthreaded mode: allow user to choose different `show out' than tree Add a U binding to switch to unthreaded from other views notmuch-hello/jump: allow saved searches to specify unthreaded mode emacs/notmuch-hello.el | 31 +++-- emacs/notmuch-jump.el | 10 -- emacs/notmuch-lib.el | 1 + emacs/notmuch-show.el | 12 ++- emacs/notmuch-tree.el | 92 +++--- emacs/notmuch.el | 6 notmuch-show.c | 61 + 7 files changed, 180 insertions(+), 33 deletions(-) -- 2.11.0 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH] emacs: tree: support fold/unfold thread
Hello > This patch allow the user to fold/unfold a thread in the current tree > buffer by pressing "t" key. This looks like a really nice feature! I will try and review the code properly soon, but have some preliminary comments. > By default a string is displayed at the beginning of the overlay to > indicate that this thread is folded. I wonder if it would make sense to make the [] replace the "tree symbol" (-> etc)? This would mean that it was always on the screen and the tree symbol looks a little odd with a collapsed thread. Secondly, I wonder whether making it collapse just the subthread below the current message (ie a subtree) would be nice? To me that feels more generic, but might be more effort than it's worth as the code would need to deal with nested folds. Then C-u t could do exactly the current folding (ie the whole thread). But this is just a thought. Finally a comment on the code > +The overlay found is located between START and END position in BUFFER." > + (seq-find (lambda (ov) > +(defun notmuch-tree-clean-up-overlays () > + "Remove overlays not referenced to any buffer" > + (setq notmuch-tree-overlays (seq-filter #'overlay-buffer > notmuch-tree-overlays))) seq-find and seq-filter are emacs 25+ only I think; at least they don't seem to be in emacs24 which I think we still support. Perhaps some cl functions can be used (eg remove-if-not) instead? Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [emacs] message list view
Dear All I think this could be very useful -- indeed I currently have been running some scruffy patches implementing this for the last couple of months. What I have done is modify notmuch-show.c so that you can pass a --unthreaded option and it returns each message as if it were a thread on its own. Then notmuch-tree basically "just works" with this output. The reason I like it was I found I was sometimes missing messages when multiple messages arrived in the same thread. I haven't tried Bremner's suggestion of just not passing entire-thread; it would give a slightly odd ordering of the messages (all matching messages by thread, and in thread order) rather than just date order. My patches are against a rather outdated version of notmuch but I can probably update and post relatively easily if people would like to try it. Best wishes Mark On Tue, 11 Dec 2018, Jeff Templon wrote: > Hi, > > David Bremner writes: > >> David Edmondson writes: >> >>> On Tuesday, 2018-12-11 at 11:20:55 -04, David Bremner wrote: >>> Discussion on #notmuch the other day led me to wonder how useful a "message list" view would be. Essentially this would display a single line summary for individual messages matching a query and allow e.g. tagging operations or "opening" the message to get a more complete view. > > > I think it'd be useful. I'll give you an example that always bugs me: > if I look in "unread" (the standard startup screen search) and see some > new message in a long thread of which I've deleted a bunch of messages, > and I type 'd' to delete, it actually first undeletes (or to be precise, > it toggles the already-present deleted tag on) all the already-deleted > messages in the thread, then I have to hit 'd' again to delete all of > them. > > If it were a message view instead of a thread view, I could just delete > the dang message ;-) > > JT > ___ > notmuch mailing list > notmuch@notmuchmail.org > https://notmuchmail.org/mailman/listinfo/notmuch ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH] lib: add support for thread: queries
Hi On Mon, 16 Oct 2017, Jani Nikula wrote: > Add support for querying threads using message-ids in addition to > thread-ids. The main benefit is that thread queries via message-ids > are portable across databases, re-indexing, and thread joining, while > thread ids can be somewhat transient. A thread: query can > be shared between notmuch users, while a thread: query may > cease to work after the regular delivery of a message that joins > threads. I like the idea. Just one thought -- is any form of recursion allowed in this sort of operator so could we have thread:'some query' which would expand to all threads matching the query? I am guessing this may not be possible now but would it be worth requiring the thread form to be thread:id: rather than thread:? Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: notmuch-emacs: Fcc to top-level directory given by database.path
Hi On Sun, 01 Oct 2017, Arun Isaac wrote: > Mark Walters writes: > >> Incidentally, I think "/" is an alternative for the fcc line which >> already works, which is "\"/\" in notmuch-fcc-dirs. > > Perhaps, notmuch should be made to tolerate a "/" at the beginning of the > Fcc folder argument. That is, notmuch should not complain about absolute > paths, and it should interpret these as relative to the root. To > maintain backward compatibility, we could add a "/" at the beginning if > it is not already there. > > So, > > "/" => database.path > "/sent" => database.path/sent > "sent" => database.path/sent > > etc. > > Is this a better idea? The reason for the warning is that this behaviour is completely different from what you would get with normal file fcc. Given that, I am a little reluctant to drop the warning. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 0/6] Sort by from and subject
Hi On Sat, 30 Sep 2017, Jani Nikula wrote: > On Sat, 30 Sep 2017, William Casarin wrote: >> Jani Nikula writes: >> >>> I think there are two considerations here: >>> >>> First, is this something we want to have? Is this generally useful? >> >> Sorting by from and subject are in most mail clients (mutt, gnus, outlook...) > > Which of those display results as threads, and of those that do, how do > they sort the threads? In the notmuch case, the threads would be sorted > based on one of the matching messages. Which one should it be? For > current date based searches, the message used for sorting is also > selected based on date. I agree with Jani that for thread based views sorting by from is a little odd -- sorting by subject less so as that is mostly constant in a thread. But allowing sorting by from in message based views could be useful. If we are looking at the notmuch-emacs frontend then that would be in tree view. This calls notmuch-show.c from the CLI, so that is the place I would suggest we do this. If notmuch-show.c returns each message as "if it were in its own thread" in the sense of the sexp output (see devel/schemata) I think notmuch-tree would just work. >>> There's still the issue of From: and Subject: needing more heuristic for >>> useful sorting that I mentioned in id:87efrm70ai@nikula.org. >> >> I think I understand what you mean in id:87efrm70ai@nikula.org but I >> don't have enough knowledge of notmuch to implement what you're asking >> :(. I believe these are rare cases because I haven't ran into the issue >> you described? > > Look at the subject line of this message. Should it be sorted starting > at "Re:", "[PATCH", or "Sort"? You could argue for and against any one > of them. Contrast that with the thread sorting above: If the matching > message in this thread changes from one with vs. without "Re:", the sort > placement of the thread could change considerably. > > It's common for some corporate mail systems to switch "Firstname > Lastname" in messages to "Lastname, Firstname". Should we do something > about that? > > Arguably we could do the sorting first, and think of ways to improve it > afterwards. These are concerns, but I agree that we try some form of sorting first and then think about improving it. I think the above as an interface to notmuch-tree should work -- I had something similar in the very early days of notmuch-tree (when it was notmuch-pick) but dropped it when trying to keep the patch set small enough to be even vaguely manageable. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: Guess 'From:' when doing notmuch reply
> One option would be for you to customize the output of notmuch-reply in > Emacs. I think the package message-templ (unfortunately only in > marmalade, debian, and my git repo) provides tools that could help with > that. If you want to investigate it's at: > > http://pivot.cs.unb.ca/git?p=message-templ.git;a=summary Just a thought: would it be worth including this in contrib? Best wishes Mark > > There may well be better tools for message-mode. > > d > ___ > notmuch mailing list > notmuch@notmuchmail.org > https://notmuchmail.org/mailman/listinfo/notmuch ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: notmuch.el: "wash" date in message display
On Thu, 21 Sep 2017, Tomi Ollila wrote: > On Wed, Sep 20 2017, Matt Armstrong wrote: > >> I miss some of the Gnus "wash" functions available for message display. >> There was one that either reformatted the Date: header into my time >> zone, or displayed the Date in terms of elapsed time from now (e.g. 1 >> hour ago, 1 day ago, etc.). I don't remember which, but I'd be happy >> with either. > > I personally use > > http://mid.mail-archive.com/1427132722-20346-1-git-send-email-tomi.ollila@iki.fi > > -- this shows (date) in local time in addition to the default Date: > in case time zones differ... Hi I agree that something like this would be useful. I made some suggestions further down in the thread Tomi linked to above: in particular I think there should be three possibilities -- show original date, date in my timezone, or both. As three of us seem to be thinking of patching/writing our snippets to do this, I think it could well be worth including in notmuch. I am happy to review a patch. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: notmuch-emacs: Fcc to top-level directory given by database.path
On Sun, 24 Sep 2017, David Bremner wrote: > Arun Isaac writes: > >>> In any case I've noted your feature request/bug-report. It doesn't sound >>> terribly difficult to change, but it will need someone motivated to >>> think about all of the related details like updating the test suite and >>> changing docstrings. >> >> I can contribute this patch. Shall I make it such that if the folder >> part of `notmuch-fcc-dirs' is an empty string, then `notmuch insert' is >> called without a `--folder=' argument? > > Sounds reasonable to me. Any objections Mark? I am not sure: do we want an empty Fcc header to save the message to the root folder? (At the moment the insert fails for an empty Fcc header which isn't good either) In general though are suggesting Fcc header lines of the form "" or "" +sent save to the root folder? Apart from the empty header case that sounds fine. I am not sure about the documentation for it -- the variable is already a little complicated, so I wouldn't want to clutter it further. Incidentally, I think "/" is an alternative for the fcc line which already works, which is "\"/\" in notmuch-fcc-dirs. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: notmuch-emacs: Fcc to top-level directory given by database.path
On Sat, 23 Sep 2017, David Bremner wrote: > Arun Isaac writes: > >> I am using notmuch-emacs, and I would like to Fcc my sent mail to the >> top-level directory given by database.path, instead of using a folder >> like "sent" relative to the top-level directory. >> >> The function `notmuch-maildir-notmuch-insert-current-buffer' in >> notmuch-maildir-fcc.el calls `notmuch insert' with the `--folder=' >> argument. I would like it to not do this. > > Do you happen to know if it calls with an empty string as the folder > name? It would be consistent with searching for that to insert at the > top level. > > In any case I've noted your feature request/bug-report. It doesn't sound > terribly difficult to change, but it will need someone motivated to > think about all of the related details like updating the test suite and > changing docstrings. Alternatively, does just using / as the folder work? Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 2/2] emacs: show: allow user to insert rfc822 parts as messages
> >> + (let* ((folder >> + (read-from-minibuffer "Folder/tags to insert part to: " >> +notmuch-show-part-notmuch-insert-folder))) >> +(mm-with-unibyte-buffer >> + (mm-insert-part handle) >> + (notmuch-maildir-fcc-with-notmuch-insert folder nil "Folder/tags to >> insert part to") >> + (message nil > > Why this? It would be nice to have a comment explaining it. Assuming you mean the message nil bit, This is actually me being dim. I want to remove things like the retry message. But it would be much better to make the insert-part function return something saying whether it succeeded or not, and then give a useful message. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 1/2] emacs: maildir fcc make insert more flexible
Hi Thanks for the review. On Mon, 28 Aug 2017, David Edmondson wrote: > On Monday, 2017-08-28 at 08:32:21 +0100, Mark Walters wrote: > >> This changeset makes the function >> notmuch-maildir-fcc-with-notmuch-insert slightly more flexible by >> allowing some of the prompts to be controlled by the caller. >> --- >> emacs/notmuch-maildir-fcc.el | 16 ++-- >> 1 file changed, 10 insertions(+), 6 deletions(-) >> >> diff --git a/emacs/notmuch-maildir-fcc.el b/emacs/notmuch-maildir-fcc.el >> index 1551e8b..acff24d 100644 >> --- a/emacs/notmuch-maildir-fcc.el >> +++ b/emacs/notmuch-maildir-fcc.el >> @@ -227,7 +227,7 @@ should be a list of tag changes to apply to the inserted >> message." >> (apply 'notmuch-call-notmuch-process >> :stdin-string (buffer-string) "insert" args))) >> >> -(defun notmuch-maildir-fcc-with-notmuch-insert (fcc-header &optional create) >> +(defun notmuch-maildir-fcc-with-notmuch-insert (fcc-header &optional create >> header-name) > > Given that this is not FCC specific, perhaps rename it? Yes that might make sense. > >>"Store message with notmuch insert. >> >> The fcc-header should be of the form \"folder +tag1 -tag2\" where > > I realise that this patch set didn't add this string, but it is mildly > ridiculous. There's no reason that we couldn't use a list, where a > leading “+” or “-” indicates a tag and anything else is a folder. > > Even two variables (one for folder and another for tags) would be an > improvement The reason for this choice is that, when writing the postpone code, I wanted to keep within the message mode compose world, which has the fcc header as a string. I think I would also only like to be queried once when inserting. Or are you suggesting that the user types in a lisp list? Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 0/2] emacs: allow message/rfc822 to be inserted in the mailstore
Several people including id:87bmnlko2o.fsf@len have asked to be able to reply directly to message/rfc822 messages from the emacs frontend. Doing that in emacs would be likely to be a little fragile as all other replies are generated by the cli code. This pair of patches provide an alternative approach: let the user insert the attached message directly into the mailstore. Once it is there, the user can reply as normal. I have been running something like this for a long time (see id:1463744295-12533-1-git-send-email-markwalters1...@gmail.com for my earlier version) with no problems. This new version includes some better error checking, and allows the user to specify tags for the inserted message. The new version is not heavily tested but seems to work. Best wishes Mark Mark Walters (2): emacs: maildir fcc make insert more flexible emacs: show: allow user to insert rfc822 parts as messages emacs/notmuch-maildir-fcc.el | 16 ++-- emacs/notmuch-show.el| 35 +++ 2 files changed, 45 insertions(+), 6 deletions(-) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 1/2] emacs: maildir fcc make insert more flexible
This changeset makes the function notmuch-maildir-fcc-with-notmuch-insert slightly more flexible by allowing some of the prompts to be controlled by the caller. --- emacs/notmuch-maildir-fcc.el | 16 ++-- 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/emacs/notmuch-maildir-fcc.el b/emacs/notmuch-maildir-fcc.el index 1551e8b..acff24d 100644 --- a/emacs/notmuch-maildir-fcc.el +++ b/emacs/notmuch-maildir-fcc.el @@ -227,7 +227,7 @@ should be a list of tag changes to apply to the inserted message." (apply 'notmuch-call-notmuch-process :stdin-string (buffer-string) "insert" args))) -(defun notmuch-maildir-fcc-with-notmuch-insert (fcc-header &optional create) +(defun notmuch-maildir-fcc-with-notmuch-insert (fcc-header &optional create header-name) "Store message with notmuch insert. The fcc-header should be of the form \"folder +tag1 -tag2\" where @@ -239,7 +239,8 @@ quoting each space with an immediately preceding backslash or surrounding the entire folder name in double quotes. If CREATE is non-nil then create the folder if necessary." - (let* ((args (split-string-and-unquote fcc-header)) + (let* ((header-name (or header-name "Fcc header")) +(args (split-string-and-unquote fcc-header)) (folder (car args)) (tags (cdr args))) (condition-case nil @@ -250,14 +251,17 @@ If CREATE is non-nil then create the folder if necessary." ;; how to deal with it. (error (let ((response (notmuch-read-char-choice - "Insert failed: (r)etry, (c)reate folder, (i)gnore, or (e)dit the header? " + (concat +"Insert failed: (r)etry, (c)reate folder, (i)gnore, or (e)dit the " +header-name "? ") '(?r ?c ?i ?e (case response - (?r (notmuch-maildir-fcc-with-notmuch-insert fcc-header)) - (?c (notmuch-maildir-fcc-with-notmuch-insert fcc-header 't)) + (?r (notmuch-maildir-fcc-with-notmuch-insert fcc-header nil header-name)) + (?c (notmuch-maildir-fcc-with-notmuch-insert fcc-header 't header-name)) (?i 't) (?e (notmuch-maildir-fcc-with-notmuch-insert - (read-from-minibuffer "Fcc header: " fcc-header) + (read-from-minibuffer (concat header-name ": ") fcc-header) + nil header-name ; -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 2/2] emacs: show: allow user to insert rfc822 parts as messages
This adds a part-handler function that uses notmuch-insert to insert an rfc822 part as a message in its own right. This allows the user to reply directly to that message. We use notmuch-maildir-fcc-with-notmuch-insert as that has builtin error handling/retry functionality, and it allows the user to specify tags to identify the inserted message. The format of the folder/tags line is the same as for Fcc: headers when using notmuch insert. --- emacs/notmuch-show.el | 35 +++ 1 file changed, 35 insertions(+) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index cd901e4..b3717d0 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -143,6 +143,20 @@ indentation." (const :tag "View interactively" notmuch-show-interactively-view-part))) +(defcustom notmuch-show-part-notmuch-insert-folder "" + "Default folder/tags to use when inserting rfc822 parts into the database. + +It should be of the form \"folder +tag1 -tag2\" where folder is +the folder (relative to the notmuch mailstore) to store the +message in, and tag1 and tag2 are tag changes to apply to the +stored message. This string is split using +`split-string-and-unquote', so a folder name containing spaces +can be specified by quoting each space with an immediately +preceding backslash or surrounding the entire folder name in +double quotes." + :group 'notmuch-show + :type 'string) + (defcustom notmuch-show-only-matching-messages nil "Only matching messages are shown by default." :type 'boolean @@ -1448,6 +1462,7 @@ reset based on the original query." (define-key map "o" 'notmuch-show-interactively-view-part) (define-key map "|" 'notmuch-show-pipe-part) (define-key map "m" 'notmuch-show-choose-mime-of-part) +(define-key map "i" 'notmuch-show-notmuch-insert-part) (define-key map "?" 'notmuch-subkeymap-help) map) "Submap for part commands") @@ -2463,6 +2478,26 @@ part to be treated as if it had that mime-type." (interactive) (notmuch-show-apply-to-current-part-handle #'mm-pipe-part)) +(defun notmuch-show--notmuch-insert-handle (handle) + "Notmuch insert the part associated with HANDLE." + ;; This is based on mm-pipe-part + (let* ((folder + (read-from-minibuffer "Folder/tags to insert part to: " + notmuch-show-part-notmuch-insert-folder))) +(mm-with-unibyte-buffer + (mm-insert-part handle) + (notmuch-maildir-fcc-with-notmuch-insert folder nil "Folder/tags to insert part to") + (message nil + +(defun notmuch-show-notmuch-insert-part () + "If the current part is rfc822 then insert into the mailstore" + (interactive) + (let* ((part (notmuch-show-get-part-properties)) +(computed-type (plist-get part :computed-type))) +(if (notmuch-match-content-type computed-type "message/rfc822") + (notmuch-show-apply-to-current-part-handle +#'notmuch-show--notmuch-insert-handle) + (message "Not a message/rfc822 part." (defun notmuch-show--mm-display-part (handle) "Use mm-display-part to display HANDLE in a new buffer. -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] test: duplicate mids: add an extra broken search test
--- Hi Many thanks to bremner for the parent patch. I thought it might be worth adding a search test after the broken show test demonstrating the distinction between show and search. When I added it I found it actually gives the other file as the answer! This applies on top of the parent patch. Best wishes Mark test/T670-duplicate-mid.sh | 8 1 file changed, 8 insertions(+) diff --git a/test/T670-duplicate-mid.sh b/test/T670-duplicate-mid.sh index 55ebde3..0de2bc0 100755 --- a/test/T670-duplicate-mid.sh +++ b/test/T670-duplicate-mid.sh @@ -86,6 +86,14 @@ expected='[[[{ [' test_expect_equal_json "$output" "$expected" +test_begin_subtest 'First subject preserved in notmuch-search file order' +test_subtest_known_broken +notmuch search id:duplicate | notmuch_search_sanitize > OUTPUT +cat < EXPECTED +thread:XXX 2001-01-05 [1/1(3)] Notmuch Test Suite; message 1 (inbox unread) +EOF +test_expect_equal_file EXPECTED OUTPUT + rm ${MAIL_DIR}/00-copy4 test_begin_subtest 'Deleted first duplicate file does not stop notmuch show from working' output=$(notmuch show --body=false --format=json id:duplicate | notmuch_json_show_sanitize) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Duplicate message ids
Hi A concern for notmuch is some form of attack via someone sending a message with a duplicate message id. I think I have seen it asserted that it is not so much of a problem as the first message received by notmuch will have priority. However, I believe that this is not the case. The script below gives a demonstration (on my system at least). I have written it as a "test" so (I hope) it doesn't mess up the system. It should work if you put it in the test directory and execute it. It adds a message, runs notmuch new, adds a message with the same id, runs notmuch new, and then runs notmuch search and notmuch show . The former shows the subject of the first message, and the latter the subject of the second message. Best wishes Mark #!/usr/bin/env bash test_description='Do duplicate message ids get shown in arrival order' . ./test-lib.sh || exit 1 find ${MAIL_DIR} generate_message [id]=duplicate-id [subject]=first [body]=first mkdir "${MAIL_DIR}"/b mv "$gen_msg_filename" "${MAIL_DIR}"/b notmuch new generate_message [id]=duplicate-id [subject]=second [body]=second mv "$gen_msg_filename" "${MAIL_DIR}"/a notmuch new find ${MAIL_DIR} echo echo SEARCH: observe \"first\" is the subject notmuch search id:duplicate-id echo echo SHOW: observe \"second\" is the subject and body notmuch show --format=json id:duplicate-id |json_pp ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v2] emacs: Add notmuch-update-search-tags
Hi OK I have now actually tested it, and I have read the patch more carefully, but I am afraid I still have concerns. The key problem is the patch assumes that the display of a thread in a search buffer depends only on the thread. And this is not true as the number of matching messages is displayed eg [10/19], and the author list is split into matching authors | unmatching authors. However, when the tags in a thread are changed the patch makes all search buffers containing that thread update to look the same. Indeed, if you change a tag on a single message I think the count will always update to be [1/??] as there is only one message matching the tag-change query. I think you could get round this by modifying your code only slightly -- rather than calling notmuch-search-update-result in notmuch-search-update-results, *just* update the tags, using something like notmuch-search-set-tags. (I have just tried this and it seems to work.) This is not perfect, as this will show tags of newly arrived messages in the thread, but that might well be acceptable. And this still keeps it to one call to the database, which avoids your (completely correct) performance concerns. > It may be possible to optimize this down to one batch search query per > notmuch-search buffer - however, this results in a large search query. > Not only would one take a while to execute, but the resulting query can > become too large to be passed as a command-line parameter, and "notmuch > search" does not seem to have a --batch switch to read queries from > standard input. This points to my next concern -- this is already a problem in the current patch. If you go into a moderately large search buffer, and do something like * +foo (to tag all the messages with foo), the tag step works because is uses the --batch switch to tag, but your search query doesn't. The options here are to: add --batch to search handling, or just decide not to do display the tag updates for large queries. Incidentally there also seems to a bug in the current that the first thread in a search buffer doesn't seem to get updated. I think you are using too low level functions -- things like notmuch-search-foreach-result might do exactly what you need. Finally, in the longer term, do you wanting to do this for tree and show buffers too? [An alternative approach, which I don't think I like but I mention in case others do -- we could only propagate tag changes to parent buffers. So updating a tag in a show buffer only updates the single search buffer that called it. This might avoid the large query problem as show buffers probably don't have large queries.] Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v2] emacs: Add notmuch-update-search-tags
Hi On Sat, 26 Aug 2017, Vladimir Panteleev wrote: > From: Vladimir Panteleev > > Implement an option which, when enabled, causes any tag changes done > from within notmuch-emacs to instantly update matching threads in open > search buffers. I like the idea, and provided it only marks the tags as changed in the normal way, I think we could even default to on. However, I am concerned that this version does other things as well. Note these comments are from reading the patch not from testing, so please point out if I am wrong. 1) Suppose a new message arrives in the thread. Then triggering a tag change in the show buffer, (eg notmuch automatically removing an unread tag) pulls that message into original search buffer. 2) If that new message has some tags that aren't in the thread they will get marked as "added tags" 3) At least in theory I think the thread may no longer exist -- it could have merged with another thread and taken the other threads id. I think 3 is probably rare enough not to be real concern (though we should make sure we don't actually give an error). But 1 and 2 seem undesirable. Rather than refreshing the result it might make sense to fetch the tags for the actual messages in that thread (as it was when the search buffer was loaded) by using notmuch-search-find-stable-query. So something like the following, - in each notmuch-search buffer - see if thread-id thread is in that buffer (or perhaps even if there is a thread which contains message id in that buffer?) - If yes, fetch a new list of tags for the messages that buffer thinks are in that thread (using notmuch-search-find-stable-query). - Update tags appropriately. If we do that then I think the only change in these buffers is the tag updates, and exactly as if you changed those tags in the search buffer itself, the threads shown etc don't change. What do you think? Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: High CPU usage on Tree View with many emails
Hi > When I make a query that gives many results (e.g. "review", which hits > ~2200 emails with my Gerrit reviews) and want to display them in Tree > View, the CPU usage stays high for several seconds. > > While this happens, the Emacs window flickers, like it was busy with > redisplaying the buffer. Yes I see this but I don't quite know why it happens. I think it is to do with the special tree graphics characters. Two things you could try are running emacs in a terminal, and changing the font. If you are happy compiling from source, then you could also try changing the characters used for the tree graphics (in emacs/notmuch-tree.el) If you are feeling more adventurous I think the flicker is fixed in emacs master, so emacs 26 should be OK. (*) Best wishes Mark (*) For an entertaining description of quite what was needed to make emacs double buffer its output see https://www.facebook.com/notes/daniel-colascione/buttery-smooth-emacs/10155313440066102/ > If I pull the horizontal scroll of the Emacs > buffer down, I can see that the buffer grows (like messages being > inserted there). The Emacs profiler says that more than 50% of CPU > time is spend in notmuch-tree-insert-forest-thread. > > Interestingly, the in the non-tree view the same query is processed in no > time. > > Any idea? > > -- > Piotr Trojanek > ___ > notmuch mailing list > notmuch@notmuchmail.org > https://notmuchmail.org/mailman/listinfo/notmuch ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] emacs: tree: bugfix: specify --format-version
Previously notmuch tree did not specify the format-version when calling notmuch. This meant that when the structured output was slightly changed (in commit 14c60cf168ac3b0f277188c16e6012b7ebdadde7) stash filename broke. This fixes this breakage by specifying the format-version. --- Bremner pointed out this bug today on irc. In due course we may want to use format-version=3 and update the helper functions but as none of notmuch-emacs uses the new format version yet this seem the right fix for now. Best wishes Mark emacs/notmuch-tree.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index 7bebdba..d4d4076 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -917,7 +917,7 @@ the same as for the function notmuch-tree." (notmuch-tag-clear-cache) (let ((proc (notmuch-start-notmuch "notmuch-tree" (current-buffer) #'notmuch-tree-process-sentinel -"show" "--body=false" "--format=sexp" +"show" "--body=false" "--format=sexp" "--format-version=2" message-arg search-args)) ;; Use a scratch buffer to accumulate partial output. ;; This buffer will be killed by the sentinel, which -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [RFC patch 2/2] lib: index message files with duplicate message-ids
Hi Just a comment on your last point: > It also occurs to me that one of the things i'd love to have is > well-indexed notes about any given e-mail. So if this was adopted, i > could presumably just write a file that has the same Message-Id as the > message, put my notes in it, and index it. that's a little weird, > though. would there be a better way to do such a thing? A different way which might get pretty close to what you would be to start a reply and then postpone it. Ideally we would wrap this in a "note" function would delete the to/cc/bcc headers to make sure it doesn't accidentally get sent and add a +note tag when saving. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH] emacs: remove use of message-send-hook
On Fri, 10 Mar 2017, David Bremner wrote: > Mark Walters writes: > >> +(let (tag-change >> + post-send-tag-changes) >> + ;; post-send-tag-changes are tag-changes to apply after sending, >> + ;; but we need to store them now as the compose buffer is >> + ;; typically killed before message-send-and-exit returns. >> + (push (notmuch-message-mark-replied t) post-send-tag-changes) >> + (push (notmuch-draft--mark-deleted t) post-send-tag-changes) >> + (letf (((symbol-function 'message-do-fcc) >> #'notmuch-maildir-message-do-fcc)) >> +(if exit >> +(message-send-and-exit arg) >> + (message-send arg))) >> + (dolist (tag-change post-send-tag-changes) >> +(when tag-change >> + (apply #'notmuch-tag tag-change)) Hi > Would it be possible to concatenate the two lists and only call > notmuch-tag once? It seems like that should be notably faster. I think that it's not possible as they are tagging different messages. We could probably do something with --batch but that would mean some change in notmuch-tag itself. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] NEWS for emacs
--- This is the NEWS updates for most of my changes. I am not quite sure whether any of my other changes warranted news items -- prod me if you think they do. Note I changed the heading to Emacs not Emacs Interface to match previous releases but obviously that can be changed back if you prefer. Best wishes Mark NEWS | 65 ++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 652affa..bfd5255 100644 --- a/NEWS +++ b/NEWS @@ -9,10 +9,69 @@ Regular expression searches supported for `from:` and `subject:`. This requires recent Xapian (1.4+) See notmuch-search-terms(7) for details. -Emacs Interface +Emacs +- + +Postpone and resume messages in `notmuch-message-mode` (composition) + + Notmuch now has built in support for postponing, saving and resuming + messages. The default bindings are C-x C-s to save a draft, C-c C-p + to postpone a draft (save and exit compose buffer), and "e" in show + or tree view to resume. + + Draft messages are tagged with `notmuch-draft-tags` (draft by + default) so you may wish to add that to the excluded tags list. When + saving a previously saved draft message the earlier draft gets + tagged deleted. + + Note that attachments added before postponing will be included as + they were when you postponed in the final message. + +Address Completion + + It is now possible to save the list of address completions for + notmuch's internal completion between runs of emacs. This makes the + first calls to address completion much better and faster. For + privacy reasons it is disabled by default, to enable set or + customize `notmuch-address-save-filename`. + +Tag jump menu + + It is now possible to configure tagging shortcuts (with an interface + like notmuch jump). For example (by default) k u will remove the + unread tag, and k s will add a tag "spam" and remove the inbox + tag. Pressing k twice will do the reverse operation so, for example, + k k s removes the spam tag and adds the inbox tag. See the customize + variable `notmuch-tagging-keys` for more information. + +Refresh all buffers + + It is now possible to refresh all notmuch buffers to reflect the + current state of the database with a single command, `M-=`. + +Stop display of application/* parts + + By default gnus displays all application/* parts such as + application/zip in the message buffer. This has several undesirable + effects for notmuch (security, triggering errors etc). Notmuch now + overrides this and does not display them by default. If you have + customized `mm-inline-override-types` then we assume you know what + you want and do not interfere; if you do want to stop the display of + application/* add application/* to your customization. If you want + to allow application/* then set `mm-inline-override-types` to + "non/existent". + +Small change in the api for notmuch-search-tag + + When `notmuch-search-tag` is called non-interactively and the region + is set, then it only tags the threads in the region. (Previously it + only tagged the current thread.) + +Bugfix for sending messages with very long headers. - Save and resume messages in `notmuch-message-mode` (composition). + Previously emacs didn't fold very long headers when sending which + could cause the MTA to refuse to send the message. This makes sure + it does fold any long headers so the message is RFC compliant. Library changes --- -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v3 1/2] Test: emacs: test for folding long headers.
Headers of more than 998 characters should be folded when sending. However, until recently, emacs did not do this. This adds a (known broken) test for this when sending messages in emacs. We will backport the fix to notmuch-emacs in the next changeset. --- test/T310-emacs.sh | 78 ++ 1 file changed, 78 insertions(+) diff --git a/test/T310-emacs.sh b/test/T310-emacs.sh index 01385ae..f626d9a 100755 --- a/test/T310-emacs.sh +++ b/test/T310-emacs.sh @@ -208,6 +208,84 @@ This is a test that messages are sent via SMTP EOF test_expect_equal_file OUTPUT EXPECTED +test_begin_subtest "Folding a long header when sending via (fake) SMTP" +long_subject="This is a long subject `echo {1..1000}`" +emacs_deliver_message \ +"${long_subject}" \ +'This is a test that long headers are folded when messages are sent via SMTP' \ +'(message-goto-to) + (kill-whole-line) + (insert "To: u...@example.com\n")' +sed \ +-e s',^Message-ID: <.*>$,Message-ID: ,' \ +-e s',^\(Content-Type: text/plain\); charset=us-ascii$,\1,' < sent_message >OUTPUT +cat
[PATCH v3 0/2] emacs: fold long headers when sending
Version 2 of this series is at id:1488649637-19006-1-git-send-email-markwalters1...@gmail.com The change here is to split the folding headers function into an explicit function as this makes managing the hook simpler. Best wishes Mark Mark Walters (2): Test: emacs: test for folding long headers. emacs: compat: backport fix for folding long headers when sending emacs/notmuch-compat.el | 28 +++--- test/T310-emacs.sh | 78 + 2 files changed, 102 insertions(+), 4 deletions(-) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v3 2/2] emacs: compat: backport fix for folding long headers when sending
This backports the fix from emacs master (commit 77bbca8c82f6e553c42abbfafca28f55fc995d00) to notmuch-emacs to wrap long headers. This fixes the test introduced in the previous changeset. --- emacs/notmuch-compat.el | 28 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/emacs/notmuch-compat.el b/emacs/notmuch-compat.el index c3d827a..2cedd39 100644 --- a/emacs/notmuch-compat.el +++ b/emacs/notmuch-compat.el @@ -1,8 +1,28 @@ -;; Compatibility functions for emacs 23 and 24 pre 24.4 +;; Compatibility functions for earlier versions of emacs -;; The functions in this file are copied from eamcs 24.4 and are -;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2014 Free Software -;; Foundation, Inc. +;; The functions in this file are copied from more modern versions of +;; emacs and are Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2017 +;; Free Software Foundation, Inc. + + +;; emacs master has a bugfix for folding long headers when sending +;; messages. Include the fix for earlier versions of emacs. To avoid +;; interfering with gnus we only run the hook when called from +;; notmuch-message-mode. + +(declare-function mail-header-fold-field "mail-parse" nil) + +(defun notmuch-message--fold-long-headers () + (when (eq major-mode 'notmuch-message-mode) +(goto-char (point-min)) +(while (not (eobp)) + (when (and (looking-at "[^:]+:") +(> (- (line-end-position) (point)) 998)) + (mail-header-fold-field)) + (forward-line 1 + +(unless (fboundp 'message--fold-long-headers) + (add-hook 'message-header-hook 'notmuch-message--fold-long-headers)) (if (fboundp 'setq-local) (defalias 'notmuch-setq-local 'setq-local) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 0/2] emacs: fold long headers when sending
The only change from v1 (at id:1485684281-2760-1-git-send-email-markwalters1...@gmail.com ) is an updated test as suggested by Domo using echo {1..1000} instead of seq. Best wishes Mark Mark Walters (2): Test: emacs: test for folding long headers. emacs: compat: backport fix for folding long headers when sending emacs/notmuch-compat.el | 28 +++--- test/T310-emacs.sh | 78 + 2 files changed, 102 insertions(+), 4 deletions(-) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 2/2] emacs: compat: backport fix for folding long headers when sending
This backports the fix from emacs master (commit 77bbca8c82f6e553c42abbfafca28f55fc995d00) to notmuch-emacs to wrap long headers. This fixes the test introduced in the previous changeset. --- emacs/notmuch-compat.el | 28 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/emacs/notmuch-compat.el b/emacs/notmuch-compat.el index c3d827a..e71e861 100644 --- a/emacs/notmuch-compat.el +++ b/emacs/notmuch-compat.el @@ -1,8 +1,28 @@ -;; Compatibility functions for emacs 23 and 24 pre 24.4 +;; Compatibility functions for earlier versions of emacs -;; The functions in this file are copied from eamcs 24.4 and are -;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2014 Free Software -;; Foundation, Inc. +;; The functions in this file are copied from more modern versions of +;; emacs and are Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2017 +;; Free Software Foundation, Inc. + + + +;; emacs master has a bugfix for folding long headers when sending +;; messages. Include the fix for earlier versions of emacs. To avoid +;; interfering with gnus we only run the hook when called from +;; notmuch-message-mode. + +(declare-function mail-header-fold-field "mail-parse" nil) + +(unless (fboundp 'message--fold-long-headers) + (add-hook 'message-header-hook + (lambda () + (when (eq major-mode 'notmuch-message-mode) + (goto-char (point-min)) + (while (not (eobp)) + (when (and (looking-at "[^:]+:") +(> (- (line-end-position) (point)) 998)) + (mail-header-fold-field)) + (forward-line 1)) (if (fboundp 'setq-local) (defalias 'notmuch-setq-local 'setq-local) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 1/2] Test: emacs: test for folding long headers.
Headers of more than 998 characters should be folded when sending. However, until recently, emacs did not do this. This adds a (known broken) test for this when sending messages in emacs. We will backport the fix to notmuch-emacs in the next changeset. --- test/T310-emacs.sh | 78 ++ 1 file changed, 78 insertions(+) diff --git a/test/T310-emacs.sh b/test/T310-emacs.sh index 01385ae..f626d9a 100755 --- a/test/T310-emacs.sh +++ b/test/T310-emacs.sh @@ -208,6 +208,84 @@ This is a test that messages are sent via SMTP EOF test_expect_equal_file OUTPUT EXPECTED +test_begin_subtest "Folding a long header when sending via (fake) SMTP" +long_subject="This is a long subject `echo {1..1000}`" +emacs_deliver_message \ +"${long_subject}" \ +'This is a test that long headers are folded when messages are sent via SMTP' \ +'(message-goto-to) + (kill-whole-line) + (insert "To: u...@example.com\n")' +sed \ +-e s',^Message-ID: <.*>$,Message-ID: ,' \ +-e s',^\(Content-Type: text/plain\); charset=us-ascii$,\1,' < sent_message >OUTPUT +cat
Re: Github an licensing
> On irc rlb pointed me to > https://joeyh.name/blog/entry/removing_everything_from_github/ > > IANAL so I don't know whether it is a real problem, a hypothetical > problem or not a problem. I got a couple of links sent to me privately which look relevant: * https://news.ycombinator.com/item?id=13767373 * https://news.ycombinator.com/item?id=13766933 (hacker threads, but from people claiming to be lawyers) Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Github an licensing
Dear All On irc rlb pointed me to https://joeyh.name/blog/entry/removing_everything_from_github/ IANAL so I don't know whether it is a real problem, a hypothetical problem or not a problem. My guess is that it can't affect the main notmuch license as the bulk of notmuch's copyright is owned by people not responsible for the github mirror (*), but it might mean that those of us responsible for the mirror are illegally posting notmuch's code. Does anyone have any views on this, and whether we should carry on maintaining the github mirror? Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v2] emacs: show: stop display of application/* parts
Hi >> But what will we do if the user has not customized it because she >> /wants/ to display all possible things inline. I have not seen that this >> patch is merged into master, and probably, when I have learned about >> this variable, I think maybe it's better not to do it in the notmuch >> code. Well they can set mm-inline-override-types to "non-existent/type". Rather a kludge I agree. > The problem is that the gnus default is somehow unsafe, and causes bad > behaviour for people receiving large attachments. I agree with this and do think we should block this by default. In particular, gnus/mm stuff doesn't even check for the existence of unzip before running it on zip attachments so on my machines which don't have unzip I get a bodypart insertion error. One alternative would be to add a variable notmuch-mm-inline-override-types which would combine or replace mm-inline-override-types for notmuch's use. A defcustom would be clutter, but a variable would mean anyone with unusual requirements could just setq it. What does anyone think? Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [Patch v4] lib: regexp matching in 'subject' and 'from'
On Thu, 09 Feb 2017, David Bremner wrote: > Jani Nikula writes: > >> >> Theoretically "/" is an acceptable character in message-ids [1]. Rare, >> unlikely, but acceptable. Searching for message-id's beginning with "/" >> would have to use regexps, which would break in all sorts of ways >> throughout the stack. I don't think there are handy alternatives to >> "//", given the characters that are acceptable in message-ids, >> but this is something to think about. > > Would telling the user to \ escape ( or double /) the initial / be good > enough there? This would disable regex processing. I guess this goes > back to someone's earlier suggestion. A third option would be to use > single quotes there ("id:'/foo'"), but that isn't really consistent with > either Xapian > or usual regex conventions. > > So I guess my favourite idea ATM is to use id:\/some/crazy/message-id > FWIW, I don't have any such message ids. > >> For example, could the regexp matcher for message-ids first check if the >> "regexp" is a strict match with "/" and all, and accept those? This >> might be a reasonable workaround if it can be made to work. > > We're building a query, so I think the equivalent is to make an OR, with > the exact match and the regex posting source. That could be done, > although I'm a bit uneasy about how this makes the syntax for id: > different, so id:/foo would be legit, but from:/foo would be an error. > Maybe the dwim-factor is worth it. Hi Broadly I like the backslash escaping option. Two thoughts: can any fields (from/subject/message-id) start with a "\" anyway? I think not but thought it worth checking. Secondly, message-id is often round-tripped, that is output from notmuch and then fed back to notmuch. Do we want to escape the output as above before printing in any cases? My view is that if we output the message-id prefixed with "id:" then we should escape it (which applies with --output=messages --format=text), but if we don't print the "id:" part then we shouldn't (eg with --format=json). A similar thing would apply to emacs: if it is a normal stash then escape the id, but if it is a "bare stash" then do not. Actually, one more thing: it would be a shame to block or significantly delay the series for such a corner case. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] test: fix tests for content-disposition
This fixes all tests for the recent addition of content-disposition to the structured format outputs of notmuch-show. --- Since Jani added the content-disposition as I wanted to use it from emacs (thanks Jani!) I thought I should fix the tests. I don't know if it should be folded in to the main patch or applied separately. Either is fine with me. Best wishes Mark test/T160-json.sh | 2 +- test/T170-sexp.sh | 2 +- test/T190-multipart.sh | 22 ++ test/T350-crypto.sh| 1 + 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/test/T160-json.sh b/test/T160-json.sh index b346f37..74e0d8f 100755 --- a/test/T160-json.sh +++ b/test/T160-json.sh @@ -48,7 +48,7 @@ output=$(notmuch show --format=json "id:$id") filename=$(notmuch search --output=files "id:$id") # Get length of README after base64-encoding, minus additional newline. attachment_length=$(( $(base64 $TEST_DIRECTORY/README | wc -c) - 1 )) -test_expect_equal_json "$output" "[[[{\"id\": \"$id\", \"match\": true, \"excluded\": false, \"filename\": \"$filename\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subject\": \"$subject\", \"From\": \"Notmuch Test Suite \", \"To\": \"test_su...@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +\"}, \"body\": [{\"id\": 1, \"content-type\": \"multipart/mixed\", \"content\": [{\"id\": 2, \"content-type\": \"text/plain\", \"content\": \"This is a test message with inline attachment with a filename\"}, {\"id\": 3, \"content-type\": \"application/octet-stream\", \"content-length\": $attachment_length, \"content-transfer-encoding\": \"base64\", \"filename\": \"README\"}]}]}, [" +test_expect_equal_json "$output" "[[[{\"id\": \"$id\", \"match\": true, \"excluded\": false, \"filename\": \"$filename\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subject\": \"$subject\", \"From\": \"Notmuch Test Suite \", \"To\": \"test_su...@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +\"}, \"body\": [{\"id\": 1, \"content-type\": \"multipart/mixed\", \"content\": [{\"id\": 2, \"content-type\": \"text/plain\", \"content\": \"This is a test message with inline attachment with a filename\"}, {\"id\": 3, \"content-type\": \"application/octet-stream\", \"content-length\": $attachment_length, \"content-transfer-encoding\": \"base64\", \"content-disposition\": \"inline\", \"filename\": \"README\"}]}]}, [" test_begin_subtest "Search message: json, utf-8" add_message "[subject]=\"json-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" "[body]=\"jsön-search-méssage\"" diff --git a/test/T170-sexp.sh b/test/T170-sexp.sh index 800ebc6..2088972 100755 --- a/test/T170-sexp.sh +++ b/test/T170-sexp.sh @@ -39,7 +39,7 @@ output=$(notmuch show --format=sexp "id:$id") filename=$(notmuch search --output=files "id:$id") # Get length of README after base64-encoding, minus additional newline. attachment_length=$(( $(base64 $TEST_DIRECTORY/README | wc -c) - 1 )) -test_expect_equal "$output" ":id \"$id\" :match t :excluded nil :filename \"$filename\" :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\") :headers (:Subject \"sexp-show-inline-attachment-filename\" :From \"Notmuch Test Suite \" :To \"test_su...@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +\") :body ((:id 1 :content-type \"multipart/mixed\" :content ((:id 2 :content-type \"text/plain\" :content \"This is a test message with inline attachment with a filename\") (:id 3 :content-type \"application/octet-stream\" :filename \"README\" :content-transfer-encoding \"base64\" :content-length $attachment_length) (" +test_expect_equal "$output" ":id \"$id\" :match t :excluded nil :filename \"$filename\" :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\") :headers (:Subject \"sexp-show-inline-attachment-filename\" :From \"Notmuch Test Suite \" :To \"test_su...@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +\") :body ((:id 1 :content-type \"multipart/mixed\" :content ((:id 2 :content-type \"text/plain\" :content \"This is a test message with inline attachment with a filename\") (:id 3 :content-type \"application/octet-stream\" :content-disposition \"inline\" :filename \"README\" :content-transfer-encoding \"base64\" :content-length $attachment_length) (" test_begin_subtest "Search message: sexp, utf-8" add_message "[subject]=\"sexp-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" "[body]=\"jsön-search-méssage\"" diff --git a/test/T190-multipart.sh b/test/T190-multipart.sh index 3567890..b631c5e 100755 --- a/test/T190-multipart.sh +++ b/test/T190-multipart.sh @@ -348,11 +348,11 @@ cat
Re: [PATCH 2/2] cli/show: add content-disposition to structured output message parts
On Sat, 28 Jan 2017, Jani Nikula wrote: > Help the clients decide how to display parts. This series looks good to me. I would say +1, but I am not sure my knowledge of C is really up to that. There are a bunch of tests to update; I will send a patch to do that in shortly. > I'm not sure if this should bump the version in schemata, because the > comment in notmuch-client.h says new map fields can be added without > increasing NOTMUCH_FORMAT_CUR. Yet the schemata version history says > thread_summary.query was added in v2... which looks like a change that > shouldn't need a version bump. Confused. I think the reason for the bump before was that the client needed to know it had got the new format, so it could either bail out, or at least work around it, if it got the old format. In this case though, I think any sane program has to treat content-disposition nil as being "do whatever the default is" (since I don't think all parts have a content-disposition). Thus, I don't think we need a schemata bump, as the client can just use the extra information if present, and otherwise do what it normally would. Best wishes Mark > > The problem could be avoided by conflating both this change and > id:20170110201929.21875-1-j...@nikula.org into v3... ;) > --- > devel/schemata | 1 + > notmuch-show.c | 6 ++ > 2 files changed, 7 insertions(+) > > diff --git a/devel/schemata b/devel/schemata > index 41dc4a60fff3..c94459eb783a 100644 > --- a/devel/schemata > +++ b/devel/schemata > @@ -76,6 +76,7 @@ part = { > sigstatus?: sigstatus, > > content-type: string, > +content-disposition?: string, > content-id?:string, > # if content-type starts with "multipart/": > content:[part*], > diff --git a/notmuch-show.c b/notmuch-show.c > index 8b38fe6db136..8e69b3465886 100644 > --- a/notmuch-show.c > +++ b/notmuch-show.c > @@ -582,6 +582,7 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, > mime_node_t *node, > GMimeObject *meta = node->envelope_part ? > GMIME_OBJECT (node->envelope_part) : node->part; > GMimeContentType *content_type = g_mime_object_get_content_type (meta); > +const char *disposition = _get_disposition (meta); > const char *cid = g_mime_object_get_content_id (meta); > const char *filename = GMIME_IS_PART (node->part) ? > g_mime_part_get_filename (GMIME_PART (node->part)) : NULL; > @@ -611,6 +612,11 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, > mime_node_t *node, > sp->map_key (sp, "content-type"); > sp->string (sp, g_mime_content_type_to_string (content_type)); > > +if (disposition) { > + sp->map_key (sp, "content-disposition"); > + sp->string (sp, disposition); > +} > + > if (cid) { > sp->map_key (sp, "content-id"); > sp->string (sp, cid); > -- > 2.11.0 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 0/2] emacs: Fold long headers when sending
This pair of patches add a test for folding long headers, and backport the bugfix from emacs master. This fixes the bug reported in id:87612qwh04@viking.dsc.soic.indiana.edu The fix in emacs master (77bbca8c82f6e553c42abbfafca28f55fc995d00) runs the folding function just before message-header-hook, so this fix should give almost exactly the same behaviour. Since message--fold-long-headers was introduced in the same commit this should mean we do not apply the fix for any version of emacs which it already has it. I don't know whether my bash in the test suite is sufficiently portable, so if anyone who knows about that could check I would be grateful. (For example, is seq -s " " 1 1000 standard?) Best wishes Mark Mark Walters (2): Test: emacs: test for folding long headers. emacs: compat: backport fix for folding long headers when sending emacs/notmuch-compat.el | 28 +++--- test/T310-emacs.sh | 78 + 2 files changed, 102 insertions(+), 4 deletions(-) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 1/2] Test: emacs: test for folding long headers.
Headers of more than 998 characters should be folded when sending. However, until recently, emacs did not do this. This adds a (known broken) test for this when sending messages in emacs. We will backport the fix to notmuch-emacs in the next changeset. --- test/T310-emacs.sh | 79 ++ 1 file changed, 79 insertions(+) diff --git a/test/T310-emacs.sh b/test/T310-emacs.sh index 01385ae..5331514 100755 --- a/test/T310-emacs.sh +++ b/test/T310-emacs.sh @@ -208,6 +208,85 @@ This is a test that messages are sent via SMTP EOF test_expect_equal_file OUTPUT EXPECTED +test_begin_subtest "Folding a long header when sending via (fake) SMTP" +test_subtest_known_broken +long_subject="This is a long subject `seq -s ' ' 1 1000`" +emacs_deliver_message \ +"${long_subject}" \ +'This is a test that long headers are folded when messages are sent via SMTP' \ +'(message-goto-to) + (kill-whole-line) + (insert "To: u...@example.com\n")' +sed \ +-e s',^Message-ID: <.*>$,Message-ID: ,' \ +-e s',^\(Content-Type: text/plain\); charset=us-ascii$,\1,' < sent_message >OUTPUT +cat
[PATCH 2/2] emacs: compat: backport fix for folding long headers when sending
This backports the fix from emacs master (commit 77bbca8c82f6e553c42abbfafca28f55fc995d00) to notmuch-emacs to wrap long headers. This fixes the test introduced in the previous changeset. --- emacs/notmuch-compat.el | 28 test/T310-emacs.sh | 1 - 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/emacs/notmuch-compat.el b/emacs/notmuch-compat.el index c3d827a..e71e861 100644 --- a/emacs/notmuch-compat.el +++ b/emacs/notmuch-compat.el @@ -1,8 +1,28 @@ -;; Compatibility functions for emacs 23 and 24 pre 24.4 +;; Compatibility functions for earlier versions of emacs -;; The functions in this file are copied from eamcs 24.4 and are -;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2014 Free Software -;; Foundation, Inc. +;; The functions in this file are copied from more modern versions of +;; emacs and are Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2017 +;; Free Software Foundation, Inc. + + + +;; emacs master has a bugfix for folding long headers when sending +;; messages. Include the fix for earlier versions of emacs. To avoid +;; interfering with gnus we only run the hook when called from +;; notmuch-message-mode. + +(declare-function mail-header-fold-field "mail-parse" nil) + +(unless (fboundp 'message--fold-long-headers) + (add-hook 'message-header-hook + (lambda () + (when (eq major-mode 'notmuch-message-mode) + (goto-char (point-min)) + (while (not (eobp)) + (when (and (looking-at "[^:]+:") +(> (- (line-end-position) (point)) 998)) + (mail-header-fold-field)) + (forward-line 1)) (if (fboundp 'setq-local) (defalias 'notmuch-setq-local 'setq-local) diff --git a/test/T310-emacs.sh b/test/T310-emacs.sh index 5331514..a486df8 100755 --- a/test/T310-emacs.sh +++ b/test/T310-emacs.sh @@ -209,7 +209,6 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Folding a long header when sending via (fake) SMTP" -test_subtest_known_broken long_subject="This is a long subject `seq -s ' ' 1 1000`" emacs_deliver_message \ "${long_subject}" \ -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] emacs: fully add the notmuch-address customize group
We now have several customizable options for address completion. There is a customize group notmuch-address but it only contains one of these options. Add all the others, and make it part of the notmuch customize group. --- Bremner pointed out that many of these were not in the notmuch-addres customize group, so we add them all. Best wishes Mark emacs/notmuch-address.el | 7 ++- emacs/notmuch-lib.el | 4 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el index 15c709d..d504ff2 100644 --- a/emacs/notmuch-address.el +++ b/emacs/notmuch-address.el @@ -66,6 +66,7 @@ disabled." (const :tag "Disable address completion" nil) (string :tag "Use external completion command")) :group 'notmuch-send + :group 'notmuch-address :group 'notmuch-external) (defcustom notmuch-address-internal-completion '(sent nil) @@ -93,6 +94,7 @@ This should be a list of the form '(DIRECTION FILTER), where (setq notmuch-address-completions (clrhash notmuch-address-completions)) (setq notmuch-address-full-harvest-finished nil)) :group 'notmuch-send + :group 'notmuch-address :group 'notmuch-external) (defcustom notmuch-address-save-filename nil @@ -104,6 +106,7 @@ should make sure it is not somewhere publicly readable." :type '(choice (const :tag "Off" nil) (file :tag "Filename")) :group 'notmuch-send + :group 'notmuch-address :group 'notmuch-external) (defcustom notmuch-address-selection-function 'notmuch-address-selection-function @@ -115,6 +118,7 @@ See documentation of function `notmuch-address-selection-function' to know how address selection is made by default." :type 'function :group 'notmuch-send + :group 'notmuch-address :group 'notmuch-external) (defcustom notmuch-address-post-completion-functions nil @@ -145,7 +149,8 @@ matching `notmuch-address-completion-headers-regexp'. (defcustom notmuch-address-use-company t "If available, use company mode for address completion" :type 'boolean - :group 'notmuch-send) + :group 'notmuch-send + :group 'notmuch-address) (defun notmuch-address-setup () (let* ((setup-company (and notmuch-address-use-company diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 5dc6797..337b20a 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -74,6 +74,10 @@ "Running external commands from within Notmuch." :group 'notmuch) +(defgroup notmuch-address nil + "Address completion." + :group 'notmuch) + (defgroup notmuch-faces nil "Graphical attributes for displaying text" :group 'notmuch) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] emacs: company: remove two build warnings
This adds two defvars to avoid two build warnings in the notmuch emacs code. These were both introduced (by me) in commit 827c28a0. --- The defvar for notmuch-address-command is clearly correct as that is defined in notmuch-address so will definitely be defined when this code is run. The other, for company-idle-timeout, is slightly less clear, as the user may not use company. It feels a little unpleasant to be defining variables outside our namespace but we do the same with company-backends. [Incidentally I don't think emacs compiler should complain as the actual use (line 59) is a macro which does bind the variable in any case.] Best wishes Mark emacs/notmuch-company.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/emacs/notmuch-company.el b/emacs/notmuch-company.el index dca6471..3e12e7a 100644 --- a/emacs/notmuch-company.el +++ b/emacs/notmuch-company.el @@ -37,12 +37,14 @@ (declare-function company-mode "company") (declare-function company-manual-begin "company") (defvar company-backends) +(defvar company-idle-delay) (declare-function notmuch-address-harvest "notmuch-address") (declare-function notmuch-address-harvest-trigger "notmuch-address") (declare-function notmuch-address-matching "notmuch-address") (declare-function notmuch-address--harvest-ready "notmuch-address") (defvar notmuch-address-completion-headers-regexp) +(defvar notmuch-address-command) ;;;###autoload (defun notmuch-company-setup () -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2] emacs: show: stop display of application/* parts
Gnus seems to display application/zip and application/tar by default. This doesn't seem desirable so we override it. We only override if the user has not customized mm-inline-override-types themselves. --- I think this fixes all the bugs (and typos). Thanks to Tomas and Tomi for finding and verifying the correct way to get the default value of a defcustom variable. It's only lightly tested but seems to work. Best wishes Mark emacs/notmuch-show.el | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 364004b..c670160 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -1227,7 +1227,15 @@ matched." (interactive "sNotmuch show: \nP") (let ((buffer-name (generate-new-buffer-name (or buffer-name - (concat "*notmuch-" thread-id "*") + (concat "*notmuch-" thread-id "*" + ;; We override mm-inline-override-types to stop application/* + ;; parts from being displayed unless the user has customized + ;; it themselves. + (mm-inline-override-types +(if (equal mm-inline-override-types + (eval (car (get 'mm-inline-override-types 'standard-value +(cons "application/*" mm-inline-override-types) + mm-inline-override-types))) (switch-to-buffer (get-buffer-create buffer-name)) ;; No need to track undo information for this buffer. (setq buffer-undo-list t) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: Q: notmuch emacs, fcc, maildir, notmuch insert and message-kill-buffer-on-exit
Hi I am not sure what the full problem is (I will try and have a better look later), but I think the main problem is that the sending mail part is returning an error. The "Sending...failed to" is coming from emacs, and I think the "mail for [ -oi -t > ] : send was successful; " from msmtp/msmptq. The insert is done after the send, so since this returns an error the insert is never attempted. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] emacs: show: stop display of appliaction/* parts
Gnus seems to display application/zip and application/tar by default. This doesn't seem desirable so we override it. We only override ifthe user has not customized mm-inline-override-types themselves. --- This was mentioned on irc today and this might be a reasonable way of doing this. It does mean that if a user adds, for example, image/* to mm-inline-override-types then application/* will be displayed again. It also makes it slightly awkward to allow all types (eg setting mm-inline-override-types to non/existent would do). Also I feel there ought to be a better way to tell if a variable has been customized (or otherwise set), but I didn't find one. Best wishes Mark emacs/notmuch-show.el | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 364004b..42734ac 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -1227,7 +1227,15 @@ matched." (interactive "sNotmuch show: \nP") (let ((buffer-name (generate-new-buffer-name (or buffer-name - (concat "*notmuch-" thread-id "*") + (concat "*notmuch-" thread-id "*" + ;; We override mm-inline-override-types to stop appliacation/* + ;; parts from being displayed unless the user has customized + ;; it themselves. + (mm-inline-override-types +(if (equal (list mm-inline-override-types) + (get 'mm-inline-override-types 'standard-value)) +(cons "application/*" mm-inline-override-types) + mm-inline-override-types))) (switch-to-buffer (get-buffer-create buffer-name)) ;; No need to track undo information for this buffer. (setq buffer-undo-list t) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[WIP PATCH] emacs: tag-jump allow post tag functions
This adds an option to the tag-jump defcustom to apply a post-tagging function. One natural option is to go to the next thread/message. --- This is a first attempt at this. The main change needed is to update the docstrings. The structure is a little weird (a list with a plist as an element). However this has two advantage, it is backward compatible, and it is possible to hide the more complicated options. Best wishes Mark emacs/notmuch-tag.el | 33 ++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el index 09d182d..a6506dc 100644 --- a/emacs/notmuch-tag.el +++ b/emacs/notmuch-tag.el @@ -42,7 +42,25 @@ (key-sequence :tag "Key") (radio :tag "Tag operations" (repeat :tag "Tag list" (string :format "%v" :tag "change")) (variable :tag "Tag variable")) - (string :tag "Name" + (string :tag "Name") + (choice :tag "Advanced Options" + (const :tag "None" nil) + (list :tag "Choose" + (const :format "" :post-search) + (choice :tag "Post tag in search view: " + (const :tag "None" ignore) + (const :tag "Next" notmuch-search-next-thread) + (function :tag "Custom function" :format "%v")) + (const :format "" :post-tree) + (choice :tag "Post tag in tree view: " + (const :tag "None" ignore) + (const :tag "Next" notmuch-tree-next-message) + (function :tag "Custom function" :format "%v")) + (const :format "" :post-show) + (choice :tag "Post tag in show view: " + (const :tag "None" ignore) + (const :tag "Next" notmuch-show-next-message) + (function :tag "Custom function" :format "%v"))) (defcustom notmuch-tagging-keys `((,(kbd "a") notmuch-archive-tags "Archive") @@ -530,9 +548,18 @@ and vice versa." (name-string (if name (if reverse (concat "Reverse " name) name) - (mapconcat #'identity tag-change " " + (mapconcat #'identity tag-change " "))) +(adv-opts (fourth binding)) +(post-tag-function + (case major-mode + (notmuch-search-mode (plist-get adv-opts :post-search)) + (notmuch-show-mode (plist-get adv-opts :post-show)) + (notmuch-tree-mode (plist-get adv-opts :post-tree) (push (list key name-string -`(lambda () (,tag-function ',tag-change))) + `(lambda () (,tag-function ',tag-change) + ,(if post-tag-function + `(,post-tag-function) + '(ignore action-map))) (push (list notmuch-tag-jump-reverse-key (if reverse -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: anyone uses notmuch-web?
> i'm an user of notmuch already for some years (in fact from the beginning). > great product! i want to replace my roundcube installation on web server by > notmuch-web, which - at least in testing on local computer - looks great and > does exactly the job. > > my concerns are in the domain of the internet security. apparently the haskell > stuff (sorry, not a haskell guy) cannot go over https, but only http, and for > this one has to do some proxying between http and https done on http > server > level. I can't say much about notmuch-web but as a shameless plug rlb and I are working on noservice https://gitlab.com/noservice/noservice This is intended as pure https (ideally you use a firewall to block its http port), and by default uses client certificate verification so is probably reasonably secure. Note neither rlb nor I are security experts. A rough guide is that noservice is intended to look and feel like the emacs frontend. I use it every day and it meets most of my requirements. > is anyone using such modus operandi? could you share your thoughts about using > notmuch-web? If you do decide to use notmuch-web then possibly try nginx as the https frontend, and you can configure that to require client certificates. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [emacs] thread view is showing all messages
Hi >> -- >> By default, various components of email messages, (citations, >> signatures, already-read messages), are hidden. >> -- I wonder if this text should be changed -- I am not sure what is meant by already-read messages (maybe completely cited messages?) but it does seem misleading. Having said that, I don't have a good suggestion -- the best I can come up with is "quoted messages" Interestingly the wording above dates back to 2009 so maybe it isn't that big a problem. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: Filtering completions
Hi On Mon, 21 Nov 2016, Sebastian Fischmeister wrote: > Hi, > > Is there a variable defining a regex to filter harvested completions before > showing them? My completions include some outdated or invalid email addresses > for people and I would like to automatically remove them from the list. > > I didn't find something for that in notmuch-address.el, and for instance > notmuch-address-matching. There is no regex or similar, but you can filter the search used to harvest the addresses -- see notmuch-address-internal-completion (customisable under notmuch-send). You might find that putting a date limit would work; alternatively you could tag messages from the dead addresses (eg tag:dead-address) and put a "not tag:dead-address" in the filter field. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 2/2] emacs: address: save hash
This allows the user to save the address hash so that it is much faster for the first completion after a restart. This defaults to off as there are privacy implications to saving this information. The code tries hard to avoid overwriting the wrong file. It also notes if changes have been made to any of the relevant user settings, so that the user does not get surprising results (i.e., outdated options being used). Finally it stores some version information so that is easy for us to update the format of the save file. --- emacs/notmuch-address.el | 83 +--- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el index 2eaca79..15c709d 100644 --- a/emacs/notmuch-address.el +++ b/emacs/notmuch-address.el @@ -37,11 +37,15 @@ (defvar notmuch-address-full-harvest-finished nil "t indicates that full completion address harvesting has been -finished. Use notmuch-address--harvest-ready to access.") +finished. Use notmuch-address--harvest-ready to access as that +will load a saved hash if necessary (and available).") (defun notmuch-address--harvest-ready () - "Return t if there is a full address hash available." - notmuch-address-full-harvest-finished) + "Return t if there is a full address hash available. + +If the hash is not present it attempts to load a saved hash." + (or notmuch-address-full-harvest-finished + (notmuch-address--load-address-hash))) (defcustom notmuch-address-command 'internal "Determines how address completion candidates are generated. @@ -91,6 +95,17 @@ This should be a list of the form '(DIRECTION FILTER), where :group 'notmuch-send :group 'notmuch-external) +(defcustom notmuch-address-save-filename nil + "Filename to save the cached completion addresses. + +All the addresses notmuch uses for address completion will be +cached in this file. This has obvious privacy implications so you +should make sure it is not somewhere publicly readable." + :type '(choice (const :tag "Off" nil) +(file :tag "Filename")) + :group 'notmuch-send + :group 'notmuch-external) + (defcustom notmuch-address-selection-function 'notmuch-address-selection-function "The function to select address from given list. The function is called with PROMPT, COLLECTION, and INITIAL-INPUT as arguments @@ -327,6 +342,64 @@ execution, CALLBACK is called when harvesting finishes." ;; return value nil) +(defvar notmuch-address--save-hash-version 1 + "Version format of the save hash.") + +(defun notmuch-address--get-address-hash () + "Returns the saved address hash as a plist. + +Returns nil if the save file does not exist, or it does not seem +to be a saved address hash." + (when notmuch-address-save-filename +(condition-case nil + (with-temp-buffer + (insert-file-contents notmuch-address-save-filename) + (let ((name (read (current-buffer))) + (plist (read (current-buffer + ;; We do two simple sanity checks on the loaded file. We just + ;; check a version is specified, not that it is the current + ;; version, as we are allowed to over-write and a save-file with + ;; an older version. + (when (and (string= name "notmuch-address-hash") + (plist-get plist :version)) + plist))) + ;; The error case catches any of the reads failing. + (error nil + +(defun notmuch-address--load-address-hash () + "Read the saved address hash and set the corresponding variables." + (let ((load-plist (notmuch-address--get-address-hash))) +(when (and load-plist + ;; If the user's setting have changed, or the version + ;; has changed, return nil to make sure the new settings + ;; take effect. + (equal (plist-get load-plist :completion-settings) + notmuch-address-internal-completion) + (equal (plist-get load-plist :version) + notmuch-address--save-hash-version)) + (setq notmuch-address-last-harvest (plist-get load-plist :last-harvest) + notmuch-address-completions (plist-get load-plist :completions) + notmuch-address-full-harvest-finished t) + ;; Return t to say load was successful. + t))) + +(defun notmuch-address--save-address-hash () + (when notmuch-address-save-filename +(if (or (not (file-exists-p notmuch-address-save-filename)) + ;; The file exists, check it is a file we saved + (notmuch-address--get-address-hash)) + (with-temp-file notmuch-address-save-filename + (let ((save-plist (list :version notmuch-address--save-hash-version + :completion-settings notmuch-address-internal-completion + :last-harvest notmuch-address-last-harvest + :completions notmuch-address-completi
[PATCH 0/2] emacs allow save and load of the address-completions
This series adds a load/save functionality for the address completions. This avoids the slow and poor completion provided until the full address-hash has been generated -- this can take some time, (over a minute on my machine), and is annoying if you frequently restart emacs (e.g. when debugging things). Although the patch is quite large it is relatively simple: essentially a "print" to save, and a "read" to load. I have tried quite hard to stop over-writing existing files, and to make sure the user does not get surprising results if they change settings or the address completion is upgraded in some way (e.g., we store the frequency of each match in the map). By default the save/load is switched off: this avoids accidental privacy leaks, but does make it harder for users to discover. Best wishes Mark Mark Walters (2): emacs: address: move address-full-harvest-finished to a function emacs: address: save hash emacs/notmuch-address.el | 85 ++-- emacs/notmuch-company.el | 4 +-- 2 files changed, 84 insertions(+), 5 deletions(-) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 1/2] emacs: address: move address-full-harvest-finished to a function
This makes the code access notmuch-address-full-harvest-finished via a helper function, notmuch-address--harvest-ready. Later we will use this to check whether we can load the harvest instead of regenerating it. --- emacs/notmuch-address.el | 8 ++-- emacs/notmuch-company.el | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el index b3c56cf..2eaca79 100644 --- a/emacs/notmuch-address.el +++ b/emacs/notmuch-address.el @@ -37,7 +37,11 @@ (defvar notmuch-address-full-harvest-finished nil "t indicates that full completion address harvesting has been -finished") +finished. Use notmuch-address--harvest-ready to access.") + +(defun notmuch-address--harvest-ready () + "Return t if there is a full address hash available." + notmuch-address-full-harvest-finished) (defcustom notmuch-address-command 'internal "Determines how address completion candidates are generated. @@ -170,7 +174,7 @@ elisp-based implementation or older implementation requiring external commands." (cond ((eq notmuch-address-command 'internal) -(when (not notmuch-address-full-harvest-finished) +(unless (notmuch-address--harvest-ready) ;; First, run quick synchronous harvest based on what the user ;; entered so far (notmuch-address-harvest original t)) diff --git a/emacs/notmuch-company.el b/emacs/notmuch-company.el index ebe2c08..dca6471 100644 --- a/emacs/notmuch-company.el +++ b/emacs/notmuch-company.el @@ -41,7 +41,7 @@ (declare-function notmuch-address-harvest "notmuch-address") (declare-function notmuch-address-harvest-trigger "notmuch-address") (declare-function notmuch-address-matching "notmuch-address") -(defvar notmuch-address-full-harvest-finished) +(declare-function notmuch-address--harvest-ready "notmuch-address") (defvar notmuch-address-completion-headers-regexp) ;;;###autoload @@ -70,7 +70,7 @@ (line-beginning-position)) (setq notmuch-company-last-prefix (company-grab "[:,][ \t]*\\(.*\\)" 1 (point-at-bol) (candidates (cond - (notmuch-address-full-harvest-finished + ((notmuch-address--harvest-ready) ;; Update harvested addressed from time to time (notmuch-address-harvest-trigger) (notmuch-address-matching arg)) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] NEWS for notmuch-cycle-notmuch-buffers
--- A first attempt at NEWS for 09caa0f. I am not fully happy with it, so any suggestions very welcome. It applies on top of id:20161117121820.23393-1-da...@tethera.net Best wishes Mark NEWS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/NEWS b/NEWS index e693da7..3413a9c 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,13 @@ Notmuch 0.23.2 (UNRELEASED) Emacs - +Fix notmuch-interesting-buffer and notmuch-cycle-notmuch-buffers. + + The functions `notmuch-interesting-buffer` which detects notmuch + buffers, and `notmuch-cycle-notmuch-buffers` which cycles between + notmuch buffers, now additionally detect notmuch-tree-mode and + notmuch-message-mode buffers. + Restore compatibility with Emacs 23. Notmuch support for Emacs 23 is now deprecated. -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] emacs: remove use of message-send-hook
We use message-send-hook for two things -- tagging drafts deleted, and tagging replied the parent message of a reply. We should not use message-send-hook as that will affect gnus etc too. Moreover, message-send-hook is run before the message is sent, even before the user confirms they want to send it (if message-confirm-send is set). This means the user can do C-c C-c to send, then cancel, and the parent is still tagged replied. Now we have our own send function it is natural to put these functions there rather than in the hook. We also fix the bug mentioned above. This is slightly tricky as message-send-and-exit kills the compose buffer, so we need to store the tagging commands ready to be run after the send is successful. --- As mentioned in the commit message, we need to remove our use of message-send-hook and fix the bug of erroneously tagging messages "replied" or "deleted". This approach might be a little overkill (a dolist for a list of two elements), but it avoids breaking the api (for notmuch-message-mark-replied) and is easily extendable if we need to add more post send tagging operations later. Also, it seemed easiest to tweak the require orders, but maybe we should just move the two things in notmuch-message into notmuch-mua. Best wishes Mark emacs/notmuch-draft.el | 12 ++-- emacs/notmuch-message.el | 12 +++- emacs/notmuch-mua.el | 19 +++ 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/emacs/notmuch-draft.el b/emacs/notmuch-draft.el index fb7f4f5..738628b 100644 --- a/emacs/notmuch-draft.el +++ b/emacs/notmuch-draft.el @@ -91,12 +91,15 @@ postponing and resuming a message." "Message-id of the most recent saved draft of this message") (make-variable-buffer-local 'notmuch-draft-id) -(defun notmuch-draft--mark-deleted () +(defun notmuch-draft--mark-deleted (&optional dry-run) "Tag the last saved draft deleted. -Used when a new version is saved, or the message is sent." +Used when a new version is saved, or the message is sent. If +DRY-RUN is set, then just return a list of the arguments for +`notmuch-tag' rather than doing the tagging." (when notmuch-draft-id -(notmuch-tag notmuch-draft-id '("+deleted" +(funcall (if dry-run #'list #'notmuch-tag) +notmuch-draft-id '("+deleted" (defun notmuch-draft-quote-some-mml () "Quote the mml tags in `notmuch-draft-quoted-tags`." @@ -259,9 +262,6 @@ applied to newly inserted messages)." (setq notmuch-draft-id (when draft id) -(add-hook 'message-send-hook 'notmuch-draft--mark-deleted) - - (provide 'notmuch-draft) ;;; notmuch-draft.el ends here diff --git a/emacs/notmuch-message.el b/emacs/notmuch-message.el index 55e4cfe..373d38c 100644 --- a/emacs/notmuch-message.el +++ b/emacs/notmuch-message.el @@ -23,7 +23,6 @@ (require 'message) (require 'notmuch-tag) -(require 'notmuch-mua) (defcustom notmuch-message-replied-tags '("+replied") "List of tag changes to apply to a message when it has been replied to. @@ -38,15 +37,18 @@ the \"inbox\" and \"todo\" tags, you would set: :type '(repeat string) :group 'notmuch-send) -(defun notmuch-message-mark-replied () +(defun notmuch-message-mark-replied (&optional dry-run) + "Tag the parent message replied. + +If DRY-RUN is set, then just return a list of the arguments for +`notmuch-tag' rather than doing the tagging." ;; get the in-reply-to header and parse it for the message id. (let ((rep (mail-header-parse-addresses (message-field-value "In-Reply-To" (when (and notmuch-message-replied-tags rep) - (notmuch-tag (notmuch-id-to-query (car (car rep))) + (funcall (if dry-run #'list #'notmuch-tag) + (notmuch-id-to-query (car (car rep))) (notmuch-tag-change-list notmuch-message-replied-tags) -(add-hook 'message-send-hook 'notmuch-message-mark-replied) - (provide 'notmuch-message) ;;; notmuch-message.el ends here diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index 93747b1..07be69a 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -28,6 +28,7 @@ (require 'notmuch-lib) (require 'notmuch-address) (require 'notmuch-draft) +(require 'notmuch-message) (eval-when-compile (require 'cl)) @@ -545,10 +546,20 @@ unencrypted. Really send? " (interactive "P") (when (and (notmuch-mua-check-no-misplaced-secure-tag) (notmuch-mua-check-secure-tag-has-newline)) -(letf (((symbol-function 'message-do-fcc) #'notmuch-maildir-message-do-fcc)) - (if exit - (message-send-and-exit arg) - (message-send arg) +(let (tag-change + post-send-tag-changes) + ;; post-send-tag-changes are tag-changes to apply after sending, + ;; but we need to store them now as the compose buffer is + ;; typically killed before message-send-and-exit returns. + (push (notmuch-message-mark-replied t) post-send-tag-changes) + (push (notmuch-dra
[PATCH v3] emacs: add compatibility functions for emacs 23
Some of the recent changes to the emacs code have used functions introduced in emacs 24. The functions used are read-char-choice and setq-local. This changeset adds a file notmuch-compat.el which contains compatibility functions so that it should work on emacs 23. Note, since these functions are taken almost unchanged from the emacs source they are copyright the Free Software Foundation, and the header in the file reflects that. --- Hi This is another version of this patch. The previous version is at id:1477736487-31319-1-git-send-email-markwalters1...@gmail.com The main change is to split out the compatibility functions into a separate file. I haven't moved the defadvice code mentioned in id:87mvh4rigu@tethera.net into this file as that confuses the copyright situation (I think that it is all Tomi's code) Best wishes Mark emacs/Makefile.local | 1 + emacs/notmuch-address.el | 4 +-- emacs/notmuch-company.el | 3 +- emacs/notmuch-compat.el | 73 emacs/notmuch-lib.el | 1 + emacs/notmuch-maildir-fcc.el | 4 +-- 6 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 emacs/notmuch-compat.el diff --git a/emacs/Makefile.local b/emacs/Makefile.local index 6896ff9..442a5e4 100644 --- a/emacs/Makefile.local +++ b/emacs/Makefile.local @@ -3,6 +3,7 @@ dir := emacs emacs_sources := \ $(dir)/notmuch-lib.el \ + $(dir)/notmuch-compat.el \ $(dir)/notmuch-parser.el \ $(dir)/notmuch.el \ $(dir)/notmuch-query.el \ diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el index 5b2beef..b3c56cf 100644 --- a/emacs/notmuch-address.el +++ b/emacs/notmuch-address.el @@ -147,11 +147,11 @@ toggles the setting in this buffer." (interactive) (if (local-variable-p 'notmuch-address-command) (kill-local-variable 'notmuch-address-command) -(setq-local notmuch-address-command 'internal)) +(notmuch-setq-local notmuch-address-command 'internal)) (if (boundp 'company-idle-delay) (if (local-variable-p 'company-idle-delay) (kill-local-variable 'company-idle-delay) - (setq-local company-idle-delay nil + (notmuch-setq-local company-idle-delay nil (defun notmuch-address-matching (substring) "Returns a list of completion candidates matching SUBSTRING. diff --git a/emacs/notmuch-company.el b/emacs/notmuch-company.el index b0f9782..ebe2c08 100644 --- a/emacs/notmuch-company.el +++ b/emacs/notmuch-company.el @@ -28,6 +28,7 @@ ;;; Code: (eval-when-compile (require 'cl)) +(require 'notmuch-lib) (defvar notmuch-company-last-prefix nil) (make-variable-buffer-local 'notmuch-company-last-prefix) @@ -53,7 +54,7 @@ ;; internal completion) can still be accessed via standard company ;; functions, e.g., company-complete. (unless (eq notmuch-address-command 'internal) -(setq-local company-idle-delay nil))) +(notmuch-setq-local company-idle-delay nil))) ;;;###autoload (defun notmuch-company (command &optional arg &rest _ignore) diff --git a/emacs/notmuch-compat.el b/emacs/notmuch-compat.el new file mode 100644 index 000..c3d827a --- /dev/null +++ b/emacs/notmuch-compat.el @@ -0,0 +1,73 @@ +;; Compatibility functions for emacs 23 and 24 pre 24.4 + +;; The functions in this file are copied from eamcs 24.4 and are +;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2014 Free Software +;; Foundation, Inc. + +(if (fboundp 'setq-local) +(defalias 'notmuch-setq-local 'setq-local) + (defmacro notmuch-setq-local (var val) +"Set variable VAR to value VAL in current buffer. + +Backport of setq-local for emacs without setq-local (pre 24.3)." +`(set (make-local-variable ',var) ,val))) + +(if (fboundp 'read-char-choice) +(defalias 'notmuch-read-char-choice 'read-char-choice) + (defun notmuch-read-char-choice (prompt chars &optional inhibit-keyboard-quit) + "Read and return one of CHARS, prompting for PROMPT. +Any input that is not one of CHARS is ignored. + +If optional argument INHIBIT-KEYBOARD-QUIT is non-nil, ignore +keyboard-quit events while waiting for a valid input. + +This is an exact copy of this function from emacs 24 for use on +emacs 23, except with the one emacs 24 only function it calls +inlined." + (unless (consp chars) +(error "Called `read-char-choice' without valid char choices")) + (let (char done show-help (helpbuf " *Char Help*")) +(let ((cursor-in-echo-area t) + (executing-kbd-macro executing-kbd-macro) + (esc-flag nil)) + (save-window-excursion ; in case we call help-form-show + (while (not done) + (unless (get-text-property 0 'face prompt) + (setq prompt (propertize prompt 'face 'minibuffer-prompt))) + (setq char (let ((inhibit-quit inhibit-keyboard-quit)) + (read-key prompt))) + (and show-help (buffer-live-p (get-buffer helpbuf)) + (kill-buffer helpbuf)) + (con
[PATCH] Test: fix draft test for emacs23
emacs24 and emacs23 have different secure tag defaults: in particular, mml-secure-message-sign only signs the part on emacs23 but the whole message on emacs24. This difference makes one of the draft tests fail (which causes a cascade of later failures) on emacs23. It seems that travis uses emacs23 so it is useful to fix this. We do this by forcing the whole message to be signed in either case -- the code snippet is extracted from mml-secure-message-sign on emacs24. --- The main thing to note with this is that the motivation for fixing is that travis seems to use emacs23. Best wishes Mark test/T630-emacs-draft.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/T630-emacs-draft.sh b/test/T630-emacs-draft.sh index 46fc356..cd9e33a 100755 --- a/test/T630-emacs-draft.sh +++ b/test/T630-emacs-draft.sh @@ -32,7 +32,9 @@ test_begin_subtest "Saving a signed draft adds header" test_emacs '(notmuch-mua-mail) (message-goto-subject) (insert "draft-test-0003") - (mml-secure-message-sign) +;; We would use (mml-secure-message-sign) but on emacs23 +;; that only signs the part, not the whole message. +(mml-secure-message mml-secure-method '\''sign) (notmuch-draft-save) (test-output)' header_count=$(notmuch show --format=raw subject:draft-test-0003 | grep -c ^X-Notmuch-Emacs-Secure) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v7 3/4] emacs: check drafts for encryption tags before saving
From: David Bremner In general the user may not want to save plaintext copies of messages that they are sending encrypted, so give them a chance to abort. --- emacs/notmuch-draft.el | 39 +++ test/T630-emacs-draft.sh | 13 + 2 files changed, 52 insertions(+) diff --git a/emacs/notmuch-draft.el b/emacs/notmuch-draft.el index b8a5e67..1fb049a 100644 --- a/emacs/notmuch-draft.el +++ b/emacs/notmuch-draft.el @@ -71,6 +71,21 @@ postponing and resuming a message." :type '(repeat string) :group 'notmuch-send) +(defcustom notmuch-draft-save-plaintext 'ask + "Should notmuch save/postpone in plaintext messages that seem + like they are intended to be sent encrypted +(i.e with an mml encryption tag in it)." + :type '(radio + (const :tag "Never" nil) + (const :tag "Ask every time" ask) + (const :tag "Always" t)) + :group 'notmuch-draft + :group 'notmuch-crypto) + +(defvar notmuch-draft-encryption-tag-regex + "<#\\(part encrypt\\|secure.*mode=.*encrypt>\\)" + "Regular expression matching mml tags indicating encryption of part or message") + (defvar notmuch-draft-id nil "Message-id of the most recent saved draft of this message") (make-variable-buffer-local 'notmuch-draft-id) @@ -103,6 +118,28 @@ Used when a new version is saved, or the message is sent." (goto-char (+ (match-beginning 0) 2)) (insert "!")) +(defun notmuch-draft--has-encryption-tag () + "Returns t if there is an mml secure tag." + (save-excursion +(message-goto-body) +(re-search-forward notmuch-draft-encryption-tag-regex nil 't))) + +(defun notmuch-draft--query-encryption () + "Checks if we should save a message that should be encrypted. + +`notmuch-draft-save-plaintext' controls the behaviour." + (case notmuch-draft-save-plaintext + ((ask) +(notmuch-draft--query-encryption) +(unless (yes-or-no-p "(Customize `notmuch-draft-save-plaintext' to avoid this warning) +This message contains mml tags that suggest it is intended to be encrypted. +Really save and index an unencrypted copy? ") + (error "Save aborted"))) + ((nil) +(error "Refusing to save draft with encryption tags (see `notmuch-draft-save-plaintext')")) + ((t) +(ignore + (defun notmuch-draft--make-message-id () ;; message-make-message-id gives the id inside a "<" ">" pair, ;; but notmuch doesn't want that form, so remove them. @@ -115,6 +152,8 @@ This saves the current message in the database with tags `notmuch-draft-tags` (in addition to any default tags applied to newly inserted messages)." (interactive) + (when (notmuch-draft--has-encryption-tag) +(notmuch-draft--query-encryption)) (let ((id (notmuch-draft--make-message-id))) (with-temporary-notmuch-message-buffer ;; We insert a Date header and a Message-ID header, the former diff --git a/test/T630-emacs-draft.sh b/test/T630-emacs-draft.sh index e39690c..689ccfb 100755 --- a/test/T630-emacs-draft.sh +++ b/test/T630-emacs-draft.sh @@ -39,4 +39,17 @@ header_count=$(notmuch show --format=raw subject:draft-test-0003 | grep -c ^X-No body_count=$(notmuch notmuch show --format=raw subject:draft-test-0003 | grep -c '^\<#secure') test_expect_equal "$header_count,$body_count" "1,0" +test_begin_subtest "Refusing to save an encrypted draft" +test_emacs '(notmuch-mua-mail) + (message-goto-subject) + (insert "draft-test-0004") + (mml-secure-message-sign-encrypt) + (let ((notmuch-draft-save-plaintext nil)) +(notmuch-draft-save)) + (test-output)' +count1=$(notmuch count tag:draft) +count2=$(notmuch count subject:draft-test-0004) + +test_expect_equal "$count1,$count2" "3,0" + test_done -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v7 4/4] emacs: resume messages
From: David Bremner Provide functionality to resume editing a message previously saved with notmuch-draft-save, including decoding the X-Notmuch-Emacs-Secure header. Resume gets the raw file from notmuch and using the emacs function mime-to-mml reconstructs the message (including attachments). 'e' is bound to resume a draft from show or tree mode. --- emacs/notmuch-draft.el | 62 emacs/notmuch-show.el| 8 +++ emacs/notmuch-tree.el| 10 test/T630-emacs-draft.sh | 15 4 files changed, 95 insertions(+) diff --git a/emacs/notmuch-draft.el b/emacs/notmuch-draft.el index 1fb049a..496e11f 100644 --- a/emacs/notmuch-draft.el +++ b/emacs/notmuch-draft.el @@ -25,6 +25,7 @@ (require 'notmuch-maildir-fcc) (require 'notmuch-tag) +(require 'notmuch-mua) (declare-function notmuch-show-get-message-id "notmuch-show" (&optional bare)) @@ -118,6 +119,27 @@ Used when a new version is saved, or the message is sent." (goto-char (+ (match-beginning 0) 2)) (insert "!")) +(defun notmuch-draft-unquote-some-mml () + "Unquote the mml tags in `notmuch-draft-quoted-tags`." + (save-excursion +(when notmuch-draft-quoted-tags + (let ((re (concat "<#!+/?\\(" + (mapconcat 'regexp-quote notmuch-draft-quoted-tags "\\|") + "\\)"))) + (message-goto-body) + (while (re-search-forward re nil t) + ;; Remove one ! from after the #. + (goto-char (+ (match-beginning 0) 2)) + (delete-char 1 +(let (secure-tag) + (save-restriction + (message-narrow-to-headers) + (setq secure-tag (message-fetch-field "X-Notmuch-Emacs-Secure" 't)) + (message-remove-header "X-Notmuch-Emacs-Secure")) + (message-goto-body) + (when secure-tag + (insert secure-tag "\n") + (defun notmuch-draft--has-encryption-tag () "Returns t if there is an mml secure tag." (save-excursion @@ -198,6 +220,46 @@ applied to newly inserted messages)." (notmuch-draft-save) (kill-buffer)) +(defun notmuch-draft-resume (id) + "Resume editing of message with id ID." + (let* ((tags (process-lines notmuch-command "search" "--output=tags" + "--exclude=false" id)) +(draft (equal tags (notmuch-update-tags tags notmuch-draft-tags +(when (or draft + (yes-or-no-p "Message does not appear to be a draft: really resume? ")) + (switch-to-buffer (get-buffer-create (concat "*notmuch-draft-" id "*"))) + (setq buffer-read-only nil) + (erase-buffer) + (let ((coding-system-for-read 'no-conversion)) + (call-process notmuch-command nil t nil "show" "--format=raw" id)) + (mime-to-mml) + (goto-char (point-min)) + (when (re-search-forward "^$" nil t) + (replace-match mail-header-separator t t)) + ;; Remove the Date and Message-ID headers (unless the user has + ;; explicitly customized emacs to tell us not to) as they will + ;; be replaced when the message is sent. + (save-restriction + (message-narrow-to-headers) + (when (member 'Message-ID message-deletable-headers) + (message-remove-header "Message-ID")) + (when (member 'Date message-deletable-headers) + (message-remove-header "Date")) + ;; The X-Notmuch-Emacs-Draft header is a more reliable + ;; indication of whether the message really is a draft. + (setq draft (> (message-remove-header "X-Notmuch-Emacs-Draft") 0))) + ;; If the message is not a draft we should not unquote any mml. + (when draft + (notmuch-draft-unquote-some-mml)) + (notmuch-message-mode) + (message-goto-body) + (set-buffer-modified-p nil) + ;; If the resumed message was a draft then set the draft + ;; message-id so that we can delete the current saved draft if the + ;; message is resaved or sent. + (setq notmuch-draft-id (when draft id) + + (add-hook 'message-send-hook 'notmuch-draft--mark-deleted) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index fcf7e6e..364004b 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -38,6 +38,7 @@ (require 'notmuch-mua) (require 'notmuch-crypto) (require 'notmuch-print) +(require 'notmuch-draft) (declare-function notmuch-call-notmuch-process "notmuch" (&rest args)) (declare-function notmuch-search-next-thread "notmuch" nil) @@ -50,6 +51,7 @@ (&optional query query-context target buffer-name open-target)) (declare-function notmuch-tree-get-message-properties "notmuch-tree" nil) (declare-function notmuch-read-query "notmuch" (prompt)) +(declare-function notmuch-draft-resume "notmuch-draft" (id)) (defcustom notmuch-message-headers '("Subject" "To" "Cc" "Date") "Headers that should be shown in a message, in this order. @@ -1445,6 +1447,7 @@ reset based on the original query." (define-key map "|" 'n
[PATCH v7 0/4] emacs postpone/resume patches
The previous version of this series is at id:1479036106-32453-1-git-send-email-markwalters1...@gmail.com The only change is for the error handling for resume. In show mode is is actually simpler than before -- notmuch-show-get-message-id will always return an id, so we don't need to check for non-nil there. Indeed, if this were not the case then the tag commands would all need to check too. However, in tree-mode the corresponding command can fail if point is after the end of the last message. Thus there we do check for non-nil (as do the tagging commands). The diff from v6 is below. Best wishes Mark David Bremner (2): emacs: check drafts for encryption tags before saving emacs: resume messages Mark Walters (2): emacs: tree: remove binding for pressing button in message pane emacs: postpone a message emacs/Makefile.local | 3 +- emacs/notmuch-draft.el | 268 +++ emacs/notmuch-mua.el | 4 + emacs/notmuch-show.el| 8 ++ emacs/notmuch-tree.el| 11 +- test/T630-emacs-draft.sh | 70 + 6 files changed, 362 insertions(+), 2 deletions(-) create mode 100644 emacs/notmuch-draft.el create mode 100755 test/T630-emacs-draft.sh diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 79e4435..364004b 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -1988,9 +1988,7 @@ to show, nil otherwise." (defun notmuch-show-resume-message () "Resume EDITING the current draft message." (interactive) - (let ((id (notmuch-show-get-message-id))) -(when id - (notmuch-draft-resume id + (notmuch-draft-resume (notmuch-show-get-message-id))) (put 'notmuch-show-pipe-message 'notmuch-doc "Pipe the contents of the current message to a command.") diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index 4abcf60..7bebdba 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -273,7 +273,6 @@ FUNC." (define-key map "r" (notmuch-tree-close-message-pane-and #'notmuch-show-reply-sender)) (define-key map "R" (notmuch-tree-close-message-pane-and #'notmuch-show-reply)) (define-key map "V" (notmuch-tree-close-message-pane-and #'notmuch-show-view-raw-message)) -(define-key map "e" (notmuch-tree-close-message-pane-and #'notmuch-show-resume-message)) ;; The main tree view bindings (define-key map (kbd "RET") 'notmuch-tree-show-message) @@ -294,6 +293,7 @@ FUNC." (define-key map "*" 'notmuch-tree-tag-thread) (define-key map " " 'notmuch-tree-scroll-or-next) (define-key map (kbd "DEL") 'notmuch-tree-scroll-message-window-back) +(define-key map "e" 'notmuch-tree-resume-message) map)) (fset 'notmuch-tree-mode-map notmuch-tree-mode-map) @@ -406,6 +406,15 @@ NOT change the database." (list (notmuch-read-tag-changes (notmuch-tree-get-tags) "Tag message" "-"))) (notmuch-tree-tag tag-changes)) +(defun notmuch-tree-resume-message () + "Resume EDITING the current draft message." + (interactive) + (notmuch-tree-close-message-window) + (let ((id (notmuch-tree-get-message-id))) +(if id + (notmuch-draft-resume id) + (message "No message to resume!" + ;; The next two functions close the message window before calling ;; notmuch-search or notmuch-tree but they do so after the user has ;; entered the query (in case the user was basing the query on ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v7 2/4] emacs: postpone a message
This provides initial support for postponing in the emacs frontend; resuming will follow in a later commit. On saving/postponing it uses notmuch insert to put the message in the notmuch database Current bindings are C-x C-s to save a draft, C-c C-p to postpone a draft (save and exit compose buffer). Previous drafts get tagged deleted on subsequent saves, or on the message being sent. Each draft gets its own message-id, and we use the namespace draft- for draft message ids (so, at least for most people, drafts are easily distinguisable). --- emacs/Makefile.local | 3 +- emacs/notmuch-draft.el | 167 +++ emacs/notmuch-mua.el | 4 ++ test/T630-emacs-draft.sh | 42 4 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 emacs/notmuch-draft.el create mode 100755 test/T630-emacs-draft.sh diff --git a/emacs/Makefile.local b/emacs/Makefile.local index 2d6aedb..6896ff9 100644 --- a/emacs/Makefile.local +++ b/emacs/Makefile.local @@ -20,7 +20,8 @@ emacs_sources := \ $(dir)/notmuch-print.el \ $(dir)/notmuch-version.el \ $(dir)/notmuch-jump.el \ - $(dir)/notmuch-company.el + $(dir)/notmuch-company.el \ + $(dir)/notmuch-draft.el $(dir)/notmuch-version.el: $(dir)/Makefile.local version.stamp $(dir)/notmuch-version.el: $(srcdir)/$(dir)/notmuch-version.el.tmpl diff --git a/emacs/notmuch-draft.el b/emacs/notmuch-draft.el new file mode 100644 index 000..b8a5e67 --- /dev/null +++ b/emacs/notmuch-draft.el @@ -0,0 +1,167 @@ +;;; notmuch-draft.el --- functions for postponing and editing drafts +;; +;; Copyright © Mark Walters +;; Copyright © David Bremner +;; +;; 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 <https://www.gnu.org/licenses/>. +;; +;; Authors: Mark Walters +;; David Bremner + +;;; Code: + +(require 'notmuch-maildir-fcc) +(require 'notmuch-tag) + +(declare-function notmuch-show-get-message-id "notmuch-show" (&optional bare)) + +(defgroup notmuch-draft nil + "Saving and editing drafts in Notmuch." + :group 'notmuch) + +(defcustom notmuch-draft-tags '("+draft") + "List of tags changes to apply to a draft message when it is saved in the database. + +Tags starting with \"+\" (or not starting with either \"+\" or +\"-\") in the list will be added, and tags starting with \"-\" +will be removed from the message being stored. + +For example, if you wanted to give the message a \"draft\" tag +but not the (normally added by default) \"inbox\" tag, you would +set: +(\"+draft\" \"-inbox\")" + :type '(repeat string) + :group 'notmuch-draft) + +(defcustom notmuch-draft-folder "drafts" + "Folder to save draft messages in. + +This should be specified relative to the root of the notmuch +database. It will be created if necessary." + :type 'string + :group 'notmuch-draft) + +(defcustom notmuch-draft-quoted-tags '() + "Mml tags to quote. + +This should be a list of mml tags to quote before saving. You do +not need to include \"secure\" as that is handled separately. + +If you include \"part\" then attachments will not be saved with +the draft -- if not then they will be saved with the draft. The +former means the attachments may not still exist when you resume +the message, the latter means that the attachments as they were +when you postponed will be sent with the resumed message. + +Note you may get strange results if you change this between +postponing and resuming a message." + :type '(repeat string) + :group 'notmuch-send) + +(defvar notmuch-draft-id nil + "Message-id of the most recent saved draft of this message") +(make-variable-buffer-local 'notmuch-draft-id) + +(defun notmuch-draft--mark-deleted () + "Tag the last saved draft deleted. + +Used when a new version is saved, or the message is sent." + (when notmuch-draft-id +(notmuch-tag notmuch-draft-id '("+deleted" + +(defun notmuch-draft-quote-some-mml () + "Quote the mml tags in `notmuch-draft-quoted-tags`." + (save-excursion +;; First we deal with any secure tag separately. +(message-goto-body) +(when (looking-a
[PATCH v7 1/4] emacs: tree: remove binding for pressing button in message pane
We want to use "e" for editting postponed messages in show, and in tree view, so remove the binding for the function which does (In message pane) Activate BUTTON or button at point --- emacs/notmuch-tree.el | 1 - 1 file changed, 1 deletion(-) diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index 62064ce..8398eb1 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -266,7 +266,6 @@ FUNC." (define-key map (kbd "M-TAB") (notmuch-tree-to-message-pane #'notmuch-show-previous-button)) (define-key map (kbd "") (notmuch-tree-to-message-pane #'notmuch-show-previous-button)) (define-key map (kbd "TAB") (notmuch-tree-to-message-pane #'notmuch-show-next-button)) -(define-key map "e" (notmuch-tree-to-message-pane #'notmuch-tree-button-activate)) (define-key map "$" (notmuch-tree-to-message-pane #'notmuch-show-toggle-process-crypto)) ;; bindings from show (or elsewhere) but we close the message pane first. -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v6 4/4] emacs: resume messages
From: David Bremner Provide functionality to resume editing a message previously saved with notmuch-draft-save, including decoding the X-Notmuch-Emacs-Secure header. Resume gets the raw file from notmuch and using the emacs function mime-to-mml reconstructs the message (including attachments). 'e' is bound to resume a draft from show or tree mode. --- emacs/notmuch-draft.el | 62 emacs/notmuch-show.el| 10 emacs/notmuch-tree.el| 1 + test/T630-emacs-draft.sh | 15 4 files changed, 88 insertions(+) diff --git a/emacs/notmuch-draft.el b/emacs/notmuch-draft.el index 1fb049a..496e11f 100644 --- a/emacs/notmuch-draft.el +++ b/emacs/notmuch-draft.el @@ -25,6 +25,7 @@ (require 'notmuch-maildir-fcc) (require 'notmuch-tag) +(require 'notmuch-mua) (declare-function notmuch-show-get-message-id "notmuch-show" (&optional bare)) @@ -118,6 +119,27 @@ Used when a new version is saved, or the message is sent." (goto-char (+ (match-beginning 0) 2)) (insert "!")) +(defun notmuch-draft-unquote-some-mml () + "Unquote the mml tags in `notmuch-draft-quoted-tags`." + (save-excursion +(when notmuch-draft-quoted-tags + (let ((re (concat "<#!+/?\\(" + (mapconcat 'regexp-quote notmuch-draft-quoted-tags "\\|") + "\\)"))) + (message-goto-body) + (while (re-search-forward re nil t) + ;; Remove one ! from after the #. + (goto-char (+ (match-beginning 0) 2)) + (delete-char 1 +(let (secure-tag) + (save-restriction + (message-narrow-to-headers) + (setq secure-tag (message-fetch-field "X-Notmuch-Emacs-Secure" 't)) + (message-remove-header "X-Notmuch-Emacs-Secure")) + (message-goto-body) + (when secure-tag + (insert secure-tag "\n") + (defun notmuch-draft--has-encryption-tag () "Returns t if there is an mml secure tag." (save-excursion @@ -198,6 +220,46 @@ applied to newly inserted messages)." (notmuch-draft-save) (kill-buffer)) +(defun notmuch-draft-resume (id) + "Resume editing of message with id ID." + (let* ((tags (process-lines notmuch-command "search" "--output=tags" + "--exclude=false" id)) +(draft (equal tags (notmuch-update-tags tags notmuch-draft-tags +(when (or draft + (yes-or-no-p "Message does not appear to be a draft: really resume? ")) + (switch-to-buffer (get-buffer-create (concat "*notmuch-draft-" id "*"))) + (setq buffer-read-only nil) + (erase-buffer) + (let ((coding-system-for-read 'no-conversion)) + (call-process notmuch-command nil t nil "show" "--format=raw" id)) + (mime-to-mml) + (goto-char (point-min)) + (when (re-search-forward "^$" nil t) + (replace-match mail-header-separator t t)) + ;; Remove the Date and Message-ID headers (unless the user has + ;; explicitly customized emacs to tell us not to) as they will + ;; be replaced when the message is sent. + (save-restriction + (message-narrow-to-headers) + (when (member 'Message-ID message-deletable-headers) + (message-remove-header "Message-ID")) + (when (member 'Date message-deletable-headers) + (message-remove-header "Date")) + ;; The X-Notmuch-Emacs-Draft header is a more reliable + ;; indication of whether the message really is a draft. + (setq draft (> (message-remove-header "X-Notmuch-Emacs-Draft") 0))) + ;; If the message is not a draft we should not unquote any mml. + (when draft + (notmuch-draft-unquote-some-mml)) + (notmuch-message-mode) + (message-goto-body) + (set-buffer-modified-p nil) + ;; If the resumed message was a draft then set the draft + ;; message-id so that we can delete the current saved draft if the + ;; message is resaved or sent. + (setq notmuch-draft-id (when draft id) + + (add-hook 'message-send-hook 'notmuch-draft--mark-deleted) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index fcf7e6e..79e4435 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -38,6 +38,7 @@ (require 'notmuch-mua) (require 'notmuch-crypto) (require 'notmuch-print) +(require 'notmuch-draft) (declare-function notmuch-call-notmuch-process "notmuch" (&rest args)) (declare-function notmuch-search-next-thread "notmuch" nil) @@ -50,6 +51,7 @@ (&optional query query-context target buffer-name open-target)) (declare-function notmuch-tree-get-message-properties "notmuch-tree" nil) (declare-function notmuch-read-query "notmuch" (prompt)) +(declare-function notmuch-draft-resume "notmuch-draft" (id)) (defcustom notmuch-message-headers '("Subject" "To" "Cc" "Date") "Headers that should be shown in a message, in this order. @@ -1445,6 +1447,7 @@ reset based on the original query." (define-key map "|" 'notmuch
[PATCH v6 0/4] emacs postpone/resume patches
This version 6 of this series. The previous version is at id:20161107125211.23405-1-da...@tethera.net This addresses the review comments on the previous version, adds a couple of "requires" to fix some compile warnings, and1 updates on function name which was missed previously. I also rejigged Patch 3 (the secure tag checks). I think I like this version but i am happy to revert to the previous one if preferred. The diff from the previous version is below. Best wishes Mark David Bremner (2): emacs: check drafts for encryption tags before saving emacs: resume messages Mark Walters (2): emacs: tree: remove binding for pressing button in message pane emacs: postpone a message emacs/Makefile.local | 3 +- emacs/notmuch-draft.el | 268 +++ emacs/notmuch-mua.el | 4 + emacs/notmuch-show.el| 10 ++ emacs/notmuch-tree.el| 2 +- test/T630-emacs-draft.sh | 70 + 6 files changed, 355 insertions(+), 2 deletions(-) create mode 100644 emacs/notmuch-draft.el create mode 100755 test/T630-emacs-draft.sh diff --git a/emacs/notmuch-draft.el b/emacs/notmuch-draft.el index 1528d79..496e11f 100644 --- a/emacs/notmuch-draft.el +++ b/emacs/notmuch-draft.el @@ -24,6 +24,8 @@ ;;; Code: (require 'notmuch-maildir-fcc) +(require 'notmuch-tag) +(require 'notmuch-mua) (declare-function notmuch-show-get-message-id "notmuch-show" (&optional bare)) @@ -109,7 +111,7 @@ Used when a new version is saved, or the message is sent." ;; specified tags. (when notmuch-draft-quoted-tags (let ((re (concat "<#!*/?\\(" - (mapconcat 'identity notmuch-draft-quoted-tags "\\|") + (mapconcat 'regexp-quote notmuch-draft-quoted-tags "\\|") "\\)"))) (message-goto-body) (while (re-search-forward re nil t) @@ -122,7 +124,7 @@ Used when a new version is saved, or the message is sent." (save-excursion (when notmuch-draft-quoted-tags (let ((re (concat "<#!+/?\\(" - (mapconcat 'identity notmuch-draft-quoted-tags "\\|") + (mapconcat 'regexp-quote notmuch-draft-quoted-tags "\\|") "\\)"))) (message-goto-body) (while (re-search-forward re nil t) @@ -138,21 +140,32 @@ Used when a new version is saved, or the message is sent." (when secure-tag (insert secure-tag "\n") -(defun notmuch-draft--check-encryption-tag (&optional ask) - "Query user if there an mml tag that looks like it might indicate encryption. - -Returns t if there is no such tag, or the user confirms they mean -it." +(defun notmuch-draft--has-encryption-tag () + "Returns t if there is an mml secure tag." (save-excursion (message-goto-body) - (or - ;; We are fine if no relevant tag is found, or - (not (re-search-forward notmuch-draft-encryption-tag-regex nil 't)) - ;; The user confirms they means it. - (and ask - (yes-or-no-p "(Customize `notmuch-draft-save-plaintext' to avoid this warning) +(re-search-forward notmuch-draft-encryption-tag-regex nil 't))) + +(defun notmuch-draft--query-encryption () + "Checks if we should save a message that should be encrypted. + +`notmuch-draft-save-plaintext' controls the behaviour." + (case notmuch-draft-save-plaintext + ((ask) +(notmuch-draft--query-encryption) +(unless (yes-or-no-p "(Customize `notmuch-draft-save-plaintext' to avoid this warning) This message contains mml tags that suggest it is intended to be encrypted. -Really save and index an unencrypted copy? ") +Really save and index an unencrypted copy? ") + (error "Save aborted"))) + ((nil) +(error "Refusing to save draft with encryption tags (see `notmuch-draft-save-plaintext')")) + ((t) +(ignore + +(defun notmuch-draft--make-message-id () + ;; message-make-message-id gives the id inside a "<" ">" pair, + ;; but notmuch doesn't want that form, so remove them. + (concat "draft-" (substring (message-make-message-id) 1 -1))) (defun notmuch-draft-save () "Save the current draft message in the notmuch database. @@ -161,19 +174,9 @@ This saves the current message in the database with tags `notmuch-draft-tags` (in addition to any default tags applied to newly inserted messages)." (interactive) - (case notmuch-draft-save-plaintext -((ask) - (unless (notmuch-draft--check-encryption-tag t) - (error "Save aborted"))) -((t) - (ignore)) -((nil) - (unless (notmuch-draft--check-encryption-tag
[PATCH v6 2/4] emacs: postpone a message
This provides initial support for postponing in the emacs frontend; resuming will follow in a later commit. On saving/postponing it uses notmuch insert to put the message in the notmuch database Current bindings are C-x C-s to save a draft, C-c C-p to postpone a draft (save and exit compose buffer). Previous drafts get tagged deleted on subsequent saves, or on the message being sent. Each draft gets its own message-id, and we use the namespace draft- for draft message ids (so, at least for most people, drafts are easily distinguisable). --- emacs/Makefile.local | 3 +- emacs/notmuch-draft.el | 167 +++ emacs/notmuch-mua.el | 4 ++ test/T630-emacs-draft.sh | 42 4 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 emacs/notmuch-draft.el create mode 100755 test/T630-emacs-draft.sh diff --git a/emacs/Makefile.local b/emacs/Makefile.local index 2d6aedb..6896ff9 100644 --- a/emacs/Makefile.local +++ b/emacs/Makefile.local @@ -20,7 +20,8 @@ emacs_sources := \ $(dir)/notmuch-print.el \ $(dir)/notmuch-version.el \ $(dir)/notmuch-jump.el \ - $(dir)/notmuch-company.el + $(dir)/notmuch-company.el \ + $(dir)/notmuch-draft.el $(dir)/notmuch-version.el: $(dir)/Makefile.local version.stamp $(dir)/notmuch-version.el: $(srcdir)/$(dir)/notmuch-version.el.tmpl diff --git a/emacs/notmuch-draft.el b/emacs/notmuch-draft.el new file mode 100644 index 000..b8a5e67 --- /dev/null +++ b/emacs/notmuch-draft.el @@ -0,0 +1,167 @@ +;;; notmuch-draft.el --- functions for postponing and editing drafts +;; +;; Copyright © Mark Walters +;; Copyright © David Bremner +;; +;; 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 <https://www.gnu.org/licenses/>. +;; +;; Authors: Mark Walters +;; David Bremner + +;;; Code: + +(require 'notmuch-maildir-fcc) +(require 'notmuch-tag) + +(declare-function notmuch-show-get-message-id "notmuch-show" (&optional bare)) + +(defgroup notmuch-draft nil + "Saving and editing drafts in Notmuch." + :group 'notmuch) + +(defcustom notmuch-draft-tags '("+draft") + "List of tags changes to apply to a draft message when it is saved in the database. + +Tags starting with \"+\" (or not starting with either \"+\" or +\"-\") in the list will be added, and tags starting with \"-\" +will be removed from the message being stored. + +For example, if you wanted to give the message a \"draft\" tag +but not the (normally added by default) \"inbox\" tag, you would +set: +(\"+draft\" \"-inbox\")" + :type '(repeat string) + :group 'notmuch-draft) + +(defcustom notmuch-draft-folder "drafts" + "Folder to save draft messages in. + +This should be specified relative to the root of the notmuch +database. It will be created if necessary." + :type 'string + :group 'notmuch-draft) + +(defcustom notmuch-draft-quoted-tags '() + "Mml tags to quote. + +This should be a list of mml tags to quote before saving. You do +not need to include \"secure\" as that is handled separately. + +If you include \"part\" then attachments will not be saved with +the draft -- if not then they will be saved with the draft. The +former means the attachments may not still exist when you resume +the message, the latter means that the attachments as they were +when you postponed will be sent with the resumed message. + +Note you may get strange results if you change this between +postponing and resuming a message." + :type '(repeat string) + :group 'notmuch-send) + +(defvar notmuch-draft-id nil + "Message-id of the most recent saved draft of this message") +(make-variable-buffer-local 'notmuch-draft-id) + +(defun notmuch-draft--mark-deleted () + "Tag the last saved draft deleted. + +Used when a new version is saved, or the message is sent." + (when notmuch-draft-id +(notmuch-tag notmuch-draft-id '("+deleted" + +(defun notmuch-draft-quote-some-mml () + "Quote the mml tags in `notmuch-draft-quoted-tags`." + (save-excursion +;; First we deal with any secure tag separately. +(message-goto-body) +(when (looking-a
[PATCH v6 3/4] emacs: check drafts for encryption tags before saving
From: David Bremner In general the user may not want to save plaintext copies of messages that they are sending encrypted, so give them a chance to abort. --- emacs/notmuch-draft.el | 39 +++ test/T630-emacs-draft.sh | 13 + 2 files changed, 52 insertions(+) diff --git a/emacs/notmuch-draft.el b/emacs/notmuch-draft.el index b8a5e67..1fb049a 100644 --- a/emacs/notmuch-draft.el +++ b/emacs/notmuch-draft.el @@ -71,6 +71,21 @@ postponing and resuming a message." :type '(repeat string) :group 'notmuch-send) +(defcustom notmuch-draft-save-plaintext 'ask + "Should notmuch save/postpone in plaintext messages that seem + like they are intended to be sent encrypted +(i.e with an mml encryption tag in it)." + :type '(radio + (const :tag "Never" nil) + (const :tag "Ask every time" ask) + (const :tag "Always" t)) + :group 'notmuch-draft + :group 'notmuch-crypto) + +(defvar notmuch-draft-encryption-tag-regex + "<#\\(part encrypt\\|secure.*mode=.*encrypt>\\)" + "Regular expression matching mml tags indicating encryption of part or message") + (defvar notmuch-draft-id nil "Message-id of the most recent saved draft of this message") (make-variable-buffer-local 'notmuch-draft-id) @@ -103,6 +118,28 @@ Used when a new version is saved, or the message is sent." (goto-char (+ (match-beginning 0) 2)) (insert "!")) +(defun notmuch-draft--has-encryption-tag () + "Returns t if there is an mml secure tag." + (save-excursion +(message-goto-body) +(re-search-forward notmuch-draft-encryption-tag-regex nil 't))) + +(defun notmuch-draft--query-encryption () + "Checks if we should save a message that should be encrypted. + +`notmuch-draft-save-plaintext' controls the behaviour." + (case notmuch-draft-save-plaintext + ((ask) +(notmuch-draft--query-encryption) +(unless (yes-or-no-p "(Customize `notmuch-draft-save-plaintext' to avoid this warning) +This message contains mml tags that suggest it is intended to be encrypted. +Really save and index an unencrypted copy? ") + (error "Save aborted"))) + ((nil) +(error "Refusing to save draft with encryption tags (see `notmuch-draft-save-plaintext')")) + ((t) +(ignore + (defun notmuch-draft--make-message-id () ;; message-make-message-id gives the id inside a "<" ">" pair, ;; but notmuch doesn't want that form, so remove them. @@ -115,6 +152,8 @@ This saves the current message in the database with tags `notmuch-draft-tags` (in addition to any default tags applied to newly inserted messages)." (interactive) + (when (notmuch-draft--has-encryption-tag) +(notmuch-draft--query-encryption)) (let ((id (notmuch-draft--make-message-id))) (with-temporary-notmuch-message-buffer ;; We insert a Date header and a Message-ID header, the former diff --git a/test/T630-emacs-draft.sh b/test/T630-emacs-draft.sh index e39690c..689ccfb 100755 --- a/test/T630-emacs-draft.sh +++ b/test/T630-emacs-draft.sh @@ -39,4 +39,17 @@ header_count=$(notmuch show --format=raw subject:draft-test-0003 | grep -c ^X-No body_count=$(notmuch notmuch show --format=raw subject:draft-test-0003 | grep -c '^\<#secure') test_expect_equal "$header_count,$body_count" "1,0" +test_begin_subtest "Refusing to save an encrypted draft" +test_emacs '(notmuch-mua-mail) + (message-goto-subject) + (insert "draft-test-0004") + (mml-secure-message-sign-encrypt) + (let ((notmuch-draft-save-plaintext nil)) +(notmuch-draft-save)) + (test-output)' +count1=$(notmuch count tag:draft) +count2=$(notmuch count subject:draft-test-0004) + +test_expect_equal "$count1,$count2" "3,0" + test_done -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v6 1/4] emacs: tree: remove binding for pressing button in message pane
We want to use "e" for editting postponed messages in show, and in tree view, so remove the binding for the function which does (In message pane) Activate BUTTON or button at point --- emacs/notmuch-tree.el | 1 - 1 file changed, 1 deletion(-) diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index 62064ce..8398eb1 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -266,7 +266,6 @@ FUNC." (define-key map (kbd "M-TAB") (notmuch-tree-to-message-pane #'notmuch-show-previous-button)) (define-key map (kbd "") (notmuch-tree-to-message-pane #'notmuch-show-previous-button)) (define-key map (kbd "TAB") (notmuch-tree-to-message-pane #'notmuch-show-next-button)) -(define-key map "e" (notmuch-tree-to-message-pane #'notmuch-tree-button-activate)) (define-key map "$" (notmuch-tree-to-message-pane #'notmuch-show-toggle-process-crypto)) ;; bindings from show (or elsewhere) but we close the message pane first. -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [Patch v5 4/4] emacs: resume messages
On Sat, 12 Nov 2016, David Bremner wrote: > David Bremner writes: > >> Provide functionality to resume editing a mesage previously saved with >> notmuch-draft-save, including decoding the X-Notmuch-Emacs-Secure >> header. > > s/mesage/message/ > >> +(defun notmuch-draft-unquote-some-mml () >> + "Unquote the mml tags in `notmuch-draft-quoted-tags`." >> + (save-excursion >> +(when notmuch-draft-quoted-tags >> + (let ((re (concat "<#!+/?\\(" >> +(mapconcat 'identity notmuch-draft-quoted-tags "\\|") >> + > Same issue here with regex quoting, I think. Yes I will change this. >> +(let (secure-tag) >> + (save-restriction >> +(message-narrow-to-headers) >> +(setq secure-tag (message-fetch-field "X-Notmuch-Emacs-Secure" 't)) >> +(message-remove-header "X-Notmuch-Emacs-Secure")) >> + (message-goto-body) >> + (when secure-tag >> +(insert secure-tag "\n") > > Can the setq inside the let be replaced with > > (let ((secure-tag (message-fetch-field "X-Notmuch-Emacs-Secure" 't))) > ... > > Perhaps by pushing the let inside the save-restriction? We need to insert the secure-tag in the body, so outside of the save-restriction. However, message-fetch-field requires the message to be narrowed to the headers. So I don't see an easy way to avoid the setq. > >> (require 'notmuch-mua) >> (require 'notmuch-crypto) >> (require 'notmuch-print) >> +(require 'notmuch-draft) > > This line I added. > >> +(defun notmuch-show-resume-message () >> + "Resume EDITING the current draft message." >> + (interactive) >> + (let ((id (notmuch-show-get-message-id))) >> +(when id >> + (notmuch-draft-resume id Do you mean if we are not on a message? I think this may not be needed: I think all I intended to check was that we are on a message, but that seems to always be true in the show buffer (unlike threads in the search buffer). Best wishes Mark > > The error handling is not very clear to me > here. notmuch-show-get-message-id is not documented to return nil on > error. Should some docstring be changed here? > >> +<#secure method=pgpmime mode=sign> >> +EOF >> +test_expect_equal_file EXPECTED OUTPUT.clean >> test_done > > The quoting of the secure tag here is not present in the original test, > but sure confused me for a few minutes. > ___ > notmuch mailing list > notmuch@notmuchmail.org > https://notmuchmail.org/mailman/listinfo/notmuch ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [Patch v5 2/4] emacs: postpone a message
On Sat, 12 Nov 2016, David Bremner wrote: > David Bremner writes: > >> From: Mark Walters > > This really Mark's work, that I have split out into a separate file. > >> +(defcustom notmuch-draft-tags '("+draft") >> + "List of tags changes to apply to a draft message when it is saved in the >> database. > > Here and a few other places the documentation uses "the database" to > mean the directory hierachy containing mail messages + the xapian > database. At some point I would like to be able to distinguish between > the database and the maildir root (which doesn't need to be maildirs) > when talking about configuration. I don't really know better terminology > here, but I thought I would mention it in case someone else is inspired. I think we could use "mailstore" for the maildir root, "database" makes sense for the xapian database. However, I don't have a good term for the combined whole -- so I am not sure what would make sense in this particular case. > >> +(defun notmuch-draft--mark-deleted () > > This -- naming convention is my contribution. Perhaps eventually we > could mark all private functions not intended to be called by users this > way. Since it is essentially cosmetic, I didn't want to do that > now. Indeed, one could quibble about the correctness of calling a > function private and then putting it in a public hook. I like it, and I agree. I do intend to remove it from the public hook later (see below). >> +(defun notmuch-draft-quote-some-mml () >> + "Quote the mml tags in `notmuch-draft-quoted-tags`." >> + (save-excursion >> +;; First we deal with any secure tag separately. >> +(message-goto-body) >> +(when (looking-at "<#secure[^\n]*>\n") >> + (let ((secure-tag (match-string 0))) >> +(delete-region (match-beginning 0) (match-end 0)) >> +(message-add-header (concat "X-Notmuch-Emacs-Secure: " secure-tag >> +;; This is copied from mml-quote-region but only quotes the >> +;; specified tags. >> +(when notmuch-draft-quoted-tags >> + (let ((re (concat "<#!*/?\\(" >> +(mapconcat 'identity notmuch-draft-quoted-tags "\\|") >> +"\\)"))) > One "hidden feature" is that regex characters in the quoted tags will be > interpreted. Possibly calling regexp-quote instead of identity would be > extra cautious here? Good catch: I have made it regexp-quote as you suggest. >> +(defun notmuch-draft-save () >> + "Save the current draft message in the notmuch database. >> + >> +This saves the current message in the database with tags >> +`notmuch-draft-tags` (in addition to any default tags >> +applied to newly inserted messages)." >> + (interactive) >> + (let (;; We need the message id as we need it for tagging. Note >> +;; message-make-message-id gives the id inside a "<" ">" pair, >> +;; but notmuch doesn't want that form, so remove them. >> +(id (concat "draft-" (substring (message-make-message-id) 1 >> -1 > > what do you think of isolating this code and commentary in a private > function? I have done this. >> + (if (member 'Message-ID message-deletable-headers) >> + (progn >> + (message-remove-header "Message-ID") >> + (message-add-header (concat "Message-ID: <" id ">"))) >> + (message "You have customized emacs so Message-ID is not a deletable >> header, so not changing it") >> + (setq id nil)) > > I'm not sure if it's just me, but I find the (if (progn ...) > else-clauses) a bit off-putting. An alternative would be to use cond > > (cond > ((member 'Message-ID message-deletable-headers) > (message-remove-header "Message-id") > (message-add-header (concat "Message-ID: <" id ">"))) > (t > (message "You have customized emacs so Message-ID is not a deletable > header, so not changing it") > (setq id nil))) I am happy either way, so I have made the change >> +(add-hook 'message-send-hook 'notmuch-draft--mark-deleted) > > Can we avoid this by adding some code notmuch-mua-send-common? Yes. We should do the same for notmuch-message-mark-replied. However getting it right looks slightly non-trivial. In particular, the user can abort sending for various reasons (eg charset things, or they have message-confirm-send set) and we should not do the marking if they do abort. However
Re: [PATCH] emacs: mua: add a pre-send-check-hook
> For consistency with Emacs' own elisp, perhaps rename > notmuch-mua-pre-send-check-hooks to > notmuch-mua-pre-send-check-functions? Hi Yes you are correct. (Annoyingly I had thought about this and thought it was OK since I didn't need to pass an argument. I had missed the return value case). Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v4] emacs: add notmuch-address-post-completion-hook
On Sat, 12 Nov 2016, David Bremner wrote: > Tomi Ollila writes: > >> Like someone (whose message I cannot find just now) mentioned in another >> thread, just now it is right time to mention here too... >> >> https://www.gnu.org/software/emacs/manual/html_node/elisp/Hooks.html >> >> ... that when hook name ends with `-hook` it is supposed to be "normal hook" >> -- a function which does not take arguments nor return values. >> >> So, I'd like to suggest that this variable is renamed to >> notmuch-address-completion-functions >> > > Well, I guess the -functions convention should be followed, but > notmuch-address-completion-functions seems a bit vague. Maybe notmuch-address-post-completion-functions ? Alternatively maybe we can end in -hook-functions to indicate it is a function which is like a hook? Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [Patch v5 3/4] emacs: check drafts for encryption tags before saving
On Mon, 07 Nov 2016, David Bremner wrote: > In general the user may not want to save plaintext copies of messages > that they are sending encrypted, so give them a chance to abort. > --- > emacs/notmuch-draft.el | 40 > test/T630-emacs-draft.sh | 13 + > 2 files changed, 53 insertions(+) > > diff --git a/emacs/notmuch-draft.el b/emacs/notmuch-draft.el > index 11d906b..5a230e8 100644 > --- a/emacs/notmuch-draft.el > +++ b/emacs/notmuch-draft.el > @@ -70,6 +70,21 @@ postponing and resuming a message." >:type '(repeat string) >:group 'notmuch-send) > > +(defcustom notmuch-draft-save-plaintext 'ask > + "Should notmuch save/postpone in plaintext messages that seem > + like they are intended to be sent encrypted > +(i.e with an mml encryption tag in it)." > + :type '(radio > + (const :tag "Never" nil) > + (const :tag "Ask every time" ask) > + (const :tag "Always" t)) > + :group 'notmuch-draft > + :group 'notmuch-crypto) > + > +(defvar notmuch-draft-encryption-tag-regex > + "<#\\(part encrypt\\|secure.*mode=.*encrypt>\\)" > + "Regular expression matching mml tags indicating encryption of part or > message") > + > (defvar notmuch-draft-id nil >"Message-id of the most recent saved draft of this message") > (make-variable-buffer-local 'notmuch-draft-id) > @@ -102,6 +117,22 @@ Used when a new version is saved, or the message is > sent." > (goto-char (+ (match-beginning 0) 2)) > (insert "!")) > > +(defun notmuch-draft--check-encryption-tag (&optional ask) > + "Query user if there an mml tag that looks like it might indicate > encryption. > + > +Returns t if there is no such tag, or the user confirms they mean > +it." > + (save-excursion > +(message-goto-body) > + (or > + ;; We are fine if no relevant tag is found, or > + (not (re-search-forward notmuch-draft-encryption-tag-regex nil 't)) > + ;; The user confirms they means it. > + (and ask > + (yes-or-no-p "(Customize `notmuch-draft-save-plaintext' to avoid > this warning) > +This message contains mml tags that suggest it is intended to be encrypted. > +Really save and index an unencrypted copy? ") > + > (defun notmuch-draft-save () >"Save the current draft message in the notmuch database. > > @@ -109,6 +140,15 @@ This saves the current message in the database with tags > `notmuch-draft-tags` (in addition to any default tags > applied to newly inserted messages)." >(interactive) > + (case notmuch-draft-save-plaintext > +((ask) > + (unless (notmuch-draft--check-encryption-tag t) > + (error "Save aborted"))) > +((t) > + (ignore)) > +((nil) > + (unless (notmuch-draft--check-encryption-tag nil) > + (error "Refusing to save draft with encryption tags (see > `notmuch-draft-save-plaintext')" What would you think of rejigging the logic here? I would prefer that the first check was "is there an encryption tag" and then if there is such a tag decide what to do. The reason I prefer that is that it makes the common case clear. I realise there are downsides too -- eg in your code you don't even check for secure tags if they are going to be ignored anyway. If you prefer your way then lets leave it as is. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [Patch v3 2/2] emacs: postpone/resume support
> +(defun notmuch-draft--check-encryption-tag () > + "Query user if there an mml tag that looks like it might indicate > encryption. > + > +Returns t if there is no such tag, or the user confirms they mean > +it." > + (save-excursion > +(message-goto-body) > + (or > + ;; We are fine if no relevant tag is found, or > + (not (re-search-forward notmuch-draft-encryption-tag-regex nil 't)) > + ;; The user confirms they means it. > + (yes-or-no-p "(Customize `notmuch-draft-save-plaintext' to avoid this > warning) > +This message contains mml tags that suggest it is intended to be encrypted. > +Really save and index an unencrypted copy? " > + > +(defun notmuch-draft-save () > + "Save the current draft message in the notmuch database. > + > +This saves the current message in the database with tags > +`notmuch-draft-draft-tags` (in addition to any default tags > +applied to newly inserted messages)." > + (interactive) > + (case notmuch-draft-save-plaintext > +((ask) > + (unless (notmuch-draft--check-encryption-tag) > + (error "Save aborted"))) > +((t) > + (ignore)) > +((nil) > + (error "Refusing to save draft with encryption tags (see > `notmuch-draft-save-plaintext')"))) Hi Did you mean for the case when notmuch-draft-save-plaintext is nil to abort in all cases, not just when there is an mml secure tag? (I haven't tested but it looks like that is what happens above) Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [Patch v3 2/2] emacs: postpone/resume support
On Sun, 06 Nov 2016, David Bremner wrote: > From: Mark Walters > > This provides preliminary support for postponing and resuming in the > emacs frontend. On postponing it uses notmuch insert to put the > message in the notmuch database; resume gets the raw file from notmuch > and using the emacs function mime-to-mml reconstructs the message > (including attachments). > > Current bindings are C-x C-s to save a draft, C-c C-p to postpone a > draft (save and exit compose buffer), and e to resume a draft from > show or tree mode. > > Previous drafts get tagged deleted on subsequent saves, or on the > message being sent. > > Each draft gets its own message-id, and we use the namespace > draft- for draft message ids (so, at least for most people, drafts > are easily distinguisable). Hi Many thanks for doing this; I definitely like the move to a notmuch-draft file. I haven't checked it completely yet, or tested it, but I think the move itself looks fine except for two documentation bits which aren't quite right -- see below. Best wishes Mark > --- > emacs/notmuch-draft.el | 261 > + > emacs/notmuch-mua.el | 4 + > emacs/notmuch-show.el | 10 ++ > emacs/notmuch-tree.el | 1 + > 4 files changed, 276 insertions(+) > create mode 100644 emacs/notmuch-draft.el > > diff --git a/emacs/notmuch-draft.el b/emacs/notmuch-draft.el > new file mode 100644 > index 000..806c1a7 > --- /dev/null > +++ b/emacs/notmuch-draft.el > @@ -0,0 +1,261 @@ > +;;; notmuch-draft.el --- functions for postponing and editing drafts > +;; > +;; Copyright © Mark Walters > +;; Copyright © David Bremner > +;; > +;; 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 <https://www.gnu.org/licenses/>. > +;; > +;; Authors: Mark Walters > +;; David Bremner > + > +;;; Code: > + > +(require 'notmuch-maildir-fcc) > + > +(declare-function notmuch-show-get-message-id "notmuch-show" (&optional > bare)) > + > +(defgroup notmuch-draft nil > + "Saving and editing drafts in Notmuch." > + :group 'notmuch) > + > +(defcustom notmuch-draft-tags '("+draft") > + "List of tags changes to apply to a draft message when it is saved in the > database. > + > +Tags starting with \"+\" (or not starting with either \"+\" or > +\"-\") in the list will be added, and tags starting with \"-\" > +will be removed from the message being stored. > + > +For example, if you wanted to give the message a \"draft\" tag > +but not the (normally added by default) \"inbox\" tag, you would > +set: > +(\"+draft\" \"-inbox\")" > + :type '(repeat string) > + :group 'notmuch-draft) > + > +(defcustom notmuch-draft-folder "drafts" > + "Folder to save draft messages in. > + > +This should be specified relative to the root of the notmuch > +database. It will be created if necessary." > + :type 'string > + :group 'notmuch-draft) > + > +(defcustom notmuch-draft-quoted-tags '() > + "Mml tags to quote. > + > +This should be a list of mml tags to quote before saving. You do > +not need to include \"secure\" as that is handled separately. > + > +If you include \"part\" then attachments will not be saved with > +the draft -- if not then they will be saved with the draft. The > +former means the attachments may not still exist when you resume > +the message, the latter means that the attachments as they were > +when you postponed will be sent with the resumed message. > + > +Note you may get strange results if you change this between > +postponing and resuming a message." > + :type '(repeat string) > + :group 'notmuch-send) > + > +(defcustom notmuch-draft-save-plaintext 'ask > + "Should notmuch save/postpone in plaintext messages that seem > + like they are intended to be sent encrypted > +(i.e with an mml encryption tag i
Re: [PATCH] emacs: add check for encryption before saving.
On Sat, 05 Nov 2016, David Bremner wrote: > Mark Walters writes: > >> >> I think this is an excellent thing to add. I agree that false positives >> aren't much of a worry. If someone bumps into them a lot then they can >> complain or come up with a better regex. >> > > Should the regex also be a defcustom? I think not a defcustom, but perhaps a defvar (the difference being that defvar's are hidden from most users -- anyone who can write a better regex can use setq in their init file). I think even if we don't expect users to change it making it a defvar is quite clean so that might be best. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH] emacs: add check for encryption before saving.
On Sat, 05 Nov 2016, David Bremner wrote: > This is intended to decrease the chance of people ending up with a bunch > of plaintext drafts of encrypted messages without knowing it. > > The check is intentionally overcautious; I think the false positive of > misplaced #secure tag is probably OK here. > --- > > This is somewhat RFC. The regex needs to be double checked, and the > variable name is not ideal. However it does solve reduce a worry I > have about this code saving drafts of sensitive messages in plaintext > that are effectively invisible because they are tagged deleted. Hi I think this is an excellent thing to add. I agree that false positives aren't much of a worry. If someone bumps into them a lot then they can complain or come up with a better regex. > emacs/notmuch-message.el | 25 + > 1 file changed, 25 insertions(+) > > diff --git a/emacs/notmuch-message.el b/emacs/notmuch-message.el > index a503296..a2b079d 100644 > --- a/emacs/notmuch-message.el > +++ b/emacs/notmuch-message.el > @@ -80,6 +80,12 @@ postponing and resuming a message." >:type '(repeat string) >:group 'notmuch-send) > > +(defcustom notmuch-message-warn-encryption t > + "Warn if the user postpones or saves a message with an mml encryption tag > in it" > + :type 'boolean > + :group 'notmuch-send > + :group 'notmuch-crypto) I think it would be good if the variable name contained postpone or save in it as it is not part of the normal send message route. Perhaps notmuch-message-warn-unencrypted-save ? (not perfect I know) Maybe change the docstring to something like "Warn if the user postpones or saves a message that would be encrypted if sent (i.e., has an mml encryption tag)." > +(defun notmuch-message-check-encryption () > + "Query user if there an mml tag that looks like it might indicate > encryption. Maybe a name like notmuch-message-check-has-encrypt-tag (or omit "check")? But this is probably excessive bikeshedding on my part. In any case the only one I care about above is the name of the defcustom variable (and there is one trivial typo below) Best wishes Mark > +Returns t if there is no such tag, or the user confirms they mean > +it." > + (save-excursion > +(message-goto-body) > + (or > + ;; We fine if there is no secure tag, and no #part encryption ^^^ are > + (not (re-search-forward "<#\\(part > encrypt\\|secure.*mode=.*encrypt>\\)" nil 't)) > + ;; The user confirms they means it. > + (yes-or-no-p "\ > +This message contains mml tags that suggest it is intended to be encrypted. > +Really save and index an unencrypted copy? > +(Customize `notmuch-message-warn-encrypted' to avoid this warning)" > + > (defun notmuch-message-save-draft () >"Save the current draft message in the notmuch database. > > @@ -147,6 +169,9 @@ This saves the current message in the database with tags > `notmuch-message-draft-tags` (in addition to any default tags > applied to newly inserted messages)." >(interactive) > + (when (and notmuch-message-warn-encryption > + (not (notmuch-message-check-encryption)) > + (error "Save aborted"))) >(let (;; We need the message id as we need it for tagging. Note > ;; message-make-message-id gives the id inside a "<" ">" pair, > ;; but notmuch doesn't want that form, so remove them. > -- > 2.10.1 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] emacs: mua: add a pre-send-check-hook
This add a pre-send hook for any checks the user wants to run before sending the message. If any function in the hook returns nil then the send will abort. One use would be to check that the from address is appropriate for the recipients (i.e., test From: based on To: and Cc:), but many other uses are possible: checking spelling, checking that the message is set to be encrypted etc. --- bremner and I were discussing the address-completion-hook on irc, and before he implemented that I suggested an alternative of adding a pre-send-check-hook. The idea is that functions in this hook can force abort sending (or at least get confirmation from the user) based on the message. For example I would be quite likely to use something like the following in the hook. (lambda () (save-excursion (save-restriction (let ((to (message-fetch-field "To")) (from (message-fetch-field "From")) (case-fold-search t)) (or (not (string-match "work-domain-address" to)) (string= from "my-work-address") (yes-or-no-p "Message to work but not from work address. Really send? ")) I think this is reasonably orthogonal to the notmuch-address-completion-hook. Setting the from address based on the to addresses makes a lot of sense, but checking on send also does -- if the from is correct then the check is silent, and if the user types in the To: without using completion then the check will catch it. Best wishes Mark emacs/notmuch-mua.el | 12 +++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index f333655..78130e6 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -36,6 +36,15 @@ ;; +(defcustom notmuch-mua-pre-send-check-hook nil + "Hook of checks run before sending messages. + +If any of the functions in the hook return nil then the send will +be aborted." + :type 'hook + :group 'notmuch-send + :group 'notmuch-hooks) + (defcustom notmuch-mua-send-hook '(notmuch-mua-message-send-hook) "Hook run before sending messages." :type 'hook @@ -538,7 +547,8 @@ unencrypted. Really send? " (defun notmuch-mua-send-common (arg &optional exit) (interactive "P") - (when (and (notmuch-mua-check-no-misplaced-secure-tag) + (when (and (run-hook-with-args-until-failure 'notmuch-mua-pre-send-check-hook) +(notmuch-mua-check-no-misplaced-secure-tag) (notmuch-mua-check-secure-tag-has-newline)) (letf (((symbol-function 'message-do-fcc) #'notmuch-maildir-message-do-fcc)) (if exit -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v4] emacs: add notmuch-address-post-completion-hook
This version looks good to me +1 Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 0/2] add postpone support
This is version 2 of this set. The previous version is at id:1473004582-19396-1-git-send-email-markwalters1...@gmail.com The diff between v1 and v2 is below. The main change is that we store the secure tag in a temporary header and restore it afterwards. This avoids a bug in the way emacs deals with secure tags not at the top of the message. Other comments: I haven't tested this version heavily: I have been running something similar in my tree but I just don't postpone enough messages to test it thoroughly. It unbinds rather than rebinds the press button in message pane option in tree-view (currently bound to "e"). I have some thoughts on how to deal better with attachment handling in tree-view but that can follow later. It uses message-send-hook -- we really shouldn't do that, but as we already do for tagging replies "replied" it is probably OK to do so for now. (Fixing this properly is a little tricky -- avoiding the use of message-send-hook is easy but we currently mark a message replied even if the user aborts sending the message.) Best wishes Mark Mark Walters (2): emacs: tree: move binding for pressing button in message pane to u emacs: postpone/resume support emacs/notmuch-message.el | 187 +++ emacs/notmuch-mua.el | 4 + emacs/notmuch-show.el| 9 +++ emacs/notmuch-tree.el| 2 +- 4 files changed, 201 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch-message.el b/emacs/notmuch-message.el index b8d6d07..a503296 100644 --- a/emacs/notmuch-message.el +++ b/emacs/notmuch-message.el @@ -63,11 +63,11 @@ database. It will be created if necessary." :type 'string :group 'notmuch-send) -(defcustom notmuch-message-quoted-tags '("secure") +(defcustom notmuch-message-quoted-tags '() "Mml tags to quote. -This should be a list of mml tags to quote before saving. It is -recommended that the list includes \"secure\". +This should be a list of mml tags to quote before saving. You do +not need to include \"secure\" as that is handled separately. If you include \"part\" then attachments will not be saved with the draft -- if not then they will be saved with the draft. The @@ -100,10 +100,16 @@ Used when a new version is saved, or the message is sent." (defun notmuch-message-quote-some-mml () "Quote the mml tags in `notmuch-message-quoted-tags`." + (save-excursion +;; First we deal with any secure tag separately. +(message-goto-body) +(when (looking-at "<#secure[^\n]*>\n") + (let ((secure-tag (match-string 0))) + (delete-region (match-beginning 0) (match-end 0)) + (message-add-header (concat "X-Notmuch-Emacs-Secure: " secure-tag ;; This is copied from mml-quote-region but only quotes the ;; specified tags. (when notmuch-message-quoted-tags -(save-excursion (let ((re (concat "<#!*/?\\(" (mapconcat 'identity notmuch-message-quoted-tags "\\|") "\\)"))) @@ -115,8 +121,8 @@ Used when a new version is saved, or the message is sent." (defun notmuch-message-unquote-some-mml () "Unquote the mml tags in `notmuch-message-quoted-tags`." - (when notmuch-message-quoted-tags (save-excursion +(when notmuch-message-quoted-tags (let ((re (concat "<#!+/?\\(" (mapconcat 'identity notmuch-message-quoted-tags "\\|") "\\)"))) @@ -124,7 +130,15 @@ Used when a new version is saved, or the message is sent." (while (re-search-forward re nil t) ;; Remove one ! from after the #. (goto-char (+ (match-beginning 0) 2)) - (delete-char 1)) + (delete-char 1 +(let (secure-tag) + (save-restriction + (message-narrow-to-headers) + (setq secure-tag (message-fetch-field "X-Notmuch-Emacs-Secure" 't)) + (message-remove-header "X-Notmuch-Emacs-Secure")) + (message-goto-body) + (when secure-tag + (insert secure-tag "\n") (defun notmuch-message-save-draft () "Save the current draft message in the notmuch database. @@ -157,6 +171,7 @@ applied to newly inserted messages)." (message-remove-header "Date") (message-add-header (concat "Date: " (message-make-date (message "You have customized emacs so Date is not a deletable header, so not changing it")) + (message-add-header "X-Notmuch-Emacs-Draft: True") (notmuch-message-quote-some-mml) (notmuch-maildir-setup-message-for-saving) (notmuch-maildir-notmuch-insert-current-buffer @@ -201,10 +216,11 @@ applied to newly inserted messages)." (when
[PATCH v2 2/2] emacs: postpone/resume support
This provides preliminary support for postponing and resuming in the emacs frontend. On postponing it uses notmuch insert to put the message in the notmuch database; resume gets the raw file from notmuch and using the emacs function mime-to-mml reconstructs the message (including attachments). Current bindings are C-x C-s to save a draft, C-c C-p to postpone a draft (save and exit compose buffer), and e to resume a draft from show or tree mode. Previous drafts get tagged deleted on subsequent saves, or on the message being sent. Each draft gets its own message-id, and we use the namespace draft- for draft message ids (so, at least for most people, drafts are easily distinguisable). --- emacs/notmuch-message.el | 187 +++ emacs/notmuch-mua.el | 4 + emacs/notmuch-show.el| 9 +++ emacs/notmuch-tree.el| 1 + 4 files changed, 201 insertions(+) diff --git a/emacs/notmuch-message.el b/emacs/notmuch-message.el index 55e4cfe..a503296 100644 --- a/emacs/notmuch-message.el +++ b/emacs/notmuch-message.el @@ -24,6 +24,9 @@ (require 'message) (require 'notmuch-tag) (require 'notmuch-mua) +(require 'notmuch-maildir-fcc) + +(declare-function notmuch-show-get-message-id "notmuch-show" (&optional bare)) (defcustom notmuch-message-replied-tags '("+replied") "List of tag changes to apply to a message when it has been replied to. @@ -38,6 +41,49 @@ the \"inbox\" and \"todo\" tags, you would set: :type '(repeat string) :group 'notmuch-send) +(defcustom notmuch-message-draft-tags '("+draft") + "List of tags changes to apply to a draft message when it is saved in the database. + +Tags starting with \"+\" (or not starting with either \"+\" or +\"-\") in the list will be added, and tags starting with \"-\" +will be removed from the message being stored. + +For example, if you wanted to give the message a \"draft\" tag +but not the (normally added by default) \"inbox\" tag, you would +set: +(\"+draft\" \"-inbox\")" + :type '(repeat string) + :group 'notmuch-send) + +(defcustom notmuch-message-draft-folder "drafts" + "Folder to save draft messages in. + +This should be specified relative to the root of the notmuch +database. It will be created if necessary." + :type 'string + :group 'notmuch-send) + +(defcustom notmuch-message-quoted-tags '() + "Mml tags to quote. + +This should be a list of mml tags to quote before saving. You do +not need to include \"secure\" as that is handled separately. + +If you include \"part\" then attachments will not be saved with +the draft -- if not then they will be saved with the draft. The +former means the attachments may not still exist when you resume +the message, the latter means that the attachments as they were +when you postponed will be sent with the resumed message. + +Note you may get strange results if you change this between +postponing and resuming a message." + :type '(repeat string) + :group 'notmuch-send) + +(defvar notmuch-message-draft-id nil + "Message-id of the most recent saved draft of this message") +(make-variable-buffer-local 'notmuch-message-draft-id) + (defun notmuch-message-mark-replied () ;; get the in-reply-to header and parse it for the message id. (let ((rep (mail-header-parse-addresses (message-field-value "In-Reply-To" @@ -45,7 +91,148 @@ the \"inbox\" and \"todo\" tags, you would set: (notmuch-tag (notmuch-id-to-query (car (car rep))) (notmuch-tag-change-list notmuch-message-replied-tags) +(defun notmuch-message-mark-draft-deleted () + "Tag the last saved draft deleted. + +Used when a new version is saved, or the message is sent." + (when notmuch-message-draft-id +(notmuch-tag notmuch-message-draft-id '("+deleted" + +(defun notmuch-message-quote-some-mml () + "Quote the mml tags in `notmuch-message-quoted-tags`." + (save-excursion +;; First we deal with any secure tag separately. +(message-goto-body) +(when (looking-at "<#secure[^\n]*>\n") + (let ((secure-tag (match-string 0))) + (delete-region (match-beginning 0) (match-end 0)) + (message-add-header (concat "X-Notmuch-Emacs-Secure: " secure-tag +;; This is copied from mml-quote-region but only quotes the +;; specified tags. +(when notmuch-message-quoted-tags + (let ((re (concat "<#!*/?\\(" + (mapconcat 'identity notmuch-message-quoted-tags "\\|") + "\\)"))) + (message-goto-body) + (while (re-search-forward re nil t) + ;; Insert ! after the #. + (goto-char (+ (match-beginning 0) 2)) + (insert "!")) + +(defun notmuch-message-unquote-some-mml () + "Unquote the mml tags in `notmuch-message-quoted-tags`." + (save-excursion +(when notmuch-message-quoted-tags + (let ((re (concat "<#!+/?\\(" + (mapconcat 'identity notmuch-message-quoted-tags "\\|") + "\\)"))) + (message-goto-bod
[PATCH v2 1/2] emacs: tree: remove binding for pressing button in message pane
We want to use "e" for editting postponed messages in show, and in tree view, so remove the binding for the function which does (In message pane) Activate BUTTON or button at point --- emacs/notmuch-tree.el | 1 - 1 file changed, 1 deletion(-) diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el index 1ab0810..b719b1e 100644 --- a/emacs/notmuch-tree.el +++ b/emacs/notmuch-tree.el @@ -257,7 +257,6 @@ FUNC." (define-key map (kbd "M-TAB") (notmuch-tree-to-message-pane #'notmuch-show-previous-button)) (define-key map (kbd "") (notmuch-tree-to-message-pane #'notmuch-show-previous-button)) (define-key map (kbd "TAB") (notmuch-tree-to-message-pane #'notmuch-show-next-button)) -(define-key map "e" (notmuch-tree-to-message-pane #'notmuch-tree-button-activate)) ;; bindings from show (or elsewhere) but we close the message pane first. (define-key map "f" (notmuch-tree-close-message-pane-and #'notmuch-show-forward-message)) -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v3] emacs: add notmuch-address-post-completion-hook
On Thu, 03 Nov 2016, David Bremner wrote: > This hook can be used to update the message based on the results of > address completion. For example using message-templ or gnus-alias to set > the From address based on the To address just completed. > > The post-completion command is added to the notmuch-company backend to > ensure that the hook is also called company completion is started > without going through notmuch-address-expand-name. See the docstring of > `company-backends' for more information. > --- > > Sorry for the false send. My fingers somehow mix up Debian's > "reportbug" and git-send-email. > > Here is a simplified version. As far as I could tell during testing > with company-mode the hook is only called via the post-completion > command, and always with a single argument. This might indicate a > separate bug, since I noticed in one fairly long running emacs session > (11 days), notmuch-address-history is nil. > > I guess the docstring for notmuch-address-completion-hook should have > a '.' at the end, or probably ' function.' > > > emacs/notmuch-address.el | 7 +++ > emacs/notmuch-company.el | 1 + > 2 files changed, 8 insertions(+) > > diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el > index b2e1fba..d1abb21 100644 > --- a/emacs/notmuch-address.el > +++ b/emacs/notmuch-address.el > @@ -98,6 +98,12 @@ to know how address selection is made by default." >:group 'notmuch-send >:group 'notmuch-external) > > +(defcustom notmuch-address-completion-hook nil > + "Functions called after completing address. The completed address is > passed as an argument to each" > + :type 'hook > + :group 'notmuch-address > + :group 'notmuch-hooks) > + > (defun notmuch-address-selection-function (prompt collection initial-input) >"Call (`completing-read' >PROMPT COLLECTION nil nil INITIAL-INPUT 'notmuch-address-history)" > @@ -205,6 +211,7 @@ external commands." >(if chosen > (progn > (push chosen notmuch-address-history) > + (run-hook-with-args 'notmuch-address-completion-hook chosen) > (delete-region beg end) > (insert chosen)) Hi Would it be worth putting the run-hook after the (insert chosen) rather than before? That would mean that the hook had access to the full new header. It would also mean that it wouldn't matter if the hook changed the buffer -- as it is I think the replace might go wrong as we replace beg to end and those seem to be integer-points not markers One final query -- this function will be called when completing any of To: Cc: Bcc: From: and some other less common headers. We could pass an argument which says which header we are on but that is probably more complexity than necessary. However, it is probably worth documenting that it may be called from these headers in the defcustom for the hook. But otherwise it looks good to me. Best wishes Mark > (message "No matches.") > diff --git a/emacs/notmuch-company.el b/emacs/notmuch-company.el > index 168315f..91c4804 100644 > --- a/emacs/notmuch-company.el > +++ b/emacs/notmuch-company.el > @@ -86,6 +86,7 @@ >(match (if (string-match notmuch-company-last-prefix arg) >(match-end 0) > 0)) > + (post-completion (run-hook-with-args 'notmuch-address-completion-hook > arg)) >(no-cache t > > > -- > 2.10.1 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH] emacs: add notmuch-address-post-completion-hook
On Thu, 03 Nov 2016, David Bremner wrote: > This hook can be used to update the message based on the results of > address completion. For example I use it to set the From address based > on the To address just completed. > > The post-completion command is added to the notmuch-company backend to > ensure that the hook is also called company completion is started > without going through notmuch-address-expand-name. See the docstring of > `company-backends' for more information. > --- > emacs/notmuch-address.el | 10 ++ > emacs/notmuch-company.el | 1 + > 2 files changed, 11 insertions(+) > > diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el > index b2e1fba..17960bf 100644 > --- a/emacs/notmuch-address.el > +++ b/emacs/notmuch-address.el > @@ -98,6 +98,12 @@ to know how address selection is made by default." >:group 'notmuch-send >:group 'notmuch-external) > > +(defcustom notmuch-address-completion-hook nil > + "Functions called after completing address. The completed address is > passed as an argument to each" Hi when testing this with company I think the following happens: if you trigger it manually with tab then I think the hook gets passed a list of possible addresses, not just one. > + :type 'hook > + :group 'notmuch-address > + :group 'notmuch-hooks) > + > (defun notmuch-address-selection-function (prompt collection initial-input) >"Call (`completing-read' >PROMPT COLLECTION nil nil INITIAL-INPUT 'notmuch-address-history)" > @@ -170,6 +176,10 @@ external commands." > (process-lines notmuch-address-command original > > (defun notmuch-address-expand-name () > + (let ((return-value (notmuch-address-real-expand-name))) > +(run-hook-with-args 'notmuch-address-completion-hook))) I think you need to return return-value here? But you also need to modify notmuch-address-real-expand-name to return chosen. Around line 217 of notmuch-address.el (if chosen (progn (push chosen notmuch-address-history) (delete-region beg end) (insert chosen)) should become (if chosen (progn (push chosen notmuch-address-history) (delete-region beg end) (insert chosen) ;; Return completed address chosen) I guess an alternative would to just run the hook there, and then you wouldn't need to the notmuch-address-real-expand-name function at all. (Sorry for misleading you about this on irc yesterday.) > + > +(defun notmuch-address-real-expand-name () >(cond > ((and (eq notmuch-address-command 'internal) >notmuch-address-use-company > diff --git a/emacs/notmuch-company.el b/emacs/notmuch-company.el > index 168315f..91c4804 100644 > --- a/emacs/notmuch-company.el > +++ b/emacs/notmuch-company.el > @@ -86,6 +86,7 @@ >(match (if (string-match notmuch-company-last-prefix arg) >(match-end 0) > 0)) > + (post-completion (run-hook-with-args 'notmuch-address-completion-hook > arg)) >(no-cache t To fix the list of addresses case you might be able to just put a (unless (listp arg) or something round the run-hook-with-args Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: rfc for notmuch remote access script
On Sun, 30 Oct 2016, David Bremner wrote: > Jani Nikula writes: > >> >> Personally, I prefer a simple script that assumes a certain type of ssh >> client configuration. We can typically reference documentation written >> by others how to do that, and just say "put that stuff under a Host >> notmuch section in ~/.ssh/config". Hi The only possible downside I can see with this is if the address for the notmuch-server varies. For example my router does NAT the address from inside and outside my home network is different. I don't know if that is a common setup, and quite plausibly I could configure things better. I only mention it as it might be easier to change an environment variable, than change the .ssh/config file. Quite plausibly though the simpler common case outweighs that. If we did want to support my use case above, maybe we could have an environment variable to say which .ssh/config section to use, which most people could completely ignore? > OK, I misunderstood, and thought you wanted to edit the script after > installation. Hence my question about installing into $HOME. > > I'm not using remote access, and I don't really have opinions about the > best way to do it. I do have 2 concerns about the overall idea > > 1. I worry about the maintenance burden of extra code ./configure > 2. I worry about promoting remote-notmuch for non-experts when the >situation with gpg seems quite broken, at least for people not >willing to store private key material on the server. I wonder if we could do the following -- 1) have 2 separate config targets for notmuch-cli and notmuch-emacs so you can install one without the other. 2) Have things under contrib which config/make can install. Then this script could go in contrib, which would be a clear signal that it is not fully supported. Moreover, point 2 would go very nicely with Jani's other patch id:1477140605-3011-1-git-send-email-j...@nikula.org for notmuch prefixed commands. It would mean we could have various notmuch extensions in contrib and the user could install any they wanted. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2] emacs: add compatability functions for emacs 23
Some of the recent changes to the emacs code have used functions introduced in emacs 24. The functions used are read-char-choice and setq-local. This changeset adds compatability functions to notmuch-lib so that it should work on emacs 23. --- Version 1 of this patch (with some discussion) is at id:1477191835-17828-1-git-send-email-markwalters1...@gmail.com The general consensus is that we should not define functions outside our namespace, even when they are just backports of functions from later emacs. rlb on irc gave one additional reason not mentioned earlier in the thread -- it could be that some other package choses to test for the setq-local say and perhaps draws incorrect conclusions about the environment. In particular this would be a case where we were breaking otherwise working packages. I think it makes sense to included the whole of read-char-choice, not some cutdown version, as we may use other functionality from it later (eg help-forms etc), and it would be confusing if the change only worked on emacs 24. Finally, I have two questions 1) please could someone with emacs 23 see if the testsuite passes? My system with emacs 23 is so outdated the test suite doesn't run (wrong python versions I think). 2) Is the copyright notice I have included above the two functions sufficient, and suitably placed? Best wishes Mark emacs/notmuch-address.el | 4 +-- emacs/notmuch-company.el | 3 +- emacs/notmuch-lib.el | 72 emacs/notmuch-maildir-fcc.el | 4 +-- 4 files changed, 78 insertions(+), 5 deletions(-) diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el index b2e1fba..1af3263 100644 --- a/emacs/notmuch-address.el +++ b/emacs/notmuch-address.el @@ -136,11 +136,11 @@ toggles the setting in this buffer." (interactive) (if (local-variable-p 'notmuch-address-command) (kill-local-variable 'notmuch-address-command) -(setq-local notmuch-address-command 'internal)) +(notmuch-setq-local notmuch-address-command 'internal)) (if (boundp 'company-idle-delay) (if (local-variable-p 'company-idle-delay) (kill-local-variable 'company-idle-delay) - (setq-local company-idle-delay nil + (notmuch-setq-local company-idle-delay nil (defun notmuch-address-matching (substring) "Returns a list of completion candidates matching SUBSTRING. diff --git a/emacs/notmuch-company.el b/emacs/notmuch-company.el index 168315f..5d75c14 100644 --- a/emacs/notmuch-company.el +++ b/emacs/notmuch-company.el @@ -28,6 +28,7 @@ ;;; Code: (eval-when-compile (require 'cl)) +(require 'notmuch-lib) (defvar notmuch-company-last-prefix nil) (make-variable-buffer-local 'notmuch-company-last-prefix) @@ -53,7 +54,7 @@ ;; internal completion) can still be accessed via standard company ;; functions, e.g., company-complete. (unless (eq notmuch-address-command 'internal) -(setq-local company-idle-delay nil))) +(notmuch-setq-local company-idle-delay nil))) ;;;###autoload (defun notmuch-company (command &optional arg &rest _ignore) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 1f0d167..bb53170 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -966,6 +966,78 @@ status." (defvar notmuch-show-process-crypto nil) (make-variable-buffer-local 'notmuch-show-process-crypto) +;; Compatibility functions for emacs 23. + +;; The functions in this section are copied from eamcs 24.4 and are +;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2014 Free Software +;; Foundation, Inc. + +(if (fboundp 'setq-local) +(defalias 'notmuch-setq-local 'setq-local) + (defmacro notmuch-setq-local (var val) +"Set variable VAR to value VAL in current buffer. + +Backport of setq-local for emacs without setq-local (pre 24.3)." +`(set (make-local-variable ',var) ,val))) + +(if (fboundp 'read-char-choice) +(defalias 'notmuch-read-char-choice 'read-char-choice) + (defun notmuch-read-char-choice (prompt chars &optional inhibit-keyboard-quit) + "Read and return one of CHARS, prompting for PROMPT. +Any input that is not one of CHARS is ignored. + +If optional argument INHIBIT-KEYBOARD-QUIT is non-nil, ignore +keyboard-quit events while waiting for a valid input. + +This is an exact copy of this function from emacs 24 for use on +emacs 23, except with the one emacs 24 only function it calls +inlined." + (unless (consp chars) +(error "Called `read-char-choice' without valid char choices")) + (let (char done show-help (helpbuf " *Char Help*")) +(let ((cursor-in-echo-area t) + (executing-kbd-macro executing-kbd-macro) + (esc-flag nil)) + (save-window-excursion ; in case we call help-form-show + (while (not done) + (unless (get-text-property 0 'face prompt) + (setq prompt (propertize prompt 'face 'minibuffer-prompt))) + (setq char (let ((inhibit-quit inhibit-keyboard-quit)) +
Re: [PATCH] emacs: add compatability functions for emacs 23
On Thu, 27 Oct 2016, Matt Armstrong wrote: > Mark Walters writes: > >> +;; Compatability functions for emacs 23. >> + >> +(unless (fboundp 'setq-local) >> + (defmacro setq-local (var val) >> +`(set (make-local-variable ',var) ,val))) > > A concern I have with this approach is that it modifies symbols outside > the notmuch namespace. Could people on old Emacsen come to rely on the > newer Emacs interfaces inadvertently, and wonder how they came to be, > etc? This is a good point. I think I don't mind too much if they do -- they should see it is provided by notmuch-lib if they do describe-function etc. But maybe bremner would like to comment? However, maybe other packages are doing the same. Thus I think we should not put in a cut down version of read-char-choice but just include the whole command from the emacs24 source. That way if any other package is doing the same load order doesn't matter -- we don't stomp on them and they don't stomp on us. (As an aside if we do that do we need to include any copyright notice or similar? -- maybe notmuch-lib.el could include notmuch-compat.el which would contain all the compatability functions?) > The only other package I have non-trivial experience working with is > Gnus, and the practice there was to place portability interfaces in the > gnus- namespace, and refrain from calling the "native" interfaces > directly. I think this would introduce a lot of clutter, so I would prefer not to go that route. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH] emacs: add compatability functions for emacs 23
On Tue, 25 Oct 2016, David Bremner wrote: > Mark Walters writes: > >> Some of the recent changes to the emacs code have used functions >> introduced in emacs 24. The functions used are read-char-choice and >> setq-local. This changeset adds compatability functions to >> notmuch-lib so that it should work on emacs 23. >> >> --- >> >> Hi >> >> I tried compiling under emacs 23 recently and noticed that some recent >> changes have used some features introuduced in emacs 24. I think we >> still support emacs 23 so this changeset adds two compatability >> functions. > > Hi Mark; > > Can you give me a recipe to reproduce the failures in emacs23? I only > get warnings when building. Of course I believe that things will go > wrong at some point calling non-existent functions. Hi You can make the read-char-choice fail by setting the fcc header to use insert (the default), locking the database (eg doing notmuch tag --batch), composing and sending a message. The Fcc will fail, which will trigger the error. For the setq-local start to compose a message, and then run M-x notmuch-address-toggle-internal-completion This will give the error. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2] devel: Document emacs keybindings
This adds a file under devel listing all the keybindings sorted by key in the main three modes (search, show and tree). To reduce clutter it only lists the single key "unmodified" keybindings: I think all our uses of prefixes and modifiers are natural variants of the unmodified binding (eg M-n compared to n in show mode) This should make easier to see what keybindings are available when adding new features. --- Hi This is an updated version of id:1474377391-17960-1-git-send-email-markwalters1...@gmail.com It is almost unchanged, but I have changed the commit message to make it clear that I only intend it to contain unmodified (no C- M- etc) bindings. Otherwise the only change is that I updated the table to reflect 9966720453c72286b5f36a56323244d70202cb26 which moved "b" in tree-mode to bounce, and DEL to backscroll. Best wishes Mark devel/emacs-keybindings.org | 59 + 1 file changed, 59 insertions(+) create mode 100644 devel/emacs-keybindings.org diff --git a/devel/emacs-keybindings.org b/devel/emacs-keybindings.org new file mode 100644 index 000..0f13b36 --- /dev/null +++ b/devel/emacs-keybindings.org @@ -0,0 +1,59 @@ +|---++---+-| +| Key | Search Mode| Show Mode | Tree Mode | +|---++---+-| +| a | notmuch-search-archive-thread | notmuch-show-archive-message-then-next-or-next-thread | notmuch-tree-archive-message-then-next | +| b | notmuch-search-scroll-down | notmuch-show-resend-message | notmuch-show-resend-message | +| c | notmuch-search-stash-map | notmuch-show-stash-map | notmuch-show-stash-map | +| d || | | +| e || | (notmuch-tree-button-activate) | +| f || notmuch-show-forward-message | notmuch-show-forward-message| +| g || | | +| h || notmuch-show-toggle-visibility-headers| | +| i || | | +| j | notmuch-jump-search| notmuch-jump-search | notmuch-jump-search | +| k | notmuch-tag-jump | notmuch-tag-jump | notmuch-tag-jump| +| l | notmuch-search-filter | notmuch-show-filter-thread| | +| m | notmuch-mua-new-mail | notmuch-mua-new-mail | notmuch-mua-new-mail| +| n | notmuch-search-next-thread | notmuch-show-next-open-message| notmuch-tree-next-matching-message | +| o | notmuch-search-toggle-order| | | +| p | notmuch-search-previous-thread | notmuch-show-previous-open-message| notmuch-tree-prev-matching-message | +| q | notmuch-bury-or-kill-this-buffer | notmuch-bury-or-kill-this-buffer | notmuch-bury-or-kill-this-buffer| +| r | notmuch-search-reply-to-thread-sender | notmuch-show-reply-sender | notmuch-show-reply-sender | +| s | notmuch-search | notmuch-search | notmuch-search | +| t | notmuch-search-filter-by-tag | toggle-truncate-lines | | +| u || | | +| v ||
Re: [PATCH] cli: try to run external notmuch- prefixed commands as subcommands
On Sat, 22 Oct 2016, Jani Nikula wrote: > If the given subcommand is not known to notmuch, try to execute > external notmuch- instead. This allows users to have their > own notmuch related tools be run via the notmuch command, not unlike > git does. Also notmuch-emacs-mua will be executable via 'notmuch > emacs-mua'. > > By design, this does not allow notmuch's own subcommands to be > overriden using external commands. > > --- > > Whether internal subcommands can be overridden or not is up to debate, > can be consider either a bug or a feature depending on how you look at > it. This looks good to me +1 (note my C is not great, and I haven't tested yet). It took me a while to realise that a nice feature of this was that we can have some commands in languages other than C, like the emacs-mua command in the next patch. My only query is whether we are setting ourselves up to annoy people if we add official commands later. For example if we add a notmuch delete command then it could break a user's setup if they have a notmuch-delete command. Would it be worth saying that we guarantee some namespace such as local-* (so commands called notmuch-local-*) won't be touched? Best wishes Mark > --- > notmuch.c | 39 +-- > 1 file changed, 37 insertions(+), 2 deletions(-) > > diff --git a/notmuch.c b/notmuch.c > index 38b73c1d2acc..b9c320329dd5 100644 > --- a/notmuch.c > +++ b/notmuch.c > @@ -363,6 +363,39 @@ notmuch_command (notmuch_config_t *config, > return EXIT_SUCCESS; > } > > +/* > + * Try to run subcommand in argv[0] as notmuch- prefixed external > + * command. argv must be NULL terminated (argv passed to main always > + * is). > + * > + * Does not return if the external command is found and > + * executed. Return TRUE if external command is not found. Return > + * FALSE on errors. > + */ > +static notmuch_bool_t try_external_command(char *argv[]) > +{ > +char *old_argv0 = argv[0]; > +notmuch_bool_t ret = TRUE; > + > +argv[0] = talloc_asprintf (NULL, "notmuch-%s", old_argv0); > + > +/* > + * This will only return on errors. Not finding an external > + * command (ENOENT) is not an error from our perspective. > + */ > +execvp (argv[0], argv); > +if (errno != ENOENT) { > + fprintf (stderr, "Error: Running external command '%s' failed: %s\n", > + argv[0], strerror(errno)); > + ret = FALSE; > +} > + > +talloc_free (argv[0]); > +argv[0] = old_argv0; > + > +return ret; > +} > + > int > main (int argc, char *argv[]) > { > @@ -406,8 +439,10 @@ main (int argc, char *argv[]) > > command = find_command (command_name); > if (!command) { > - fprintf (stderr, "Error: Unknown command '%s' (see \"notmuch help\")\n", > - command_name); > + /* This won't return if the external command is found. */ > + if (try_external_command(argv + opt_index)) > + fprintf (stderr, "Error: Unknown command '%s' (see \"notmuch > help\")\n", > + command_name); > ret = EXIT_FAILURE; > goto DONE; > } > -- > 2.1.4 > > ___ > notmuch mailing list > notmuch@notmuchmail.org > https://notmuchmail.org/mailman/listinfo/notmuch ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] emacs: add compatability functions for emacs 23
Some of the recent changes to the emacs code have used functions introduced in emacs 24. The functions used are read-char-choice and setq-local. This changeset adds compatability functions to notmuch-lib so that it should work on emacs 23. --- Hi I tried compiling under emacs 23 recently and noticed that some recent changes have used some features introuduced in emacs 24. I think we still support emacs 23 so this changeset adds two compatability functions. They are setq-local, which is esentially trivial, and read-char-choice. I have written a minimal version of read-char-choice for the functionality we need -- an alternative would be to just copy and paste the function from emacs 24 source. I have tested (lightly) on emacs 23 and it seems to work (and didn't before). It should not change anything on more recent emacs (i.e. in cases where we weren't already broken). Finally, it does leave a compiler warning when compiling under emacs 23: notmuch-company.el does not require notmuch-lib.el but I think that is probably OK. Best wishes Mark emacs/notmuch-lib.el | 18 ++ 1 file changed, 18 insertions(+) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 1f0d167..1459f83 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -966,6 +966,24 @@ status." (defvar notmuch-show-process-crypto nil) (make-variable-buffer-local 'notmuch-show-process-crypto) +;; Compatability functions for emacs 23. + +(unless (fboundp 'setq-local) + (defmacro setq-local (var val) +`(set (make-local-variable ',var) ,val))) + +(unless (fboundp 'read-char-choice) + (defun read-char-choice (prompt chars) +(let (char done) + (while (not done) + (setq char (read-key prompt)) + (cond +((memq char chars) + (setq done t)) +((memq char '(?\C-g ?\e)) + (keyboard-quit + char))) + (provide 'notmuch-lib) ;; Local Variables: -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] emacs: interesting-buffer bugfixes/updates
The command notmuch-interesting-buffer has got out of date -- it doesn't mention notmuch-tree, and it still refers to message-mode not notmuch-message-mode. Update both of these. This fixes the bug that notmuch-cycle-notmuch-buffers does not include notmuch-tree or notmuch-message-mode buffers in its cycling. --- Jani pointed notmuch-cycle-notmuch-buffers out to me on irc (I hadn't known it existed). It seems like it could be very useful. However, it call notmuch-interesting-buffer which has not been updated since 2011, so doesn't know about notmuch-tree or notmuch-message-mode. notmuch-tree came into mainline in 2013, and we switched to notmuch-message-mode (from message-mode) in August last year, so both bugs have been present for quite some time. Best wishes Mark emacs/notmuch.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch.el b/emacs/notmuch.el index bd08aa0..2fc72b7 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -1066,8 +1066,9 @@ current search results AND that are tagged with the given tag." (with-current-buffer b (memq major-mode '(notmuch-show-mode notmuch-search-mode + notmuch-tree-mode notmuch-hello-mode - message-mode + notmuch-message-mode ;;;###autoload (defun notmuch-cycle-notmuch-buffers () -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] nmbug: allow excluded messages
This makes nmbug work even if the notmuch mailing list messages are excluded (i.e., have a tag in the excluded tags list). --- I keep all my mailing list emails under an excluded tag (initially this was to test the exclude code thoroughly, but I find it convenient to keep day to day email and mailing list email separate). However, this confuses nmbug -- would the following patch be acceptable? (I think this is the only place it is needed, but I don't use nmbug much so I haven't tested thoroughly.) Best wishes Mark devel/nmbug/nmbug | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devel/nmbug/nmbug b/devel/nmbug/nmbug index 6febf16..dc565c4 100755 --- a/devel/nmbug/nmbug +++ b/devel/nmbug/nmbug @@ -580,7 +580,7 @@ def get_status(): maybe_deleted = _diff_index(index=index, filter='D') for id, tags in maybe_deleted.items(): (_, stdout, stderr) = _spawn( -args=['notmuch', 'search', '--output=files', 'id:{0}'.format(id)], +args=['notmuch', 'search', '--output=files', '--exclude=false', 'id:{0}'.format(id)], stdout=_subprocess.PIPE, wait=True) if stdout: -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] NEWS for two bugfixes
This adds news items for the two bugs emacs: search face bugfix and emacs: fix notmuch-search-line-faces defcustom --- Hi here is a NEWS update as requested. Best wishes Mark NEWS | 9 + 1 file changed, 9 insertions(+) diff --git a/NEWS b/NEWS index ac3ceb1..547b961 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,15 @@ Require Xapian >= 1.2.6 Emacs - +Fix default colours for unread and flagged messages + + In 0.23 the default colours for unread and flagged messages in + search view were accidentally swapped. This release returns them to + the original colours. + + A related change in 0.23 broke the customize widget for + notmuch-search-line-faces. This is now fixed. + Fix test failure with Emacs 25.1 A previously undiscovered jit-lock related bug was exposed by Emacs -- 2.1.4 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch