unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
From: Austin Clements <amdragon@MIT.EDU>
To: Daniel Schoepe <daniel.schoepe@googlemail.com>
Cc: notmuch@notmuchmail.org
Subject: Re: [PATCH] emacs: Tab completion for notmuch-search and notmuch-search-filter
Date: Sat, 4 Jun 2011 17:55:24 -0400	[thread overview]
Message-ID: <20110604215523.GF29861@mit.edu> (raw)
In-Reply-To: <87mxhxjrry.fsf@gilead.invalid>

Quoth Daniel Schoepe on Jun 04 at  9:55 pm:
> On Sat, 4 Jun 2011 11:32:15 -0400, Austin Clements <amdragon@mit.edu> wrote:
> > Dynamic scoping is obnoxious, but I think programmed completion is
> > steeped in the assumption that you'll use it.  This code would be much
> > simpler if notmuch-query-completions took only `string' and used the
> > dynamically-bound all-compls (which should probably be renamed
> > notmuch-completions or something if you do this).  Then this could be
> > just
> >   (minibuffer-completion-table (completion-table-dynamic
> > #'notmuch-query-completions)))
> > and there'd be no need for quasiquoting, comments, and fake lexical scoping.
> 
> Sounds reasonable, I guess I really should stop fighting all those ugly
> parts of elisp with unreadable constructs like that. I made it a global
> variable though to avoid compilation warnings about notmuch-completion
> being a free variable. Since it's contents are not dependent on
> how/where notmuch-read-query is called, this shouldn't cause any
> problems, except my personal discomfort arising from the use of side
> effects for something as simple as this. :)

Oh, sorry, I wasn't suggesting setq'ing a global.  I agree that that's
really ugly.  Rather, something like

(defun notmuch-query-completions (string)
  ... as you have it now ...)

(defun notmuch-read-query (prompt)
  (let ((notmuch-completions (append (list "folder:" ...)))
        (keymap ...)
        (minibuffer-completion-table ...))
    (read-from-minibuffer ...)))

Unfortunately, you still need the global defvar to avoid compilation
warnings, but this at least avoids the side-effects, and is probably
how programmed completion was intended to be used.

Alternatively, here's a completely different way to structure this
that avoids globals and dynamic scoping entirely.  This is how some of
the standard completing read functions appear to work:

(defun notmuch-read-query (prompt)
  "Read a notmuch-query from the minibuffer with completion.

PROMPT is the string to prompt with."
  (lexical-let ((completions
		 (append (list "folder:" "thread:" "id:" "date:" "from:" "to:"
			       "subject:" "attachment:")
			 (mapcar (lambda (tag)
				   (concat "tag:" tag))
				 (process-lines "notmuch" "search-tags")))))
    (let ((minibuffer-completion-table
	   (completion-table-dynamic
	    (lambda (string)
	      (cond
	       ;; this ugly regexp is used to get the last word of the
	       ;; input possibly preceded by a '('
	       ((string-match "\\(^\\|.* (?\\)\\([^ ]*\\)$" string)
		(mapcar (lambda (compl)
			  (concat (match-string-no-properties 1 string) compl))
			(all-completions (match-string-no-properties 2 string)
					 completions)))
	       (t (list string))))))
	  (keymap (copy-keymap minibuffer-local-map)))
      ;; this was simpler than convincing completing-read to accept spaces:
      (define-key keymap (kbd "<tab>") 'minibuffer-complete)
    (read-from-minibuffer prompt nil keymap nil minibuffer-history nil nil))))

> > > +    (define-key keymap (kbd "<tab>") 'minibuffer-complete)
> > 
> > This probably deserves a comment about why you're doing so much work
> > to avoid completing-read (which I assume is because it also binds SPC,
> > even if require-match is nil, which is unfortunate).
> 
> Yes, that was the reason.
> 
> Another thing that bugs me, is that I did not find a better way of doing
> the completion: Ideally I'd like to just specify a list of completions
> for individual words and have emacs handle separating the input string
> into individual words, but I couldn't find any options to accomplish
> that.

Yeah, I futzed with it for a bit, swearing that there had to be a
better way, but didn't find one either.

  parent reply	other threads:[~2011-06-04 21:55 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-06-04 12:19 [PATCH] emacs: Tab completion for notmuch-search and notmuch-search-filter Daniel Schoepe
2011-06-04 13:14 ` Daniel Schoepe
2011-06-04 15:32 ` Austin Clements
2011-06-04 19:55   ` Daniel Schoepe
2011-06-04 20:39     ` Daniel Schoepe
2011-06-04 21:55     ` Austin Clements [this message]
2011-06-04 22:54       ` Daniel Schoepe
2011-06-06 16:32         ` Daniel Schoepe
2011-08-05 15:17           ` Daniel Schoepe
2011-08-05 21:00             ` Jameson Graef Rollins
2011-08-05 21:03               ` Jameson Graef Rollins
2011-08-06  6:09                 ` Jameson Graef Rollins
2011-08-09 17:31                   ` Daniel Schoepe
2011-08-09 21:41                     ` Jameson Graef Rollins
2011-08-09 17:32                   ` Daniel Schoepe
2011-11-03  1:19                     ` David Bremner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://notmuchmail.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110604215523.GF29861@mit.edu \
    --to=amdragon@mit.edu \
    --cc=daniel.schoepe@googlemail.com \
    --cc=notmuch@notmuchmail.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).