Return-Path: X-Original-To: notmuch@notmuchmail.org Delivered-To: notmuch@notmuchmail.org Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id BEA19429E2C for ; Sat, 4 Jun 2011 14:55:34 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: -0.7 X-Spam-Level: X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5 tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id KjOBEpJbPrQu for ; Sat, 4 Jun 2011 14:55:33 -0700 (PDT) Received: from dmz-mailsec-scanner-4.mit.edu (DMZ-MAILSEC-SCANNER-4.MIT.EDU [18.9.25.15]) by olra.theworths.org (Postfix) with ESMTP id C279C431FB6 for ; Sat, 4 Jun 2011 14:55:33 -0700 (PDT) X-AuditID: 1209190f-b7c4dae0000007bd-cb-4deaa9d71c74 Received: from mailhub-auth-2.mit.edu ( [18.7.62.36]) by dmz-mailsec-scanner-4.mit.edu (Symantec Messaging Gateway) with SMTP id C0.C6.01981.7D9AAED4; Sat, 4 Jun 2011 17:55:35 -0400 (EDT) Received: from outgoing.mit.edu (OUTGOING-AUTH.MIT.EDU [18.7.22.103]) by mailhub-auth-2.mit.edu (8.13.8/8.9.2) with ESMTP id p54LtWUf002615; Sat, 4 Jun 2011 17:55:32 -0400 Received: from awakening.csail.mit.edu (awakening.csail.mit.edu [18.26.4.91]) (authenticated bits=0) (User authenticated as amdragon@ATHENA.MIT.EDU) by outgoing.mit.edu (8.13.6/8.12.4) with ESMTP id p54LtU6f009874 (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT); Sat, 4 Jun 2011 17:55:31 -0400 (EDT) Received: from amthrax by awakening.csail.mit.edu with local (Exim 4.72) (envelope-from ) id 1QSyoW-0004OG-4u; Sat, 04 Jun 2011 17:55:24 -0400 Date: Sat, 4 Jun 2011 17:55:24 -0400 From: Austin Clements To: Daniel Schoepe Subject: Re: [PATCH] emacs: Tab completion for notmuch-search and notmuch-search-filter Message-ID: <20110604215523.GF29861@mit.edu> References: <1307189970-728-1-git-send-email-daniel.schoepe@googlemail.com> <87mxhxjrry.fsf@gilead.invalid> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <87mxhxjrry.fsf@gilead.invalid> User-Agent: Mutt/1.5.20 (2009-06-14) X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprAKsWRmVeSWpSXmKPExsUixG6nont95StfgyXLFSwWHjrDYnH95kxm ByaPpxMms3s8W3WLOYApissmJTUnsyy1SN8ugSvj/p9bjAW3ZSsur7/B3sB4VryLkZNDQsBE YkHnfkYIW0ziwr31bF2MXBxCAvsYJTY9uMMK4axnlJh0o5EdwjnBJNH44AZU2RJGic4dW8D6 WQRUJNqP7WADsdkENCS27V8OFhcRMJJ4teYxE4jNLCAt8e13M5DNwSEsEClxbEUgSJhXQEfi x5Z3jHAzd/cfYoFICEqcnPmEBaJXS+LGv5dgvSBzlv/jAAlzAvUevtgIViIKdMK1/e1sExiF ZiHpnoWkexZC9wJG5lWMsim5Vbq5iZk5xanJusXJiXl5qUW6Jnq5mSV6qSmlmxhBgc0pyb+D 8dtBpUOMAhyMSjy8rkmvfIVYE8uKK3MPMUpyMCmJ8iauAArxJeWnVGYkFmfEF5XmpBYfYpTg YFYS4a0TAcrxpiRWVqUW5cOkpDlYlMR5Z0mq+woJpCeWpGanphakFsFkZTg4lCR4o4ERLCRY lJqeWpGWmVOCkGbi4AQZzgM0PAikhre4IDG3ODMdIn+KUZfj0MlXBxmFWPLy81KlxHmVQIoE QIoySvPg5sAS0itGcaC3hHmlQap4gMkMbtIroCVMQEuOO4EtKUlESEk1MPLmqFcofAsVcZux bqvbLX+PfFUpExHxNXGdcnoZodKl9usdOp+ImNVsnWr4XeyBq9Q76TeaX/c4vWHvd795+v6j nCTDTjfnhSxTVufEF9ZObDZ5vvmTKRdfw9SM0Pkzmfr71tqwLf+R979m9t9dP7Y/fNARE5/w rCiokPvSQ86fs+duF7xiq8RSnJFoqMVcVJwIAMVxfGsjAwAA Cc: notmuch@notmuchmail.org X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jun 2011 21:55:34 -0000 Quoth Daniel Schoepe on Jun 04 at 9:55 pm: > On Sat, 4 Jun 2011 11:32:15 -0400, Austin Clements 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 "") 'minibuffer-complete) (read-from-minibuffer prompt nil keymap nil minibuffer-history nil nil)))) > > > + (define-key keymap (kbd "") '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.