Re: [PATCH v2 4/7] emacs: Use result text properties for search result iteration
On Fri, Jul 13 2012, Austin Clements amdra...@mit.edu wrote: Coincidentally, this also essentially enables multi-line search result formats; the only remaining non-multi-line-capable functions are notmuch-search-{next,previous}-thread, which are only used interactively. So I tried to experiment with multi-line search results with this patch series, but it didn't work. I tried adding a '\n' in one of the formatter fields, but I got a series of errors for each result insertion in the buffer. What's the way to get multi-line to work? +(defmacro notmuch-search-do-results (beg end pos-sym rest body) + Invoke BODY for each result between BEG and END. + +POS-SYM will be bound to the point at the beginning of the +current result. + (declare (indent 3)) + (let ((end-sym (make-symbol end)) + (first-sym (make-symbol first))) +`(let ((,pos-sym (notmuch-search-result-beginning ,beg)) +;; End must be a marker in case body changes the text +(,end-sym (copy-marker ,end)) +;; Make sure we examine one result, even if (= beg end) +(,first-sym t)) + ;; We have to be careful if the region extends beyond the + ;; results. In this case, pos could be null or there could be + ;; no result at pos. + (while (and ,pos-sym (or ( ,pos-sym ,end-sym) ,first-sym)) + (when (notmuch-search-get-result ,pos-sym) +,@body) + (setq ,pos-sym (notmuch-search-result-end ,pos-sym) +,first-sym nil) Austin, can you explain why you use a defmacro here? I'm honestly have a hard time parsing what's going on here. I understand in principle how elisp macros work, but I don't see why it's needed here. I'm also trying to understand what the commas are doing (e.g. ,pos-sym). Are they doing some sort of escaping? Some sophisticated elisp here! jamie. pgpir2LGeaLnI.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v2 4/7] emacs: Use result text properties for search result iteration
Quoth Jameson Graef Rollins on Jul 14 at 12:31 pm: On Fri, Jul 13 2012, Austin Clements amdra...@mit.edu wrote: Coincidentally, this also essentially enables multi-line search result formats; the only remaining non-multi-line-capable functions are notmuch-search-{next,previous}-thread, which are only used interactively. So I tried to experiment with multi-line search results with this patch series, but it didn't work. I tried adding a '\n' in one of the formatter fields, but I got a series of errors for each result insertion in the buffer. What's the way to get multi-line to work? That's strange. What was the error? I've been testing with ((date . %12s ) (count . %-7s ) (authors . %-20s ) (subject . \n%s ) (tags . (%s))) But maybe there are other cases it doesn't handle correctly? +(defmacro notmuch-search-do-results (beg end pos-sym rest body) + Invoke BODY for each result between BEG and END. + +POS-SYM will be bound to the point at the beginning of the +current result. + (declare (indent 3)) + (let ((end-sym (make-symbol end)) + (first-sym (make-symbol first))) +`(let ((,pos-sym (notmuch-search-result-beginning ,beg)) + ;; End must be a marker in case body changes the text + (,end-sym (copy-marker ,end)) + ;; Make sure we examine one result, even if (= beg end) + (,first-sym t)) + ;; We have to be careful if the region extends beyond the + ;; results. In this case, pos could be null or there could be + ;; no result at pos. + (while (and ,pos-sym (or ( ,pos-sym ,end-sym) ,first-sym)) +(when (notmuch-search-get-result ,pos-sym) + ,@body) +(setq ,pos-sym (notmuch-search-result-end ,pos-sym) + ,first-sym nil) Austin, can you explain why you use a defmacro here? I'm honestly have a hard time parsing what's going on here. I understand in principle how elisp macros work, but I don't see why it's needed here. I'm also trying to understand what the commas are doing (e.g. ,pos-sym). Are they doing some sort of escaping? Some sophisticated elisp here! I did this as a macro to parallel things like dolist and loop, I'll try this out with a higher-order procedure and see if the results are less opaque. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v2 4/7] emacs: Use result text properties for search result iteration
Quoth myself on Jul 14 at 3:50 pm: Quoth Jameson Graef Rollins on Jul 14 at 12:31 pm: On Fri, Jul 13 2012, Austin Clements amdra...@mit.edu wrote: +(defmacro notmuch-search-do-results (beg end pos-sym rest body) + Invoke BODY for each result between BEG and END. + +POS-SYM will be bound to the point at the beginning of the +current result. + (declare (indent 3)) + (let ((end-sym (make-symbol end)) + (first-sym (make-symbol first))) +`(let ((,pos-sym (notmuch-search-result-beginning ,beg)) +;; End must be a marker in case body changes the text +(,end-sym (copy-marker ,end)) +;; Make sure we examine one result, even if (= beg end) +(,first-sym t)) + ;; We have to be careful if the region extends beyond the + ;; results. In this case, pos could be null or there could be + ;; no result at pos. + (while (and ,pos-sym (or ( ,pos-sym ,end-sym) ,first-sym)) + (when (notmuch-search-get-result ,pos-sym) +,@body) + (setq ,pos-sym (notmuch-search-result-end ,pos-sym) +,first-sym nil) Austin, can you explain why you use a defmacro here? I'm honestly have a hard time parsing what's going on here. I understand in principle how elisp macros work, but I don't see why it's needed here. I'm also trying to understand what the commas are doing (e.g. ,pos-sym). Are they doing some sort of escaping? Some sophisticated elisp here! I did this as a macro to parallel things like dolist and loop, I'll try this out with a higher-order procedure and see if the results are less opaque. Here's what it looks like as a higher-order procedure and an example use: (defun notmuch-search-foreach-result (beg end function) Invoke FUNCTION with the position of each result between BEG and END. (lexical-let ((pos (notmuch-search-result-beginning beg)) ;; End must be a marker in case function changes the ;; text. (end (copy-marker end)) ;; Make sure we examine at least one result, even if ;; (= beg end). (first t)) ;; We have to be careful if the region extends beyond the results. ;; In this case, pos could be null or there could be no result at ;; pos. (while (and pos (or ( pos end) first)) (when (notmuch-search-get-result pos) (apply function pos)) (setq pos (notmuch-search-result-end pos) first nil (defun notmuch-search-properties-in-region (property beg end) (let (output) (notmuch-search-foreach-result beg end (lambda (pos) (push (plist-get (notmuch-search-get-result pos) property) output))) output)) ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v2 4/7] emacs: Use result text properties for search result iteration
On Sat, Jul 14 2012, Austin Clements amdra...@mit.edu wrote: That's strange. What was the error? I've been testing with ((date . %12s ) (count . %-7s ) (authors . %-20s ) (subject . \n%s ) (tags . (%s))) But maybe there are other cases it doesn't handle correctly? Hrm. The error was: error in process filter: wrong type argument: wholenump, -13 However, that's in my test emacs setup. It works fine in my normal emacs session. Lets assume this is just a problem with my setup that I'll look into. The other problem I seem to be running into is that the customize-variable interface definitely doesn't handle newlines very well. If I try to add a '\n' in the interface it gets escaped, so I end up with: (subject . \\n%s ) If I add the '\n' manually in my config, notmuch-search then interprets the string correctly and adds newlines to the search results, but then the customize-variable interface interprets the newline and adds a newline the string field that kind makes the interface a little weird. Is there proper way to add a newline to a string value in the customize-variable interface that I'm not aware of? In any event, this is in no way a blocker for this patch series. This is all totally tangential. The patch series is great. jamie. pgppV4gW3Tw9i.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v2 4/7] emacs: Use result text properties for search result iteration
On Sat, 14 Jul 2012, Austin Clements amdra...@mit.edu wrote: This simplifies the traversal of regions of results and eliminates the need for save-excursions (which tend to get in the way of maintaining point when we make changes to the buffer). It also fixes some strange corner cases in the old line-based code where results that bordered the region but were not included in it could be affected by region commands. Coincidentally, this also essentially enables multi-line search result formats; the only remaining non-multi-line-capable functions are notmuch-search-{next,previous}-thread, which are only used interactively. Having understood how macros work (thanks to Austin's patient explanations on irc) this looks fine. So +1 for the whole series. Best wishes Mark --- emacs/notmuch.el | 61 ++ 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/emacs/notmuch.el b/emacs/notmuch.el index 8e1a769..92ba2c1 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -427,17 +427,33 @@ returns nil (next-single-property-change (or pos (point)) 'notmuch-search-result nil (point-max +(defmacro notmuch-search-do-results (beg end pos-sym rest body) + Invoke BODY for each result between BEG and END. + +POS-SYM will be bound to the point at the beginning of the +current result. + (declare (indent 3)) + (let ((end-sym (make-symbol end)) + (first-sym (make-symbol first))) +`(let ((,pos-sym (notmuch-search-result-beginning ,beg)) +;; End must be a marker in case body changes the text +(,end-sym (copy-marker ,end)) +;; Make sure we examine one result, even if (= beg end) +(,first-sym t)) + ;; We have to be careful if the region extends beyond the + ;; results. In this case, pos could be null or there could be + ;; no result at pos. + (while (and ,pos-sym (or ( ,pos-sym ,end-sym) ,first-sym)) + (when (notmuch-search-get-result ,pos-sym) +,@body) + (setq ,pos-sym (notmuch-search-result-end ,pos-sym) +,first-sym nil) + (defun notmuch-search-properties-in-region (property beg end) - (save-excursion -(let ((output nil) - (last-line (line-number-at-pos end)) - (max-line (- (line-number-at-pos (point-max)) 2))) - (goto-char beg) - (beginning-of-line) - (while (= (line-number-at-pos) (min last-line max-line)) - (setq output (cons (get-text-property (point) property) output)) - (forward-line 1)) - output))) + (let (output) +(notmuch-search-do-results beg end pos + (push (get-text-property pos property) output)) +output)) (defun notmuch-search-find-thread-id () Return the thread for the current thread @@ -517,28 +533,19 @@ and will also appear in a buffer named \*Notmuch errors*\. (plist-get (notmuch-search-get-result pos) :tags)) (defun notmuch-search-get-tags-region (beg end) - (save-excursion -(let ((output nil) - (last-line (line-number-at-pos end)) - (max-line (- (line-number-at-pos (point-max)) 2))) - (goto-char beg) - (while (= (line-number-at-pos) (min last-line max-line)) - (setq output (append output (notmuch-search-get-tags))) - (forward-line 1)) - output))) + (let (output) +(notmuch-search-do-results beg end pos + (setq output (append output (notmuch-search-get-tags pos +output)) (defun notmuch-search-tag-region (beg end optional tag-changes) Change tags for threads in the given region. (let ((search-string (notmuch-search-find-thread-id-region-search beg end))) (setq tag-changes (funcall 'notmuch-tag search-string tag-changes)) -(save-excursion - (let ((last-line (line-number-at-pos end)) - (max-line (- (line-number-at-pos (point-max)) 2))) - (goto-char beg) - (while (= (line-number-at-pos) (min last-line max-line)) - (notmuch-search-set-tags -(notmuch-update-tags (notmuch-search-get-tags) tag-changes)) - (forward-line)) +(notmuch-search-do-results beg end pos + (notmuch-search-set-tags + (notmuch-update-tags (notmuch-search-get-tags pos) tag-changes) + pos (defun notmuch-search-tag (optional tag-changes) Change tags for the currently selected thread or region. -- 1.7.10 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v2 4/7] emacs: Use result text properties for search result iteration
Quoth Jameson Graef Rollins on Jul 14 at 2:13 pm: On Sat, Jul 14 2012, Austin Clements amdra...@mit.edu wrote: That's strange. What was the error? I've been testing with ((date . %12s ) (count . %-7s ) (authors . %-20s ) (subject . \n%s ) (tags . (%s))) But maybe there are other cases it doesn't handle correctly? Hrm. The error was: error in process filter: wrong type argument: wholenump, -13 However, that's in my test emacs setup. It works fine in my normal emacs session. Lets assume this is just a problem with my setup that I'll look into. Interesting. The error in process filter suggests that it is happening somewhere in the notmuch code under the search process filter, so it's probably some combination of something unusual in your environment and this patch. If you M-x toggle-debug-on-error, will it drop you into the debugger when this happens? The other problem I seem to be running into is that the customize-variable interface definitely doesn't handle newlines very well. If I try to add a '\n' in the interface it gets escaped, so I end up with: (subject . \\n%s ) If I add the '\n' manually in my config, notmuch-search then interprets the string correctly and adds newlines to the search results, but then the customize-variable interface interprets the newline and adds a newline the string field that kind makes the interface a little weird. Is there proper way to add a newline to a string value in the customize-variable interface that I'm not aware of? I think this is just a sharp corner in customize and there's notmuch we can do about it. I believe the proper way to enter the newline directly in customize is to hit C-q C-j (same way you get a raw newline in any other buffer). Given that I wouldn't expect anyone to guess that, though, we could mention this in the defcustom's docstring. In any event, this is in no way a blocker for this patch series. This is all totally tangential. The patch series is great. jamie. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH v2 4/7] emacs: Use result text properties for search result iteration
On Sat, Jul 14 2012, Austin Clements amdra...@mit.edu wrote: I think this is just a sharp corner in customize and there's notmuch we can do about it. I believe the proper way to enter the newline directly in customize is to hit C-q C-j (same way you get a raw newline in any other buffer). Given that I wouldn't expect anyone to guess that, though, we could mention this in the defcustom's docstring. Ah. C-q C-j definitely does it. Thanks, Austin. I'll follow up with a patch that modifies the doc string, which can maybe help make things clearer for the uninitiated. jamie. pgpdSD0CDV8AE.pgp Description: PGP signature ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch