[PATCH] emacs: functions to import sender or recipient into BBDB
>From a show buffer, bbdb/notmuch-snarf-from imports the sender into bbdb. bbdb/notmuch-snarf-to attempts to import all recipients. BBDB displays a buffer with each contact; C-g displays the next contact, or returns to the notmuch-show buffer. Both functions assume that email contacts are seperated by commas. If a comma is included in a name, it will try to make two separate contacts. --- This is my first notmuch patch. Comments very welcome. emacs/notmuch-show.el | 28 1 file changed, 28 insertions(+) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 6335d45..3bc1da0 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -1895,6 +1895,34 @@ the user (see `notmuch-show-stash-mlarchive-link-alist')." (button-get button :notmuch-filename) (button-get button :notmuch-content-type))) +;; bbdb interaction functions, awaiting user keybindings + +(defun bbdb/snarf-between-commas () + ; What about names written "Surname, First M" ? + (goto-char (point-min)) + (let ((comma (point))) +(while (search-forward "," nil "end") + (bbdb-snarf-region comma (point)) + (setq comma (point))) +(bbdb-snarf-region comma (point)) ; last entry + )) + +(defun bbdb/notmuch-snarf-header (header) + (let ((text (notmuch-show-get-header header))) +(with-temp-buffer + (insert text) + (bbdb/snarf-between-commas + +(defun bbdb/notmuch-snarf-from () + "Import the sender of the current message into BBDB" + (interactive) + (bbdb/notmuch-snarf-header :From)) + +(defun bbdb/notmuch-snarf-to () + "Import all recipients of the current message into BBDB" + (interactive) + (bbdb/notmuch-snarf-header :To)) + ;; (provide 'notmuch-show) -- 1.7.10.4
[PATCH] emacs: Add customization group for replying
When one wants to customize the format of reply message, there nothing to tell the user how to do it. Without knowing that construction of reply buffer is actually implemented in the message package, it seems that replying cannot be customized. Because I was getting annoyed by the empty line the between citation line and the quoted message, I figured out that changing this is fairly easy when one knows what to customize. This patch adds notmuch-reply customization group that that contains references to the relevant customization options. The new group is easy to find as it is shown as a result of running "M-x customize-group RET notmuch RET". --- emacs/notmuch-lib.el | 11 +++ 1 file changed, 11 insertions(+) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 30db58f..47d9e0c 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -45,6 +45,17 @@ "Showing messages and threads." :group 'notmuch) +(defgroup notmuch-reply + '((message-citation-line-function custom-variable) +(message-citation-line-format custom-variable) +(message-insertion custom-group)) + "Replying to messages. + +Replying in notmuch can be customized in `Message insertion' +group. However, the most important options from that group are +also included here." + :group 'notmuch) + (defgroup notmuch-send nil "Sending messages from Notmuch." :group 'notmuch) -- 1.7.10
[PATCH 01/18] cli: add stub for insert command
On Wed, 25 Jul 2012 10:11:14 -0700, Jameson Graef Rollins wrote: > > This is an interesting series, but let me play devil's advocate for a > moment: Why is this functionality needed? What can this functionality > do that notmuch new can't? My mail is stored on a remote server running notmuch. My email client runs locally, calling notmuch on the server via ssh. After sending a message, I immediately add that message to the Maildir/Sent folder and tag it `sent'. When postponing a message, I add the message to the Maildir/Drafts folder and tag it `draft' (excluded by default). notmuch new doesn't help me get the message into the Maildir in the first place. I would also need a second step to tag the messages. Right now notmuch-deliver serves my purposes, but I would prefer it to be part of notmuch. Peter
[PATCH 01/13] test: Uniformly canonicalize actual and expected JSON
On Wed, Jul 25 2012, Austin Clements wrote: > Previously, we used a variety of ad-hoc canonicalizations for JSON > output in the test suite, but were ultimately very sensitive to JSON > irrelevancies such as whitespace. This introduces a new test > comparison function, test_expect_equal_json, that first pretty-prints > *both* the actual and expected JSON and the compares the result. > > The current implementation of this simply uses Python's json.tool to > perform pretty-printing (with a fallback to the identity function if > parsing fails). However, since the interface it introduces is > semantically high-level, we could swap in other mechanisms in the > future, such as another pretty-printer or something that does not > re-order object keys (if we decide that we care about that). The whole series looks good to me and was easy to read through. The use of Python json.tool is pretty reasonable; It is shipped in Python 2.6+ (For example perl does not ship json components by default, making it more complicated to set up for this purpose). If that is too "much", then we could also use tr -d '[:space:]' as an intermediate solution (but that eats whitespace in quoted content too...) I'll be afk for a few days then I test this... Tomi
[PATCH 1/5] emacs: compile and load notmuch-pick.el if present.
On Thu, Jul 26 2012, Mark Walters wrote: > On Wed, 25 Jul 2012, Tomi Ollila wrote: >> On Wed, Jul 25 2012, Mark Walters wrote: >> >>> Compile and load notmuch-pick.el if present. >>> >>> All the actual setup of pick is done in the function notmuch-pick-init >>> so we call that in the notmuch init function if it is bound. This >>> function will setup all extra keybinding etc. >> >> Great stuff! See a few thoughts below... > > Thanks for these: I think they are all clear improvements. > >> >>> --- >>> emacs/Makefile.local |3 ++- >>> emacs/notmuch.el |5 + >>> 2 files changed, 7 insertions(+), 1 deletions(-) >>> >>> diff --git a/emacs/Makefile.local b/emacs/Makefile.local >>> index fb82247..9f4dba6 100644 >>> --- a/emacs/Makefile.local >>> +++ b/emacs/Makefile.local >>> @@ -15,7 +15,8 @@ emacs_sources := \ >>> $(dir)/notmuch-crypto.el \ >>> $(dir)/notmuch-tag.el \ >>> $(dir)/coolj.el \ >>> - $(dir)/notmuch-print.el >>> + $(dir)/notmuch-print.el \ >>> + $(wildcard $(dir)/notmuch-pick.el) >> >> I wonder whether having this conditional is good idea. What if >> someone copies (or (sym)links) notmuch-pick.el there and then >> compiles and takes to use. Next time he takes clean tree and >> forgets to do this copying and installs to the same destination. >> Now there is old notmuch-pick.elc which might be out of sync. >> >> I think it would be better to provide a shell script in >> notmuch-pick directory which byte-compiles and installs notmuch-pick >> in case user wants to install/update notmuch-pick. Whenever notmuch-pick >> is good enough to be shipped inside $(dir) above then the aboce conditional >> is not needed (at all). >> > > I have now done this: I actually use a Makefile so that I can pick up > the config from notmuch: in particular the install directory > for the notmuch-pick.elc file. Does that seem reasonable? I believe so.. I can say for sure when I see the code -- but anything that makes the brave user's live in the bleeding edge easier is good. > >>> emacs_images := \ >>> $(srcdir)/$(dir)/notmuch-logo.png >>> diff --git a/emacs/notmuch.el b/emacs/notmuch.el >>> index fd1836f..4f3da4f 100644 >>> --- a/emacs/notmuch.el >>> +++ b/emacs/notmuch.el >>> @@ -59,6 +59,9 @@ >>> (require 'notmuch-maildir-fcc) >>> (require 'notmuch-message) >>> >>> +;; Load notmuch-pick if available (but do not error if not present). >>> +(load "notmuch-pick" t) >>> + >>> (defcustom notmuch-search-result-format >>>`(("date" . "%12s ") >>> ("count" . "%-7s ") >>> @@ -1088,6 +1091,8 @@ current search results AND that are tagged with the >>> given tag." >>> (defun notmuch () >>>"Run notmuch and display saved searches, known tags, etc." >>>(interactive) >>> + (when (fboundp 'notmuch-pick-init) >>> +(notmuch-pick-init)) >>>(notmuch-hello)) >> >> Instead of this could notmuch-pick.el contain: >> >> In the beginning: >> >> (require 'notmuch-hello) >> (require 'notmuch-show) >> (require 'notmuch) ;; XXX ATM, as notmuch-search-mode-map is defined here >> >> And, at the end, before (provide 'notmuch-pick), execute the lines >> what currenty are contained in (notmuch-pick-init). >> >> Then, those who want to start using notmuch-pick at this time >> can (just) write the following in their .emacs: >> >> (require 'notmuch) >> (require 'notmuch-pick) > > This works very nicely. And if we want a transitional period the > notmuch-pick could be in (dir) but not loaded automatically. Yes. > > Many thanks for the excellent suggestions. Np. Thank you. > Mark Tomi
[PATCH 18/18] test: test insert --create-folder
Add tests for the new option. --- test/insert | 24 1 files changed, 24 insertions(+), 0 deletions(-) diff --git a/test/insert b/test/insert index 3514920..548da58 100755 --- a/test/insert +++ b/test/insert @@ -50,4 +50,28 @@ generate_message \ notmuch insert --folder=Drafts -- +draft -unread < "$gen_msg_filename" test_expect_equal "`notmuch count folder:Drafts tag:draft NOT tag:unread`" "1" +test_begin_subtest "Insert message, create folder" +generate_message \ +"[subject]=\"insert-subject-createfolder\"" \ +"[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" \ +"[body]=\"insert-message-createfolder\"" +notmuch insert --folder=F --create-folder -- +folder < "$gen_msg_filename" +test_expect_equal "`notmuch count folder:F tag:folder`" "1" + +test_begin_subtest "Insert message, create subfolder" +generate_message \ +"[subject]=\"insert-subject-createfolder\"" \ +"[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" \ +"[body]=\"insert-message-createfolder\"" +notmuch insert --folder=F/G/H/I/J --create-folder -- +folder < "$gen_msg_filename" +test_expect_equal "`notmuch count folder:F/G/H/I/J tag:folder`" "1" + +test_begin_subtest "Insert message, create existing subfolder" +generate_message \ +"[subject]=\"insert-subject-createfolder\"" \ +"[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" \ +"[body]=\"insert-message-createfolder\"" +notmuch insert --folder=F/G/H/I/J --create-folder -- +folder < "$gen_msg_filename" +test_expect_equal "`notmuch count folder:F/G/H/I/J tag:folder`" "2" + test_done -- 1.7.4.4
[PATCH 17/18] man: document insert --create-folder option
Document the new option. --- man/man1/notmuch-insert.1 |9 - 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/man/man1/notmuch-insert.1 b/man/man1/notmuch-insert.1 index 7d281b5..4bd8a35 100644 --- a/man/man1/notmuch-insert.1 +++ b/man/man1/notmuch-insert.1 @@ -36,10 +36,17 @@ include Deliver the message to the .RI Maildir/ folder -directory, which must already exist. +directory. The default is to deliver to the top-level directory. .RE + +.RS 4 +.TP 4 +.BI "--create-folder" + +Try to create the named folder if it does not exist. + .RE .SH SEE ALSO -- 1.7.4.4
[PATCH 16/18] insert: add --create-folder option
Support an option to create a new folder in the maildir. --- notmuch-insert.c | 71 ++ 1 files changed, 71 insertions(+), 0 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index a69dfe6..380c520 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -48,6 +48,70 @@ check_folder_name (const char *folder) } } +static int +mkdir_parents (void *ctx, const char *path, int mode) +{ +struct stat st; +char *pathcopy; +char *start; +char *end; +int ret; + +/* First check the common case: directory already exists. */ +if (stat (path, ) == 0) { + return (S_ISDIR (st.st_mode)) ? 0 : -1; +} + +pathcopy = talloc_strdup (ctx, path); +ret = 0; + +for (start = pathcopy; *start != '\0'; start = end + 1) { + end = strchr (start + 1, '/'); + if (!end) { + ret = mkdir (path, mode); + break; + } + *end = '\0'; + ret = mkdir (pathcopy, mode); + if (ret != 0 && errno != EEXIST) { + break; + } + *end = '/'; +} + +talloc_free (pathcopy); + +return ret; +} + +static notmuch_bool_t +maildir_create (void *ctx, const char *dir) +{ +const int mode = 0755; +char *subdir; +char *end; + +/* Create 'cur' directory, including parent directories. */ +subdir = talloc_asprintf (ctx, "%s/cur", dir); +if (mkdir_parents (ctx, subdir, mode) != 0) + return FALSE; + +end = subdir + strlen (subdir); + +/* Create 'new' directory. */ +strcpy (end - 3, "new"); +if (mkdir (subdir, mode) != 0 && errno != EEXIST) + return FALSE; + +/* Create 'tmp' directory. */ +strcpy (end - 3, "tmp"); +if (mkdir (subdir, mode) != 0 && errno != EEXIST) + return FALSE; + +talloc_free (subdir); +return TRUE; +} + static notmuch_bool_t safe_gethostname (char *hostname, size_t hostname_size) { @@ -253,6 +317,7 @@ notmuch_insert_command (void *ctx, int argc, char *argv[]) const char **new_tags; size_t new_tags_length; const char *folder = NULL; +notmuch_bool_t create_folder = FALSE; tag_operation_t *tag_ops; int tag_ops_count = 0; char *maildir; @@ -262,6 +327,7 @@ notmuch_insert_command (void *ctx, int argc, char *argv[]) notmuch_opt_desc_t options[] = { { NOTMUCH_OPT_STRING, , "folder", 0, 0 }, + { NOTMUCH_OPT_BOOLEAN, _folder, "create-folder", 0, 0 }, { NOTMUCH_OPT_END, 0, 0, 0, 0 } }; @@ -328,6 +394,11 @@ notmuch_insert_command (void *ctx, int argc, char *argv[]) return 1; } maildir = talloc_asprintf (ctx, "%s/%s", db_path, folder); + if (create_folder && ! maildir_create (ctx, maildir)) { + fprintf (stderr, "Error: creating maildir %s: %s\n", +maildir, strerror (errno)); + return 1; + } } else { maildir = talloc_asprintf (ctx, "%s", db_path); } -- 1.7.4.4
[PATCH 15/18] man: reference notmuch-insert.1
Add references to notmuch-insert.1 from other man pages. --- man/man1/notmuch-config.1 |4 ++-- man/man1/notmuch-count.1|4 ++-- man/man1/notmuch-dump.1 |4 ++-- man/man1/notmuch-new.1 |4 ++-- man/man1/notmuch-reply.1|3 ++- man/man1/notmuch-restore.1 |3 ++- man/man1/notmuch-search.1 |3 ++- man/man1/notmuch-show.1 |3 ++- man/man1/notmuch-tag.1 |3 ++- man/man1/notmuch.1 |3 ++- man/man5/notmuch-hooks.5|4 ++-- man/man7/notmuch-search-terms.7 |3 ++- 12 files changed, 24 insertions(+), 17 deletions(-) diff --git a/man/man1/notmuch-config.1 b/man/man1/notmuch-config.1 index 2ee555d..484ccdb 100644 --- a/man/man1/notmuch-config.1 +++ b/man/man1/notmuch-config.1 @@ -152,7 +152,7 @@ use ${HOME}/.notmuch\-config if this variable is not set. .SH SEE ALSO \fBnotmuch\fR(1), \fBnotmuch-count\fR(1), \fBnotmuch-dump\fR(1), -\fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1), \fBnotmuch-reply\fR(1), -\fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1), +\fBnotmuch-hooks\fR(5), \fBnotmuch-insert\fR(1), \fBnotmuch-new\fR(1), +\fBnotmuch-reply\fR(1), \fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1), \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1), \fBnotmuch-tag\fR(1) diff --git a/man/man1/notmuch-count.1 b/man/man1/notmuch-count.1 index 8551ab2..f9ba926 100644 --- a/man/man1/notmuch-count.1 +++ b/man/man1/notmuch-count.1 @@ -52,7 +52,7 @@ count (the default) or not. .SH SEE ALSO \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-dump\fR(1), -\fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1), \fBnotmuch-reply\fR(1), -\fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1), +\fBnotmuch-hooks\fR(5), \fBnotmuch-insert\fR(1), \fBnotmuch-new\fR(1), +\fBnotmuch-reply\fR(1), \fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1), \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1), \fBnotmuch-tag\fR(1) diff --git a/man/man1/notmuch-dump.1 b/man/man1/notmuch-dump.1 index 64abf01..4f219e7 100644 --- a/man/man1/notmuch-dump.1 +++ b/man/man1/notmuch-dump.1 @@ -31,7 +31,7 @@ for details of the supported syntax for . .SH SEE ALSO \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1), -\fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1), \fBnotmuch-reply\fR(1), -\fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1), +\fBnotmuch-hooks\fR(5), \fBnotmuch-insert\fR(1), \fBnotmuch-new\fR(1), +\fBnotmuch-reply\fR(1), \fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1), \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1), \fBnotmuch-tag\fR(1) diff --git a/man/man1/notmuch-new.1 b/man/man1/notmuch-new.1 index e01f2eb..b5c14f3 100644 --- a/man/man1/notmuch-new.1 +++ b/man/man1/notmuch-new.1 @@ -64,7 +64,7 @@ Prevents hooks from being run. .SH SEE ALSO \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1), -\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), \fBnotmuch-reply\fR(1), -\fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1), +\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), \fBnotmuch-insert\fR(1), +\fBnotmuch-reply\fR(1), \fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1), \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1), \fBnotmuch-tag\fR(1) diff --git a/man/man1/notmuch-reply.1 b/man/man1/notmuch-reply.1 index 5aa86c0..416c796 100644 --- a/man/man1/notmuch-reply.1 +++ b/man/man1/notmuch-reply.1 @@ -96,7 +96,8 @@ replying to multiple messages at once, but the JSON format does not. .SH SEE ALSO \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1), -\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1), +\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), +\fBnotmuch-insert\fR(1), \fBnotmuch-new\fR(1), \fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1), \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1), \fBnotmuch-tag\fR(1) diff --git a/man/man1/notmuch-restore.1 b/man/man1/notmuch-restore.1 index 18281c7..55a902d 100644 --- a/man/man1/notmuch-restore.1 +++ b/man/man1/notmuch-restore.1 @@ -39,7 +39,8 @@ details. .SH SEE ALSO \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1), -\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1), +\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), +\fBnotmuch-insert\fR(1), \fBnotmuch-new\fR(1), \fBnotmuch-reply\fR(1), \fBnotmuch-search\fR(1), \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1), \fBnotmuch-tag\fR(1) diff --git a/man/man1/notmuch-search.1 b/man/man1/notmuch-search.1 index b42eb2c..1794a5e 100644 --- a/man/man1/notmuch-search.1 +++ b/man/man1/notmuch-search.1 @@ -128,7 +128,8 @@ is the number of matching non-excluded messages in the thread. .SH SEE ALSO \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1), -\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1), +\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), +\fBnotmuch-insert\fR(1), \fBnotmuch-new\fR(1), \fBnotmuch-reply\fR(1), \fBnotmuch-restore\fR(1), \fBnotmuch-search-terms\fR(7),
[PATCH 14/18] man: document 'insert' command
Add initial documentation for notmuch insert command. --- man/Makefile.local|1 + man/man1/notmuch-insert.1 | 50 + 2 files changed, 51 insertions(+), 0 deletions(-) create mode 100644 man/man1/notmuch-insert.1 diff --git a/man/Makefile.local b/man/Makefile.local index d43a949..f91bfd4 100644 --- a/man/Makefile.local +++ b/man/Makefile.local @@ -12,6 +12,7 @@ MAN1 := \ $(dir)/man1/notmuch-count.1 \ $(dir)/man1/notmuch-dump.1 \ $(dir)/man1/notmuch-restore.1 \ + $(dir)/man1/notmuch-insert.1 \ $(dir)/man1/notmuch-new.1 \ $(dir)/man1/notmuch-reply.1 \ $(dir)/man1/notmuch-search.1 \ diff --git a/man/man1/notmuch-insert.1 b/man/man1/notmuch-insert.1 new file mode 100644 index 000..7d281b5 --- /dev/null +++ b/man/man1/notmuch-insert.1 @@ -0,0 +1,50 @@ +.TH NOTMUCH-INSERT 1 2012-xx-xx "Notmuch 0.xx" +.SH NAME +notmuch-insert \- add a message to the maildir and notmuch database +.SH SYNOPSIS + +.B notmuch insert +.RI "[" options "]" +.RI "--" +.RI "[ +<" tag> "|\-<" tag "> ... ]" + +.SH DESCRIPTION + +.B notmuch insert +reads a message from standard input and delivers it to the specified +maildir folder, then incorporates the message into the notmuch +database. It is an alternative to using a separate tool to deliver +the message then running +.B notmuch new +afterwards. + +The new message will be tagged with the tags specified by the +.B new.tags +configuration option. +Additional tagging operations may be specified on the command-line. +Tags prefixed by '+' are added while those prefixed by '\-' are +removed. notmuch will warn about ambiguous tag removal arguments +which may be confused with option arguments. It is recommended to use +the option list terminator "--" to avoid ambiguity. + +Supported options for +.B insert +include +.RS 4 +.TP 4 +.BI "--folder=<" folder ">" + +Deliver the message to the +.RI Maildir/ folder +directory, which must already exist. +The default is to deliver to the top-level directory. + +.RE +.RE +.SH SEE ALSO + +\fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1), +\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), \fBnotmuch-reply\fR(1), +\fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1), +\fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1), +\fBnotmuch-tag\fR(1) -- 1.7.4.4
[PATCH 13/18] test: add tests for insert
Add tests for new 'insert' command. --- test/insert | 53 + test/notmuch-test |1 + 2 files changed, 54 insertions(+), 0 deletions(-) create mode 100755 test/insert diff --git a/test/insert b/test/insert new file mode 100755 index 000..3514920 --- /dev/null +++ b/test/insert @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +test_description='"notmuch insert"' +. ./test-lib.sh + +# Create directories and database before inserting. +mkdir -p "$MAIL_DIR"/{cur,new,tmp} +mkdir -p "$MAIL_DIR"/Drafts/{cur,new,tmp} +notmuch new > /dev/null + +# We use generate_message to create the temporary message file. +# It happens to be in the mail directory already but that is okay. + +test_begin_subtest "Insert message, default" +generate_message \ +"[subject]=\"insert-subject\"" \ +"[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" \ +"[body]=\"insert-message\"" +notmuch insert < "$gen_msg_filename" +test_expect_equal "`notmuch count subject:insert-subject tag:unread`" "1" + +test_begin_subtest "Insert message, add tag" +generate_message \ +"[subject]=\"insert-subject-addtag\"" \ +"[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" \ +"[body]=\"insert-message-addtag\"" +notmuch insert +custom < "$gen_msg_filename" +test_expect_equal "`notmuch count tag:custom`" "1" + +test_begin_subtest "Insert message, add/remove tag" +generate_message \ +"[subject]=\"insert-subject-addrmtag\"" \ +"[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" \ +"[body]=\"insert-message-addrmtag\"" +notmuch insert -- +custom -unread < "$gen_msg_filename" +test_expect_equal "`notmuch count tag:custom NOT tag:unread`" "1" + +test_begin_subtest "Insert message, folder" +generate_message \ +"[subject]=\"insert-subject-draft\"" \ +"[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" \ +"[body]=\"insert-message-draft\"" +notmuch insert --folder=Drafts < "$gen_msg_filename" +test_expect_equal "`notmuch count folder:Drafts`" "1" + +test_begin_subtest "Insert message, folder and tags" +generate_message \ +"[subject]=\"insert-subject-draft\"" \ +"[date]=\"Sat, 01 Jan 2000 12:00:00 -\"" \ +"[body]=\"insert-message-draft\"" +notmuch insert --folder=Drafts -- +draft -unread < "$gen_msg_filename" +test_expect_equal "`notmuch count folder:Drafts tag:draft NOT tag:unread`" "1" + +test_done diff --git a/test/notmuch-test b/test/notmuch-test index ea39dfc..b40ba0b 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -22,6 +22,7 @@ TESTS=" config new count + insert search search-output search-by-folder -- 1.7.4.4
[PATCH 12/18] insert: add copyright line from notmuch-deliver
The 'insert' implementation was based partly on notmuch-deliver. --- notmuch-insert.c |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index 5fd79be..a69dfe6 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -2,6 +2,9 @@ * * Copyright ? 2012 Peter Wang * + * Based in part on notmuch-deliver + * Copyright ? 2010 Ali Polatel + * * 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 -- 1.7.4.4
[PATCH 11/18] insert: apply command-line tag operations
Apply the +tag and -tag operations which were specified on the command-line. --- notmuch-insert.c | 18 ++ 1 files changed, 14 insertions(+), 4 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index 6db03e3..5fd79be 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -151,7 +151,7 @@ copy_fd_data (int fdin, int fdout) static notmuch_bool_t save_database (notmuch_database_t *notmuch, const char *path, - const char **new_tags) + const char **new_tags, const tag_operation_t *tag_ops) { notmuch_message_t *message; notmuch_status_t status; @@ -186,6 +186,14 @@ save_database (notmuch_database_t *notmuch, const char *path, notmuch_message_add_tag (message, new_tags[i]); } +for (i = 0; tag_ops[i].tag; i++) { + if (tag_ops[i].remove) { + notmuch_message_remove_tag (message, tag_ops[i].tag); + } else { + notmuch_message_add_tag (message, tag_ops[i].tag); + } +} + notmuch_message_thaw (message); notmuch_message_tags_to_maildir_flags (message); @@ -197,7 +205,8 @@ save_database (notmuch_database_t *notmuch, const char *path, static notmuch_bool_t insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, - const char *dir, const char **new_tags) + const char *dir, const char **new_tags, + const tag_operation_t *tag_ops) { char *tmppath; char *newpath; @@ -222,7 +231,7 @@ insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, return FALSE; } -ret = save_database (notmuch, newpath, new_tags); +ret = save_database (notmuch, newpath, new_tags, tag_ops); if (!ret) { /* XXX maybe there should be an option to keep the file in maildir? */ @@ -324,7 +333,8 @@ notmuch_insert_command (void *ctx, int argc, char *argv[]) NOTMUCH_DATABASE_MODE_READ_WRITE, )) return 1; -ret = insert_message (ctx, notmuch, STDIN_FILENO, maildir, new_tags); +ret = insert_message (ctx, notmuch, STDIN_FILENO, maildir, new_tags, + tag_ops); notmuch_database_destroy (notmuch); -- 1.7.4.4
[PATCH 10/18] insert: parse command-line tag operations
Parse +tag and -tag on the 'insert' command-line. Issue a warning about ambiguous -tag arguments which don't follow +tag nor an explicit option list terminator. --- notmuch-insert.c | 50 ++ 1 files changed, 50 insertions(+), 0 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index 4fb3ea3..6db03e3 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -24,6 +24,11 @@ #include #include +typedef struct { +const char *tag; +notmuch_bool_t remove; +} tag_operation_t; + static notmuch_bool_t check_folder_name (const char *folder) { @@ -236,8 +241,11 @@ notmuch_insert_command (void *ctx, int argc, char *argv[]) const char **new_tags; size_t new_tags_length; const char *folder = NULL; +tag_operation_t *tag_ops; +int tag_ops_count = 0; char *maildir; int opt_index; +notmuch_bool_t warn_tag_rem; notmuch_bool_t ret; notmuch_opt_desc_t options[] = { @@ -253,6 +261,48 @@ notmuch_insert_command (void *ctx, int argc, char *argv[]) return 1; } +if (opt_index > 0 && strcmp (argv[opt_index - 1], "--") == 0) { + warn_tag_rem = FALSE; +} else { + warn_tag_rem = TRUE; +} + +/* Array of tagging operations (add or remove), terminated with an + * empty element. */ +tag_ops = talloc_array (ctx, tag_operation_t, argc - opt_index + 1); +if (tag_ops == NULL) { + fprintf (stderr, "Out of memory.\n"); + return 1; +} + +for (; opt_index < argc; opt_index++) { + if (argv[opt_index][0] == '+') { + tag_ops[tag_ops_count].tag = argv[opt_index] + 1; + tag_ops[tag_ops_count].remove = FALSE; + tag_ops_count++; + warn_tag_rem = FALSE; + } else if (argv[opt_index][0] == '-') { + if (warn_tag_rem) { + fprintf (stderr, +"Warning: ambiguous argument treated as tag removal: %s\n", +argv[opt_index]); + } + tag_ops[tag_ops_count].tag = argv[opt_index] + 1; + tag_ops[tag_ops_count].remove = TRUE; + tag_ops_count++; + } else { + break; + } +} + +tag_ops[tag_ops_count].tag = NULL; + +if (opt_index != argc) { + fprintf (stderr, "Error: bad argument to notmuch insert: %s\n", +argv[opt_index]); + return 1; +} + config = notmuch_config_open (ctx, NULL, NULL); if (config == NULL) return 1; -- 1.7.4.4
[PATCH 09/18] insert: apply default tags to new message
Apply the new.tags to messages added by 'insert'. This mirrors the behaviour if the message were delivered by a separate tool followed by 'notmuch new'. --- notmuch-insert.c | 21 + 1 files changed, 17 insertions(+), 4 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index ee51a87..4fb3ea3 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -145,10 +145,12 @@ copy_fd_data (int fdin, int fdout) } static notmuch_bool_t -save_database (notmuch_database_t *notmuch, const char *path) +save_database (notmuch_database_t *notmuch, const char *path, + const char **new_tags) { notmuch_message_t *message; notmuch_status_t status; +int i; status = notmuch_database_add_message (notmuch, path, ); switch (status) { @@ -173,6 +175,14 @@ save_database (notmuch_database_t *notmuch, const char *path) return FALSE; } +notmuch_message_freeze (message); + +for (i = 0; new_tags[i]; i++) { + notmuch_message_add_tag (message, new_tags[i]); +} + +notmuch_message_thaw (message); + notmuch_message_tags_to_maildir_flags (message); notmuch_message_destroy (message); @@ -182,7 +192,7 @@ save_database (notmuch_database_t *notmuch, const char *path) static notmuch_bool_t insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, - const char *dir) + const char *dir, const char **new_tags) { char *tmppath; char *newpath; @@ -207,7 +217,7 @@ insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, return FALSE; } -ret = save_database (notmuch, newpath); +ret = save_database (notmuch, newpath, new_tags); if (!ret) { /* XXX maybe there should be an option to keep the file in maildir? */ @@ -223,6 +233,8 @@ notmuch_insert_command (void *ctx, int argc, char *argv[]) notmuch_config_t *config; notmuch_database_t *notmuch; const char *db_path; +const char **new_tags; +size_t new_tags_length; const char *folder = NULL; char *maildir; int opt_index; @@ -246,6 +258,7 @@ notmuch_insert_command (void *ctx, int argc, char *argv[]) return 1; db_path = notmuch_config_get_database_path (config); +new_tags = notmuch_config_get_new_tags (config, _tags_length); if (folder != NULL) { if (! check_folder_name (folder)) { @@ -261,7 +274,7 @@ notmuch_insert_command (void *ctx, int argc, char *argv[]) NOTMUCH_DATABASE_MODE_READ_WRITE, )) return 1; -ret = insert_message (ctx, notmuch, STDIN_FILENO, maildir); +ret = insert_message (ctx, notmuch, STDIN_FILENO, maildir, new_tags); notmuch_database_destroy (notmuch); -- 1.7.4.4
[PATCH 08/18] insert: check folder name
Don't accept folder names containing a ".." component, to prevent writing outside of the maildir. --- notmuch-insert.c | 20 1 files changed, 20 insertions(+), 0 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index 6398618..ee51a87 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -25,6 +25,22 @@ #include static notmuch_bool_t +check_folder_name (const char *folder) +{ +const char *p = folder; + +/* Check ".." appears nowhere in the folder name. */ +for (;;) { + if ((p[0] == '.') && (p[1] == '.') && (p[2] == '\0' || p[2] == '/')) + return FALSE; + p = strchr (p, '/'); + if (!p) + return TRUE; + p++; +} +} + +static notmuch_bool_t safe_gethostname (char *hostname, size_t hostname_size) { if (gethostname (hostname, hostname_size) == -1) { @@ -232,6 +248,10 @@ notmuch_insert_command (void *ctx, int argc, char *argv[]) db_path = notmuch_config_get_database_path (config); if (folder != NULL) { + if (! check_folder_name (folder)) { + fprintf (stderr, "Error: bad folder name: %s\n", folder); + return 1; + } maildir = talloc_asprintf (ctx, "%s/%s", db_path, folder); } else { maildir = talloc_asprintf (ctx, "%s", db_path); -- 1.7.4.4
[PATCH 07/18] insert: add --folder option
Allow the new message to be inserted into a folder within the Maildir hierarchy instead of the top-level folder. --- notmuch-insert.c | 21 - 1 files changed, 20 insertions(+), 1 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index dd449bc..6398618 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -207,16 +207,35 @@ notmuch_insert_command (void *ctx, int argc, char *argv[]) notmuch_config_t *config; notmuch_database_t *notmuch; const char *db_path; +const char *folder = NULL; char *maildir; +int opt_index; notmuch_bool_t ret; +notmuch_opt_desc_t options[] = { + { NOTMUCH_OPT_STRING, , "folder", 0, 0 }, + { NOTMUCH_OPT_END, 0, 0, 0, 0 } +}; + +opt_index = parse_arguments (argc, argv, options, 1); + +if (opt_index < 0) { + fprintf (stderr, "Error: bad argument to notmuch insert: %s\n", +argv[-opt_index]); + return 1; +} + config = notmuch_config_open (ctx, NULL, NULL); if (config == NULL) return 1; db_path = notmuch_config_get_database_path (config); -maildir = talloc_asprintf (ctx, "%s", db_path); +if (folder != NULL) { + maildir = talloc_asprintf (ctx, "%s/%s", db_path, folder); +} else { + maildir = talloc_asprintf (ctx, "%s", db_path); +} if (notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_WRITE, )) -- 1.7.4.4
[PATCH 06/18] insert: add new message to database
Add the new message to the notmuch database, renaming the file to encode notmuch tags as maildir flags. --- notmuch-insert.c | 44 1 files changed, 44 insertions(+), 0 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index bab1fed..dd449bc 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -129,6 +129,42 @@ copy_fd_data (int fdin, int fdout) } static notmuch_bool_t +save_database (notmuch_database_t *notmuch, const char *path) +{ +notmuch_message_t *message; +notmuch_status_t status; + +status = notmuch_database_add_message (notmuch, path, ); +switch (status) { +case NOTMUCH_STATUS_SUCCESS: + break; +case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID: + fprintf (stderr, "Warning: duplicate message.\n"); + break; +default: +case NOTMUCH_STATUS_FILE_NOT_EMAIL: +case NOTMUCH_STATUS_READ_ONLY_DATABASE: +case NOTMUCH_STATUS_XAPIAN_EXCEPTION: +case NOTMUCH_STATUS_OUT_OF_MEMORY: +case NOTMUCH_STATUS_FILE_ERROR: +case NOTMUCH_STATUS_NULL_POINTER: +case NOTMUCH_STATUS_TAG_TOO_LONG: +case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: +case NOTMUCH_STATUS_UNBALANCED_ATOMIC: +case NOTMUCH_STATUS_LAST_STATUS: + fprintf (stderr, "Error: failed to add `%s' to notmuch database: %s\n", +path, notmuch_status_to_string (status)); + return FALSE; +} + +notmuch_message_tags_to_maildir_flags (message); + +notmuch_message_destroy (message); + +return TRUE; +} + +static notmuch_bool_t insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, const char *dir) { @@ -152,6 +188,14 @@ insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, if (!ret) { unlink (tmppath); + return FALSE; +} + +ret = save_database (notmuch, newpath); + +if (!ret) { + /* XXX maybe there should be an option to keep the file in maildir? */ + unlink (newpath); } return ret; -- 1.7.4.4
[PATCH 05/18] insert: move file from Maildir tmp to new
Atomically move the new message file from the Maildir 'tmp' directory to 'new'. --- notmuch-insert.c | 18 ++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index 340f7e4..bab1fed 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -75,6 +75,20 @@ maildir_open_tmp (void *ctx, const char *dir, char **tmppath, char **newpath) } static notmuch_bool_t +maildir_move_to_new (const char *tmppath, const char *newpath) +{ +/* We follow the Dovecot recommendation to simply use rename() + * instead of link() and unlink(). + */ +if (rename (tmppath, newpath) == 0) { + return TRUE; +} + +fprintf (stderr, "Error: rename() failed: %s\n", strerror (errno)); +return FALSE; +} + +static notmuch_bool_t copy_fd_data (int fdin, int fdout) { char buf[4096]; @@ -132,6 +146,10 @@ insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, close (fdout); +if (ret) { + ret = maildir_move_to_new (tmppath, newpath); +} + if (!ret) { unlink (tmppath); } -- 1.7.4.4
[PATCH 04/18] insert: copy stdin to Maildir tmp file
Read the new message from standard input into the Maildir tmp file. --- notmuch-insert.c | 51 +-- 1 files changed, 49 insertions(+), 2 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index f01a6f2..340f7e4 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -75,21 +75,68 @@ maildir_open_tmp (void *ctx, const char *dir, char **tmppath, char **newpath) } static notmuch_bool_t +copy_fd_data (int fdin, int fdout) +{ +char buf[4096]; +char *p; +ssize_t remain; +ssize_t written; + +for (;;) { + remain = read (fdin, buf, sizeof(buf)); + if (remain == 0) + break; + if (remain < 0) { + if (errno == EINTR) + continue; + fprintf (stderr, "Error: reading from standard input: %s\n", +strerror (errno)); + return FALSE; + } + + p = buf; + do { + written = write (fdout, p, remain); + if (written == 0) + return FALSE; + if (written < 0) { + if (errno == EINTR) + continue; + fprintf (stderr, "Error: writing to temporary file: %s", +strerror (errno)); + return FALSE; + } + p += written; + remain -= written; + } while (remain > 0); +} + +return TRUE; +} + +static notmuch_bool_t insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, const char *dir) { char *tmppath; char *newpath; int fdout; +notmuch_bool_t ret; fdout = maildir_open_tmp (ctx, dir, , ); if (fdout < 0) { return FALSE; } +ret = copy_fd_data (fdin, fdout); + close (fdout); -unlink (tmppath); -return FALSE; + +if (!ret) { + unlink (tmppath); +} + +return ret; } int -- 1.7.4.4
[PATCH 03/18] insert: open Maildir tmp file
Open a unique file in the Maildir tmp directory. The new message is not yet copied into the file. --- notmuch-insert.c | 80 +- 1 files changed, 79 insertions(+), 1 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index 21424cf..f01a6f2 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -20,12 +20,86 @@ #include "notmuch-client.h" +#include +#include +#include + +static notmuch_bool_t +safe_gethostname (char *hostname, size_t hostname_size) +{ +if (gethostname (hostname, hostname_size) == -1) { + strncpy (hostname, "unknown", hostname_size); +} +hostname[hostname_size - 1] = '\0'; + +return (strchr (hostname, '/') == NULL); +} + +static int +maildir_open_tmp (void *ctx, const char *dir, char **tmppath, char **newpath) +{ +pid_t pid; +char hostname[256]; +struct timeval tv; +char *filename; +int fd = -1; + +/* This is the file name format used by Dovecot. */ +pid = getpid (); +if (! safe_gethostname (hostname, sizeof (hostname))) { + fprintf (stderr, "Error: invalid host name.\n"); + return -1; +} +gettimeofday (, NULL); +filename = talloc_asprintf (ctx, "%ld.M%ldP%d.%s", + tv.tv_sec, tv.tv_usec, pid, hostname); + +*tmppath = talloc_asprintf (ctx, "%s/tmp/%s", dir, filename); + +do { + fd = open (*tmppath, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0666); +} while (fd == -1 && errno == EEXIST); + +if (fd != -1) { + *newpath = talloc_asprintf (ctx, "%s/new/%s", dir, filename); +} +else { + fprintf (stderr, "Error: opening %s: %s\n", +*tmppath, strerror (errno)); + talloc_free (*tmppath); +} + +talloc_free (filename); + +return fd; +} + +static notmuch_bool_t +insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, + const char *dir) +{ +char *tmppath; +char *newpath; +int fdout; + +fdout = maildir_open_tmp (ctx, dir, , ); +if (fdout < 0) { + return FALSE; +} + +close (fdout); +unlink (tmppath); +return FALSE; +} + int notmuch_insert_command (void *ctx, int argc, char *argv[]) { notmuch_config_t *config; notmuch_database_t *notmuch; const char *db_path; +char *maildir; +notmuch_bool_t ret; config = notmuch_config_open (ctx, NULL, NULL); if (config == NULL) @@ -33,11 +107,15 @@ notmuch_insert_command (void *ctx, int argc, char *argv[]) db_path = notmuch_config_get_database_path (config); +maildir = talloc_asprintf (ctx, "%s", db_path); + if (notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_WRITE, )) return 1; +ret = insert_message (ctx, notmuch, STDIN_FILENO, maildir); + notmuch_database_destroy (notmuch); -return 1; +return (ret) ? 0 : 1; } -- 1.7.4.4
[PATCH 02/18] insert: open database
Open the notmuch configuration file and database. --- notmuch-insert.c | 16 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/notmuch-insert.c b/notmuch-insert.c index 0e061a0..21424cf 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -23,5 +23,21 @@ int notmuch_insert_command (void *ctx, int argc, char *argv[]) { +notmuch_config_t *config; +notmuch_database_t *notmuch; +const char *db_path; + +config = notmuch_config_open (ctx, NULL, NULL); +if (config == NULL) + return 1; + +db_path = notmuch_config_get_database_path (config); + +if (notmuch_database_open (notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_WRITE, )) + return 1; + +notmuch_database_destroy (notmuch); + return 1; } -- 1.7.4.4
[PATCH 01/18] cli: add stub for insert command
This does nothing yet. --- Makefile.local |1 + notmuch-client.h |3 +++ notmuch-insert.c | 27 +++ notmuch.c|3 +++ 4 files changed, 34 insertions(+), 0 deletions(-) create mode 100644 notmuch-insert.c diff --git a/Makefile.local b/Makefile.local index 296995d..950f046 100644 --- a/Makefile.local +++ b/Makefile.local @@ -282,6 +282,7 @@ notmuch_client_srcs = \ notmuch-config.c\ notmuch-count.c \ notmuch-dump.c \ + notmuch-insert.c\ notmuch-new.c \ notmuch-reply.c \ notmuch-restore.c \ diff --git a/notmuch-client.h b/notmuch-client.h index f930798..edbd3ee 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -132,6 +132,9 @@ int notmuch_dump_command (void *ctx, int argc, char *argv[]); int +notmuch_insert_command (void *ctx, int argc, char *argv[]); + +int notmuch_new_command (void *ctx, int argc, char *argv[]); int diff --git a/notmuch-insert.c b/notmuch-insert.c new file mode 100644 index 000..0e061a0 --- /dev/null +++ b/notmuch-insert.c @@ -0,0 +1,27 @@ +/* notmuch - Not much of an email program, (just index and search) + * + * Copyright ? 2012 Peter Wang + * + * 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: Peter Wang + */ + +#include "notmuch-client.h" + +int +notmuch_insert_command (void *ctx, int argc, char *argv[]) +{ +return 1; +} diff --git a/notmuch.c b/notmuch.c index 477a09c..86239fd 100644 --- a/notmuch.c +++ b/notmuch.c @@ -53,6 +53,9 @@ static command_t commands[] = { { "new", notmuch_new_command, "[options...]", "Find and import new messages to the notmuch database." }, +{ "insert", notmuch_insert_command, + "[options...] [--] [+|- ...] < message", + "Add a new message into the maildir and notmuch database." }, { "search", notmuch_search_command, "[options...] [...]", "Search for messages matching the given search terms." }, -- 1.7.4.4
[PATCH] emacs: Add customization group for replying
When one wants to customize the format of reply message, there nothing to tell the user how to do it. Without knowing that construction of reply buffer is actually implemented in the message package, it seems that replying cannot be customized. Because I was getting annoyed by the empty line the between citation line and the quoted message, I figured out that changing this is fairly easy when one knows what to customize. This patch adds notmuch-reply customization group that that contains references to the relevant customization options. The new group is easy to find as it is shown as a result of running M-x customize-group RET notmuch RET. --- emacs/notmuch-lib.el | 11 +++ 1 file changed, 11 insertions(+) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 30db58f..47d9e0c 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -45,6 +45,17 @@ Showing messages and threads. :group 'notmuch) +(defgroup notmuch-reply + '((message-citation-line-function custom-variable) +(message-citation-line-format custom-variable) +(message-insertion custom-group)) + Replying to messages. + +Replying in notmuch can be customized in `Message insertion' +group. However, the most important options from that group are +also included here. + :group 'notmuch) + (defgroup notmuch-send nil Sending messages from Notmuch. :group 'notmuch) -- 1.7.10 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] emacs: functions to import sender or recipient into BBDB
From a show buffer, bbdb/notmuch-snarf-from imports the sender into bbdb. bbdb/notmuch-snarf-to attempts to import all recipients. BBDB displays a buffer with each contact; C-g displays the next contact, or returns to the notmuch-show buffer. Both functions assume that email contacts are seperated by commas. If a comma is included in a name, it will try to make two separate contacts. --- This is my first notmuch patch. Comments very welcome. emacs/notmuch-show.el | 28 1 file changed, 28 insertions(+) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 6335d45..3bc1da0 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -1895,6 +1895,34 @@ the user (see `notmuch-show-stash-mlarchive-link-alist'). (button-get button :notmuch-filename) (button-get button :notmuch-content-type))) +;; bbdb interaction functions, awaiting user keybindings + +(defun bbdb/snarf-between-commas () + ; What about names written Surname, First M u...@server.tld? + (goto-char (point-min)) + (let ((comma (point))) +(while (search-forward , nil end) + (bbdb-snarf-region comma (point)) + (setq comma (point))) +(bbdb-snarf-region comma (point)) ; last entry + )) + +(defun bbdb/notmuch-snarf-header (header) + (let ((text (notmuch-show-get-header header))) +(with-temp-buffer + (insert text) + (bbdb/snarf-between-commas + +(defun bbdb/notmuch-snarf-from () + Import the sender of the current message into BBDB + (interactive) + (bbdb/notmuch-snarf-header :From)) + +(defun bbdb/notmuch-snarf-to () + Import all recipients of the current message into BBDB + (interactive) + (bbdb/notmuch-snarf-header :To)) + ;; (provide 'notmuch-show) -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch