[PATCH] emacs: In hello mode, bind `C-tab' to move backwards through widgets.
From: David Edmondson <d...@dme.org> `C-tab' is now the inverse operation to `tab'. --- emacs/notmuch-hello.el |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 538785f..bf49bb1 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -448,6 +448,7 @@ should be. Returns a cons cell `(tags-per-line width)'." (use-local-map widget-keymap) (local-set-key "=" 'notmuch-hello-update) + (local-set-key (kbd "") 'widget-backward) (local-set-key "G" 'notmuch-hello-poll-and-update) (local-set-key "m" 'notmuch-mua-mail) (local-set-key "q" '(lambda () (interactive) (kill-buffer (current-buffer -- 1.7.0
[PATCH] notmuch: Fix off-by-one errors if a header is >200 characters long.
From: David Edmondson <d...@dme.org> If a single header is more than 200 characters long a set of 'off by one' errors cause memory corruption. When allocating memory with: a = malloc (len); the last usable byte of the memory is 'a + len - 1' rather than 'a + len'. Fix the same bug when calculating the current offset should the buffer used for collecting the output header need to be reallocated. --- This is the cause of my segmentation fault (or bus error) during `notmuch reply'. The patch is for the 0.3.1 branch, but I'd expect that it will apply cleanly to master. gmime-filter-headers.c |6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gmime-filter-headers.c b/gmime-filter-headers.c index 2f3df80..7db3779 100644 --- a/gmime-filter-headers.c +++ b/gmime-filter-headers.c @@ -169,7 +169,7 @@ filter_filter (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace, headers->lineptr = headers->line = malloc (headers->line_size); } lineptr = headers->lineptr; - lineend = headers->line + headers->line_size; + lineend = headers->line + headers->line_size - 1; if (lineptr == NULL) return; outptr = filter->outbuf; @@ -185,8 +185,8 @@ filter_filter (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace, if (lineptr == lineend) { headers->line_size *= 2; headers->line = xrealloc (headers->line, headers->line_size); - lineptr = headers->line + headers->line_size / 2; - lineend = headers->line + headers->line_size; + lineptr = headers->line + (headers->line_size / 2) - 1; + lineend = headers->line + headers->line_size - 1; } if (headers->saw_nl && *inptr != ' ' && *inptr != '\t') { -- 1.7.0
[PATCH] emacs: Allow tuning of the tag/saved search layout.
From: David Edmondson <d...@dme.org> Add `notmuch-hello-tag-width', which has three potential sets of values: - t: automatically calculate the number of tags per line possible based on the tags to be shown and the window width, - an integer: a lower bound on the number of characters that will be used to display each tag, - a float: a fraction of the window width that is the lower bound on the number of characters that should be used for each tag. So: - if you would like two columns of tags, set this to 0.5. - if you would like a single column of tags, set this to 1.0. - if you would like tags to be 30 characters wide, set this to 30. - if you don't want to worry about all of this nonsense, leave this set to `t'. --- Carl, for 0.4. You mentioned that you might like to have a single column of tags/saved searches, but others appear to like multiple columns. So, make it configurable. emacs/notmuch-hello.el | 62 +++ 1 files changed, 56 insertions(+), 6 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 378d41c..f7703d9 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -141,13 +141,63 @@ diagonal." (defun notmuch-saved-search-count (search) (car (process-lines notmuch-command "count" search))) +(defcustom notmuch-hello-tag-width t + "How wide should a tag be? + +This variable has three potential sets of values: + +- t: automatically calculate the number of tags per line possible + based on the tags to be shown and the window width, +- an integer: a lower bound on the number of characters that will + be used to display each tag, +- a float: a fraction of the window width that is the lower bound + on the number of characters that should be used for each tag. + +So: +- if you would like two columns of tags, set this to 0.5. +- if you would like a single column of tags, set this to 1.0. +- if you would like tags to be 30 characters wide, set this to + 30. +- if you don't want to worry about all of this nonsense, leave + this set to `t'." + :group 'notmuch + :type '(choice + (const :tag "Automatically calculated" t) + (integer :tag "Number of characters") + (float :tag "Fraction of window"))) + +(defun notmuch-hello-tags-per-line (widest) + "Determine how many tags to show per line and how wide they +should be. Returns a cons cell `(tags-per-line width)'." + (let ((tags-per-line +(cond + ((integerp notmuch-hello-tag-width) + (max 1 + (/ (- (window-width) notmuch-hello-indent) + ;; Count is 7 wide (6 digits plus space), 1 for the space + ;; after the name. + (+ 7 1 (max notmuch-hello-tag-width widest) + + ((floatp notmuch-hello-tag-width) + (let* ((available-width (- (window-width) notmuch-hello-indent)) + (proposed-width (max (* available-width notmuch-hello-tag-width) widest))) +(floor available-width proposed-width))) + + (t + (max 1 + (/ (- (window-width) notmuch-hello-indent) + ;; Count is 7 wide (6 digits plus space), 1 for the space + ;; after the name. + (+ 7 1 widest))) + +(cons tags-per-line (/ (- (window-width) notmuch-hello-indent + (* tags-per-line (+ 7 1))) + tags-per-line + (defun notmuch-hello-insert-tags (tag-alist widest target) - (let* ((tags-per-line (max 1 -(/ (- (window-width) notmuch-hello-indent) - ;; Count is 7 wide (6 digits plus - ;; space), 1 for the space after the - ;; name. - (+ 7 1 widest + (let* ((tags-and-width (notmuch-hello-tags-per-line widest)) +(tags-per-line (car tags-and-width)) +(widest (cdr tags-and-width)) (count 0) (reordered-list (notmuch-hello-reflect tag-alist tags-per-line)) ;; Hack the display of the buttons used. -- 1.7.0
[PATCH] emacs/notmuch-wash.el: Add `notmuch-wash-convert-inline-patch-to-part'.
From: David Edmondson <d...@dme.org> Detect inline patches and convert them to fake attachments, in order that `diff-mode' highlighting can be applied to the patch. This can be enabled by customising `notmuch-show-insert-text/plain-hook'. --- emacs/notmuch-show.el |3 ++- emacs/notmuch-wash.el | 38 ++ 2 files changed, 40 insertions(+), 1 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index eb5335f..4b1baf3 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -71,7 +71,8 @@ any given message." "Functions used to improve the display of text/plain parts." :group 'notmuch :type 'hook - :options '(notmuch-wash-wrap-long-lines + :options '(notmuch-wash-convert-inline-patch-to-part +notmuch-wash-wrap-long-lines notmuch-wash-tidy-citations notmuch-wash-elide-blank-lines notmuch-wash-excerpt-citations)) diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el index 57f0cc5..bf0a354 100644 --- a/emacs/notmuch-wash.el +++ b/emacs/notmuch-wash.el @@ -23,6 +23,8 @@ (require 'coolj) +(declare-function notmuch-show-insert-bodypart "notmuch-show" (msg part depth) + ;; (defvar notmuch-wash-signature-regexp @@ -231,4 +233,40 @@ When doing so, maintaining citation leaders in the wrapped text." ;; +(require 'diff-mode) + +(defvar diff-file-header-re) ; From `diff-mode.el'. + +(defun notmuch-wash-convert-inline-patch-to-part (depth) + "Convert an inline patch into a fake 'text/x-diff' attachment. + +Given that this function guesses whether a buffer includes a +patch and then guesses the extent of the patch, there is scope +for error." + + (goto-char (point-min)) + (if (re-search-forward diff-file-header-re nil t) + (progn + (beginning-of-line -1) + (let ((patch-start (point)) + (patch-end (point-max)) + part) + (goto-char patch-start) + (if (or + ;; Patch ends with signature. + (re-search-forward notmuch-wash-signature-regexp nil t) + ;; Patch ends with bugtraq comment. + (re-search-forward "^\\*\\*\\* " nil t)) + (setq patch-end (match-beginning 0))) + (save-restriction + (narrow-to-region patch-start patch-end) + (setq part (plist-put part :content-type "text/x-diff")) + (setq part (plist-put part :content (buffer-string))) + (setq part (plist-put part :id -1)) + (setq part (plist-put part :filename "inline patch")) + (delete-region (point-min) (point-max)) + (notmuch-show-insert-bodypart nil part depth)) + +;; + (provide 'notmuch-wash) -- 1.7.0
[PATCH 2/2] emacs: Fix `notmuch-hello-insert-tags' to correctly draw the tags.
From: David Edmondson <d...@dme.org> The fix in 1e1871154341cdd3413fe3f32e3aae477826d815 broke end-of-row wrapping when drawing the table of tags/saved searches. Fix that and improve the readability of the matrix reflection code to hasten future debugging. --- Carl, this is a fix for a regression that I caused this morning when fixing the line wrapping. Serves me right for doing more than was really necessary in the previous patch. Sorry :-( emacs/notmuch-hello.el | 37 +++-- 1 files changed, 19 insertions(+), 18 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 1b59ef1..6a1c56e 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -118,23 +118,24 @@ (+ (/ dividend divisor) (if (> (% dividend divisor) 0) 1 0))) -(defun notmuch-hello-reflect (list width) - "Reflect a `width' wide matrix represented by `list' along the +(defun notmuch-hello-reflect-generate-row (ncols nrows row list) + (let ((len (length list))) +(loop for col from 0 to (- ncols 1) + collect (let ((offset (+ (* nrows col) row))) + (if (< offset len) + (nth offset list) + ;; Don't forget to insert an empty slot in the + ;; output matrix if there is no corresponding + ;; value in the input matrix. + nil) + +(defun notmuch-hello-reflect (list ncols) + "Reflect a `ncols' wide matrix represented by `list' along the diagonal." ;; Not very lispy... - (let* ((len (length list)) -(nrows (notmuch-hello-roundup len width))) + (let ((nrows (notmuch-hello-roundup (length list) ncols))) (loop for row from 0 to (- nrows 1) - append (loop for col from 0 to (- width 1) - ;; How could we calculate the offset just once - ;; per inner-loop? - if (< (+ (* nrows col) row) len) - collect (nth (+ (* nrows col) row) list) - else - ;; Don't forget to insert an empty slot in the - ;; output matrix if there is no corresponding - ;; value in the input matrix. - collect nil + append (notmuch-hello-reflect-generate-row ncols nrows row list (defun notmuch-hello-widget-search (widget ignore) (notmuch-search (widget-get widget @@ -179,10 +180,10 @@ diagonal." ;; can just insert `(- widest (length name))' spaces - ;; the column separator is included in the button if ;; `(equal widest (length name)'. - (widget-insert (make-string (- widest (length name)) ? ))) - (setq count (1+ count)) - (if (eq (% count tags-per-line) 0) - (widget-insert "\n" + (widget-insert (make-string (- widest (length name)) ? + (setq count (1+ count)) + (if (eq (% count tags-per-line) 0) + (widget-insert "\n"))) reordered-list) ;; If the last line was not full (and hence did not include a -- 1.7.0
[PATCH 1/2] emacs: If 'all tags' is not shown, don't use it when calculating widths.
From: David Edmondson <d...@dme.org> If the 'all tags' section of the hello buffer will not be shown, don't consider those tags when determining the number of saved searches that can be displayed on a single line. --- emacs/notmuch-hello.el | 38 -- 1 files changed, 20 insertions(+), 18 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 50d8911..1b59ef1 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -284,8 +284,9 @@ diagonal." if (> (string-to-number (notmuch-saved-search-count (cdr elem))) 0) collect elem))) (saved-widest (notmuch-hello-longest-label saved-alist)) -(alltags-alist (mapcar '(lambda (tag) (cons tag (concat "tag:" tag))) - (process-lines notmuch-command "search-tags"))) +(alltags-alist (if notmuch-show-all-tags-list + (mapcar '(lambda (tag) (cons tag (concat "tag:" tag))) + (process-lines notmuch-command "search-tags" (alltags-widest (notmuch-hello-longest-label alltags-alist)) (widest (max saved-widest alltags-widest))) @@ -360,26 +361,27 @@ diagonal." (indent-rigidly start (point) notmuch-hello-indent))) (when alltags-alist - (if notmuch-show-all-tags-list - (progn - (widget-insert "\nAll tags: ") - (widget-create 'push-button - :notify (lambda (widget ignore) -(setq notmuch-show-all-tags-list nil) -(notmuch-hello-update)) - "hide") - (widget-insert "\n\n") - (let ((start (point))) - (setq found-target-pos (notmuch-hello-insert-tags alltags-alist widest target)) - (if (not final-target-pos) - (setq final-target-pos found-target-pos)) - (indent-rigidly start (point) notmuch-hello-indent))) - (widget-insert "\n") + (widget-insert "\nAll tags: ") + (widget-create 'push-button +:notify (lambda (widget ignore) + (setq notmuch-show-all-tags-list nil) + (notmuch-hello-update)) +"hide") + (widget-insert "\n\n") + (let ((start (point))) + (setq found-target-pos (notmuch-hello-insert-tags alltags-alist widest target)) + (if (not final-target-pos) + (setq final-target-pos found-target-pos)) + (indent-rigidly start (point) notmuch-hello-indent))) + + (widget-insert "\n") + + (if (not notmuch-show-all-tags-list) (widget-create 'push-button :notify (lambda (widget ignore) (setq notmuch-show-all-tags-list t) (notmuch-hello-update)) - "Show all tags" + "Show all tags"))) (let ((start (point))) (widget-insert "\n\n") -- 1.7.0
[PATCH] emacs: Fix column alignment in `notmuch-hello-insert-tags'
From: David Edmondson <d...@dme.org> Re-working the saved search/tag insertion to buttonize only the name of the saved search/tag plus one space broke the calculation of how much filler is required to complete the column, resulting in lines wider than the window. --- emacs/notmuch-hello.el | 44 +++- 1 files changed, 27 insertions(+), 17 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index cbe414f..50d8911 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -148,8 +148,9 @@ diagonal." (defun notmuch-hello-insert-tags (tag-alist widest target) (let* ((tags-per-line (max 1 (/ (- (window-width) notmuch-hello-indent) - ;; Count is 7 wide, 1 for the space - ;; after the name. + ;; Count is 7 wide (6 digits plus + ;; space), 1 for the space after the + ;; name. (+ 7 1 widest (count 0) (reordered-list (notmuch-hello-reflect tag-alist tags-per-line)) @@ -159,21 +160,30 @@ diagonal." (found-target-pos nil)) ;; dme: It feels as though there should be a better way to ;; implement this loop than using an incrementing counter. -(loop for elem in reordered-list - do (progn - ;; (not elem) indicates an empty slot in the matrix. - (when elem -(widget-insert (format "%6s " (notmuch-saved-search-count (cdr elem -(if (string= (format "%s " (car elem)) target) -(setq found-target-pos (point-marker))) -(widget-create 'push-button - :notify #'notmuch-hello-widget-search - :notmuch-search-terms (cdr elem) - (format "%s " (car elem))) -(insert (make-string (1+ (- widest (length (car elem ? ))) - (setq count (1+ count)) - (if (eq (% count tags-per-line) 0) - (widget-insert "\n" +(mapc (lambda (elem) + ;; (not elem) indicates an empty slot in the matrix. + (when elem + (let* ((name (car elem)) +(query (cdr elem)) +(formatted-name (format "%s " name))) + (widget-insert (format "%6s " (notmuch-saved-search-count query))) + (if (string= formatted-name target) + (setq found-target-pos (point-marker))) + (widget-create 'push-button + :notify #'notmuch-hello-widget-search + :notmuch-search-terms query + formatted-name) + ;; Insert enough space to consume the rest of the + ;; column. Because the button for the name is `(1+ + ;; (length name))' long (due to the trailing space) we + ;; can just insert `(- widest (length name))' spaces - + ;; the column separator is included in the button if + ;; `(equal widest (length name)'. + (widget-insert (make-string (- widest (length name)) ? ))) + (setq count (1+ count)) + (if (eq (% count tags-per-line) 0) + (widget-insert "\n" + reordered-list) ;; If the last line was not full (and hence did not include a ;; carriage return), insert one now. -- 1.7.0
[PATCH] emacs: Tell the user how many addresses matched when completing
From: David Edmondson <d...@dme.org> When completing an address, tell the user how many addresses in the database matched the query. --- emacs/notmuch-address.el |6 -- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-address.el b/emacs/notmuch-address.el index 69a52a2..a295204 100644 --- a/emacs/notmuch-address.el +++ b/emacs/notmuch-address.el @@ -53,9 +53,11 @@ line." (orig (buffer-substring-no-properties beg end)) (completion-ignore-case t) (options (notmuch-address-options orig)) -(chosen (if (eq (length options) 1) +(num-options (length options)) +(chosen (if (eq num-options 1) (car options) - (completing-read "Address: " (cdr options) nil nil (car options) + (completing-read (format "Address (%s matches): " num-options 1) + (cdr options) nil nil (car options) 'notmuch-address-history (when chosen (push chosen notmuch-address-history) -- 1.7.0
[PATCH] emacs: Remove duplicate declaration of `notmuch-folders'
From: David Edmondson <d...@dme.org> --- emacs/notmuch.el |5 - 1 files changed, 0 insertions(+), 5 deletions(-) diff --git a/emacs/notmuch.el b/emacs/notmuch.el index 428ae6c..e207180 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -659,11 +659,6 @@ characters as well as `_.+-'. (apply 'notmuch-call-notmuch-process "tag" (append action-split (list notmuch-search-query-string) nil -(defcustom notmuch-folders (quote (("inbox" . "tag:inbox") ("unread" . "tag:unread"))) - "List of searches for the notmuch folder view" - :type '(alist :key-type (string) :value-type (string)) - :group 'notmuch) - (defun notmuch-search-buffer-title (query) "Returns the title for a buffer with notmuch search results." (let* ((folder (rassoc-if (lambda (key) -- 1.7.0
[PATCH] emacs: `notmuch' should display the `notmuch-hello' interface
From: David Edmondson <d...@dme.org> --- emacs/notmuch-hello.el |1 - emacs/notmuch-lib.el |5 + emacs/notmuch.el |7 +++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 30b3a5e..bd882b8 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -24,7 +24,6 @@ (require 'cl) (require 'notmuch-lib) -(require 'notmuch) (require 'notmuch-mua) (declare-function notmuch-search "notmuch" (query oldest-first target-thread target-line continuation)) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 47c74b9..b64aeab 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -33,6 +33,11 @@ :type '(alist :key-type (string) :value-type (string)) :group 'notmuch) +(defcustom notmuch-search-oldest-first t + "Show the oldest mail first when searching." + :type 'boolean + :group 'notmuch) + ;; (defun notmuch-version () diff --git a/emacs/notmuch.el b/emacs/notmuch.el index eecff23..428ae6c 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -54,6 +54,7 @@ (require 'notmuch-lib) (require 'notmuch-show) (require 'notmuch-mua) +(require 'notmuch-hello) (defcustom notmuch-search-result-format `(("date" . "%s ") @@ -221,8 +222,6 @@ For a mouse binding, return nil." (defvar notmuch-search-query-string) (defvar notmuch-search-target-thread) (defvar notmuch-search-target-line) -(defvar notmuch-search-oldest-first t - "Show the oldest mail first in the search-mode") (defvar notmuch-search-continuation) (defvar notmuch-search-disjunctive-regexp "\\<[oO][rR]\\>") @@ -811,9 +810,9 @@ current search results AND that are tagged with the given tag." ;;;###autoload (defun notmuch () - "Run notmuch to display all mail with tag of 'inbox'" + "Run notmuch and display saved searches, known tags, etc." (interactive) - (notmuch-search "tag:inbox" notmuch-search-oldest-first)) + (notmuch-hello)) (setq mail-user-agent 'notmuch-user-agent) -- 1.7.0
[PATCH] emacs: Fix `notmuch-show-rewind' in the presence of invisible text
From: David Edmondson <d...@dme.org> When determining whether or not to re-align the head of the current message with the top of the window, use `count-screen-lines' rather than `count-lines' to allow for invisible text in the preceding message. When comparing that number of lines against `next-screen-context-lines', realign if the number of lines of the previous message visible is 'smaller than or equal to' rather than just 'smaller than' to improve usability. --- emacs/notmuch-show.el |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index f5de8ae..eb5335f 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -833,8 +833,8 @@ any effects from previous calls to ;; If a small number of lines from the previous message are ;; visible, realign so that the top of the current message is at ;; the top of the screen. - (if (< (count-lines (window-start) (notmuch-show-message-top)) -next-screen-context-lines) + (if (<= (count-screen-lines (window-start) start-of-message) + next-screen-context-lines) (progn (goto-char (notmuch-show-message-top)) (notmuch-show-message-adjust))) -- 1.7.0