[PATCH] emacs: Allow the display of absolute dates in the header line.

2010-05-19 Thread Dirk Hohndel
On Wed, 19 May 2010 07:44:18 +0100, David Edmondson  wrote:
> Add `notmuch-show-relative-dates' to control whether the summary line
> in `notmuch-show' mode displays relative dates (e.g. '26 mins. ago') or
> the full date string from the message. Default to `t' for
> compatibility with the previous behaviour.

Excellent - thanks for providing this (and all I did was mention it
briefly on IRC... I love this project)

/D

-- 
Dirk Hohndel
Intel Open Source Technology Center


[PATCH 13/13] emacs: Allow the display of absolute dates in the header line.

2010-05-19 Thread David Edmondson
Add `notmuch-show-relative-dates' to control whether the summary line
in `notmuch-show' mode displays relative dates (e.g. '26 mins ago') or
the full date string from the message. Default to `t' for
compatibility with the previous behaviour.
---
 emacs/notmuch-show.el |9 -
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 7601857..cbc3012 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -58,6 +58,11 @@ any given message."
   :group 'notmuch
   :type 'boolean)

+(defcustom notmuch-show-relative-dates t
+  "Display relative dates in the message summary line."
+  :group 'notmuch
+  :type 'boolean)
+
 (defvar notmuch-show-markup-headers-hook '(notmuch-show-colour-headers)
   "A list of functions called to decorate the headers listed in
 `notmuch-message-headers'.")
@@ -407,7 +412,9 @@ current buffer, if possible."
 (setq message-start (point-marker))

 (notmuch-show-insert-headerline headers
-   (or (plist-get msg :date_relative)
+   (or (if notmuch-show-relative-dates
+   (plist-get msg :date_relative)
+ nil)
(plist-get headers :Date))
(plist-get msg :tags) depth)

-- 
1.7.1



[PATCH 12/13] emacs: Tags should be shown with `notmuch-tag-face'.

2010-05-19 Thread David Edmondson
Use the same face for tags in `notmuch-show' mode as that used in
`notmuch-search' mode.
---
 emacs/notmuch-show.el |6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index ff1a7a7..7601857 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -189,7 +189,8 @@ any given message."
 (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
(let ((inhibit-read-only t))
  (replace-match (concat "("
-(mapconcat 'identity tags " ")
+(propertize (mapconcat 'identity tags " ")
+'face 'notmuch-tag-face)
 ")"))

 (defun notmuch-show-insert-headerline (headers date tags depth)
@@ -201,7 +202,8 @@ message at DEPTH in the current thread."
" ("
date
") ("
-   (mapconcat 'identity tags " ")
+   (propertize (mapconcat 'identity tags " ")
+   'face 'notmuch-tag-face)
")\n")
 (overlay-put (make-overlay start (point)) 'face 
'notmuch-message-summary-face)))

-- 
1.7.1



[PATCH 11/13] emacs: Pretty print the numbers of matching messages.

2010-05-19 Thread David Edmondson
Insert a separator every three digits when outputting numbers. Allow
the user to choose the separator by customizing
`notmuch-decimal-separator'. Widen the space allocated for message
counts accordingly.
---
 emacs/notmuch-hello.el |   38 +++---
 1 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 538785f..7ade0eb 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -91,6 +91,13 @@ So:
  (integer :tag "Number of characters")
  (float :tag "Fraction of window")))

+(defcustom notmuch-decimal-separator ","
+  "The string used as a decimal separator.
+
+Typically \",\" in the US and UK and \".\" in Europe."
+  :group 'notmuch
+  :type 'string)
+
 (defvar notmuch-hello-url "http://notmuchmail.org";
   "The `notmuch' web site.")

@@ -103,6 +110,17 @@ So:
 notmuch-recent-searches-max)
   (setq notmuch-hello-recent-searches (butlast 
notmuch-hello-recent-searches

+(defun notmuch-hello-nice-number (n)
+  (let (result)
+(while (> n 0)
+  (push (% n 1000) result)
+  (setq n (/ n 1000)))
+(apply #'concat
+ (number-to-string (car result))
+ (mapcar (lambda (elem)
+ (format "%s%03d" notmuch-decimal-separator elem))
+(cdr result)
+
 (defun notmuch-hello-trim (search)
   "Trim whitespace."
   (if (string-match "^[[:space:]]*\\(.*[^[:space:]]\\)[[:space:]]*$" search)
@@ -180,9 +198,9 @@ should be. Returns a cons cell `(tags-per-line width)'."
  ((integerp notmuch-column-control)
   (max 1
(/ (- (window-width) notmuch-hello-indent)
-  ;; Count is 7 wide (6 digits plus space), 1 for the space
+  ;; Count is 9 wide (8 digits plus space), 1 for the space
   ;; after the name.
-  (+ 7 1 (max notmuch-column-control widest)
+  (+ 9 1 (max notmuch-column-control widest)

  ((floatp notmuch-column-control)
   (let* ((available-width (- (window-width) notmuch-hello-indent))
@@ -192,12 +210,15 @@ should be. Returns a cons cell `(tags-per-line width)'."
  (t
   (max 1
(/ (- (window-width) notmuch-hello-indent)
-  ;; Count is 7 wide (6 digits plus space), 1 for the space
+  ;; Count is 9 wide (8 digits plus space), 1 for the space
   ;; after the name.
-  (+ 7 1 widest)))
+  (+ 9 1 widest)))

 (cons tags-per-line (/ (- (window-width) notmuch-hello-indent
- (* tags-per-line (+ 7 1)))
+ ;; Count is 9 wide (8 digits plus
+ ;; space), 1 for the space after the
+ ;; name.
+ (* tags-per-line (+ 9 1)))
   tags-per-line

 (defun notmuch-hello-insert-tags (tag-alist widest target)
@@ -218,7 +239,9 @@ should be. Returns a cons cell `(tags-per-line width)'."
  (let* ((name (car elem))
 (query (cdr elem))
 (formatted-name (format "%s " name)))
-   (widget-insert (format "%6s " (notmuch-saved-search-count 
query)))
+   (widget-insert (format "%8s "
+  (notmuch-hello-nice-number
+   (string-to-number 
(notmuch-saved-search-count query)
(if (string= formatted-name target)
(setq found-target-pos (point-marker)))
(widget-create 'push-button
@@ -323,7 +346,8 @@ should be. Returns a cons cell `(tags-per-line width)'."
 :notify (lambda (&rest ignore)
   (notmuch-hello-update))
 :help-echo "Refresh"
-(car (process-lines notmuch-command "count")))
+(notmuch-hello-nice-number
+ (string-to-number (car (process-lines notmuch-command 
"count")
   (widget-insert " messages (that's not much mail).\n"))

 (let ((found-target-pos nil)
-- 
1.7.1



[PATCH 10/13] emacs: In search mode, truncate authors using invisible text.

2010-05-19 Thread David Edmondson
Rather than discarding authors when truncated to fit the defined
column width, mark the text beyond the end of the column as invisible
and allow `isearch' to be used over the text so hidden.

This allows us to retain the compact display whilst enabling a user to
find the elided text.
---
 emacs/notmuch.el |   61 +++--
 1 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index c2fefe5..10babe4 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -608,23 +608,52 @@ matching will be applied."
  (t
   (setq tags-faces (cdr tags-faces)

+(defun notmuch-search-isearch-authors-show (overlay)
+  (remove-from-invisibility-spec (cons (overlay-get overlay 'invisible) t)))
+
 (defun notmuch-search-insert-authors (format-string authors)
-  (insert (let* ((formatted-sample (format format-string ""))
-(formatted-authors (format format-string authors))
-(truncated-string
- (if (> (length formatted-authors)
-(length formatted-sample))
- (concat (substring authors 0 (- (length formatted-sample) 
4)) "... ")
-   formatted-authors)))
-   ;; Need to save the match data to avoid interfering with
-   ;; `notmuch-search-process-filter'.
-   (save-match-data
- (if (string-match "\\(.*\\)|\\(..*\\)" truncated-string)
- (concat (propertize (concat (match-string 1 truncated-string) 
",")
- 'face 'notmuch-search-matching-authors)
- (propertize (match-string 2 truncated-string)
- 'face 
'notmuch-search-non-matching-authors))
-   (propertize truncated-string 'face 
'notmuch-search-matching-authors))
+  (let* ((propertized-authors
+ ;; Need to save the match data to avoid interfering with
+ ;; `notmuch-search-process-filter'.
+ (save-match-data
+   ;; Authors that don't match the search query are shown in a
+   ;; different font.
+   (if (string-match "\\(.*\\)|\\(..*\\)" authors)
+   (concat (propertize (concat (match-string 1 authors) ",")
+   'face 'notmuch-search-matching-authors)
+   (propertize (match-string 2 authors)
+   'face 'notmuch-search-non-matching-authors))
+ (propertize authors 'face 'notmuch-search-matching-authors
+
+(formatted-sample (format format-string ""))
+(formatted-authors (format format-string propertized-authors))
+visible-string invisible-string)
+
+;; Determine the part of the authors that will be visible by
+;; default.
+(if (> (length formatted-authors)
+  (length formatted-sample))
+   ;; 4 is `(length "... ")'.
+   (let ((visible-length (- (length formatted-sample) 4)))
+ (setq visible-string (substring propertized-authors 0 visible-length)
+   invisible-string (substring propertized-authors 
visible-length)))
+  (setq visible-string formatted-authors
+   invisible-string nil))
+
+;; Insert both the visible and invisible author strings.
+(insert visible-string)
+(when invisible-string
+  (let ((start (point))
+   (invis-spec (make-symbol "notmuch-search-authors"))
+   overlay)
+   (insert invisible-string)
+   ;; Using a cons-cell here causes an ellipsis to be inserted
+   ;; instead of the invisible text.
+   (add-to-invisibility-spec (cons invis-spec t))
+   (setq overlay (make-overlay start (point)))
+   (overlay-put overlay 'invisible invis-spec)
+   (overlay-put overlay 'isearch-open-invisible 
#'notmuch-search-isearch-authors-show)
+   (insert " ")

 (defun notmuch-search-insert-field (field date count authors subject tags)
   (cond
-- 
1.7.1



[PATCH 09/13] emacs: Avoid runtime use of `cl'.

2010-05-19 Thread David Edmondson
The GNU Emacs Lisp Reference Manual section D.1 says:

> *  Please don't require the cl package of Common Lisp extensions at
>run time. Use of this package is optional, and it is not part of
>the standard Emacs namespace. If your package loads cl at run time,
>that could cause name clashes for users who don't use that package.
>
>However, there is no problem with using the cl package at compile
>time, with (eval-when-compile (require 'cl)). That's sufficient for
>using the macros in the cl package, because the compiler expands
>them before generating the byte-code.

Follow this advice, requiring the following changes where `cl' was
used at runtime:

- replace `rassoc-if' in `notmuch-search-buffer-title' with the `loop'
  macro and inline code. At the same time find the longest prefix
  which matches the query rather than simply the last,
- replace `union', `intersection' and `set-difference' in
  `notmuch-show-add-tag' and `notmuch-show-remove-tag' with local code
  to calculate the result of adding and removing a list of tags from
  another list of tags.
---
 emacs/notmuch-hello.el |2 +-
 emacs/notmuch-show.el  |   54 +++
 emacs/notmuch.el   |   16 +
 3 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index acf40bc..538785f 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -19,9 +19,9 @@
 ;;
 ;; Authors: David Edmondson 

+(eval-when-compile (require 'cl))
 (require 'widget)
 (require 'wid-edit) ; For `widget-forward'.
-(require 'cl)

 (require 'notmuch-lib)
 (require 'notmuch-mua)
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 4b1baf3..ff1a7a7 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -21,7 +21,7 @@
 ;; Authors: Carl Worth 
 ;;  David Edmondson 

-(require 'cl)
+(eval-when-compile (require 'cl))
 (require 'mm-view)
 (require 'message)
 (require 'mm-decode)
@@ -908,29 +908,55 @@ to stdout or stderr will appear in the *Messages* buffer."
 (list command " < "
   (shell-quote-argument (notmuch-show-get-filename)

+(defun notmuch-show-add-tags-worker (current-tags add-tags)
+  "Add to `current-tags' with any tags from `add-tags' not
+currently present and return the result."
+  (let ((result-tags (copy-seq current-tags)))
+(mapc (lambda (add-tag)
+   (unless (member add-tag current-tags)
+ (setq result-tags (push add-tag result-tags
+   add-tags)
+(sort result-tags 'string<)))
+
+(defun notmuch-show-del-tags-worker (current-tags del-tags)
+  "Remove any tags in `del-tags' from `current-tags' and return
+the result."
+  (let ((result-tags (copy-seq current-tags)))
+(mapc (lambda (del-tag)
+   (setq result-tags (delete del-tag result-tags)))
+ del-tags)
+result-tags))
+
 (defun notmuch-show-add-tag (&rest toadd)
   "Add a tag to the current message."
   (interactive
(list (notmuch-select-tag-with-completion "Tag to add: ")))
-  (apply 'notmuch-call-notmuch-process
-(append (cons "tag"
-  (mapcar (lambda (s) (concat "+" s)) toadd))
-(cons (notmuch-show-get-message-id) nil)))
-  (notmuch-show-set-tags (sort (union toadd (notmuch-show-get-tags) :test 
'string=) 'string<)))
+
+  (let* ((current-tags (notmuch-show-get-tags))
+(new-tags (notmuch-show-add-tags-worker current-tags toadd)))
+
+(unless (equal current-tags new-tags)
+  (apply 'notmuch-call-notmuch-process
+(append (cons "tag"
+  (mapcar (lambda (s) (concat "+" s)) toadd))
+(cons (notmuch-show-get-message-id) nil)))
+  (notmuch-show-set-tags new-tags

 (defun notmuch-show-remove-tag (&rest toremove)
   "Remove a tag from the current message."
   (interactive
(list (notmuch-select-tag-with-completion
  "Tag to remove: " (notmuch-show-get-message-id
-  (let ((tags (notmuch-show-get-tags)))
-(if (intersection tags toremove :test 'string=)
-   (progn
- (apply 'notmuch-call-notmuch-process
-(append (cons "tag"
-  (mapcar (lambda (s) (concat "-" s)) toremove))
-(cons (notmuch-show-get-message-id) nil)))
- (notmuch-show-set-tags (sort (set-difference tags toremove :test 
'string=) 'string<))
+
+  (let* ((current-tags (notmuch-show-get-tags))
+(new-tags (notmuch-show-del-tags-worker current-tags toremove)))
+
+(unless (equal current-tags new-tags)
+  (apply 'notmuch-call-notmuch-process
+(append (cons "tag"
+  (mapcar (lambda (s) (concat "-" s)) toremove))
+(cons (notmuch-show-get-message-id) nil)))
+  (notmuch-show-set-tags new-tags

 (defun notmuch-show-toggle-headers ()
   "Toggle the visibility of the current message headers."
diff --git a/em

[PATCH 08/13] emacs: Reuse rather than reinvent message header filtering

2010-05-19 Thread David Edmondson
From: Sebastian Spaeth 

In notmuch-mua-reply we were filtering out the Subject and To headers
manually in a loop, but message mode offers a nice function for
exactly that. Simplify the code by using that. Also, as
notmuch-mua-mail already sorts and hides headers that we want sorted
and hidden, we can safely remove those 2 functions from here as well.

Signed-off-by: Sebastian Spaeth 
---
 emacs/notmuch-mua.el |7 +--
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index bd06e3c..6318c15 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -92,12 +92,7 @@ list."
((same-window-regexps '("\\*mail .*")))
   (notmuch-mua-mail (mail-header 'to headers)
(mail-header 'subject headers)
-   (loop for header in headers
- if (not (or (eq 'to (car header))
- (eq 'subject (car header
- collect header)))
-(message-sort-headers)
-(message-hide-headers)
+   (message-headers-to-generate headers t '(to subject
 ;; insert the message body - but put it in front of the signature
 ;; if one is present
 (goto-char (point-max))
-- 
1.7.1



[PATCH 07/13] emacs: Allow tuning of the tag/saved search layout.

2010-05-19 Thread David Edmondson
Add `notmuch-column-control', which has three potential sets of
values:

- t: automatically calculate the number of columns per line 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 column,
- a float: a fraction of the window width that is the lower bound on
  the number of characters that should be used for each column.

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'.
---
 emacs/notmuch-hello.el |   63 +++
 1 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 1358387..acf40bc 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -65,6 +65,32 @@
   "Background colour for the notmuch logo."
   :group 'notmuch)

+(defcustom notmuch-column-control t
+  "Controls the number of columns for saved searches/tags in notmuch view.
+
+This variable has three potential sets of values:
+
+- t: automatically calculate the number of columns 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 column,
+- a float: a fraction of the window width that is the lower bound
+  on the number of characters that should be used for each
+  column.
+
+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")))
+
 (defvar notmuch-hello-url "http://notmuchmail.org";
   "The `notmuch' web site.")

@@ -146,13 +172,38 @@ diagonal."
 (defun notmuch-saved-search-count (search)
   (car (process-lines notmuch-command "count" search)))

+(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-column-control)
+  (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-column-control widest)
+
+ ((floatp notmuch-column-control)
+  (let* ((available-width (- (window-width) notmuch-hello-indent))
+ (proposed-width (max (* available-width 
notmuch-column-control) 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.1



[PATCH 06/13] emacs: Allow control over faces for search mode columns.

2010-05-19 Thread David Edmondson
Add face declarations for the date, count, matching author and subject
columns in search mode and apply those faces when building the search
mode display.
---
 emacs/notmuch.el |   59 +++--
 1 files changed, 43 insertions(+), 16 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index d36a92d..7c9c028 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -285,27 +285,48 @@ For a mouse binding, return nil."
  "Face for the single-line message summary in notmuch-show-mode."
  :group 'notmuch)

-(defface notmuch-tag-face
+(defface notmuch-search-date
+  '((t :inherit default))
+  "Face used in search mode for dates."
+  :group 'notmuch)
+
+(defface notmuch-search-count
+  '((t :inherit default))
+  "Face used in search mode for the count matching the query."
+  :group 'notmuch)
+
+(defface notmuch-search-subject
+  '((t :inherit default))
+  "Face used in search mode for subjects."
+  :group 'notmuch)
+
+(defface notmuch-search-matching-authors
+  '((t :inherit default))
+  "Face used in search mode for authors matching the query."
+  :group 'notmuch)
+
+(defface notmuch-search-non-matching-authors
   'class color)
   (background dark))
- (:foreground "OliveDrab1"))
+ (:foreground "grey30"))
 (((class color)
   (background light))
- (:foreground "navy blue" :bold t))
+ (:foreground "grey60"))
 (t
- (:bold t)))
-  "Notmuch search mode face used to highligh tags."
+ (:italic t)))
+  "Face used in search mode for authors not matching the query."
   :group 'notmuch)

-(defface notmuch-search-non-matching-authors
+(defface notmuch-tag-face
   'class color)
   (background dark))
- (:foreground "grey30"))
+ (:foreground "OliveDrab1"))
 (((class color)
   (background light))
- (:foreground "grey60"))
-(t (:italic t)))
-  "Face used in search mode for authors not matching the query."
+ (:foreground "navy blue" :bold t))
+(t
+ (:bold t)))
+  "Face used in search mode face for tags."
   :group 'notmuch)

 ;;;###autoload
@@ -599,21 +620,27 @@ matching will be applied."
;; `notmuch-search-process-filter'.
(save-match-data
  (if (string-match "\\(.*\\)|\\(..*\\)" truncated-string)
- (concat (match-string 1 truncated-string) ","
+ (concat (propertize (concat (match-string 1 truncated-string) 
",")
+ 'face 'notmuch-search-matching-authors)
  (propertize (match-string 2 truncated-string)
  'face 
'notmuch-search-non-matching-authors))
-   truncated-string)
+   (propertize truncated-string 'face 
'notmuch-search-matching-authors))

 (defun notmuch-search-insert-field (field date count authors subject tags)
   (cond
((string-equal field "date")
-(insert (format (cdr (assoc field notmuch-search-result-format)) date)))
+(insert (propertize (format (cdr (assoc field 
notmuch-search-result-format)) date)
+   'face 'notmuch-search-date)))
((string-equal field "count")
-(insert (format (cdr (assoc field notmuch-search-result-format)) count)))
+(insert (propertize (format (cdr (assoc field 
notmuch-search-result-format)) count)
+   'face 'notmuch-search-count)))
+   ((string-equal field "subject")
+(insert (propertize (format (cdr (assoc field 
notmuch-search-result-format)) subject)
+   'face 'notmuch-search-subject)))
+
((string-equal field "authors")
 (notmuch-search-insert-authors (cdr (assoc field 
notmuch-search-result-format)) authors))
-   ((string-equal field "subject")
-(insert (format (cdr (assoc field notmuch-search-result-format)) subject)))
+
((string-equal field "tags")
 (insert (concat "(" (propertize tags 'font-lock-face 'notmuch-tag-face) 
")")

-- 
1.7.1



[PATCH 05/13] emacs: Set the `face' property rather than `font-lock-face'.

2010-05-19 Thread David Edmondson
Avoid using face properties reserved for the font-lock package.
---
 emacs/notmuch.el |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 60c0ee5..d36a92d 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -438,7 +438,7 @@ and will also appear in a buffer named \"*Notmuch 
errors*\"."
   (let ((end (point)))
(delete-region beg end)
(insert (propertize (mapconcat  'identity tags " ")
-   'font-lock-face 'notmuch-tag-face))
+   'face 'notmuch-tag-face))

 (defun notmuch-search-get-tags ()
   (save-excursion
-- 
1.7.1



[PATCH 04/13] emacs: Display non-matching authors with a different face.

2010-05-19 Thread David Edmondson
In search mode some messages don't match the search criteria. Show
their authors names with a different face - generally darker than
those that do match.
---
 emacs/notmuch.el |   36 +---
 1 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 7457da9..60c0ee5 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -297,6 +297,17 @@ For a mouse binding, return nil."
   "Notmuch search mode face used to highligh tags."
   :group 'notmuch)

+(defface notmuch-search-non-matching-authors
+  'class color)
+  (background dark))
+ (:foreground "grey30"))
+(((class color)
+  (background light))
+ (:foreground "grey60"))
+(t (:italic t)))
+  "Face used in search mode for authors not matching the query."
+  :group 'notmuch)
+
 ;;;###autoload
 (defun notmuch-search-mode ()
   "Major mode displaying results of a notmuch search.
@@ -576,6 +587,23 @@ matching will be applied."
  (t
   (setq tags-faces (cdr tags-faces)

+(defun notmuch-search-insert-authors (format-string authors)
+  (insert (let* ((formatted-sample (format format-string ""))
+(formatted-authors (format format-string authors))
+(truncated-string
+ (if (> (length formatted-authors)
+(length formatted-sample))
+ (concat (substring authors 0 (- (length formatted-sample) 
4)) "... ")
+   formatted-authors)))
+   ;; Need to save the match data to avoid interfering with
+   ;; `notmuch-search-process-filter'.
+   (save-match-data
+ (if (string-match "\\(.*\\)|\\(..*\\)" truncated-string)
+ (concat (match-string 1 truncated-string) ","
+ (propertize (match-string 2 truncated-string)
+ 'face 
'notmuch-search-non-matching-authors))
+   truncated-string)
+
 (defun notmuch-search-insert-field (field date count authors subject tags)
   (cond
((string-equal field "date")
@@ -583,13 +611,7 @@ matching will be applied."
((string-equal field "count")
 (insert (format (cdr (assoc field notmuch-search-result-format)) count)))
((string-equal field "authors")
-(insert (let* ((format-string (cdr (assoc field 
notmuch-search-result-format)))
-  (formatted-sample (format format-string ""))
-  (formatted-authors (format format-string authors)))
- (if (> (length formatted-authors)
-(length formatted-sample))
- (concat (substring authors 0 (- (length formatted-sample) 4)) 
"... ")
-   formatted-authors
+(notmuch-search-insert-authors (cdr (assoc field 
notmuch-search-result-format)) authors))
((string-equal field "subject")
 (insert (format (cdr (assoc field notmuch-search-result-format)) subject)))
((string-equal field "tags")
-- 
1.7.1



[PATCH 03/13] emacs: Adjust comment to avoid confusing font-lock.

2010-05-19 Thread David Edmondson
Comments with an open bracket in the first column confuse `font-lock'
mode, so avoid them.
---
 emacs/notmuch.el |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 57e1140..7457da9 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -551,10 +551,10 @@ This function advances the next thread when finished."
   "Tag/face mapping for line highlighting in notmuch-search.

 Here is an example of how to color search results based on tags.
-(the following text would be placed in your ~/.emacs file):
+ (the following text would be placed in your ~/.emacs file):

-(setq notmuch-search-line-faces '((\"delete\" . '(:foreground \"red\"))
- (\"unread\" . '(:foreground \"green\"
+ (setq notmuch-search-line-faces '((\"delete\" . '(:foreground \"red\"))
+   (\"unread\" . '(:foreground \"green\"

 Order matters: for lines with multiple tags, the the first
 matching will be applied."
-- 
1.7.1



[PATCH 02/13] notmuch: Fix off-by-one errors if a header is >200 characters long.

2010-05-19 Thread David Edmondson
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.
---
 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.1



[PATCH 01/13] emacs: Usability improvements for `notmuch-hello'.

2010-05-19 Thread David Edmondson
- If no saved searches exist or are displayed, don't signal an error,
- If no saved searches exist or are displayed, leave the cursor in the
  search bar,
- Minor layout improvements.
---
 emacs/notmuch-hello.el |   36 +++-
 1 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 6a1c56e..1358387 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -273,7 +273,7 @@ diagonal."
   (notmuch-hello-update))
 :help-echo "Refresh"
 (car (process-lines notmuch-command "count")))
-  (widget-insert " messages (that's not much mail).\n\n"))
+  (widget-insert " messages (that's not much mail).\n"))

 (let ((found-target-pos nil)
  (final-target-pos nil))
@@ -292,7 +292,7 @@ diagonal."
 (widest (max saved-widest alltags-widest)))

(when saved-alist
- (widget-insert "Saved searches: ")
+ (widget-insert "\nSaved searches: ")
  (widget-create 'push-button
 :notify (lambda (&rest ignore)
   (customize-variable 'notmuch-saved-searches))
@@ -305,18 +305,16 @@ diagonal."
(setq final-target-pos found-target-pos))
(indent-rigidly start (point) notmuch-hello-indent)))

-   (let ((start (point)))
- (widget-insert "\nSearch: ")
- (setq notmuch-hello-search-bar-marker (point-marker))
- (widget-create 'editable-field
-;; Leave some space at the start and end of the
-;; search boxes.
-:size (max 8 (- (window-width) (* 2 
notmuch-hello-indent)
-(length "Search: ")))
-:action (lambda (widget &rest ignore)
-  (notmuch-hello-search (widget-value 
widget
- (widget-insert "\n")
- (indent-rigidly start (point) notmuch-hello-indent))
+   (widget-insert "\nSearch: ")
+   (setq notmuch-hello-search-bar-marker (point-marker))
+   (widget-create 'editable-field
+  ;; Leave some space at the start and end of the
+  ;; search boxes.
+  :size (max 8 (- (window-width) notmuch-hello-indent
+  (length "Search: ")))
+  :action (lambda (widget &rest ignore)
+(notmuch-hello-search (widget-value widget
+   (widget-insert "\n")

(when notmuch-hello-recent-searches
  (widget-insert "\nRecent searches: ")
@@ -408,9 +406,13 @@ diagonal."

   (widget-setup)

-  (goto-char final-target-pos)
-  (if (not (widget-at))
- (widget-forward 1)
+  (when final-target-pos
+   (goto-char final-target-pos)
+   (unless (widget-at)
+ (widget-forward 1)))
+
+  (unless (widget-at)
+   (notmuch-hello-goto-search)

 ;;;###autoload
 (defun notmuch-folder ()
-- 
1.7.1



patches for 0.4

2010-05-19 Thread David Edmondson
This is a set of small feature and cleanup patches. The only
particularly significant one is patch 2, as it fixes a memory
corruption bug in notmuch.

dme.

[PATCH 01/13] emacs: Usability improvements for `notmuch-hello'.
[PATCH 02/13] notmuch: Fix off-by-one errors if a header is >200 characters 
long.
[PATCH 03/13] emacs: Adjust comment to avoid confusing font-lock.
[PATCH 04/13] emacs: Display non-matching authors with a different face.
[PATCH 05/13] emacs: Set the `face' property rather than `font-lock-face'.
[PATCH 06/13] emacs: Allow control over faces for search mode columns.
[PATCH 07/13] emacs: Allow tuning of the tag/saved search layout.
[PATCH 08/13] emacs: Reuse rather than reinvent message header filtering
[PATCH 09/13] emacs: Avoid runtime use of `cl'.
[PATCH 10/13] emacs: In search mode, truncate authors using invisible text.
[PATCH 11/13] emacs: Pretty print the numbers of matching messages.
[PATCH 12/13] emacs: Tags should be shown with `notmuch-tag-face'.
[PATCH 13/13] emacs: Allow the display of absolute dates in the header line.


[PATCH] emacs: Allow the display of absolute dates in the header line.

2010-05-19 Thread David Edmondson
Add `notmuch-show-relative-dates' to control whether the summary line
in `notmuch-show' mode displays relative dates (e.g. '26 mins. ago') or
the full date string from the message. Default to `t' for
compatibility with the previous behaviour.
---

Re:
>  one thing I'd love for 0.4 (and haven't seen a patch for) is the
>  ability to disable the "xxmins. ago" and simply have it always
>  display the time a message arrived

 emacs/notmuch-show.el |9 -
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 5b0050a..2a95e62 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -64,6 +64,11 @@ any given message."
   :group 'notmuch
   :type 'boolean)

+(defcustom notmuch-show-relative-dates t
+  "Display relative dates in the message summary line."
+  :group 'notmuch
+  :type 'boolean)
+
 (defvar notmuch-show-markup-headers-hook '(notmuch-show-colour-headers)
   "A list of functions called to decorate the headers listed in
 `notmuch-message-headers'.")
@@ -592,7 +597,9 @@ current buffer, if possible."
 (setq message-start (point-marker))

 (notmuch-show-insert-headerline headers
-   (or (plist-get msg :date_relative)
+   (or (if notmuch-show-relative-dates
+   (plist-get msg :date_relative)
+ nil)
(plist-get headers :Date))
(plist-get msg :tags) depth)

-- 
1.7.1



[PATCH 03/13] emacs: Adjust comment to avoid confusing font-lock.

2010-05-19 Thread David Edmondson
Comments with an open bracket in the first column confuse `font-lock'
mode, so avoid them.
---
 emacs/notmuch.el |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 57e1140..7457da9 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -551,10 +551,10 @@ This function advances the next thread when finished."
   "Tag/face mapping for line highlighting in notmuch-search.
 
 Here is an example of how to color search results based on tags.
-(the following text would be placed in your ~/.emacs file):
+ (the following text would be placed in your ~/.emacs file):
 
-(setq notmuch-search-line-faces '((\"delete\" . '(:foreground \"red\"))
- (\"unread\" . '(:foreground \"green\"
+ (setq notmuch-search-line-faces '((\"delete\" . '(:foreground \"red\"))
+   (\"unread\" . '(:foreground \"green\"
 
 Order matters: for lines with multiple tags, the the first
 matching will be applied."
-- 
1.7.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 07/13] emacs: Allow tuning of the tag/saved search layout.

2010-05-19 Thread David Edmondson
Add `notmuch-column-control', which has three potential sets of
values:

- t: automatically calculate the number of columns per line 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 column,
- a float: a fraction of the window width that is the lower bound on
  the number of characters that should be used for each column.

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'.
---
 emacs/notmuch-hello.el |   63 +++
 1 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 1358387..acf40bc 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -65,6 +65,32 @@
   "Background colour for the notmuch logo."
   :group 'notmuch)
 
+(defcustom notmuch-column-control t
+  "Controls the number of columns for saved searches/tags in notmuch view.
+
+This variable has three potential sets of values:
+
+- t: automatically calculate the number of columns 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 column,
+- a float: a fraction of the window width that is the lower bound
+  on the number of characters that should be used for each
+  column.
+
+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")))
+
 (defvar notmuch-hello-url "http://notmuchmail.org";
   "The `notmuch' web site.")
 
@@ -146,13 +172,38 @@ diagonal."
 (defun notmuch-saved-search-count (search)
   (car (process-lines notmuch-command "count" search)))
 
+(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-column-control)
+  (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-column-control widest)
+
+ ((floatp notmuch-column-control)
+  (let* ((available-width (- (window-width) notmuch-hello-indent))
+ (proposed-width (max (* available-width 
notmuch-column-control) 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.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 02/13] notmuch: Fix off-by-one errors if a header is >200 characters long.

2010-05-19 Thread David Edmondson
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.
---
 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.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 06/13] emacs: Allow control over faces for search mode columns.

2010-05-19 Thread David Edmondson
Add face declarations for the date, count, matching author and subject
columns in search mode and apply those faces when building the search
mode display.
---
 emacs/notmuch.el |   59 +++--
 1 files changed, 43 insertions(+), 16 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index d36a92d..7c9c028 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -285,27 +285,48 @@ For a mouse binding, return nil."
  "Face for the single-line message summary in notmuch-show-mode."
  :group 'notmuch)
 
-(defface notmuch-tag-face
+(defface notmuch-search-date
+  '((t :inherit default))
+  "Face used in search mode for dates."
+  :group 'notmuch)
+
+(defface notmuch-search-count
+  '((t :inherit default))
+  "Face used in search mode for the count matching the query."
+  :group 'notmuch)
+
+(defface notmuch-search-subject
+  '((t :inherit default))
+  "Face used in search mode for subjects."
+  :group 'notmuch)
+
+(defface notmuch-search-matching-authors
+  '((t :inherit default))
+  "Face used in search mode for authors matching the query."
+  :group 'notmuch)
+
+(defface notmuch-search-non-matching-authors
   'class color)
   (background dark))
- (:foreground "OliveDrab1"))
+ (:foreground "grey30"))
 (((class color)
   (background light))
- (:foreground "navy blue" :bold t))
+ (:foreground "grey60"))
 (t
- (:bold t)))
-  "Notmuch search mode face used to highligh tags."
+ (:italic t)))
+  "Face used in search mode for authors not matching the query."
   :group 'notmuch)
 
-(defface notmuch-search-non-matching-authors
+(defface notmuch-tag-face
   'class color)
   (background dark))
- (:foreground "grey30"))
+ (:foreground "OliveDrab1"))
 (((class color)
   (background light))
- (:foreground "grey60"))
-(t (:italic t)))
-  "Face used in search mode for authors not matching the query."
+ (:foreground "navy blue" :bold t))
+(t
+ (:bold t)))
+  "Face used in search mode face for tags."
   :group 'notmuch)
 
 ;;;###autoload
@@ -599,21 +620,27 @@ matching will be applied."
;; `notmuch-search-process-filter'.
(save-match-data
  (if (string-match "\\(.*\\)|\\(..*\\)" truncated-string)
- (concat (match-string 1 truncated-string) ","
+ (concat (propertize (concat (match-string 1 truncated-string) 
",")
+ 'face 'notmuch-search-matching-authors)
  (propertize (match-string 2 truncated-string)
  'face 
'notmuch-search-non-matching-authors))
-   truncated-string)
+   (propertize truncated-string 'face 
'notmuch-search-matching-authors))
 
 (defun notmuch-search-insert-field (field date count authors subject tags)
   (cond
((string-equal field "date")
-(insert (format (cdr (assoc field notmuch-search-result-format)) date)))
+(insert (propertize (format (cdr (assoc field 
notmuch-search-result-format)) date)
+   'face 'notmuch-search-date)))
((string-equal field "count")
-(insert (format (cdr (assoc field notmuch-search-result-format)) count)))
+(insert (propertize (format (cdr (assoc field 
notmuch-search-result-format)) count)
+   'face 'notmuch-search-count)))
+   ((string-equal field "subject")
+(insert (propertize (format (cdr (assoc field 
notmuch-search-result-format)) subject)
+   'face 'notmuch-search-subject)))
+
((string-equal field "authors")
 (notmuch-search-insert-authors (cdr (assoc field 
notmuch-search-result-format)) authors))
-   ((string-equal field "subject")
-(insert (format (cdr (assoc field notmuch-search-result-format)) subject)))
+
((string-equal field "tags")
 (insert (concat "(" (propertize tags 'font-lock-face 'notmuch-tag-face) 
")")
 
-- 
1.7.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 08/13] emacs: Reuse rather than reinvent message header filtering

2010-05-19 Thread David Edmondson
From: Sebastian Spaeth 

In notmuch-mua-reply we were filtering out the Subject and To headers
manually in a loop, but message mode offers a nice function for
exactly that. Simplify the code by using that. Also, as
notmuch-mua-mail already sorts and hides headers that we want sorted
and hidden, we can safely remove those 2 functions from here as well.

Signed-off-by: Sebastian Spaeth 
---
 emacs/notmuch-mua.el |7 +--
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index bd06e3c..6318c15 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -92,12 +92,7 @@ list."
((same-window-regexps '("\\*mail .*")))
   (notmuch-mua-mail (mail-header 'to headers)
(mail-header 'subject headers)
-   (loop for header in headers
- if (not (or (eq 'to (car header))
- (eq 'subject (car header
- collect header)))
-(message-sort-headers)
-(message-hide-headers)
+   (message-headers-to-generate headers t '(to subject
 ;; insert the message body - but put it in front of the signature
 ;; if one is present
 (goto-char (point-max))
-- 
1.7.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 05/13] emacs: Set the `face' property rather than `font-lock-face'.

2010-05-19 Thread David Edmondson
Avoid using face properties reserved for the font-lock package.
---
 emacs/notmuch.el |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 60c0ee5..d36a92d 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -438,7 +438,7 @@ and will also appear in a buffer named \"*Notmuch 
errors*\"."
   (let ((end (point)))
(delete-region beg end)
(insert (propertize (mapconcat  'identity tags " ")
-   'font-lock-face 'notmuch-tag-face))
+   'face 'notmuch-tag-face))
 
 (defun notmuch-search-get-tags ()
   (save-excursion
-- 
1.7.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 09/13] emacs: Avoid runtime use of `cl'.

2010-05-19 Thread David Edmondson
The GNU Emacs Lisp Reference Manual section D.1 says:

> *  Please don't require the cl package of Common Lisp extensions at
>run time. Use of this package is optional, and it is not part of
>the standard Emacs namespace. If your package loads cl at run time,
>that could cause name clashes for users who don't use that package.
>
>However, there is no problem with using the cl package at compile
>time, with (eval-when-compile (require 'cl)). That's sufficient for
>using the macros in the cl package, because the compiler expands
>them before generating the byte-code.

Follow this advice, requiring the following changes where `cl' was
used at runtime:

- replace `rassoc-if' in `notmuch-search-buffer-title' with the `loop'
  macro and inline code. At the same time find the longest prefix
  which matches the query rather than simply the last,
- replace `union', `intersection' and `set-difference' in
  `notmuch-show-add-tag' and `notmuch-show-remove-tag' with local code
  to calculate the result of adding and removing a list of tags from
  another list of tags.
---
 emacs/notmuch-hello.el |2 +-
 emacs/notmuch-show.el  |   54 +++
 emacs/notmuch.el   |   16 +
 3 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index acf40bc..538785f 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -19,9 +19,9 @@
 ;;
 ;; Authors: David Edmondson 
 
+(eval-when-compile (require 'cl))
 (require 'widget)
 (require 'wid-edit) ; For `widget-forward'.
-(require 'cl)
 
 (require 'notmuch-lib)
 (require 'notmuch-mua)
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 4b1baf3..ff1a7a7 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -21,7 +21,7 @@
 ;; Authors: Carl Worth 
 ;;  David Edmondson 
 
-(require 'cl)
+(eval-when-compile (require 'cl))
 (require 'mm-view)
 (require 'message)
 (require 'mm-decode)
@@ -908,29 +908,55 @@ to stdout or stderr will appear in the *Messages* buffer."
 (list command " < "
   (shell-quote-argument (notmuch-show-get-filename)
 
+(defun notmuch-show-add-tags-worker (current-tags add-tags)
+  "Add to `current-tags' with any tags from `add-tags' not
+currently present and return the result."
+  (let ((result-tags (copy-seq current-tags)))
+(mapc (lambda (add-tag)
+   (unless (member add-tag current-tags)
+ (setq result-tags (push add-tag result-tags
+   add-tags)
+(sort result-tags 'string<)))
+
+(defun notmuch-show-del-tags-worker (current-tags del-tags)
+  "Remove any tags in `del-tags' from `current-tags' and return
+the result."
+  (let ((result-tags (copy-seq current-tags)))
+(mapc (lambda (del-tag)
+   (setq result-tags (delete del-tag result-tags)))
+ del-tags)
+result-tags))
+
 (defun notmuch-show-add-tag (&rest toadd)
   "Add a tag to the current message."
   (interactive
(list (notmuch-select-tag-with-completion "Tag to add: ")))
-  (apply 'notmuch-call-notmuch-process
-(append (cons "tag"
-  (mapcar (lambda (s) (concat "+" s)) toadd))
-(cons (notmuch-show-get-message-id) nil)))
-  (notmuch-show-set-tags (sort (union toadd (notmuch-show-get-tags) :test 
'string=) 'string<)))
+
+  (let* ((current-tags (notmuch-show-get-tags))
+(new-tags (notmuch-show-add-tags-worker current-tags toadd)))
+
+(unless (equal current-tags new-tags)
+  (apply 'notmuch-call-notmuch-process
+(append (cons "tag"
+  (mapcar (lambda (s) (concat "+" s)) toadd))
+(cons (notmuch-show-get-message-id) nil)))
+  (notmuch-show-set-tags new-tags
 
 (defun notmuch-show-remove-tag (&rest toremove)
   "Remove a tag from the current message."
   (interactive
(list (notmuch-select-tag-with-completion
  "Tag to remove: " (notmuch-show-get-message-id
-  (let ((tags (notmuch-show-get-tags)))
-(if (intersection tags toremove :test 'string=)
-   (progn
- (apply 'notmuch-call-notmuch-process
-(append (cons "tag"
-  (mapcar (lambda (s) (concat "-" s)) toremove))
-(cons (notmuch-show-get-message-id) nil)))
- (notmuch-show-set-tags (sort (set-difference tags toremove :test 
'string=) 'string<))
+
+  (let* ((current-tags (notmuch-show-get-tags))
+(new-tags (notmuch-show-del-tags-worker current-tags toremove)))
+
+(unless (equal current-tags new-tags)
+  (apply 'notmuch-call-notmuch-process
+(append (cons "tag"
+  (mapcar (lambda (s) (concat "-" s)) toremove))
+(cons (notmuch-show-get-message-id) nil)))
+  (notmuch-show-set-tags new-tags
 
 (defun notmuch-show-toggle-headers ()
   "Toggle the visibility of the current message headers."
diff --gi

[PATCH 10/13] emacs: In search mode, truncate authors using invisible text.

2010-05-19 Thread David Edmondson
Rather than discarding authors when truncated to fit the defined
column width, mark the text beyond the end of the column as invisible
and allow `isearch' to be used over the text so hidden.

This allows us to retain the compact display whilst enabling a user to
find the elided text.
---
 emacs/notmuch.el |   61 +++--
 1 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index c2fefe5..10babe4 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -608,23 +608,52 @@ matching will be applied."
  (t
   (setq tags-faces (cdr tags-faces)
 
+(defun notmuch-search-isearch-authors-show (overlay)
+  (remove-from-invisibility-spec (cons (overlay-get overlay 'invisible) t)))
+
 (defun notmuch-search-insert-authors (format-string authors)
-  (insert (let* ((formatted-sample (format format-string ""))
-(formatted-authors (format format-string authors))
-(truncated-string
- (if (> (length formatted-authors)
-(length formatted-sample))
- (concat (substring authors 0 (- (length formatted-sample) 
4)) "... ")
-   formatted-authors)))
-   ;; Need to save the match data to avoid interfering with
-   ;; `notmuch-search-process-filter'.
-   (save-match-data
- (if (string-match "\\(.*\\)|\\(..*\\)" truncated-string)
- (concat (propertize (concat (match-string 1 truncated-string) 
",")
- 'face 'notmuch-search-matching-authors)
- (propertize (match-string 2 truncated-string)
- 'face 
'notmuch-search-non-matching-authors))
-   (propertize truncated-string 'face 
'notmuch-search-matching-authors))
+  (let* ((propertized-authors
+ ;; Need to save the match data to avoid interfering with
+ ;; `notmuch-search-process-filter'.
+ (save-match-data
+   ;; Authors that don't match the search query are shown in a
+   ;; different font.
+   (if (string-match "\\(.*\\)|\\(..*\\)" authors)
+   (concat (propertize (concat (match-string 1 authors) ",")
+   'face 'notmuch-search-matching-authors)
+   (propertize (match-string 2 authors)
+   'face 'notmuch-search-non-matching-authors))
+ (propertize authors 'face 'notmuch-search-matching-authors
+
+(formatted-sample (format format-string ""))
+(formatted-authors (format format-string propertized-authors))
+visible-string invisible-string)
+
+;; Determine the part of the authors that will be visible by
+;; default.
+(if (> (length formatted-authors)
+  (length formatted-sample))
+   ;; 4 is `(length "... ")'.
+   (let ((visible-length (- (length formatted-sample) 4)))
+ (setq visible-string (substring propertized-authors 0 visible-length)
+   invisible-string (substring propertized-authors 
visible-length)))
+  (setq visible-string formatted-authors
+   invisible-string nil))
+
+;; Insert both the visible and invisible author strings.
+(insert visible-string)
+(when invisible-string
+  (let ((start (point))
+   (invis-spec (make-symbol "notmuch-search-authors"))
+   overlay)
+   (insert invisible-string)
+   ;; Using a cons-cell here causes an ellipsis to be inserted
+   ;; instead of the invisible text.
+   (add-to-invisibility-spec (cons invis-spec t))
+   (setq overlay (make-overlay start (point)))
+   (overlay-put overlay 'invisible invis-spec)
+   (overlay-put overlay 'isearch-open-invisible 
#'notmuch-search-isearch-authors-show)
+   (insert " ")
 
 (defun notmuch-search-insert-field (field date count authors subject tags)
   (cond
-- 
1.7.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


patches for 0.4

2010-05-19 Thread David Edmondson
This is a set of small feature and cleanup patches. The only
particularly significant one is patch 2, as it fixes a memory
corruption bug in notmuch.

dme.

[PATCH 01/13] emacs: Usability improvements for `notmuch-hello'.
[PATCH 02/13] notmuch: Fix off-by-one errors if a header is >200 characters 
long.
[PATCH 03/13] emacs: Adjust comment to avoid confusing font-lock.
[PATCH 04/13] emacs: Display non-matching authors with a different face.
[PATCH 05/13] emacs: Set the `face' property rather than `font-lock-face'.
[PATCH 06/13] emacs: Allow control over faces for search mode columns.
[PATCH 07/13] emacs: Allow tuning of the tag/saved search layout.
[PATCH 08/13] emacs: Reuse rather than reinvent message header filtering
[PATCH 09/13] emacs: Avoid runtime use of `cl'.
[PATCH 10/13] emacs: In search mode, truncate authors using invisible text.
[PATCH 11/13] emacs: Pretty print the numbers of matching messages.
[PATCH 12/13] emacs: Tags should be shown with `notmuch-tag-face'.
[PATCH 13/13] emacs: Allow the display of absolute dates in the header line.
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 04/13] emacs: Display non-matching authors with a different face.

2010-05-19 Thread David Edmondson
In search mode some messages don't match the search criteria. Show
their authors names with a different face - generally darker than
those that do match.
---
 emacs/notmuch.el |   36 +---
 1 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 7457da9..60c0ee5 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -297,6 +297,17 @@ For a mouse binding, return nil."
   "Notmuch search mode face used to highligh tags."
   :group 'notmuch)
 
+(defface notmuch-search-non-matching-authors
+  'class color)
+  (background dark))
+ (:foreground "grey30"))
+(((class color)
+  (background light))
+ (:foreground "grey60"))
+(t (:italic t)))
+  "Face used in search mode for authors not matching the query."
+  :group 'notmuch)
+
 ;;;###autoload
 (defun notmuch-search-mode ()
   "Major mode displaying results of a notmuch search.
@@ -576,6 +587,23 @@ matching will be applied."
  (t
   (setq tags-faces (cdr tags-faces)
 
+(defun notmuch-search-insert-authors (format-string authors)
+  (insert (let* ((formatted-sample (format format-string ""))
+(formatted-authors (format format-string authors))
+(truncated-string
+ (if (> (length formatted-authors)
+(length formatted-sample))
+ (concat (substring authors 0 (- (length formatted-sample) 
4)) "... ")
+   formatted-authors)))
+   ;; Need to save the match data to avoid interfering with
+   ;; `notmuch-search-process-filter'.
+   (save-match-data
+ (if (string-match "\\(.*\\)|\\(..*\\)" truncated-string)
+ (concat (match-string 1 truncated-string) ","
+ (propertize (match-string 2 truncated-string)
+ 'face 
'notmuch-search-non-matching-authors))
+   truncated-string)
+
 (defun notmuch-search-insert-field (field date count authors subject tags)
   (cond
((string-equal field "date")
@@ -583,13 +611,7 @@ matching will be applied."
((string-equal field "count")
 (insert (format (cdr (assoc field notmuch-search-result-format)) count)))
((string-equal field "authors")
-(insert (let* ((format-string (cdr (assoc field 
notmuch-search-result-format)))
-  (formatted-sample (format format-string ""))
-  (formatted-authors (format format-string authors)))
- (if (> (length formatted-authors)
-(length formatted-sample))
- (concat (substring authors 0 (- (length formatted-sample) 4)) 
"... ")
-   formatted-authors
+(notmuch-search-insert-authors (cdr (assoc field 
notmuch-search-result-format)) authors))
((string-equal field "subject")
 (insert (format (cdr (assoc field notmuch-search-result-format)) subject)))
((string-equal field "tags")
-- 
1.7.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 11/13] emacs: Pretty print the numbers of matching messages.

2010-05-19 Thread David Edmondson
Insert a separator every three digits when outputting numbers. Allow
the user to choose the separator by customizing
`notmuch-decimal-separator'. Widen the space allocated for message
counts accordingly.
---
 emacs/notmuch-hello.el |   38 +++---
 1 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 538785f..7ade0eb 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -91,6 +91,13 @@ So:
  (integer :tag "Number of characters")
  (float :tag "Fraction of window")))
 
+(defcustom notmuch-decimal-separator ","
+  "The string used as a decimal separator.
+
+Typically \",\" in the US and UK and \".\" in Europe."
+  :group 'notmuch
+  :type 'string)
+
 (defvar notmuch-hello-url "http://notmuchmail.org";
   "The `notmuch' web site.")
 
@@ -103,6 +110,17 @@ So:
 notmuch-recent-searches-max)
   (setq notmuch-hello-recent-searches (butlast 
notmuch-hello-recent-searches
 
+(defun notmuch-hello-nice-number (n)
+  (let (result)
+(while (> n 0)
+  (push (% n 1000) result)
+  (setq n (/ n 1000)))
+(apply #'concat
+ (number-to-string (car result))
+ (mapcar (lambda (elem)
+ (format "%s%03d" notmuch-decimal-separator elem))
+(cdr result)
+
 (defun notmuch-hello-trim (search)
   "Trim whitespace."
   (if (string-match "^[[:space:]]*\\(.*[^[:space:]]\\)[[:space:]]*$" search)
@@ -180,9 +198,9 @@ should be. Returns a cons cell `(tags-per-line width)'."
  ((integerp notmuch-column-control)
   (max 1
(/ (- (window-width) notmuch-hello-indent)
-  ;; Count is 7 wide (6 digits plus space), 1 for the space
+  ;; Count is 9 wide (8 digits plus space), 1 for the space
   ;; after the name.
-  (+ 7 1 (max notmuch-column-control widest)
+  (+ 9 1 (max notmuch-column-control widest)
 
  ((floatp notmuch-column-control)
   (let* ((available-width (- (window-width) notmuch-hello-indent))
@@ -192,12 +210,15 @@ should be. Returns a cons cell `(tags-per-line width)'."
  (t
   (max 1
(/ (- (window-width) notmuch-hello-indent)
-  ;; Count is 7 wide (6 digits plus space), 1 for the space
+  ;; Count is 9 wide (8 digits plus space), 1 for the space
   ;; after the name.
-  (+ 7 1 widest)))
+  (+ 9 1 widest)))
 
 (cons tags-per-line (/ (- (window-width) notmuch-hello-indent
- (* tags-per-line (+ 7 1)))
+ ;; Count is 9 wide (8 digits plus
+ ;; space), 1 for the space after the
+ ;; name.
+ (* tags-per-line (+ 9 1)))
   tags-per-line
 
 (defun notmuch-hello-insert-tags (tag-alist widest target)
@@ -218,7 +239,9 @@ should be. Returns a cons cell `(tags-per-line width)'."
  (let* ((name (car elem))
 (query (cdr elem))
 (formatted-name (format "%s " name)))
-   (widget-insert (format "%6s " (notmuch-saved-search-count 
query)))
+   (widget-insert (format "%8s "
+  (notmuch-hello-nice-number
+   (string-to-number 
(notmuch-saved-search-count query)
(if (string= formatted-name target)
(setq found-target-pos (point-marker)))
(widget-create 'push-button
@@ -323,7 +346,8 @@ should be. Returns a cons cell `(tags-per-line width)'."
 :notify (lambda (&rest ignore)
   (notmuch-hello-update))
 :help-echo "Refresh"
-(car (process-lines notmuch-command "count")))
+(notmuch-hello-nice-number
+ (string-to-number (car (process-lines notmuch-command 
"count")
   (widget-insert " messages (that's not much mail).\n"))
 
 (let ((found-target-pos nil)
-- 
1.7.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH] emacs: Allow the display of absolute dates in the header line.

2010-05-19 Thread David Edmondson
Add `notmuch-show-relative-dates' to control whether the summary line
in `notmuch-show' mode displays relative dates (e.g. '26 mins. ago') or
the full date string from the message. Default to `t' for
compatibility with the previous behaviour.
---

Re:
>  one thing I'd love for 0.4 (and haven't seen a patch for) is the
>  ability to disable the "xxmins. ago" and simply have it always
>  display the time a message arrived

 emacs/notmuch-show.el |9 -
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 5b0050a..2a95e62 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -64,6 +64,11 @@ any given message."
   :group 'notmuch
   :type 'boolean)
 
+(defcustom notmuch-show-relative-dates t
+  "Display relative dates in the message summary line."
+  :group 'notmuch
+  :type 'boolean)
+
 (defvar notmuch-show-markup-headers-hook '(notmuch-show-colour-headers)
   "A list of functions called to decorate the headers listed in
 `notmuch-message-headers'.")
@@ -592,7 +597,9 @@ current buffer, if possible."
 (setq message-start (point-marker))
 
 (notmuch-show-insert-headerline headers
-   (or (plist-get msg :date_relative)
+   (or (if notmuch-show-relative-dates
+   (plist-get msg :date_relative)
+ nil)
(plist-get headers :Date))
(plist-get msg :tags) depth)
 
-- 
1.7.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 12/13] emacs: Tags should be shown with `notmuch-tag-face'.

2010-05-19 Thread David Edmondson
Use the same face for tags in `notmuch-show' mode as that used in
`notmuch-search' mode.
---
 emacs/notmuch-show.el |6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index ff1a7a7..7601857 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -189,7 +189,8 @@ any given message."
 (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t)
(let ((inhibit-read-only t))
  (replace-match (concat "("
-(mapconcat 'identity tags " ")
+(propertize (mapconcat 'identity tags " ")
+'face 'notmuch-tag-face)
 ")"))
 
 (defun notmuch-show-insert-headerline (headers date tags depth)
@@ -201,7 +202,8 @@ message at DEPTH in the current thread."
" ("
date
") ("
-   (mapconcat 'identity tags " ")
+   (propertize (mapconcat 'identity tags " ")
+   'face 'notmuch-tag-face)
")\n")
 (overlay-put (make-overlay start (point)) 'face 
'notmuch-message-summary-face)))
 
-- 
1.7.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 13/13] emacs: Allow the display of absolute dates in the header line.

2010-05-19 Thread David Edmondson
Add `notmuch-show-relative-dates' to control whether the summary line
in `notmuch-show' mode displays relative dates (e.g. '26 mins ago') or
the full date string from the message. Default to `t' for
compatibility with the previous behaviour.
---
 emacs/notmuch-show.el |9 -
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 7601857..cbc3012 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -58,6 +58,11 @@ any given message."
   :group 'notmuch
   :type 'boolean)
 
+(defcustom notmuch-show-relative-dates t
+  "Display relative dates in the message summary line."
+  :group 'notmuch
+  :type 'boolean)
+
 (defvar notmuch-show-markup-headers-hook '(notmuch-show-colour-headers)
   "A list of functions called to decorate the headers listed in
 `notmuch-message-headers'.")
@@ -407,7 +412,9 @@ current buffer, if possible."
 (setq message-start (point-marker))
 
 (notmuch-show-insert-headerline headers
-   (or (plist-get msg :date_relative)
+   (or (if notmuch-show-relative-dates
+   (plist-get msg :date_relative)
+ nil)
(plist-get headers :Date))
(plist-get msg :tags) depth)
 
-- 
1.7.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 01/13] emacs: Usability improvements for `notmuch-hello'.

2010-05-19 Thread David Edmondson
- If no saved searches exist or are displayed, don't signal an error,
- If no saved searches exist or are displayed, leave the cursor in the
  search bar,
- Minor layout improvements.
---
 emacs/notmuch-hello.el |   36 +++-
 1 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 6a1c56e..1358387 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -273,7 +273,7 @@ diagonal."
   (notmuch-hello-update))
 :help-echo "Refresh"
 (car (process-lines notmuch-command "count")))
-  (widget-insert " messages (that's not much mail).\n\n"))
+  (widget-insert " messages (that's not much mail).\n"))
 
 (let ((found-target-pos nil)
  (final-target-pos nil))
@@ -292,7 +292,7 @@ diagonal."
 (widest (max saved-widest alltags-widest)))
 
(when saved-alist
- (widget-insert "Saved searches: ")
+ (widget-insert "\nSaved searches: ")
  (widget-create 'push-button
 :notify (lambda (&rest ignore)
   (customize-variable 'notmuch-saved-searches))
@@ -305,18 +305,16 @@ diagonal."
(setq final-target-pos found-target-pos))
(indent-rigidly start (point) notmuch-hello-indent)))
 
-   (let ((start (point)))
- (widget-insert "\nSearch: ")
- (setq notmuch-hello-search-bar-marker (point-marker))
- (widget-create 'editable-field
-;; Leave some space at the start and end of the
-;; search boxes.
-:size (max 8 (- (window-width) (* 2 
notmuch-hello-indent)
-(length "Search: ")))
-:action (lambda (widget &rest ignore)
-  (notmuch-hello-search (widget-value 
widget
- (widget-insert "\n")
- (indent-rigidly start (point) notmuch-hello-indent))
+   (widget-insert "\nSearch: ")
+   (setq notmuch-hello-search-bar-marker (point-marker))
+   (widget-create 'editable-field
+  ;; Leave some space at the start and end of the
+  ;; search boxes.
+  :size (max 8 (- (window-width) notmuch-hello-indent
+  (length "Search: ")))
+  :action (lambda (widget &rest ignore)
+(notmuch-hello-search (widget-value widget
+   (widget-insert "\n")
 
(when notmuch-hello-recent-searches
  (widget-insert "\nRecent searches: ")
@@ -408,9 +406,13 @@ diagonal."
 
   (widget-setup)
 
-  (goto-char final-target-pos)
-  (if (not (widget-at))
- (widget-forward 1)
+  (when final-target-pos
+   (goto-char final-target-pos)
+   (unless (widget-at)
+ (widget-forward 1)))
+
+  (unless (widget-at)
+   (notmuch-hello-goto-search)
 
 ;;;###autoload
 (defun notmuch-folder ()
-- 
1.7.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch