[PATCH 2/5] emacs: allow notmuch-tag to accept string inputs and prompt for tags

2012-04-14 Thread Mark Walters
On Sat, 14 Apr 2012, Jameson Graef Rollins  
wrote:
> notmuch-tag is extended to accept various formats of the tag changes.
> In particular, user prompting for tag changes is now incorporated
> here, so it is common for modes.
>
> The tag binary and the notmuch-{before,after}-tag-hooks are only
> called if tag changes is non-nil.
>
> The actual tag-changes applied are returned by the function.
> ---
>  emacs/notmuch-tag.el |   20 +++-
>  1 file changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
> index c25cff8..dd7f9d7 100644
> --- a/emacs/notmuch-tag.el
> +++ b/emacs/notmuch-tag.el
> @@ -108,18 +108,26 @@ from TAGS if present."
>  (error "Changed tag must be of the form `+this_tag' or 
> `-that_tag'")
>  (sort result-tags 'string<)))
>  
> -(defun notmuch-tag (query  tag-changes)
> +(defun notmuch-tag (query  tag-changes)
>"Add/remove tags in TAG-CHANGES to messages matching QUERY.
>  
> -TAG-CHANGES should be a list of strings of the form \"+tag\" or
> -\"-tag\" and QUERY should be a string containing the
> -search-query.
> +QUERY should be a string containing the search-terms.
> +TAG-CHANGES can take multiple forms.  If TAG-CHANGES is a list of
> +strings of the form \"+tag\" or \"-tag\" then those are the tag
> +changes applied.  If TAG-CHANGES is a string then it is
> +interpreted as a single tag change.  If TAG-CHANGES is the string
> +\"-\" or \"+\", or null, then the user is prompted to enter the
> +tag changes.
>  
>  Note: Other code should always use this function alter tags of
>  messages instead of running (notmuch-call-notmuch-process \"tag\" ..)
>  directly, so that hooks specified in notmuch-before-tag-hook and
>  notmuch-after-tag-hook will be run."
>;; Perform some validation
> +  (if (string-or-null-p tag-changes)
> +  (if (or (string= tag-changes "-") (string= tag-changes "+") (null 
> tag-changes))
> +   (setq tag-changes (notmuch-read-tag-changes tag-changes query))
> + (setq tag-changes (list tag-changes
>(mapc (lambda (tag-change)
> (unless (string-match-p "^[-+]\\S-+$" tag-change)
>   (error "Tag must be of the form `+this_tag' or `-that_tag'")))
> @@ -128,7 +136,9 @@ notmuch-after-tag-hook will be run."
>  (run-hooks 'notmuch-before-tag-hook)
>  (apply 'notmuch-call-notmuch-process "tag"
>  (append tag-changes (list "--" query)))
> -(run-hooks 'notmuch-after-tag-hook)))
> +(run-hooks 'notmuch-after-tag-hook))

Hi

The series looks good to me with one minor point:

> +  ;; return the list of actual changed tags
> +  tag-changes)

I found the comment confusing: I read it as the function looked at the
tags the message had before and after and returned the
difference. Perhaps something like "in all cases we return tag-changes
as a list" (and a similar comment for the commit message).

Best wishes

Mark



[PATCH 3/3] emacs: allow notmuch-show-line-faces to use flags for colouring

2012-04-14 Thread Mark Walters
This allows header-lines `notmuch-show-mode' buffers to be coloured
based on the flags (match/excluded) of the message. It supplies the
line colouring function with a list of tags each prefixed with "tag:"
and a list of flags ("match" or "excluded") each prefixed with
"flag:".

The match flag is obviously not equivalent to a tag; the excluded flag
looks equivalent but is subtly different: a message is not marked
excluded if that tag appeared in the query.
---
 emacs/notmuch-show.el |   21 -
 1 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 3dbb25f..66b8ec7 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -97,14 +97,16 @@ any given message."
 (defcustom notmuch-show-line-faces nil
   "Tag to face mapping for header line highlighting in `notmuch-show-mode'.

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

- (setq notmuch-search-line-faces '((\"delete\" . (:foreground \"red\"
+ (setq notmuch-search-line-faces '((\"tag:delete\" . (:foreground \"red\"
  :background \"blue\"))
-   (\"unread\" . (:foreground \"green\"
+   (\"tag:unread\" . (:foreground \"green\"))
+   (\"flag:excluded\" . (:background 
\"grey\"

-The attributes defined for matching tags are merged, with later
+The attributes defined for matching tags/flags are merged, with later
 attributes overriding earlier. A message having both \"delete\"
 and \"unread\" tags with the above settings would have a green
 foreground and blue background."
@@ -872,11 +874,20 @@ current buffer, if possible."
 content-start content-end
 headers-start headers-end
 body-start body-end
+tags-and-flags
 (headers-invis-spec (notmuch-show-make-symbol "header"))
 (message-invis-spec (notmuch-show-make-symbol "message"))
 (bare-subject (notmuch-show-strip-re (plist-get headers :Subject)))
 (tags (plist-get msg :tags)))

+(mapc (lambda (tag)
+   (setq tags-and-flags (cons (concat "tag:" tag) tags-and-flags)))
+ tags)
+(if (plist-get msg :match)
+   (setq tags-and-flags (cons "flag:match" tags-and-flags)))
+(if (plist-get msg :excluded)
+   (setq tags-and-flags (cons "flag:excluded" tags-and-flags)))
+
 ;; Set `buffer-invisibility-spec' to `nil' (a list), otherwise
 ;; removing items from `buffer-invisibility-spec' (which is what
 ;; `notmuch-show-headers-visible' and
@@ -905,7 +916,7 @@ current buffer, if possible."
 (setq content-start (point-marker))

 ;; Colour the header line according to the tags of the message.
-(notmuch-color-line message-start content-start tags 
notmuch-show-line-faces)
+(notmuch-color-line message-start content-start tags-and-flags 
notmuch-show-line-faces)

 (plist-put msg :headers-invis-spec headers-invis-spec)
 (plist-put msg :message-invis-spec message-invis-spec)
-- 
1.7.9.1



[PATCH 2/3] emacs: Add `notmuch-show-line-faces' and apply it.

2012-04-14 Thread Mark Walters
Similar to `notmuch-search-line-faces', `notmuch-show-line-faces'
allows the header line in `notmuch-show-mode' buffers to be coloured
according to the tags of the message. This is just a rebased version of
the  emacs/notmuch-show.el of David Edmondson's patch
id:"1325006003-27152-1-git-send-email-dme at dme.org"
---
 emacs/notmuch-show.el |   33 +
 1 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 30b26d1..3dbb25f 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -94,6 +94,24 @@ any given message."
   :group 'notmuch-show
   :group 'notmuch-hooks)

+(defcustom notmuch-show-line-faces nil
+  "Tag to face mapping for header line highlighting in `notmuch-show-mode'.
+
+Here is an example of how to color search results based on tags.
+ (the following text would be placed in your ~/.emacs file):
+
+ (setq notmuch-search-line-faces '((\"delete\" . (:foreground \"red\"
+ :background \"blue\"))
+   (\"unread\" . (:foreground \"green\"
+
+The attributes defined for matching tags are merged, with later
+attributes overriding earlier. A message having both \"delete\"
+and \"unread\" tags with the above settings would have a green
+foreground and blue background."
+  :type '(alist :key-type (string) :value-type (custom-face-edit))
+  :group 'notmuch-show
+  :group 'notmuch-faces)
+
 ;; Mostly useful for debugging.
 (defcustom notmuch-show-all-multipart/alternative-parts t
   "Should all parts of multipart/alternative parts be shown?"
@@ -412,7 +430,8 @@ unchanged ADDRESS if parsing fails."
 (defun notmuch-show-insert-headerline (headers date tags depth)
   "Insert a notmuch style headerline based on HEADERS for a
 message at DEPTH in the current thread."
-  (let ((start (point)))
+  (let ((start (point))
+   overlay)
 (insert (notmuch-show-spaces-n (* notmuch-show-indent-messages-width 
depth))
(notmuch-show-clean-address (plist-get headers :From))
" ("
@@ -421,7 +440,9 @@ message at DEPTH in the current thread."
(propertize (mapconcat 'identity tags " ")
'face 'notmuch-tag-face)
")\n")
-(overlay-put (make-overlay start (point)) 'face 
'notmuch-message-summary-face)))
+(setq overlay (make-overlay start (point)))
+(overlay-put overlay 'face 'notmuch-message-summary-face)
+(overlay-put overlay 'priority 2)))

 (defun notmuch-show-insert-header (header header-value)
   "Insert a single header."
@@ -853,7 +874,8 @@ current buffer, if possible."
 body-start body-end
 (headers-invis-spec (notmuch-show-make-symbol "header"))
 (message-invis-spec (notmuch-show-make-symbol "message"))
-(bare-subject (notmuch-show-strip-re (plist-get headers :Subject
+(bare-subject (notmuch-show-strip-re (plist-get headers :Subject)))
+(tags (plist-get msg :tags)))

 ;; Set `buffer-invisibility-spec' to `nil' (a list), otherwise
 ;; removing items from `buffer-invisibility-spec' (which is what
@@ -878,10 +900,13 @@ current buffer, if possible."
(plist-get msg :date_relative)
  nil)
(plist-get headers :Date))
-   (plist-get msg :tags) depth)
+   tags depth)

 (setq content-start (point-marker))

+;; Colour the header line according to the tags of the message.
+(notmuch-color-line message-start content-start tags 
notmuch-show-line-faces)
+
 (plist-put msg :headers-invis-spec headers-invis-spec)
 (plist-put msg :message-invis-spec message-invis-spec)

-- 
1.7.9.1



[PATCH 1/3] emacs: Move colour line from search to lib

2012-04-14 Thread Mark Walters
This patch moves the overlay/colouring from notmuch.el to
notmuch-lib.el. This is in preparation for its use by notmuch-show in
the next patch. This is just a rebased version of the emacs/notmuch.el
and emacs/notmuch-lib.el parts of David Edmondson's patch (see
id:"1325006003-27152-1-git-send-email-dme at dme.org")
---
 emacs/notmuch-lib.el |   18 ++
 emacs/notmuch.el |   15 +--
 2 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
index 6907a5f..c8a9351 100644
--- a/emacs/notmuch-lib.el
+++ b/emacs/notmuch-lib.el
@@ -148,6 +148,24 @@ the user hasn't set this variable with the old or new 
value."
   "Return a query that matches the message with id ID."
   (concat "id:\"" (replace-regexp-in-string "\"" "\"\"" id t t) "\""))

+(defun notmuch-color-line (start end line-tag-list spec)
+  "Colorize a line based on tags."
+  ;; Create the overlay only if the message has tags which match one
+  ;; of those specified in `spec'.
+  (let (overlay)
+(mapc (lambda (elem)
+   (let ((tag (car elem))
+ (attributes (cdr elem)))
+ (when (member tag line-tag-list)
+   (when (not overlay)
+ (setq overlay (make-overlay start end))
+ (overlay-put overlay 'priority 5))
+   ;; Merge the specified properties with any already
+   ;; applied from an earlier match.
+   (overlay-put overlay 'face
+(append (overlay-get overlay 'face) attributes)
+ spec)))
+
 ;;

 (defun notmuch-common-do-stash (text)
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index ba833e6..09f6c50 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -728,20 +728,7 @@ foreground and blue background."

 (defun notmuch-search-color-line (start end line-tag-list)
   "Colorize lines in `notmuch-show' based on tags."
-  ;; Create the overlay only if the message has tags which match one
-  ;; of those specified in `notmuch-search-line-faces'.
-  (let (overlay)
-(mapc (lambda (elem)
-   (let ((tag (car elem))
- (attributes (cdr elem)))
- (when (member tag line-tag-list)
-   (when (not overlay)
- (setq overlay (make-overlay start end)))
-   ;; Merge the specified properties with any already
-   ;; applied from an earlier match.
-   (overlay-put overlay 'face
-(append (overlay-get overlay 'face) attributes)
- notmuch-search-line-faces)))
+  (notmuch-color-line start end line-tag-list notmuch-search-line-faces))

 (defun notmuch-search-author-propertize (authors)
   "Split `authors' into matching and non-matching authors and
-- 
1.7.9.1



[PATCH 0/3] emacs: allow show to colour based on tags and flags

2012-04-14 Thread Mark Walters
These three patches allow emacs to colour the headerline in show mode
according to the messages tags and flags (ie match or excluded).

The first two are David Edmondson's patch
id:"1325006003-27152-1-git-send-email-dme at dme.org" rebased to master
and split into one which is trivial code movement and one which adds
the show colouring functionality.

The first two give a very similar result to notmuch-search-line-faces
and just allow colouring based on tags (not flags). The final one adds
the colouring by flag: it does this by passing to the line colouring
code a list of tags prefixed by "tag:" and flags prefixed by "flag:"

The final patch could be folded into the second, and this would somewhat reduce 
the diff. 

Mark Walters (3):
  emacs: Move colour line from search to lib
  emacs: Add `notmuch-show-line-faces' and apply it.
  emacs: allow notmuch-show-line-faces to use flags for colouring

 emacs/notmuch-lib.el  |   18 ++
 emacs/notmuch-show.el |   44 
 emacs/notmuch.el  |   15 +--
 3 files changed, 59 insertions(+), 18 deletions(-)

-- 
1.7.9.1



[PATCH v2] emacs: do not modify subject in search or show

2012-04-14 Thread Jameson Graef Rollins
A previous patch [0] replaced blank subject lines with '[No Subject]'
in search and show mode.  Apparently this was needed to circumvent
some bug in the printing code, but there was no need for it search or
show, and it is definitely not desirable, so we undo it here (a revert
is no longer feasible).  We should not be modifying strings in the
original message without good reason, or without a clear indication
that we are doing so, neither of which apply in this case.  For
further discussion see [0].

[0] id:"1327918561-16245-3-git-send-email-dme at dme.org"
---
Sorry, there was a small bug in the previous version (notmuch-print.el
was mistakenly modified).

 emacs/notmuch-show.el |5 +
 emacs/notmuch.el  |5 ++---
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 30b26d1..1e55099 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -1075,7 +1075,7 @@ function is used."
   (run-hooks 'notmuch-show-hook))

 ;; Set the header line to the subject of the first message.
-(setq header-line-format (notmuch-show-strip-re 
(notmuch-show-get-pretty-subject)
+(setq header-line-format (notmuch-show-strip-re 
(notmuch-show-get-subject)

 (defun notmuch-show-capture-state ()
   "Capture the state of the current buffer.
@@ -1375,9 +1375,6 @@ current thread."
 (defun notmuch-show-get-depth ()
   (notmuch-show-get-prop :depth))

-(defun notmuch-show-get-pretty-subject ()
-  (notmuch-prettify-subject (notmuch-show-get-subject)))
-
 (defun notmuch-show-set-tags (tags)
   "Set the tags of the current message."
   (notmuch-show-set-prop :tags tags)
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index ba833e6..326645d 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -507,7 +507,7 @@ Complete list of currently available key bindings:
   "Display the currently selected thread."
   (interactive)
   (let ((thread-id (notmuch-search-find-thread-id))
-   (subject (notmuch-prettify-subject (notmuch-search-find-subject
+   (subject (notmuch-search-find-subject)))
 (if (> (length thread-id) 0)
(notmuch-show thread-id
  (current-buffer)
@@ -877,8 +877,7 @@ non-authors is found, assume that all of the authors match."
  ;; We currently just throw away excluded matches.
  (unless (eq (aref count 1) ?0)
(let ((beg (point)))
- (notmuch-search-show-result date count authors
- (notmuch-prettify-subject 
subject) tags)
+ (notmuch-search-show-result date count authors 
subject tags)
  (notmuch-search-color-line beg (point) tag-list)
  (put-text-property beg (point) 
'notmuch-search-thread-id thread-id)
  (put-text-property beg (point) 
'notmuch-search-authors authors)
-- 
1.7.9.5



[PATCH v2 6/6] man: document notmuch tag --stdin option

2012-04-14 Thread Jani Nikula
---
 man/man1/notmuch-tag.1 |   44 +++-
 1 files changed, 43 insertions(+), 1 deletions(-)

diff --git a/man/man1/notmuch-tag.1 b/man/man1/notmuch-tag.1
index aa4546e..30693cf 100644
--- a/man/man1/notmuch-tag.1
+++ b/man/man1/notmuch-tag.1
@@ -4,7 +4,11 @@ notmuch-tag \- Add/remove tags for all messages matching the 
search terms.

 .SH SYNOPSIS
 .B notmuch tag
-.RI  "+<" tag> "|\-<" tag "> [...] [\-\-] <" search-term ">..."
+.RI "+<" tag ">|\-<" tag "> [...] [\-\-] <" search-terms ">"
+
+.B notmuch tag
+.RI "--stdin"
+

 .SH DESCRIPTION

@@ -29,6 +33,44 @@ updates the maildir flags according to tag changes if the
 configuration option is enabled. See \fBnotmuch-config\fR(1) for
 details.

+Supported options for
+.B tag
+include
+.RS 4
+.TP 4
+.BR \-\-stdin
+
+Read batch tagging operations from standard input. This is more
+efficient than repeated
+.B notmuch tag
+invocations. See
+.B TAG FILE FORMAT
+below for the input format. This option is not compatible with
+specifying tagging on the command line.
+.RE
+
+.SH TAG FILE FORMAT
+
+The input must consist of lines of the format:
+
+.RI "T +<" tag ">|\-<" tag "> [...] [\-\-] <" search-terms ">"
+
+Each line is interpreted similarly to
+.B notmuch tag
+command line arguments. The delimiter is one or more spaces ' '. Any
+characters in  and 
+.B may
+be hex encoded with %NN where NN is the hexadecimal value of the
+character. Any ' ' and '%' characters in  and 
+.B must
+be hex encoded (using %20 and %25, respectively). Any characters that
+are not part of  or 
+.B must not
+be hex encoded.
+
+Leading and trailing space ' ' is ignored. Empty lines and lines
+beginning with '#' are ignored.
+
 .SH SEE ALSO

 \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1),
-- 
1.7.5.4



[PATCH v2 5/6] test: add test for notmuch tag --stdin option

2012-04-14 Thread Jani Nikula
---
 test/tagging |   13 +
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/test/tagging b/test/tagging
index e4782ed..15eb42d 100755
--- a/test/tagging
+++ b/test/tagging
@@ -46,4 +46,17 @@ test_expect_equal "$output" "\
 thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; One (:\"  inbox tag1 unread)
 thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag4 unread)"

+test_begin_subtest "Batch stdin"
+notmuch tag --stdin <

[PATCH v2 4/6] cli: add support for batch tagging operations to "notmuch tag"

2012-04-14 Thread Jani Nikula
Add support for batch tagging operations through stdin to "notmuch
tag". This can be enabled with the new --stdin command line option to
"notmuch new". The input must consist of lines of the format:

T +|- [...] [--] 

Each line is interpreted similarly to "notmuch tag" command line
arguments. The delimiter is one or more spaces ' '. Any characters in
 and  MAY be hex encoded with %NN where NN is the
hexadecimal value of the character. Any ' ' and '%' characters in
 and  MUST be hex encoded (using %20 and %25,
respectively). Any characters that are not part of  or
 MUST NOT be hex encoded.

Leading and trailing space ' ' is ignored. Empty lines and lines
beginning with '#' are ignored.

Signed-off-by: Jani Nikula 
---
 notmuch-tag.c |  244 +---
 1 files changed, 213 insertions(+), 31 deletions(-)

diff --git a/notmuch-tag.c b/notmuch-tag.c
index 05feed3..e67555f 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -19,6 +19,7 @@
  */

 #include "notmuch-client.h"
+#include "hex-escape.h"

 static volatile sig_atomic_t interrupted;

@@ -167,17 +168,181 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const 
char *query_string,
 return interrupted;
 }

+/* like strtok(3), but without state, and doesn't modify s. usage pattern:
+ *
+ * const char *tok = input;
+ * const char *delim = " \t";
+ * size_t tok_len = 0;
+ *
+ * while ((tok = strtok_len (tok + tok_len, delim, _len)) != NULL) {
+ * // do stuff with string tok of length tok_len
+ * }
+ */
+static
+char *strtok_len(char *s, const char *delim, size_t *len)
+{
+/* skip initial delims */
+s += strspn (s, delim);
+
+/* length of token */
+*len = strcspn (s, delim);
+
+return *len ? s : NULL;
+}
+
+/* Tag messages according to 'input', which must consist of lines of
+ * the format:
+ *
+ * T +|- [...] [--] 
+ *
+ * Each line is interpreted similarly to "notmuch tag" command line
+ * arguments. The delimiter is one or more spaces ' '. Any characters
+ * in  and  MAY be hex encoded with %NN where NN is
+ * the hexadecimal value of the character. Any ' ' and '%' characters
+ * in  and  MUST be hex encoded (using %20 and %25,
+ * respectively). Any characters that are not part of  or
+ *  MUST NOT be hex encoded.
+ *
+ * Leading and trailing space ' ' is ignored. Empty lines and lines
+ * beginning with '#' are ignored.
+ */
+static int
+tag_file (void *ctx, notmuch_database_t *notmuch, FILE *input,
+ notmuch_bool_t synchronize_flags)
+{
+char *line = NULL;
+size_t line_size;
+ssize_t line_len;
+tag_operation_t *tag_ops;
+int tag_ops_array_size = 10;
+int ret = 0;
+
+/* Array of tagging operations (add or remove), terminated with an
+ * empty element. Size will be increased as necessary. */
+tag_ops = talloc_array (ctx, tag_operation_t, tag_ops_array_size);
+if (tag_ops == NULL) {
+   fprintf (stderr, "Out of memory.\n");
+   return 1;
+}
+
+while ((line_len = getline (, _size, input)) != -1 &&
+  !interrupted) {
+   char *tok;
+   size_t tok_len;
+   int tag_ops_count = 0;
+
+   chomp_newline (line);
+
+   tok = strtok_len (line, " ", _len);
+
+   /* Skip empty and comment lines. */
+   if (tok == NULL || *tok == '#')
+   continue;
+
+   /* T for tagging is the only recognized action for now. */
+   if (strncmp (tok, "T", tok_len) != 0) {
+   fprintf (stderr, "Warning: Ignoring invalid input line: %s\n",
+line);
+   continue;
+   }
+
+   /* Parse tags. */
+   while ((tok = strtok_len (tok + tok_len, " ", _len)) != NULL) {
+   notmuch_bool_t remove;
+   char *tag;
+
+   /* Optional explicit end of tags marker. */
+   if (strncmp (tok, "--", tok_len) == 0) {
+   tok = strtok_len (tok + tok_len, " ", _len);
+   break;
+   }
+
+   /* Implicit end of tags. */
+   if (*tok != '-' && *tok != '+')
+   break;
+
+   /* If tag is terminated by NUL, there's no query string. */
+   if (*(tok + tok_len) == '\0') {
+   tok = NULL;
+   break;
+   }
+
+   /* Terminate, and start next token after terminator. */
+   *(tok + tok_len++) = '\0';
+
+   remove = (*tok == '-');
+   tag = tok + 1;
+
+   /* Refuse empty tags. */
+   if (*tag == '\0') {
+   tok = NULL;
+   break;
+   }
+
+   /* Decode tag. */
+   if (hex_decode_inplace (tag) != HEX_SUCCESS) {
+   tok = NULL;
+   break;
+   }
+
+   tag_ops[tag_ops_count].tag = tag;
+   tag_ops[tag_ops_count].remove = remove;
+   tag_ops_count++;
+
+   /* Make room for terminating empty element and potential
+* new tags, if necessary. This should be a fairly rare
+* case, 

[PATCH v2 3/6] test/hex-escaping: new test for hex escaping routines

2012-04-14 Thread Jani Nikula
From: David Bremner 

These are more like unit tests, to (try to) make sure the library
functionality is working before building more complicated things on
top of it.
---
 test/hex-escaping |   26 ++
 test/notmuch-test |1 +
 2 files changed, 27 insertions(+), 0 deletions(-)
 create mode 100755 test/hex-escaping

diff --git a/test/hex-escaping b/test/hex-escaping
new file mode 100755
index 000..f34cc8c
--- /dev/null
+++ b/test/hex-escaping
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+test_description="hex encoding and decoding"
+. ./test-lib.sh
+
+test_begin_subtest "round trip"
+find $TEST_DIRECTORY/corpus -type f -print | sort | xargs cat > EXPECTED
+$TEST_DIRECTORY/hex-xcode --direction=encode < EXPECTED | 
$TEST_DIRECTORY/hex-xcode --direction=decode > OUTPUT
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "punctuation"
+tag1='comic_swear=$&^%$^%\\//-+$^%$'
+tag_enc1=$($TEST_DIRECTORY/hex-xcode --direction=encode "$tag1")
+test_expect_equal "$tag_enc1" 
"comic_swear=%24%26%5e%25%24%5e%25%5c%5c%2f%2f-+%24%5e%25%24"
+
+test_begin_subtest "round trip newlines"
+printf 'this\n tag\t has\n spaces\n' > EXPECTED.$test_count
+$TEST_DIRECTORY/hex-xcode --direction=encode  < EXPECTED.$test_count |\
+   $TEST_DIRECTORY/hex-xcode --direction=decode > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest "round trip 8bit chars"
+echo '%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a' > EXPECTED.$test_count
+$TEST_DIRECTORY/hex-xcode --direction=decode  < EXPECTED.$test_count |\
+   $TEST_DIRECTORY/hex-xcode --direction=encode > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+test_done
diff --git a/test/notmuch-test b/test/notmuch-test
index 801df73..2d0b381 100755
--- a/test/notmuch-test
+++ b/test/notmuch-test
@@ -57,6 +57,7 @@ TESTS="
   emacs-address-cleaning
   emacs-hello
   emacs-show
+  hex-escaping
 "
 TESTS=${NOTMUCH_TESTS:=$TESTS}

-- 
1.7.5.4



[PATCH v2 2/6] test/hex-xcode: new test binary

2012-04-14 Thread Jani Nikula
From: David Bremner 

This program is used both as a test-bed/unit-tester for
../util/hex-escape.c, and also as a utility in future tests of dump
and restore.
---
 test/.gitignore |1 +
 test/Makefile.local |6 ++-
 test/basic  |2 +-
 test/hex-xcode.c|  103 +++
 4 files changed, 110 insertions(+), 2 deletions(-)
 create mode 100644 test/hex-xcode.c

diff --git a/test/.gitignore b/test/.gitignore
index e63c689..be7ab5e 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -3,4 +3,5 @@ corpus.mail
 smtp-dummy
 symbol-test
 arg-test
+hex-xcode
 tmp.*
diff --git a/test/Makefile.local b/test/Makefile.local
index 4a6a4b1..9cecd28 100644
--- a/test/Makefile.local
+++ b/test/Makefile.local
@@ -13,6 +13,9 @@ smtp_dummy_modules = $(smtp_dummy_srcs:.c=.o)
 $(dir)/arg-test: $(dir)/arg-test.o command-line-arguments.o util/libutil.a
$(call quiet,CC) -I. $^ -o $@

+$(dir)/hex-xcode: $(dir)/hex-xcode.o command-line-arguments.o util/libutil.a
+   $(call quiet,CC) -I. $^ -o $@ -ltalloc
+
 $(dir)/smtp-dummy: $(smtp_dummy_modules)
$(call quiet,CC) $^ -o $@

@@ -21,7 +24,8 @@ $(dir)/symbol-test: $(dir)/symbol-test.o

 .PHONY: test check

-test-binaries: $(dir)/arg-test $(dir)/smtp-dummy $(dir)/symbol-test
+test-binaries: $(dir)/arg-test $(dir)/hex-xcode \
+$(dir)/smtp-dummy $(dir)/symbol-test

 test:  all test-binaries
@${dir}/notmuch-test $(OPTIONS)
diff --git a/test/basic b/test/basic
index d6aed24..af57026 100755
--- a/test/basic
+++ b/test/basic
@@ -54,7 +54,7 @@ test_begin_subtest 'Ensure that all available tests will be 
run by notmuch-test'
 eval $(sed -n -e '/^TESTS="$/,/^"$/p' $TEST_DIRECTORY/notmuch-test)
 tests_in_suite=$(for i in $TESTS; do echo $i; done | sort)
 available=$(find "$TEST_DIRECTORY" -maxdepth 1 -type f -executable -printf 
'%f\n' | \
-sed -r -e 
"/^(aggregate-results.sh|notmuch-test|smtp-dummy|test-verbose|symbol-test|arg-test)$/d"
 | \
+sed -r -e 
"/^(aggregate-results.sh|notmuch-test|smtp-dummy|test-verbose|symbol-test|arg-test|hex-xcode)$/d"
 | \
 sort)
 test_expect_equal "$tests_in_suite" "$available"

diff --git a/test/hex-xcode.c b/test/hex-xcode.c
new file mode 100644
index 000..eec6541
--- /dev/null
+++ b/test/hex-xcode.c
@@ -0,0 +1,103 @@
+/* No, nothing to to with IDE from Apple Inc.
+   testbed for ../util/hex-escape.c.
+
+   usage:
+   hex-xcode [--direction=(encode|decode)] [--omit-newline] < file
+   hex-xcode [--direction=(encode|decode)] [--omit-newline] arg1 arg2 arg3 ...
+
+ */
+
+#include "notmuch-client.h"
+#include "hex-escape.h"
+#include 
+
+
+enum direction {
+ENCODE,
+DECODE
+};
+
+static int
+xcode (void *ctx, enum direction dir, char *in, char **buf_p, size_t *size_p)
+{
+hex_status_t status;
+
+if (dir == ENCODE)
+   status = hex_encode (ctx, in, buf_p, size_p);
+else
+   status = hex_decode (ctx, in, buf_p, size_p);
+
+if (status == HEX_SUCCESS)
+   fputs (*buf_p, stdout);
+
+return status;
+}
+
+
+int
+main (int argc, char **argv)
+{
+
+
+enum direction dir = DECODE;
+int omit_newline = FALSE;
+
+notmuch_opt_desc_t options[] = {
+   { NOTMUCH_OPT_KEYWORD, , "direction", 'd',
+ (notmuch_keyword_t []){ { "encode", ENCODE },
+ { "decode", DECODE },
+ { 0, 0 } } },
+   { NOTMUCH_OPT_BOOLEAN, _newline, "omit-newline", 'n', 0 },
+   { 0, 0, 0, 0, 0 }
+};
+
+int opt_index = parse_arguments (argc, argv, options, 1);
+
+if (opt_index < 0)
+   exit (1);
+
+void *ctx = talloc_new (NULL);
+
+char *line = NULL;
+size_t line_size;
+ssize_t line_len;
+
+char *buffer = NULL;
+size_t buf_size = 0;
+
+notmuch_bool_t read_stdin = TRUE;
+
+for (; opt_index < argc; opt_index++) {
+
+   if (xcode (ctx, dir, argv[opt_index],
+  , _size) != HEX_SUCCESS)
+   return 1;
+
+   if (!omit_newline)
+   putchar ('\n');
+
+   read_stdin = FALSE;
+}
+
+if (!read_stdin)
+   return 0;
+
+while ((line_len = getline (, _size, stdin)) != -1) {
+
+   chomp_newline (line);
+
+   if (xcode (ctx, dir, line, , _size) != HEX_SUCCESS)
+   return 1;
+
+   if (!omit_newline)
+   putchar ('\n');
+
+}
+
+if (line)
+   free (line);
+
+talloc_free (ctx);
+
+return 0;
+}
-- 
1.7.5.4



[PATCH v2 1/6] hex-escape: (en|de)code strings to/from restricted character set

2012-04-14 Thread Jani Nikula
From: David Bremner 

The character set is chosen to be suitable for pathnames, and the same
as that used by contrib/nmbug

[With additions by Jani Nikula]
---
 util/Makefile.local |2 +-
 util/hex-escape.c   |  168 +++
 util/hex-escape.h   |   41 
 3 files changed, 210 insertions(+), 1 deletions(-)
 create mode 100644 util/hex-escape.c
 create mode 100644 util/hex-escape.h

diff --git a/util/Makefile.local b/util/Makefile.local
index c7cae61..3ca623e 100644
--- a/util/Makefile.local
+++ b/util/Makefile.local
@@ -3,7 +3,7 @@
 dir := util
 extra_cflags += -I$(srcdir)/$(dir)

-libutil_c_srcs := $(dir)/xutil.c $(dir)/error_util.c
+libutil_c_srcs := $(dir)/xutil.c $(dir)/error_util.c $(dir)/hex-escape.c

 libutil_modules := $(libutil_c_srcs:.c=.o)

diff --git a/util/hex-escape.c b/util/hex-escape.c
new file mode 100644
index 000..d8905d0
--- /dev/null
+++ b/util/hex-escape.c
@@ -0,0 +1,168 @@
+/* hex-escape.c -  Manage encoding and decoding of byte strings into path names
+ *
+ * Copyright (c) 2011 David Bremner
+ *
+ * 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: David Bremner 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include "error_util.h"
+#include "hex-escape.h"
+
+static const size_t default_buf_size = 1024;
+
+static const char *output_charset =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-_@=.:,";
+
+static const char escape_char = '%';
+
+static int
+is_output (char c)
+{
+return (strchr (output_charset, c) != NULL);
+}
+
+static int
+maybe_realloc (void *ctx, size_t needed, char **out, size_t *out_size)
+{
+if (*out_size < needed) {
+
+   if (*out == NULL)
+   *out = talloc_size (ctx, needed);
+   else
+   *out = talloc_realloc (ctx, *out, char, needed);
+
+   if (*out == NULL)
+   return 0;
+
+   *out_size = needed;
+}
+return 1;
+}
+
+hex_status_t
+hex_encode (void *ctx, const char *in, char **out, size_t *out_size)
+{
+
+const unsigned char *p;
+char *q;
+
+size_t escape_count = 0;
+size_t len = 0;
+size_t needed;
+
+assert (ctx); assert (in); assert (out); assert (out_size);
+
+for (p = (unsigned char *) in; *p; p++) {
+   escape_count += (!is_output (*p));
+   len++;
+}
+
+needed = len + escape_count * 2 + 1;
+
+if (*out == NULL)
+   *out_size = 0;
+
+if (!maybe_realloc (ctx, needed, out, out_size))
+   return HEX_OUT_OF_MEMORY;
+
+q = *out;
+p = (unsigned char *) in;
+
+while (*p) {
+   if (is_output (*p)) {
+   *q++ = *p++;
+   } else {
+   sprintf (q, "%%%02x", *p++);
+   q += 3;
+   }
+}
+
+*q = '\0';
+return HEX_SUCCESS;
+}
+
+/* Hex decode 'in' to 'out'.
+ *
+ * This must succeed for in == out to support hex_decode_inplace().
+ */
+static hex_status_t
+hex_decode_internal (const char *in, unsigned char *out)
+{
+char buf[3];
+
+while (*in) {
+   if (*in == escape_char) {
+   char *endp;
+
+   /* This also handles unexpected end-of-string. */
+   if (!isxdigit ((unsigned char) in[1]) ||
+   !isxdigit ((unsigned char) in[2]))
+   return HEX_SYNTAX_ERROR;
+
+   buf[0] = in[1];
+   buf[1] = in[2];
+   buf[2] = '\0';
+
+   *out = strtoul (buf, , 16);
+
+   if (endp != buf + 2)
+   return HEX_SYNTAX_ERROR;
+
+   in += 3;
+   out++;
+   } else {
+   *out++ = *in++;
+   }
+}
+
+*out = '\0';
+
+return HEX_SUCCESS;
+}
+
+hex_status_t
+hex_decode_inplace (char *s)
+{
+/* A decoded string is never longer than the encoded one, so it is
+ * safe to decode a string onto itself. */
+return hex_decode_internal (s, (unsigned char *) s);
+}
+
+hex_status_t
+hex_decode (void *ctx, const char *in, char **out, size_t * out_size)
+{
+const char *p;
+size_t escape_count = 0;
+size_t needed = 0;
+
+assert (ctx); assert (in); assert (out); assert (out_size);
+
+size_t len = strlen (in);
+
+for (p = in; *p; p++)
+   escape_count += (*p == escape_char);
+
+needed = len - escape_count * 2 + 1;
+
+if (!maybe_realloc (ctx, needed, out, out_size))
+   return HEX_OUT_OF_MEMORY;
+
+return hex_decode_internal 

[PATCH v2 0/6] batch tagging support: "notmuch tag --stdin"

2012-04-14 Thread Jani Nikula
v2 of id:"cover.1333231401.git.jani at nikula.org"

This series adds support for batch tagging through stdin to "notmuch
tag". This should be useful and efficient for e.g. initial tagging
scripts. Also, this adds locking around a batch of tag changes, which is
also useful for initial tagging scripts. See the test patch for an
example using a "here document".

The idea is that the same format (and parser) would be later used for
notmuch dump/restore, building on David's earlier work at
id:"1324214111-32079-1-git-send-email-david at tethera.net".

The v2 only has non-functional changes per David's comments, and
squashes the first three patches of v1 into one.

BR,
Jani.


David Bremner (3):
  hex-escape: (en|de)code strings to/from restricted character set
  test/hex-xcode: new test binary
  test/hex-escaping: new test for hex escaping routines

Jani Nikula (3):
  cli: add support for batch tagging operations to "notmuch tag"
  test: add test for notmuch tag --stdin option
  man: document notmuch tag --stdin option

 man/man1/notmuch-tag.1 |   44 +-
 notmuch-tag.c  |  244 ++--
 test/.gitignore|1 +
 test/Makefile.local|6 +-
 test/basic |2 +-
 test/hex-escaping  |   26 +
 test/hex-xcode.c   |  103 
 test/notmuch-test  |1 +
 test/tagging   |   13 +++
 util/Makefile.local|2 +-
 util/hex-escape.c  |  168 +
 util/hex-escape.h  |   41 
 12 files changed, 616 insertions(+), 35 deletions(-)
 create mode 100755 test/hex-escaping
 create mode 100644 test/hex-xcode.c
 create mode 100644 util/hex-escape.c
 create mode 100644 util/hex-escape.h

-- 
1.7.5.4



[PATCH v2 2/2] emacs: new mua mailto: URI handler

2012-04-14 Thread Jameson Graef Rollins
The new function 'notmuch-mua-mailto' provides an interactive handler
for rfc6068 "mailto:; URIs.  It attempts to implement the rfc6068
specification: http://tools.ietf.org/html/rfc6068

More decoding of the mailto string needs to be done, as is evident by
the fact that the mailto test remains broken.
---
Rebased against current master.

 emacs/notmuch-mua.el |   62 ++
 1 file changed, 62 insertions(+)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 87bd88d..59b4cf4 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -26,6 +26,10 @@
 (require 'notmuch-lib)
 (require 'notmuch-address)

+(require 'rfc2368)
+(require 'rfc2047)
+(require 'mailheader)
+
 (eval-when-compile (require 'cl))

 ;;
@@ -198,6 +202,64 @@ list."

   (message-goto-to))

+(defun notmuch-mua-mailto (mailto)
+  "Invoke the notmuch mail composition window for a `mailto:' URI."
+  ;; this should implement implement rfc6068: 
http://tools.ietf.org/html/rfc6068
+  ;; which obsoleted: http://tools.ietf.org/html/rfc2368
+  ;; this function is based on previous work: 
http://www.emacswiki.org/emacs/MailtoHandler
+  (interactive)
+  (when (and (stringp mailto)
+(string-match "\\`mailto:; mailto))
+(let* (
+  ;; FIXME: need to decode all html encodings in uri.
+  (mailto (replace-regexp-in-string "" "&" mailto))
+  (hdr-alist (rfc2368-parse-mailto-url mailto))
+  to subject other-headers body
+  (allowed-xtra-hdrs '(cc bcc in-reply-to)))
+
+  (with-temp-buffer
+   ;; extract body if it's defined
+   (when (assoc "Body" hdr-alist)
+ (dolist (hdr hdr-alist)
+   (when (equal "Body" (car hdr))
+ (insert (format "%s\n" (cdr hdr)
+ (rfc2047-decode-region (point-min) (point-max))
+ (setq body (buffer-substring-no-properties
+ (point-min) (point-max)))
+ (erase-buffer))
+
+   ;; extract headers
+   (dolist (hdr hdr-alist)
+ (unless (equal "Body" (car hdr))
+   (insert (format "%s: %s\n" (car hdr) (cdr hdr)
+   (rfc2047-decode-region (point-min) (point-max))
+   (goto-char (point-min))
+   (setq hdr-alist (mail-header-extract-no-properties)))
+
+  (setq to (cdr (assoc 'to hdr-alist)))
+  (setq subject (cdr (assoc 'subject hdr-alist)))
+
+  ;; extract allowed other headers, taking only first defined
+  ;; value
+  (dolist (hdr hdr-alist)
+   (if (and (member (car hdr) allowed-xtra-hdrs)
+(not (assoc (car hdr) other-headers)))
+   (add-to-list 'other-headers hdr)))
+
+  (notmuch-mua-mail to subject other-headers)
+
+  ;; insert the message body - but put it in front of the signature
+  ;; if one is present
+  (goto-char (point-max))
+  (if (re-search-backward message-signature-separator nil t)
+ (forward-line -1)
+   (goto-char (point-max)))
+  (insert body)
+  (push-mark))
+(set-buffer-modified-p nil)
+
+(message-goto-body)))
+
 (defun notmuch-mua-mail ( to subject other-headers  other-args)
   "Invoke the notmuch mail composition window.

-- 
1.7.9.5



[PATCH 2/2] emacs: new mua mailto: URI handler

2012-04-14 Thread Jameson Graef Rollins
On Sat, Apr 14 2012, Jani Nikula  wrote:
> I was doing this purely based on whether the patches apply or not.

I'm so sorry, Jani.  You are correct that this patch requires a small
rebase fix to apply to master.  I'm not sure how I missed it previously.

Updated version on the way.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120414/c1a89311/attachment.pgp>


[PATCH 0/2] Allow JSON to use non-entire thread, and use for elide

2012-04-14 Thread Jameson Graef Rollins
On Sat, Apr 14 2012, Jameson Graef Rollins  
wrote:
> Can this be applied to notmuch-reply as well, so that we can regain the
> ability to reply to threads?

Sorry, nevermind.  I was misinterpreting the point of this patch.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120414/f2d1d19f/attachment.pgp>


[PATCH 0/2] Allow JSON to use non-entire thread, and use for elide

2012-04-14 Thread Jameson Graef Rollins
On Tue, Apr 10 2012, Mark Walters  wrote:
> The first patch allows --entire-thread=false for notmuch-show.c when
> the output format is JSON. In the previous version [2] Austin
> suggested that we should output an empty message (i.e., {}) for
> non-matching messages rather than just omitting them. This version
> does that.

Can this be applied to notmuch-reply as well, so that we can regain the
ability to reply to threads?

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120414/5a6a67a7/attachment-0001.pgp>


[PATCH v2 2/5] emacs: allow notmuch-tag to accept string inputs and prompt for tags

2012-04-14 Thread Jameson Graef Rollins
notmuch-tag is extended to accept various formats of the tag changes.
In particular, user prompting for tag changes is now incorporated
here, so it is common for modes.

The tag binary and the notmuch-{before,after}-tag-hooks are only
called if tag changes is non-nil.

In all cases tag-changes is returned as a list.
---
This addresses Mark Walters concerns in regards to a code comment.

 emacs/notmuch-tag.el |   20 +++-
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
index c25cff8..0c0fc87 100644
--- a/emacs/notmuch-tag.el
+++ b/emacs/notmuch-tag.el
@@ -108,18 +108,26 @@ from TAGS if present."
   (error "Changed tag must be of the form `+this_tag' or 
`-that_tag'")
 (sort result-tags 'string<)))

-(defun notmuch-tag (query  tag-changes)
+(defun notmuch-tag (query  tag-changes)
   "Add/remove tags in TAG-CHANGES to messages matching QUERY.

-TAG-CHANGES should be a list of strings of the form \"+tag\" or
-\"-tag\" and QUERY should be a string containing the
-search-query.
+QUERY should be a string containing the search-terms.
+TAG-CHANGES can take multiple forms.  If TAG-CHANGES is a list of
+strings of the form \"+tag\" or \"-tag\" then those are the tag
+changes applied.  If TAG-CHANGES is a string then it is
+interpreted as a single tag change.  If TAG-CHANGES is the string
+\"-\" or \"+\", or null, then the user is prompted to enter the
+tag changes.

 Note: Other code should always use this function alter tags of
 messages instead of running (notmuch-call-notmuch-process \"tag\" ..)
 directly, so that hooks specified in notmuch-before-tag-hook and
 notmuch-after-tag-hook will be run."
   ;; Perform some validation
+  (if (string-or-null-p tag-changes)
+  (if (or (string= tag-changes "-") (string= tag-changes "+") (null 
tag-changes))
+ (setq tag-changes (notmuch-read-tag-changes tag-changes query))
+   (setq tag-changes (list tag-changes
   (mapc (lambda (tag-change)
  (unless (string-match-p "^[-+]\\S-+$" tag-change)
(error "Tag must be of the form `+this_tag' or `-that_tag'")))
@@ -128,7 +136,9 @@ notmuch-after-tag-hook will be run."
 (run-hooks 'notmuch-before-tag-hook)
 (apply 'notmuch-call-notmuch-process "tag"
   (append tag-changes (list "--" query)))
-(run-hooks 'notmuch-after-tag-hook)))
+(run-hooks 'notmuch-after-tag-hook))
+  ;; in all cases we return tag-changes as a list
+  tag-changes)

 ;;

-- 
1.7.9.5



[PATCH v5] emacs: Let the user choose where to compose new mails

2012-04-14 Thread Jameson Graef Rollins
From: Thomas Jost 

Introduce a new defcustom notmuch-mua-compose-in that allows users to
specify where new mails are composed, either in the current window or
in a new window or frame.

Signed-off-by: Jameson Rollins 
---
There was a small bug in the previous rebased version of this patch
that this new version fixes.  Sorry about the noise.

I also updated the subject line to indicate that this is in fact the
fifth version of this patch.

 emacs/notmuch-mua.el |   40 ++--
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 87bd88d..1fb59de 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -36,6 +36,21 @@
   :group 'notmuch-send
   :group 'notmuch-hooks)

+(defcustom notmuch-mua-compose-in 'current-window
+  "Where to create the mail buffer used to compose a new message.
+  Possible values are `current-window' (default), `new-window'
+  and `new-frame'. If set to `current-window', the mail buffer
+  will be displayed in the current window, so the old buffer will
+  be restored when the mail buffer is killed. If set to
+  `new-window' or `new-frame', the mail buffer will be displayed
+  in a new window/frame that will be destroyed when the buffer is
+  killed. You may want to customize `message-kill-buffer-on-exit'
+  accordingly."
+  :group 'notmuch
+  :type '(choice (const :tag "Compose in the current window" current-window)
+(const :tag "Compose mail in a new window"  new-window)
+(const :tag "Compose mail in a new frame"   new-frame)))
+
 (defcustom notmuch-mua-user-agent-function 'notmuch-mua-user-agent-full
   "Function used to generate a `User-Agent:' string. If this is
 `nil' then no `User-Agent:' will be generated."
@@ -55,6 +70,23 @@ list."

 ;;

+(defun notmuch-mua-get-switch-function ()
+  "Get a switch function according to `notmuch-mua-compose-in'."
+  (cond ((eq notmuch-mua-compose-in 'current-window)
+'switch-to-buffer)
+   ((eq notmuch-mua-compose-in 'new-window)
+'switch-to-buffer-other-window)
+   ((eq notmuch-mua-compose-in 'new-frame)
+'switch-to-buffer-other-frame)
+   (t (error "Invalid value for `notmuch-mua-compose-in'"
+
+(defun notmuch-mua-maybe-set-window-dedicated ()
+  "Set the selected window as dedicated according to
+`notmuch-mua-compose-in'."
+  (when (or (eq notmuch-mua-compose-in 'new-frame)
+   (eq notmuch-mua-compose-in 'new-window))
+(set-window-dedicated-p (selected-window) t)))
+
 (defun notmuch-mua-user-agent-full ()
   "Generate a `User-Agent:' string suitable for notmuch."
   (concat (notmuch-mua-user-agent-notmuch)
@@ -148,7 +180,8 @@ list."
 collect pair)))
  (notmuch-mua-mail (plist-get reply-headers :To)
(plist-get reply-headers :Subject)
-   (notmuch-headers-plist-to-alist reply-headers
+   (notmuch-headers-plist-to-alist reply-headers)
+   nil (notmuch-mua-get-switch-function

   ;; Insert the message body - but put it in front of the signature
   ;; if one is present
@@ -186,6 +219,7 @@ list."
   (set-buffer-modified-p nil))

 (defun notmuch-mua-forward-message ()
+  (funcall (notmuch-mua-get-switch-function) (current-buffer))
   (message-forward)

   (when notmuch-mua-user-agent-function
@@ -195,6 +229,7 @@ list."
   (message-sort-headers)
   (message-hide-headers)
   (set-buffer-modified-p nil)
+  (notmuch-mua-maybe-set-window-dedicated)

   (message-goto-to))

@@ -217,6 +252,7 @@ OTHER-ARGS are passed through to `message-mail'."
   (message-sort-headers)
   (message-hide-headers)
   (set-buffer-modified-p nil)
+  (notmuch-mua-maybe-set-window-dedicated)

   (message-goto-to))

@@ -273,7 +309,7 @@ the From: address first."
   (let ((other-headers
 (when (or prompt-for-sender notmuch-always-prompt-for-sender)
   (list (cons 'From (notmuch-mua-prompt-for-sender))
-(notmuch-mua-mail nil nil other-headers)))
+(notmuch-mua-mail nil nil other-headers nil 
(notmuch-mua-get-switch-function

 (defun notmuch-mua-new-forward-message ( prompt-for-sender)
   "Invoke the notmuch message forwarding window.
-- 
1.7.9.5



[PATCH 2/2] emacs: new mua mailto: URI handler

2012-04-14 Thread Jameson Graef Rollins
On Sat, Apr 14 2012, Jani Nikula  wrote:
> I'm going through the review queue right now, tagging notmuch::stale any
> patches that don't apply on master. I was just about to nmbug push stale
> on this one (2/2). Is that in error? Care to verify?

Yes, it is an error.  This patch applies to master.  Did you in fact
verify that it doesn't?  You should not be tagging patches stale if they
in fact still apply to master.  If they still need review or something
else that's a different matter.  Please don't mark things as stale if
they are not.

Obviously I still care about this patch, or I wouldn't have re-commented
on it.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120414/5a6cb337/attachment.pgp>


[PATCH v2 0/6] batch tagging support: "notmuch tag --stdin"

2012-04-14 Thread Jameson Graef Rollins
On Sat, Apr 14 2012, Jani Nikula  wrote:
> This series adds support for batch tagging through stdin to "notmuch
> tag". This should be useful and efficient for e.g. initial tagging
> scripts. Also, this adds locking around a batch of tag changes, which is
> also useful for initial tagging scripts. See the test patch for an
> example using a "here document".

My issues from v1 still stand.  I would rather see some unification with
the existing tag file format, rather than introduce a second format,
with it's increased maintenance burden and confusion to users.  Either
that or a more general batch command interface.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120414/03183a31/attachment.pgp>


[PATCH] emacs: Let the user choose where to compose new mails

2012-04-14 Thread Jameson Graef Rollins
From: Thomas Jost 

Introduce a new defcustom notmuch-mua-compose-in that allows users to
specify where new mails are composed., either in the current window or
in a new window or frame.

Signed-off-by: Jameson Rollins 
---
This is a rebase of this original patch against the current master,
with an expanded commit message.

 emacs/notmuch-mua.el |   42 +++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 87bd88d..a96ac3d 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -36,6 +36,21 @@
   :group 'notmuch-send
   :group 'notmuch-hooks)

+(defcustom notmuch-mua-compose-in 'current-window
+  "Where to create the mail buffer used to compose a new message.
+  Possible values are `current-window' (default), `new-window'
+  and `new-frame'. If set to `current-window', the mail buffer
+  will be displayed in the current window, so the old buffer will
+  be restored when the mail buffer is killed. If set to
+  `new-window' or `new-frame', the mail buffer will be displayed
+  in a new window/frame that will be destroyed when the buffer is
+  killed. You may want to customize `message-kill-buffer-on-exit'
+  accordingly."
+  :group 'notmuch
+  :type '(choice (const :tag "Compose in the current window" current-window)
+(const :tag "Compose mail in a new window"  new-window)
+(const :tag "Compose mail in a new frame"   new-frame)))
+
 (defcustom notmuch-mua-user-agent-function 'notmuch-mua-user-agent-full
   "Function used to generate a `User-Agent:' string. If this is
 `nil' then no `User-Agent:' will be generated."
@@ -55,6 +70,23 @@ list."

 ;;

+(defun notmuch-mua-get-switch-function ()
+  "Get a switch function according to `notmuch-mua-compose-in'."
+  (cond ((eq notmuch-mua-compose-in 'current-window)
+'switch-to-buffer)
+   ((eq notmuch-mua-compose-in 'new-window)
+'switch-to-buffer-other-window)
+   ((eq notmuch-mua-compose-in 'new-frame)
+'switch-to-buffer-other-frame)
+   (t (error "Invalid value for `notmuch-mua-compose-in'"
+
+(defun notmuch-mua-maybe-set-window-dedicated ()
+  "Set the selected window as dedicated according to
+`notmuch-mua-compose-in'."
+  (when (or (eq notmuch-mua-compose-in 'new-frame)
+   (eq notmuch-mua-compose-in 'new-window))
+(set-window-dedicated-p (selected-window) t)))
+
 (defun notmuch-mua-user-agent-full ()
   "Generate a `User-Agent:' string suitable for notmuch."
   (concat (notmuch-mua-user-agent-notmuch)
@@ -148,7 +180,8 @@ list."
 collect pair)))
  (notmuch-mua-mail (plist-get reply-headers :To)
(plist-get reply-headers :Subject)
-   (notmuch-headers-plist-to-alist reply-headers
+   (notmuch-headers-plist-to-alist reply-headers)
+   nil (notmuch-mua-get-switch-function

   ;; Insert the message body - but put it in front of the signature
   ;; if one is present
@@ -186,6 +219,7 @@ list."
   (set-buffer-modified-p nil))

 (defun notmuch-mua-forward-message ()
+  (funcall (notmuch-mua-get-switch-function) (current-buffer))
   (message-forward)

   (when notmuch-mua-user-agent-function
@@ -195,6 +229,7 @@ list."
   (message-sort-headers)
   (message-hide-headers)
   (set-buffer-modified-p nil)
+  (notmuch-mua-maybe-set-window-dedicated)

   (message-goto-to))

@@ -217,6 +252,7 @@ OTHER-ARGS are passed through to `message-mail'."
   (message-sort-headers)
   (message-hide-headers)
   (set-buffer-modified-p nil)
+  (notmuch-mua-maybe-set-window-dedicated)

   (message-goto-to))

@@ -272,8 +308,8 @@ the From: address first."
   (interactive "P")
   (let ((other-headers
 (when (or prompt-for-sender notmuch-always-prompt-for-sender)
-  (list (cons 'From (notmuch-mua-prompt-for-sender))
-(notmuch-mua-mail nil nil other-headers)))
+  (list (cons "From" (notmuch-mua-prompt-for-sender))
+(notmuch-mua-mail nil nil other-headers nil 
(notmuch-mua-get-switch-function

 (defun notmuch-mua-new-forward-message ( prompt-for-sender)
   "Invoke the notmuch message forwarding window.
-- 
1.7.9.5



[PATCH 2/2] emacs: new mua mailto: URI handler

2012-04-14 Thread Jameson Graef Rollins
On Sun, Jan 29 2012, Jameson Graef Rollins  
wrote:
> The new function 'notmuch-mua-mailto' provides an interactive handler
> for rfc6068 "mailto:; URIs.  It attempts to implement the rfc6068
> specification: http://tools.ietf.org/html/rfc6068

I am using and finding this patch useful.  It has no conflict with
anything when not used.  Is there any other objection with pushing it?

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120414/f9e9e1d3/attachment.pgp>


[PATCH 0/6] Finish show rewrite

2012-04-14 Thread Jameson Graef Rollins
On Sat, Apr 07 2012, Austin Clements  wrote:
> The long-awaited and oft-belated conclusion of the show rewrite.  All
> of the formatters have been converted to the new style, so this series
> just rips out unused code and does a little cleanup.

LGTM, tested, and +1.

This has been a truly epic endeavor, Austin, and the result is
phenomenal.  The show code is much cleaner, more efficient, and better
functioning.  Thank you so much for working through it all and pushing
it through to the end.  Kudos.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120414/04269a95/attachment.pgp>


[PATCH v3 1/4] emacs: Let the user choose where to compose new mails

2012-04-14 Thread Jameson Graef Rollins
On Tue, Dec 13 2011, Thomas Jost  wrote:
> Reusing the current window to compose a new mail may be troublesome for the
> user. This patch introduces a new customizable variable, 
> notmuch-mua-compose-in,
> which lets the user choose where to create the mail buffer: in the current
> window (current and default behaviour), in a new window, or in a new frame.

Hi.  I have been using this patch for many months now with no problems.
I really depend on it's functionality now, so I would really like to see
it pushed so that I don't have to keep maintaining it on my own personal
branch.

I think the issues that David was experiencing have to do with flakiness
in emacs's dedicated windows, not in this patch itself.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120414/d5092747/attachment.pgp>


[PATCH v4 0/6] Config-related patches

2012-04-14 Thread Jameson Graef Rollins
On Sat, Apr 14 2012, Mark Walters  wrote:
> Two minor comments which you might like to consider (but definitely are
> not required):
> 1) You could check that there are no further arguments when the user
> calls `notmuch config list'

This doesn't seem so necessary to me.  I'm fine if it just silently
ignores extra arguments.

> 2) In the man page you could explicitly say what the output is for a
> configuration item which has not been set.

I'm also fine with it as it is.  I think it's implied that if the value
is null then the field is left blank.  That's ok.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120414/05e9d046/attachment.pgp>


[PATCH v4 0/6] Config-related patches

2012-04-14 Thread Jameson Graef Rollins
On Fri, Apr 13 2012, Peter Wang  wrote:
> Changes from v3:
> - rephrase part of the 'list' implementation as a separate patch
> - test 'set' on an extant key
> - test removing keys

LGTM, tested, and +1.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120414/826d5cf6/attachment.pgp>


[WIP 0/2] Thread based searching

2012-04-14 Thread Jameson Graef Rollins
On Tue, Mar 20 2012, Mark Walters  wrote:
> It implements a very crude form of thread based search: the user can
> ask for all the threads that have a message matching the primary query
> and have a (possibly different) message matching a secondary query.
>
> For example notmuch search --secondary-search from:A :AND: from:B
> returns all threads that have a message from A and a message from B.

Hey, Mark.  I think this is a useful idea, but I think the
implementation is more complicated than it needs to be.  I would rather
just have a switch that allows me to search by thread, instead of by
message.  Something like just --by-thread would work for me.

I guess it might be nice to have such fined grain control to specify
independent search terms for both messages and threads simultaneously,
but I really don't think I would ever use such capabilities, and the
additional syntax is a little confusing.  But I certainly would use the
ability to search entire threads instead of just messages.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120414/617d6a7a/attachment.pgp>


[PATCH 5/8] emacs: modify search tag functions to use new notmuch-tag interface

2012-04-14 Thread Jameson Graef Rollins
On Mon, Apr 09 2012, Mark Walters  wrote:
> My only comment here is that I wonder about the tag-all command. I can
> see that this is a performance win over applying tag region to the whole
> buffer but is it another place where we have a race with incoming mail
> (ie we tag everything that now matches rather than everything in the
> buffer).

Yes, I think this is a problem.  notmuch-{search,show}-tag-all are both
subject to race conditions.  I suggest we remove notmuch-search-tag-all
in favor of the region tagging capabilities of notmuch-show-tag.  I will
submit a patch for that.  notmuch-show-tag-all is trickier, since there
no tag-by-region capability at the moment.  That will have to be added
before this function can be replaced.

> A second advantage with the tag-region form is that it automatically
> does excludes. Currently notmuch-tag does not do excludes as it looked
> very hairy to implement correctly: thus the tag-all command could spend
> a lot of time tagging excluded messages.

Actually, I don't think this is true, at least for search mode.  In
search mode threads are tagged by their thread id, therefore any
excluded messages in the thread will receive the same tagging
operations.

The current operation is at least, in my opinion, self consistent.  If
we're going to tag by thread then all messages in the thread should be
tagged, whether or not they're excluded.  I do think, however, that it
might be nice to add a tagging function that only tags the matching
messages in the thread.  In that case excluded messages would not be
tagged.  That's for future work, though.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20120414/a613c298/attachment.pgp>


[PATCH 5/5] emacs: eliminate search-tag-thread in favor of just search-tag

2012-04-14 Thread Jameson Graef Rollins
notmuch-search-tag-thread is now completely redundant with
notmuch-search-tag so we eliminate it to simplify the interface.
---
 emacs/notmuch.el |8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index a03a526..cfc3b29 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -517,12 +517,6 @@ and will also appear in a buffer named \"*Notmuch 
errors*\"."
(forward-line 1))
   output)))

-(defun notmuch-search-tag-thread ( tag-changes)
-  "Change tags for the currently selected thread.
-
-See `notmuch-search-tag-region' for details."
-  (apply 'notmuch-search-tag-region (point) (point) tag-changes))
-
 (defun notmuch-search-tag-region (beg end  tag-changes)
   "Change tags for threads in the given region."
   (let ((search-string (notmuch-search-find-thread-id-region-search beg end)))
@@ -560,7 +554,7 @@ See `notmuch-tag' for information on the format of 
TAG-CHANGES."

 This function advances the next thread when finished."
   (interactive)
-  (notmuch-search-tag-thread "-inbox")
+  (notmuch-search-tag '("-inbox"))
   (notmuch-search-next-thread))

 (defvar notmuch-search-process-filter-data nil
-- 
1.7.9.5



[PATCH 4/5] emacs: modify show tag functions to use new notmuch-tag interface

2012-04-14 Thread Jameson Graef Rollins
The main change here is to modify argument parsing so as to not force
tag-changes to be a list, and to let notmuch-tag handle prompting the
user when required.  doc strings are also updated and cleaned up.
---
 emacs/notmuch-show.el |   26 +++---
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index a4c313d..69bca02 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -1641,22 +1641,26 @@ TAG-CHANGES is a list of tag operations for 
`notmuch-tag'."
   (let* ((current-tags (notmuch-show-get-tags))
 (new-tags (notmuch-update-tags current-tags tag-changes)))
 (unless (equal current-tags new-tags)
-  (apply 'notmuch-tag (notmuch-show-get-message-id) tag-changes)
+  (funcall 'notmuch-tag (notmuch-show-get-message-id) tag-changes)
   (notmuch-show-set-tags new-tags

-(defun notmuch-show-tag ( initial-input)
-  "Change tags for the current message, read input from the minibuffer."
+(defun notmuch-show-tag ( tag-changes)
+  "Change tags for the current message.
+
+See `notmuch-tag' for information on the format of TAG-CHANGES."
   (interactive)
-  (let ((tag-changes (notmuch-read-tag-changes
- initial-input (notmuch-show-get-message-id
-(apply 'notmuch-show-tag-message tag-changes)))
+  (setq tag-changes (funcall 'notmuch-tag (notmuch-show-get-message-id) 
tag-changes))
+  (let* ((current-tags (notmuch-show-get-tags))
+(new-tags (notmuch-update-tags current-tags tag-changes)))
+(unless (equal current-tags new-tags)
+  (notmuch-show-set-tags new-tags

-(defun notmuch-show-tag-all ( tag-changes)
-  "Change tags for all messages in the current buffer.
+(defun notmuch-show-tag-all ( tag-changes)
+  "Change tags for all messages in the current show buffer.

-TAG-CHANGES is a list of tag operations for `notmuch-tag'."
-  (interactive (notmuch-read-tag-changes nil notmuch-show-thread-id))
-  (apply 'notmuch-tag (notmuch-show-get-messages-ids-search) tag-changes)
+See `notmuch-tag' for information on the format of TAG-CHANGES."
+  (interactive)
+  (setq tag-changes (funcall 'notmuch-tag 
(notmuch-show-get-messages-ids-search) tag-changes))
   (notmuch-show-mapc
(lambda ()
  (let* ((current-tags (notmuch-show-get-tags))
-- 
1.7.9.5



[PATCH 3/5] emacs: modify search tag functions to use new notmuch-tag interface

2012-04-14 Thread Jameson Graef Rollins
The main change here is to modify argument parsing so as to not force
tag-changes to be a list, and to let notmuch-tag handle prompting the
user when required.  doc strings are also updated and cleaned up.
---
 emacs/notmuch.el |   36 +---
 1 file changed, 13 insertions(+), 23 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 9aec96d..a03a526 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -523,13 +523,10 @@ and will also appear in a buffer named \"*Notmuch 
errors*\"."
 See `notmuch-search-tag-region' for details."
   (apply 'notmuch-search-tag-region (point) (point) tag-changes))

-(defun notmuch-search-tag-region (beg end  tag-changes)
-  "Change tags for threads in the given region.
-
-TAGS is a list of tag operations for `notmuch-tag'.  The tags are
-added or removed for all threads in the region from BEG to END."
+(defun notmuch-search-tag-region (beg end  tag-changes)
+  "Change tags for threads in the given region."
   (let ((search-string (notmuch-search-find-thread-id-region-search beg end)))
-(apply 'notmuch-tag search-string tag-changes)
+(setq tag-changes (funcall 'notmuch-tag search-string tag-changes))
 (save-excursion
   (let ((last-line (line-number-at-pos end))
(max-line (- (line-number-at-pos (point-max)) 2)))
@@ -539,14 +536,14 @@ added or removed for all threads in the region from BEG 
to END."
   (notmuch-update-tags (notmuch-search-get-tags) tag-changes))
  (forward-line))

-(defun notmuch-search-tag ( initial-input)
-  "Change tags for the currently selected thread or region."
+(defun notmuch-search-tag ( tag-changes)
+  "Change tags for the currently selected thread or region.
+
+See `notmuch-tag' for information on the format of TAG-CHANGES."
   (interactive)
   (let* ((beg (if (region-active-p) (region-beginning) (point)))
-(end (if (region-active-p) (region-end) (point)))
-(search-string (notmuch-search-find-thread-id-region-search beg end))
-(tags (notmuch-read-tag-changes initial-input search-string)))
-(apply 'notmuch-search-tag-region beg end tags)))
+(end (if (region-active-p) (region-end) (point
+(funcall 'notmuch-search-tag-region beg end tag-changes)))

 (defun notmuch-search-add-tag ()
   "Same as `notmuch-search-tag' but sets initial input to '+'."
@@ -790,18 +787,11 @@ non-authors is found, assume that all of the authors 
match."
  (goto-char found-target)))
   (delete-process proc

-(defun notmuch-search-tag-all ( tag-changes)
-  "Add/remove tags from all matching messages.
+(defun notmuch-search-tag-all ( tag-changes)
+  "Add/remove tags from all messages in current search buffer.

-This 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 `_.+-'.
-"
-  (interactive (notmuch-read-tag-changes))
+See `notmuch-tag' for information on the format of TAG-CHANGES."
+  (interactive)
   (apply 'notmuch-tag notmuch-search-query-string tag-changes))

 (defun notmuch-search-buffer-title (query)
-- 
1.7.9.5



[PATCH 2/5] emacs: allow notmuch-tag to accept string inputs and prompt for tags

2012-04-14 Thread Jameson Graef Rollins
notmuch-tag is extended to accept various formats of the tag changes.
In particular, user prompting for tag changes is now incorporated
here, so it is common for modes.

The tag binary and the notmuch-{before,after}-tag-hooks are only
called if tag changes is non-nil.

The actual tag-changes applied are returned by the function.
---
 emacs/notmuch-tag.el |   20 +++-
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
index c25cff8..dd7f9d7 100644
--- a/emacs/notmuch-tag.el
+++ b/emacs/notmuch-tag.el
@@ -108,18 +108,26 @@ from TAGS if present."
   (error "Changed tag must be of the form `+this_tag' or 
`-that_tag'")
 (sort result-tags 'string<)))

-(defun notmuch-tag (query  tag-changes)
+(defun notmuch-tag (query  tag-changes)
   "Add/remove tags in TAG-CHANGES to messages matching QUERY.

-TAG-CHANGES should be a list of strings of the form \"+tag\" or
-\"-tag\" and QUERY should be a string containing the
-search-query.
+QUERY should be a string containing the search-terms.
+TAG-CHANGES can take multiple forms.  If TAG-CHANGES is a list of
+strings of the form \"+tag\" or \"-tag\" then those are the tag
+changes applied.  If TAG-CHANGES is a string then it is
+interpreted as a single tag change.  If TAG-CHANGES is the string
+\"-\" or \"+\", or null, then the user is prompted to enter the
+tag changes.

 Note: Other code should always use this function alter tags of
 messages instead of running (notmuch-call-notmuch-process \"tag\" ..)
 directly, so that hooks specified in notmuch-before-tag-hook and
 notmuch-after-tag-hook will be run."
   ;; Perform some validation
+  (if (string-or-null-p tag-changes)
+  (if (or (string= tag-changes "-") (string= tag-changes "+") (null 
tag-changes))
+ (setq tag-changes (notmuch-read-tag-changes tag-changes query))
+   (setq tag-changes (list tag-changes
   (mapc (lambda (tag-change)
  (unless (string-match-p "^[-+]\\S-+$" tag-change)
(error "Tag must be of the form `+this_tag' or `-that_tag'")))
@@ -128,7 +136,9 @@ notmuch-after-tag-hook will be run."
 (run-hooks 'notmuch-before-tag-hook)
 (apply 'notmuch-call-notmuch-process "tag"
   (append tag-changes (list "--" query)))
-(run-hooks 'notmuch-after-tag-hook)))
+(run-hooks 'notmuch-after-tag-hook))
+  ;; return the list of actual changed tags
+  tag-changes)

 ;;

-- 
1.7.9.5



[PATCH 1/5] emacs: create notmuch-tag.el, and move appropriate functions from notmuch.el

2012-04-14 Thread Jameson Graef Rollins
Tagging functions are used in notmuch.el, notmuch-show.el, and
notmuch-message.el.  There are enough common functions for tagging
that it makes sense to put them all in their own library.

No code is modified, just moved around.
---
 emacs/Makefile.local |1 +
 emacs/notmuch-message.el |1 +
 emacs/notmuch-show.el|3 +-
 emacs/notmuch-tag.el |  135 ++
 emacs/notmuch.el |  109 +
 5 files changed, 139 insertions(+), 110 deletions(-)
 create mode 100644 emacs/notmuch-tag.el

diff --git a/emacs/Makefile.local b/emacs/Makefile.local
index 4fee0e8..fb82247 100644
--- a/emacs/Makefile.local
+++ b/emacs/Makefile.local
@@ -13,6 +13,7 @@ emacs_sources := \
$(dir)/notmuch-maildir-fcc.el \
$(dir)/notmuch-message.el \
$(dir)/notmuch-crypto.el \
+   $(dir)/notmuch-tag.el \
$(dir)/coolj.el \
$(dir)/notmuch-print.el

diff --git a/emacs/notmuch-message.el b/emacs/notmuch-message.el
index 3010281..5964caa 100644
--- a/emacs/notmuch-message.el
+++ b/emacs/notmuch-message.el
@@ -20,6 +20,7 @@
 ;; Authors: Jesse Rosenthal 

 (require 'message)
+(require 'notmuch-tag)
 (require 'notmuch-mua)

 (defcustom notmuch-message-replied-tags '("replied")
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 30b26d1..a4c313d 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -30,6 +30,7 @@
 (require 'goto-addr)

 (require 'notmuch-lib)
+(require 'notmuch-tag)
 (require 'notmuch-query)
 (require 'notmuch-wash)
 (require 'notmuch-mua)
@@ -38,10 +39,8 @@

 (declare-function notmuch-call-notmuch-process "notmuch" ( args))
 (declare-function notmuch-fontify-headers "notmuch" nil)
-(declare-function notmuch-read-tag-changes "notmuch" ( initial-input 
 search-terms))
 (declare-function notmuch-search-next-thread "notmuch" nil)
 (declare-function notmuch-search-show-thread "notmuch" nil)
-(declare-function notmuch-update-tags "notmuch" (current-tags tag-changes))

 (defcustom notmuch-message-headers '("Subject" "To" "Cc" "Date")
   "Headers that should be shown in a message, in this order.
diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
new file mode 100644
index 000..c25cff8
--- /dev/null
+++ b/emacs/notmuch-tag.el
@@ -0,0 +1,135 @@
+;; notmuch-tag.el --- tag messages within emacs
+;;
+;; Copyright ? Carl Worth
+;;
+;; This file is part of Notmuch.
+;;
+;; Notmuch is free software: you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Notmuch is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Notmuch.  If not, see .
+;;
+;; Authors: Carl Worth 
+
+(eval-when-compile (require 'cl))
+(require 'crm)
+(require 'notmuch-lib)
+
+(defcustom notmuch-before-tag-hook nil
+  "Hooks that are run before tags of a message are modified.
+
+'tags' will contain the tags that are about to be added or removed as
+a list of strings of the form \"+TAG\" or \"-TAG\".
+'query' will be a string containing the search query that determines
+the messages that are about to be tagged"
+
+  :type 'hook
+  :options '(notmuch-hl-line-mode)
+  :group 'notmuch-hooks)
+
+(defcustom notmuch-after-tag-hook nil
+  "Hooks that are run after tags of a message are modified.
+
+'tags' will contain the tags that were added or removed as
+a list of strings of the form \"+TAG\" or \"-TAG\".
+'query' will be a string containing the search query that determines
+the messages that were tagged"
+  :type 'hook
+  :options '(notmuch-hl-line-mode)
+  :group 'notmuch-hooks)
+
+(defvar notmuch-select-tag-history nil
+  "Variable to store minibuffer history for
+`notmuch-select-tag-with-completion' function.")
+
+(defvar notmuch-read-tag-changes-history nil
+  "Variable to store minibuffer history for
+`notmuch-read-tag-changes' function.")
+
+(defun notmuch-tag-completions ( search-terms)
+  (if (null search-terms)
+  (setq search-terms (list "*")))
+  (split-string
+   (with-output-to-string
+ (with-current-buffer standard-output
+   (apply 'call-process notmuch-command nil t
+ nil "search" "--output=tags" "--exclude=false" search-terms)))
+   "\n+" t))
+
+(defun notmuch-select-tag-with-completion (prompt  search-terms)
+  (let ((tag-list (notmuch-tag-completions search-terms)))
+(completing-read prompt tag-list nil nil nil 'notmuch-select-tag-history)))
+
+(defun notmuch-read-tag-changes ( initial-input  search-terms)
+  (let* ((all-tag-list (notmuch-tag-completions))
+(add-tag-list (mapcar 

emacs tagging cleanup, v3

2012-04-14 Thread Jameson Graef Rollins
This is a further cleaned up and simplified version of [0].  The scope
is slightly reduced, but we still end up with a simpler user
interface, with the primary tagging functions being:

notmuch-search-tag
notmuch-show-tag

In this series only one user facing tagging function,
notmuch-search-tag-thread, is removed, since it is completely
redundant with the now more flexible notmuch-search-tag.

jamie.

[0] id:"1333845338-22960-1-git-send-email-jrollins at finestructure.net"



[PATCH v4 6/6] man: Document 'config list' command

2012-04-14 Thread Peter Wang
Document the 'config list' command and its output.
---
 man/man1/notmuch-config.1 |   14 ++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/man/man1/notmuch-config.1 b/man/man1/notmuch-config.1
index 395cb9c..a55dbef 100644
--- a/man/man1/notmuch-config.1
+++ b/man/man1/notmuch-config.1
@@ -9,6 +9,8 @@ notmuch-config \- Access notmuch configuration file.
 .B notmuch config set
 .RI  "<" section ">.<" item "> [" value " ...]"

+.B notmuch config list
+
 .SH DESCRIPTION

 The
@@ -35,6 +37,18 @@ If no values are provided, the specified configuration item 
will be
 removed from the configuration file.
 .RE

+.RS 4
+.TP 4
+.B list
+Every configuration item is printed to stdout, each on a separate line
+of the form:
+
+.RI  "" section "." item "=" value
+
+No additional whitespace surrounds the dot or equals sign characters. In a
+multiple-value item (a list), the values are separated by semicolon characters.
+.RE
+
 The available configuration items are described below.

 .RS 4
-- 
1.7.4.4



[PATCH v4 5/6] config: Add 'config list' command

2012-04-14 Thread Peter Wang
Add a command to list all configuration items with their associated
values.

One use is as follows: a MUA may prefer to store data in a central
notmuch configuration file so that the data is accessible across
different machines, e.g. an addressbook.  The list command helps
to implement features such as tab completion on the keys.
---
 notmuch-config.c |   47 +++
 test/config  |1 -
 2 files changed, 47 insertions(+), 1 deletions(-)

diff --git a/notmuch-config.c b/notmuch-config.c
index f9eb977..3e37a2d 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -799,6 +799,51 @@ notmuch_config_command_set (void *ctx, char *item, int 
argc, char *argv[])
 return ret;
 }

+static int
+notmuch_config_command_list (void *ctx)
+{
+notmuch_config_t *config;
+char **groups;
+size_t g, groups_length;
+
+config = notmuch_config_open (ctx, NULL, NULL);
+if (config == NULL)
+   return 1;
+
+groups = g_key_file_get_groups (config->key_file, _length);
+if (groups == NULL)
+   return 1;
+
+for (g = 0; g < groups_length; g++) {
+   char **keys;
+   size_t k, keys_length;
+
+   keys = g_key_file_get_keys (config->key_file,
+   groups[g], _length, NULL);
+   if (keys == NULL)
+   continue;
+
+   for (k = 0; k < keys_length; k++) {
+   char *value;
+
+   value = g_key_file_get_string (config->key_file,
+  groups[g], keys[k], NULL);
+   if (value != NULL) {
+   printf ("%s.%s=%s\n", groups[g], keys[k], value);
+   free (value);
+   }
+   }
+
+   g_strfreev (keys);
+}
+
+g_strfreev (groups);
+
+notmuch_config_close (config);
+
+return 0;
+}
+
 int
 notmuch_config_command (void *ctx, int argc, char *argv[])
 {
@@ -823,6 +868,8 @@ notmuch_config_command (void *ctx, int argc, char *argv[])
return 1;
}
return notmuch_config_command_set (ctx, argv[1], argc - 2, argv + 2);
+} else if (strcmp (argv[0], "list") == 0) {
+   return notmuch_config_command_list (ctx);
 }

 fprintf (stderr, "Unrecognized argument for notmuch config: %s\n",
diff --git a/test/config b/test/config
index 3bf8098..93ecb13 100755
--- a/test/config
+++ b/test/config
@@ -43,7 +43,6 @@ notmuch config set foo.nonexistent
 test_expect_equal "$(notmuch config get foo.nonexistent)" ""

 test_begin_subtest "List all items"
-test_subtest_known_broken
 notmuch config set database.path "/canonical/path"
 output=$(notmuch config list)
 test_expect_equal "$output" "\
-- 
1.7.4.4



[PATCH v4 4/6] test: Add broken test for 'config list'

2012-04-14 Thread Peter Wang
Proposed functionality.
---
 test/config |   16 
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/test/config b/test/config
index 9030154..3bf8098 100755
--- a/test/config
+++ b/test/config
@@ -42,4 +42,20 @@ test_begin_subtest "Remove non-existent key"
 notmuch config set foo.nonexistent
 test_expect_equal "$(notmuch config get foo.nonexistent)" ""

+test_begin_subtest "List all items"
+test_subtest_known_broken
+notmuch config set database.path "/canonical/path"
+output=$(notmuch config list)
+test_expect_equal "$output" "\
+database.path=/canonical/path
+user.name=Notmuch Test Suite
+user.primary_email=test_suite at notmuchmail.org
+user.other_email=test_suite_other at notmuchmail.org;test_suite at 
otherdomain.org
+new.tags=unread;inbox;
+new.ignore=
+search.exclude_tags=
+maildir.synchronize_flags=true
+foo.string=this is another string value
+foo.list=this;is another;list value;"
+
 test_done
-- 
1.7.4.4



[PATCH v4 3/6] test: Add tests for 'config' command

2012-04-14 Thread Peter Wang
Start a new test script.
---
 test/config   |   45 +
 test/notmuch-test |1 +
 2 files changed, 46 insertions(+), 0 deletions(-)
 create mode 100755 test/config

diff --git a/test/config b/test/config
new file mode 100755
index 000..9030154
--- /dev/null
+++ b/test/config
@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+
+test_description='"notmuch config"'
+. test-lib.sh
+
+test_begin_subtest "Get string value"
+test_expect_equal "$(notmuch config get user.name)" "Notmuch Test Suite"
+
+test_begin_subtest "Get list value"
+test_expect_equal "$(notmuch config get new.tags)" "\
+unread
+inbox"
+
+test_begin_subtest "Set string value"
+notmuch config set foo.string "this is a string value"
+test_expect_equal "$(notmuch config get foo.string)" "this is a string value"
+
+test_begin_subtest "Set string value again"
+notmuch config set foo.string "this is another string value"
+test_expect_equal "$(notmuch config get foo.string)" "this is another string 
value"
+
+test_begin_subtest "Set list value"
+notmuch config set foo.list this "is a" "list value"
+test_expect_equal "$(notmuch config get foo.list)" "\
+this
+is a
+list value"
+
+test_begin_subtest "Set list value again"
+notmuch config set foo.list this "is another" "list value"
+test_expect_equal "$(notmuch config get foo.list)" "\
+this
+is another
+list value"
+
+test_begin_subtest "Remove key"
+notmuch config set foo.remove baz
+notmuch config set foo.remove
+test_expect_equal "$(notmuch config get foo.remove)" ""
+
+test_begin_subtest "Remove non-existent key"
+notmuch config set foo.nonexistent
+test_expect_equal "$(notmuch config get foo.nonexistent)" ""
+
+test_done
diff --git a/test/notmuch-test b/test/notmuch-test
index f03b594..e08ec72 100755
--- a/test/notmuch-test
+++ b/test/notmuch-test
@@ -19,6 +19,7 @@ cd $(dirname "$0")
 TESTS="
   basic
   help-test
+  config
   new
   count
   search
-- 
1.7.4.4



[PATCH v4 2/6] config: Check 'config get' arity exactly

2012-04-14 Thread Peter Wang
Require that 'config get' is passed exactly one additional argument,
instead of silently ignoring extra arguments. As a side-effect, produce
more specific error messages for the 'config' command as a whole.
---
 notmuch-config.c |   19 +++
 1 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/notmuch-config.c b/notmuch-config.c
index 85fc774..f9eb977 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -804,15 +804,26 @@ notmuch_config_command (void *ctx, int argc, char *argv[])
 {
 argc--; argv++; /* skip subcommand argument */

-if (argc < 2) {
-   fprintf (stderr, "Error: notmuch config requires at least two 
arguments.\n");
+if (argc < 1) {
+   fprintf (stderr, "Error: notmuch config requires at least one 
argument.\n");
return 1;
 }

-if (strcmp (argv[0], "get") == 0)
+if (strcmp (argv[0], "get") == 0) {
+   if (argc != 2) {
+   fprintf (stderr, "Error: notmuch config get requires exactly "
+"one argument.\n");
+   return 1;
+   }
return notmuch_config_command_get (ctx, argv[1]);
-else if (strcmp (argv[0], "set") == 0)
+} else if (strcmp (argv[0], "set") == 0) {
+   if (argc < 2) {
+   fprintf (stderr, "Error: notmuch config set requires at least "
+"one argument.\n");
+   return 1;
+   }
return notmuch_config_command_set (ctx, argv[1], argc - 2, argv + 2);
+}

 fprintf (stderr, "Unrecognized argument for notmuch config: %s\n",
 argv[0]);
-- 
1.7.4.4



[PATCH v4 1/6] config: Fix free in 'config get' implementation.

2012-04-14 Thread Peter Wang
The array returned by g_key_file_get_string_list() should be freed with
g_strfreev(), not free().
---
 notmuch-config.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/notmuch-config.c b/notmuch-config.c
index e9b2750..85fc774 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -751,7 +751,7 @@ notmuch_config_command_get (void *ctx, char *item)
for (i = 0; i < length; i++)
printf ("%s\n", value[i]);

-   free (value);
+   g_strfreev (value);
 }

 notmuch_config_close (config);
-- 
1.7.4.4



[PATCH v4 0/6] Config-related patches

2012-04-14 Thread Peter Wang
Changes from v3:
- rephrase part of the 'list' implementation as a separate patch
- test 'set' on an extant key
- test removing keys

Peter Wang (6):
  config: Fix free in 'config get' implementation.
  config: Check 'config get' arity exactly
  test: Add tests for 'config' command
  test: Add broken test for 'config list'
  config: Add 'config list' command
  man: Document 'config list' command

 man/man1/notmuch-config.1 |   14 +
 notmuch-config.c  |   68 +---
 test/config   |   60 +++
 test/notmuch-test |1 +
 4 files changed, 138 insertions(+), 5 deletions(-)
 create mode 100755 test/config

-- 
1.7.4.4



[PATCH v4 0/6] Config-related patches

2012-04-14 Thread Mark Walters
On Sat, 14 Apr 2012, Peter Wang  wrote:
> Changes from v3:
> - rephrase part of the 'list' implementation as a separate patch
> - test 'set' on an extant key
> - test removing keys

This looks good to me. +1

Two minor comments which you might like to consider (but definitely are
not required):
1) You could check that there are no further arguments when the user
calls `notmuch config list'
2) In the man page you could explicitly say what the output is for a
configuration item which has not been set.

Best wishes

Mark






> Peter Wang (6):
>   config: Fix free in 'config get' implementation.
>   config: Check 'config get' arity exactly
>   test: Add tests for 'config' command
>   test: Add broken test for 'config list'
>   config: Add 'config list' command
>   man: Document 'config list' command
>
>  man/man1/notmuch-config.1 |   14 +
>  notmuch-config.c  |   68 +---
>  test/config   |   60 +++
>  test/notmuch-test |1 +
>  4 files changed, 138 insertions(+), 5 deletions(-)
>  create mode 100755 test/config
>
> -- 
> 1.7.4.4
>
> ___
> notmuch mailing list
> notmuch at notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v4 0/6] Config-related patches

2012-04-14 Thread Mark Walters
On Sat, 14 Apr 2012, Peter Wang noval...@gmail.com wrote:
 Changes from v3:
 - rephrase part of the 'list' implementation as a separate patch
 - test 'set' on an extant key
 - test removing keys

This looks good to me. +1

Two minor comments which you might like to consider (but definitely are
not required):
1) You could check that there are no further arguments when the user
calls `notmuch config list'
2) In the man page you could explicitly say what the output is for a
configuration item which has not been set.

Best wishes

Mark






 Peter Wang (6):
   config: Fix free in 'config get' implementation.
   config: Check 'config get' arity exactly
   test: Add tests for 'config' command
   test: Add broken test for 'config list'
   config: Add 'config list' command
   man: Document 'config list' command

  man/man1/notmuch-config.1 |   14 +
  notmuch-config.c  |   68 +---
  test/config   |   60 +++
  test/notmuch-test |1 +
  4 files changed, 138 insertions(+), 5 deletions(-)
  create mode 100755 test/config

 -- 
 1.7.4.4

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


[PATCH v2 0/6] batch tagging support: notmuch tag --stdin

2012-04-14 Thread Jani Nikula
v2 of id:cover.1333231401.git.j...@nikula.org

This series adds support for batch tagging through stdin to notmuch
tag. This should be useful and efficient for e.g. initial tagging
scripts. Also, this adds locking around a batch of tag changes, which is
also useful for initial tagging scripts. See the test patch for an
example using a here document.

The idea is that the same format (and parser) would be later used for
notmuch dump/restore, building on David's earlier work at
id:1324214111-32079-1-git-send-email-da...@tethera.net.

The v2 only has non-functional changes per David's comments, and
squashes the first three patches of v1 into one.

BR,
Jani.


David Bremner (3):
  hex-escape: (en|de)code strings to/from restricted character set
  test/hex-xcode: new test binary
  test/hex-escaping: new test for hex escaping routines

Jani Nikula (3):
  cli: add support for batch tagging operations to notmuch tag
  test: add test for notmuch tag --stdin option
  man: document notmuch tag --stdin option

 man/man1/notmuch-tag.1 |   44 +-
 notmuch-tag.c  |  244 ++--
 test/.gitignore|1 +
 test/Makefile.local|6 +-
 test/basic |2 +-
 test/hex-escaping  |   26 +
 test/hex-xcode.c   |  103 
 test/notmuch-test  |1 +
 test/tagging   |   13 +++
 util/Makefile.local|2 +-
 util/hex-escape.c  |  168 +
 util/hex-escape.h  |   41 
 12 files changed, 616 insertions(+), 35 deletions(-)
 create mode 100755 test/hex-escaping
 create mode 100644 test/hex-xcode.c
 create mode 100644 util/hex-escape.c
 create mode 100644 util/hex-escape.h

-- 
1.7.5.4

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


[PATCH v2 1/6] hex-escape: (en|de)code strings to/from restricted character set

2012-04-14 Thread Jani Nikula
From: David Bremner brem...@debian.org

The character set is chosen to be suitable for pathnames, and the same
as that used by contrib/nmbug

[With additions by Jani Nikula]
---
 util/Makefile.local |2 +-
 util/hex-escape.c   |  168 +++
 util/hex-escape.h   |   41 
 3 files changed, 210 insertions(+), 1 deletions(-)
 create mode 100644 util/hex-escape.c
 create mode 100644 util/hex-escape.h

diff --git a/util/Makefile.local b/util/Makefile.local
index c7cae61..3ca623e 100644
--- a/util/Makefile.local
+++ b/util/Makefile.local
@@ -3,7 +3,7 @@
 dir := util
 extra_cflags += -I$(srcdir)/$(dir)
 
-libutil_c_srcs := $(dir)/xutil.c $(dir)/error_util.c
+libutil_c_srcs := $(dir)/xutil.c $(dir)/error_util.c $(dir)/hex-escape.c
 
 libutil_modules := $(libutil_c_srcs:.c=.o)
 
diff --git a/util/hex-escape.c b/util/hex-escape.c
new file mode 100644
index 000..d8905d0
--- /dev/null
+++ b/util/hex-escape.c
@@ -0,0 +1,168 @@
+/* hex-escape.c -  Manage encoding and decoding of byte strings into path names
+ *
+ * Copyright (c) 2011 David Bremner
+ *
+ * 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: David Bremner da...@tethera.net
+ */
+
+#include assert.h
+#include string.h
+#include talloc.h
+#include ctype.h
+#include error_util.h
+#include hex-escape.h
+
+static const size_t default_buf_size = 1024;
+
+static const char *output_charset =
+ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-_@=.:,;
+
+static const char escape_char = '%';
+
+static int
+is_output (char c)
+{
+return (strchr (output_charset, c) != NULL);
+}
+
+static int
+maybe_realloc (void *ctx, size_t needed, char **out, size_t *out_size)
+{
+if (*out_size  needed) {
+
+   if (*out == NULL)
+   *out = talloc_size (ctx, needed);
+   else
+   *out = talloc_realloc (ctx, *out, char, needed);
+
+   if (*out == NULL)
+   return 0;
+
+   *out_size = needed;
+}
+return 1;
+}
+
+hex_status_t
+hex_encode (void *ctx, const char *in, char **out, size_t *out_size)
+{
+
+const unsigned char *p;
+char *q;
+
+size_t escape_count = 0;
+size_t len = 0;
+size_t needed;
+
+assert (ctx); assert (in); assert (out); assert (out_size);
+
+for (p = (unsigned char *) in; *p; p++) {
+   escape_count += (!is_output (*p));
+   len++;
+}
+
+needed = len + escape_count * 2 + 1;
+
+if (*out == NULL)
+   *out_size = 0;
+
+if (!maybe_realloc (ctx, needed, out, out_size))
+   return HEX_OUT_OF_MEMORY;
+
+q = *out;
+p = (unsigned char *) in;
+
+while (*p) {
+   if (is_output (*p)) {
+   *q++ = *p++;
+   } else {
+   sprintf (q, %%%02x, *p++);
+   q += 3;
+   }
+}
+
+*q = '\0';
+return HEX_SUCCESS;
+}
+
+/* Hex decode 'in' to 'out'.
+ *
+ * This must succeed for in == out to support hex_decode_inplace().
+ */
+static hex_status_t
+hex_decode_internal (const char *in, unsigned char *out)
+{
+char buf[3];
+
+while (*in) {
+   if (*in == escape_char) {
+   char *endp;
+
+   /* This also handles unexpected end-of-string. */
+   if (!isxdigit ((unsigned char) in[1]) ||
+   !isxdigit ((unsigned char) in[2]))
+   return HEX_SYNTAX_ERROR;
+
+   buf[0] = in[1];
+   buf[1] = in[2];
+   buf[2] = '\0';
+
+   *out = strtoul (buf, endp, 16);
+
+   if (endp != buf + 2)
+   return HEX_SYNTAX_ERROR;
+
+   in += 3;
+   out++;
+   } else {
+   *out++ = *in++;
+   }
+}
+
+*out = '\0';
+
+return HEX_SUCCESS;
+}
+
+hex_status_t
+hex_decode_inplace (char *s)
+{
+/* A decoded string is never longer than the encoded one, so it is
+ * safe to decode a string onto itself. */
+return hex_decode_internal (s, (unsigned char *) s);
+}
+
+hex_status_t
+hex_decode (void *ctx, const char *in, char **out, size_t * out_size)
+{
+const char *p;
+size_t escape_count = 0;
+size_t needed = 0;
+
+assert (ctx); assert (in); assert (out); assert (out_size);
+
+size_t len = strlen (in);
+
+for (p = in; *p; p++)
+   escape_count += (*p == escape_char);
+
+needed = len - escape_count * 2 + 1;
+
+if (!maybe_realloc (ctx, needed, out, out_size))
+   return 

[PATCH v2 2/6] test/hex-xcode: new test binary

2012-04-14 Thread Jani Nikula
From: David Bremner brem...@debian.org

This program is used both as a test-bed/unit-tester for
../util/hex-escape.c, and also as a utility in future tests of dump
and restore.
---
 test/.gitignore |1 +
 test/Makefile.local |6 ++-
 test/basic  |2 +-
 test/hex-xcode.c|  103 +++
 4 files changed, 110 insertions(+), 2 deletions(-)
 create mode 100644 test/hex-xcode.c

diff --git a/test/.gitignore b/test/.gitignore
index e63c689..be7ab5e 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -3,4 +3,5 @@ corpus.mail
 smtp-dummy
 symbol-test
 arg-test
+hex-xcode
 tmp.*
diff --git a/test/Makefile.local b/test/Makefile.local
index 4a6a4b1..9cecd28 100644
--- a/test/Makefile.local
+++ b/test/Makefile.local
@@ -13,6 +13,9 @@ smtp_dummy_modules = $(smtp_dummy_srcs:.c=.o)
 $(dir)/arg-test: $(dir)/arg-test.o command-line-arguments.o util/libutil.a
$(call quiet,CC) -I. $^ -o $@
 
+$(dir)/hex-xcode: $(dir)/hex-xcode.o command-line-arguments.o util/libutil.a
+   $(call quiet,CC) -I. $^ -o $@ -ltalloc
+
 $(dir)/smtp-dummy: $(smtp_dummy_modules)
$(call quiet,CC) $^ -o $@
 
@@ -21,7 +24,8 @@ $(dir)/symbol-test: $(dir)/symbol-test.o
 
 .PHONY: test check
 
-test-binaries: $(dir)/arg-test $(dir)/smtp-dummy $(dir)/symbol-test
+test-binaries: $(dir)/arg-test $(dir)/hex-xcode \
+$(dir)/smtp-dummy $(dir)/symbol-test
 
 test:  all test-binaries
@${dir}/notmuch-test $(OPTIONS)
diff --git a/test/basic b/test/basic
index d6aed24..af57026 100755
--- a/test/basic
+++ b/test/basic
@@ -54,7 +54,7 @@ test_begin_subtest 'Ensure that all available tests will be 
run by notmuch-test'
 eval $(sed -n -e '/^TESTS=$/,/^$/p' $TEST_DIRECTORY/notmuch-test)
 tests_in_suite=$(for i in $TESTS; do echo $i; done | sort)
 available=$(find $TEST_DIRECTORY -maxdepth 1 -type f -executable -printf 
'%f\n' | \
-sed -r -e 
/^(aggregate-results.sh|notmuch-test|smtp-dummy|test-verbose|symbol-test|arg-test)$/d
 | \
+sed -r -e 
/^(aggregate-results.sh|notmuch-test|smtp-dummy|test-verbose|symbol-test|arg-test|hex-xcode)$/d
 | \
 sort)
 test_expect_equal $tests_in_suite $available
 
diff --git a/test/hex-xcode.c b/test/hex-xcode.c
new file mode 100644
index 000..eec6541
--- /dev/null
+++ b/test/hex-xcode.c
@@ -0,0 +1,103 @@
+/* No, nothing to to with IDE from Apple Inc.
+   testbed for ../util/hex-escape.c.
+
+   usage:
+   hex-xcode [--direction=(encode|decode)] [--omit-newline]  file
+   hex-xcode [--direction=(encode|decode)] [--omit-newline] arg1 arg2 arg3 ...
+
+ */
+
+#include notmuch-client.h
+#include hex-escape.h
+#include assert.h
+
+
+enum direction {
+ENCODE,
+DECODE
+};
+
+static int
+xcode (void *ctx, enum direction dir, char *in, char **buf_p, size_t *size_p)
+{
+hex_status_t status;
+
+if (dir == ENCODE)
+   status = hex_encode (ctx, in, buf_p, size_p);
+else
+   status = hex_decode (ctx, in, buf_p, size_p);
+
+if (status == HEX_SUCCESS)
+   fputs (*buf_p, stdout);
+
+return status;
+}
+
+
+int
+main (int argc, char **argv)
+{
+
+
+enum direction dir = DECODE;
+int omit_newline = FALSE;
+
+notmuch_opt_desc_t options[] = {
+   { NOTMUCH_OPT_KEYWORD, dir, direction, 'd',
+ (notmuch_keyword_t []){ { encode, ENCODE },
+ { decode, DECODE },
+ { 0, 0 } } },
+   { NOTMUCH_OPT_BOOLEAN, omit_newline, omit-newline, 'n', 0 },
+   { 0, 0, 0, 0, 0 }
+};
+
+int opt_index = parse_arguments (argc, argv, options, 1);
+
+if (opt_index  0)
+   exit (1);
+
+void *ctx = talloc_new (NULL);
+
+char *line = NULL;
+size_t line_size;
+ssize_t line_len;
+
+char *buffer = NULL;
+size_t buf_size = 0;
+
+notmuch_bool_t read_stdin = TRUE;
+
+for (; opt_index  argc; opt_index++) {
+
+   if (xcode (ctx, dir, argv[opt_index],
+  buffer, buf_size) != HEX_SUCCESS)
+   return 1;
+
+   if (!omit_newline)
+   putchar ('\n');
+
+   read_stdin = FALSE;
+}
+
+if (!read_stdin)
+   return 0;
+
+while ((line_len = getline (line, line_size, stdin)) != -1) {
+
+   chomp_newline (line);
+
+   if (xcode (ctx, dir, line, buffer, buf_size) != HEX_SUCCESS)
+   return 1;
+
+   if (!omit_newline)
+   putchar ('\n');
+
+}
+
+if (line)
+   free (line);
+
+talloc_free (ctx);
+
+return 0;
+}
-- 
1.7.5.4

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


[PATCH v2 3/6] test/hex-escaping: new test for hex escaping routines

2012-04-14 Thread Jani Nikula
From: David Bremner brem...@debian.org

These are more like unit tests, to (try to) make sure the library
functionality is working before building more complicated things on
top of it.
---
 test/hex-escaping |   26 ++
 test/notmuch-test |1 +
 2 files changed, 27 insertions(+), 0 deletions(-)
 create mode 100755 test/hex-escaping

diff --git a/test/hex-escaping b/test/hex-escaping
new file mode 100755
index 000..f34cc8c
--- /dev/null
+++ b/test/hex-escaping
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+test_description=hex encoding and decoding
+. ./test-lib.sh
+
+test_begin_subtest round trip
+find $TEST_DIRECTORY/corpus -type f -print | sort | xargs cat  EXPECTED
+$TEST_DIRECTORY/hex-xcode --direction=encode  EXPECTED | 
$TEST_DIRECTORY/hex-xcode --direction=decode  OUTPUT
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest punctuation
+tag1='comic_swear=$^%$^%\\//-+$^%$'
+tag_enc1=$($TEST_DIRECTORY/hex-xcode --direction=encode $tag1)
+test_expect_equal $tag_enc1 
comic_swear=%24%26%5e%25%24%5e%25%5c%5c%2f%2f-+%24%5e%25%24
+
+test_begin_subtest round trip newlines
+printf 'this\n tag\t has\n spaces\n'  EXPECTED.$test_count
+$TEST_DIRECTORY/hex-xcode --direction=encode   EXPECTED.$test_count |\
+   $TEST_DIRECTORY/hex-xcode --direction=decode  OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest round trip 8bit chars
+echo '%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a'  EXPECTED.$test_count
+$TEST_DIRECTORY/hex-xcode --direction=decode   EXPECTED.$test_count |\
+   $TEST_DIRECTORY/hex-xcode --direction=encode  OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+test_done
diff --git a/test/notmuch-test b/test/notmuch-test
index 801df73..2d0b381 100755
--- a/test/notmuch-test
+++ b/test/notmuch-test
@@ -57,6 +57,7 @@ TESTS=
   emacs-address-cleaning
   emacs-hello
   emacs-show
+  hex-escaping
 
 TESTS=${NOTMUCH_TESTS:=$TESTS}
 
-- 
1.7.5.4

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


[PATCH v2 4/6] cli: add support for batch tagging operations to notmuch tag

2012-04-14 Thread Jani Nikula
Add support for batch tagging operations through stdin to notmuch
tag. This can be enabled with the new --stdin command line option to
notmuch new. The input must consist of lines of the format:

T +tag|-tag [...] [--] search-terms

Each line is interpreted similarly to notmuch tag command line
arguments. The delimiter is one or more spaces ' '. Any characters in
tag and search-terms MAY be hex encoded with %NN where NN is the
hexadecimal value of the character. Any ' ' and '%' characters in
tag and search-terms MUST be hex encoded (using %20 and %25,
respectively). Any characters that are not part of tag or
search-terms MUST NOT be hex encoded.

Leading and trailing space ' ' is ignored. Empty lines and lines
beginning with '#' are ignored.

Signed-off-by: Jani Nikula j...@nikula.org
---
 notmuch-tag.c |  244 +---
 1 files changed, 213 insertions(+), 31 deletions(-)

diff --git a/notmuch-tag.c b/notmuch-tag.c
index 05feed3..e67555f 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -19,6 +19,7 @@
  */
 
 #include notmuch-client.h
+#include hex-escape.h
 
 static volatile sig_atomic_t interrupted;
 
@@ -167,17 +168,181 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const 
char *query_string,
 return interrupted;
 }
 
+/* like strtok(3), but without state, and doesn't modify s. usage pattern:
+ *
+ * const char *tok = input;
+ * const char *delim =  \t;
+ * size_t tok_len = 0;
+ *
+ * while ((tok = strtok_len (tok + tok_len, delim, tok_len)) != NULL) {
+ * // do stuff with string tok of length tok_len
+ * }
+ */
+static
+char *strtok_len(char *s, const char *delim, size_t *len)
+{
+/* skip initial delims */
+s += strspn (s, delim);
+
+/* length of token */
+*len = strcspn (s, delim);
+
+return *len ? s : NULL;
+}
+
+/* Tag messages according to 'input', which must consist of lines of
+ * the format:
+ *
+ * T +tag|-tag [...] [--] search-terms
+ *
+ * Each line is interpreted similarly to notmuch tag command line
+ * arguments. The delimiter is one or more spaces ' '. Any characters
+ * in tag and search-terms MAY be hex encoded with %NN where NN is
+ * the hexadecimal value of the character. Any ' ' and '%' characters
+ * in tag and search-terms MUST be hex encoded (using %20 and %25,
+ * respectively). Any characters that are not part of tag or
+ * search-terms MUST NOT be hex encoded.
+ *
+ * Leading and trailing space ' ' is ignored. Empty lines and lines
+ * beginning with '#' are ignored.
+ */
+static int
+tag_file (void *ctx, notmuch_database_t *notmuch, FILE *input,
+ notmuch_bool_t synchronize_flags)
+{
+char *line = NULL;
+size_t line_size;
+ssize_t line_len;
+tag_operation_t *tag_ops;
+int tag_ops_array_size = 10;
+int ret = 0;
+
+/* Array of tagging operations (add or remove), terminated with an
+ * empty element. Size will be increased as necessary. */
+tag_ops = talloc_array (ctx, tag_operation_t, tag_ops_array_size);
+if (tag_ops == NULL) {
+   fprintf (stderr, Out of memory.\n);
+   return 1;
+}
+
+while ((line_len = getline (line, line_size, input)) != -1 
+  !interrupted) {
+   char *tok;
+   size_t tok_len;
+   int tag_ops_count = 0;
+
+   chomp_newline (line);
+
+   tok = strtok_len (line,  , tok_len);
+
+   /* Skip empty and comment lines. */
+   if (tok == NULL || *tok == '#')
+   continue;
+
+   /* T for tagging is the only recognized action for now. */
+   if (strncmp (tok, T, tok_len) != 0) {
+   fprintf (stderr, Warning: Ignoring invalid input line: %s\n,
+line);
+   continue;
+   }
+
+   /* Parse tags. */
+   while ((tok = strtok_len (tok + tok_len,  , tok_len)) != NULL) {
+   notmuch_bool_t remove;
+   char *tag;
+
+   /* Optional explicit end of tags marker. */
+   if (strncmp (tok, --, tok_len) == 0) {
+   tok = strtok_len (tok + tok_len,  , tok_len);
+   break;
+   }
+
+   /* Implicit end of tags. */
+   if (*tok != '-'  *tok != '+')
+   break;
+
+   /* If tag is terminated by NUL, there's no query string. */
+   if (*(tok + tok_len) == '\0') {
+   tok = NULL;
+   break;
+   }
+
+   /* Terminate, and start next token after terminator. */
+   *(tok + tok_len++) = '\0';
+
+   remove = (*tok == '-');
+   tag = tok + 1;
+
+   /* Refuse empty tags. */
+   if (*tag == '\0') {
+   tok = NULL;
+   break;
+   }
+
+   /* Decode tag. */
+   if (hex_decode_inplace (tag) != HEX_SUCCESS) {
+   tok = NULL;
+   break;
+   }
+
+   tag_ops[tag_ops_count].tag = tag;
+   tag_ops[tag_ops_count].remove = remove;
+   tag_ops_count++;
+
+   /* Make room for 

[PATCH v2 5/6] test: add test for notmuch tag --stdin option

2012-04-14 Thread Jani Nikula
---
 test/tagging |   13 +
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/test/tagging b/test/tagging
index e4782ed..15eb42d 100755
--- a/test/tagging
+++ b/test/tagging
@@ -46,4 +46,17 @@ test_expect_equal $output \
 thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; One (:\  inbox tag1 unread)
 thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag4 unread)
 
+test_begin_subtest Batch stdin
+notmuch tag --stdin EOF
+# %20 is a space in tag
+T -:%20 -tag1 +tag5 +tag6 -- One
+T +tag1 -tag1 -tag4 +tag4 -- Two
+T -tag6 One
+T +tag5 Two
+EOF
+output=$(notmuch search \* | notmuch_search_sanitize)
+test_expect_equal $output \
+thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag5 unread)
+thread:XXX   2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag4 tag5 unread)
+
 test_done
-- 
1.7.5.4

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


[PATCH v2 6/6] man: document notmuch tag --stdin option

2012-04-14 Thread Jani Nikula
---
 man/man1/notmuch-tag.1 |   44 +++-
 1 files changed, 43 insertions(+), 1 deletions(-)

diff --git a/man/man1/notmuch-tag.1 b/man/man1/notmuch-tag.1
index aa4546e..30693cf 100644
--- a/man/man1/notmuch-tag.1
+++ b/man/man1/notmuch-tag.1
@@ -4,7 +4,11 @@ notmuch-tag \- Add/remove tags for all messages matching the 
search terms.
 
 .SH SYNOPSIS
 .B notmuch tag
-.RI  + tag |\- tag  [...] [\-\-]  search-term ...
+.RI + tag |\- tag  [...] [\-\-]  search-terms 
+
+.B notmuch tag
+.RI --stdin
+
 
 .SH DESCRIPTION
 
@@ -29,6 +33,44 @@ updates the maildir flags according to tag changes if the
 configuration option is enabled. See \fBnotmuch-config\fR(1) for
 details.
 
+Supported options for
+.B tag
+include
+.RS 4
+.TP 4
+.BR \-\-stdin
+
+Read batch tagging operations from standard input. This is more
+efficient than repeated
+.B notmuch tag
+invocations. See
+.B TAG FILE FORMAT
+below for the input format. This option is not compatible with
+specifying tagging on the command line.
+.RE
+
+.SH TAG FILE FORMAT
+
+The input must consist of lines of the format:
+
+.RI T + tag |\- tag  [...] [\-\-]  search-terms 
+
+Each line is interpreted similarly to
+.B notmuch tag
+command line arguments. The delimiter is one or more spaces ' '. Any
+characters in tag and search-terms
+.B may
+be hex encoded with %NN where NN is the hexadecimal value of the
+character. Any ' ' and '%' characters in tag and search-terms
+.B must
+be hex encoded (using %20 and %25, respectively). Any characters that
+are not part of tag or search-terms
+.B must not
+be hex encoded.
+
+Leading and trailing space ' ' is ignored. Empty lines and lines
+beginning with '#' are ignored.
+
 .SH SEE ALSO
 
 \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1),
-- 
1.7.5.4

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


[PATCH 2/5] emacs: allow notmuch-tag to accept string inputs and prompt for tags

2012-04-14 Thread Jameson Graef Rollins
notmuch-tag is extended to accept various formats of the tag changes.
In particular, user prompting for tag changes is now incorporated
here, so it is common for modes.

The tag binary and the notmuch-{before,after}-tag-hooks are only
called if tag changes is non-nil.

The actual tag-changes applied are returned by the function.
---
 emacs/notmuch-tag.el |   20 +++-
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
index c25cff8..dd7f9d7 100644
--- a/emacs/notmuch-tag.el
+++ b/emacs/notmuch-tag.el
@@ -108,18 +108,26 @@ from TAGS if present.
   (error Changed tag must be of the form `+this_tag' or 
`-that_tag')
 (sort result-tags 'string)))
 
-(defun notmuch-tag (query rest tag-changes)
+(defun notmuch-tag (query optional tag-changes)
   Add/remove tags in TAG-CHANGES to messages matching QUERY.
 
-TAG-CHANGES should be a list of strings of the form \+tag\ or
-\-tag\ and QUERY should be a string containing the
-search-query.
+QUERY should be a string containing the search-terms.
+TAG-CHANGES can take multiple forms.  If TAG-CHANGES is a list of
+strings of the form \+tag\ or \-tag\ then those are the tag
+changes applied.  If TAG-CHANGES is a string then it is
+interpreted as a single tag change.  If TAG-CHANGES is the string
+\-\ or \+\, or null, then the user is prompted to enter the
+tag changes.
 
 Note: Other code should always use this function alter tags of
 messages instead of running (notmuch-call-notmuch-process \tag\ ..)
 directly, so that hooks specified in notmuch-before-tag-hook and
 notmuch-after-tag-hook will be run.
   ;; Perform some validation
+  (if (string-or-null-p tag-changes)
+  (if (or (string= tag-changes -) (string= tag-changes +) (null 
tag-changes))
+ (setq tag-changes (notmuch-read-tag-changes tag-changes query))
+   (setq tag-changes (list tag-changes
   (mapc (lambda (tag-change)
  (unless (string-match-p ^[-+]\\S-+$ tag-change)
(error Tag must be of the form `+this_tag' or `-that_tag')))
@@ -128,7 +136,9 @@ notmuch-after-tag-hook will be run.
 (run-hooks 'notmuch-before-tag-hook)
 (apply 'notmuch-call-notmuch-process tag
   (append tag-changes (list -- query)))
-(run-hooks 'notmuch-after-tag-hook)))
+(run-hooks 'notmuch-after-tag-hook))
+  ;; return the list of actual changed tags
+  tag-changes)
 
 ;;
 
-- 
1.7.9.5

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


emacs tagging cleanup, v3

2012-04-14 Thread Jameson Graef Rollins
This is a further cleaned up and simplified version of [0].  The scope
is slightly reduced, but we still end up with a simpler user
interface, with the primary tagging functions being:

notmuch-search-tag
notmuch-show-tag

In this series only one user facing tagging function,
notmuch-search-tag-thread, is removed, since it is completely
redundant with the now more flexible notmuch-search-tag.

jamie.

[0] id:1333845338-22960-1-git-send-email-jroll...@finestructure.net

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


[PATCH 4/5] emacs: modify show tag functions to use new notmuch-tag interface

2012-04-14 Thread Jameson Graef Rollins
The main change here is to modify argument parsing so as to not force
tag-changes to be a list, and to let notmuch-tag handle prompting the
user when required.  doc strings are also updated and cleaned up.
---
 emacs/notmuch-show.el |   26 +++---
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index a4c313d..69bca02 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -1641,22 +1641,26 @@ TAG-CHANGES is a list of tag operations for 
`notmuch-tag'.
   (let* ((current-tags (notmuch-show-get-tags))
 (new-tags (notmuch-update-tags current-tags tag-changes)))
 (unless (equal current-tags new-tags)
-  (apply 'notmuch-tag (notmuch-show-get-message-id) tag-changes)
+  (funcall 'notmuch-tag (notmuch-show-get-message-id) tag-changes)
   (notmuch-show-set-tags new-tags
 
-(defun notmuch-show-tag (optional initial-input)
-  Change tags for the current message, read input from the minibuffer.
+(defun notmuch-show-tag (optional tag-changes)
+  Change tags for the current message.
+
+See `notmuch-tag' for information on the format of TAG-CHANGES.
   (interactive)
-  (let ((tag-changes (notmuch-read-tag-changes
- initial-input (notmuch-show-get-message-id
-(apply 'notmuch-show-tag-message tag-changes)))
+  (setq tag-changes (funcall 'notmuch-tag (notmuch-show-get-message-id) 
tag-changes))
+  (let* ((current-tags (notmuch-show-get-tags))
+(new-tags (notmuch-update-tags current-tags tag-changes)))
+(unless (equal current-tags new-tags)
+  (notmuch-show-set-tags new-tags
 
-(defun notmuch-show-tag-all (rest tag-changes)
-  Change tags for all messages in the current buffer.
+(defun notmuch-show-tag-all (optional tag-changes)
+  Change tags for all messages in the current show buffer.
 
-TAG-CHANGES is a list of tag operations for `notmuch-tag'.
-  (interactive (notmuch-read-tag-changes nil notmuch-show-thread-id))
-  (apply 'notmuch-tag (notmuch-show-get-messages-ids-search) tag-changes)
+See `notmuch-tag' for information on the format of TAG-CHANGES.
+  (interactive)
+  (setq tag-changes (funcall 'notmuch-tag 
(notmuch-show-get-messages-ids-search) tag-changes))
   (notmuch-show-mapc
(lambda ()
  (let* ((current-tags (notmuch-show-get-tags))
-- 
1.7.9.5

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


[PATCH 3/5] emacs: modify search tag functions to use new notmuch-tag interface

2012-04-14 Thread Jameson Graef Rollins
The main change here is to modify argument parsing so as to not force
tag-changes to be a list, and to let notmuch-tag handle prompting the
user when required.  doc strings are also updated and cleaned up.
---
 emacs/notmuch.el |   36 +---
 1 file changed, 13 insertions(+), 23 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 9aec96d..a03a526 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -523,13 +523,10 @@ and will also appear in a buffer named \*Notmuch 
errors*\.
 See `notmuch-search-tag-region' for details.
   (apply 'notmuch-search-tag-region (point) (point) tag-changes))
 
-(defun notmuch-search-tag-region (beg end rest tag-changes)
-  Change tags for threads in the given region.
-
-TAGS is a list of tag operations for `notmuch-tag'.  The tags are
-added or removed for all threads in the region from BEG to END.
+(defun notmuch-search-tag-region (beg end optional tag-changes)
+  Change tags for threads in the given region.
   (let ((search-string (notmuch-search-find-thread-id-region-search beg end)))
-(apply 'notmuch-tag search-string tag-changes)
+(setq tag-changes (funcall 'notmuch-tag search-string tag-changes))
 (save-excursion
   (let ((last-line (line-number-at-pos end))
(max-line (- (line-number-at-pos (point-max)) 2)))
@@ -539,14 +536,14 @@ added or removed for all threads in the region from BEG 
to END.
   (notmuch-update-tags (notmuch-search-get-tags) tag-changes))
  (forward-line))
 
-(defun notmuch-search-tag (optional initial-input)
-  Change tags for the currently selected thread or region.
+(defun notmuch-search-tag (optional tag-changes)
+  Change tags for the currently selected thread or region.
+
+See `notmuch-tag' for information on the format of TAG-CHANGES.
   (interactive)
   (let* ((beg (if (region-active-p) (region-beginning) (point)))
-(end (if (region-active-p) (region-end) (point)))
-(search-string (notmuch-search-find-thread-id-region-search beg end))
-(tags (notmuch-read-tag-changes initial-input search-string)))
-(apply 'notmuch-search-tag-region beg end tags)))
+(end (if (region-active-p) (region-end) (point
+(funcall 'notmuch-search-tag-region beg end tag-changes)))
 
 (defun notmuch-search-add-tag ()
   Same as `notmuch-search-tag' but sets initial input to '+'.
@@ -790,18 +787,11 @@ non-authors is found, assume that all of the authors 
match.
  (goto-char found-target)))
   (delete-process proc
 
-(defun notmuch-search-tag-all (rest tag-changes)
-  Add/remove tags from all matching messages.
+(defun notmuch-search-tag-all (optional tag-changes)
+  Add/remove tags from all messages in current search buffer.
 
-This 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 `_.+-'.
-
-  (interactive (notmuch-read-tag-changes))
+See `notmuch-tag' for information on the format of TAG-CHANGES.
+  (interactive)
   (apply 'notmuch-tag notmuch-search-query-string tag-changes))
 
 (defun notmuch-search-buffer-title (query)
-- 
1.7.9.5

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


[PATCH 5/5] emacs: eliminate search-tag-thread in favor of just search-tag

2012-04-14 Thread Jameson Graef Rollins
notmuch-search-tag-thread is now completely redundant with
notmuch-search-tag so we eliminate it to simplify the interface.
---
 emacs/notmuch.el |8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index a03a526..cfc3b29 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -517,12 +517,6 @@ and will also appear in a buffer named \*Notmuch 
errors*\.
(forward-line 1))
   output)))
 
-(defun notmuch-search-tag-thread (rest tag-changes)
-  Change tags for the currently selected thread.
-
-See `notmuch-search-tag-region' for details.
-  (apply 'notmuch-search-tag-region (point) (point) tag-changes))
-
 (defun notmuch-search-tag-region (beg end optional tag-changes)
   Change tags for threads in the given region.
   (let ((search-string (notmuch-search-find-thread-id-region-search beg end)))
@@ -560,7 +554,7 @@ See `notmuch-tag' for information on the format of 
TAG-CHANGES.
 
 This function advances the next thread when finished.
   (interactive)
-  (notmuch-search-tag-thread -inbox)
+  (notmuch-search-tag '(-inbox))
   (notmuch-search-next-thread))
 
 (defvar notmuch-search-process-filter-data nil
-- 
1.7.9.5

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


[PATCH 1/5] emacs: create notmuch-tag.el, and move appropriate functions from notmuch.el

2012-04-14 Thread Jameson Graef Rollins
Tagging functions are used in notmuch.el, notmuch-show.el, and
notmuch-message.el.  There are enough common functions for tagging
that it makes sense to put them all in their own library.

No code is modified, just moved around.
---
 emacs/Makefile.local |1 +
 emacs/notmuch-message.el |1 +
 emacs/notmuch-show.el|3 +-
 emacs/notmuch-tag.el |  135 ++
 emacs/notmuch.el |  109 +
 5 files changed, 139 insertions(+), 110 deletions(-)
 create mode 100644 emacs/notmuch-tag.el

diff --git a/emacs/Makefile.local b/emacs/Makefile.local
index 4fee0e8..fb82247 100644
--- a/emacs/Makefile.local
+++ b/emacs/Makefile.local
@@ -13,6 +13,7 @@ emacs_sources := \
$(dir)/notmuch-maildir-fcc.el \
$(dir)/notmuch-message.el \
$(dir)/notmuch-crypto.el \
+   $(dir)/notmuch-tag.el \
$(dir)/coolj.el \
$(dir)/notmuch-print.el
 
diff --git a/emacs/notmuch-message.el b/emacs/notmuch-message.el
index 3010281..5964caa 100644
--- a/emacs/notmuch-message.el
+++ b/emacs/notmuch-message.el
@@ -20,6 +20,7 @@
 ;; Authors: Jesse Rosenthal jrosent...@jhu.edu
 
 (require 'message)
+(require 'notmuch-tag)
 (require 'notmuch-mua)
 
 (defcustom notmuch-message-replied-tags '(replied)
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 30b26d1..a4c313d 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -30,6 +30,7 @@
 (require 'goto-addr)
 
 (require 'notmuch-lib)
+(require 'notmuch-tag)
 (require 'notmuch-query)
 (require 'notmuch-wash)
 (require 'notmuch-mua)
@@ -38,10 +39,8 @@
 
 (declare-function notmuch-call-notmuch-process notmuch (rest args))
 (declare-function notmuch-fontify-headers notmuch nil)
-(declare-function notmuch-read-tag-changes notmuch (optional initial-input 
rest search-terms))
 (declare-function notmuch-search-next-thread notmuch nil)
 (declare-function notmuch-search-show-thread notmuch nil)
-(declare-function notmuch-update-tags notmuch (current-tags tag-changes))
 
 (defcustom notmuch-message-headers '(Subject To Cc Date)
   Headers that should be shown in a message, in this order.
diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
new file mode 100644
index 000..c25cff8
--- /dev/null
+++ b/emacs/notmuch-tag.el
@@ -0,0 +1,135 @@
+;; notmuch-tag.el --- tag messages within emacs
+;;
+;; Copyright © Carl Worth
+;;
+;; This file is part of Notmuch.
+;;
+;; Notmuch is free software: you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Notmuch is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with Notmuch.  If not, see http://www.gnu.org/licenses/.
+;;
+;; Authors: Carl Worth cwo...@cworth.org
+
+(eval-when-compile (require 'cl))
+(require 'crm)
+(require 'notmuch-lib)
+
+(defcustom notmuch-before-tag-hook nil
+  Hooks that are run before tags of a message are modified.
+
+'tags' will contain the tags that are about to be added or removed as
+a list of strings of the form \+TAG\ or \-TAG\.
+'query' will be a string containing the search query that determines
+the messages that are about to be tagged
+
+  :type 'hook
+  :options '(notmuch-hl-line-mode)
+  :group 'notmuch-hooks)
+
+(defcustom notmuch-after-tag-hook nil
+  Hooks that are run after tags of a message are modified.
+
+'tags' will contain the tags that were added or removed as
+a list of strings of the form \+TAG\ or \-TAG\.
+'query' will be a string containing the search query that determines
+the messages that were tagged
+  :type 'hook
+  :options '(notmuch-hl-line-mode)
+  :group 'notmuch-hooks)
+
+(defvar notmuch-select-tag-history nil
+  Variable to store minibuffer history for
+`notmuch-select-tag-with-completion' function.)
+
+(defvar notmuch-read-tag-changes-history nil
+  Variable to store minibuffer history for
+`notmuch-read-tag-changes' function.)
+
+(defun notmuch-tag-completions (optional search-terms)
+  (if (null search-terms)
+  (setq search-terms (list *)))
+  (split-string
+   (with-output-to-string
+ (with-current-buffer standard-output
+   (apply 'call-process notmuch-command nil t
+ nil search --output=tags --exclude=false search-terms)))
+   \n+ t))
+
+(defun notmuch-select-tag-with-completion (prompt rest search-terms)
+  (let ((tag-list (notmuch-tag-completions search-terms)))
+(completing-read prompt tag-list nil nil nil 'notmuch-select-tag-history)))
+
+(defun notmuch-read-tag-changes (optional initial-input rest search-terms)
+  (let* ((all-tag-list (notmuch-tag-completions))
+

Re: [PATCH 5/8] emacs: modify search tag functions to use new notmuch-tag interface

2012-04-14 Thread Jameson Graef Rollins
On Mon, Apr 09 2012, Mark Walters markwalters1...@gmail.com wrote:
 My only comment here is that I wonder about the tag-all command. I can
 see that this is a performance win over applying tag region to the whole
 buffer but is it another place where we have a race with incoming mail
 (ie we tag everything that now matches rather than everything in the
 buffer).

Yes, I think this is a problem.  notmuch-{search,show}-tag-all are both
subject to race conditions.  I suggest we remove notmuch-search-tag-all
in favor of the region tagging capabilities of notmuch-show-tag.  I will
submit a patch for that.  notmuch-show-tag-all is trickier, since there
no tag-by-region capability at the moment.  That will have to be added
before this function can be replaced.

 A second advantage with the tag-region form is that it automatically
 does excludes. Currently notmuch-tag does not do excludes as it looked
 very hairy to implement correctly: thus the tag-all command could spend
 a lot of time tagging excluded messages.

Actually, I don't think this is true, at least for search mode.  In
search mode threads are tagged by their thread id, therefore any
excluded messages in the thread will receive the same tagging
operations.

The current operation is at least, in my opinion, self consistent.  If
we're going to tag by thread then all messages in the thread should be
tagged, whether or not they're excluded.  I do think, however, that it
might be nice to add a tagging function that only tags the matching
messages in the thread.  In that case excluded messages would not be
tagged.  That's for future work, though.

jamie.


pgpBZ4h7Ihjm1.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [WIP 0/2] Thread based searching

2012-04-14 Thread Jameson Graef Rollins
On Tue, Mar 20 2012, Mark Walters markwalters1...@gmail.com wrote:
 It implements a very crude form of thread based search: the user can
 ask for all the threads that have a message matching the primary query
 and have a (possibly different) message matching a secondary query.

 For example notmuch search --secondary-search from:A :AND: from:B
 returns all threads that have a message from A and a message from B.

Hey, Mark.  I think this is a useful idea, but I think the
implementation is more complicated than it needs to be.  I would rather
just have a switch that allows me to search by thread, instead of by
message.  Something like just --by-thread would work for me.

I guess it might be nice to have such fined grain control to specify
independent search terms for both messages and threads simultaneously,
but I really don't think I would ever use such capabilities, and the
additional syntax is a little confusing.  But I certainly would use the
ability to search entire threads instead of just messages.

jamie.


pgpUfYLVP6OBe.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 0/3] emacs: allow show to colour based on tags and flags

2012-04-14 Thread Mark Walters
These three patches allow emacs to colour the headerline in show mode
according to the messages tags and flags (ie match or excluded).

The first two are David Edmondson's patch
id:1325006003-27152-1-git-send-email-...@dme.org rebased to master
and split into one which is trivial code movement and one which adds
the show colouring functionality.

The first two give a very similar result to notmuch-search-line-faces
and just allow colouring based on tags (not flags). The final one adds
the colouring by flag: it does this by passing to the line colouring
code a list of tags prefixed by tag: and flags prefixed by flag:

The final patch could be folded into the second, and this would somewhat reduce 
the diff. 

Mark Walters (3):
  emacs: Move colour line from search to lib
  emacs: Add `notmuch-show-line-faces' and apply it.
  emacs: allow notmuch-show-line-faces to use flags for colouring

 emacs/notmuch-lib.el  |   18 ++
 emacs/notmuch-show.el |   44 
 emacs/notmuch.el  |   15 +--
 3 files changed, 59 insertions(+), 18 deletions(-)

-- 
1.7.9.1

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


[PATCH 2/3] emacs: Add `notmuch-show-line-faces' and apply it.

2012-04-14 Thread Mark Walters
Similar to `notmuch-search-line-faces', `notmuch-show-line-faces'
allows the header line in `notmuch-show-mode' buffers to be coloured
according to the tags of the message. This is just a rebased version of
the  emacs/notmuch-show.el of David Edmondson's patch
id:1325006003-27152-1-git-send-email-...@dme.org
---
 emacs/notmuch-show.el |   33 +
 1 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 30b26d1..3dbb25f 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -94,6 +94,24 @@ any given message.
   :group 'notmuch-show
   :group 'notmuch-hooks)
 
+(defcustom notmuch-show-line-faces nil
+  Tag to face mapping for header line highlighting in `notmuch-show-mode'.
+
+Here is an example of how to color search results based on tags.
+ (the following text would be placed in your ~/.emacs file):
+
+ (setq notmuch-search-line-faces '((\delete\ . (:foreground \red\
+ :background \blue\))
+   (\unread\ . (:foreground \green\
+
+The attributes defined for matching tags are merged, with later
+attributes overriding earlier. A message having both \delete\
+and \unread\ tags with the above settings would have a green
+foreground and blue background.
+  :type '(alist :key-type (string) :value-type (custom-face-edit))
+  :group 'notmuch-show
+  :group 'notmuch-faces)
+
 ;; Mostly useful for debugging.
 (defcustom notmuch-show-all-multipart/alternative-parts t
   Should all parts of multipart/alternative parts be shown?
@@ -412,7 +430,8 @@ unchanged ADDRESS if parsing fails.
 (defun notmuch-show-insert-headerline (headers date tags depth)
   Insert a notmuch style headerline based on HEADERS for a
 message at DEPTH in the current thread.
-  (let ((start (point)))
+  (let ((start (point))
+   overlay)
 (insert (notmuch-show-spaces-n (* notmuch-show-indent-messages-width 
depth))
(notmuch-show-clean-address (plist-get headers :From))
 (
@@ -421,7 +440,9 @@ message at DEPTH in the current thread.
(propertize (mapconcat 'identity tags  )
'face 'notmuch-tag-face)
)\n)
-(overlay-put (make-overlay start (point)) 'face 
'notmuch-message-summary-face)))
+(setq overlay (make-overlay start (point)))
+(overlay-put overlay 'face 'notmuch-message-summary-face)
+(overlay-put overlay 'priority 2)))
 
 (defun notmuch-show-insert-header (header header-value)
   Insert a single header.
@@ -853,7 +874,8 @@ current buffer, if possible.
 body-start body-end
 (headers-invis-spec (notmuch-show-make-symbol header))
 (message-invis-spec (notmuch-show-make-symbol message))
-(bare-subject (notmuch-show-strip-re (plist-get headers :Subject
+(bare-subject (notmuch-show-strip-re (plist-get headers :Subject)))
+(tags (plist-get msg :tags)))
 
 ;; Set `buffer-invisibility-spec' to `nil' (a list), otherwise
 ;; removing items from `buffer-invisibility-spec' (which is what
@@ -878,10 +900,13 @@ current buffer, if possible.
(plist-get msg :date_relative)
  nil)
(plist-get headers :Date))
-   (plist-get msg :tags) depth)
+   tags depth)
 
 (setq content-start (point-marker))
 
+;; Colour the header line according to the tags of the message.
+(notmuch-color-line message-start content-start tags 
notmuch-show-line-faces)
+
 (plist-put msg :headers-invis-spec headers-invis-spec)
 (plist-put msg :message-invis-spec message-invis-spec)
 
-- 
1.7.9.1

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


[PATCH 3/3] emacs: allow notmuch-show-line-faces to use flags for colouring

2012-04-14 Thread Mark Walters
This allows header-lines `notmuch-show-mode' buffers to be coloured
based on the flags (match/excluded) of the message. It supplies the
line colouring function with a list of tags each prefixed with tag:
and a list of flags (match or excluded) each prefixed with
flag:.

The match flag is obviously not equivalent to a tag; the excluded flag
looks equivalent but is subtly different: a message is not marked
excluded if that tag appeared in the query.
---
 emacs/notmuch-show.el |   21 -
 1 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 3dbb25f..66b8ec7 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -97,14 +97,16 @@ any given message.
 (defcustom notmuch-show-line-faces nil
   Tag to face mapping for header line highlighting in `notmuch-show-mode'.
 
-Here is an example of how to color search results based on tags.
+Here is an example of how to color search results based on tags
+and flags (match and excluded).
  (the following text would be placed in your ~/.emacs file):
 
- (setq notmuch-search-line-faces '((\delete\ . (:foreground \red\
+ (setq notmuch-search-line-faces '((\tag:delete\ . (:foreground \red\
  :background \blue\))
-   (\unread\ . (:foreground \green\
+   (\tag:unread\ . (:foreground \green\))
+   (\flag:excluded\ . (:background 
\grey\
 
-The attributes defined for matching tags are merged, with later
+The attributes defined for matching tags/flags are merged, with later
 attributes overriding earlier. A message having both \delete\
 and \unread\ tags with the above settings would have a green
 foreground and blue background.
@@ -872,11 +874,20 @@ current buffer, if possible.
 content-start content-end
 headers-start headers-end
 body-start body-end
+tags-and-flags
 (headers-invis-spec (notmuch-show-make-symbol header))
 (message-invis-spec (notmuch-show-make-symbol message))
 (bare-subject (notmuch-show-strip-re (plist-get headers :Subject)))
 (tags (plist-get msg :tags)))
 
+(mapc (lambda (tag)
+   (setq tags-and-flags (cons (concat tag: tag) tags-and-flags)))
+ tags)
+(if (plist-get msg :match)
+   (setq tags-and-flags (cons flag:match tags-and-flags)))
+(if (plist-get msg :excluded)
+   (setq tags-and-flags (cons flag:excluded tags-and-flags)))
+
 ;; Set `buffer-invisibility-spec' to `nil' (a list), otherwise
 ;; removing items from `buffer-invisibility-spec' (which is what
 ;; `notmuch-show-headers-visible' and
@@ -905,7 +916,7 @@ current buffer, if possible.
 (setq content-start (point-marker))
 
 ;; Colour the header line according to the tags of the message.
-(notmuch-color-line message-start content-start tags 
notmuch-show-line-faces)
+(notmuch-color-line message-start content-start tags-and-flags 
notmuch-show-line-faces)
 
 (plist-put msg :headers-invis-spec headers-invis-spec)
 (plist-put msg :message-invis-spec message-invis-spec)
-- 
1.7.9.1

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


Re: [PATCH v4 0/6] Config-related patches

2012-04-14 Thread Jameson Graef Rollins
On Fri, Apr 13 2012, Peter Wang noval...@gmail.com wrote:
 Changes from v3:
 - rephrase part of the 'list' implementation as a separate patch
 - test 'set' on an extant key
 - test removing keys

LGTM, tested, and +1.

jamie.


pgpizPhunDGgy.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v4 0/6] Config-related patches

2012-04-14 Thread Jameson Graef Rollins
On Sat, Apr 14 2012, Mark Walters markwalters1...@gmail.com wrote:
 Two minor comments which you might like to consider (but definitely are
 not required):
 1) You could check that there are no further arguments when the user
 calls `notmuch config list'

This doesn't seem so necessary to me.  I'm fine if it just silently
ignores extra arguments.

 2) In the man page you could explicitly say what the output is for a
 configuration item which has not been set.

I'm also fine with it as it is.  I think it's implied that if the value
is null then the field is left blank.  That's ok.

jamie.


pgpRNe7bql3Xv.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v3 1/4] emacs: Let the user choose where to compose new mails

2012-04-14 Thread Jameson Graef Rollins
On Tue, Dec 13 2011, Thomas Jost schno...@schnouki.net wrote:
 Reusing the current window to compose a new mail may be troublesome for the
 user. This patch introduces a new customizable variable, 
 notmuch-mua-compose-in,
 which lets the user choose where to create the mail buffer: in the current
 window (current and default behaviour), in a new window, or in a new frame.

Hi.  I have been using this patch for many months now with no problems.
I really depend on it's functionality now, so I would really like to see
it pushed so that I don't have to keep maintaining it on my own personal
branch.

I think the issues that David was experiencing have to do with flakiness
in emacs's dedicated windows, not in this patch itself.

jamie.


pgpZbLjwUzx7D.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 0/6] Finish show rewrite

2012-04-14 Thread Jameson Graef Rollins
On Sat, Apr 07 2012, Austin Clements amdra...@mit.edu wrote:
 The long-awaited and oft-belated conclusion of the show rewrite.  All
 of the formatters have been converted to the new style, so this series
 just rips out unused code and does a little cleanup.

LGTM, tested, and +1.

This has been a truly epic endeavor, Austin, and the result is
phenomenal.  The show code is much cleaner, more efficient, and better
functioning.  Thank you so much for working through it all and pushing
it through to the end.  Kudos.

jamie.


pgpEyv3Io2aJl.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 2/2] emacs: new mua mailto: URI handler

2012-04-14 Thread Jameson Graef Rollins
On Sun, Jan 29 2012, Jameson Graef Rollins jroll...@finestructure.net wrote:
 The new function 'notmuch-mua-mailto' provides an interactive handler
 for rfc6068 mailto:; URIs.  It attempts to implement the rfc6068
 specification: http://tools.ietf.org/html/rfc6068

I am using and finding this patch useful.  It has no conflict with
anything when not used.  Is there any other objection with pushing it?

jamie.


pgp1lWhlMub3I.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH] emacs: Let the user choose where to compose new mails

2012-04-14 Thread Jameson Graef Rollins
From: Thomas Jost schno...@schnouki.net

Introduce a new defcustom notmuch-mua-compose-in that allows users to
specify where new mails are composed., either in the current window or
in a new window or frame.

Signed-off-by: Jameson Rollins jroll...@finestructure.net
---
This is a rebase of this original patch against the current master,
with an expanded commit message.

 emacs/notmuch-mua.el |   42 +++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 87bd88d..a96ac3d 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -36,6 +36,21 @@
   :group 'notmuch-send
   :group 'notmuch-hooks)
 
+(defcustom notmuch-mua-compose-in 'current-window
+  Where to create the mail buffer used to compose a new message.
+  Possible values are `current-window' (default), `new-window'
+  and `new-frame'. If set to `current-window', the mail buffer
+  will be displayed in the current window, so the old buffer will
+  be restored when the mail buffer is killed. If set to
+  `new-window' or `new-frame', the mail buffer will be displayed
+  in a new window/frame that will be destroyed when the buffer is
+  killed. You may want to customize `message-kill-buffer-on-exit'
+  accordingly.
+  :group 'notmuch
+  :type '(choice (const :tag Compose in the current window current-window)
+(const :tag Compose mail in a new window  new-window)
+(const :tag Compose mail in a new frame   new-frame)))
+
 (defcustom notmuch-mua-user-agent-function 'notmuch-mua-user-agent-full
   Function used to generate a `User-Agent:' string. If this is
 `nil' then no `User-Agent:' will be generated.
@@ -55,6 +70,23 @@ list.
 
 ;;
 
+(defun notmuch-mua-get-switch-function ()
+  Get a switch function according to `notmuch-mua-compose-in'.
+  (cond ((eq notmuch-mua-compose-in 'current-window)
+'switch-to-buffer)
+   ((eq notmuch-mua-compose-in 'new-window)
+'switch-to-buffer-other-window)
+   ((eq notmuch-mua-compose-in 'new-frame)
+'switch-to-buffer-other-frame)
+   (t (error Invalid value for `notmuch-mua-compose-in'
+
+(defun notmuch-mua-maybe-set-window-dedicated ()
+  Set the selected window as dedicated according to
+`notmuch-mua-compose-in'.
+  (when (or (eq notmuch-mua-compose-in 'new-frame)
+   (eq notmuch-mua-compose-in 'new-window))
+(set-window-dedicated-p (selected-window) t)))
+
 (defun notmuch-mua-user-agent-full ()
   Generate a `User-Agent:' string suitable for notmuch.
   (concat (notmuch-mua-user-agent-notmuch)
@@ -148,7 +180,8 @@ list.
 collect pair)))
  (notmuch-mua-mail (plist-get reply-headers :To)
(plist-get reply-headers :Subject)
-   (notmuch-headers-plist-to-alist reply-headers
+   (notmuch-headers-plist-to-alist reply-headers)
+   nil (notmuch-mua-get-switch-function
 
   ;; Insert the message body - but put it in front of the signature
   ;; if one is present
@@ -186,6 +219,7 @@ list.
   (set-buffer-modified-p nil))
 
 (defun notmuch-mua-forward-message ()
+  (funcall (notmuch-mua-get-switch-function) (current-buffer))
   (message-forward)
 
   (when notmuch-mua-user-agent-function
@@ -195,6 +229,7 @@ list.
   (message-sort-headers)
   (message-hide-headers)
   (set-buffer-modified-p nil)
+  (notmuch-mua-maybe-set-window-dedicated)
 
   (message-goto-to))
 
@@ -217,6 +252,7 @@ OTHER-ARGS are passed through to `message-mail'.
   (message-sort-headers)
   (message-hide-headers)
   (set-buffer-modified-p nil)
+  (notmuch-mua-maybe-set-window-dedicated)
 
   (message-goto-to))
 
@@ -272,8 +308,8 @@ the From: address first.
   (interactive P)
   (let ((other-headers
 (when (or prompt-for-sender notmuch-always-prompt-for-sender)
-  (list (cons 'From (notmuch-mua-prompt-for-sender))
-(notmuch-mua-mail nil nil other-headers)))
+  (list (cons From (notmuch-mua-prompt-for-sender))
+(notmuch-mua-mail nil nil other-headers nil 
(notmuch-mua-get-switch-function
 
 (defun notmuch-mua-new-forward-message (optional prompt-for-sender)
   Invoke the notmuch message forwarding window.
-- 
1.7.9.5

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


Re: [PATCH 2/2] emacs: new mua mailto: URI handler

2012-04-14 Thread Jani Nikula
Jameson Graef Rollins jroll...@finestructure.net writes:

 On Sun, Jan 29 2012, Jameson Graef Rollins jroll...@finestructure.net wrote:
 The new function 'notmuch-mua-mailto' provides an interactive handler
 for rfc6068 mailto:; URIs.  It attempts to implement the rfc6068
 specification: http://tools.ietf.org/html/rfc6068

 I am using and finding this patch useful.  It has no conflict with
 anything when not used.  Is there any other objection with pushing it?

I'm going through the review queue right now, tagging notmuch::stale any
patches that don't apply on master. I was just about to nmbug push stale
on this one (2/2). Is that in error? Care to verify?

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


Re: [PATCH v2 0/6] batch tagging support: notmuch tag --stdin

2012-04-14 Thread Jameson Graef Rollins
On Sat, Apr 14 2012, Jani Nikula j...@nikula.org wrote:
 This series adds support for batch tagging through stdin to notmuch
 tag. This should be useful and efficient for e.g. initial tagging
 scripts. Also, this adds locking around a batch of tag changes, which is
 also useful for initial tagging scripts. See the test patch for an
 example using a here document.

My issues from v1 still stand.  I would rather see some unification with
the existing tag file format, rather than introduce a second format,
with it's increased maintenance burden and confusion to users.  Either
that or a more general batch command interface.

jamie.


pgppGvkda9oMI.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 2/5] emacs: allow notmuch-tag to accept string inputs and prompt for tags

2012-04-14 Thread Mark Walters
On Sat, 14 Apr 2012, Jameson Graef Rollins jroll...@finestructure.net wrote:
 notmuch-tag is extended to accept various formats of the tag changes.
 In particular, user prompting for tag changes is now incorporated
 here, so it is common for modes.

 The tag binary and the notmuch-{before,after}-tag-hooks are only
 called if tag changes is non-nil.

 The actual tag-changes applied are returned by the function.
 ---
  emacs/notmuch-tag.el |   20 +++-
  1 file changed, 15 insertions(+), 5 deletions(-)

 diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
 index c25cff8..dd7f9d7 100644
 --- a/emacs/notmuch-tag.el
 +++ b/emacs/notmuch-tag.el
 @@ -108,18 +108,26 @@ from TAGS if present.
  (error Changed tag must be of the form `+this_tag' or 
 `-that_tag')
  (sort result-tags 'string)))
  
 -(defun notmuch-tag (query rest tag-changes)
 +(defun notmuch-tag (query optional tag-changes)
Add/remove tags in TAG-CHANGES to messages matching QUERY.
  
 -TAG-CHANGES should be a list of strings of the form \+tag\ or
 -\-tag\ and QUERY should be a string containing the
 -search-query.
 +QUERY should be a string containing the search-terms.
 +TAG-CHANGES can take multiple forms.  If TAG-CHANGES is a list of
 +strings of the form \+tag\ or \-tag\ then those are the tag
 +changes applied.  If TAG-CHANGES is a string then it is
 +interpreted as a single tag change.  If TAG-CHANGES is the string
 +\-\ or \+\, or null, then the user is prompted to enter the
 +tag changes.
  
  Note: Other code should always use this function alter tags of
  messages instead of running (notmuch-call-notmuch-process \tag\ ..)
  directly, so that hooks specified in notmuch-before-tag-hook and
  notmuch-after-tag-hook will be run.
;; Perform some validation
 +  (if (string-or-null-p tag-changes)
 +  (if (or (string= tag-changes -) (string= tag-changes +) (null 
 tag-changes))
 +   (setq tag-changes (notmuch-read-tag-changes tag-changes query))
 + (setq tag-changes (list tag-changes
(mapc (lambda (tag-change)
 (unless (string-match-p ^[-+]\\S-+$ tag-change)
   (error Tag must be of the form `+this_tag' or `-that_tag')))
 @@ -128,7 +136,9 @@ notmuch-after-tag-hook will be run.
  (run-hooks 'notmuch-before-tag-hook)
  (apply 'notmuch-call-notmuch-process tag
  (append tag-changes (list -- query)))
 -(run-hooks 'notmuch-after-tag-hook)))
 +(run-hooks 'notmuch-after-tag-hook))

Hi

The series looks good to me with one minor point:

 +  ;; return the list of actual changed tags
 +  tag-changes)

I found the comment confusing: I read it as the function looked at the
tags the message had before and after and returned the
difference. Perhaps something like in all cases we return tag-changes
as a list (and a similar comment for the commit message).

Best wishes

Mark

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


Re: [PATCH 2/2] emacs: new mua mailto: URI handler

2012-04-14 Thread Jameson Graef Rollins
On Sat, Apr 14 2012, Jani Nikula j...@nikula.org wrote:
 I'm going through the review queue right now, tagging notmuch::stale any
 patches that don't apply on master. I was just about to nmbug push stale
 on this one (2/2). Is that in error? Care to verify?

Yes, it is an error.  This patch applies to master.  Did you in fact
verify that it doesn't?  You should not be tagging patches stale if they
in fact still apply to master.  If they still need review or something
else that's a different matter.  Please don't mark things as stale if
they are not.

Obviously I still care about this patch, or I wouldn't have re-commented
on it.

jamie.


pgpN7lrQF3qgU.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v5] emacs: Let the user choose where to compose new mails

2012-04-14 Thread Jameson Graef Rollins
From: Thomas Jost schno...@schnouki.net

Introduce a new defcustom notmuch-mua-compose-in that allows users to
specify where new mails are composed, either in the current window or
in a new window or frame.

Signed-off-by: Jameson Rollins jroll...@finestructure.net
---
There was a small bug in the previous rebased version of this patch
that this new version fixes.  Sorry about the noise.

I also updated the subject line to indicate that this is in fact the
fifth version of this patch.

 emacs/notmuch-mua.el |   40 ++--
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 87bd88d..1fb59de 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -36,6 +36,21 @@
   :group 'notmuch-send
   :group 'notmuch-hooks)
 
+(defcustom notmuch-mua-compose-in 'current-window
+  Where to create the mail buffer used to compose a new message.
+  Possible values are `current-window' (default), `new-window'
+  and `new-frame'. If set to `current-window', the mail buffer
+  will be displayed in the current window, so the old buffer will
+  be restored when the mail buffer is killed. If set to
+  `new-window' or `new-frame', the mail buffer will be displayed
+  in a new window/frame that will be destroyed when the buffer is
+  killed. You may want to customize `message-kill-buffer-on-exit'
+  accordingly.
+  :group 'notmuch
+  :type '(choice (const :tag Compose in the current window current-window)
+(const :tag Compose mail in a new window  new-window)
+(const :tag Compose mail in a new frame   new-frame)))
+
 (defcustom notmuch-mua-user-agent-function 'notmuch-mua-user-agent-full
   Function used to generate a `User-Agent:' string. If this is
 `nil' then no `User-Agent:' will be generated.
@@ -55,6 +70,23 @@ list.
 
 ;;
 
+(defun notmuch-mua-get-switch-function ()
+  Get a switch function according to `notmuch-mua-compose-in'.
+  (cond ((eq notmuch-mua-compose-in 'current-window)
+'switch-to-buffer)
+   ((eq notmuch-mua-compose-in 'new-window)
+'switch-to-buffer-other-window)
+   ((eq notmuch-mua-compose-in 'new-frame)
+'switch-to-buffer-other-frame)
+   (t (error Invalid value for `notmuch-mua-compose-in'
+
+(defun notmuch-mua-maybe-set-window-dedicated ()
+  Set the selected window as dedicated according to
+`notmuch-mua-compose-in'.
+  (when (or (eq notmuch-mua-compose-in 'new-frame)
+   (eq notmuch-mua-compose-in 'new-window))
+(set-window-dedicated-p (selected-window) t)))
+
 (defun notmuch-mua-user-agent-full ()
   Generate a `User-Agent:' string suitable for notmuch.
   (concat (notmuch-mua-user-agent-notmuch)
@@ -148,7 +180,8 @@ list.
 collect pair)))
  (notmuch-mua-mail (plist-get reply-headers :To)
(plist-get reply-headers :Subject)
-   (notmuch-headers-plist-to-alist reply-headers
+   (notmuch-headers-plist-to-alist reply-headers)
+   nil (notmuch-mua-get-switch-function
 
   ;; Insert the message body - but put it in front of the signature
   ;; if one is present
@@ -186,6 +219,7 @@ list.
   (set-buffer-modified-p nil))
 
 (defun notmuch-mua-forward-message ()
+  (funcall (notmuch-mua-get-switch-function) (current-buffer))
   (message-forward)
 
   (when notmuch-mua-user-agent-function
@@ -195,6 +229,7 @@ list.
   (message-sort-headers)
   (message-hide-headers)
   (set-buffer-modified-p nil)
+  (notmuch-mua-maybe-set-window-dedicated)
 
   (message-goto-to))
 
@@ -217,6 +252,7 @@ OTHER-ARGS are passed through to `message-mail'.
   (message-sort-headers)
   (message-hide-headers)
   (set-buffer-modified-p nil)
+  (notmuch-mua-maybe-set-window-dedicated)
 
   (message-goto-to))
 
@@ -273,7 +309,7 @@ the From: address first.
   (let ((other-headers
 (when (or prompt-for-sender notmuch-always-prompt-for-sender)
   (list (cons 'From (notmuch-mua-prompt-for-sender))
-(notmuch-mua-mail nil nil other-headers)))
+(notmuch-mua-mail nil nil other-headers nil 
(notmuch-mua-get-switch-function
 
 (defun notmuch-mua-new-forward-message (optional prompt-for-sender)
   Invoke the notmuch message forwarding window.
-- 
1.7.9.5

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


[PATCH v2 2/5] emacs: allow notmuch-tag to accept string inputs and prompt for tags

2012-04-14 Thread Jameson Graef Rollins
notmuch-tag is extended to accept various formats of the tag changes.
In particular, user prompting for tag changes is now incorporated
here, so it is common for modes.

The tag binary and the notmuch-{before,after}-tag-hooks are only
called if tag changes is non-nil.

In all cases tag-changes is returned as a list.
---
This addresses Mark Walters concerns in regards to a code comment.

 emacs/notmuch-tag.el |   20 +++-
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/emacs/notmuch-tag.el b/emacs/notmuch-tag.el
index c25cff8..0c0fc87 100644
--- a/emacs/notmuch-tag.el
+++ b/emacs/notmuch-tag.el
@@ -108,18 +108,26 @@ from TAGS if present.
   (error Changed tag must be of the form `+this_tag' or 
`-that_tag')
 (sort result-tags 'string)))
 
-(defun notmuch-tag (query rest tag-changes)
+(defun notmuch-tag (query optional tag-changes)
   Add/remove tags in TAG-CHANGES to messages matching QUERY.
 
-TAG-CHANGES should be a list of strings of the form \+tag\ or
-\-tag\ and QUERY should be a string containing the
-search-query.
+QUERY should be a string containing the search-terms.
+TAG-CHANGES can take multiple forms.  If TAG-CHANGES is a list of
+strings of the form \+tag\ or \-tag\ then those are the tag
+changes applied.  If TAG-CHANGES is a string then it is
+interpreted as a single tag change.  If TAG-CHANGES is the string
+\-\ or \+\, or null, then the user is prompted to enter the
+tag changes.
 
 Note: Other code should always use this function alter tags of
 messages instead of running (notmuch-call-notmuch-process \tag\ ..)
 directly, so that hooks specified in notmuch-before-tag-hook and
 notmuch-after-tag-hook will be run.
   ;; Perform some validation
+  (if (string-or-null-p tag-changes)
+  (if (or (string= tag-changes -) (string= tag-changes +) (null 
tag-changes))
+ (setq tag-changes (notmuch-read-tag-changes tag-changes query))
+   (setq tag-changes (list tag-changes
   (mapc (lambda (tag-change)
  (unless (string-match-p ^[-+]\\S-+$ tag-change)
(error Tag must be of the form `+this_tag' or `-that_tag')))
@@ -128,7 +136,9 @@ notmuch-after-tag-hook will be run.
 (run-hooks 'notmuch-before-tag-hook)
 (apply 'notmuch-call-notmuch-process tag
   (append tag-changes (list -- query)))
-(run-hooks 'notmuch-after-tag-hook)))
+(run-hooks 'notmuch-after-tag-hook))
+  ;; in all cases we return tag-changes as a list
+  tag-changes)
 
 ;;
 
-- 
1.7.9.5

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


Re: [PATCH 0/2] Allow JSON to use non-entire thread, and use for elide

2012-04-14 Thread Jameson Graef Rollins
On Tue, Apr 10 2012, Mark Walters markwalters1...@gmail.com wrote:
 The first patch allows --entire-thread=false for notmuch-show.c when
 the output format is JSON. In the previous version [2] Austin
 suggested that we should output an empty message (i.e., {}) for
 non-matching messages rather than just omitting them. This version
 does that.

Can this be applied to notmuch-reply as well, so that we can regain the
ability to reply to threads?

jamie.


pgp8v1sqywcdJ.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 0/2] Allow JSON to use non-entire thread, and use for elide

2012-04-14 Thread Jameson Graef Rollins
On Sat, Apr 14 2012, Jameson Graef Rollins jroll...@finestructure.net wrote:
 Can this be applied to notmuch-reply as well, so that we can regain the
 ability to reply to threads?

Sorry, nevermind.  I was misinterpreting the point of this patch.

jamie.


pgptgB89TQ0DJ.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v2 0/6] batch tagging support: notmuch tag --stdin

2012-04-14 Thread Jani Nikula
Jameson Graef Rollins jroll...@finestructure.net writes:

 On Sat, Apr 14 2012, Jani Nikula j...@nikula.org wrote:
 This series adds support for batch tagging through stdin to notmuch
 tag. This should be useful and efficient for e.g. initial tagging
 scripts. Also, this adds locking around a batch of tag changes, which is
 also useful for initial tagging scripts. See the test patch for an
 example using a here document.

 My issues from v1 still stand.  I would rather see some unification with
 the existing tag file format, rather than introduce a second format,
 with it's increased maintenance burden and confusion to users.  Either
 that or a more general batch command interface.

The existing dump/restore file format is a dead end. It fails
magnificently with tags and message-ids that have spaces or some other
special characters in them. It doesn't support removal of tags. There's
zero room for extensibility. I can't imagine how that could be used for
notmuch tag.

David originally wrote the dump/restore patches
id:1324214111-32079-1-git-send-email-da...@tethera.net to add a
notmuch format (yes, a second format) in addition to the sup format
we currently have, to fix the issues with special characters. That too
lacked features to support batch tagging in notmuch new. The format
proposed here would fix the issues and work with notmuch tag, and it
would be obvious to use for anyone who has used notmuch tag.

I see a general batch command interface overkill. Too many problems to
solve for little gain (see the previous thread for details). What other
notmuch commands than tag would really benefit from it? If you want to
do search or show or whatever, the general batch command interface to
use is /bin/sh.

For notmuch tag, particularly in connection with notmuch new, there's a
clear benefit in having a batch mode: if you have new in new.tags, and
do initial tagging on the new tagged messages (e.g. in post-new hook),
you don't want anyone messing with the database while you're processing
the messages tagged new. The batch tagging of this series keeps the db
locked for the duration of such initial tagging.

I'm totally fine with modifying the proposed format (e.g. change T to
tag, make things compatible with a future general batch mode), but to
be absolutely clear: I will not implement a general batch command
mode. If that is deemed to be what is wanted, that's okay too. I can
share my WIP patches for dump/restore, and focus on something else.


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


Re: using bbdb with autocompletion

2012-04-14 Thread Tomi Ollila
On Thu, Apr 12 2012, David Belohrad da...@belohrad.ch wrote:

 Dear All,
 before I was using gnus to read my emails. This was setup together with
 bbdb such, that every email address I got an email delivered got stored
 into the bbdb database. 

 The config was following:

 ---
 ;; IF USING GNUS TO FETCH MAIL:
 (if (locate-library bbdb)
 ;; bbdb to automatically create email address list
 (progn
   (require 'bbdb)
   (bbdb-initialize)
   (add-hook 'gnus-startup-hook 'bbdb-insinuate-gnus)
   (add-hook 'gnus-startup-hook 'bbdb-insinuate-message)
   (add-hook 'message-setup-hook 'bbdb-define-all-aliases)

   (setq bbdb/news-auto-create-p t)
   (setq bbdb-complete-name-allow-cycling t)
   (setq bbdb-complete-mail-allow-cycling t)
   (setq bbdb-complete-name-full-completion t)
   (setq bbdb-completion-type 'primary-or-name)
   (setq bbdb-use-pop-up nil)
   ;; set BBDB to AFS so we have the access from all computers to the same 
 bbdb database!
   (setq bbdb-file /afs/cern.ch/user/b/belohrad/private/bbdb)
   (setq bbdb-offer-save 1)
   (setq bbdb-electric-p t)
   (message bbdb initialized)
   )
   (message bbdb is missing: address lookup will not work))
 --

 The problem I have with this now is, that when using notmuch to read
 emails, the email addresses do not automatically add to bbdb. So when I
 write an email, I can only choose 'To:' email address, which is already
 in the bbdb from the times I was using gnus. But all new addresses are
 not added.

 How can I setup notmuch properly so with each email arrived it checks
 against email address and stores it in the bbdb as in case of gnus?

There is (too) brief notice about that in

http://notmuchmail.org/emacstips/#index13h2

There is just little bit more information in notmuch archives
about that -- I did not dig deeper though.

If you're interested you could figure that out and update the
wiki page.

I'm, using this: id:m2ehtm1w7p@guru.guru-group.fi :D

(currently my last mail on nottoomuch-addresses.sh)

 thanks for any help.

 -- 
 .david.

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


Re: [PATCH 2/2] emacs: new mua mailto: URI handler

2012-04-14 Thread Jani Nikula
Jameson Graef Rollins jroll...@finestructure.net writes:

 On Sat, Apr 14 2012, Jani Nikula j...@nikula.org wrote:
 I'm going through the review queue right now, tagging notmuch::stale any
 patches that don't apply on master. I was just about to nmbug push stale
 on this one (2/2). Is that in error? Care to verify?

 Yes, it is an error.  This patch applies to master.  Did you in fact
 verify that it doesn't?  You should not be tagging patches stale if they
 in fact still apply to master.  If they still need review or something
 else that's a different matter.  Please don't mark things as stale if
 they are not.

My nmfirehose script flagged the patch as not applying, and I verified
this (and all of them) by hand, using the emacs interface to save the
patch. No, I'm not intentionally tagging patches stale if they apply,
but I'll stop for now in case there's a bug somewhere (incl. PEBKAC)
breaking the patches and thus making them not apply.

 Obviously I still care about this patch, or I wouldn't have re-commented
 on it.

I was doing this purely based on whether the patches apply or not.


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


Re: [PATCH 2/2] emacs: new mua mailto: URI handler

2012-04-14 Thread Jameson Graef Rollins
On Sat, Apr 14 2012, Jani Nikula j...@nikula.org wrote:
 I was doing this purely based on whether the patches apply or not.

I'm so sorry, Jani.  You are correct that this patch requires a small
rebase fix to apply to master.  I'm not sure how I missed it previously.

Updated version on the way.

jamie.


pgpQxP1Ds7RsD.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v2 2/2] emacs: new mua mailto: URI handler

2012-04-14 Thread Jameson Graef Rollins
The new function 'notmuch-mua-mailto' provides an interactive handler
for rfc6068 mailto:; URIs.  It attempts to implement the rfc6068
specification: http://tools.ietf.org/html/rfc6068

More decoding of the mailto string needs to be done, as is evident by
the fact that the mailto test remains broken.
---
Rebased against current master.

 emacs/notmuch-mua.el |   62 ++
 1 file changed, 62 insertions(+)

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 87bd88d..59b4cf4 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -26,6 +26,10 @@
 (require 'notmuch-lib)
 (require 'notmuch-address)
 
+(require 'rfc2368)
+(require 'rfc2047)
+(require 'mailheader)
+
 (eval-when-compile (require 'cl))
 
 ;;
@@ -198,6 +202,64 @@ list.
 
   (message-goto-to))
 
+(defun notmuch-mua-mailto (mailto)
+  Invoke the notmuch mail composition window for a `mailto:' URI.
+  ;; this should implement implement rfc6068: 
http://tools.ietf.org/html/rfc6068
+  ;; which obsoleted: http://tools.ietf.org/html/rfc2368
+  ;; this function is based on previous work: 
http://www.emacswiki.org/emacs/MailtoHandler
+  (interactive)
+  (when (and (stringp mailto)
+(string-match \\`mailto:; mailto))
+(let* (
+  ;; FIXME: need to decode all html encodings in uri.
+  (mailto (replace-regexp-in-string amp;  mailto))
+  (hdr-alist (rfc2368-parse-mailto-url mailto))
+  to subject other-headers body
+  (allowed-xtra-hdrs '(cc bcc in-reply-to)))
+
+  (with-temp-buffer
+   ;; extract body if it's defined
+   (when (assoc Body hdr-alist)
+ (dolist (hdr hdr-alist)
+   (when (equal Body (car hdr))
+ (insert (format %s\n (cdr hdr)
+ (rfc2047-decode-region (point-min) (point-max))
+ (setq body (buffer-substring-no-properties
+ (point-min) (point-max)))
+ (erase-buffer))
+
+   ;; extract headers
+   (dolist (hdr hdr-alist)
+ (unless (equal Body (car hdr))
+   (insert (format %s: %s\n (car hdr) (cdr hdr)
+   (rfc2047-decode-region (point-min) (point-max))
+   (goto-char (point-min))
+   (setq hdr-alist (mail-header-extract-no-properties)))
+
+  (setq to (cdr (assoc 'to hdr-alist)))
+  (setq subject (cdr (assoc 'subject hdr-alist)))
+
+  ;; extract allowed other headers, taking only first defined
+  ;; value
+  (dolist (hdr hdr-alist)
+   (if (and (member (car hdr) allowed-xtra-hdrs)
+(not (assoc (car hdr) other-headers)))
+   (add-to-list 'other-headers hdr)))
+
+  (notmuch-mua-mail to subject other-headers)
+
+  ;; insert the message body - but put it in front of the signature
+  ;; if one is present
+  (goto-char (point-max))
+  (if (re-search-backward message-signature-separator nil t)
+ (forward-line -1)
+   (goto-char (point-max)))
+  (insert body)
+  (push-mark))
+(set-buffer-modified-p nil)
+
+(message-goto-body)))
+
 (defun notmuch-mua-mail (optional to subject other-headers rest other-args)
   Invoke the notmuch mail composition window.
 
-- 
1.7.9.5

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


some stale patches dropped from the review queue

2012-04-14 Thread Jani Nikula

I have tagged the following patches notmuch::stale, removing them from
the review queue [1], purely based on they not applying to master
anymore (see [2] for tag definitions). Please rebase your patches
against master and resubmit if you think they're still relevant. If you
think this is in error, please complain.

BR,
Jani.

[1] http://nmbug.tethera.net/status/
[2] http://notmuchmail.org/nmbug/


id:1310874973-28437-1-git-send-email-anar...@koumbit.org
id:1310874973-28437-2-git-send-email-anar...@koumbit.org

id:1316999137-28257-8-git-send-email-4win...@informatik.uni-hamburg.de

id:1319884807-7206-1-git-send-email-tho...@schwinge.name

id:1323766883-17607-1-git-send-email-tomi.oll...@iki.fi
id:1323766883-17607-2-git-send-email-tomi.oll...@iki.fi

id:1325006003-27152-1-git-send-email-...@dme.org

id:1325160490-23472-1-git-send-email-...@dme.org
id:1325160490-23472-2-git-send-email-...@dme.org

id:1325975294-646-2-git-send-email-jroll...@finestructure.net
id:1325975294-646-3-git-send-email-jroll...@finestructure.net
id:1325975294-646-4-git-send-email-jroll...@finestructure.net
id:1325975294-646-5-git-send-email-jroll...@finestructure.net

id:1327601789-6040-2-git-send-email-...@dme.org
id:1327601789-6040-3-git-send-email-...@dme.org

id:1326826969-23545-2-git-send-email-jroll...@finestructure.net
id:1326826969-23545-3-git-send-email-jroll...@finestructure.net

id:1328141050-30356-3-git-send-email-dmitry.kuroch...@gmail.com
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH 2/2] emacs: new mua mailto: URI handler

2012-04-14 Thread Jani Nikula
Jameson Graef Rollins jroll...@finestructure.net writes:

 On Sat, Apr 14 2012, Jani Nikula j...@nikula.org wrote:
 I was doing this purely based on whether the patches apply or not.

 I'm so sorry, Jani.  You are correct that this patch requires a small
 rebase fix to apply to master.  I'm not sure how I missed it previously.

No problem. Thanks for checking again; I was worried we might have a bug
somewhere. :)

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


[PATCH] emacs: do not modify subject in search or show

2012-04-14 Thread Jameson Graef Rollins
A previous patch [0] replaced blank subject lines with '[No Subject]'
in search and show mode.  Apparently this was needed to circumvent
some bug in the printing code, but there was no need for it search or
show, and it is definitely not desirable, so we undo it here (a revert
is no longer feasible).  We should not be modifying strings in the
original message without good reason, or without a clear indication
that we are doing so, neither of which apply in this case.  For
further discussion see [0].

[0] id:1327918561-16245-3-git-send-email-...@dme.org
---
 emacs/notmuch-print.el |4 ++--
 emacs/notmuch-show.el  |5 +
 emacs/notmuch.el   |5 ++---
 3 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/emacs/notmuch-print.el b/emacs/notmuch-print.el
index 6653d97..81b2ef0 100644
--- a/emacs/notmuch-print.el
+++ b/emacs/notmuch-print.el
@@ -60,7 +60,7 @@ Optional OUTPUT allows passing a list of flags to muttprint.
 
 (defun notmuch-print-ps-print (msg)
   Print a message buffer using the ps-print package.
-  (let ((subject (notmuch-prettify-subject
+  (let ((subject (notmuch-print-prettify-subject
  (plist-get (notmuch-show-get-prop :headers msg) :Subject
 (rename-buffer subject t)
 (ps-print-buffer)))
@@ -68,7 +68,7 @@ Optional OUTPUT allows passing a list of flags to muttprint.
 (defun notmuch-print-ps-print/evince (msg)
   Preview a message buffer using ps-print and evince.
   (let ((ps-file (make-temp-file notmuch))
-   (subject (notmuch-prettify-subject
+   (subject (notmuch-print-prettify-subject
  (plist-get (notmuch-show-get-prop :headers msg) :Subject
 (rename-buffer subject t)
 (ps-print-buffer ps-file)
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 30b26d1..1e55099 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -1075,7 +1075,7 @@ function is used.
   (run-hooks 'notmuch-show-hook))
 
 ;; Set the header line to the subject of the first message.
-(setq header-line-format (notmuch-show-strip-re 
(notmuch-show-get-pretty-subject)
+(setq header-line-format (notmuch-show-strip-re 
(notmuch-show-get-subject)
 
 (defun notmuch-show-capture-state ()
   Capture the state of the current buffer.
@@ -1375,9 +1375,6 @@ current thread.
 (defun notmuch-show-get-depth ()
   (notmuch-show-get-prop :depth))
 
-(defun notmuch-show-get-pretty-subject ()
-  (notmuch-prettify-subject (notmuch-show-get-subject)))
-
 (defun notmuch-show-set-tags (tags)
   Set the tags of the current message.
   (notmuch-show-set-prop :tags tags)
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index ba833e6..326645d 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -507,7 +507,7 @@ Complete list of currently available key bindings:
   Display the currently selected thread.
   (interactive)
   (let ((thread-id (notmuch-search-find-thread-id))
-   (subject (notmuch-prettify-subject (notmuch-search-find-subject
+   (subject (notmuch-search-find-subject)))
 (if ( (length thread-id) 0)
(notmuch-show thread-id
  (current-buffer)
@@ -877,8 +877,7 @@ non-authors is found, assume that all of the authors match.
  ;; We currently just throw away excluded matches.
  (unless (eq (aref count 1) ?0)
(let ((beg (point)))
- (notmuch-search-show-result date count authors
- (notmuch-prettify-subject 
subject) tags)
+ (notmuch-search-show-result date count authors 
subject tags)
  (notmuch-search-color-line beg (point) tag-list)
  (put-text-property beg (point) 
'notmuch-search-thread-id thread-id)
  (put-text-property beg (point) 
'notmuch-search-authors authors)
-- 
1.7.9.5

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


[PATCH v2] emacs: do not modify subject in search or show

2012-04-14 Thread Jameson Graef Rollins
A previous patch [0] replaced blank subject lines with '[No Subject]'
in search and show mode.  Apparently this was needed to circumvent
some bug in the printing code, but there was no need for it search or
show, and it is definitely not desirable, so we undo it here (a revert
is no longer feasible).  We should not be modifying strings in the
original message without good reason, or without a clear indication
that we are doing so, neither of which apply in this case.  For
further discussion see [0].

[0] id:1327918561-16245-3-git-send-email-...@dme.org
---
Sorry, there was a small bug in the previous version (notmuch-print.el
was mistakenly modified).

 emacs/notmuch-show.el |5 +
 emacs/notmuch.el  |5 ++---
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 30b26d1..1e55099 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -1075,7 +1075,7 @@ function is used.
   (run-hooks 'notmuch-show-hook))
 
 ;; Set the header line to the subject of the first message.
-(setq header-line-format (notmuch-show-strip-re 
(notmuch-show-get-pretty-subject)
+(setq header-line-format (notmuch-show-strip-re 
(notmuch-show-get-subject)
 
 (defun notmuch-show-capture-state ()
   Capture the state of the current buffer.
@@ -1375,9 +1375,6 @@ current thread.
 (defun notmuch-show-get-depth ()
   (notmuch-show-get-prop :depth))
 
-(defun notmuch-show-get-pretty-subject ()
-  (notmuch-prettify-subject (notmuch-show-get-subject)))
-
 (defun notmuch-show-set-tags (tags)
   Set the tags of the current message.
   (notmuch-show-set-prop :tags tags)
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index ba833e6..326645d 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -507,7 +507,7 @@ Complete list of currently available key bindings:
   Display the currently selected thread.
   (interactive)
   (let ((thread-id (notmuch-search-find-thread-id))
-   (subject (notmuch-prettify-subject (notmuch-search-find-subject
+   (subject (notmuch-search-find-subject)))
 (if ( (length thread-id) 0)
(notmuch-show thread-id
  (current-buffer)
@@ -877,8 +877,7 @@ non-authors is found, assume that all of the authors match.
  ;; We currently just throw away excluded matches.
  (unless (eq (aref count 1) ?0)
(let ((beg (point)))
- (notmuch-search-show-result date count authors
- (notmuch-prettify-subject 
subject) tags)
+ (notmuch-search-show-result date count authors 
subject tags)
  (notmuch-search-color-line beg (point) tag-list)
  (put-text-property beg (point) 
'notmuch-search-thread-id thread-id)
  (put-text-property beg (point) 
'notmuch-search-authors authors)
-- 
1.7.9.5

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