From 0671436872a37589003860ab31bac40ed04a7cce Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 09:48:15 -0800 Subject: [PATCH 01/74] notmuch.el: Don't use beginning-of-buffer from elisp program. This silences a warning when compiling notmuch.el. The documentation of beginning-of-buffer does say (rather emphatically) that it's not to be used from lisp programs. --- notmuch.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notmuch.el b/notmuch.el index 65473ba7..9b23e351 100644 --- a/notmuch.el +++ b/notmuch.el @@ -877,7 +877,7 @@ thread from that buffer can be show when done with this one)." (setq btn (forward-button 1)) (error (setq btn nil))) )) - (beginning-of-buffer) + (goto-char (point-min)) )))) ))) From 04036fb8065e2ad11e9ee483f2b59b4fdd1a94dd Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 09:49:53 -0800 Subject: [PATCH 02/74] notmuch.el: Add documentation for notmuch-search-show-thread. It's especially unkind to leave interactive functions without documentation. --- notmuch.el | 1 + 1 file changed, 1 insertion(+) diff --git a/notmuch.el b/notmuch.el index 9b23e351..b99ca02e 100644 --- a/notmuch.el +++ b/notmuch.el @@ -1012,6 +1012,7 @@ global search. (get-text-property (point) 'notmuch-search-thread-id)) (defun notmuch-search-show-thread () + "Display the currently selected thread." (interactive) (let ((thread-id (notmuch-search-find-thread-id))) (if (> (length thread-id) 0) From de4be1b2293699e45d42b6f395b16d854151a58f Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 09:53:38 -0800 Subject: [PATCH 03/74] notmuch.el: Implement our own notmuch-help instead of describe-mode. This gives somewhat friendlier output for the '?' binding than we had previously with `describe-mode'. First, we no longer have the various minor modes cluttering up the output. Second the display of the binding table uses the first line of documentation for the bound function rather than the function name. --- notmuch.el | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/notmuch.el b/notmuch.el index b99ca02e..6e548f10 100644 --- a/notmuch.el +++ b/notmuch.el @@ -81,7 +81,7 @@ (define-key map (kbd "DEL") 'notmuch-show-rewind) (define-key map " " 'notmuch-show-advance-marking-read-and-archiving) (define-key map "|" 'notmuch-show-pipe-message) - (define-key map "?" 'describe-mode) + (define-key map "?" 'notmuch-help) (define-key map (kbd "TAB") 'notmuch-show-next-button) (define-key map (kbd "M-TAB") 'notmuch-show-previous-button) map) @@ -775,6 +775,42 @@ which this thread was originally shown." (notmuch-show-markup-message))) (notmuch-show-hide-markers)) +(defun notmuch-documentation-first-line (symbol) + "Return the first line of the documentation string for SYMBOL." + (let ((doc (documentation symbol))) + (if doc + (with-temp-buffer + (insert (documentation symbol)) + (goto-char (point-min)) + (let ((beg (point))) + (end-of-line) + (buffer-substring beg (point)))) + ""))) + +(defun notmuch-substitute-one-command-key (binding) + "For a key binding, return a string showing a human-readable representation +of the key as well as the first line of documentation from the bound function." + (concat (format-kbd-macro (vector (car binding))) + "\t" + (notmuch-documentation-first-line (cdr binding)))) + +(defun notmuch-substitute-command-keys (doc) + "Like `substitute-command-keys' but with documentation, not function names." + (let ((beg 0)) + (while (string-match "\\\\{\\([^}[:space:]]*\\)}" doc beg) + (let ((map (substring doc (match-beginning 1) (match-end 1)))) + (setq doc (replace-match (mapconcat 'notmuch-substitute-one-command-key + (cdr (symbol-value (intern map))) "\n") 1 1 doc))) + (setq beg (match-end 0))) + doc)) + +(defun notmuch-help () + "Display help for the current notmuch mode." + (interactive) + (let ((mode major-mode)) + (with-help-window (help-buffer) + (princ (notmuch-substitute-command-keys (documentation mode t)))))) + ;;;###autoload (defun notmuch-show-mode () "Major mode for viewing a thread with notmuch. @@ -909,7 +945,7 @@ thread from that buffer can be show when done with this one)." (define-key map "\M->" 'notmuch-search-goto-last-thread) (define-key map " " 'notmuch-search-scroll-up) (define-key map (kbd "") 'notmuch-search-scroll-down) - (define-key map "?" 'describe-mode) + (define-key map "?" 'notmuch-help) map) "Keymap for \"notmuch search\" buffers.") (fset 'notmuch-search-mode-map notmuch-search-mode-map) @@ -977,8 +1013,8 @@ keys can be used to add or remove tags from a thread. The 'a' key is a convenience key for archiving a thread (removing the \"inbox\" tag). -Other useful commands are `notmuch-search-filter' for filtering -the current search based on an additional query string, +Other useful commands are `notmuch-search-filter' for +filtering the current search based on an additional query string, `notmuch-search-filter-by-tag' for filtering to include only messages with a given tag, and `notmuch-search' to execute a new, global search. @@ -1258,7 +1294,7 @@ current search results AND that are tagged with the given tag." (define-key map (kbd "RET") 'notmuch-folder-show-search) (define-key map "<" 'beginning-of-buffer) (define-key map "=" 'notmuch-folder) - (define-key map "?" 'describe-mode) + (define-key map "?" 'notmuch-help) (define-key map [mouse-1] 'notmuch-folder-show-search) map) "Keymap for \"notmuch folder\" buffers.") From 161b2738e1b99f56d0d44a446045e223deddea22 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 16:02:27 -0800 Subject: [PATCH 04/74] notmuch.el: Reorder notmuch-search-mode keybindings map. I had originally created this keymap in order from most important to least important commands. But our new notmuch-help command is presented with the list in the reverse order. So we reverse the input so that the user sees the most important commands first. --- notmuch.el | 64 +++++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/notmuch.el b/notmuch.el index 6e548f10..ddfcdc2a 100644 --- a/notmuch.el +++ b/notmuch.el @@ -922,30 +922,29 @@ thread from that buffer can be show when done with this one)." (defvar notmuch-search-mode-map (let ((map (make-sparse-keymap))) - (define-key map "a" 'notmuch-search-archive-thread) - (define-key map "b" 'notmuch-search-scroll-down) - (define-key map "f" 'notmuch-search-filter) - (define-key map "m" 'message-mail) - (define-key map "n" 'next-line) - (define-key map "o" 'notmuch-search-toggle-order) - (define-key map "p" 'previous-line) + (define-key map "?" 'notmuch-help) (define-key map "q" 'kill-this-buffer) - (define-key map "r" 'notmuch-search-reply-to-thread) - (define-key map "s" 'notmuch-search) - (define-key map "t" 'notmuch-search-filter-by-tag) (define-key map "x" 'kill-this-buffer) - (define-key map (kbd "RET") 'notmuch-search-show-thread) - (define-key map [mouse-1] 'notmuch-search-show-thread) - (define-key map "+" 'notmuch-search-add-tag) - (define-key map "-" 'notmuch-search-remove-tag) - (define-key map "*" 'notmuch-search-operate-all) + (define-key map (kbd "") 'notmuch-search-scroll-down) + (define-key map "b" 'notmuch-search-scroll-down) + (define-key map " " 'notmuch-search-scroll-up) (define-key map "<" 'beginning-of-buffer) (define-key map ">" 'notmuch-search-goto-last-thread) + (define-key map "p" 'previous-line) + (define-key map "n" 'next-line) + (define-key map "r" 'notmuch-search-reply-to-thread) + (define-key map "m" 'message-mail) + (define-key map "s" 'notmuch-search) + (define-key map "o" 'notmuch-search-toggle-order) (define-key map "=" 'notmuch-search-refresh-view) - (define-key map "\M->" 'notmuch-search-goto-last-thread) - (define-key map " " 'notmuch-search-scroll-up) - (define-key map (kbd "") 'notmuch-search-scroll-down) - (define-key map "?" 'notmuch-help) + (define-key map "t" 'notmuch-search-filter-by-tag) + (define-key map "f" 'notmuch-search-filter) + (define-key map "*" 'notmuch-search-operate-all) + (define-key map "a" 'notmuch-search-archive-thread) + (define-key map "-" 'notmuch-search-remove-tag) + (define-key map "+" 'notmuch-search-add-tag) + (define-key map [mouse-1] 'notmuch-search-show-thread) + (define-key map (kbd "RET") 'notmuch-search-show-thread) map) "Keymap for \"notmuch search\" buffers.") (fset 'notmuch-search-mode-map notmuch-search-mode-map) @@ -1002,22 +1001,27 @@ thread from that buffer can be show when done with this one)." ;;;###autoload (defun notmuch-search-mode () - "Major mode for searching mail with notmuch. + "Major mode displaying results of a notmuch search. This buffer contains the results of a \"notmuch search\" of your email archives. Each line in the buffer represents a single -thread giving a relative date for the thread and a subject. +thread giving a summary of the thread (a relative date, the +number of matched messages and total messages in the thread, +participants in the thread, a representative subject line, and +any tags). -Pressing RET on any line displays that thread. The '+' and '-' -keys can be used to add or remove tags from a thread. The 'a' key -is a convenience key for archiving a thread (removing the -\"inbox\" tag). +By default, pressing RET on any line displays that thread. The +'+' and '-' keys can be used to add or remove tags from a +thread. The 'a' key is a convenience key for archiving a +thread (removing the \"inbox\" tag). The '*' key can be used to +add or remove a tag from all threads in the current buffer. -Other useful commands are `notmuch-search-filter' for -filtering the current search based on an additional query string, -`notmuch-search-filter-by-tag' for filtering to include only -messages with a given tag, and `notmuch-search' to execute a new, -global search. +Other useful commands are 'f' for filtering the current search +based on an additional query string, 't' for filtering to include +only messages with a given tag, and 's' to execute a new, global +search. + +Complete list of currently available key bindings: \\{notmuch-search-mode-map}" (interactive) From c24360e59e90893f1edf2a95289c1091ccd98975 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 16:44:05 -0800 Subject: [PATCH 05/74] notmuch.el: Don't document mouse actions in notmuch-help. The concept behind direct manipulation with mouse clicks is that documentation shouldn't be necessary, (though my original motivation here was simply that "" was exceeding my TAB width. This does cause a blank line to be added for the mouse binding. This isn't directly desired, but as long as it's there we put it at a natural place for a separator. --- notmuch.el | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/notmuch.el b/notmuch.el index ddfcdc2a..40d78753 100644 --- a/notmuch.el +++ b/notmuch.el @@ -789,10 +789,15 @@ which this thread was originally shown." (defun notmuch-substitute-one-command-key (binding) "For a key binding, return a string showing a human-readable representation -of the key as well as the first line of documentation from the bound function." - (concat (format-kbd-macro (vector (car binding))) - "\t" - (notmuch-documentation-first-line (cdr binding)))) +of the key as well as the first line of documentation from the bound function. + +For a mouse binding, return nil." + (let ((key (car binding))) + (if (mouse-event-p key) + nil + (concat (format-kbd-macro (vector key)) + "\t" + (notmuch-documentation-first-line (cdr binding)))))) (defun notmuch-substitute-command-keys (doc) "Like `substitute-command-keys' but with documentation, not function names." @@ -939,11 +944,11 @@ thread from that buffer can be show when done with this one)." (define-key map "=" 'notmuch-search-refresh-view) (define-key map "t" 'notmuch-search-filter-by-tag) (define-key map "f" 'notmuch-search-filter) + (define-key map [mouse-1] 'notmuch-search-show-thread) (define-key map "*" 'notmuch-search-operate-all) (define-key map "a" 'notmuch-search-archive-thread) (define-key map "-" 'notmuch-search-remove-tag) (define-key map "+" 'notmuch-search-add-tag) - (define-key map [mouse-1] 'notmuch-search-show-thread) (define-key map (kbd "RET") 'notmuch-search-show-thread) map) "Keymap for \"notmuch search\" buffers.") From 07a46d10eaf93707f37f3325c8192ef0684ad06d Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 16:48:19 -0800 Subject: [PATCH 06/74] notmuch.el: Fix notmuch-search-scroll-down to go to first thread. When there's no more to scroll, we want to select the first thread. This used to work, and I'm not sure when it broke, (perhaps when we switched from post-process decorating of the search results to filtering). Fix the calculation to work again. --- notmuch.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notmuch.el b/notmuch.el index 40d78753..9eb84696 100644 --- a/notmuch.el +++ b/notmuch.el @@ -977,8 +977,8 @@ thread from that buffer can be show when done with this one)." ; directly to that position. (We have to count lines since the ; window-start position is not the same as point-min due to the ; invisible thread-ID characters on the first line. - (if (equal (count-lines (point-min) (window-start)) 1) - (goto-char (window-start)) + (if (equal (count-lines (point-min) (window-start)) 0) + (goto-char (point-min)) (scroll-down nil))) (defun notmuch-search-goto-last-thread () From b7a6e0598041b830256eaad52750672b442ff687 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 16:50:52 -0800 Subject: [PATCH 07/74] notmuch.el: Fix notmuch-search-goto-last-thread. This broke when we switched to filter-based processing of search results and added the "End of search results" line onto the end. Fix to skip ignore that line when moving to the last thread. --- notmuch.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notmuch.el b/notmuch.el index 9eb84696..439a975f 100644 --- a/notmuch.el +++ b/notmuch.el @@ -985,7 +985,7 @@ thread from that buffer can be show when done with this one)." "Move point to the last thread in the buffer." (interactive) (goto-char (point-max)) - (forward-line -1)) + (forward-line -2)) (defface notmuch-tag-face '((((class color) From 335a8aec2bf36a9f947e4ebc333d9977c4606cd4 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 16:52:31 -0800 Subject: [PATCH 08/74] notmuch.el: Clean up documentation of notmuch-search-mode-map commands. Since notmuch-help now displays a single line of documentation from each of these commands we ensure that the first line stands alone for each command. We also override some builtin commands with new commands that don't behave any differently, but have our own notmuch-specific documentation, (such as "select next thread" rather than "move point to next line"). --- notmuch.el | 60 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/notmuch.el b/notmuch.el index 439a975f..3f27f08e 100644 --- a/notmuch.el +++ b/notmuch.el @@ -933,10 +933,10 @@ thread from that buffer can be show when done with this one)." (define-key map (kbd "") 'notmuch-search-scroll-down) (define-key map "b" 'notmuch-search-scroll-down) (define-key map " " 'notmuch-search-scroll-up) - (define-key map "<" 'beginning-of-buffer) - (define-key map ">" 'notmuch-search-goto-last-thread) - (define-key map "p" 'previous-line) - (define-key map "n" 'next-line) + (define-key map "<" 'notmuch-search-first-thread) + (define-key map ">" 'notmuch-search-last-thread) + (define-key map "p" 'notmuch-search-previous-thread) + (define-key map "n" 'notmuch-search-next-thread) (define-key map "r" 'notmuch-search-reply-to-thread) (define-key map "m" 'message-mail) (define-key map "s" 'notmuch-search) @@ -958,16 +958,15 @@ thread from that buffer can be show when done with this one)." (defvar notmuch-search-oldest-first t "Show the oldest mail first in the search-mode") - (defun notmuch-search-scroll-up () - "Scroll up, moving point to last message in thread if at end." + "Move forward through search results by one window's worth." (interactive) (condition-case nil (scroll-up nil) - ((end-of-buffer) (notmuch-search-goto-last-thread)))) + ((end-of-buffer) (notmuch-search-last-thread)))) (defun notmuch-search-scroll-down () - "Scroll down, moving point to first message in thread if at beginning." + "Move backward through the search results by one window's worth." (interactive) ; I don't know why scroll-down doesn't signal beginning-of-buffer ; the way that scroll-up signals end-of-buffer, but c'est la vie. @@ -981,12 +980,27 @@ thread from that buffer can be show when done with this one)." (goto-char (point-min)) (scroll-down nil))) -(defun notmuch-search-goto-last-thread () - "Move point to the last thread in the buffer." +(defun notmuch-search-next-thread () + "Select the next thread in the search results." + (interactive) + (next-line)) + +(defun notmuch-search-previous-thread () + "Select the previous thread in the search results." + (interactive) + (previous-line)) + +(defun notmuch-search-last-thread () + "Select the last thread in the search results." (interactive) (goto-char (point-max)) (forward-line -2)) +(defun notmuch-search-first-thread () + "Select the first thread in the search results." + (interactive) + (goto-char (point-min))) + (defface notmuch-tag-face '((((class color) (background dark)) @@ -1110,25 +1124,29 @@ and will also appear in a buffer named \"*Notmuch errors*\"." (split-string (buffer-substring beg end)))))) (defun notmuch-search-add-tag (tag) - "Add a tag to messages in the current thread matching the -active query." + "Add a tag to the currently selected thread. + +The tag is added to messages in the currently selected thread +which match the current search terms." (interactive (list (notmuch-select-tag-with-completion "Tag to add: "))) (notmuch-call-notmuch-process "tag" (concat "+" tag) (notmuch-search-find-thread-id) " and " notmuch-search-query-string) (notmuch-search-set-tags (delete-dups (sort (cons tag (notmuch-search-get-tags)) 'string<)))) (defun notmuch-search-remove-tag (tag) - "Remove a tag from messages in the current thread matching the -active query." + "Remove a tag from the currently selected thread. + +The tag is removed from messages in the currently selected thread +which match the current search terms." (interactive (list (notmuch-select-tag-with-completion "Tag to remove: " (notmuch-search-find-thread-id)))) (notmuch-call-notmuch-process "tag" (concat "-" tag) (notmuch-search-find-thread-id) " and " notmuch-search-query-string) (notmuch-search-set-tags (delete tag (notmuch-search-get-tags)))) (defun notmuch-search-archive-thread () - "Archive the current thread (remove its \"inbox\" tag). + "Archive the currently selected thread (remove its \"inbox\" tag). -This function advances point to the next line when finished." +This function advances the next thread when finished." (interactive) (notmuch-search-remove-tag "inbox") (forward-line)) @@ -1182,12 +1200,12 @@ This function advances point to the next line when finished." (delete-process proc)))) (defun notmuch-search-operate-all (action) - "Operate on all messages matching the current query. Any -number of whitespace separated actions can be given. Each action -must have one of the two forms + "Add/remove tags from all matching messages. - +tagname Add the tag `tagname' - -tagname Remove the tag `tagname' +Tis command adds or removes tags from all messages matching the +current search terms. When called interactively, this command +will prompt for tags to be added or removed. Tags prefixed with +'+' will be added and tags prefixed with '-' will be removed. Each character of the tag name may consist of alphanumeric characters as well as `_.+-'. From f5e125a9c02c0afbe52d0be4033fb46e0d74dfc0 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 21:46:55 -0800 Subject: [PATCH 09/74] notmuch.el: Fix notmuch-help to properly display prefixed bindings. Previously, we would do only a single-level traverse of the keymap. That meant that for a keybinding such as "M-TAB" we would just see the prefix key ("ESC") and print that it was a keymap---never printing the TAB nor the documentation for the command it is bound to. Now, we do the full walk, constructing a proper description of the full keybdinding with prefix characters, (and converting "ESC" to "M-" for legibility). --- notmuch.el | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/notmuch.el b/notmuch.el index 3f27f08e..b21aeaea 100644 --- a/notmuch.el +++ b/notmuch.el @@ -787,17 +787,38 @@ which this thread was originally shown." (buffer-substring beg (point)))) ""))) -(defun notmuch-substitute-one-command-key (binding) - "For a key binding, return a string showing a human-readable representation -of the key as well as the first line of documentation from the bound function. +(defun notmuch-prefix-key-description (key) + "Given a prefix key code, return a human-readable string representation. + +This is basically just `format-kbd-macro' but we also convert ESC to M-." + (let ((desc (format-kbd-macro (vector key)))) + (if (string= desc "ESC") + "M-" + (concat desc " ")))) + +; I would think that emacs would have code handy for walking a keymap +; and generating strings for each key, and I would prefer to just call +; that. But I couldn't find any (could be all implemented in C I +; suppose), so I wrote my own here. +(defun notmuch-substitute-one-command-key-with-prefix (prefix binding) + "For a key binding, return a string showing a human-readable +representation of the prefixed key as well as the first line of +documentation from the bound function. For a mouse binding, return nil." - (let ((key (car binding))) + (let ((key (car binding)) + (action (cdr binding))) (if (mouse-event-p key) nil - (concat (format-kbd-macro (vector key)) - "\t" - (notmuch-documentation-first-line (cdr binding)))))) + (if (keymapp action) + (let ((substitute (apply-partially 'notmuch-substitute-one-command-key-with-prefix (notmuch-prefix-key-description key)))) + (mapconcat substitute (cdr action) "\n")) + (concat prefix (format-kbd-macro (vector key)) + "\t" + (notmuch-documentation-first-line action)))))) + +(defalias 'notmuch-substitute-one-command-key + (apply-partially 'notmuch-substitute-one-command-key-with-prefix nil)) (defun notmuch-substitute-command-keys (doc) "Like `substitute-command-keys' but with documentation, not function names." From 62993c76227376aca1b1958a7b82bc99ed76ea98 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 22:24:05 -0800 Subject: [PATCH 10/74] notmuch.el: Clean up documentation of notmuch-show-mode-map commands. As we did recently for notmuch-search-mode-map, ensure that the first line of docuemntation for each command stands alone. We also take advantage of the substitute-command-keys functionality within notmuch-help so that the introductory paragraphs can talk about key bindings by key (rather than function name) in a way that will always be current even in the face of the user rebinding keys. --- notmuch.el | 99 +++++++++++++++++++++++++++--------------------------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/notmuch.el b/notmuch.el index b21aeaea..a8e523d5 100644 --- a/notmuch.el +++ b/notmuch.el @@ -53,37 +53,30 @@ (defvar notmuch-show-mode-map (let ((map (make-sparse-keymap))) - ; I don't actually want all of these toggle commands occupying - ; keybindings. They steal valuable key-binding space, are hard - ; to remember, and act globally rather than locally. - ; - ; Will be much preferable to switch to direct manipulation for - ; toggling visibility of these components. Probably using - ; overlays-at to query and manipulate the current overlay. - (define-key map "a" 'notmuch-show-archive-thread) - (define-key map "A" 'notmuch-show-mark-read-then-archive-thread) - (define-key map "f" 'notmuch-show-forward-current) - (define-key map "m" 'message-mail) - (define-key map "n" 'notmuch-show-next-message) - (define-key map "N" 'notmuch-show-mark-read-then-next-open-message) - (define-key map "p" 'notmuch-show-previous-message) - (define-key map (kbd "C-n") 'notmuch-show-next-line) - (define-key map (kbd "C-p") 'notmuch-show-previous-line) + (define-key map "?" 'notmuch-help) (define-key map "q" 'kill-this-buffer) - (define-key map "r" 'notmuch-show-reply) - (define-key map "s" 'notmuch-search) - (define-key map "v" 'notmuch-show-view-all-mime-parts) - (define-key map "V" 'notmuch-show-view-raw-message) - (define-key map "w" 'notmuch-show-save-attachments) (define-key map "x" 'kill-this-buffer) - (define-key map "+" 'notmuch-show-add-tag) + (define-key map (kbd "C-p") 'notmuch-show-previous-line) + (define-key map (kbd "C-n") 'notmuch-show-next-line) + (define-key map (kbd "M-TAB") 'notmuch-show-previous-button) + (define-key map (kbd "TAB") 'notmuch-show-next-button) + (define-key map "s" 'notmuch-search) + (define-key map "m" 'message-mail) + (define-key map "f" 'notmuch-show-forward-current) + (define-key map "r" 'notmuch-show-reply) + (define-key map "|" 'notmuch-show-pipe-message) + (define-key map "w" 'notmuch-show-save-attachments) + (define-key map "V" 'notmuch-show-view-raw-message) + (define-key map "v" 'notmuch-show-view-all-mime-parts) (define-key map "-" 'notmuch-show-remove-tag) + (define-key map "+" 'notmuch-show-add-tag) + (define-key map "A" 'notmuch-show-mark-read-then-archive-thread) + (define-key map "a" 'notmuch-show-archive-thread) + (define-key map "p" 'notmuch-show-previous-message) + (define-key map "N" 'notmuch-show-mark-read-then-next-open-message) + (define-key map "n" 'notmuch-show-next-message) (define-key map (kbd "DEL") 'notmuch-show-rewind) (define-key map " " 'notmuch-show-advance-marking-read-and-archiving) - (define-key map "|" 'notmuch-show-pipe-message) - (define-key map "?" 'notmuch-help) - (define-key map (kbd "TAB") 'notmuch-show-next-button) - (define-key map (kbd "M-TAB") 'notmuch-show-previous-button) map) "Keymap for \"notmuch show\" buffers.") (fset 'notmuch-show-mode-map notmuch-show-mode-map) @@ -252,7 +245,7 @@ Unlike builtin `next-line' this version accepts no arguments." (notmuch-search-show-thread))))) (defun notmuch-show-mark-read-then-archive-thread () - "Remove \"unread\" tag from each message, then archive and show next thread. + "Remove unread tags from thread, then archive and show next thread. Archive each message currently shown by removing the \"unread\" and \"inbox\" tag from each. Then kill this buffer and show the @@ -267,7 +260,7 @@ buffer." (notmuch-show-archive-thread-maybe-mark-read t)) (defun notmuch-show-archive-thread () - "Archive each message in thread, and show next thread from search. + "Archive each message in thread, then show next thread from search. Archive each message currently shown by removing the \"inbox\" tag from each. Then kill this buffer and show the next thread @@ -296,7 +289,7 @@ buffer." (kill-buffer buf))))) (defun notmuch-show-view-all-mime-parts () - "Use external viewers (according to mailcap) to view all MIME-encoded parts." + "Use external viewers to view all attachments from the current message." (interactive) (with-current-notmuch-show-message (mm-display-parts (mm-dissect-buffer)))) @@ -334,7 +327,7 @@ buffer." mm-handle)) (defun notmuch-show-save-attachments () - "Save the attachments to a message" + "Save all attachments from the current message." (interactive) (with-current-notmuch-show-message (let ((mm-handle (mm-dissect-buffer))) @@ -360,7 +353,7 @@ buffer." (notmuch-reply message-id))) (defun notmuch-show-forward-current () - "Forward a the current message." + "Forward the current message." (interactive) (with-current-notmuch-show-message (message-forward))) @@ -486,13 +479,13 @@ it." (point)))) (defun notmuch-show-mark-read-then-next-open-message () - "Remove unread tag from current message, then advance to next unread message." + "Remove unread tag from this message, then advance to next open message." (interactive) (notmuch-show-remove-tag "unread") (notmuch-show-next-open-message)) (defun notmuch-show-rewind () - "Do reverse scrolling compared to `notmuch-show-advance-marking-read-and-archiving' + "Backup through the thread, (reverse scrolling compared to \\[notmuch-show-advance-marking-read-and-archiving]). Specifically, if the beginning of the previous email is fewer than `window-height' lines from the current point, move to it @@ -514,7 +507,7 @@ any effects from previous calls to (notmuch-show-previous-message)))) (defun notmuch-show-advance-marking-read-and-archiving () - "Advance through buffer, marking read and archiving. + "Advance through thread, marking read and archiving. This command is intended to be one of the simplest ways to process a thread of email. It does the following: @@ -780,7 +773,7 @@ which this thread was originally shown." (let ((doc (documentation symbol))) (if doc (with-temp-buffer - (insert (documentation symbol)) + (insert (documentation symbol t)) (goto-char (point-min)) (let ((beg (point))) (end-of-line) @@ -835,7 +828,7 @@ For a mouse binding, return nil." (interactive) (let ((mode major-mode)) (with-help-window (help-buffer) - (princ (notmuch-substitute-command-keys (documentation mode t)))))) + (princ (substitute-command-keys (notmuch-substitute-command-keys (documentation mode t))))))) ;;;###autoload (defun notmuch-show-mode () @@ -845,22 +838,28 @@ This buffer contains the results of the \"notmuch show\" command for displaying a single thread of email from your email archives. By default, various components of email messages, (citations, -signatures, already-read messages), are invisible to help you -focus on the most important things, (new text from unread -messages). See the various commands below for toggling the -visibility of hidden components. +signatures, already-read messages), are hidden. You can make +these parts visible by clicking with the mouse button or by +pressing RET after positioning the cursor on a hidden part, (for +which \\[notmuch-show-next-button] and \\[notmuch-show-previous-button] are helpful). -The `notmuch-show-next-message' and -`notmuch-show-previous-message' commands, (bound to 'n' and 'p by -default), allow you to navigate to the next and previous -messages. Each time you navigate away from a message with -`notmuch-show-next-message' the current message will have its -\"unread\" tag removed. +Reading the thread sequentially is well-supported by pressing +\\[notmuch-show-advance-marking-read-and-archiving]. This will scroll the current message (if necessary), +advance to the next message, or advance to the next thread (if +already on the last message of a thread). As each message is +scrolled away its \"unread\" tag will be removed, and as each +thread is scrolled away the \"inbox\" tag will be removed from +each message in the thread. -You can add or remove tags from the current message with '+' and -'-'. You can also archive all messages in the current -view, (remove the \"inbox\" tag from each), with -`notmuch-show-archive-thread' (bound to 'a' by default). +Other commands are available to read or manipulate the thread more +selectively, (such as '\\[notmuch-show-next-message]' and '\\[notmuch-show-previous-message]' to advance to messages without +removing any tags, and '\\[notmuch-show-archive-thread]' to archive an entire thread without +scrolling through with \\[notmuch-show-advance-marking-read-and-archiving]). + +You can add or remove arbitary tags from the current message with +'\\[notmuch-show-add-tag]' or '\\[notmuch-show-remove-tag]'. + +All currently available key bindings: \\{notmuch-show-mode-map}" (interactive) From 86992aeb857b58c16440e6d890b68ee9b3c1a55f Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 22:43:14 -0800 Subject: [PATCH 11/74] notmuch.el: Clean up documentation of notmuch-folder-mode-map commands. Again, ensuring we have standalone first-line documentation strings, and overriding builtin commands to add our own documentation strings to them. --- notmuch.el | 58 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/notmuch.el b/notmuch.el index a8e523d5..72224742 100644 --- a/notmuch.el +++ b/notmuch.el @@ -1333,16 +1333,17 @@ current search results AND that are tagged with the given tag." (defvar notmuch-folder-mode-map (let ((map (make-sparse-keymap))) - (define-key map "n" 'next-line) - (define-key map "p" 'previous-line) + (define-key map "?" 'notmuch-help) (define-key map "x" 'kill-this-buffer) (define-key map "q" 'kill-this-buffer) - (define-key map "s" 'notmuch-search) - (define-key map (kbd "RET") 'notmuch-folder-show-search) - (define-key map "<" 'beginning-of-buffer) + (define-key map ">" 'notmuch-folder-last) + (define-key map "<" 'notmuch-folder-first) (define-key map "=" 'notmuch-folder) - (define-key map "?" 'notmuch-help) + (define-key map "s" 'notmuch-search) (define-key map [mouse-1] 'notmuch-folder-show-search) + (define-key map (kbd "RET") 'notmuch-folder-show-search) + (define-key map "p" 'notmuch-folder-previous) + (define-key map "n" 'notmuch-folder-next) map) "Keymap for \"notmuch folder\" buffers.") @@ -1356,12 +1357,26 @@ current search results AND that are tagged with the given tag." (defun notmuch-folder-mode () "Major mode for showing notmuch 'folders'. -This buffer contains a list of messages counts returned by a -customizable set of searches of your email archives. Each line -in the buffer shows the search terms and the resulting message count. +This buffer contains a list of message counts returned by a +customizable set of searches of your email archives. Each line in +the buffer shows the name of a saved search and the resulting +message count. Pressing RET on any line opens a search window containing the -results for the search terms in that line. +results for the saved search on that line. + +Here is an example of how the search list could be +customized, (the following text would be placed in your ~/.emacs +file): + +(setq notmuch-folders '((\"inbox\" . \"tag:inbox\") + (\"unread\" . \"tag:inbox AND tag:unread\") + (\"notmuch\" . \"tag:inbox AND to:notmuchmail.org\"))) + +Of course, you can have any number of folders, each configured +with any supported search terms (see \"notmuch help search-terms\"). + +Currently available key bindings: \\{notmuch-folder-mode-map}" (interactive) @@ -1373,6 +1388,29 @@ results for the search terms in that line. mode-name "notmuch-folder") (setq buffer-read-only t)) +(defun notmuch-folder-next () + "Select the next folder in the list." + (interactive) + (forward-line 1) + (if (eobp) + (forward-line -1))) + +(defun notmuch-folder-previous () + "Select the previous folder in the list." + (interactive) + (forward-line -1)) + +(defun notmuch-folder-first () + "Select the first folder in the list." + (interactive) + (goto-char (point-min))) + +(defun notmuch-folder-last () + "Select the last folder in the list." + (interactive) + (goto-char (point-max)) + (forward-line -1)) + (defun notmuch-folder-add (folders) (if folders (let ((name (car (car folders))) From e9443aeafc0bdeb0d11fa44ee2ad523fb019281e Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 22:47:10 -0800 Subject: [PATCH 12/74] notmuch.el: Make documentation of notmuch-search-mode dynamic. Previously, we had some hard-coded keybindings mentioned in the introductory paragraphs of the documentation for notmuch-search-mode. Now, we take advantage of the substitute-command-keys functionality to produce the same text by default, but to dynamically generate the correct text in the face of the user customizing the keybindings. --- notmuch.el | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/notmuch.el b/notmuch.el index 72224742..a6b71b77 100644 --- a/notmuch.el +++ b/notmuch.el @@ -1049,15 +1049,15 @@ number of matched messages and total messages in the thread, participants in the thread, a representative subject line, and any tags). -By default, pressing RET on any line displays that thread. The -'+' and '-' keys can be used to add or remove tags from a -thread. The 'a' key is a convenience key for archiving a -thread (removing the \"inbox\" tag). The '*' key can be used to -add or remove a tag from all threads in the current buffer. +Pressing \\[notmuch-search-show-thread] on any line displays that thread. The '\\[notmuch-search-add-tag]' and '\\[notmuch-search-remove-tag]' +keys can be used to add or remove tags from a thread. The '\\[notmuch-search-archive-thread]' key +is a convenience for archiving a thread (removing the \"inbox\" +tag). The '\\[notmuch-search-operate-all]' key can be used to add or remove a tag from all +threads in the current buffer. -Other useful commands are 'f' for filtering the current search -based on an additional query string, 't' for filtering to include -only messages with a given tag, and 's' to execute a new, global +Other useful commands are '\\[notmuch-search-filter]' for filtering the current search +based on an additional query string, '\\[notmuch-search-filter-by-tag]' for filtering to include +only messages with a given tag, and '\\[notmuch-search]' to execute a new, global search. Complete list of currently available key bindings: From 9e6ee30cbec3e24b04c1774b398e56858fa206e7 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 23:02:10 -0800 Subject: [PATCH 13/74] notmuch.el: Make notmuch-help use a full-screen window. Our documentation is long enough that I think it will be more useful to use an entire window for it (which is easily dismissed with 'q'). This is also kinder for a user not well-initiated with emacs, for whom the multi-window help can be confusing. --- notmuch.el | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/notmuch.el b/notmuch.el index a6b71b77..118c0ee7 100644 --- a/notmuch.el +++ b/notmuch.el @@ -826,9 +826,13 @@ For a mouse binding, return nil." (defun notmuch-help () "Display help for the current notmuch mode." (interactive) - (let ((mode major-mode)) - (with-help-window (help-buffer) - (princ (substitute-command-keys (notmuch-substitute-command-keys (documentation mode t))))))) + (let* ((mode major-mode) + (doc (substitute-command-keys (notmuch-substitute-command-keys (documentation mode t))))) + (with-current-buffer (generate-new-buffer "*notmuch-help*") + (insert doc) + (goto-char (point-min)) + (set-buffer-modified-p nil) + (view-buffer (current-buffer) 'kill-buffer-if-not-modified)))) ;;;###autoload (defun notmuch-show-mode () From 9ec9662ec74e1ed2f569d77008324d2a272749ae Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 23:05:32 -0800 Subject: [PATCH 14/74] notmuch.el: Avoid calling next/previous-line non-interactively. Emacs always complains if we use these from lisp code. --- notmuch.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/notmuch.el b/notmuch.el index 118c0ee7..28ef5c6b 100644 --- a/notmuch.el +++ b/notmuch.el @@ -158,7 +158,7 @@ Unlike builtin `next-line' this version accepts no arguments." By advancing forward until reaching a visible character. -Unlike builtin `next-line' this version accepts no arguments." +Unlike builtin `previous-line' this version accepts no arguments." (interactive) (set 'this-command 'previous-line) (call-interactively 'previous-line) @@ -1007,12 +1007,12 @@ thread from that buffer can be show when done with this one)." (defun notmuch-search-next-thread () "Select the next thread in the search results." (interactive) - (next-line)) + (forward-line 1)) (defun notmuch-search-previous-thread () "Select the previous thread in the search results." (interactive) - (previous-line)) + (forward-line -1)) (defun notmuch-search-last-thread () "Select the last thread in the search results." From a708ea627ea89f69ffc799bc2428edd389c7013a Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 23:09:08 -0800 Subject: [PATCH 15/74] notmuch.el: Avoid warning about referencing free variable `button'. I'm not even sure how the previous code worked at all---it seems clear it was supposed to be using `cite-button' rather than `button'. --- notmuch.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notmuch.el b/notmuch.el index 28ef5c6b..94a63844 100644 --- a/notmuch.el +++ b/notmuch.el @@ -545,7 +545,7 @@ which this thread was originally shown." (goto-char (button-start (previous-button (point))))) (defun notmuch-toggle-invisible-action (cite-button) - (let ((invis-spec (button-get button 'invisibility-spec))) + (let ((invis-spec (button-get cite-button 'invisibility-spec))) (if (invisible-p invis-spec) (remove-from-invisibility-spec invis-spec) (add-to-invisibility-spec invis-spec) From 7a6394257722c81dd47adefb172c8df2ac898973 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 23:14:11 -0800 Subject: [PATCH 16/74] notmuch.el: Use let to avoid assigning to a free variable. The dynamic scoping of emacs lisp is such that we never want to assign to any variable unless it's something we've defined with `defvar' or else something we're using locally via `let'. --- notmuch.el | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/notmuch.el b/notmuch.el index 94a63844..e605d9d2 100644 --- a/notmuch.el +++ b/notmuch.el @@ -1081,12 +1081,11 @@ Complete list of currently available key bindings: (if (not notmuch-tag-face-alist) (add-to-list 'notmuch-search-font-lock-keywords (list "(\\([^)]*\\))$" '(1 'notmuch-tag-face))) - (progn - (setq notmuch-search-tags (mapcar 'car notmuch-tag-face-alist)) - (loop for notmuch-search-tag in notmuch-search-tags - do (add-to-list 'notmuch-search-font-lock-keywords (list - (concat "([^)]*\\(" notmuch-search-tag "\\)[^)]*)$") - `(1 ,(cdr (assoc notmuch-search-tag notmuch-tag-face-alist)))))))) + (let ((notmuch-search-tags (mapcar 'car notmuch-tag-face-alist))) + (loop for notmuch-search-tag in notmuch-search-tags + do (add-to-list 'notmuch-search-font-lock-keywords (list + (concat "([^)]*\\(" notmuch-search-tag "\\)[^)]*)$") + `(1 ,(cdr (assoc notmuch-search-tag notmuch-tag-face-alist)))))))) (set (make-local-variable 'font-lock-defaults) '(notmuch-search-font-lock-keywords t))) From 55559ea409ad8df367f13752430244b7087dcd23 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 30 Nov 2009 23:21:04 -0800 Subject: [PATCH 17/74] notmuch.el: Make 'x' and 'X' in show-mode archive the current thread. This makes these keys different than 'q' in this mode, (where 'x' and 'q' are identical in all of the other modes currently). The idea here is to make it easier to do non-linear reading of messages, (such as when poking in to read just one or two threads from a search result that returned many threads). --- notmuch.el | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/notmuch.el b/notmuch.el index e605d9d2..25096513 100644 --- a/notmuch.el +++ b/notmuch.el @@ -55,7 +55,6 @@ (let ((map (make-sparse-keymap))) (define-key map "?" 'notmuch-help) (define-key map "q" 'kill-this-buffer) - (define-key map "x" 'kill-this-buffer) (define-key map (kbd "C-p") 'notmuch-show-previous-line) (define-key map (kbd "C-n") 'notmuch-show-next-line) (define-key map (kbd "M-TAB") 'notmuch-show-previous-button) @@ -70,6 +69,8 @@ (define-key map "v" 'notmuch-show-view-all-mime-parts) (define-key map "-" 'notmuch-show-remove-tag) (define-key map "+" 'notmuch-show-add-tag) + (define-key map "X" 'notmuch-show-mark-read-then-archive-then-exit) + (define-key map "x" 'notmuch-show-archive-thread-then-exit) (define-key map "A" 'notmuch-show-mark-read-then-archive-thread) (define-key map "a" 'notmuch-show-archive-thread) (define-key map "p" 'notmuch-show-previous-message) @@ -273,6 +274,18 @@ buffer." (interactive) (notmuch-show-archive-thread-maybe-mark-read nil)) +(defun notmuch-show-archive-thread-then-exit () + "Archive each message in thread, then exit back to search results." + (interactive) + (notmuch-show-archive-thread) + (kill-this-buffer)) + +(defun notmuch-show-mark-read-then-archive-then-exit () + "Remove unread tags from thread, then archive and exit to search results." + (interactive) + (notmuch-show-mark-read-then-archive-thread) + (kill-this-buffer)) + (defun notmuch-show-view-raw-message () "View the raw email of the current message." (interactive) From 5f0b2ece161b16321792d9ff2f76bcc33a3b6b42 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Mon, 23 Nov 2009 08:03:35 +0200 Subject: [PATCH 18/74] Avoid compiler warnings due to ignored write return values Glibc (at least) provides the warn_unused_result attribute on write, (if optimizing and _FORTIFY_SOURCE is defined). So we explicitly ignore the return value in our signal handler, where we couldn't do anything anyway. Compile with: make CFLAGS="-O -D_FORTIFY_SOURCE" before this commit to see the warning. --- notmuch-new.c | 4 +++- notmuch-tag.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/notmuch-new.c b/notmuch-new.c index f58a384b..9d206167 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -35,8 +35,10 @@ static volatile sig_atomic_t interrupted; static void handle_sigint (unused (int sig)) { + ssize_t ignored; static char msg[] = "Stopping... \n"; - write(2, msg, sizeof(msg)-1); + + ignored = write(2, msg, sizeof(msg)-1); interrupted = 1; } diff --git a/notmuch-tag.c b/notmuch-tag.c index 07cb8c5f..00588a11 100644 --- a/notmuch-tag.c +++ b/notmuch-tag.c @@ -25,8 +25,10 @@ static volatile sig_atomic_t interrupted; static void handle_sigint (unused (int sig)) { + ssize_t ignored; + static char msg[] = "Stopping... \n"; - write(2, msg, sizeof(msg)-1); + ignored = write(2, msg, sizeof(msg)-1); interrupted = 1; } From eb0cf86c7a9d5cda464d4d36a9cac66f26b5529d Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 08:06:09 -0800 Subject: [PATCH 19/74] notmuch setup: Exit if EOF is encountered at any prompt. If the user is explicitly providing EOF, then terminating the program is the most likely desired thing to do. This also avoids undefined behavior from continuing with an uninitialized response after ignoring the return value of getline(). --- notmuch-setup.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/notmuch-setup.c b/notmuch-setup.c index 5ec176d3..622bbaa6 100644 --- a/notmuch-setup.c +++ b/notmuch-setup.c @@ -100,12 +100,15 @@ notmuch_setup_command (unused (void *ctx), unsigned int i; int is_new; -#define prompt(format, ...) \ - do { \ - printf (format, ##__VA_ARGS__); \ - fflush (stdout); \ - getline (&response, &response_size, stdin); \ - chomp_newline (response); \ +#define prompt(format, ...) \ + do { \ + printf (format, ##__VA_ARGS__); \ + fflush (stdout); \ + if (getline (&response, &response_size, stdin) < 0) { \ + printf ("Exiting.\n"); \ + exit (1); \ + } \ + chomp_newline (response); \ } while (0) config = notmuch_config_open (ctx, NULL, &is_new); From 98b93a7d5ad3713a7c408e497065cd0a931d90c7 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 08:34:09 -0800 Subject: [PATCH 20/74] Remove Makefile.config from the repository. Instead of shipping a default version, we now add a rule to automatically run configure if necessary to create Makefile.config. --- .gitignore | 1 + Makefile | 3 +++ Makefile.config | 3 --- 3 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 Makefile.config diff --git a/.gitignore b/.gitignore index 8794354e..efa98fbb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +Makefile.config TAGS tags *cscope* diff --git a/Makefile b/Makefile index 2cd1b1ba..ae0f9912 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,9 @@ include Makefile.local include lib/Makefile.local # And get user settings from the output of configure +Makefile.config: configure + ./configure + include Makefile.config # The user has not set any verbosity, default to quiet mode and inform the diff --git a/Makefile.config b/Makefile.config deleted file mode 100644 index ddc74365..00000000 --- a/Makefile.config +++ /dev/null @@ -1,3 +0,0 @@ -prefix = /usr/local -bash_completion_dir = /etc/bash_completion.d -CFLAGS += -DHAVE_VALGRIND From d4a765b63e70254273c0fd5673056ad2a456a96c Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 08:40:45 -0800 Subject: [PATCH 21/74] configure: Clean up the introductory message a bit. Eliminate a typo or two, and mention that the user can edit Makefile.config if necessary. --- configure | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/configure b/configure index e55f067e..b1ac741d 100755 --- a/configure +++ b/configure @@ -7,14 +7,16 @@ We hope that the process of building and installing notmuch is quick and smooth so that you can soon be reading and processing your email more efficiently than ever. -If anything goes wrong in this process, please do as much as you can -to figure out what could be different on your machine compared to -those of the notmuch developers. Then, please email those details to -the Notmuch list (notmuch@notmuchmail.org) so that we can hopefully make -future versions of notmuch easier for you to use. +If anything goes wrong in the configure process, you can override any +decisions it makes by manually editing the Makefile.config file that +it creates. Also please do as much as you can to figure out what could +be different on your machine compared to those of the notmuch +developers. Then, please email those details to the Notmuch list +(notmuch@notmuchmail.org) so that we can hopefully make future +versions of notmuch easier for you to use. -We'll now investigate your system to find verify that various software -components that notmuch relies on are available. +We'll now investigate your system to verify that all required +dependencies are available: EOF From 72edf82cd0d102405e962ea266eb00f5eb2d1f3c Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 10:07:14 -0800 Subject: [PATCH 22/74] configure: Fix pkg-config warning to not refer to non-existent variables. We used to have NOTMUCH_CFLAGS and NOTMUCH_LDFLAGS in the Makefile, but we don't anymore, so don't refer to them. --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index b1ac741d..64816e0f 100755 --- a/configure +++ b/configure @@ -106,8 +106,8 @@ with a command such as: sudo apt-get install pkg-config But if pkg-config is not available for your system, then you will need -to manually edit the notmuch Makefile to set NOTMUCH_CFLAGS and -NOTMUCH_LDFLAGS to the correct values without calling pkg-config. +to manually edit the notmuch Makefile to set the variables such as +CFLAGS and LDFLAGS to the correct values without calling pkg-config. EOF fi From 7c2c26bc4ec5fdab5c6fa72ea325d846b46929e3 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 10:14:00 -0800 Subject: [PATCH 23/74] Makefile: Add new "install-bash" target for bash completion support It was problematic to have this in "make install" since it would unconditionally try to install to /etc, (even if a non-privileged user was attempting an install to a prefix in the user's home directory, for example). --- Makefile | 2 ++ Makefile.local | 10 ++++++---- configure | 1 - 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index ae0f9912..e42584b2 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,8 @@ ifeq ($(emacs_lispdir),) emacs_lispdir = $(prefix)/share/emacs/site-lisp endif +bash_completion_dir = /etc/bash_completion.d + all_deps = Makefile Makefile.local Makefile.config \ lib/Makefile lib/Makefile.local diff --git a/Makefile.local b/Makefile.local index 1744747a..aff7d2c0 100644 --- a/Makefile.local +++ b/Makefile.local @@ -29,15 +29,12 @@ notmuch.1.gz: notmuch.1 $(call quiet,gzip) --stdout $^ > $@ install: all notmuch.1.gz - for d in $(DESTDIR)$(prefix)/bin/ $(DESTDIR)$(prefix)/share/man/man1 \ - $(DESTDIR)$(bash_completion_dir) ; \ + for d in $(DESTDIR)$(prefix)/bin/ $(DESTDIR)$(prefix)/share/man/man1 ; \ do \ install -d $$d ; \ done ; install notmuch $(DESTDIR)$(prefix)/bin/ install -m0644 notmuch.1.gz $(DESTDIR)$(prefix)/share/man/man1/ - install contrib/notmuch-completion.bash \ - $(DESTDIR)$(bash_completion_dir)/notmuch install-emacs: install emacs for d in $(DESTDIR)/$(emacs_lispdir) ; \ @@ -47,5 +44,10 @@ install-emacs: install emacs install -m0644 notmuch.el $(DESTDIR)$(emacs_lispdir) install -m0644 notmuch.elc $(DESTDIR)$(emacs_lispdir) +install-bash: + install -d $(DESTDIR)$(bash_completion_dir) + install contrib/notmuch-completion.bash \ + $(DESTDIR)$(bash_completion_dir)/notmuch + SRCS := $(SRCS) $(notmuch_client_srcs) CLEAN := $(CLEAN) notmuch $(notmuch_client_modules) notmuch.elc notmuch.1.gz diff --git a/configure b/configure index 64816e0f..140711f3 100755 --- a/configure +++ b/configure @@ -133,6 +133,5 @@ EOF # construct the Makefile.config cat > Makefile.config < Date: Tue, 1 Dec 2009 11:39:30 -0800 Subject: [PATCH 24/74] configure: Use printf to achieve result of "echo -n". We had avoided using "echo -n" originally for portability concerns, and instead just printed the same string in both conditions, (and also printed the string late if any check took long). The word is that printf is quite portable, so we use that instead. --- configure | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 140711f3..2ceda74b 100755 --- a/configure +++ b/configure @@ -28,38 +28,42 @@ else have_pkg_config=0 fi +printf "Checking for Xapian development files... " if xapian-config --version > /dev/null 2>&1; then - echo "Checking for Xapian development files... Yes." + printf "Yes.\n" have_xapian=1 else - echo "Checking for Xapian development files... No." + printf "No.\n" have_xapian=0 errors=$((errors + 1)) fi +printf "Checking for GMime 2.4 development files... " if pkg-config --modversion gmime-2.4 > /dev/null 2>&1; then - echo "Checking for GMime 2.4 development files... Yes." + printf "Yes.\n" have_gmime=1 else - echo "Checking for GMime 2.4 development files... No." + printf "No.\n" have_gmime=0 errors=$((errors + 1)) fi +printf "Checking for talloc development files... " if pkg-config --modversion talloc > /dev/null 2>&1; then - echo "Checking for talloc development files... Yes." + printf "Yes.\n" have_talloc=1 else - echo "Checking for talloc development files... No." + printf "No.\n" have_talloc=0 errors=$((errors + 1)) fi +printf "Checking for valgrind development files... " if pkg-config --modversion valgrind > /dev/null 2>&1; then - echo "Checking for valgrind development files... Yes." + printf "Yes.\n" have_valgrind=-DHAVE_VALGRIND else - echo "Checking for valgrind development files... No." + printf "No (but that's fine).\n" have_valgrind= fi From e5316b320a51915fc1dbdd8724643931cd03327f Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 12:40:13 -0800 Subject: [PATCH 25/74] lib/index: Fix memory leak for email addresses without names. We carefully noted the fact that we had locally allocated the string here, but then we neglected to free it. Switch to talloc instead which makes it easier to get the behavior we want. It's simpler since we can just call talloc_free unconditionally, without having to track the state of whether we allocated the storage for name or not. --- lib/index.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/index.cc b/lib/index.cc index 80df64bf..125fa6c9 100644 --- a/lib/index.cc +++ b/lib/index.cc @@ -31,7 +31,7 @@ _index_address_mailbox (notmuch_message_t *message, { InternetAddressMailbox *mailbox = INTERNET_ADDRESS_MAILBOX (address); const char *name, *addr; - int own_name = 0; + void *local = talloc_new (NULL); name = internet_address_get_name (address); addr = internet_address_mailbox_get_addr (mailbox); @@ -42,16 +42,16 @@ _index_address_mailbox (notmuch_message_t *message, const char *at; at = strchr (addr, '@'); - if (at) { - name = strndup (addr, at - addr); - own_name = 1; - } + if (at) + name = talloc_strndup (local, addr, at - addr); } if (name) _notmuch_message_gen_terms (message, prefix_name, name); if (addr) _notmuch_message_gen_terms (message, prefix_name, addr); + + talloc_free (local); } static void From 8b445212e46a194b59edbd6857449430fe460165 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 12:51:39 -0800 Subject: [PATCH 26/74] xutil: Implement xstrndup without relying on strndup. Since we need to do this for portability, (some systems don't have a strndup function), we might as well do it unconditionally. There's almost no disadvantage to doing so, and this has the advantages of not requiring a configure-time check nor having two different implementations, one of which would often be less tested. --- TODO | 2 -- lib/xutil.c | 8 ++++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/TODO b/TODO index 1b8fb42a..87f84a42 100644 --- a/TODO +++ b/TODO @@ -41,8 +41,6 @@ Portability ----------- Fix configure script to test each compiler warning we want to use. -Implement strndup locally (or call talloc_strndup instead). - Implement getline locally, (look at gnulib). Completion diff --git a/lib/xutil.c b/lib/xutil.c index 6fa5eb0d..268225b8 100644 --- a/lib/xutil.c +++ b/lib/xutil.c @@ -18,7 +18,6 @@ * Author: Carl Worth */ -#define _GNU_SOURCE /* For strndup */ #include "notmuch-private.h" #include @@ -84,11 +83,16 @@ xstrndup (const char *s, size_t n) { char *ret; - ret = strndup (s, n); + if (strlen (s) <= n) + n = strlen (s); + + ret = malloc (n + 1); if (ret == NULL) { fprintf (stderr, "Out of memory.\n"); exit (1); } + memcpy (ret, s, n); + ret[n] = '\0'; return ret; } From 96c9109d94ddd985994cb431080d2823688b0ed6 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 14:06:41 -0800 Subject: [PATCH 27/74] compat: Add implementation of getline from gnulib. These were copied from the gnulib git repository as of: commit 563c779682040ed4b89c9b4bbe428dcd8157c90a They come under the GNU GPL v3 (or later) exactly as notmuch is licensed. --- compat/getdelim.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++ compat/getline.c | 29 ++++++++++ 2 files changed, 162 insertions(+) create mode 100644 compat/getdelim.c create mode 100644 compat/getline.c diff --git a/compat/getdelim.c b/compat/getdelim.c new file mode 100644 index 00000000..b74e5b53 --- /dev/null +++ b/compat/getdelim.c @@ -0,0 +1,133 @@ +/* getdelim.c --- Implementation of replacement getdelim function. + Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005, 2006, 2007, + 2008, 2009 Free Software Foundation, Inc. + + This program 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, or (at + your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* Ported from glibc by Simon Josefsson. */ + +#include + +#include + +#include +#include +#include +#include + +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +#endif + +#if USE_UNLOCKED_IO +# include "unlocked-io.h" +# define getc_maybe_unlocked(fp) getc(fp) +#elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED +# undef flockfile +# undef funlockfile +# define flockfile(x) ((void) 0) +# define funlockfile(x) ((void) 0) +# define getc_maybe_unlocked(fp) getc(fp) +#else +# define getc_maybe_unlocked(fp) getc_unlocked(fp) +#endif + +/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and + NUL-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'ed as + necessary. Returns the number of characters read (not including + the null terminator), or -1 on error or EOF. */ + +ssize_t +getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) +{ + ssize_t result; + size_t cur_len = 0; + + if (lineptr == NULL || n == NULL || fp == NULL) + { + errno = EINVAL; + return -1; + } + + flockfile (fp); + + if (*lineptr == NULL || *n == 0) + { + char *new_lineptr; + *n = 120; + new_lineptr = (char *) realloc (*lineptr, *n); + if (new_lineptr == NULL) + { + result = -1; + goto unlock_return; + } + *lineptr = new_lineptr; + } + + for (;;) + { + int i; + + i = getc_maybe_unlocked (fp); + if (i == EOF) + { + result = -1; + break; + } + + /* Make enough space for len+1 (for final NUL) bytes. */ + if (cur_len + 1 >= *n) + { + size_t needed_max = + SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; + size_t needed = 2 * *n + 1; /* Be generous. */ + char *new_lineptr; + + if (needed_max < needed) + needed = needed_max; + if (cur_len + 1 >= needed) + { + result = -1; + errno = EOVERFLOW; + goto unlock_return; + } + + new_lineptr = (char *) realloc (*lineptr, needed); + if (new_lineptr == NULL) + { + result = -1; + goto unlock_return; + } + + *lineptr = new_lineptr; + *n = needed; + } + + (*lineptr)[cur_len] = i; + cur_len++; + + if (i == delimiter) + break; + } + (*lineptr)[cur_len] = '\0'; + result = cur_len ? cur_len : result; + + unlock_return: + funlockfile (fp); /* doesn't set errno */ + + return result; +} diff --git a/compat/getline.c b/compat/getline.c new file mode 100644 index 00000000..a653648f --- /dev/null +++ b/compat/getline.c @@ -0,0 +1,29 @@ +/* getline.c --- Implementation of replacement getline function. + Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. + + This program 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, or (at + your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* Written by Simon Josefsson. */ + +#include + +#include + +ssize_t +getline (char **lineptr, size_t *n, FILE *stream) +{ + return getdelim (lineptr, n, '\n', stream); +} From c04a432ef201e090a8711b80ad7bb175b9719fa1 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 14:09:12 -0800 Subject: [PATCH 28/74] compat: Change includes from config.h to compat.h. We may switch to using an autoconf-like config.h, but we're not doing that just yet. --- compat/compat.h | 41 +++++++++++++++++++++++++++++++++++++++++ compat/getdelim.c | 2 +- compat/getline.c | 2 +- 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 compat/compat.h diff --git a/compat/compat.h b/compat/compat.h new file mode 100644 index 00000000..d639e0f9 --- /dev/null +++ b/compat/compat.h @@ -0,0 +1,41 @@ +/* notmuch - Not much of an email library, (just index and search) + * + * Copyright © 2009 Carl Worth + * + * This program 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. + * + * This program 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 this program. If not, see http://www.gnu.org/licenses/ . + * + * Author: Carl Worth + */ + +/* This header file defines functions that will only be conditionally + * compiled for compatibility on systems that don't provide their own + * implementations of the functions. + */ + +#ifndef NOTMUCH_COMPAT_H +#define NOTMUCH_COMPAT_H + +#if !HAVE_GETLINE +#include +#include + +ssize_t +getline (char **lineptr, size_t *n, FILE *stream); + +ssize_t +getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp); + +#endif /* !HAVE_GETLINE */ + +#endif /* NOTMUCH_COMPAT_H */ diff --git a/compat/getdelim.c b/compat/getdelim.c index b74e5b53..84bef87b 100644 --- a/compat/getdelim.c +++ b/compat/getdelim.c @@ -19,7 +19,7 @@ /* Ported from glibc by Simon Josefsson. */ -#include +#include "compat.h" #include diff --git a/compat/getline.c b/compat/getline.c index a653648f..222e0f6c 100644 --- a/compat/getline.c +++ b/compat/getline.c @@ -18,7 +18,7 @@ /* Written by Simon Josefsson. */ -#include +#include "compat.h" #include From 7fd7611b23ad33ed8bb7db44916cb03bbc2c47c1 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 14:12:01 -0800 Subject: [PATCH 29/74] compat/getdelim: Silence a warning about mixing of signed/unsigned. If the length is ever so large as to overflow, then we'll end up returning a negative value (which indicates an error anyway). --- compat/getdelim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compat/getdelim.c b/compat/getdelim.c index 84bef87b..1bedef7c 100644 --- a/compat/getdelim.c +++ b/compat/getdelim.c @@ -124,7 +124,7 @@ getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) break; } (*lineptr)[cur_len] = '\0'; - result = cur_len ? cur_len : result; + result = cur_len ? (ssize_t) cur_len : result; unlock_return: funlockfile (fp); /* doesn't set errno */ From 880b21a097104bee5f50a444c5130695d143fd8a Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 15:23:25 -0800 Subject: [PATCH 30/74] Makefile: Incorporate getline implementation into the build. It's unconditional for a very short time. We expect to soon be building it only if necessary. --- Makefile | 6 ++++-- Makefile.local | 3 +-- TODO | 2 -- compat/Makefile | 5 +++++ compat/Makefile.local | 8 ++++++++ lib/notmuch-private.h | 2 ++ notmuch-client.h | 3 ++- 7 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 compat/Makefile create mode 100644 compat/Makefile.local diff --git a/Makefile b/Makefile index e42584b2..c0b1b3fa 100644 --- a/Makefile +++ b/Makefile @@ -32,9 +32,11 @@ override LDFLAGS += \ $(shell pkg-config --libs glib-2.0 gmime-2.4 talloc) \ $(shell xapian-config --libs) -# Include our local Makefile.local first so that its first target is default -include Makefile.local +all: notmuch notmuch.1.gz + include lib/Makefile.local +include compat/Makefile.local +include Makefile.local # And get user settings from the output of configure Makefile.config: configure diff --git a/Makefile.local b/Makefile.local index aff7d2c0..4b29ad83 100644 --- a/Makefile.local +++ b/Makefile.local @@ -1,8 +1,7 @@ -all: notmuch notmuch.1.gz - emacs: notmuch.elc notmuch_client_srcs = \ + $(notmuch_compat_srcs) \ debugger.c \ gmime-filter-reply.c \ notmuch.c \ diff --git a/TODO b/TODO index 87f84a42..578d833c 100644 --- a/TODO +++ b/TODO @@ -41,8 +41,6 @@ Portability ----------- Fix configure script to test each compiler warning we want to use. -Implement getline locally, (look at gnulib). - Completion ---------- Fix bash completion to complete multiple search options (both --first diff --git a/compat/Makefile b/compat/Makefile new file mode 100644 index 00000000..9a29ffcf --- /dev/null +++ b/compat/Makefile @@ -0,0 +1,5 @@ +all: + $(MAKE) -C .. all + +clean: + $(MAKE) -C .. clean diff --git a/compat/Makefile.local b/compat/Makefile.local new file mode 100644 index 00000000..ccc59aef --- /dev/null +++ b/compat/Makefile.local @@ -0,0 +1,8 @@ +dir=compat +extra_cflags += -I$(dir) + +notmuch_compat_srcs = + +ifneq ($(HAVE_GETLINE),1) +notmuch_compat_srcs += $(dir)/getline.c $(dir)/getdelim.c +endif diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index d3f9a4c4..d2678f06 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -26,6 +26,8 @@ #endif #include +#include "compat.h" + #include "notmuch.h" NOTMUCH_BEGIN_DECLS diff --git a/notmuch-client.h b/notmuch-client.h index 2888a6c8..50a30fed 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -21,12 +21,13 @@ #ifndef NOTMUCH_CLIENT_H #define NOTMUCH_CLIENT_H - #ifndef _GNU_SOURCE #define _GNU_SOURCE /* for getline */ #endif #include +#include "compat.h" + #include #include "notmuch.h" From 1682633f65061247d90129b73650593261eed892 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 15:52:44 -0800 Subject: [PATCH 31/74] configure: Fix valgrind check to take effect, and to work. We were missing an "override" directive in the assignment of CFLAGS within Makefile.config so it was actually having no effect. Then, we were also failing to get the proper include path for valgrind.h so it wouldn't have worked even it were having effect. Fix both problems. --- configure | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 2ceda74b..6b571977 100755 --- a/configure +++ b/configure @@ -61,10 +61,12 @@ fi printf "Checking for valgrind development files... " if pkg-config --modversion valgrind > /dev/null 2>&1; then printf "Yes.\n" - have_valgrind=-DHAVE_VALGRIND + have_valgrind=1 + valgrind_flags=$(pkg-config --cflags valgrind) else printf "No (but that's fine).\n" - have_valgrind= + have_valgrind=0 + valgrind_flags= fi if [ $errors -gt 0 ]; then @@ -137,5 +139,5 @@ EOF # construct the Makefile.config cat > Makefile.config < Date: Mon, 23 Nov 2009 12:14:15 -0600 Subject: [PATCH 32/74] Add test to configure script to detect getline Add a simple test to the configure script to detect getline. It's not important that the test run, just that it compiles and links without any errors. Signed-off-by: Jeffrey C. Ollie --- configure | 11 ++++++++++- getlinetest.c | 13 +++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 getlinetest.c diff --git a/configure b/configure index 6b571977..1b5f7e04 100755 --- a/configure +++ b/configure @@ -126,6 +126,15 @@ EOF exit 1 fi +if ! gcc -o getlinetest getlinetest.c > /dev/null 2>&1 +then + echo "Checking for getline... No." + getline=-Dgetline=_notmuch_getline +else + echo "Checking for getline... Yes." +fi +rm -f getlinetest + cat < Makefile.config < +#include + +int main() +{ + ssize_t count = 0; + size_t n = 0; + char **lineptr = NULL; + FILE *stream = NULL; + + count = getline(lineptr, &n, stream); +} From 650f6ac573ae6d08dbd2752fe58e670b28fee957 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 16:00:31 -0800 Subject: [PATCH 33/74] configure: Assimilate new getlinetest into recent configure conventions. We're now using printf to print what we're checking before we check. We're also making variables such as HAVE_GETLINE available to both make and to the C pre-processor. With this, the local getline implementation is now only compiled if not available on the system. --- Makefile | 11 ++++++----- configure | 11 +++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index c0b1b3fa..17be8b48 100644 --- a/Makefile +++ b/Makefile @@ -34,16 +34,17 @@ override LDFLAGS += \ all: notmuch notmuch.1.gz -include lib/Makefile.local -include compat/Makefile.local -include Makefile.local - -# And get user settings from the output of configure +# Before including any other Makefile fragments, get settings from the +# output of configure Makefile.config: configure ./configure include Makefile.config +include lib/Makefile.local +include compat/Makefile.local +include Makefile.local + # The user has not set any verbosity, default to quiet mode and inform the # user how to enable verbose compiles. ifeq ($(V),) diff --git a/configure b/configure index 1b5f7e04..bb1f0dbc 100755 --- a/configure +++ b/configure @@ -126,12 +126,14 @@ EOF exit 1 fi +printf "Checking for getline... " if ! gcc -o getlinetest getlinetest.c > /dev/null 2>&1 then - echo "Checking for getline... No." - getline=-Dgetline=_notmuch_getline + printf "No.\n" + have_getline=0 else - echo "Checking for getline... Yes." + printf "Yes.\n" + have_getline=1 fi rm -f getlinetest @@ -148,5 +150,6 @@ EOF # construct the Makefile.config cat > Makefile.config < Date: Tue, 1 Dec 2009 16:38:47 -0800 Subject: [PATCH 34/74] Makefile: Switch from echo to printf for better portability. Some systems have an echo implementation which doesn't know how to interpret a sequence of "\n". The word is that printf should be much more portable, so let's try that instead. --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 17be8b48..7a9e44c6 100644 --- a/Makefile +++ b/Makefile @@ -49,11 +49,11 @@ include Makefile.local # user how to enable verbose compiles. ifeq ($(V),) quiet_DOC := "Use \"$(MAKE) V=1\" to see the verbose compile lines.\n" -quiet = @echo $(quiet_DOC)$(eval quiet_DOC:=)" $1 $@"; $($1) +quiet = @printf $(quiet_DOC)$(eval quiet_DOC:=)" $1 $@\n"; $($1) endif # The user has explicitly enabled quiet compilation. ifeq ($(V),0) -quiet = @echo " $1 $@"; $($1) +quiet = @printf " $1 $@\n"; $($1) endif # Otherwise, print the full command line. quiet ?= $($1) From e806e723c8ac8f97a3f8ba0e0048708a8f5bb475 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 16:42:50 -0800 Subject: [PATCH 35/74] Makefile: Split warnings into two sets (WARN_CFLAGS and WARN_CXXFLAGS) Some C++ compilers complain about -Wmissing-declarations not being valid, so avoid passing it except when compiling a C file. --- Makefile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 7a9e44c6..6a2ecea5 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,9 @@ -# Default FLAGS, (can be overridden by user such as "make CFLAGS=-O2") -WARN_FLAGS=-Wall -Wextra -Wmissing-declarations -Wwrite-strings -Wswitch-enum +# Default FLAGS, (can be overridden by user such as "make CFLAGS=-g") CFLAGS=-O2 +WARN_CXXFLAGS=-Wall -Wextra -Wwrite-strings -Wswitch-enum +WARN_CFLAGS=$(WARN_CXXFLAGS) -Wmissing-declarations + # Additional programs that are used during the compilation process. EMACS ?= emacs # Lowercase to avoid clash with GZIP environment variable for passing @@ -25,8 +27,8 @@ all_deps = Makefile Makefile.local Makefile.config \ lib/Makefile lib/Makefile.local # Now smash together user's values with our extra values -override CFLAGS += $(WARN_FLAGS) $(extra_cflags) -override CXXFLAGS += $(WARN_FLAGS) $(extra_cflags) $(extra_cxxflags) +override CFLAGS += $(WARN_CFLAGS) $(extra_cflags) +override CXXFLAGS += $(WARN_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) override LDFLAGS += \ $(shell pkg-config --libs glib-2.0 gmime-2.4 talloc) \ From 1466e249e741e3ef907e8c48c2861742b676e255 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 16:46:21 -0800 Subject: [PATCH 36/74] getdelim: Silence a (bogus) compiler warning. Some compilers complain that result might be used uninitialized in this function. I believe such compilers simply aren't looking hard enough, but it's easy enough to silence them. --- compat/getdelim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compat/getdelim.c b/compat/getdelim.c index 1bedef7c..407f3d07 100644 --- a/compat/getdelim.c +++ b/compat/getdelim.c @@ -54,7 +54,7 @@ ssize_t getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) { - ssize_t result; + ssize_t result = -1; size_t cur_len = 0; if (lineptr == NULL || n == NULL || fp == NULL) From e93520f1091ba67bfad317cfa9a75c4097e28db9 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 16:56:39 -0800 Subject: [PATCH 37/74] configure: Move getlinetest.c down into config/have_getline.c. This keeps configure-related clutter out of the main directory, and also gives a more direct correlation between the name of the test and the feature being tested for. --- config/README | 5 +++++ config/have_getline.c | 13 +++++++++++++ configure | 10 +++++----- getlinetest.c | 13 ------------- 4 files changed, 23 insertions(+), 18 deletions(-) create mode 100644 config/README create mode 100644 config/have_getline.c delete mode 100644 getlinetest.c diff --git a/config/README b/config/README new file mode 100644 index 00000000..eabfe285 --- /dev/null +++ b/config/README @@ -0,0 +1,5 @@ +notmuch/config + +This directory consists of small programs used by the notmuch +configure script to test for the availability of certain system +features, (library functions, etc.). diff --git a/config/have_getline.c b/config/have_getline.c new file mode 100644 index 00000000..a8bcd17e --- /dev/null +++ b/config/have_getline.c @@ -0,0 +1,13 @@ +#define _GNU_SOURCE +#include +#include + +int main() +{ + ssize_t count = 0; + size_t n = 0; + char **lineptr = NULL; + FILE *stream = NULL; + + count = getline(lineptr, &n, stream); +} diff --git a/configure b/configure index bb1f0dbc..ef90a8ba 100755 --- a/configure +++ b/configure @@ -127,15 +127,15 @@ EOF fi printf "Checking for getline... " -if ! gcc -o getlinetest getlinetest.c > /dev/null 2>&1 +if gcc -o config/have_getline config/have_getline.c > /dev/null 2>&1 then - printf "No.\n" - have_getline=0 -else printf "Yes.\n" have_getline=1 +else + printf "No (will use our own instead).\n" + have_getline=0 fi -rm -f getlinetest +rm -f config/have_getline cat < -#include - -int main() -{ - ssize_t count = 0; - size_t n = 0; - char **lineptr = NULL; - FILE *stream = NULL; - - count = getline(lineptr, &n, stream); -} From 222ee87dfefdd85ddbd7f148d5636746919d4100 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 17:56:39 -0800 Subject: [PATCH 38/74] configure: Resolve all pkg-config flags at configure time. Previously, we were resolving these within the Makefile. This had the problem that if pkg-config was not present, the Makefile would still invoke it resulting in ugly errors before the configure script was even run, (which would finally present a kind error message about pkg-config not being present). --- Makefile | 18 +++--------------- configure | 21 ++++++++++++++++++--- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index 6a2ecea5..588f8538 100644 --- a/Makefile +++ b/Makefile @@ -10,30 +10,18 @@ EMACS ?= emacs # arguments to gzip. gzip = gzip -# Additional flags that we will append to whatever the user set. -# These aren't intended for the user to manipulate. -extra_cflags := $(shell pkg-config --cflags glib-2.0 gmime-2.4 talloc) -extra_cxxflags := $(shell xapian-config --cxxflags) - -emacs_lispdir := $(shell pkg-config emacs --variable sitepkglispdir) -# Hard-code if this system doesn't have an emacs.pc file -ifeq ($(emacs_lispdir),) - emacs_lispdir = $(prefix)/share/emacs/site-lisp -endif - bash_completion_dir = /etc/bash_completion.d all_deps = Makefile Makefile.local Makefile.config \ lib/Makefile lib/Makefile.local +extra_cflags := +extra_cxxflags := + # Now smash together user's values with our extra values override CFLAGS += $(WARN_CFLAGS) $(extra_cflags) override CXXFLAGS += $(WARN_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) -override LDFLAGS += \ - $(shell pkg-config --libs glib-2.0 gmime-2.4 talloc) \ - $(shell xapian-config --libs) - all: notmuch notmuch.1.gz # Before including any other Makefile fragments, get settings from the diff --git a/configure b/configure index ef90a8ba..97ee606f 100755 --- a/configure +++ b/configure @@ -32,6 +32,8 @@ printf "Checking for Xapian development files... " if xapian-config --version > /dev/null 2>&1; then printf "Yes.\n" have_xapian=1 + cxxflags="${cxxflags} $(xapian-config --cxxflags)" + ldflags="${ldflags} $(xapian-config --libs)" else printf "No.\n" have_xapian=0 @@ -42,6 +44,8 @@ printf "Checking for GMime 2.4 development files... " if pkg-config --modversion gmime-2.4 > /dev/null 2>&1; then printf "Yes.\n" have_gmime=1 + cflags="${cflags} $(pkg-config --cflags gmime-2.4)" + ldflags="${ldflags} $(pkg-config --libs gmime-2.4)" else printf "No.\n" have_gmime=0 @@ -52,9 +56,12 @@ printf "Checking for talloc development files... " if pkg-config --modversion talloc > /dev/null 2>&1; then printf "Yes.\n" have_talloc=1 + cflags="${cflags} $(pkg-config --cflags talloc)" + ldflags="${ldflags} $(pkg-config --libs talloc)" else printf "No.\n" have_talloc=0 + talloc_cflags= errors=$((errors + 1)) fi @@ -62,11 +69,16 @@ printf "Checking for valgrind development files... " if pkg-config --modversion valgrind > /dev/null 2>&1; then printf "Yes.\n" have_valgrind=1 - valgrind_flags=$(pkg-config --cflags valgrind) + cflags="${cflags} $(pkg-config --cflags valgrind)" else printf "No (but that's fine).\n" have_valgrind=0 - valgrind_flags= +fi + +if pkg-config --modversion emacs > /dev/null 2>&1; then + emacs_lispdir=$(pkg-config emacs --variable sitepkglispdir) +else + emacs_lispdir='$(prefix)/share/emacs/site-lisp' fi if [ $errors -gt 0 ]; then @@ -150,6 +162,9 @@ EOF # construct the Makefile.config cat > Makefile.config < Date: Tue, 1 Dec 2009 18:09:47 -0800 Subject: [PATCH 39/74] configure: Generate some documentation into Makefile.config. It's just not nice to auto-generate a file without helping out the poor user who gets stuck trying to figure out what went wrong. --- configure | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/configure b/configure index 97ee606f..92b6710f 100755 --- a/configure +++ b/configure @@ -161,9 +161,25 @@ EOF # construct the Makefile.config cat > Makefile.config < Date: Tue, 1 Dec 2009 18:13:43 -0800 Subject: [PATCH 40/74] configure: Clarify pkg-config warning now that Makefile does not invoke pkg-config. It's probably a bit more work to use this configure script without pkg-config, but it's at least possible, (and we could make it even easier if this becomes an important use case). --- configure | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/configure b/configure index 92b6710f..65411956 100755 --- a/configure +++ b/configure @@ -115,17 +115,17 @@ package names may be different, (such as "devel" in place of "dev"). EOF if [ $have_pkg_config -eq 0 ]; then cat < Date: Tue, 1 Dec 2009 18:25:17 -0800 Subject: [PATCH 41/74] configure: Generate more friendly Makefile.config with separated CFLAGS Each dependency now gets its own variable in the resulting Makefile.config to make it much easier to debug where the various flags came from in the case of any problems. --- configure | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/configure b/configure index 65411956..1097b7c4 100755 --- a/configure +++ b/configure @@ -32,8 +32,8 @@ printf "Checking for Xapian development files... " if xapian-config --version > /dev/null 2>&1; then printf "Yes.\n" have_xapian=1 - cxxflags="${cxxflags} $(xapian-config --cxxflags)" - ldflags="${ldflags} $(xapian-config --libs)" + xapian_cxxflags=$(xapian-config --cxxflags) + xapian_ldflags=$(xapian-config --libs) else printf "No.\n" have_xapian=0 @@ -44,8 +44,8 @@ printf "Checking for GMime 2.4 development files... " if pkg-config --modversion gmime-2.4 > /dev/null 2>&1; then printf "Yes.\n" have_gmime=1 - cflags="${cflags} $(pkg-config --cflags gmime-2.4)" - ldflags="${ldflags} $(pkg-config --libs gmime-2.4)" + gmime_cflags=$(pkg-config --cflags gmime-2.4) + gmime_ldflags=$(pkg-config --libs gmime-2.4) else printf "No.\n" have_gmime=0 @@ -56,8 +56,8 @@ printf "Checking for talloc development files... " if pkg-config --modversion talloc > /dev/null 2>&1; then printf "Yes.\n" have_talloc=1 - cflags="${cflags} $(pkg-config --cflags talloc)" - ldflags="${ldflags} $(pkg-config --libs talloc)" + talloc_cflags=$(pkg-config --cflags talloc) + talloc_ldflags=$(pkg-config --libs talloc) else printf "No.\n" have_talloc=0 @@ -69,7 +69,7 @@ printf "Checking for valgrind development files... " if pkg-config --modversion valgrind > /dev/null 2>&1; then printf "Yes.\n" have_valgrind=1 - cflags="${cflags} $(pkg-config --cflags valgrind)" + valgrind_cflags=$(pkg-config --cflags valgrind) else printf "No (but that's fine).\n" have_valgrind=0 @@ -178,9 +178,30 @@ emacs_lispdir=${emacs_lispdir} # build its own version) HAVE_GETLINE = ${have_getline} -# Various flags needed to compile and link against the dependencies of -# notmuch. -override CFLAGS += ${cflags} -DHAVE_VALGRIND=${have_valgrind} -DHAVE_GETLINE=\$(HAVE_GETLINE) -override CXXFLAGS += ${cflags} ${cxxflags} -override LDFLAGS += ${ldflags} +# Flags needed to compile and link against Xapian +XAPIAN_CXXFLAGS = ${xapian_cxxflags} +XAPIAN_LDFLAGS = ${xapian_ldflags} + +# Flags needed to compile and link against GMime-2.4 +GMIME_CFLAGS = ${gmime_cflags} +GMIME_LDFLAGS = ${gmime_ldflags} + +# Flags needed to compile and linke against talloc +TALLOC_CFLAGS = ${talloc_cflags} +TALLOC_LDFLAGS = ${talloc_ldflags} + +# Whether valgrind header files are available +HAVE_VALGRIND = ${have_valgrind} + +# And if so, flags needed at compile time for valgrind macros +VALGRIND_CFLAGS = ${valgrind_cflags} + +# Combined flags for compiling and linking against all of the above +override CFLAGS += -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS) \\ + \$(TALLOC_CFLAGS) -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \\ + \$(VALGRIND_CFLAGS) +override CXXFLAGS += -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS) \\ + \$(TALLOC_CFLAGS) -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \\ + \$(VALGRIND_CFLAGS) \$(XAPIAN_CXXFLAGS) +override LDFLAGS += \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(XAPIAN_LDFLAGS) EOF From ea2d9a2cbfe6af2a1f7b664e998d09ac5d68d5e0 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Tue, 1 Dec 2009 18:33:23 -0800 Subject: [PATCH 42/74] configure: Allow user to specify compiler to be used. The environment variables CC and CXX can be set at configure time to specify what compiler to use. This compiler will be used for any configure-time compilation, and will also be recorded in Makefile.config to be used during the actual build. The compiler to be used can still be overridden at build time by using a make variable such as: make CC=gcc --- configure | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 1097b7c4..cd4a30e2 100755 --- a/configure +++ b/configure @@ -1,5 +1,8 @@ #! /bin/sh +CC=${CC:-gcc} +CXX=${CXX:-g++} + cat < /dev/null 2>&1 +if ${CC} -o config/have_getline config/have_getline.c > /dev/null 2>&1 then printf "Yes.\n" have_getline=1 @@ -168,6 +171,12 @@ cat > Makefile.config < Date: Fri, 27 Nov 2009 21:49:39 -0500 Subject: [PATCH 43/74] notmuch show: limit display to only matching messages This patch changes the default behaviour of notmuch show to display only messages that match the search expression. However, --entire-thread option is provided to display all messages in threads that matched the search expression. It is deemed that will be more useful for human users on the command line. Scripts can be modified to include the --entire-thread option so that they can display all messages once more. Example: $ notmuch search subject:git AND thread:23d99d0f364f93e90e15df8b42eddb5b thread:23d99d0f364f93e90e15df8b42eddb5b July 31 [4/12] Johan Herland; [RFCv2 00/12] Foreign VCS helper program for CVS repositories (inbox unread) Note that in this thread 4 out of 12 messages matched. The default show behaviour is to show only those messages that match: $ notmuch show subject:git AND thread:23d99d0f364f93e90e15df8b42eddb5b | grep 'message{' | wc -l 4 With the --entire-thread option the output will contain all dozen messages: $ notmuch show --entire-thread subject:git AND thread:23d99d0f364f93e90e15df8b42eddb5b | grep 'message{' | wc -l 12 Signed-off-by: Bart Trojanowski --- notmuch-show.c | 50 ++++++++++++++++++++++++++++++++++++++------------ notmuch.c | 8 ++++++++ 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/notmuch-show.c b/notmuch-show.c index 13c91e47..60339d08 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -212,6 +212,24 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) notmuch_thread_t *thread; notmuch_messages_t *messages; char *query_string; + int entire_thread = 0; + int i; + + for (i = 0; i < argc && argv[i][0] == '-'; i++) { + if (strcmp (argv[i], "--") == 0) { + i++; + break; + } + if (strcmp(argv[i], "--entire-thread") == 0) { + entire_thread = 1; + } else { + fprintf (stderr, "Unrecognized option: %s\n", argv[i]); + return 1; + } + } + + argc -= i; + argv += i; config = notmuch_config_open (ctx, NULL, NULL); if (config == NULL) @@ -239,21 +257,29 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) return 1; } - for (threads = notmuch_query_search_threads (query); - notmuch_threads_has_more (threads); - notmuch_threads_advance (threads)) - { - thread = notmuch_threads_get (threads); - - messages = notmuch_thread_get_toplevel_messages (thread); - + if (!entire_thread) { + messages = notmuch_query_search_messages (query); if (messages == NULL) - INTERNAL_ERROR ("Thread %s has no toplevel messages.\n", - notmuch_thread_get_thread_id (thread)); - + INTERNAL_ERROR ("No messages.\n"); show_messages (ctx, messages, 0); - notmuch_thread_destroy (thread); + } else { + for (threads = notmuch_query_search_threads (query); + notmuch_threads_has_more (threads); + notmuch_threads_advance (threads)) + { + thread = notmuch_threads_get (threads); + + messages = notmuch_thread_get_toplevel_messages (thread); + + if (messages == NULL) + INTERNAL_ERROR ("Thread %s has no toplevel messages.\n", + notmuch_thread_get_thread_id (thread)); + + show_messages (ctx, messages, 0); + + notmuch_thread_destroy (thread); + } } notmuch_query_destroy (query); diff --git a/notmuch.c b/notmuch.c index d9846ce7..06b55f9d 100644 --- a/notmuch.c +++ b/notmuch.c @@ -177,6 +177,14 @@ command_t commands[] = { "\t\t(all replies to a particular message appear immediately\n" "\t\tafter that message in date order).\n" "\n" + "\t\tSupported options for show include:\n" + "\n" + "\t\t--entire-thread\n" + "\n" + "\t\t\tBy default only messages strictly matching the\n" + "\t\t\tsearch expression will be displayed. With this\n" + "\t\t\toption all messages in matching threads are shown.\n" + "\n" "\t\tThe output format is plain-text, with all text-content\n" "\t\tMIME parts decoded. Various components in the output,\n" "\t\t('message', 'header', 'body', 'attachment', and MIME 'part')\n" From 8a3352e619de6d347e1eb42011e65a85f0f4c7ca Mon Sep 17 00:00:00 2001 From: Bart Trojanowski Date: Fri, 27 Nov 2009 21:49:40 -0500 Subject: [PATCH 44/74] vim: use notmuch show --entire-thread --- vim/plugin/notmuch.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vim/plugin/notmuch.vim b/vim/plugin/notmuch.vim index b415f500..f33d0582 100644 --- a/vim/plugin/notmuch.vim +++ b/vim/plugin/notmuch.vim @@ -408,7 +408,7 @@ endfunction function! s:NM_cmd_show(words) let prev_bufnr = bufnr('%') - let data = s:NM_run(['show'] + a:words) + let data = s:NM_run(['show', '--entire-thread'] + a:words) let lines = split(data, "\n") let info = s:NM_cmd_show_parse(lines) From 4d19b89d293253def0b25aaa0c0c30ed8810804d Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 2 Dec 2009 14:38:00 -0800 Subject: [PATCH 45/74] emacs: Add --entire-thread option to "notmuch show" command line. We (plan to) do any hiding of messages from within emacs, so don't let notmuch hide messages from us. --- notmuch.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notmuch.el b/notmuch.el index 25096513..84247aa5 100644 --- a/notmuch.el +++ b/notmuch.el @@ -933,7 +933,7 @@ thread from that buffer can be show when done with this one)." (erase-buffer) (goto-char (point-min)) (save-excursion - (call-process notmuch-command nil t nil "show" thread-id) + (call-process notmuch-command nil t nil "show" "--entire-thread" thread-id) (notmuch-show-markup-messages) ) (run-hooks 'notmuch-show-hook) From 63c503a5ac1a8441b32c615ea91a0dac5f8507c4 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 2 Dec 2009 15:48:34 -0800 Subject: [PATCH 46/74] notmuch.1: Document the new --entire-thread option to "notmuch show". This was added to "notmuch help" earlier, but not to the man page. Add it there, and use consistent wording in both places. --- notmuch.1 | 18 +++++++++++++++++- notmuch.c | 7 ++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/notmuch.1 b/notmuch.1 index 04bd0cf1..369ecba1 100644 --- a/notmuch.1 +++ b/notmuch.1 @@ -169,6 +169,8 @@ when sorting by .B newest\-first the threads will be sorted by the newest message in each thread. +.RE +.RS 4 By default, results will be displayed in reverse chronological order, (that is, the newest results will be displayed first). @@ -177,7 +179,7 @@ See the section below for details of the supported syntax for . .RE .TP -.BR show " ..." +.BR show " [options...] ..." Shows all messages matching the search terms. @@ -187,6 +189,19 @@ message in date order). The output is not indented by default, but depth tags are printed so that proper indentation can be performed by a post-processor (such as the emacs interface to notmuch). +Supported options for +.B show +include +.RS 4 +.TP 4 +.B \-\-entire\-thread + +By default only those messages that match the search terms will be +displayed. With this option, all messages in the same thread as any +matched message will be displayed. +.RE + +.RS 4 The output format is plain-text, with all text-content MIME parts decoded. Various components in the output, .RB ( message ", " header ", " body ", " attachment ", and MIME " part ), @@ -207,6 +222,7 @@ See the .B "SEARCH SYNTAX" section below for details of the supported syntax for . .RE +.RE The .B reply diff --git a/notmuch.c b/notmuch.c index 06b55f9d..2ac8a592 100644 --- a/notmuch.c +++ b/notmuch.c @@ -181,9 +181,10 @@ command_t commands[] = { "\n" "\t\t--entire-thread\n" "\n" - "\t\t\tBy default only messages strictly matching the\n" - "\t\t\tsearch expression will be displayed. With this\n" - "\t\t\toption all messages in matching threads are shown.\n" + "\t\t\tBy default only those messages that match the\n" + "\t\t\tsearch terms will be displayed. With this option,\n" + "\t\t\tall messages in the same thread as any matched\n" + "\t\t\tmessage will be displayed.\n" "\n" "\t\tThe output format is plain-text, with all text-content\n" "\t\tMIME parts decoded. Various components in the output,\n" From 115b7c15b88a4969715f35252229f2a68a09083f Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 2 Dec 2009 16:05:23 -0800 Subject: [PATCH 47/74] notmuch show: Preserve thread-ordering and nesting without --entire-thread When "notmuch show" was recently modified to not show an entire thread by default, it also lost all capability to properly order the messages in a thread and to print their proper depth. For example, the command: notmuch show thread:6d5e3e276461188c5778c9f219f63782 had dramatically different output than: notmuch show --entire-thread thread:6d5e3e276461188c5778c9f219f63782 even though both commands were selecting and displaying the same set of messages. The first command would diplay them "flat", (all with depth:0), and in strict date order; while the second command would display them "nested" (with depth based on threading), and in thread order. We now fix "notmuch show" without the --entire-thread option to also display nested and thread-ordered messages. If some messages in the thread are not included in the displayed results, then they are not counted when computing depth values. --- notmuch-show.c | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/notmuch-show.c b/notmuch-show.c index 60339d08..376aacd7 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -184,9 +184,12 @@ show_message (void *ctx, notmuch_message_t *message, int indent) static void -show_messages (void *ctx, notmuch_messages_t *messages, int indent) +show_messages (void *ctx, notmuch_messages_t *messages, int indent, + notmuch_bool_t entire_thread) { notmuch_message_t *message; + notmuch_bool_t match; + int next_indent; for (; notmuch_messages_has_more (messages); @@ -194,9 +197,17 @@ show_messages (void *ctx, notmuch_messages_t *messages, int indent) { message = notmuch_messages_get (messages); - show_message (ctx, message, indent); + match = notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH); - show_messages (ctx, notmuch_message_get_replies (message), indent + 1); + next_indent = indent; + + if (match || entire_thread) { + show_message (ctx, message, indent); + next_indent = indent + 1; + } + + show_messages (ctx, notmuch_message_get_replies (message), + next_indent, entire_thread); notmuch_message_destroy (message); } @@ -257,29 +268,21 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) return 1; } - if (!entire_thread) { - messages = notmuch_query_search_messages (query); + for (threads = notmuch_query_search_threads (query); + notmuch_threads_has_more (threads); + notmuch_threads_advance (threads)) + { + thread = notmuch_threads_get (threads); + + messages = notmuch_thread_get_toplevel_messages (thread); + if (messages == NULL) - INTERNAL_ERROR ("No messages.\n"); - show_messages (ctx, messages, 0); + INTERNAL_ERROR ("Thread %s has no toplevel messages.\n", + notmuch_thread_get_thread_id (thread)); - } else { - for (threads = notmuch_query_search_threads (query); - notmuch_threads_has_more (threads); - notmuch_threads_advance (threads)) - { - thread = notmuch_threads_get (threads); + show_messages (ctx, messages, 0, entire_thread); - messages = notmuch_thread_get_toplevel_messages (thread); - - if (messages == NULL) - INTERNAL_ERROR ("Thread %s has no toplevel messages.\n", - notmuch_thread_get_thread_id (thread)); - - show_messages (ctx, messages, 0); - - notmuch_thread_destroy (thread); - } + notmuch_thread_destroy (thread); } notmuch_query_destroy (query); From 656709b5ed0ed216dd71e7376ac99e3b66f8ebd3 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Wed, 2 Dec 2009 17:18:51 -0800 Subject: [PATCH 48/74] TODO: Add some tasks, delete some tasks. A new item from IRC discussion, (speeding up "notmuch restore"), as well as a bug I just hit myself, (content from citations is not being indexed). While here, notce that several items have recently been completed ('?' now displays documentation, not function names; we have a search binding from notmush-show-mode; and "notmuch new" responds to SIGINT by flushing). Finally, the item regarding optimizing chunky searching is irrelevant since we dropped chunky searching in favor of the much better streamed searching. --- TODO | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/TODO b/TODO index 578d833c..68ea2666 100644 --- a/TODO +++ b/TODO @@ -8,9 +8,6 @@ Fix the things that are causing the most pain to new users Emacs interface (notmuch.el) ---------------------------- -Make the keybindings help ('?') display the summary of each command's -documentation, not the function name. - Add a global keybinding table for notmuch, and then view-specific tables that add to it. @@ -18,8 +15,6 @@ Add a command to archive all threads in a search view. Add a '|' binding from the search view. -Add a binding to run a search from notmuch-show-mode. - When a thread has been entirely read, start out by closing all messages except those that matched the search terms. @@ -68,6 +63,10 @@ Give "notmuch restore" some progress indicator. Until we get the Xapian bugs fixed that are making this operation slow, we really need to let the user know that things are still moving. +Fix "notmuch restore" to operate in a single pass much like "notmuch +dump" does, rather than doing N searches into the database, each +matching 1/N messages. + Add a "-f " option to select an alternate configuration file. @@ -76,10 +75,6 @@ relative to the database path. (Otherwise, moving the database to a new directory will result in notmuch creating new timestamp documents and leaving stale ones behind.) -Ensure that "notmuch new" is sane if its first, giant indexing session -gets interrupted, (that is, ensure that any results indexed so far are -flushed). - Fix notmuch.c to use a DIR prefix for directory timestamps, (the idea being that it can then add other non-directory timestamps such as for noting how far back in the past mail has been indexed, and whether it @@ -100,10 +95,12 @@ indexing. notmuch library --------------- +Index content from citations, please. + Provide a sane syntax for date ranges. First, we don't want to require both endpoints to be specified. For example it would be nice to be able to say things like "since:2009-01-1" or "until:2009-01-1" and -have the other enpoint be implicit. Second we'de like to support +have the other enpoint be implicit. Second we'd like to support relative specifications of time such as "since:'2 months ago'". To do any of this we're probably going to need to break down an write our own parser for the query string rather than using Xapian's QueryParser @@ -128,11 +125,6 @@ Add support for configuring "virtual tags" which are a tuple of (tag-name, search-specification). The database is responsible for ensuring that the virtual tag is always consistent. -Think about optimizing chunked searches (max-threads > 0) to avoid -repeating work. That would be saving state from the previous chunk and -reusing it if the next search is the next chunk with the same search -string. - General ------- Audit everything for dealing with out-of-memory (and drop xutil.c). From 48a1b8b0060c02d0ba111e3fc8a953bdc088cb88 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 3 Dec 2009 07:30:26 -0800 Subject: [PATCH 49/74] TODO, emacs: Correct a few typos. Sometime I'll stop misspelling things so much, honets. --- TODO | 2 +- notmuch.el | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 68ea2666..25c565fa 100644 --- a/TODO +++ b/TODO @@ -100,7 +100,7 @@ Index content from citations, please. Provide a sane syntax for date ranges. First, we don't want to require both endpoints to be specified. For example it would be nice to be able to say things like "since:2009-01-1" or "until:2009-01-1" and -have the other enpoint be implicit. Second we'd like to support +have the other endpoint be implicit. Second we'd like to support relative specifications of time such as "since:'2 months ago'". To do any of this we're probably going to need to break down an write our own parser for the query string rather than using Xapian's QueryParser diff --git a/notmuch.el b/notmuch.el index 84247aa5..7bbaaefa 100644 --- a/notmuch.el +++ b/notmuch.el @@ -391,7 +391,7 @@ point either forward or backward to the next visible character when a command ends with point on an invisible character). Emits an error if point is not within a valid message, (that is -not pattern of `notmuch-show-message-begin-regexp' could be found +no pattern of `notmuch-show-message-begin-regexp' could be found by searching backward)." (beginning-of-line) (if (not (looking-at notmuch-show-message-begin-regexp)) @@ -408,7 +408,7 @@ by searching backward)." (not (re-search-forward notmuch-show-message-begin-regexp nil t))))) (defun notmuch-show-message-unread-p () - "Preficate testing whether current message is unread." + "Predicate testing whether current message is unread." (member "unread" (notmuch-show-get-tags))) (defun notmuch-show-next-message () From e1f05f1c20b1ff582cbe150cefe39fd9aea64907 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 3 Dec 2009 07:37:40 -0800 Subject: [PATCH 50/74] emacs: Fix notmuch-show-next-open-message. This function was still implemented in terms of the old, global toggle for visibility of unread messages, (which no longer exists). Fix it to use the local 'invisibility-spec property on the button controlling message visibility. --- notmuch.el | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/notmuch.el b/notmuch.el index 7bbaaefa..744f4d3c 100644 --- a/notmuch.el +++ b/notmuch.el @@ -411,19 +411,32 @@ by searching backward)." "Predicate testing whether current message is unread." (member "unread" (notmuch-show-get-tags))) +(defun notmuch-show-message-open-p () + "Predicate testing whether current message is open (body is visible)." + (let ((btn (previous-button (point) t))) + (while (not (button-has-type-p btn 'notmuch-button-body-toggle-type)) + (setq btn (previous-button (button-start btn)))) + (not (invisible-p (button-get btn 'invisibility-spec))))) + (defun notmuch-show-next-message () "Advance to the beginning of the next message in the buffer. Moves to the last visible character of the current message if -already on the last message in the buffer." +already on the last message in the buffer. + +Returns nil if already on the last message in the buffer." (interactive) (notmuch-show-move-to-current-message-summary-line) (if (re-search-forward notmuch-show-message-begin-regexp nil t) - (notmuch-show-move-to-current-message-summary-line) + (progn + (notmuch-show-move-to-current-message-summary-line) + (recenter 0) + t) (goto-char (- (point-max) 1)) (while (point-invisible-p) - (backward-char))) - (recenter 0)) + (backward-char)) + (recenter 0) + nil)) (defun notmuch-show-find-next-message () "Returns the position of the next message in the buffer. @@ -451,14 +464,9 @@ there are no more unread messages past the current point." (notmuch-show-next-message))) (defun notmuch-show-next-open-message () - "Advance to the next message which is not hidden. - -If read messages are currently hidden, advance to the next unread -message. Otherwise, advance to the next message." - (if (or (memq 'notmuch-show-body-read buffer-invisibility-spec) - (assq 'notmuch-show-body-read buffer-invisibility-spec)) - (notmuch-show-next-unread-message) - (notmuch-show-next-message))) + "Advance to the next open message (that is, body is not invisible)." + (while (and (notmuch-show-next-message) + (not (notmuch-show-message-open-p))))) (defun notmuch-show-previous-message () "Backup to the beginning of the previous message in the buffer. From 682102c2df45bb6642f2d5c538284fe48136d4ea Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 3 Dec 2009 09:48:00 -0800 Subject: [PATCH 51/74] emacs: Make the message-summary highlighting extend to end of visible line. This will look much nicer than the highlighting terminating at the end of the summary text. --- notmuch.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/notmuch.el b/notmuch.el index 744f4d3c..29bb9eb2 100644 --- a/notmuch.el +++ b/notmuch.el @@ -726,11 +726,11 @@ which this thread was originally shown." (re-search-forward notmuch-show-header-begin-regexp) (forward-line) (let ((beg (point-marker)) + (summary-end (copy-marker (line-beginning-position 2))) (btn nil)) - (end-of-line) ; Inverse video for subject - (overlay-put (make-overlay beg (point)) 'face '(:inverse-video t)) - (setq btn (make-button beg (point) :type 'notmuch-button-body-toggle-type)) + (overlay-put (make-overlay beg summary-end) 'face '(:inverse-video t)) + (setq btn (make-button beg summary-end :type 'notmuch-button-body-toggle-type)) (forward-line 1) (end-of-line) (let ((beg-hidden (point-marker))) From 6945e7e103fdc10cb676571b313eac5abd62d0c6 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 3 Dec 2009 09:52:43 -0800 Subject: [PATCH 52/74] emacs: Highlight message-summary with background-color instead of inverse video. Also, do this with a notmuch-message-summary-face variable so that the user can easily customize the desried effect. --- notmuch.el | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/notmuch.el b/notmuch.el index 29bb9eb2..f3adfcf5 100644 --- a/notmuch.el +++ b/notmuch.el @@ -728,8 +728,7 @@ which this thread was originally shown." (let ((beg (point-marker)) (summary-end (copy-marker (line-beginning-position 2))) (btn nil)) - ; Inverse video for subject - (overlay-put (make-overlay beg summary-end) 'face '(:inverse-video t)) + (overlay-put (make-overlay beg summary-end) 'face 'notmuch-message-summary-face) (setq btn (make-button beg summary-end :type 'notmuch-button-body-toggle-type)) (forward-line 1) (end-of-line) @@ -1046,6 +1045,12 @@ thread from that buffer can be show when done with this one)." (interactive) (goto-char (point-min))) +(defface notmuch-message-summary-face + '((((class color) (background light)) (:background "#f0f0f0")) + (((class color) (background dark)) (:background "#303030"))) + "Face for the single-line message summary in notmuch-show-mode." + :group 'notmuch) + (defface notmuch-tag-face '((((class color) (background dark)) From fcc36df1fa37b940a46a3c14f0ccee8a39875145 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 3 Dec 2009 10:37:35 -0800 Subject: [PATCH 53/74] emacs: Make message-summary button begin at beginning of line. Otherwise, RET is unreliable for opening/closing messages when navigating through messages with 'n' and 'p'. --- notmuch.el | 64 +++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/notmuch.el b/notmuch.el index f3adfcf5..6d7228fb 100644 --- a/notmuch.el +++ b/notmuch.el @@ -695,8 +695,11 @@ which this thread was originally shown." (set-marker beg nil) (set-marker end nil) ))) + (defun notmuch-fontify-headers () (progn + (while (looking-at "[[:space:]]") + (forward-char)) (if (looking-at "[Tt]o:") (progn (overlay-put (make-overlay (point) (re-search-forward ":")) @@ -727,39 +730,36 @@ which this thread was originally shown." (forward-line) (let ((beg (point-marker)) (summary-end (copy-marker (line-beginning-position 2))) + (subject-end (copy-marker (line-end-position 2))) + (invis-spec (make-symbol "notmuch-show-header")) (btn nil)) - (overlay-put (make-overlay beg summary-end) 'face 'notmuch-message-summary-face) - (setq btn (make-button beg summary-end :type 'notmuch-button-body-toggle-type)) - (forward-line 1) - (end-of-line) - (let ((beg-hidden (point-marker))) - (re-search-forward notmuch-show-header-end-regexp) - (beginning-of-line) - (let ((end (point-marker))) - (goto-char beg) - (forward-line) - (while (looking-at "[A-Za-z][-A-Za-z0-9]*:") - (beginning-of-line) - (notmuch-fontify-headers) - (forward-line) - ) - (indent-rigidly beg end depth) - (let ((invis-spec (make-symbol "notmuch-show-header"))) - (add-to-invisibility-spec (cons invis-spec t)) - (overlay-put (make-overlay beg-hidden end) - 'invisible invis-spec) - (goto-char beg) - (forward-line) - (make-button (line-beginning-position) (line-end-position) - 'invisibility-spec (cons invis-spec t) - :type 'notmuch-button-headers-toggle-type)) - (goto-char end) - (insert "\n") - (set-marker beg nil) - (set-marker beg-hidden nil) - (set-marker end nil) - )) - btn)) + (re-search-forward notmuch-show-header-end-regexp) + (beginning-of-line) + (let ((end (point-marker))) + (indent-rigidly beg end depth) + (goto-char beg) + (overlay-put (make-overlay (line-beginning-position) summary-end) 'face 'notmuch-message-summary-face) + (setq btn (make-button (line-beginning-position) summary-end :type 'notmuch-button-body-toggle-type)) + (forward-line) + (add-to-invisibility-spec invis-spec) + (overlay-put (make-overlay subject-end end) + 'invisible invis-spec) + (make-button (line-beginning-position) subject-end + 'invisibility-spec invis-spec + :type 'notmuch-button-headers-toggle-type) + (while (looking-at "[[:space:]]*[A-Za-z][-A-Za-z0-9]*:") + (beginning-of-line) + (notmuch-fontify-headers) + (forward-line) + ) + (goto-char end) + (insert "\n") + (set-marker beg nil) + (set-marker summary-end nil) + (set-marker subject-end nil) + (set-marker end nil) + ) + btn)) (defun notmuch-show-markup-message () (if (re-search-forward notmuch-show-message-begin-regexp nil t) From a0439ded70b69978b982a8defa48848780aba518 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 3 Dec 2009 10:39:33 -0800 Subject: [PATCH 54/74] emacs: notmuch-fontify-headers: Remove unneeded progn and indent correctly. The defun special form doesn't require a progn. And the remainder of the function was previously indented in a misleading way, (as if each "if" was always evaluated, rather than each only being evaluated if all the previous evaluated to nil). --- notmuch.el | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/notmuch.el b/notmuch.el index 6d7228fb..b3f67d2b 100644 --- a/notmuch.el +++ b/notmuch.el @@ -697,33 +697,32 @@ which this thread was originally shown." ))) (defun notmuch-fontify-headers () - (progn - (while (looking-at "[[:space:]]") - (forward-char)) - (if (looking-at "[Tt]o:") - (progn - (overlay-put (make-overlay (point) (re-search-forward ":")) - 'face 'message-header-name) - (overlay-put (make-overlay (point) (re-search-forward ".*$")) - 'face 'message-header-to)) + (while (looking-at "[[:space:]]") + (forward-char)) + (if (looking-at "[Tt]o:") + (progn + (overlay-put (make-overlay (point) (re-search-forward ":")) + 'face 'message-header-name) + (overlay-put (make-overlay (point) (re-search-forward ".*$")) + 'face 'message-header-to)) (if (looking-at "[B]?[Cc][Cc]:") (progn (overlay-put (make-overlay (point) (re-search-forward ":")) - 'face 'message-header-name) - (overlay-put (make-overlay (point) (re-search-forward ".*$")) - 'face 'message-header-cc)) - (if (looking-at "[Ss]ubject:") - (progn - (overlay-put (make-overlay (point) (re-search-forward ":")) - 'face 'message-header-name) - (overlay-put (make-overlay (point) (re-search-forward ".*$")) - 'face 'message-header-subject)) - (if (looking-at "[Ff]rom:") - (progn - (overlay-put (make-overlay (point) (re-search-forward ":")) - 'face 'message-header-name) - (overlay-put (make-overlay (point) (re-search-forward ".*$")) - 'face 'message-header-other)))))))) + 'face 'message-header-name) + (overlay-put (make-overlay (point) (re-search-forward ".*$")) + 'face 'message-header-cc)) + (if (looking-at "[Ss]ubject:") + (progn + (overlay-put (make-overlay (point) (re-search-forward ":")) + 'face 'message-header-name) + (overlay-put (make-overlay (point) (re-search-forward ".*$")) + 'face 'message-header-subject)) + (if (looking-at "[Ff]rom:") + (progn + (overlay-put (make-overlay (point) (re-search-forward ":")) + 'face 'message-header-name) + (overlay-put (make-overlay (point) (re-search-forward ".*$")) + 'face 'message-header-other))))))) (defun notmuch-show-markup-header (depth) (re-search-forward notmuch-show-header-begin-regexp) From 8e126fe1fb188ecc85ff53134bd9afd3d394b041 Mon Sep 17 00:00:00 2001 From: Alexander Botero-Lowry Date: Thu, 3 Dec 2009 10:52:58 -0800 Subject: [PATCH 55/74] Since we know what these buttons do it seems like the underlines are unnecessary. --- notmuch.el | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/notmuch.el b/notmuch.el index b3f67d2b..54b4ba86 100644 --- a/notmuch.el +++ b/notmuch.el @@ -574,14 +574,19 @@ which this thread was originally shown." (force-window-update) (redisplay t)) -(define-button-type 'notmuch-button-invisibility-toggle-type 'action 'notmuch-toggle-invisible-action 'follow-link t) +(define-button-type 'notmuch-button-invisibility-toggle-type + 'action 'notmuch-toggle-invisible-action + 'follow-link t + 'face "default") (define-button-type 'notmuch-button-citation-toggle-type 'help-echo "mouse-1, RET: Show citation" :supertype 'notmuch-button-invisibility-toggle-type) (define-button-type 'notmuch-button-signature-toggle-type 'help-echo "mouse-1, RET: Show signature" :supertype 'notmuch-button-invisibility-toggle-type) (define-button-type 'notmuch-button-headers-toggle-type 'help-echo "mouse-1, RET: Show headers" :supertype 'notmuch-button-invisibility-toggle-type) -(define-button-type 'notmuch-button-body-toggle-type 'help-echo "mouse-1, RET: Show message" +(define-button-type 'notmuch-button-body-toggle-type + 'help-echo "mouse-1, RET: Show message" + 'face 'notmuch-message-summary-face :supertype 'notmuch-button-invisibility-toggle-type) (defun notmuch-show-markup-citations-region (beg end depth) @@ -737,7 +742,6 @@ which this thread was originally shown." (let ((end (point-marker))) (indent-rigidly beg end depth) (goto-char beg) - (overlay-put (make-overlay (line-beginning-position) summary-end) 'face 'notmuch-message-summary-face) (setq btn (make-button (line-beginning-position) summary-end :type 'notmuch-button-body-toggle-type)) (forward-line) (add-to-invisibility-spec invis-spec) From 11490cfebef4099c00031207c161132fc6363239 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 3 Dec 2009 11:34:01 -0800 Subject: [PATCH 56/74] emacs: Make message-summary button extend to very beginning of message. There's no visible change here---we're just making the button extend through the invisible portions of the message before the message-summary line. The reason this is important is that it's easy for the user to position point at the (invisible) `point-min', so we want to ensure that there's a valid button there. --- notmuch.el | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/notmuch.el b/notmuch.el index 54b4ba86..bf7e46f6 100644 --- a/notmuch.el +++ b/notmuch.el @@ -729,7 +729,18 @@ which this thread was originally shown." (overlay-put (make-overlay (point) (re-search-forward ".*$")) 'face 'message-header-other))))))) -(defun notmuch-show-markup-header (depth) +(defun notmuch-show-markup-header (message-begin depth) + "Buttonize and decorate faces in a message header. + +MESSAGE-BEGIN is the position of the absolute first character in +the message (including all delimiters that will end up being +invisible etc.). This is to allow a button to reliably extend to +the beginning of the message even if point is positioned at an +invisible character (such as the beginning of the buffer). + +DEPTH specifies the depth at which this message appears in the +tree of the current thread, (the top-level messages have depth 0 +and each reply increases depth by 1)." (re-search-forward notmuch-show-header-begin-regexp) (forward-line) (let ((beg (point-marker)) @@ -742,7 +753,7 @@ which this thread was originally shown." (let ((end (point-marker))) (indent-rigidly beg end depth) (goto-char beg) - (setq btn (make-button (line-beginning-position) summary-end :type 'notmuch-button-body-toggle-type)) + (setq btn (make-button message-begin summary-end :type 'notmuch-button-body-toggle-type)) (forward-line) (add-to-invisibility-spec invis-spec) (overlay-put (make-overlay subject-end end) @@ -766,11 +777,11 @@ which this thread was originally shown." (defun notmuch-show-markup-message () (if (re-search-forward notmuch-show-message-begin-regexp nil t) - (progn + (let ((message-begin (match-beginning 0))) (re-search-forward notmuch-show-depth-regexp) (let ((depth (string-to-number (buffer-substring (match-beginning 1) (match-end 1)))) (btn nil)) - (setq btn (notmuch-show-markup-header depth)) + (setq btn (notmuch-show-markup-header message-begin depth)) (notmuch-show-markup-body depth btn))) (goto-char (point-max)))) From 0ed126fe19db00ff23a393965c12d9d1f97186ac Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 3 Dec 2009 11:38:05 -0800 Subject: [PATCH 57/74] emacs: Open only matched (and unread) messages when displaying a thread. This is the long-awaited feature that when viewing a thread resulting from a search, only the messages that actually match the search will be opened initially (in addition to unread messages). So now, it's finally useful to tag a single message in a giant thread, and then do a search later and easily find just the single tagged message. --- notmuch.el | 52 +++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/notmuch.el b/notmuch.el index bf7e46f6..867b5635 100644 --- a/notmuch.el +++ b/notmuch.el @@ -111,7 +111,7 @@ pattern can still test against the entire line).") (defvar notmuch-show-marker-regexp "\f\\(message\\|header\\|body\\|attachment\\|part\\)[{}].*$") (defvar notmuch-show-id-regexp "\\(id:[^ ]*\\)") -(defvar notmuch-show-depth-regexp " depth:\\([0-9]*\\) ") +(defvar notmuch-show-depth-match-regexp " depth:\\([0-9]*\\).*match:\\([01]\\) ") (defvar notmuch-show-filename-regexp "filename:\\(.*\\)$") (defvar notmuch-show-tags-regexp "(\\([^)]*\\))$") @@ -684,7 +684,20 @@ which this thread was originally shown." (notmuch-show-markup-part beg end depth mime-message)))))) -(defun notmuch-show-markup-body (depth btn) +(defun notmuch-show-markup-body (depth match btn) + "Markup a message body, (indenting, buttonizing citations, +etc.), and conditionally hiding the body itself if the message +has been read and does not match the current search. + +DEPTH specifies the depth at which this message appears in the +tree of the current thread, (the top-level messages have depth 0 +and each reply increases depth by 1). MATCH indicates whether +this message is regarded as matching the current search. BTN is +the button which is used to toggle the visibility of this +message. + +When this function is called, point must be within the message, but +before the delimiter marking the beginning of the body." (re-search-forward notmuch-show-body-begin-regexp) (forward-line) (let ((beg (point-marker))) @@ -695,7 +708,7 @@ which this thread was originally shown." (overlay-put (make-overlay beg end) 'invisible invis-spec) (button-put btn 'invisibility-spec invis-spec) - (if (not (notmuch-show-message-unread-p)) + (if (not (or (notmuch-show-message-unread-p) match)) (add-to-invisibility-spec invis-spec))) (set-marker beg nil) (set-marker end nil) @@ -778,11 +791,12 @@ and each reply increases depth by 1)." (defun notmuch-show-markup-message () (if (re-search-forward notmuch-show-message-begin-regexp nil t) (let ((message-begin (match-beginning 0))) - (re-search-forward notmuch-show-depth-regexp) + (re-search-forward notmuch-show-depth-match-regexp) (let ((depth (string-to-number (buffer-substring (match-beginning 1) (match-end 1)))) + (match (string= "1" (buffer-substring (match-beginning 2) (match-end 2)))) (btn nil)) (setq btn (notmuch-show-markup-header message-begin depth)) - (notmuch-show-markup-body depth btn))) + (notmuch-show-markup-body depth match btn))) (goto-char (point-max)))) (defun notmuch-show-hide-markers () @@ -942,7 +956,8 @@ The optional PARENT-BUFFER is the notmuch-search buffer from which this notmuch-show command was executed, (so that the next thread from that buffer can be show when done with this one)." (interactive "sNotmuch show: ") - (let ((buffer (get-buffer-create (concat "*notmuch-show-" thread-id "*")))) + (let ((query notmuch-search-query-string) + (buffer (get-buffer-create (concat "*notmuch-show-" thread-id "*")))) (switch-to-buffer buffer) (notmuch-show-mode) (set (make-local-variable 'notmuch-show-parent-buffer) parent-buffer) @@ -954,30 +969,13 @@ thread from that buffer can be show when done with this one)." (erase-buffer) (goto-char (point-min)) (save-excursion - (call-process notmuch-command nil t nil "show" "--entire-thread" thread-id) + (call-process notmuch-command nil t nil "show" "--entire-thread" thread-id "and (" query ")") (notmuch-show-markup-messages) ) (run-hooks 'notmuch-show-hook) - ; Move straight to the first unread message - (if (not (notmuch-show-message-unread-p)) - (progn - (notmuch-show-next-unread-message) - ; But if there are no unread messages, go back to the - ; beginning of the buffer, and open up the bodies of all - ; read message. - (if (not (notmuch-show-message-unread-p)) - (progn - (goto-char (point-min)) - (let ((btn (forward-button 1))) - (while btn - (if (button-has-type-p btn 'notmuch-button-body-toggle-type) - (push-button)) - (condition-case err - (setq btn (forward-button 1)) - (error (setq btn nil))) - )) - (goto-char (point-min)) - )))) + ; Move straight to the first open message + (if (not (notmuch-show-message-open-p)) + (notmuch-show-next-open-message)) ))) (defvar notmuch-search-authors-width 40 From 0ca16114162f94424cb75f01c84334a17ac43f98 Mon Sep 17 00:00:00 2001 From: Bart Trojanowski Date: Fri, 27 Nov 2009 21:31:12 -0500 Subject: [PATCH 58/74] vim: preserve the 'show everything' flag when finding next/prev buffer When show mode is invoked it could be displaying just the matched messages or everything. This flag is passed to NM_search_show_thread(). It is then stored in a buffer variable, b:nm_show_everything, and used for subsequent calls to NM_search_show_thread() triggered by , and . Signed-off-by: Bart Trojanowski --- vim/plugin/notmuch.vim | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/vim/plugin/notmuch.vim b/vim/plugin/notmuch.vim index f33d0582..a226f203 100644 --- a/vim/plugin/notmuch.vim +++ b/vim/plugin/notmuch.vim @@ -275,6 +275,7 @@ function! s:NM_search_show_thread(everything) call add(words, ')') endif call NM_cmd_show(words) + let b:nm_show_everything = a:everything endfunction function! s:NM_search_prompt() @@ -430,6 +431,7 @@ function! s:NM_cmd_show(words) endfunction function! s:NM_show_previous(can_change_thread, find_matching) + let everything = exists('b:nm_show_everything') ? b:nm_show_everything : 0 let info = b:nm_raw_info let lnum = line('.') for msg in reverse(copy(info['msgs'])) @@ -450,7 +452,7 @@ function! s:NM_show_previous(can_change_thread, find_matching) call NM_kill_this_buffer() if line('.') > 1 norm k - call NM_search_show_thread() + call NM_search_show_thread(everything) norm G call NM_show_previous(0, a:find_matching) else @@ -479,10 +481,11 @@ function! s:NM_show_next(can_change_thread, find_matching) endfunction function! s:NM_show_next_thread() + let everything = exists('b:nm_show_everything') ? b:nm_show_everything : 0 call NM_kill_this_buffer() if line('.') != line('$') norm j - call NM_search_show_thread() + call NM_search_show_thread(everything) else echo 'No more messages.' endif From c8b50eee284ff880aed955018568a14eff03d129 Mon Sep 17 00:00:00 2001 From: Kan-Ru Chen Date: Sat, 28 Nov 2009 19:58:29 +0800 Subject: [PATCH 59/74] notmuch-reply: Display reply message part using UTF-8. Pass the message through the charset filter so that we can view messages wrote in different charset encoding. Signed-off-by: Kan-Ru Chen --- notmuch-reply.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/notmuch-reply.c b/notmuch-reply.c index 9ca1236b..0cda72dc 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -39,11 +39,17 @@ reply_part_content (GMimeObject *part) { GMimeStream *stream_stdout = NULL, *stream_filter = NULL; GMimeDataWrapper *wrapper; + const char *charset; + charset = g_mime_object_get_content_type_parameter (part, "charset"); stream_stdout = g_mime_stream_file_new (stdout); if (stream_stdout) { g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE); stream_filter = g_mime_stream_filter_new(stream_stdout); + if (charset) { + g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter), + g_mime_filter_charset_new(charset, "UTF-8")); + } } g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter), g_mime_filter_reply_new(TRUE)); From 8696882443048c0c31caf62e182dddb8cf8c2498 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sat, 28 Nov 2009 08:20:08 -0600 Subject: [PATCH 60/74] Add some text to configure on how to install dependencies with yum. Add some text on how to install dependencies with yum for Fedora or other systems that use yum for package management. Since the named of the required packages on Fedora are slightly different from Debian this will help get new users of notmuch that use Fedora going quicker. Signed-off-by: Jeffrey C. Ollie --- configure | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/configure b/configure index cd4a30e2..7180e5e7 100755 --- a/configure +++ b/configure @@ -112,6 +112,10 @@ line: sudo apt-get install libxapian-dev libgmime-2.4-dev libtalloc-dev +Or on Fedora or other RPM-based systems: + + sudo yum install xapian-core-devel gmime-devel libtalloc-devel + On other systems, a similar command can be used, but the details of the package names may be different, (such as "devel" in place of "dev"). @@ -125,6 +129,9 @@ to install pkg-config with a command such as: sudo apt-get install pkg-config +Or: + sudo yum install pkgconfig + But if pkg-config is not available for your system, then you will need to modify the configure script to manually set the cflags and ldflags variables to the correct values to link against each library in each From b86e30be06548f08cc002d6739c0e4071debcd0d Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Thu, 3 Dec 2009 16:52:18 -0800 Subject: [PATCH 61/74] configure: Tweak the working of the example commands slightly. Basically just getting better parallelism between the descriptions of the Defora and Debian commands. (And fixing a nearby typo.) --- configure | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 7180e5e7..fd194ab0 100755 --- a/configure +++ b/configure @@ -106,18 +106,20 @@ EOF fi cat < Date: Sat, 28 Nov 2009 14:11:16 -0600 Subject: [PATCH 62/74] Remove unused notmuch_parse_date function prototype. notmuch_parse_date is not implemented, so remove the unused function prototype. Signed-off-by: Jeffrey C. Ollie --- lib/notmuch-private.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index d2678f06..0c340a76 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -332,18 +332,6 @@ void _notmuch_message_add_reply (notmuch_message_t *message, notmuch_message_node_t *reply); -/* date.c */ - -/* Parse an RFC 8222 date string to a time_t value. - * - * The tz_offset argument can be used to also obtain the time-zone - * offset, (but can be NULL if the call is not interested in that). - * - * Returns 0 on error. - */ -time_t -notmuch_parse_date (const char *str, int *tz_offset); - /* sha1.c */ char * From ea4cb3cbdc8b3c6e450b971f52e880223e943ba0 Mon Sep 17 00:00:00 2001 From: Jed Brown Date: Wed, 2 Dec 2009 12:00:35 +0100 Subject: [PATCH 63/74] Make search filters handle disjunctive queries. notmuch-search-filter now accepts an arbitrary query and will group if necessary so that we get tag:inbox AND (gravy OR biscuits) instead of the former tag:inbox AND gravy OR biscuits Signed-off-by: Jed Brown --- notmuch.el | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/notmuch.el b/notmuch.el index 867b5635..c504f46d 100644 --- a/notmuch.el +++ b/notmuch.el @@ -1014,6 +1014,8 @@ thread from that buffer can be show when done with this one)." (defvar notmuch-search-oldest-first t "Show the oldest mail first in the search-mode") +(defvar notmuch-search-disjunctive-regexp "\\<[oO][rR]\\>") + (defun notmuch-search-scroll-up () "Move forward through search results by one window's worth." (interactive) @@ -1352,7 +1354,8 @@ search." Runs a new search matching only messages that match both the current search results AND the additional query string provided." (interactive "sFilter search: ") - (notmuch-search (concat notmuch-search-query-string " and " query) notmuch-search-oldest-first)) + (let ((grouped-query (if (string-match-p notmuch-search-disjunctive-regexp query) (concat "( " query " )") query))) + (notmuch-search (concat notmuch-search-query-string " and " grouped-query) notmuch-search-oldest-first))) (defun notmuch-search-filter-by-tag (tag) "Filter the current search results based on a single tag. From 926c71e6b92a6aa993330e06c27eb9d9d67c6f82 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Wed, 2 Dec 2009 09:11:24 +0200 Subject: [PATCH 64/74] * notmuch-config: fix small leak from 'g_key_file_to_data' Signed-off-by: Dirk-Jan C. Binnema --- notmuch-config.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notmuch-config.c b/notmuch-config.c index fc65d6b0..95430db1 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -317,9 +317,11 @@ notmuch_config_save (notmuch_config_t *config) fprintf (stderr, "Error saving configuration to %s: %s\n", config->filename, error->message); g_error_free (error); + g_free (data); return 1; } + g_free (data); return 0; } From 2c2b31d536545189e426b382fad5b5ae0b6cc4de Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Sat, 28 Nov 2009 18:57:35 -0500 Subject: [PATCH 65/74] Fix configure script to handle --prefix= Reviewed-by: Carl Worth : This is really the fundamental thing that people expect a configure script to do, so it's important to support it. --- configure | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/configure b/configure index fd194ab0..70a3c3d8 100755 --- a/configure +++ b/configure @@ -3,6 +3,16 @@ CC=${CC:-gcc} CXX=${CXX:-g++} +# defaults +PREFIX=/usr/local + +# option parsing +for option; do + if [ "${option%=*}" = '--prefix' ] ; then + PREFIX="${option#*=}" + fi +done + cat < Date: Fri, 4 Dec 2009 14:50:49 -0800 Subject: [PATCH 66/74] Fix option parsing for the case of a value with '='. To support this we need to match the longest-possible suffix and then strip the shortest-possible prefix. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 70a3c3d8..54d55cba 100755 --- a/configure +++ b/configure @@ -8,7 +8,7 @@ PREFIX=/usr/local # option parsing for option; do - if [ "${option%=*}" = '--prefix' ] ; then + if [ "${option%%=*}" = '--prefix' ] ; then PREFIX="${option#*=}" fi done From 9ea8bb11d4d35cc4222931ea498763fc705f1d02 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 4 Dec 2009 14:52:32 -0800 Subject: [PATCH 67/74] TODO: Note about adding "notmuch search --matching" This bug was recently discussed on the mailing list: id:878wdifu13.fsf@yoom.home.cworth.org so note one idea for fixing it. --- TODO | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/TODO b/TODO index 25c565fa..d6c303ee 100644 --- a/TODO +++ b/TODO @@ -44,6 +44,11 @@ and *then* --max-threads), and also complete value for --sort= notmuch command-line tool ------------------------- +Fix "notmuch show" so that the UI doesn't fail to show a thread that +is visible in a search buffer, but happens to no longer match the +current search. (Perhaps add a --matching= +option (or similar) to "notmuch show".) + Teach "notmuch search" to return many different kinds of results. Some ideas: From c7f971e8c02524ee2435406f0c14791b75c10e20 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 4 Dec 2009 15:08:37 -0800 Subject: [PATCH 68/74] Fix quiet compilation to print the user's CFLAGS, CXXFLAGS, LDFLAGS. The only reason I ever call "make V=1" myself, (other than when debugging the compiler command-line for some reason), is to ensure whether my CFLAGS, (like "-g -O0" or "-O2"), are actually making it to the command-line. But these are hard to find in the V=1 output, and really, we should just print these even in the quiet case. So do that. --- Makefile | 15 ++++++++------- Makefile.local | 2 +- configure | 6 +++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 588f8538..889a78c9 100644 --- a/Makefile +++ b/Makefile @@ -19,8 +19,9 @@ extra_cflags := extra_cxxflags := # Now smash together user's values with our extra values -override CFLAGS += $(WARN_CFLAGS) $(extra_cflags) -override CXXFLAGS += $(WARN_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) +FINAL_CFLAGS = $(CFLAGS) $(WARN_CFLAGS) $(CONFIGURE_CFLAGS) $(extra_cflags) +FINAL_CXXFLAGS = $(CXXFLAGS) $(WARN_CXXFLAGS) $(CONFIGURE_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) +FINAL_LDFLAGS = $(LDFLAGS) $(CONFIGURE_LDFLAGS) all: notmuch notmuch.1.gz @@ -39,7 +40,7 @@ include Makefile.local # user how to enable verbose compiles. ifeq ($(V),) quiet_DOC := "Use \"$(MAKE) V=1\" to see the verbose compile lines.\n" -quiet = @printf $(quiet_DOC)$(eval quiet_DOC:=)" $1 $@\n"; $($1) +quiet = @printf $(quiet_DOC)$(eval quiet_DOC:=)" $1 $2 $@\n"; $($1) endif # The user has explicitly enabled quiet compilation. ifeq ($(V),0) @@ -49,23 +50,23 @@ endif quiet ?= $($1) %.o: %.cc $(all_deps) - $(call quiet,CXX) -c $(CXXFLAGS) $< -o $@ + $(call quiet,CXX,$(CXXFLAGS)) -c $(FINAL_CXXFLAGS) $< -o $@ %.o: %.c $(all_deps) - $(call quiet,CC) -c $(CFLAGS) $< -o $@ + $(call quiet,CC,$(CFLAGS)) -c $(FINAL_CFLAGS) $< -o $@ %.elc: %.el $(call quiet,EMACS) -batch -f batch-byte-compile $< .deps/%.d: %.c $(all_deps) @set -e; rm -f $@; mkdir -p $$(dirname $@) ; \ - $(CC) -M $(CPPFLAGS) $(CFLAGS) $< > $@.$$$$; \ + $(CC) -M $(CPPFLAGS) $(FINAL_CFLAGS) $< > $@.$$$$; \ sed 's,'$$(basename $*)'\.o[ :]*,$*.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ .deps/%.d: %.cc $(all_deps) @set -e; rm -f $@; mkdir -p $$(dirname $@) ; \ - $(CXX) -M $(CPPFLAGS) $(CXXFLAGS) $< > $@.$$$$; \ + $(CXX) -M $(CPPFLAGS) $(FINAL_CXXFLAGS) $< > $@.$$$$; \ sed 's,'$$(basename $*)'\.o[ :]*,$*.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ diff --git a/Makefile.local b/Makefile.local index 4b29ad83..af1c9b5c 100644 --- a/Makefile.local +++ b/Makefile.local @@ -22,7 +22,7 @@ notmuch_client_srcs = \ notmuch_client_modules = $(notmuch_client_srcs:.c=.o) notmuch: $(notmuch_client_modules) lib/notmuch.a - $(call quiet,CXX) $^ $(LDFLAGS) -o $@ + $(call quiet,CXX,$(LDFLAGS)) $^ $(FINAL_LDFLAGS) -o $@ notmuch.1.gz: notmuch.1 $(call quiet,gzip) --stdout $^ > $@ diff --git a/configure b/configure index 54d55cba..488b3bd7 100755 --- a/configure +++ b/configure @@ -224,11 +224,11 @@ HAVE_VALGRIND = ${have_valgrind} VALGRIND_CFLAGS = ${valgrind_cflags} # Combined flags for compiling and linking against all of the above -override CFLAGS += -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS) \\ +CONFIGURE_CFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS) \\ \$(TALLOC_CFLAGS) -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \\ \$(VALGRIND_CFLAGS) -override CXXFLAGS += -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS) \\ +CONFIGURE_CXXFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS) \\ \$(TALLOC_CFLAGS) -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \\ \$(VALGRIND_CFLAGS) \$(XAPIAN_CXXFLAGS) -override LDFLAGS += \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(XAPIAN_LDFLAGS) +CONFIGURE_LDFLAGS = \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(XAPIAN_LDFLAGS) EOF From 943f415f81207ea00bf1efe8c2c1cbf13a094a56 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 4 Dec 2009 15:20:12 -0800 Subject: [PATCH 69/74] configure: Support the capturing of CFLAGS and CXXFLAGS at configure time. These variables can now be set via configure time via environment variables like so: CFLAGS=-g ./configure and subsequent builds will remember these values. The values can still be overridden at compile time by passing make variables: make CFLAGS=-O2 The CXXFLAGS variable is optional. If unset at either configure time or at compile time, it will inherit its value from the CFLAGS variable. (Though if explicitly set at configure time it must be explicitly overriden at compile time---just overriding CFLAGS will not override CXXFLAGS as well.) --- Makefile | 3 --- configure | 8 ++++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 889a78c9..d112be6a 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,3 @@ -# Default FLAGS, (can be overridden by user such as "make CFLAGS=-g") -CFLAGS=-O2 - WARN_CXXFLAGS=-Wall -Wextra -Wwrite-strings -Wswitch-enum WARN_CFLAGS=$(WARN_CXXFLAGS) -Wmissing-declarations diff --git a/configure b/configure index 488b3bd7..ff8baa5e 100755 --- a/configure +++ b/configure @@ -2,6 +2,8 @@ CC=${CC:-gcc} CXX=${CXX:-g++} +CFLAGS=${CFLAGS:--O2} +CXXFLAGS=${CXXFLAGS:-\$(CFLAGS)} # defaults PREFIX=/usr/local @@ -195,6 +197,12 @@ CC = ${CC} # The C++ compiler to use CXX = ${CXX} +# Default FLAGS for C compiler (can be overridden by user such as "make CFLAGS=-g") +CFLAGS = ${CFLAGS} + +# Default FLAGS for C++ compiler (can be overridden by user such as "make CXXFLAGS=-g") +CXXFLAGS = ${CXXFLAGS} + # The prefix to which notmuch should be installed prefix = ${PREFIX} From 4b0327004a3f9a36352b81a5b778740d68bf3078 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 4 Dec 2009 15:32:05 -0800 Subject: [PATCH 70/74] Makefile: Inform user that they might want to call ./configure explicitly. If the Makefile does this for the user, then no arguments are passed. So it's only polite to let the user know that it's possible to get pass those arguments. --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index d112be6a..c3feee1d 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,11 @@ all: notmuch notmuch.1.gz # Before including any other Makefile fragments, get settings from the # output of configure Makefile.config: configure + @echo "" + @echo "Note: Calling ./configure with no command-line arguments. This is often fine," + @echo " but if you want to specify any arguments (such as an alternate prefix" + @echo " into which to install), call ./configure explicitly and then make again." + @echo "" ./configure include Makefile.config From 40e584ecfc2da7b443ceebeabe064c096b3ab999 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 4 Dec 2009 15:37:39 -0800 Subject: [PATCH 71/74] Makefile: Silence compiler errors during dependency generation. We have a bootstrapping issue with our dependency generation. When the Makefile.config doesn't exist yet, the complete compilation flags are not yet available for passing to the compiler to generate the dependencies. But we don't have explicit rules to create these dependency files, (just the implicit rule that is created by the -include), so we can't control when make will attempt to create them. We do have a dependency of the dependency files on Makefile.config, so make should eventually call the compiler with the correct flags and everything should be good. So in the meantime, silence any complaints. --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c3feee1d..248a4cfd 100644 --- a/Makefile +++ b/Makefile @@ -62,13 +62,13 @@ quiet ?= $($1) .deps/%.d: %.c $(all_deps) @set -e; rm -f $@; mkdir -p $$(dirname $@) ; \ - $(CC) -M $(CPPFLAGS) $(FINAL_CFLAGS) $< > $@.$$$$; \ + $(CC) -M $(CPPFLAGS) $(FINAL_CFLAGS) $< > $@.$$$$ 2>/dev/null ; \ sed 's,'$$(basename $*)'\.o[ :]*,$*.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ .deps/%.d: %.cc $(all_deps) @set -e; rm -f $@; mkdir -p $$(dirname $@) ; \ - $(CXX) -M $(CPPFLAGS) $(FINAL_CXXFLAGS) $< > $@.$$$$; \ + $(CXX) -M $(CPPFLAGS) $(FINAL_CXXFLAGS) $< > $@.$$$$ 2>/dev/null ; \ sed 's,'$$(basename $*)'\.o[ :]*,$*.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ From e50461eb84a10f07278f944aea33ce6aa1a244d8 Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 4 Dec 2009 16:05:12 -0800 Subject: [PATCH 72/74] configure: Implement a --help option to document --prefix. Also document that values for CC, CFLAGS, etc. can be specified via environment variables. --- configure | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/configure b/configure index ff8baa5e..fa8e142b 100755 --- a/configure +++ b/configure @@ -1,17 +1,70 @@ #! /bin/sh +# Set several defaults (optionally specified by the user in +# environemnt variables) CC=${CC:-gcc} CXX=${CXX:-g++} CFLAGS=${CFLAGS:--O2} CXXFLAGS=${CXXFLAGS:-\$(CFLAGS)} -# defaults +# Set the defaults for values the user can specify with command-line +# options. PREFIX=/usr/local -# option parsing +usage () +{ + cat < Date: Fri, 4 Dec 2009 16:09:40 -0800 Subject: [PATCH 73/74] Makefile: Mention "./configure --help" now that it exists. Since we're directing the user to ./confgiure for more options, actually tell the user how to discover what those options are. --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 248a4cfd..021fdb82 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ Makefile.config: configure @echo "Note: Calling ./configure with no command-line arguments. This is often fine," @echo " but if you want to specify any arguments (such as an alternate prefix" @echo " into which to install), call ./configure explicitly and then make again." + @echo " See \"./configure --help\" for more details." @echo "" ./configure From 263aeb82f0a1a69864ca41cff4dfa2ae0b8b3f05 Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Sat, 28 Nov 2009 18:57:37 -0500 Subject: [PATCH 74/74] fix Makefile.local to install bash completion definitions as not executable --- Makefile.local | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.local b/Makefile.local index af1c9b5c..933ff4c7 100644 --- a/Makefile.local +++ b/Makefile.local @@ -45,7 +45,7 @@ install-emacs: install emacs install-bash: install -d $(DESTDIR)$(bash_completion_dir) - install contrib/notmuch-completion.bash \ + install -m0644 contrib/notmuch-completion.bash \ $(DESTDIR)$(bash_completion_dir)/notmuch SRCS := $(SRCS) $(notmuch_client_srcs)