[PATCH v4 0/3] indicate length of omitted body content
On Sun, 09 Dec 2012 19:21:18 +, Mark Walters wrote: > > Hi (sorry Peter I had assumed git send-email would have cc'd you on my > rebase earlier today) > > There was some discussion about this patch series on irc and the general > view was favourable but that, for consistency, all omitted parts should > received a content-length (including text/html). This is a little messy > to code into the if else stuff: Jani suggested putting > content-length/content-encoding into a small function. > > Anyway I had hope it was just a trivial rebase and could go in, but the > above will take a bit longer to do neatly so I will leave it for now. Ok. To save any potential duplicated work: I've updated the patch here, save for test/sexp. Waiting for that to be pushed before updating it. Peter
[Patch v6 1/6] tag-util: factor out rules for illegal tags, use in parse_tag_line
I don't know if this matters but it seems that one can still add a "-" tag by doing something like echo "+%2d -- search" | notmuch tag --batch This might be the right thing to do but I thought I would mention it. Best wishes Mark On Sun, 09 Dec 2012, david at tethera.net wrote: > From: David Bremner > > This will allow us to be consistent between batch tagging and command > line tagging as far as what is an illegal tag. > --- > tag-util.c | 35 ++- > 1 file changed, 30 insertions(+), 5 deletions(-) > > diff --git a/tag-util.c b/tag-util.c > index eab482f..c071ea8 100644 > --- a/tag-util.c > +++ b/tag-util.c > @@ -31,6 +31,29 @@ line_error (tag_parse_status_t status, > return status; > } > > +/* > + * Test tags for some forbidden cases. > + * > + * return: NULL if OK, > + * explanatory message otherwise. > + */ > + > +static const char * > +illegal_tag (const char *tag, notmuch_bool_t remove) { > + > +if (*tag == '\0' && !remove) > + return "adding empty tag"; > + > +/* This disallows adding the non-removable tag "-" and > + * enables notmuch tag to take long options more easily. > + */ > + > +if (*tag == '-' && !remove) > + return "adding tag starting with -"; > + > +return NULL; > +} > + > tag_parse_status_t > parse_tag_line (void *ctx, char *line, > tag_op_flag_t flags, > @@ -95,11 +118,13 @@ parse_tag_line (void *ctx, char *line, > remove = (*tok == '-'); > tag = tok + 1; > > - /* Maybe refuse empty tags. */ > - if (! (flags & TAG_FLAG_BE_GENEROUS) && *tag == '\0') { > - ret = line_error (TAG_PARSE_INVALID, line_for_error, > - "empty tag"); > - goto DONE; > + /* Maybe refuse illegal tags. */ > + if (! (flags & TAG_FLAG_BE_GENEROUS)) { > + const char *msg = illegal_tag (tag, remove); > + if (msg) { > + ret = line_error (TAG_PARSE_INVALID, line_for_error, msg); > + goto DONE; > + } > } > > /* Decode tag. */ > -- > 1.7.10.4 > > ___ > notmuch mailing list > notmuch at notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 4/4] emacs: Add unit-tests for clickable tags
Hi I thought I had checked the test output but I am getting a failure: the last test in emacs-show is failing (test_begin_subtest "id buttonization") I think it is just saying your patch is working and making the tag inbox in the message line a button. Best wishes Mark On Thu, 13 Dec 2012, Damien Cassou wrote: > Signed-off-by: Damien Cassou > --- > test/emacs | 103 > > 1 file changed, 103 insertions(+) > > diff --git a/test/emacs b/test/emacs > index 5403930..af9d37c 100755 > --- a/test/emacs > +++ b/test/emacs > @@ -852,5 +852,108 @@ test_emacs "(let ((mm-text-html-renderer > test_expect_success "Rendering HTML mail with images" \ > 'cat OUTPUT && grep -q smiley OUTPUT' > > +test_begin_subtest "Extracting all tags from a thread" > +add_message \ > +'[subject]="Extracting all tags from a thread"' \ > +'[body]="body 1"' > +parent=${gen_msg_id} > +add_message \ > +'[subject]="Extracting all tags from a thread"' \ > +'[body]="body 2"' \ > +"[in-reply-to]=\<$parent\>" > +add_message \ > +'[subject]="Extracting all tags from a thread"' \ > +'[body]="body 3"' \ > +"[in-reply-to]=\<$parent\>" > +latest=${gen_msg_id} > +# Extract the thread-id from one of the emails > +thread_id=$(notmuch search --output=threads id:${latest}) > +echo THREAD ID: '"'$thread_id'"' > +# Add tag "mytagfoo" to one of the emails > +notmuch tag +mytagfoo id:${latest} > +test_emacs_expect_t \ > +"(notmuch-show \"${thread_id}\") > + (let ((output (notmuch-show-thread-tags)) > + (expected '(\"inbox\" \"mytagfoo\" \"unread\"))) > + (notmuch-test-expect-equal > + (sort output #'string<) > + (sort expected #'string<)))" > + > +test_begin_subtest "The tags appear in the header-line of notmuch-show" > +add_message \ > +'[subject]="foo bar"' \ > +'[body]="body 1"' > +latest=${gen_msg_id} > +# Add tag "mytagfoo" to one of the emails > +notmuch tag +mytagfoo id:${latest} > +# Extract the thread-id from one of the emails > +thread_id=$(notmuch search --output=threads id:${latest}) > +test_emacs_expect_t \ > +"(notmuch-show \"${thread_id}\") > + (if (string-match-p \"mytagfoo\" (format-mode-line header-line-format)) > + t > + \"The tag 'mytagfoo' was not in the header-line-format\")" > + > +test_begin_subtest "The tags appear in the header-line of notmuch-show even > after update" > +add_message \ > +'[subject]="foo bar"' \ > +'[body]="body 1"' > +latest=${gen_msg_id} > +# Extract the thread-id from one of the emails > +thread_id=$(notmuch search --output=threads id:${latest}) > +test_emacs_expect_t \ > +"(notmuch-show \"${thread_id}\") > + (if (string-match-p \"mytagfoo\" (format-mode-line header-line-format)) > + (error \"There is no reason for 'mytagfoo' to be there.\")) > + (notmuch-show-tag \"+mytagfoo\") > + (if (string-match-p \"mytagfoo\" (format-mode-line header-line-format)) > + t > + \"The tag 'mytagfoo' was not in the header-line-format\")" > + > +test_begin_subtest "The tags of notmuch-show emails are clickable" > +add_message \ > +'[subject]="foo bar"' \ > +'[body]="body 1"' > +latest=${gen_msg_id} > +# Add tag "mytagfoo" to one of the emails > +notmuch tag +mytagfoo id:${latest} > +# Extract the thread-id from one of the emails > +thread_id=$(notmuch search --output=threads id:${latest}) > +test_emacs_expect_t \ > +"(notmuch-show \"${thread_id}\") > +(goto-char (point-min)) > +(re-search-forward \"mytagfoo\") > +(backward-char) ;; to be 'in' the tag > +(unless (eq major-mode 'notmuch-show-mode) > + (error \"We must be in notmuch-show at this point but we are in %s.\" > major-mode)) > +(push-button) ;; simulate a press on the RET key > +(if (eq major-mode 'notmuch-search-mode) > +t > + (format \"We must be in notmuch-search at this point but we are in > %s.\" major-mode))" > + > +test_begin_subtest "The tags of notmuch-show emails are clickable even after > update" > +add_message \ > +'[subject]="foo bar"' \ > +'[body]="body 1"' > +latest=${gen_msg_id} > +# Extract the thread-id from one of the emails > +thread_id=$(notmuch search --output=threads id:${latest}) > +test_emacs_expect_t \ > +"(notmuch-show \"${thread_id}\") > +(goto-char (point-min)) > +(if (re-search-forward \"mytagfoo\" nil t) > + (error \"There is no reason for 'mytagfoo' to be there.\")) > +(notmuch-show-tag \"+mytagfoo\") > +(goto-char (point-min)) > +(unless (re-search-forward \"mytagfoo\" nil t) > + (error \"The tag 'mytagfoo' must have been there.\")) > +(backward-char) ;; to be 'in' the tag > +(unless (eq major-mode 'notmuch-show-mode) > + (error \"We must be in notmuch-show at this point but we are in %s.\" > major-mode)) > +(push-button) ;; simulate a press on the RET key > +(if (eq major-mode 'notmuch-se
gmail importer script
Sorry, I'm misusing this thread as a bugtracker.. Traceback (most recent call last):4| | 10% ETA: 1:24:41 3.54 emails/s File "./gmail-notmuch.py", line 251, in main() File "./gmail-notmuch.py", line 89, in main download_new_messages(imap, database, new_messages, destination) File "./gmail-notmuch.py", line 208, in download_new_messages tag_message(database, dest, labels) File "./gmail-notmuch.py", line 168, in tag_message raise e notmuch.errors.FileNotEmailError best, /p
[PATCH v5] emacs: display tags in notmuch-show with links
This version looks good to me: +1 Best wishes Mark On Thu, 13 Dec 2012, Damien Cassou wrote: > This patch obsoletes: > id:1355216437-21109-1-git-send-email-damien.cassou at gmail.com > > [PATCH 1/4] emacs: Add a thread's tags to notmuch-show header-line > [PATCH 2/4] emacs: Make tags in notmuch-show header-line clickable > [PATCH 3/4] emacs: Make all tags in `notmuch-show' clickable > [PATCH 4/4] emacs: Add unit-tests for clickable tags > > These patches make clickable all tags that appear in notmuch-show > buffers. Each tag is a link to open a new notmuch-search buffer for > this tag. Additionally, the buffer's header-line now shows the > thread's tags (clickable only if the `header-button' library is loaded > or loadable). > > These patches are the first of an upcoming series whose goal is to > integrate notmuch-labeler into notmuch. See the following for more > details: https://github.com/DamienCassou/notmuch-labeler > > With respect to v4, I took care of the comments you made: > > - integration of Mark Walters' patch to avoid duplicate update of the > header-line tags > - implementation of Mark Walters' comment on sorting header-line tags > ___ > notmuch mailing list > notmuch at notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch
gmail importer script
\AllMail is the unlocalized generic version that maps to the localized version, as are all the other back slash situations.
notmuch python bindings corrupt db index (was: gmail importer script)
Quoting Jason A. Donenfeld (2012-12-13 14:32:53) > On Wed, Dec 12, 2012 at 9:49 PM, Austin Clements wrote: > > There should be no way to corrupt the database at this level through > > the Xapian API, which means nothing libnotmuch can do (much less users > > of libnotmuch) should be able to corrupt the database. If you can > > reproduce the problem, it's probably a serious bug in Xapian, but it > > could also have been a file system bug or even random file system > > corruption. > > Well that's... troubling. > > Patrick: could you please backup and try to reproduce? Otherwise I'll > assume this was a one-off situation. I tried it again, concurrently triggered some modifications and killed the process afer a while. (my modifications were not flushed during the run of your script as the index was locked) The index seems to be OK. So I'm afraid I cannot reproduce this reliably. /p
gmail importer script
On Thu, Dec 13, 2012 at 3:35 PM, fREW Schmidt wrote: > I just mean a general programming technique. As you get information > about tags you hold them in memory and then sync it later and clear > your memory. Oh, yea, that's a great idea. I'll play with that. Good thinking.
notmuch python bindings corrupt db index (was: gmail importer script)
On Wed, Dec 12, 2012 at 10:26 PM, David Bremner wrote: > > One thing that Olly Betts mentioned is that there is a recently fixed > bug in xapian with respect to multiple threads in the same process The script's actually single threaded.
notmuch python bindings corrupt db index (was: gmail importer script)
On Wed, Dec 12, 2012 at 9:49 PM, Austin Clements wrote: > There should be no way to corrupt the database at this level through > the Xapian API, which means nothing libnotmuch can do (much less users > of libnotmuch) should be able to corrupt the database. If you can > reproduce the problem, it's probably a serious bug in Xapian, but it > could also have been a file system bug or even random file system > corruption. Well that's... troubling. Patrick: could you please backup and try to reproduce? Otherwise I'll assume this was a one-off situation. Austin-- think you could do a quick review of the script to double check and confirm I'm not doing anything nefarious? http://git.zx2c4.com/gmail-notmuch/tree/gmail-notmuch.py
gmail importer script
Please don't reply offlist. This is message #2 that's been sent offlist. On Thu, Dec 13, 2012 at 3:22 PM, fREW Schmidt > One thing you might want to try is to only open the notmuch index for > writing at a specified sync time. How do I do this? What's the python function? I couldn't find anything. Would be interested in doing this though if it exists. > Also I was going to say you might want to catch SIGINT like The library already does this.
[PATCH 4/4] emacs: Add unit-tests for clickable tags
Signed-off-by: Damien Cassou --- test/emacs | 103 1 file changed, 103 insertions(+) diff --git a/test/emacs b/test/emacs index 5403930..af9d37c 100755 --- a/test/emacs +++ b/test/emacs @@ -852,5 +852,108 @@ test_emacs "(let ((mm-text-html-renderer test_expect_success "Rendering HTML mail with images" \ 'cat OUTPUT && grep -q smiley OUTPUT' +test_begin_subtest "Extracting all tags from a thread" +add_message \ +'[subject]="Extracting all tags from a thread"' \ +'[body]="body 1"' +parent=${gen_msg_id} +add_message \ +'[subject]="Extracting all tags from a thread"' \ +'[body]="body 2"' \ +"[in-reply-to]=\<$parent\>" +add_message \ +'[subject]="Extracting all tags from a thread"' \ +'[body]="body 3"' \ +"[in-reply-to]=\<$parent\>" +latest=${gen_msg_id} +# Extract the thread-id from one of the emails +thread_id=$(notmuch search --output=threads id:${latest}) +echo THREAD ID: '"'$thread_id'"' +# Add tag "mytagfoo" to one of the emails +notmuch tag +mytagfoo id:${latest} +test_emacs_expect_t \ +"(notmuch-show \"${thread_id}\") + (let ((output (notmuch-show-thread-tags)) + (expected '(\"inbox\" \"mytagfoo\" \"unread\"))) + (notmuch-test-expect-equal + (sort output #'string<) + (sort expected #'string<)))" + +test_begin_subtest "The tags appear in the header-line of notmuch-show" +add_message \ +'[subject]="foo bar"' \ +'[body]="body 1"' +latest=${gen_msg_id} +# Add tag "mytagfoo" to one of the emails +notmuch tag +mytagfoo id:${latest} +# Extract the thread-id from one of the emails +thread_id=$(notmuch search --output=threads id:${latest}) +test_emacs_expect_t \ +"(notmuch-show \"${thread_id}\") + (if (string-match-p \"mytagfoo\" (format-mode-line header-line-format)) + t + \"The tag 'mytagfoo' was not in the header-line-format\")" + +test_begin_subtest "The tags appear in the header-line of notmuch-show even after update" +add_message \ +'[subject]="foo bar"' \ +'[body]="body 1"' +latest=${gen_msg_id} +# Extract the thread-id from one of the emails +thread_id=$(notmuch search --output=threads id:${latest}) +test_emacs_expect_t \ +"(notmuch-show \"${thread_id}\") + (if (string-match-p \"mytagfoo\" (format-mode-line header-line-format)) + (error \"There is no reason for 'mytagfoo' to be there.\")) + (notmuch-show-tag \"+mytagfoo\") + (if (string-match-p \"mytagfoo\" (format-mode-line header-line-format)) + t + \"The tag 'mytagfoo' was not in the header-line-format\")" + +test_begin_subtest "The tags of notmuch-show emails are clickable" +add_message \ +'[subject]="foo bar"' \ +'[body]="body 1"' +latest=${gen_msg_id} +# Add tag "mytagfoo" to one of the emails +notmuch tag +mytagfoo id:${latest} +# Extract the thread-id from one of the emails +thread_id=$(notmuch search --output=threads id:${latest}) +test_emacs_expect_t \ +"(notmuch-show \"${thread_id}\") +(goto-char (point-min)) +(re-search-forward \"mytagfoo\") +(backward-char) ;; to be 'in' the tag +(unless (eq major-mode 'notmuch-show-mode) + (error \"We must be in notmuch-show at this point but we are in %s.\" major-mode)) +(push-button) ;; simulate a press on the RET key +(if (eq major-mode 'notmuch-search-mode) +t + (format \"We must be in notmuch-search at this point but we are in %s.\" major-mode))" + +test_begin_subtest "The tags of notmuch-show emails are clickable even after update" +add_message \ +'[subject]="foo bar"' \ +'[body]="body 1"' +latest=${gen_msg_id} +# Extract the thread-id from one of the emails +thread_id=$(notmuch search --output=threads id:${latest}) +test_emacs_expect_t \ +"(notmuch-show \"${thread_id}\") +(goto-char (point-min)) +(if (re-search-forward \"mytagfoo\" nil t) + (error \"There is no reason for 'mytagfoo' to be there.\")) +(notmuch-show-tag \"+mytagfoo\") +(goto-char (point-min)) +(unless (re-search-forward \"mytagfoo\" nil t) + (error \"The tag 'mytagfoo' must have been there.\")) +(backward-char) ;; to be 'in' the tag +(unless (eq major-mode 'notmuch-show-mode) + (error \"We must be in notmuch-show at this point but we are in %s.\" major-mode)) +(push-button) ;; simulate a press on the RET key +(if (eq major-mode 'notmuch-search-mode) +t + (format \"We must be in notmuch-search at this point but we are in %s.\" major-mode))" + test_done -- 1.7.10.4
[PATCH 3/4] emacs: Make all tags in `notmuch-show' clickable
Signed-off-by: Damien Cassou --- emacs/notmuch-show.el | 15 +++ emacs/notmuch-tagger.el | 33 + 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 9c5a85e..8c07a00 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -362,10 +362,8 @@ operation on the contents of the current buffer." (goto-char (notmuch-show-message-top)) (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t) (let ((inhibit-read-only t)) - (replace-match (concat "(" -(propertize (mapconcat 'identity tags " ") -'face 'notmuch-tag-face) -")") + (replace-match (propertize (notmuch-tagger-format-tags tags) +'face 'notmuch-tag-face) (unless no-headerline-update (notmuch-show-update-header-line))) @@ -443,10 +441,11 @@ message at DEPTH in the current thread." (notmuch-show-clean-address (plist-get headers :From)) " (" date - ") (" - (propertize (mapconcat 'identity tags " ") - 'face 'notmuch-tag-face) - ")\n") + ") " + (propertize +(notmuch-tagger-format-tags tags) +'face 'notmuch-tag-face) + "\n") (overlay-put (make-overlay start (point)) 'face 'notmuch-message-summary-face))) (defun notmuch-show-insert-header (header header-value) diff --git a/emacs/notmuch-tagger.el b/emacs/notmuch-tagger.el index 38b858a..35b81ca 100644 --- a/emacs/notmuch-tagger.el +++ b/emacs/notmuch-tagger.el @@ -44,12 +44,21 @@ test if the library is present before calling this function." (let ((tag (header-button-get button 'notmuch-tagger-tag))) (notmuch-tagger-goto-target tag))) +(defun notmuch-tagger-body-button-action (button) + "Open `notmuch-search' for the tag referenced by BUTTON." + (let ((tag (button-get button 'notmuch-tagger-tag))) +(notmuch-tagger-goto-target tag))) + (eval-after-load "header-button" '(define-button-type 'notmuch-tagger-header-button-type 'supertype 'header 'action#'notmuch-tagger-header-button-action 'follow-link t)) +(define-button-type 'notmuch-tagger-body-button-type + 'action#'notmuch-tagger-body-button-action + 'follow-link t) + (defun notmuch-tagger-really-make-header-link (tag) "Return a property list that presents a link to TAG. @@ -73,6 +82,20 @@ if not." (notmuch-tagger-really-make-header-link tag) tag)) +(defun notmuch-tagger-make-body-link (tag) + "Return a property list that presents a link to TAG. +The returned property list will not work in the header-line. For +a link that works on the header-line, prefer +`notmuch-tagger-make-header-link'." + (let ((button (copy-sequence tag))) +(make-text-button + button nil + 'type 'notmuch-tagger-body-button-type + 'notmuch-tagger-tag tag + 'skip t ;; don't stop when using TAB + 'help-echo (format "%s: Search other messages like this" tag)) +button)) + (defun notmuch-tagger-format-tags-header-line (tags) "Format TAGS as a `mode-line-format' template. The result is suitable for inclusion in `header-line-format'." @@ -83,5 +106,15 @@ The result is suitable for inclusion in `header-line-format'." " ") ")")) +(defun notmuch-tagger-format-tags (tags) + "Format TAGS as a string suitable for insertion in a buffer. +If the result of this function is to be used within the +header-line, prefer `notmuch-tagger-format-tags-header-line' +instead of this function." + (concat + "(" + (mapconcat #'notmuch-tagger-make-body-link tags " ") + ")")) + (provide 'notmuch-tagger) ;;; notmuch-tagger.el ends here -- 1.7.10.4
[PATCH 2/4] emacs: Make tags in notmuch-show header-line clickable
Signed-off-by: Damien Cassou --- emacs/notmuch-tagger.el | 54 ++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch-tagger.el b/emacs/notmuch-tagger.el index 6fcebff..38b858a 100644 --- a/emacs/notmuch-tagger.el +++ b/emacs/notmuch-tagger.el @@ -23,12 +23,64 @@ ;;; Code: ;; +(defun notmuch-tagger-header-button-present-p () + "Check if `header-button' can be loaded or is already loaded. + +`header-button' is a third-party library which facilitates the +creation of links in emacs header-line. This function tries to +`require' `header-button' and returns nil if and only if this +fails." + (require 'header-button nil t)) + +(defun notmuch-tagger-goto-target (tag) + "Show a `notmuch-search' buffer for the TAG." + (notmuch-search (concat "tag:\"" tag "\""))) + +(defun notmuch-tagger-header-button-action (button) + "Open `notmuch-search' for the tag referenced by BUTTON. +This function depends on the presence of the `header-button' +library. Please call `notmuch-tagger-header-button-present-p' to +test if the library is present before calling this function." + (let ((tag (header-button-get button 'notmuch-tagger-tag))) +(notmuch-tagger-goto-target tag))) + +(eval-after-load "header-button" + '(define-button-type 'notmuch-tagger-header-button-type + 'supertype 'header + 'action#'notmuch-tagger-header-button-action + 'follow-link t)) + +(defun notmuch-tagger-really-make-header-link (tag) + "Return a property list that presents a link to TAG. + +The returned property list will only work in the header-line. +Additionally, this function depends on the presence of the +`header-button' library. Please call +`notmuch-tagger-header-button-present-p' to test if library is +present before calling this function." + (header-button-format +tag +:type 'notmuch-tagger-header-button-type +'notmuch-tagger-tag tag +'help-echo (format "%s: Search other messages like this" tag))) + +(defun notmuch-tagger-make-header-link (tag) + "Return a property list to present TAG as a link to search. + +This only works if `header-button' is loaded. Simply returns tag +if not." + (if (notmuch-tagger-header-button-present-p) + (notmuch-tagger-really-make-header-link tag) +tag)) + (defun notmuch-tagger-format-tags-header-line (tags) "Format TAGS as a `mode-line-format' template. The result is suitable for inclusion in `header-line-format'." (list "(" - (notmuch-intersperse tags " ") + (notmuch-intersperse +(mapcar #'notmuch-tagger-make-header-link tags) +" ") ")")) (provide 'notmuch-tagger) -- 1.7.10.4
[PATCH 1/4] emacs: Add a thread's tags to notmuch-show header-line
Signed-off-by: Damien Cassou --- emacs/notmuch-lib.el| 11 +-- emacs/notmuch-show.el | 37 + emacs/notmuch-tagger.el | 35 +++ 3 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 emacs/notmuch-tagger.el diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 9c4ee71..3541bb7 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -603,8 +603,15 @@ left it." ;; Clear out what we've parsed (delete-region (point-min) (point - - +(defun notmuch-intersperse (list sep) + "Return a list with all elements of LIST separated by SEP." + (let ((first t) +(res nil)) +(dolist (elt list (nreverse res)) + (unless first +(push sep res)) + (setq first nil) + (push elt res (provide 'notmuch-lib) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 7d9f8a9..9c5a85e 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -36,6 +36,7 @@ (require 'notmuch-mua) (require 'notmuch-crypto) (require 'notmuch-print) +(require 'notmuch-tagger) (declare-function notmuch-call-notmuch-process "notmuch" (&rest args)) (declare-function notmuch-fontify-headers "notmuch" nil) @@ -355,7 +356,7 @@ operation on the contents of the current buffer." "Return a string comprised of `n' spaces." (make-string n ? )) -(defun notmuch-show-update-tags (tags) +(defun notmuch-show-update-tags (tags &optional no-headerline-update) "Update the displayed tags of the current message." (save-excursion (goto-char (notmuch-show-message-top)) @@ -364,7 +365,9 @@ operation on the contents of the current buffer." (replace-match (concat "(" (propertize (mapconcat 'identity tags " ") 'face 'notmuch-tag-face) -")")) +")") + (unless no-headerline-update +(notmuch-show-update-header-line))) (defun notmuch-clean-address (address) "Try to clean a single email ADDRESS for display. Return a cons @@ -1136,11 +1139,28 @@ function is used." (jit-lock-register #'notmuch-show-buttonise-links) - ;; Set the header line to the subject of the first message. - (setq header-line-format (notmuch-show-strip-re (notmuch-show-get-subject))) - + (notmuch-show-update-header-line) (run-hooks 'notmuch-show-hook +(defun notmuch-show-thread-tags () + "Return the list of tags for the current thread." + (let ((tags (list))) +(notmuch-show-mapc (lambda () +(mapcar (lambda (elt) + ;; Avoid adding duplicate tags + (add-to-list 'tags elt)) +(notmuch-show-get-tags +(sort tags 'string<))) + +(defun notmuch-show-update-header-line () + "Make the header-line show the thread's subject and tags." + (let ((thread-subject (notmuch-show-strip-re (notmuch-show-get-subject +(setq header-line-format + (list + thread-subject + " " + (notmuch-tagger-format-tags-header-line (notmuch-show-thread-tags)) + (defun notmuch-show-capture-state () "Capture the state of the current buffer. @@ -1443,10 +1463,10 @@ current thread." (defun notmuch-show-get-depth () (notmuch-show-get-prop :depth)) -(defun notmuch-show-set-tags (tags) +(defun notmuch-show-set-tags (tags &optional no-headerline-update) "Set the tags of the current message." (notmuch-show-set-prop :tags tags) - (notmuch-show-update-tags tags)) + (notmuch-show-update-tags tags no-headerline-update)) (defun notmuch-show-get-tags () "Return the tags of the current message." @@ -1760,7 +1780,8 @@ See `notmuch-tag' for information on the format of 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)) +(notmuch-show-set-tags new-tags t) + (notmuch-show-update-header-line)) (defun notmuch-show-add-tag () "Same as `notmuch-show-tag' but sets initial input to '+'." diff --git a/emacs/notmuch-tagger.el b/emacs/notmuch-tagger.el new file mode 100644 index 000..6fcebff --- /dev/null +++ b/emacs/notmuch-tagger.el @@ -0,0 +1,35 @@ +;; notmuch-tagger.el --- Library to improve the way tags are displayed +;; +;; Copyright ? Damien Cassou +;; +;; 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
[PATCH v5] emacs: display tags in notmuch-show with links
This patch obsoletes: id:1355216437-21109-1-git-send-email-damien.cassou at gmail.com [PATCH 1/4] emacs: Add a thread's tags to notmuch-show header-line [PATCH 2/4] emacs: Make tags in notmuch-show header-line clickable [PATCH 3/4] emacs: Make all tags in `notmuch-show' clickable [PATCH 4/4] emacs: Add unit-tests for clickable tags These patches make clickable all tags that appear in notmuch-show buffers. Each tag is a link to open a new notmuch-search buffer for this tag. Additionally, the buffer's header-line now shows the thread's tags (clickable only if the `header-button' library is loaded or loadable). These patches are the first of an upcoming series whose goal is to integrate notmuch-labeler into notmuch. See the following for more details: https://github.com/DamienCassou/notmuch-labeler With respect to v4, I took care of the comments you made: - integration of Mark Walters' patch to avoid duplicate update of the header-line tags - implementation of Mark Walters' comment on sorting header-line tags
Re: [Patch v6 1/6] tag-util: factor out rules for illegal tags, use in parse_tag_line
I don't know if this matters but it seems that one can still add a "-" tag by doing something like echo "+%2d -- search" | notmuch tag --batch This might be the right thing to do but I thought I would mention it. Best wishes Mark On Sun, 09 Dec 2012, da...@tethera.net wrote: > From: David Bremner > > This will allow us to be consistent between batch tagging and command > line tagging as far as what is an illegal tag. > --- > tag-util.c | 35 ++- > 1 file changed, 30 insertions(+), 5 deletions(-) > > diff --git a/tag-util.c b/tag-util.c > index eab482f..c071ea8 100644 > --- a/tag-util.c > +++ b/tag-util.c > @@ -31,6 +31,29 @@ line_error (tag_parse_status_t status, > return status; > } > > +/* > + * Test tags for some forbidden cases. > + * > + * return: NULL if OK, > + * explanatory message otherwise. > + */ > + > +static const char * > +illegal_tag (const char *tag, notmuch_bool_t remove) { > + > +if (*tag == '\0' && !remove) > + return "adding empty tag"; > + > +/* This disallows adding the non-removable tag "-" and > + * enables notmuch tag to take long options more easily. > + */ > + > +if (*tag == '-' && !remove) > + return "adding tag starting with -"; > + > +return NULL; > +} > + > tag_parse_status_t > parse_tag_line (void *ctx, char *line, > tag_op_flag_t flags, > @@ -95,11 +118,13 @@ parse_tag_line (void *ctx, char *line, > remove = (*tok == '-'); > tag = tok + 1; > > - /* Maybe refuse empty tags. */ > - if (! (flags & TAG_FLAG_BE_GENEROUS) && *tag == '\0') { > - ret = line_error (TAG_PARSE_INVALID, line_for_error, > - "empty tag"); > - goto DONE; > + /* Maybe refuse illegal tags. */ > + if (! (flags & TAG_FLAG_BE_GENEROUS)) { > + const char *msg = illegal_tag (tag, remove); > + if (msg) { > + ret = line_error (TAG_PARSE_INVALID, line_for_error, msg); > + goto DONE; > + } > } > > /* Decode tag. */ > -- > 1.7.10.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 v4 0/3] indicate length of omitted body content
On Thu, 13 Dec 2012, Peter Wang wrote: > On Sun, 09 Dec 2012 19:21:18 +, Mark Walters gmail.com> wrote: >> >> Hi (sorry Peter I had assumed git send-email would have cc'd you on my >> rebase earlier today) >> >> There was some discussion about this patch series on irc and the general >> view was favourable but that, for consistency, all omitted parts should >> received a content-length (including text/html). This is a little messy >> to code into the if else stuff: Jani suggested putting >> content-length/content-encoding into a small function. >> >> Anyway I had hope it was just a trivial rebase and could go in, but the >> above will take a bit longer to do neatly so I will leave it for now. > > Ok. To save any potential duplicated work: I've updated the patch here, > save for test/sexp. Waiting for that to be pushed before updating it. Sorry I am confused: isn't test/sexp already in master? Best wishes Mark
[no subject]
Hi This is looking good: I have two comments the second of which is significant. The first is do you want to sort (alphabetically) the headerline tags? As it stands they are in the order they appear in the thread which is probably not what is wanted. The second is that there is a notmuch-show-tag-all functions to tag all messages in the thread. Your patch is quadratic for the update (as it calculates the list of thread tags once for each message). The attached patch would avoid this and doesn't look too bad. (Note I retained no-headerline-update as an optional argument in case there are out of tree callers, eg users' .emacs files) [Note this is not purely of academic interest: on my test large thread (178 messages) updating the display after tagging all messages took some seconds without my patch and almost no time with it.] Best wishes Mark -- next part -- A non-text attachment was scrubbed... Name: 0001-mjw-tweak.patch Type: text/x-diff Size: 2187 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20121213/89dc1c66/attachment.patch> -- next part -- On Tue, 11 Dec 2012, Damien Cassou wrote: > From: Damien Cassou > Subject: [PATCH v4] emacs: display tags in notmuch-show with links > In-Reply-To: > > This patch obsoletes: > id:1355149964-27905-1-git-send-email-damien.cassou at gmail.com > > [PATCH 1/4] emacs: Add a thread's tags to notmuch-show header-line > [PATCH 2/4] emacs: Make tags in notmuch-show header-line clickable > [PATCH 3/4] emacs: Make all tags in `notmuch-show' clickable > [PATCH 4/4] emacs: Add unit-tests for clickable tags > > These patches make clickable all tags that appear in notmuch-show > buffers. Each tag is a link to open a new notmuch-search buffer for > this tag. Additionally, the buffer's header-line now shows the > thread's tags (clickable only if the `header-button' library is loaded > or loadable). > > These patches are the first of an upcoming series whose goal is to > integrate notmuch-labeler into notmuch. See the following for more > details: https://github.com/DamienCassou/notmuch-labeler > > With respect to v3, I took care of the comments you made: > - the header-line now updates when tags are changed > - the tags in the body stays clickable when tags are changed > > Additionally, I added two unit tests to cover the above two comments > and fixed some others unit tests of mine. > ___ > notmuch mailing list > notmuch at notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 07/10] emacs: Use --use-schema for search
On Thu, 13 Dec 2012, Austin Clements wrote: > Quoth Mark Walters on Dec 08 at 8:48 am: >> On Sun, 02 Dec 2012, Austin Clements wrote: >> > We detect the special exit statuses and use these to produce specific >> > diagnostic messages. >> > --- >> > emacs/notmuch-lib.el | 32 >> > emacs/notmuch.el | 17 + >> > 2 files changed, 45 insertions(+), 4 deletions(-) >> > >> > diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el >> > index 9402456..49b0da6 100644 >> > --- a/emacs/notmuch-lib.el >> > +++ b/emacs/notmuch-lib.el >> > @@ -325,6 +325,38 @@ string), a property list of face attributes, or a >> > list of these." >> >(put-text-property pos next 'face (cons face cur)) >> >(setq pos next) >> > >> > +(defun notmuch-pop-up-error (msg) >> > + "Pop up an error buffer displaying MSG." >> > + >> > + (let ((buf (get-buffer-create "*Notmuch errors*"))) >> > +(with-current-buffer buf >> > + (view-mode) >> > + (let ((inhibit-read-only t)) >> > + (erase-buffer) >> > + (insert msg) >> > + (unless (bolp) >> > +(insert "\n")) >> > + (goto-char (point-min >> > +(pop-to-buffer buf))) >> >> I am not sure about the erase-buffer in the above: do we definitely want >> to remove all previous error information? For version mismatch possibly >> we do but in patch 9 it is done for all show command-line error returns. > > Why wouldn't we want to use a cleared buffer in all cases? > notmuch-pop-up-error is only ever used when a command terminates, so > there's no danger of us clearing errors that the user hasn't seen yet. Just to make sure I understand this: whenever an error occurs the error popup appears so we see the message. Then the next error can safely erase buffer before showing the new error message? >> Incidentally why does show always pop-up an error but search only for >> version-mismatches? > > Historical reasons, I suppose. I was maintaining the status quo for > search (which already had *some* error handling), but there was no > error-handling status quo for show. Probably search should be more > vocal when the command fails. Should notmuch-call-notmuch-process also be switched to this framework? In particular that also puts errors in "*Notmuch errors*" so my earlier concern may be valid in this case. Best wishes Mark > >> Otherwise this looks good to me (but I am not that familiar with lisp >> error handling) >> >> Best wishes >> >> Mark >> >> >> >> >> >> >> > +(defun notmuch-version-mismatch-error (exit-status) >> > + "Signal a schema version mismatch error. >> > + >> > +EXIT-STATUS must be the exit status of the notmuch CLI command, >> > +and must have the value 20 or 21. This function will pop up an >> > +error buffer with a descriptive message and signal an error." >> > + (cond ((= exit-status 20) >> > + (notmuch-pop-up-error "Error: Version mismatch. >> > +Emacs requested an older output format than supported by the notmuch CLI. >> > +You may need to restart Emacs or upgrade your notmuch Emacs package.")) >> > + ((= exit-status 21) >> > + (notmuch-pop-up-error "Error: Version mismatch. >> > +Emacs requested a newer output format than supported by the notmuch CLI. >> > +You may need to restart Emacs or upgrade your notmuch package.")) >> > + (t >> > + (error "Bad exit status %d" exit-status))) >> > + (error "notmuch CLI version mismatch")) >> > + >> > ;; Compatibility functions for versions of emacs before emacs 23. >> > ;; >> > ;; Both functions here were copied from emacs 23 with the following >> > copyright: >> > diff --git a/emacs/notmuch.el b/emacs/notmuch.el >> > index f9454d8..e1f28ca 100644 >> > --- a/emacs/notmuch.el >> > +++ b/emacs/notmuch.el >> > @@ -644,6 +644,7 @@ of the result." >> >(exit-status (process-exit-status proc)) >> >(never-found-target-thread nil)) >> > (when (memq status '(exit signal)) >> > + (catch 'return >> >(kill-buffer (process-get proc 'parse-buf)) >> >(if (buffer-live-p buffer) >> >(with-current-buffer buffer >> > @@ -655,8 +656,16 @@ of the result." >> > (insert "Incomplete search results (search process was >> > killed).\n")) >> > (when (eq status 'exit) >> >(insert "End of search results.") >> > - (unless (= exit-status 0) >> > -(insert (format " (process returned %d)" exit-status))) >> > + (cond ((or (= exit-status 20) (= exit-status 21)) >> > + (kill-buffer) >> > + (condition-case err >> > + (notmuch-version-mismatch-error exit-status) >> > + ;; Strange things happen when you signal >> > + ;; an error from a sentinel. >> > + (error (throw 'return nil >> > +((/= exit-status 0) >> > + (insert (format " (process returned %d)" >> > +
[PATCH (draft)] contrib: pick: close message pane when quitting from show in the message pane
This is a way of trying to make sure notmuch-pick cleans up the split buffer after itself. --- Currently if the focus gets into the message pane and then the user quits from that pane the display stays split. This is an attempt to fix that. This seems to work but I don't know if there is a better solution. However, I would welcome any feedback on the user experience with this patch applied. Best wishes Mark contrib/notmuch-pick/notmuch-pick.el | 17 + 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/contrib/notmuch-pick/notmuch-pick.el b/contrib/notmuch-pick/notmuch-pick.el index 043e9e7..79ef319 100644 --- a/contrib/notmuch-pick/notmuch-pick.el +++ b/contrib/notmuch-pick/notmuch-pick.el @@ -160,6 +160,9 @@ (defvar notmuch-pick-message-window nil) (make-variable-buffer-local 'notmuch-pick-message-window) (put 'notmuch-pick-message-window 'permanent-local t) +(defvar notmuch-show-message-window nil) +(make-variable-buffer-local 'notmuch-show-message-window) +(put 'notmuch-show-message-window 'permanent-local t) (defvar notmuch-pick-message-buffer nil) (make-variable-buffer-local 'notmuch-pick-message-buffer-name) (put 'notmuch-pick-message-buffer-name 'permanent-local t) @@ -389,6 +392,16 @@ Does NOT change the database." (notmuch-prettify-subject (notmuch-search-find-subject))) (notmuch-pick-show-match-message-with-wait)) +;;over-ride this function to try and kill off message panes +(defun notmuch-kill-this-buffer () + "Kill the current buffer." + (interactive) + (let ((buffer (current-buffer))) +(when (and (window-live-p notmuch-show-message-window) +(eq (window-buffer notmuch-show-message-window) buffer)) + (delete-window notmuch-show-message-window)) +(kill-buffer buffer))) + (defun notmuch-pick-show-message () "Show the current message (in split-pane)." (interactive) @@ -406,6 +419,10 @@ Does NOT change the database." (let ((notmuch-show-indent-messages-width 0)) (setq current-prefix-arg '(4)) (setq buffer (notmuch-show id nil nil nil + ;; We need the let as notmuch-pick-message-window is buffer local. + (let ((window notmuch-pick-message-window)) + (with-current-buffer buffer + (setq notmuch-show-message-window window))) (notmuch-pick-tag-update-display (list "-unread")) (setq notmuch-pick-message-buffer buffer -- 1.7.9.1
Re: [PATCH 4/4] emacs: Add unit-tests for clickable tags
Hi I thought I had checked the test output but I am getting a failure: the last test in emacs-show is failing (test_begin_subtest "id buttonization") I think it is just saying your patch is working and making the tag inbox in the message line a button. Best wishes Mark On Thu, 13 Dec 2012, Damien Cassou wrote: > Signed-off-by: Damien Cassou > --- > test/emacs | 103 > > 1 file changed, 103 insertions(+) > > diff --git a/test/emacs b/test/emacs > index 5403930..af9d37c 100755 > --- a/test/emacs > +++ b/test/emacs > @@ -852,5 +852,108 @@ test_emacs "(let ((mm-text-html-renderer > test_expect_success "Rendering HTML mail with images" \ > 'cat OUTPUT && grep -q smiley OUTPUT' > > +test_begin_subtest "Extracting all tags from a thread" > +add_message \ > +'[subject]="Extracting all tags from a thread"' \ > +'[body]="body 1"' > +parent=${gen_msg_id} > +add_message \ > +'[subject]="Extracting all tags from a thread"' \ > +'[body]="body 2"' \ > +"[in-reply-to]=\<$parent\>" > +add_message \ > +'[subject]="Extracting all tags from a thread"' \ > +'[body]="body 3"' \ > +"[in-reply-to]=\<$parent\>" > +latest=${gen_msg_id} > +# Extract the thread-id from one of the emails > +thread_id=$(notmuch search --output=threads id:${latest}) > +echo THREAD ID: '"'$thread_id'"' > +# Add tag "mytagfoo" to one of the emails > +notmuch tag +mytagfoo id:${latest} > +test_emacs_expect_t \ > +"(notmuch-show \"${thread_id}\") > + (let ((output (notmuch-show-thread-tags)) > + (expected '(\"inbox\" \"mytagfoo\" \"unread\"))) > + (notmuch-test-expect-equal > + (sort output #'string<) > + (sort expected #'string<)))" > + > +test_begin_subtest "The tags appear in the header-line of notmuch-show" > +add_message \ > +'[subject]="foo bar"' \ > +'[body]="body 1"' > +latest=${gen_msg_id} > +# Add tag "mytagfoo" to one of the emails > +notmuch tag +mytagfoo id:${latest} > +# Extract the thread-id from one of the emails > +thread_id=$(notmuch search --output=threads id:${latest}) > +test_emacs_expect_t \ > +"(notmuch-show \"${thread_id}\") > + (if (string-match-p \"mytagfoo\" (format-mode-line header-line-format)) > + t > + \"The tag 'mytagfoo' was not in the header-line-format\")" > + > +test_begin_subtest "The tags appear in the header-line of notmuch-show even > after update" > +add_message \ > +'[subject]="foo bar"' \ > +'[body]="body 1"' > +latest=${gen_msg_id} > +# Extract the thread-id from one of the emails > +thread_id=$(notmuch search --output=threads id:${latest}) > +test_emacs_expect_t \ > +"(notmuch-show \"${thread_id}\") > + (if (string-match-p \"mytagfoo\" (format-mode-line header-line-format)) > + (error \"There is no reason for 'mytagfoo' to be there.\")) > + (notmuch-show-tag \"+mytagfoo\") > + (if (string-match-p \"mytagfoo\" (format-mode-line header-line-format)) > + t > + \"The tag 'mytagfoo' was not in the header-line-format\")" > + > +test_begin_subtest "The tags of notmuch-show emails are clickable" > +add_message \ > +'[subject]="foo bar"' \ > +'[body]="body 1"' > +latest=${gen_msg_id} > +# Add tag "mytagfoo" to one of the emails > +notmuch tag +mytagfoo id:${latest} > +# Extract the thread-id from one of the emails > +thread_id=$(notmuch search --output=threads id:${latest}) > +test_emacs_expect_t \ > +"(notmuch-show \"${thread_id}\") > +(goto-char (point-min)) > +(re-search-forward \"mytagfoo\") > +(backward-char) ;; to be 'in' the tag > +(unless (eq major-mode 'notmuch-show-mode) > + (error \"We must be in notmuch-show at this point but we are in %s.\" > major-mode)) > +(push-button) ;; simulate a press on the RET key > +(if (eq major-mode 'notmuch-search-mode) > +t > + (format \"We must be in notmuch-search at this point but we are in > %s.\" major-mode))" > + > +test_begin_subtest "The tags of notmuch-show emails are clickable even after > update" > +add_message \ > +'[subject]="foo bar"' \ > +'[body]="body 1"' > +latest=${gen_msg_id} > +# Extract the thread-id from one of the emails > +thread_id=$(notmuch search --output=threads id:${latest}) > +test_emacs_expect_t \ > +"(notmuch-show \"${thread_id}\") > +(goto-char (point-min)) > +(if (re-search-forward \"mytagfoo\" nil t) > + (error \"There is no reason for 'mytagfoo' to be there.\")) > +(notmuch-show-tag \"+mytagfoo\") > +(goto-char (point-min)) > +(unless (re-search-forward \"mytagfoo\" nil t) > + (error \"The tag 'mytagfoo' must have been there.\")) > +(backward-char) ;; to be 'in' the tag > +(unless (eq major-mode 'notmuch-show-mode) > + (error \"We must be in notmuch-show at this point but we are in %s.\" > major-mode)) > +(push-button) ;; simulate a press on the RET key > +(if (eq major-mode 'notmuch-se
gmail importer script
On Thu, Dec 13, 2012 at 03:28:30PM +0100, Jason A. Donenfeld wrote: > On Thu, Dec 13, 2012 at 3:19 PM, fREW Schmidt wrote: > >> Okay, I've updated it to dynamically find the All Mail folder. > > > > I can't seem to find it now, but I read that Gmail actually localizes > > the name of various folders, so I think All Mail will actually be > > called something else for non-english speakers. It might be a good > > idea for you to at least make it a config option. > > A) Why are you replying off list? > > B) Did you totally miss my message directly above yours where I wrote > "Okay, I've updated it to dynamically find the All Mail folder"? Right, I did see that and I did look at the code; all I'm saying is that Gmail may localize AllMail as I'm fairly sure they localize the other builtin labels (http://git.zx2c4.com/gmail-notmuch/tree/gmail-notmuch.py#n214) I could certainly be wrong though, I haven't looked at this at such a low level before. -- fREW Schmidt http://blog.afoolishmanifesto.com -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20121213/06c6ef37/attachment-0001.pgp>
[PATCH v2 5/5] emacs: show: set default show-all-multipart/alternatives to nil
Now that the invisibility display of parts is present we no longer need to force the display of all multipart/alternatives: users can toggle them for themselves when needed. --- emacs/notmuch-show.el |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 202258f..c43dd32 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -94,7 +94,7 @@ visible for any given message." :group 'notmuch-hooks) ;; Mostly useful for debugging. -(defcustom notmuch-show-all-multipart/alternative-parts t +(defcustom notmuch-show-all-multipart/alternative-parts nil "Should all parts of multipart/alternative parts be shown?" :type 'boolean :group 'notmuch-show) -- 1.7.9.1
[PATCH v2 4/5] emacs: wash: fix fake-diff part to include msg parameter
The fake-diff part from notmuch wash did not pass the msg parameter to notmuch-show-insert-bodypart. Previously this did not matter, but is now needed to get the overlays right for invisibility. --- emacs/notmuch-wash.el |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el index 7d003a2..b2affba 100644 --- a/emacs/notmuch-wash.el +++ b/emacs/notmuch-wash.el @@ -378,7 +378,7 @@ for error." (plist-get (plist-get msg :headers) :Subject (delete-region (point-min) (point-max)) - (notmuch-show-insert-bodypart nil part depth) + (notmuch-show-insert-bodypart msg part depth) ;; -- 1.7.9.1
[PATCH v2 3/5] emacs: show: add invisibility button action
This adds a button action to show hidden parts. In this version "t" toggles the visibility of a part. In addition "RET" on a non-shown part shows it. The button is used to hide parts when appropriate (eg text/html in multipart/alternative). --- emacs/notmuch-show.el | 36 ++-- 1 files changed, 34 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 3f2f277..202258f 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -478,6 +478,7 @@ message at DEPTH in the current thread." (define-key map "v" 'notmuch-show-part-button-view) (define-key map "o" 'notmuch-show-part-button-interactively-view) (define-key map "|" 'notmuch-show-part-button-pipe) +(define-key map "t" 'notmuch-show-toggle-invisible-part-action) map) "Submap for button commands") (fset 'notmuch-show-part-button-map notmuch-show-part-button-map) @@ -554,6 +555,28 @@ message at DEPTH in the current thread." (let ((handle (mm-make-handle (current-buffer) (list content-type (mm-pipe-part handle +;; This is taken from notmuch-wash: maybe it should be unified? +(defun notmuch-show-toggle-invisible-part-action (&optional button) + (interactive) + (let* ((button (or button (button-at (point +(overlay (button-get button 'overlay)) +(invis-spec (button-get button 'invisibility-spec)) +(show (invisible-p invis-spec))) +(when overlay + (if show + (remove-from-invisibility-spec invis-spec) + (add-to-invisibility-spec invis-spec)) + (let* ((new-start (button-start button)) +(button-label (button-get button :base-label)) +(old-point (point)) +(inhibit-read-only t)) + (goto-char new-start) + (insert "[ " button-label (if show " ]" " (hidden) ]")) + (let ((old-end (button-end button))) + (move-overlay button new-start (point)) + (delete-region (point) old-end)) + (goto-char (min old-point (1- (button-end button + (defun notmuch-show-multipart/*-to-list (part) (mapcar (lambda (inner-part) (plist-get inner-part :content-type)) (plist-get part :content))) @@ -863,7 +886,13 @@ message at DEPTH in the current thread." (cons invis-spec (overlay-get inner 'invisible) (button-put button 'invisibility-spec invis-spec) - (button-put button 'overlay overlay) + (button-put button 'overlay overlay)) + + ;; We toggle the button for hidden parts as that gets the + ;; button label right. + (save-excursion + (when hide + (notmuch-show-toggle-invisible-part-action button)) (defun notmuch-show-insert-bodypart (msg part depth &optional hide) "Insert the body part PART at depth DEPTH in the current thread. @@ -1992,7 +2021,10 @@ the user (see `notmuch-show-stash-mlarchive-link-alist')." (defun notmuch-show-part-button-default (&optional button) (interactive) - (notmuch-show-part-button-internal button notmuch-show-part-button-default-action)) + (let ((button (or button (button-at (point) +(if (button-get button 'invisibility-spec) + (notmuch-show-toggle-invisible-part-action button) + (notmuch-show-part-button-internal button notmuch-show-part-button-default-action (defun notmuch-show-part-button-save (&optional button) (interactive) -- 1.7.9.1
[PATCH v2 2/5] emacs: show: add overlays for each part
This makes notmuch-show-insert-bodypart add an overlay for any non-trivial part with a button header (currently the first text/plain part does not have a button). At this point the overlay is available to the button but there is no action using it yet. In addition the argument HIDE is passed down to notmuch-show-insert-part-overlays to request that the part be hidden by default but this is not acted on yet. --- emacs/notmuch-show.el | 61 + 1 files changed, 46 insertions(+), 15 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 06f7ca5..3f2f277 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -567,11 +567,10 @@ message at DEPTH in the current thread." ;; but it's not clear that this is the wrong thing to do - which ;; should be chosen if there are more than one that match? (mapc (lambda (inner-part) - (let ((inner-type (plist-get inner-part :content-type))) - (if (or notmuch-show-all-multipart/alternative-parts - (string= chosen-type inner-type)) - (notmuch-show-insert-bodypart msg inner-part depth) - (notmuch-show-insert-part-header (plist-get inner-part :id) inner-type inner-type nil " (not shown)" + (let* ((inner-type (plist-get inner-part :content-type)) + (hide (not (or notmuch-show-all-multipart/alternative-parts + (string= chosen-type inner-type) + (notmuch-show-insert-bodypart msg inner-part depth hide))) inner-parts) (when notmuch-show-indent-multipart @@ -839,17 +838,49 @@ message at DEPTH in the current thread." (setq handlers (cdr handlers t) -(defun notmuch-show-insert-bodypart (msg part depth) - "Insert the body part PART at depth DEPTH in the current thread." +(defun notmuch-show-insert-part-overlays (msg beg end hide) + "Add an overlay to the part between BEG and END" + (let* ((button (button-at beg)) +(part-beg (and button (1+ (button-end button) + +;; If the part contains no text we do not make it toggleable. +(when (and button (/= part-beg end)) + (let ((base-label (button-get button :base-label)) + (overlay (make-overlay part-beg end)) + (message-invis-spec (plist-get msg :message-invis-spec)) + (invis-spec (make-symbol "notmuch-part-region"))) + + (overlay-put overlay 'invisible (list invis-spec message-invis-spec)) + (overlay-put overlay 'priority 10) + (overlay-put overlay 'type "part") + ;; Now we have to add invis-spec to every overlay this + ;; overlay contains, otherwise these inner overlays will + ;; override this one. + (dolist (inner (overlays-in part-beg end)) + (when (and (>= (overlay-start inner) part-beg) + (<= (overlay-end inner) end)) + (overlay-put inner 'invisible + (cons invis-spec (overlay-get inner 'invisible) + + (button-put button 'invisibility-spec invis-spec) + (button-put button 'overlay overlay) + +(defun notmuch-show-insert-bodypart (msg part depth &optional hide) + "Insert the body part PART at depth DEPTH in the current thread. + +If HIDE is non-nil then initially hide this part." (let ((content-type (downcase (plist-get part :content-type))) - (nth (plist-get part :id))) -(notmuch-show-insert-bodypart-internal msg part content-type nth depth content-type)) - ;; Some of the body part handlers leave point somewhere up in the - ;; part, so we make sure that we're down at the end. - (goto-char (point-max)) - ;; Ensure that the part ends with a carriage return. - (unless (bolp) -(insert "\n"))) + (nth (plist-get part :id)) + (beg (point))) + +(notmuch-show-insert-bodypart-internal msg part content-type nth depth content-type) +;; Some of the body part handlers leave point somewhere up in the +;; part, so we make sure that we're down at the end. +(goto-char (point-max)) +;; Ensure that the part ends with a carriage return. +(unless (bolp) + (insert "\n")) +(notmuch-show-insert-part-overlays msg beg (point) hide))) (defun notmuch-show-insert-body (msg body depth) "Insert the body BODY at depth DEPTH in the current thread." -- 1.7.9.1
[PATCH v2 1/5] emacs: show: modify insert-part-header to save the button text
This just make notmuch-show-insert-part-header save the basic button text for parts as an attribute. This makes it simpler for the button action (added in a later patch) to reword the label as appropriate (eg append "(not shown)" or not as appropriate). --- emacs/notmuch-show.el | 18 +- 1 files changed, 9 insertions(+), 9 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index d7fa10e..06f7ca5 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -483,17 +483,17 @@ message at DEPTH in the current thread." (fset 'notmuch-show-part-button-map notmuch-show-part-button-map) (defun notmuch-show-insert-part-header (nth content-type declared-type &optional name comment) - (let ((button)) + (let ((button) + (base-label (concat (when name (concat name ": ")) + declared-type + (unless (string-equal declared-type content-type) + (concat " (as " content-type ")")) + comment))) + (setq button (insert-button - (concat "[ " - (if name (concat name ": ") "") - declared-type - (if (not (string-equal declared-type content-type)) - (concat " (as " content-type ")") -"") - (or comment "") - " ]") + (concat "[ " base-label " ]") + :base-label base-label :type 'notmuch-show-part-button-type :notmuch-part nth :notmuch-filename name -- 1.7.9.1
[PATCH v2 0/5] Use invisibility to toggle display of all parts including multipart
This is version 2 of the patch series (version 1 at id:1354663662-20524-1-git-send-email-markwalters1009 at gmail.com) Almost all of the changes and fixes are in response to Austin's review. I have changed things as he suggested. There are two small extra tiny patches in this version: I set the default value of notmuch-show-all-multipart/alternative-parts to nil. The second is to fix a bug reported by Jani: that fake-patch parts (as provided by notmuch-wash) did not get hidden when the whole message was hidden. This was due to notmuch-wash-convert-inline-patch-to-part not passing a msg on down to notmuch-show-insert-bodypart. Previously this did not matter but with with this series msg is needed to construct the correct overlays. Best wishes Mark Mark Walters (5): emacs: show: modify insert-part-header to save the button text emacs: show: add overlays for each part emacs: show: add invisibility button action emacs: wash: fix fake-diff part to include msg parameter emacs: show: set default show-all-multipart/alternatives to nil emacs/notmuch-show.el | 115 ++--- emacs/notmuch-wash.el |2 +- 2 files changed, 90 insertions(+), 27 deletions(-) -- 1.7.9.1
[PATCH 3/3] emacs: show: add invisibility button action
On Tue, 11 Dec 2012, Austin Clements wrote: > On Tue, 04 Dec 2012, Mark Walters wrote: >> This adds a button action to show hidden parts. In this version "t" >> toggles the visibility of a part. In addition "RET" on a non-shown >> part shows it. >> >> The button is used to hide parts when appropriate (eg text/html in >> multipart/alternative). >> --- >> emacs/notmuch-show.el | 36 +++- >> 1 files changed, 35 insertions(+), 1 deletions(-) >> >> diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el >> index 3215ebc..a4daff8 100644 >> --- a/emacs/notmuch-show.el >> +++ b/emacs/notmuch-show.el >> @@ -478,6 +478,7 @@ message at DEPTH in the current thread." >> (define-key map "v" 'notmuch-show-part-button-view) >> (define-key map "o" 'notmuch-show-part-button-interactively-view) >> (define-key map "|" 'notmuch-show-part-button-pipe) >> +(define-key map "t" 'notmuch-show-toggle-invisible-part-action) >> map) >>"Submap for button commands") >> (fset 'notmuch-show-part-button-map notmuch-show-part-button-map) >> @@ -555,6 +556,31 @@ message at DEPTH in the current thread." >> (let ((handle (mm-make-handle (current-buffer) (list content-type >>(mm-pipe-part handle >> >> +;; This is taken from notmuch-wash: maybe it should be unified? >> +(defun notmuch-show-toggle-invisible-part-action (&optional button >> no-redisplay) >> + (interactive) >> + (let* ((button (or button (button-at (point >> + (overlay (button-get button 'overlay)) >> + (invis-spec (button-get button 'invisibility-spec)) >> + (show (invisible-p invis-spec))) >> +(when overlay >> + (if show >> + (remove-from-invisibility-spec invis-spec) >> +(add-to-invisibility-spec invis-spec)) >> + (let* ((new-start (button-start button)) >> + (button-label (button-get button :base-label)) >> + (old-point (point)) >> + (inhibit-read-only t)) >> +(goto-char new-start) >> +(insert "[ " button-label (if show " ]" " (not shown) ]")) > > s/not shown/hidden/? Done > >> +(let ((old-end (button-end button))) >> + (move-overlay button new-start (point)) >> + (delete-region (point) old-end)) >> +(goto-char (min old-point (1- (button-end button) This is where point gets left by this toggle button function: I don't know if it should move point. Mostly it only matters if the user uses the mouse (as otherwise point is on the button). >> + (unless no-redisplay >> +(force-window-update) >> +(redisplay t) > > Is the t argument necessary? Actually, are either (force-window-update) > or (redisplay) necessary? None of this seems needed: I had just copied it from notmuch-wash. Best wishes Mark >> + >> (defun notmuch-show-multipart/*-to-list (part) >>(mapcar (lambda (inner-part) (plist-get inner-part :content-type)) >>(plist-get part :content))) >> @@ -867,6 +893,11 @@ message at DEPTH in the current thread." >> >> (button-put button 'invisibility-spec invis-spec) >> (button-put button 'overlay overlay)) >> + >> + ;; We toggle the button for hidden parts as that gets the >> + ;; button label right. >> + (when not-shown >> +(notmuch-show-toggle-invisible-part-action button t)) >>(goto-char (point-max) >> >> (defun notmuch-show-insert-bodypart (msg part depth &optional not-shown) >> @@ -1996,7 +2027,10 @@ the user (see >> `notmuch-show-stash-mlarchive-link-alist')." >> >> (defun notmuch-show-part-button-default (&optional button) >>(interactive) >> - (notmuch-show-part-button-internal button >> notmuch-show-part-button-default-action)) >> + (let ((button (or button (button-at (point) >> +(if (invisible-p (button-get button 'invisibility-spec)) >> +(notmuch-show-toggle-invisible-part-action button) >> + (notmuch-show-part-button-internal button >> notmuch-show-part-button-default-action >> >> (defun notmuch-show-part-button-save (&optional button) >>(interactive) >> -- >> 1.7.9.1
[PATCH 2/3] emacs: show: add overlays for each part
Hi Many thanks for the review: I will post a new version shortly. Some comments inline below: On Tue, 11 Dec 2012, Austin Clements wrote: > On Tue, 04 Dec 2012, Mark Walters wrote: >> This make notmuch-show-insert-bodypart add an overlay for any > > s/make/makes/ > >> non-trivial part with a button header (currently the first text/plain >> part does not have a button). At this point the overlay is available >> to the button but there is no action using it yet. >> >> In addition a not-shown variable which is used to request the part be > > not-shown is really an argument (I found this confusing). > >> hidden by default down to the overlay but this is not acted on yet. >> --- >> emacs/notmuch-show.el | 62 >> +--- >> 1 files changed, 48 insertions(+), 14 deletions(-) >> >> diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el >> index f8ce037..3215ebc 100644 >> --- a/emacs/notmuch-show.el >> +++ b/emacs/notmuch-show.el >> @@ -569,10 +569,9 @@ message at DEPTH in the current thread." >> ;; should be chosen if there are more than one that match? >> (mapc (lambda (inner-part) >> (let ((inner-type (plist-get inner-part :content-type))) >> - (if (or notmuch-show-all-multipart/alternative-parts >> - (string= chosen-type inner-type)) >> - (notmuch-show-insert-bodypart msg inner-part depth) >> -(notmuch-show-insert-part-header (plist-get inner-part :id) >> inner-type inner-type nil " (not shown)" >> + (notmuch-show-insert-bodypart msg inner-part depth >> +(not (or >> notmuch-show-all-multipart/alternative-parts > > Since notmuch-show-all-multipart/alternative-parts was basically a hack > around our poor multipart/alternative support, I think this series (or a > follow up patch) should change its default to nil or even eliminate it > entirely. I have added a patch at the end setting this to nil by default. >> + (string= chosen-type >> inner-type)) > > You could let-bind the (not (or ..)) to some variable ("hide" perhaps) > in the let above to avoid this crazy line length. > >>inner-parts) >> >> (when notmuch-show-indent-multipart >> @@ -840,17 +839,52 @@ message at DEPTH in the current thread." >>(setq handlers (cdr handlers >>t) >> >> -(defun notmuch-show-insert-bodypart (msg part depth) >> - "Insert the body part PART at depth DEPTH in the current thread." >> +(defun notmuch-show-insert-part-overlays (msg beg end not-shown) > > s/not-shown/hide/? Or hidden? > >> + "Add an overlay to the part between BEG and END" >> + (let* ((button (button-at beg)) >> + (part-beg (and button (1+ (button-end button) >> + >> +;; If the part contains no text we do not make it toggleable. >> +(unless (or (not button) (eq part-beg end)) > > (when (and button (/= part-beg end)) ...) ? > >> + (let ((base-label (button-get button :base-label)) >> +(overlay (make-overlay part-beg end)) >> +(message-invis-spec (plist-get msg :message-invis-spec)) >> +(invis-spec (make-symbol "notmuch-part-region"))) >> + >> +(overlay-put overlay 'invisible (list invis-spec message-invis-spec)) > > Non-trivial buffer invisibility specs are really bad for performance > (Emacs' renderer does the obvious O(n^2) thing when rendering a buffer > with an invisibility spec). Unfortunately, because of notmuch-wash and > the way overlays with trivial 'invisible properties combine with > overlays with list-type 'invisible properties combine, I don't think it > can be avoided. But if we get rid of buffer invisibility specs from > notmuch-wash, this code can also get much simpler. How do you plan to get rid of the invisibility properties from notmuch wash? >> +(overlay-put overlay 'isearch-open-invisible >> #'notmuch-wash-region-isearch-show) > > This will leave the "(not shown)" in the part header if isearch unfolds > the part. > > Do we even want isearch to unfold parts? It's not clear we do for > multipart/alternative. If we do, probably the right thing is something > like I don't think we want to search hidden bodyparts so I just deleted this line. > > (overlay-put overlay 'notmuch-show-part-button button) > (overlay-put overlay 'isearch-open-invisible #'notmuch-show-part-isearch-open) > > (defun notmuch-show-part-isearch-open (overlay) > (notmuch-show-toggle-invisible-part-action >(overlay-get overlay 'notmuch-show-part-button))) > >> +(overlay-put overlay 'priority 10) >> +(overlay-put overlay 'type "part") >> +;; Now we have to add invis-spec to every overlay this >> +;; overlay contains, otherwise these inner overlays will >> +;; override this one. > > Interesting. In the simple case of using nil or t for 'invisible, the > specs do combine as one would expect, but you're right that, with a > non-trivial i
Re: gmail importer script
Sorry, I'm misusing this thread as a bugtracker.. Traceback (most recent call last):4| | 10% ETA: 1:24:41 3.54 emails/s File "./gmail-notmuch.py", line 251, in main() File "./gmail-notmuch.py", line 89, in main download_new_messages(imap, database, new_messages, destination) File "./gmail-notmuch.py", line 208, in download_new_messages tag_message(database, dest, labels) File "./gmail-notmuch.py", line 168, in tag_message raise e notmuch.errors.FileNotEmailError best, /p ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v5] emacs: display tags in notmuch-show with links
This version looks good to me: +1 Best wishes Mark On Thu, 13 Dec 2012, Damien Cassou wrote: > This patch obsoletes: > id:1355216437-21109-1-git-send-email-damien.cas...@gmail.com > > [PATCH 1/4] emacs: Add a thread's tags to notmuch-show header-line > [PATCH 2/4] emacs: Make tags in notmuch-show header-line clickable > [PATCH 3/4] emacs: Make all tags in `notmuch-show' clickable > [PATCH 4/4] emacs: Add unit-tests for clickable tags > > These patches make clickable all tags that appear in notmuch-show > buffers. Each tag is a link to open a new notmuch-search buffer for > this tag. Additionally, the buffer's header-line now shows the > thread's tags (clickable only if the `header-button' library is loaded > or loadable). > > These patches are the first of an upcoming series whose goal is to > integrate notmuch-labeler into notmuch. See the following for more > details: https://github.com/DamienCassou/notmuch-labeler > > With respect to v4, I took care of the comments you made: > > - integration of Mark Walters' patch to avoid duplicate update of the > header-line tags > - implementation of Mark Walters' comment on sorting header-line tags > ___ > notmuch mailing list > notmuch@notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
gmail importer script
On Thu, Dec 13, 2012 at 03:30:19PM +0100, Jason A. Donenfeld wrote: > Please don't reply offlist. This is message #2 that's been sent offlist. Oh I'm sorry, that was an accident. > On Thu, Dec 13, 2012 at 3:22 PM, fREW Schmidt > > One thing you might want to try is to only open the notmuch index for > > writing at a specified sync time. > > How do I do this? What's the python function? I couldn't find > anything. Would be interested in doing this though if it exists. I just mean a general programming technique. As you get information about tags you hold them in memory and then sync it later and clear your memory. > > Also I was going to say you might want to catch SIGINT like > > The library already does this. -- fREW Schmidt http://blog.afoolishmanifesto.com -- next part -- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: not available URL: <http://notmuchmail.org/pipermail/notmuch/attachments/20121213/f29b8470/attachment.pgp>
Re: notmuch python bindings corrupt db index (was: gmail importer script)
Quoting Jason A. Donenfeld (2012-12-13 14:32:53) > On Wed, Dec 12, 2012 at 9:49 PM, Austin Clements wrote: > > There should be no way to corrupt the database at this level through > > the Xapian API, which means nothing libnotmuch can do (much less users > > of libnotmuch) should be able to corrupt the database. If you can > > reproduce the problem, it's probably a serious bug in Xapian, but it > > could also have been a file system bug or even random file system > > corruption. > > Well that's... troubling. > > Patrick: could you please backup and try to reproduce? Otherwise I'll > assume this was a one-off situation. I tried it again, concurrently triggered some modifications and killed the process afer a while. (my modifications were not flushed during the run of your script as the index was locked) The index seems to be OK. So I'm afraid I cannot reproduce this reliably. /p ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: gmail importer script
\AllMail is the unlocalized generic version that maps to the localized version, as are all the other back slash situations. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: gmail importer script
On Thu, Dec 13, 2012 at 03:28:30PM +0100, Jason A. Donenfeld wrote: > On Thu, Dec 13, 2012 at 3:19 PM, fREW Schmidt wrote: > >> Okay, I've updated it to dynamically find the All Mail folder. > > > > I can't seem to find it now, but I read that Gmail actually localizes > > the name of various folders, so I think All Mail will actually be > > called something else for non-english speakers. It might be a good > > idea for you to at least make it a config option. > > A) Why are you replying off list? > > B) Did you totally miss my message directly above yours where I wrote > "Okay, I've updated it to dynamically find the All Mail folder"? Right, I did see that and I did look at the code; all I'm saying is that Gmail may localize AllMail as I'm fairly sure they localize the other builtin labels (http://git.zx2c4.com/gmail-notmuch/tree/gmail-notmuch.py#n214) I could certainly be wrong though, I haven't looked at this at such a low level before. -- fREW Schmidt http://blog.afoolishmanifesto.com pgpqDMiLkFVHO.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: gmail importer script
On Thu, Dec 13, 2012 at 3:35 PM, fREW Schmidt wrote: > I just mean a general programming technique. As you get information > about tags you hold them in memory and then sync it later and clear > your memory. Oh, yea, that's a great idea. I'll play with that. Good thinking. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: gmail importer script
On Thu, Dec 13, 2012 at 03:30:19PM +0100, Jason A. Donenfeld wrote: > Please don't reply offlist. This is message #2 that's been sent offlist. Oh I'm sorry, that was an accident. > On Thu, Dec 13, 2012 at 3:22 PM, fREW Schmidt > > One thing you might want to try is to only open the notmuch index for > > writing at a specified sync time. > > How do I do this? What's the python function? I couldn't find > anything. Would be interested in doing this though if it exists. I just mean a general programming technique. As you get information about tags you hold them in memory and then sync it later and clear your memory. > > Also I was going to say you might want to catch SIGINT like > > The library already does this. -- fREW Schmidt http://blog.afoolishmanifesto.com pgpYfiABySGYw.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: notmuch python bindings corrupt db index (was: gmail importer script)
On Wed, Dec 12, 2012 at 10:26 PM, David Bremner wrote: > > One thing that Olly Betts mentioned is that there is a recently fixed > bug in xapian with respect to multiple threads in the same process The script's actually single threaded. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: notmuch python bindings corrupt db index (was: gmail importer script)
On Wed, Dec 12, 2012 at 9:49 PM, Austin Clements wrote: > There should be no way to corrupt the database at this level through > the Xapian API, which means nothing libnotmuch can do (much less users > of libnotmuch) should be able to corrupt the database. If you can > reproduce the problem, it's probably a serious bug in Xapian, but it > could also have been a file system bug or even random file system > corruption. Well that's... troubling. Patrick: could you please backup and try to reproduce? Otherwise I'll assume this was a one-off situation. Austin-- think you could do a quick review of the script to double check and confirm I'm not doing anything nefarious? http://git.zx2c4.com/gmail-notmuch/tree/gmail-notmuch.py ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: gmail importer script
Please don't reply offlist. This is message #2 that's been sent offlist. On Thu, Dec 13, 2012 at 3:22 PM, fREW Schmidt > One thing you might want to try is to only open the notmuch index for > writing at a specified sync time. How do I do this? What's the python function? I couldn't find anything. Would be interested in doing this though if it exists. > Also I was going to say you might want to catch SIGINT like The library already does this. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v4 0/3] indicate length of omitted body content
On Thu, 13 Dec 2012 12:52:50 +, Mark Walters wrote: > > Sorry I am confused: isn't test/sexp already in master? You're right, somehow I missed it. Peter ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 4/4] emacs: Add unit-tests for clickable tags
Signed-off-by: Damien Cassou --- test/emacs | 103 1 file changed, 103 insertions(+) diff --git a/test/emacs b/test/emacs index 5403930..af9d37c 100755 --- a/test/emacs +++ b/test/emacs @@ -852,5 +852,108 @@ test_emacs "(let ((mm-text-html-renderer test_expect_success "Rendering HTML mail with images" \ 'cat OUTPUT && grep -q smiley OUTPUT' +test_begin_subtest "Extracting all tags from a thread" +add_message \ +'[subject]="Extracting all tags from a thread"' \ +'[body]="body 1"' +parent=${gen_msg_id} +add_message \ +'[subject]="Extracting all tags from a thread"' \ +'[body]="body 2"' \ +"[in-reply-to]=\<$parent\>" +add_message \ +'[subject]="Extracting all tags from a thread"' \ +'[body]="body 3"' \ +"[in-reply-to]=\<$parent\>" +latest=${gen_msg_id} +# Extract the thread-id from one of the emails +thread_id=$(notmuch search --output=threads id:${latest}) +echo THREAD ID: '"'$thread_id'"' +# Add tag "mytagfoo" to one of the emails +notmuch tag +mytagfoo id:${latest} +test_emacs_expect_t \ +"(notmuch-show \"${thread_id}\") + (let ((output (notmuch-show-thread-tags)) + (expected '(\"inbox\" \"mytagfoo\" \"unread\"))) + (notmuch-test-expect-equal + (sort output #'string<) + (sort expected #'string<)))" + +test_begin_subtest "The tags appear in the header-line of notmuch-show" +add_message \ +'[subject]="foo bar"' \ +'[body]="body 1"' +latest=${gen_msg_id} +# Add tag "mytagfoo" to one of the emails +notmuch tag +mytagfoo id:${latest} +# Extract the thread-id from one of the emails +thread_id=$(notmuch search --output=threads id:${latest}) +test_emacs_expect_t \ +"(notmuch-show \"${thread_id}\") + (if (string-match-p \"mytagfoo\" (format-mode-line header-line-format)) + t + \"The tag 'mytagfoo' was not in the header-line-format\")" + +test_begin_subtest "The tags appear in the header-line of notmuch-show even after update" +add_message \ +'[subject]="foo bar"' \ +'[body]="body 1"' +latest=${gen_msg_id} +# Extract the thread-id from one of the emails +thread_id=$(notmuch search --output=threads id:${latest}) +test_emacs_expect_t \ +"(notmuch-show \"${thread_id}\") + (if (string-match-p \"mytagfoo\" (format-mode-line header-line-format)) + (error \"There is no reason for 'mytagfoo' to be there.\")) + (notmuch-show-tag \"+mytagfoo\") + (if (string-match-p \"mytagfoo\" (format-mode-line header-line-format)) + t + \"The tag 'mytagfoo' was not in the header-line-format\")" + +test_begin_subtest "The tags of notmuch-show emails are clickable" +add_message \ +'[subject]="foo bar"' \ +'[body]="body 1"' +latest=${gen_msg_id} +# Add tag "mytagfoo" to one of the emails +notmuch tag +mytagfoo id:${latest} +# Extract the thread-id from one of the emails +thread_id=$(notmuch search --output=threads id:${latest}) +test_emacs_expect_t \ +"(notmuch-show \"${thread_id}\") +(goto-char (point-min)) +(re-search-forward \"mytagfoo\") +(backward-char) ;; to be 'in' the tag +(unless (eq major-mode 'notmuch-show-mode) + (error \"We must be in notmuch-show at this point but we are in %s.\" major-mode)) +(push-button) ;; simulate a press on the RET key +(if (eq major-mode 'notmuch-search-mode) +t + (format \"We must be in notmuch-search at this point but we are in %s.\" major-mode))" + +test_begin_subtest "The tags of notmuch-show emails are clickable even after update" +add_message \ +'[subject]="foo bar"' \ +'[body]="body 1"' +latest=${gen_msg_id} +# Extract the thread-id from one of the emails +thread_id=$(notmuch search --output=threads id:${latest}) +test_emacs_expect_t \ +"(notmuch-show \"${thread_id}\") +(goto-char (point-min)) +(if (re-search-forward \"mytagfoo\" nil t) + (error \"There is no reason for 'mytagfoo' to be there.\")) +(notmuch-show-tag \"+mytagfoo\") +(goto-char (point-min)) +(unless (re-search-forward \"mytagfoo\" nil t) + (error \"The tag 'mytagfoo' must have been there.\")) +(backward-char) ;; to be 'in' the tag +(unless (eq major-mode 'notmuch-show-mode) + (error \"We must be in notmuch-show at this point but we are in %s.\" major-mode)) +(push-button) ;; simulate a press on the RET key +(if (eq major-mode 'notmuch-search-mode) +t + (format \"We must be in notmuch-search at this point but we are in %s.\" major-mode))" + test_done -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 3/4] emacs: Make all tags in `notmuch-show' clickable
Signed-off-by: Damien Cassou --- emacs/notmuch-show.el | 15 +++ emacs/notmuch-tagger.el | 33 + 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 9c5a85e..8c07a00 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -362,10 +362,8 @@ operation on the contents of the current buffer." (goto-char (notmuch-show-message-top)) (if (re-search-forward "(\\([^()]*\\))$" (line-end-position) t) (let ((inhibit-read-only t)) - (replace-match (concat "(" -(propertize (mapconcat 'identity tags " ") -'face 'notmuch-tag-face) -")") + (replace-match (propertize (notmuch-tagger-format-tags tags) +'face 'notmuch-tag-face) (unless no-headerline-update (notmuch-show-update-header-line))) @@ -443,10 +441,11 @@ message at DEPTH in the current thread." (notmuch-show-clean-address (plist-get headers :From)) " (" date - ") (" - (propertize (mapconcat 'identity tags " ") - 'face 'notmuch-tag-face) - ")\n") + ") " + (propertize +(notmuch-tagger-format-tags tags) +'face 'notmuch-tag-face) + "\n") (overlay-put (make-overlay start (point)) 'face 'notmuch-message-summary-face))) (defun notmuch-show-insert-header (header header-value) diff --git a/emacs/notmuch-tagger.el b/emacs/notmuch-tagger.el index 38b858a..35b81ca 100644 --- a/emacs/notmuch-tagger.el +++ b/emacs/notmuch-tagger.el @@ -44,12 +44,21 @@ test if the library is present before calling this function." (let ((tag (header-button-get button 'notmuch-tagger-tag))) (notmuch-tagger-goto-target tag))) +(defun notmuch-tagger-body-button-action (button) + "Open `notmuch-search' for the tag referenced by BUTTON." + (let ((tag (button-get button 'notmuch-tagger-tag))) +(notmuch-tagger-goto-target tag))) + (eval-after-load "header-button" '(define-button-type 'notmuch-tagger-header-button-type 'supertype 'header 'action#'notmuch-tagger-header-button-action 'follow-link t)) +(define-button-type 'notmuch-tagger-body-button-type + 'action#'notmuch-tagger-body-button-action + 'follow-link t) + (defun notmuch-tagger-really-make-header-link (tag) "Return a property list that presents a link to TAG. @@ -73,6 +82,20 @@ if not." (notmuch-tagger-really-make-header-link tag) tag)) +(defun notmuch-tagger-make-body-link (tag) + "Return a property list that presents a link to TAG. +The returned property list will not work in the header-line. For +a link that works on the header-line, prefer +`notmuch-tagger-make-header-link'." + (let ((button (copy-sequence tag))) +(make-text-button + button nil + 'type 'notmuch-tagger-body-button-type + 'notmuch-tagger-tag tag + 'skip t ;; don't stop when using TAB + 'help-echo (format "%s: Search other messages like this" tag)) +button)) + (defun notmuch-tagger-format-tags-header-line (tags) "Format TAGS as a `mode-line-format' template. The result is suitable for inclusion in `header-line-format'." @@ -83,5 +106,15 @@ The result is suitable for inclusion in `header-line-format'." " ") ")")) +(defun notmuch-tagger-format-tags (tags) + "Format TAGS as a string suitable for insertion in a buffer. +If the result of this function is to be used within the +header-line, prefer `notmuch-tagger-format-tags-header-line' +instead of this function." + (concat + "(" + (mapconcat #'notmuch-tagger-make-body-link tags " ") + ")")) + (provide 'notmuch-tagger) ;;; notmuch-tagger.el ends here -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 1/4] emacs: Add a thread's tags to notmuch-show header-line
Signed-off-by: Damien Cassou --- emacs/notmuch-lib.el| 11 +-- emacs/notmuch-show.el | 37 + emacs/notmuch-tagger.el | 35 +++ 3 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 emacs/notmuch-tagger.el diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 9c4ee71..3541bb7 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -603,8 +603,15 @@ left it." ;; Clear out what we've parsed (delete-region (point-min) (point - - +(defun notmuch-intersperse (list sep) + "Return a list with all elements of LIST separated by SEP." + (let ((first t) +(res nil)) +(dolist (elt list (nreverse res)) + (unless first +(push sep res)) + (setq first nil) + (push elt res (provide 'notmuch-lib) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 7d9f8a9..9c5a85e 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -36,6 +36,7 @@ (require 'notmuch-mua) (require 'notmuch-crypto) (require 'notmuch-print) +(require 'notmuch-tagger) (declare-function notmuch-call-notmuch-process "notmuch" (&rest args)) (declare-function notmuch-fontify-headers "notmuch" nil) @@ -355,7 +356,7 @@ operation on the contents of the current buffer." "Return a string comprised of `n' spaces." (make-string n ? )) -(defun notmuch-show-update-tags (tags) +(defun notmuch-show-update-tags (tags &optional no-headerline-update) "Update the displayed tags of the current message." (save-excursion (goto-char (notmuch-show-message-top)) @@ -364,7 +365,9 @@ operation on the contents of the current buffer." (replace-match (concat "(" (propertize (mapconcat 'identity tags " ") 'face 'notmuch-tag-face) -")")) +")") + (unless no-headerline-update +(notmuch-show-update-header-line))) (defun notmuch-clean-address (address) "Try to clean a single email ADDRESS for display. Return a cons @@ -1136,11 +1139,28 @@ function is used." (jit-lock-register #'notmuch-show-buttonise-links) - ;; Set the header line to the subject of the first message. - (setq header-line-format (notmuch-show-strip-re (notmuch-show-get-subject))) - + (notmuch-show-update-header-line) (run-hooks 'notmuch-show-hook +(defun notmuch-show-thread-tags () + "Return the list of tags for the current thread." + (let ((tags (list))) +(notmuch-show-mapc (lambda () +(mapcar (lambda (elt) + ;; Avoid adding duplicate tags + (add-to-list 'tags elt)) +(notmuch-show-get-tags +(sort tags 'string<))) + +(defun notmuch-show-update-header-line () + "Make the header-line show the thread's subject and tags." + (let ((thread-subject (notmuch-show-strip-re (notmuch-show-get-subject +(setq header-line-format + (list + thread-subject + " " + (notmuch-tagger-format-tags-header-line (notmuch-show-thread-tags)) + (defun notmuch-show-capture-state () "Capture the state of the current buffer. @@ -1443,10 +1463,10 @@ current thread." (defun notmuch-show-get-depth () (notmuch-show-get-prop :depth)) -(defun notmuch-show-set-tags (tags) +(defun notmuch-show-set-tags (tags &optional no-headerline-update) "Set the tags of the current message." (notmuch-show-set-prop :tags tags) - (notmuch-show-update-tags tags)) + (notmuch-show-update-tags tags no-headerline-update)) (defun notmuch-show-get-tags () "Return the tags of the current message." @@ -1760,7 +1780,8 @@ See `notmuch-tag' for information on the format of 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)) +(notmuch-show-set-tags new-tags t) + (notmuch-show-update-header-line)) (defun notmuch-show-add-tag () "Same as `notmuch-show-tag' but sets initial input to '+'." diff --git a/emacs/notmuch-tagger.el b/emacs/notmuch-tagger.el new file mode 100644 index 000..6fcebff --- /dev/null +++ b/emacs/notmuch-tagger.el @@ -0,0 +1,35 @@ +;; notmuch-tagger.el --- Library to improve the way tags are displayed +;; +;; Copyright © Damien Cassou +;; +;; 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 impl
[PATCH 2/4] emacs: Make tags in notmuch-show header-line clickable
Signed-off-by: Damien Cassou --- emacs/notmuch-tagger.el | 54 ++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch-tagger.el b/emacs/notmuch-tagger.el index 6fcebff..38b858a 100644 --- a/emacs/notmuch-tagger.el +++ b/emacs/notmuch-tagger.el @@ -23,12 +23,64 @@ ;;; Code: ;; +(defun notmuch-tagger-header-button-present-p () + "Check if `header-button' can be loaded or is already loaded. + +`header-button' is a third-party library which facilitates the +creation of links in emacs header-line. This function tries to +`require' `header-button' and returns nil if and only if this +fails." + (require 'header-button nil t)) + +(defun notmuch-tagger-goto-target (tag) + "Show a `notmuch-search' buffer for the TAG." + (notmuch-search (concat "tag:\"" tag "\""))) + +(defun notmuch-tagger-header-button-action (button) + "Open `notmuch-search' for the tag referenced by BUTTON. +This function depends on the presence of the `header-button' +library. Please call `notmuch-tagger-header-button-present-p' to +test if the library is present before calling this function." + (let ((tag (header-button-get button 'notmuch-tagger-tag))) +(notmuch-tagger-goto-target tag))) + +(eval-after-load "header-button" + '(define-button-type 'notmuch-tagger-header-button-type + 'supertype 'header + 'action#'notmuch-tagger-header-button-action + 'follow-link t)) + +(defun notmuch-tagger-really-make-header-link (tag) + "Return a property list that presents a link to TAG. + +The returned property list will only work in the header-line. +Additionally, this function depends on the presence of the +`header-button' library. Please call +`notmuch-tagger-header-button-present-p' to test if library is +present before calling this function." + (header-button-format +tag +:type 'notmuch-tagger-header-button-type +'notmuch-tagger-tag tag +'help-echo (format "%s: Search other messages like this" tag))) + +(defun notmuch-tagger-make-header-link (tag) + "Return a property list to present TAG as a link to search. + +This only works if `header-button' is loaded. Simply returns tag +if not." + (if (notmuch-tagger-header-button-present-p) + (notmuch-tagger-really-make-header-link tag) +tag)) + (defun notmuch-tagger-format-tags-header-line (tags) "Format TAGS as a `mode-line-format' template. The result is suitable for inclusion in `header-line-format'." (list "(" - (notmuch-intersperse tags " ") + (notmuch-intersperse +(mapcar #'notmuch-tagger-make-header-link tags) +" ") ")")) (provide 'notmuch-tagger) -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v5] emacs: display tags in notmuch-show with links
This patch obsoletes: id:1355216437-21109-1-git-send-email-damien.cas...@gmail.com [PATCH 1/4] emacs: Add a thread's tags to notmuch-show header-line [PATCH 2/4] emacs: Make tags in notmuch-show header-line clickable [PATCH 3/4] emacs: Make all tags in `notmuch-show' clickable [PATCH 4/4] emacs: Add unit-tests for clickable tags These patches make clickable all tags that appear in notmuch-show buffers. Each tag is a link to open a new notmuch-search buffer for this tag. Additionally, the buffer's header-line now shows the thread's tags (clickable only if the `header-button' library is loaded or loadable). These patches are the first of an upcoming series whose goal is to integrate notmuch-labeler into notmuch. See the following for more details: https://github.com/DamienCassou/notmuch-labeler With respect to v4, I took care of the comments you made: - integration of Mark Walters' patch to avoid duplicate update of the header-line tags - implementation of Mark Walters' comment on sorting header-line tags ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v4 0/3] indicate length of omitted body content
On Thu, 13 Dec 2012, Peter Wang wrote: > On Sun, 09 Dec 2012 19:21:18 +, Mark Walters > wrote: >> >> Hi (sorry Peter I had assumed git send-email would have cc'd you on my >> rebase earlier today) >> >> There was some discussion about this patch series on irc and the general >> view was favourable but that, for consistency, all omitted parts should >> received a content-length (including text/html). This is a little messy >> to code into the if else stuff: Jani suggested putting >> content-length/content-encoding into a small function. >> >> Anyway I had hope it was just a trivial rebase and could go in, but the >> above will take a bit longer to do neatly so I will leave it for now. > > Ok. To save any potential duplicated work: I've updated the patch here, > save for test/sexp. Waiting for that to be pushed before updating it. Sorry I am confused: isn't test/sexp already in master? Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v4 0/3] indicate length of omitted body content
On Sun, 09 Dec 2012 19:21:18 +, Mark Walters wrote: > > Hi (sorry Peter I had assumed git send-email would have cc'd you on my > rebase earlier today) > > There was some discussion about this patch series on irc and the general > view was favourable but that, for consistency, all omitted parts should > received a content-length (including text/html). This is a little messy > to code into the if else stuff: Jani suggested putting > content-length/content-encoding into a small function. > > Anyway I had hope it was just a trivial rebase and could go in, but the > above will take a bit longer to do neatly so I will leave it for now. Ok. To save any potential duplicated work: I've updated the patch here, save for test/sexp. Waiting for that to be pushed before updating it. Peter ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re:
Hi This is looking good: I have two comments the second of which is significant. The first is do you want to sort (alphabetically) the headerline tags? As it stands they are in the order they appear in the thread which is probably not what is wanted. The second is that there is a notmuch-show-tag-all functions to tag all messages in the thread. Your patch is quadratic for the update (as it calculates the list of thread tags once for each message). The attached patch would avoid this and doesn't look too bad. (Note I retained no-headerline-update as an optional argument in case there are out of tree callers, eg users' .emacs files) [Note this is not purely of academic interest: on my test large thread (178 messages) updating the display after tagging all messages took some seconds without my patch and almost no time with it.] Best wishes Mark >From ab15a4bdb50bcf6b2851806195bbe8bea3b099dc Mon Sep 17 00:00:00 2001 From: Mark Walters Date: Thu, 13 Dec 2012 11:23:09 + Subject: [PATCH] Avoid quadratic update --- emacs/notmuch-show.el | 12 +++- 1 files changed, 7 insertions(+), 5 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 93bce07..8dd6010 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -356,7 +356,7 @@ operation on the contents of the current buffer." "Return a string comprised of `n' spaces." (make-string n ? )) -(defun notmuch-show-update-tags (tags) +(defun notmuch-show-update-tags (tags &optional no-headerline-update) "Update the displayed tags of the current message." (save-excursion (goto-char (notmuch-show-message-top)) @@ -364,7 +364,8 @@ operation on the contents of the current buffer." (let ((inhibit-read-only t)) (replace-match (propertize (notmuch-tagger-format-tags tags) 'face 'notmuch-tag-face) - (notmuch-show-update-header-line)) + (unless no-headerline-update +(notmuch-show-update-header-line))) (defun notmuch-clean-address (address) "Try to clean a single email ADDRESS for display. Return a cons @@ -1461,10 +1462,10 @@ current thread." (defun notmuch-show-get-depth () (notmuch-show-get-prop :depth)) -(defun notmuch-show-set-tags (tags) +(defun notmuch-show-set-tags (tags &optional no-headerline-update) "Set the tags of the current message." (notmuch-show-set-prop :tags tags) - (notmuch-show-update-tags tags)) + (notmuch-show-update-tags tags no-headerline-update)) (defun notmuch-show-get-tags () "Return the tags of the current message." @@ -1778,7 +1779,8 @@ See `notmuch-tag' for information on the format of 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)) + (notmuch-show-set-tags new-tags t) + (notmuch-show-update-header-line)) (defun notmuch-show-add-tag () "Same as `notmuch-show-tag' but sets initial input to '+'." -- 1.7.9.1 On Tue, 11 Dec 2012, Damien Cassou wrote: > From: Damien Cassou > Subject: [PATCH v4] emacs: display tags in notmuch-show with links > In-Reply-To: > > This patch obsoletes: > id:1355149964-27905-1-git-send-email-damien.cas...@gmail.com > > [PATCH 1/4] emacs: Add a thread's tags to notmuch-show header-line > [PATCH 2/4] emacs: Make tags in notmuch-show header-line clickable > [PATCH 3/4] emacs: Make all tags in `notmuch-show' clickable > [PATCH 4/4] emacs: Add unit-tests for clickable tags > > These patches make clickable all tags that appear in notmuch-show > buffers. Each tag is a link to open a new notmuch-search buffer for > this tag. Additionally, the buffer's header-line now shows the > thread's tags (clickable only if the `header-button' library is loaded > or loadable). > > These patches are the first of an upcoming series whose goal is to > integrate notmuch-labeler into notmuch. See the following for more > details: https://github.com/DamienCassou/notmuch-labeler > > With respect to v3, I took care of the comments you made: > - the header-line now updates when tags are changed > - the tags in the body stays clickable when tags are changed > > Additionally, I added two unit tests to cover the above two comments > and fixed some others unit tests of mine. > ___ > notmuch mailing list > notmuch@notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 07/10] emacs: Use --use-schema for search
On Thu, 13 Dec 2012, Austin Clements wrote: > Quoth Mark Walters on Dec 08 at 8:48 am: >> On Sun, 02 Dec 2012, Austin Clements wrote: >> > We detect the special exit statuses and use these to produce specific >> > diagnostic messages. >> > --- >> > emacs/notmuch-lib.el | 32 >> > emacs/notmuch.el | 17 + >> > 2 files changed, 45 insertions(+), 4 deletions(-) >> > >> > diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el >> > index 9402456..49b0da6 100644 >> > --- a/emacs/notmuch-lib.el >> > +++ b/emacs/notmuch-lib.el >> > @@ -325,6 +325,38 @@ string), a property list of face attributes, or a >> > list of these." >> >(put-text-property pos next 'face (cons face cur)) >> >(setq pos next) >> > >> > +(defun notmuch-pop-up-error (msg) >> > + "Pop up an error buffer displaying MSG." >> > + >> > + (let ((buf (get-buffer-create "*Notmuch errors*"))) >> > +(with-current-buffer buf >> > + (view-mode) >> > + (let ((inhibit-read-only t)) >> > + (erase-buffer) >> > + (insert msg) >> > + (unless (bolp) >> > +(insert "\n")) >> > + (goto-char (point-min >> > +(pop-to-buffer buf))) >> >> I am not sure about the erase-buffer in the above: do we definitely want >> to remove all previous error information? For version mismatch possibly >> we do but in patch 9 it is done for all show command-line error returns. > > Why wouldn't we want to use a cleared buffer in all cases? > notmuch-pop-up-error is only ever used when a command terminates, so > there's no danger of us clearing errors that the user hasn't seen yet. Just to make sure I understand this: whenever an error occurs the error popup appears so we see the message. Then the next error can safely erase buffer before showing the new error message? >> Incidentally why does show always pop-up an error but search only for >> version-mismatches? > > Historical reasons, I suppose. I was maintaining the status quo for > search (which already had *some* error handling), but there was no > error-handling status quo for show. Probably search should be more > vocal when the command fails. Should notmuch-call-notmuch-process also be switched to this framework? In particular that also puts errors in "*Notmuch errors*" so my earlier concern may be valid in this case. Best wishes Mark > >> Otherwise this looks good to me (but I am not that familiar with lisp >> error handling) >> >> Best wishes >> >> Mark >> >> >> >> >> >> >> > +(defun notmuch-version-mismatch-error (exit-status) >> > + "Signal a schema version mismatch error. >> > + >> > +EXIT-STATUS must be the exit status of the notmuch CLI command, >> > +and must have the value 20 or 21. This function will pop up an >> > +error buffer with a descriptive message and signal an error." >> > + (cond ((= exit-status 20) >> > + (notmuch-pop-up-error "Error: Version mismatch. >> > +Emacs requested an older output format than supported by the notmuch CLI. >> > +You may need to restart Emacs or upgrade your notmuch Emacs package.")) >> > + ((= exit-status 21) >> > + (notmuch-pop-up-error "Error: Version mismatch. >> > +Emacs requested a newer output format than supported by the notmuch CLI. >> > +You may need to restart Emacs or upgrade your notmuch package.")) >> > + (t >> > + (error "Bad exit status %d" exit-status))) >> > + (error "notmuch CLI version mismatch")) >> > + >> > ;; Compatibility functions for versions of emacs before emacs 23. >> > ;; >> > ;; Both functions here were copied from emacs 23 with the following >> > copyright: >> > diff --git a/emacs/notmuch.el b/emacs/notmuch.el >> > index f9454d8..e1f28ca 100644 >> > --- a/emacs/notmuch.el >> > +++ b/emacs/notmuch.el >> > @@ -644,6 +644,7 @@ of the result." >> >(exit-status (process-exit-status proc)) >> >(never-found-target-thread nil)) >> > (when (memq status '(exit signal)) >> > + (catch 'return >> >(kill-buffer (process-get proc 'parse-buf)) >> >(if (buffer-live-p buffer) >> >(with-current-buffer buffer >> > @@ -655,8 +656,16 @@ of the result." >> > (insert "Incomplete search results (search process was >> > killed).\n")) >> > (when (eq status 'exit) >> >(insert "End of search results.") >> > - (unless (= exit-status 0) >> > -(insert (format " (process returned %d)" exit-status))) >> > + (cond ((or (= exit-status 20) (= exit-status 21)) >> > + (kill-buffer) >> > + (condition-case err >> > + (notmuch-version-mismatch-error exit-status) >> > + ;; Strange things happen when you signal >> > + ;; an error from a sentinel. >> > + (error (throw 'return nil >> > +((/= exit-status 0) >> > + (insert (format " (process returned %d)" >> > +
[PATCH (draft)] contrib: pick: close message pane when quitting from show in the message pane
This is a way of trying to make sure notmuch-pick cleans up the split buffer after itself. --- Currently if the focus gets into the message pane and then the user quits from that pane the display stays split. This is an attempt to fix that. This seems to work but I don't know if there is a better solution. However, I would welcome any feedback on the user experience with this patch applied. Best wishes Mark contrib/notmuch-pick/notmuch-pick.el | 17 + 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/contrib/notmuch-pick/notmuch-pick.el b/contrib/notmuch-pick/notmuch-pick.el index 043e9e7..79ef319 100644 --- a/contrib/notmuch-pick/notmuch-pick.el +++ b/contrib/notmuch-pick/notmuch-pick.el @@ -160,6 +160,9 @@ (defvar notmuch-pick-message-window nil) (make-variable-buffer-local 'notmuch-pick-message-window) (put 'notmuch-pick-message-window 'permanent-local t) +(defvar notmuch-show-message-window nil) +(make-variable-buffer-local 'notmuch-show-message-window) +(put 'notmuch-show-message-window 'permanent-local t) (defvar notmuch-pick-message-buffer nil) (make-variable-buffer-local 'notmuch-pick-message-buffer-name) (put 'notmuch-pick-message-buffer-name 'permanent-local t) @@ -389,6 +392,16 @@ Does NOT change the database." (notmuch-prettify-subject (notmuch-search-find-subject))) (notmuch-pick-show-match-message-with-wait)) +;;over-ride this function to try and kill off message panes +(defun notmuch-kill-this-buffer () + "Kill the current buffer." + (interactive) + (let ((buffer (current-buffer))) +(when (and (window-live-p notmuch-show-message-window) +(eq (window-buffer notmuch-show-message-window) buffer)) + (delete-window notmuch-show-message-window)) +(kill-buffer buffer))) + (defun notmuch-pick-show-message () "Show the current message (in split-pane)." (interactive) @@ -406,6 +419,10 @@ Does NOT change the database." (let ((notmuch-show-indent-messages-width 0)) (setq current-prefix-arg '(4)) (setq buffer (notmuch-show id nil nil nil + ;; We need the let as notmuch-pick-message-window is buffer local. + (let ((window notmuch-pick-message-window)) + (with-current-buffer buffer + (setq notmuch-show-message-window window))) (notmuch-pick-tag-update-display (list "-unread")) (setq notmuch-pick-message-buffer buffer -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 5/5] emacs: show: set default show-all-multipart/alternatives to nil
Now that the invisibility display of parts is present we no longer need to force the display of all multipart/alternatives: users can toggle them for themselves when needed. --- emacs/notmuch-show.el |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 202258f..c43dd32 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -94,7 +94,7 @@ visible for any given message." :group 'notmuch-hooks) ;; Mostly useful for debugging. -(defcustom notmuch-show-all-multipart/alternative-parts t +(defcustom notmuch-show-all-multipart/alternative-parts nil "Should all parts of multipart/alternative parts be shown?" :type 'boolean :group 'notmuch-show) -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 4/5] emacs: wash: fix fake-diff part to include msg parameter
The fake-diff part from notmuch wash did not pass the msg parameter to notmuch-show-insert-bodypart. Previously this did not matter, but is now needed to get the overlays right for invisibility. --- emacs/notmuch-wash.el |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el index 7d003a2..b2affba 100644 --- a/emacs/notmuch-wash.el +++ b/emacs/notmuch-wash.el @@ -378,7 +378,7 @@ for error." (plist-get (plist-get msg :headers) :Subject (delete-region (point-min) (point-max)) - (notmuch-show-insert-bodypart nil part depth) + (notmuch-show-insert-bodypart msg part depth) ;; -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 2/5] emacs: show: add overlays for each part
This makes notmuch-show-insert-bodypart add an overlay for any non-trivial part with a button header (currently the first text/plain part does not have a button). At this point the overlay is available to the button but there is no action using it yet. In addition the argument HIDE is passed down to notmuch-show-insert-part-overlays to request that the part be hidden by default but this is not acted on yet. --- emacs/notmuch-show.el | 61 + 1 files changed, 46 insertions(+), 15 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 06f7ca5..3f2f277 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -567,11 +567,10 @@ message at DEPTH in the current thread." ;; but it's not clear that this is the wrong thing to do - which ;; should be chosen if there are more than one that match? (mapc (lambda (inner-part) - (let ((inner-type (plist-get inner-part :content-type))) - (if (or notmuch-show-all-multipart/alternative-parts - (string= chosen-type inner-type)) - (notmuch-show-insert-bodypart msg inner-part depth) - (notmuch-show-insert-part-header (plist-get inner-part :id) inner-type inner-type nil " (not shown)" + (let* ((inner-type (plist-get inner-part :content-type)) + (hide (not (or notmuch-show-all-multipart/alternative-parts + (string= chosen-type inner-type) + (notmuch-show-insert-bodypart msg inner-part depth hide))) inner-parts) (when notmuch-show-indent-multipart @@ -839,17 +838,49 @@ message at DEPTH in the current thread." (setq handlers (cdr handlers t) -(defun notmuch-show-insert-bodypart (msg part depth) - "Insert the body part PART at depth DEPTH in the current thread." +(defun notmuch-show-insert-part-overlays (msg beg end hide) + "Add an overlay to the part between BEG and END" + (let* ((button (button-at beg)) +(part-beg (and button (1+ (button-end button) + +;; If the part contains no text we do not make it toggleable. +(when (and button (/= part-beg end)) + (let ((base-label (button-get button :base-label)) + (overlay (make-overlay part-beg end)) + (message-invis-spec (plist-get msg :message-invis-spec)) + (invis-spec (make-symbol "notmuch-part-region"))) + + (overlay-put overlay 'invisible (list invis-spec message-invis-spec)) + (overlay-put overlay 'priority 10) + (overlay-put overlay 'type "part") + ;; Now we have to add invis-spec to every overlay this + ;; overlay contains, otherwise these inner overlays will + ;; override this one. + (dolist (inner (overlays-in part-beg end)) + (when (and (>= (overlay-start inner) part-beg) + (<= (overlay-end inner) end)) + (overlay-put inner 'invisible + (cons invis-spec (overlay-get inner 'invisible) + + (button-put button 'invisibility-spec invis-spec) + (button-put button 'overlay overlay) + +(defun notmuch-show-insert-bodypart (msg part depth &optional hide) + "Insert the body part PART at depth DEPTH in the current thread. + +If HIDE is non-nil then initially hide this part." (let ((content-type (downcase (plist-get part :content-type))) - (nth (plist-get part :id))) -(notmuch-show-insert-bodypart-internal msg part content-type nth depth content-type)) - ;; Some of the body part handlers leave point somewhere up in the - ;; part, so we make sure that we're down at the end. - (goto-char (point-max)) - ;; Ensure that the part ends with a carriage return. - (unless (bolp) -(insert "\n"))) + (nth (plist-get part :id)) + (beg (point))) + +(notmuch-show-insert-bodypart-internal msg part content-type nth depth content-type) +;; Some of the body part handlers leave point somewhere up in the +;; part, so we make sure that we're down at the end. +(goto-char (point-max)) +;; Ensure that the part ends with a carriage return. +(unless (bolp) + (insert "\n")) +(notmuch-show-insert-part-overlays msg beg (point) hide))) (defun notmuch-show-insert-body (msg body depth) "Insert the body BODY at depth DEPTH in the current thread." -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 3/5] emacs: show: add invisibility button action
This adds a button action to show hidden parts. In this version "t" toggles the visibility of a part. In addition "RET" on a non-shown part shows it. The button is used to hide parts when appropriate (eg text/html in multipart/alternative). --- emacs/notmuch-show.el | 36 ++-- 1 files changed, 34 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 3f2f277..202258f 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -478,6 +478,7 @@ message at DEPTH in the current thread." (define-key map "v" 'notmuch-show-part-button-view) (define-key map "o" 'notmuch-show-part-button-interactively-view) (define-key map "|" 'notmuch-show-part-button-pipe) +(define-key map "t" 'notmuch-show-toggle-invisible-part-action) map) "Submap for button commands") (fset 'notmuch-show-part-button-map notmuch-show-part-button-map) @@ -554,6 +555,28 @@ message at DEPTH in the current thread." (let ((handle (mm-make-handle (current-buffer) (list content-type (mm-pipe-part handle +;; This is taken from notmuch-wash: maybe it should be unified? +(defun notmuch-show-toggle-invisible-part-action (&optional button) + (interactive) + (let* ((button (or button (button-at (point +(overlay (button-get button 'overlay)) +(invis-spec (button-get button 'invisibility-spec)) +(show (invisible-p invis-spec))) +(when overlay + (if show + (remove-from-invisibility-spec invis-spec) + (add-to-invisibility-spec invis-spec)) + (let* ((new-start (button-start button)) +(button-label (button-get button :base-label)) +(old-point (point)) +(inhibit-read-only t)) + (goto-char new-start) + (insert "[ " button-label (if show " ]" " (hidden) ]")) + (let ((old-end (button-end button))) + (move-overlay button new-start (point)) + (delete-region (point) old-end)) + (goto-char (min old-point (1- (button-end button + (defun notmuch-show-multipart/*-to-list (part) (mapcar (lambda (inner-part) (plist-get inner-part :content-type)) (plist-get part :content))) @@ -863,7 +886,13 @@ message at DEPTH in the current thread." (cons invis-spec (overlay-get inner 'invisible) (button-put button 'invisibility-spec invis-spec) - (button-put button 'overlay overlay) + (button-put button 'overlay overlay)) + + ;; We toggle the button for hidden parts as that gets the + ;; button label right. + (save-excursion + (when hide + (notmuch-show-toggle-invisible-part-action button)) (defun notmuch-show-insert-bodypart (msg part depth &optional hide) "Insert the body part PART at depth DEPTH in the current thread. @@ -1992,7 +2021,10 @@ the user (see `notmuch-show-stash-mlarchive-link-alist')." (defun notmuch-show-part-button-default (&optional button) (interactive) - (notmuch-show-part-button-internal button notmuch-show-part-button-default-action)) + (let ((button (or button (button-at (point) +(if (button-get button 'invisibility-spec) + (notmuch-show-toggle-invisible-part-action button) + (notmuch-show-part-button-internal button notmuch-show-part-button-default-action (defun notmuch-show-part-button-save (&optional button) (interactive) -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 1/5] emacs: show: modify insert-part-header to save the button text
This just make notmuch-show-insert-part-header save the basic button text for parts as an attribute. This makes it simpler for the button action (added in a later patch) to reword the label as appropriate (eg append "(not shown)" or not as appropriate). --- emacs/notmuch-show.el | 18 +- 1 files changed, 9 insertions(+), 9 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index d7fa10e..06f7ca5 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -483,17 +483,17 @@ message at DEPTH in the current thread." (fset 'notmuch-show-part-button-map notmuch-show-part-button-map) (defun notmuch-show-insert-part-header (nth content-type declared-type &optional name comment) - (let ((button)) + (let ((button) + (base-label (concat (when name (concat name ": ")) + declared-type + (unless (string-equal declared-type content-type) + (concat " (as " content-type ")")) + comment))) + (setq button (insert-button - (concat "[ " - (if name (concat name ": ") "") - declared-type - (if (not (string-equal declared-type content-type)) - (concat " (as " content-type ")") -"") - (or comment "") - " ]") + (concat "[ " base-label " ]") + :base-label base-label :type 'notmuch-show-part-button-type :notmuch-part nth :notmuch-filename name -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 0/5] Use invisibility to toggle display of all parts including multipart
This is version 2 of the patch series (version 1 at id:1354663662-20524-1-git-send-email-markwalters1...@gmail.com) Almost all of the changes and fixes are in response to Austin's review. I have changed things as he suggested. There are two small extra tiny patches in this version: I set the default value of notmuch-show-all-multipart/alternative-parts to nil. The second is to fix a bug reported by Jani: that fake-patch parts (as provided by notmuch-wash) did not get hidden when the whole message was hidden. This was due to notmuch-wash-convert-inline-patch-to-part not passing a msg on down to notmuch-show-insert-bodypart. Previously this did not matter but with with this series msg is needed to construct the correct overlays. Best wishes Mark Mark Walters (5): emacs: show: modify insert-part-header to save the button text emacs: show: add overlays for each part emacs: show: add invisibility button action emacs: wash: fix fake-diff part to include msg parameter emacs: show: set default show-all-multipart/alternatives to nil emacs/notmuch-show.el | 115 ++--- emacs/notmuch-wash.el |2 +- 2 files changed, 90 insertions(+), 27 deletions(-) -- 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 3/3] emacs: show: add invisibility button action
On Tue, 11 Dec 2012, Austin Clements wrote: > On Tue, 04 Dec 2012, Mark Walters wrote: >> This adds a button action to show hidden parts. In this version "t" >> toggles the visibility of a part. In addition "RET" on a non-shown >> part shows it. >> >> The button is used to hide parts when appropriate (eg text/html in >> multipart/alternative). >> --- >> emacs/notmuch-show.el | 36 +++- >> 1 files changed, 35 insertions(+), 1 deletions(-) >> >> diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el >> index 3215ebc..a4daff8 100644 >> --- a/emacs/notmuch-show.el >> +++ b/emacs/notmuch-show.el >> @@ -478,6 +478,7 @@ message at DEPTH in the current thread." >> (define-key map "v" 'notmuch-show-part-button-view) >> (define-key map "o" 'notmuch-show-part-button-interactively-view) >> (define-key map "|" 'notmuch-show-part-button-pipe) >> +(define-key map "t" 'notmuch-show-toggle-invisible-part-action) >> map) >>"Submap for button commands") >> (fset 'notmuch-show-part-button-map notmuch-show-part-button-map) >> @@ -555,6 +556,31 @@ message at DEPTH in the current thread." >> (let ((handle (mm-make-handle (current-buffer) (list content-type >>(mm-pipe-part handle >> >> +;; This is taken from notmuch-wash: maybe it should be unified? >> +(defun notmuch-show-toggle-invisible-part-action (&optional button >> no-redisplay) >> + (interactive) >> + (let* ((button (or button (button-at (point >> + (overlay (button-get button 'overlay)) >> + (invis-spec (button-get button 'invisibility-spec)) >> + (show (invisible-p invis-spec))) >> +(when overlay >> + (if show >> + (remove-from-invisibility-spec invis-spec) >> +(add-to-invisibility-spec invis-spec)) >> + (let* ((new-start (button-start button)) >> + (button-label (button-get button :base-label)) >> + (old-point (point)) >> + (inhibit-read-only t)) >> +(goto-char new-start) >> +(insert "[ " button-label (if show " ]" " (not shown) ]")) > > s/not shown/hidden/? Done > >> +(let ((old-end (button-end button))) >> + (move-overlay button new-start (point)) >> + (delete-region (point) old-end)) >> +(goto-char (min old-point (1- (button-end button) This is where point gets left by this toggle button function: I don't know if it should move point. Mostly it only matters if the user uses the mouse (as otherwise point is on the button). >> + (unless no-redisplay >> +(force-window-update) >> +(redisplay t) > > Is the t argument necessary? Actually, are either (force-window-update) > or (redisplay) necessary? None of this seems needed: I had just copied it from notmuch-wash. Best wishes Mark >> + >> (defun notmuch-show-multipart/*-to-list (part) >>(mapcar (lambda (inner-part) (plist-get inner-part :content-type)) >>(plist-get part :content))) >> @@ -867,6 +893,11 @@ message at DEPTH in the current thread." >> >> (button-put button 'invisibility-spec invis-spec) >> (button-put button 'overlay overlay)) >> + >> + ;; We toggle the button for hidden parts as that gets the >> + ;; button label right. >> + (when not-shown >> +(notmuch-show-toggle-invisible-part-action button t)) >>(goto-char (point-max) >> >> (defun notmuch-show-insert-bodypart (msg part depth &optional not-shown) >> @@ -1996,7 +2027,10 @@ the user (see >> `notmuch-show-stash-mlarchive-link-alist')." >> >> (defun notmuch-show-part-button-default (&optional button) >>(interactive) >> - (notmuch-show-part-button-internal button >> notmuch-show-part-button-default-action)) >> + (let ((button (or button (button-at (point) >> +(if (invisible-p (button-get button 'invisibility-spec)) >> +(notmuch-show-toggle-invisible-part-action button) >> + (notmuch-show-part-button-internal button >> notmuch-show-part-button-default-action >> >> (defun notmuch-show-part-button-save (&optional button) >>(interactive) >> -- >> 1.7.9.1 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 2/3] emacs: show: add overlays for each part
Hi Many thanks for the review: I will post a new version shortly. Some comments inline below: On Tue, 11 Dec 2012, Austin Clements wrote: > On Tue, 04 Dec 2012, Mark Walters wrote: >> This make notmuch-show-insert-bodypart add an overlay for any > > s/make/makes/ > >> non-trivial part with a button header (currently the first text/plain >> part does not have a button). At this point the overlay is available >> to the button but there is no action using it yet. >> >> In addition a not-shown variable which is used to request the part be > > not-shown is really an argument (I found this confusing). > >> hidden by default down to the overlay but this is not acted on yet. >> --- >> emacs/notmuch-show.el | 62 >> +--- >> 1 files changed, 48 insertions(+), 14 deletions(-) >> >> diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el >> index f8ce037..3215ebc 100644 >> --- a/emacs/notmuch-show.el >> +++ b/emacs/notmuch-show.el >> @@ -569,10 +569,9 @@ message at DEPTH in the current thread." >> ;; should be chosen if there are more than one that match? >> (mapc (lambda (inner-part) >> (let ((inner-type (plist-get inner-part :content-type))) >> - (if (or notmuch-show-all-multipart/alternative-parts >> - (string= chosen-type inner-type)) >> - (notmuch-show-insert-bodypart msg inner-part depth) >> -(notmuch-show-insert-part-header (plist-get inner-part :id) >> inner-type inner-type nil " (not shown)" >> + (notmuch-show-insert-bodypart msg inner-part depth >> +(not (or >> notmuch-show-all-multipart/alternative-parts > > Since notmuch-show-all-multipart/alternative-parts was basically a hack > around our poor multipart/alternative support, I think this series (or a > follow up patch) should change its default to nil or even eliminate it > entirely. I have added a patch at the end setting this to nil by default. >> + (string= chosen-type >> inner-type)) > > You could let-bind the (not (or ..)) to some variable ("hide" perhaps) > in the let above to avoid this crazy line length. > >>inner-parts) >> >> (when notmuch-show-indent-multipart >> @@ -840,17 +839,52 @@ message at DEPTH in the current thread." >>(setq handlers (cdr handlers >>t) >> >> -(defun notmuch-show-insert-bodypart (msg part depth) >> - "Insert the body part PART at depth DEPTH in the current thread." >> +(defun notmuch-show-insert-part-overlays (msg beg end not-shown) > > s/not-shown/hide/? Or hidden? > >> + "Add an overlay to the part between BEG and END" >> + (let* ((button (button-at beg)) >> + (part-beg (and button (1+ (button-end button) >> + >> +;; If the part contains no text we do not make it toggleable. >> +(unless (or (not button) (eq part-beg end)) > > (when (and button (/= part-beg end)) ...) ? > >> + (let ((base-label (button-get button :base-label)) >> +(overlay (make-overlay part-beg end)) >> +(message-invis-spec (plist-get msg :message-invis-spec)) >> +(invis-spec (make-symbol "notmuch-part-region"))) >> + >> +(overlay-put overlay 'invisible (list invis-spec message-invis-spec)) > > Non-trivial buffer invisibility specs are really bad for performance > (Emacs' renderer does the obvious O(n^2) thing when rendering a buffer > with an invisibility spec). Unfortunately, because of notmuch-wash and > the way overlays with trivial 'invisible properties combine with > overlays with list-type 'invisible properties combine, I don't think it > can be avoided. But if we get rid of buffer invisibility specs from > notmuch-wash, this code can also get much simpler. How do you plan to get rid of the invisibility properties from notmuch wash? >> +(overlay-put overlay 'isearch-open-invisible >> #'notmuch-wash-region-isearch-show) > > This will leave the "(not shown)" in the part header if isearch unfolds > the part. > > Do we even want isearch to unfold parts? It's not clear we do for > multipart/alternative. If we do, probably the right thing is something > like I don't think we want to search hidden bodyparts so I just deleted this line. > > (overlay-put overlay 'notmuch-show-part-button button) > (overlay-put overlay 'isearch-open-invisible #'notmuch-show-part-isearch-open) > > (defun notmuch-show-part-isearch-open (overlay) > (notmuch-show-toggle-invisible-part-action >(overlay-get overlay 'notmuch-show-part-button))) > >> +(overlay-put overlay 'priority 10) >> +(overlay-put overlay 'type "part") >> +;; Now we have to add invis-spec to every overlay this >> +;; overlay contains, otherwise these inner overlays will >> +;; override this one. > > Interesting. In the simple case of using nil or t for 'invisible, the > specs do combine as one would expect, but you're right that, with a > non-trivial i