Re: [PATCH v2 4/7] emacs: Use result text properties for search result iteration

Subject: Re: [PATCH v2 4/7] emacs: Use result text properties for search result iteration

Date: Sat, 14 Jul 2012 16:01:58 -0400

To: Jameson Graef Rollins

Cc: notmuch@notmuchmail.org

From: Austin Clements


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 <amdragon@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))


Thread: