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 68A55429E28 for ; Wed, 25 May 2011 14:22:08 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: -0.799 X-Spam-Level: X-Spam-Status: No, score=-0.799 tagged_above=-999 required=5 tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_FROM=0.001, 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 i1InsvSPNl+V for ; Wed, 25 May 2011 14:22:07 -0700 (PDT) Received: from mail-fx0-f53.google.com (mail-fx0-f53.google.com [209.85.161.53]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (No client certificate requested) by olra.theworths.org (Postfix) with ESMTPS id 980E4431FB6 for ; Wed, 25 May 2011 14:22:06 -0700 (PDT) Received: by fxm8 with SMTP id 8so172094fxm.26 for ; Wed, 25 May 2011 14:22:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:from:to:cc:subject:in-reply-to:references :user-agent:date:message-id:mime-version:content-type; bh=lzyEBwCdKa8MXZUjegknZQ/EpJfpKDhkk3FWSgHqLqk=; b=i/71VqNfVNuLnMDee6iYH+PGpFOjKSlXgrUuoKiW0ubQ0CnKp83N4MjlGZGL1mE4FO KOZywn7jOPLk8Z8lc1hy7uLb06sclKkMCSdgiBQXj3gncq4qreE4dcUF/ggKAgeXlwKD V4Buy69TrclUE6bK/9mu4DhTuNR7WOq5uS6iA= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=from:to:cc:subject:in-reply-to:references:user-agent:date :message-id:mime-version:content-type; b=ZRoTqkHfPRs+xlDs+1i5JbtJasxAwRP3lnMUWHiYcbJk3Msgl2uef5HM075u2OSHdH 5ZDWm0Kv1aBbeMnCuLqf+oqhdP8vx8rMS4O7eQxTMx3trlo0nMgOh8tBctHuyQ3+wR4P cmiMDL2aZW7UnJJlnwHBpLndmM2h/mHtOsZmM= Received: by 10.223.47.209 with SMTP id o17mr47209faf.129.1306358525226; Wed, 25 May 2011 14:22:05 -0700 (PDT) Received: from localhost (dslb-178-004-026-109.pools.arcor-ip.net [178.4.26.109]) by mx.google.com with ESMTPS id l26sm15345fam.21.2011.05.25.14.22.02 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 25 May 2011 14:22:03 -0700 (PDT) From: Daniel Schoepe To: Austin Clements Subject: Re: [PATCH] emacs: Make the queries used in the all-tags section In-Reply-To: References: <87fwoath2s.fsf@gilead.home.box> <871uznqeox.fsf@tredergarh.home.box> <874o4iwwp5.fsf@gilead.invalid> <871uzmwtng.fsf@gilead.invalid> User-Agent: Notmuch/0.5-210-g1acc997 (http://notmuchmail.org) Emacs/23.3.1 (x86_64-pc-linux-gnu) Date: Wed, 25 May 2011 23:21:54 +0200 Message-ID: <87ei3mcw7h.fsf@gilead.invalid> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="==-=-="; micalg=pgp-sha1; protocol="application/pgp-signature" 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: Wed, 25 May 2011 21:22:08 -0000 --==-=-= Content-Type: multipart/mixed; boundary="=-=-=" --=-=-= Content-Type: text/plain Content-Transfer-Encoding: quoted-printable On Wed, 25 May 2011 15:11:16 -0400, Austin Clements wrot= e: > At least in Emacs 23.3.1, it has to be (const :tag "tag:TAG" nil). I > didn't think the order mattered, but the tag didn't display otherwise. > It would also be good to give descriptive tags to the other choices. >=20 > It would be more consistent if the function form of this also returned > a filter expression, rather than a whole expression. This also > simplifies the documentation. Thanks for the suggestions. (At first, I wanted to allow the user to be able to also include messages that don't have that tag, but this really no longer belongs in the all tags-section). > So, perhaps something like > > (defcustom notmuch-hello-tag-list-counts nil > "Method for generating counts displayed in the all tags list. >=20 > This variable controls the query used to generate counts for each > tag in the \"all tags\" list. If nil, the tag list will count > all messages with each tag. This can be a query string that will > filter the messages counted for each tag. Finally, this can be a > function that will be called for each tag and should return a > filter query for that tag, or nil to hide the tag." > :type '(choice (const :tag "Count all messages" nil) > (const :tag "Count unread messages" "tag:unread") > (const :tag "Custom filter" string) > (const :tag "Custom filter function" function)) > :group 'notmuch) That is slightly less accurate though, since the query is not only used to generate the counts, but also the searches that are performed when one presses return on a tag in the list. > > +(defun notmuch-hello-generate-tag-alist () > > + "Return an alist from tags to queries to display in the all-tags sec= tion." > > + (notmuch-filter > > + 'cdr > > + (mapcar '(lambda (tag) >=20 > You don't need the quote before a lambda form. (You can also change > 'cdr to #'cdr to further hint the compiler, though it appears to not > matter in this case.) Oh, yeah, normally I'm aware of that, don't know what made me quote it at the time I wrote it. > > +(defun notmuch-filter (pred lst) > > + "Return a list containing all elements from LST that satisfy PRED." >=20 > notmuch-remove-if-not would be more canonical (yeah, it's unwieldy, > blame Common Lisp). Also, since Elisp doesn't do tail-recursion, the > standard way to define a remove-if-not function is >=20 > (defun notmuch-remove-if-not (predicate list) > "Return a copy of LIST with all items not satisfying PREDICATE removed." > (let (out) > (while list > (when (funcall predicate (car list)) > (push (car list) out)) > (setq list (cdr list))) > (nreverse out))) >=20 > (Why oh why Elisp hasn't just made remove-if and remove-if-not > standard I don't know; they're redefined all over the Elisp code base. > Any everybody's afraid to use cl-seq's remove-if-not because it's so > ridiculously complicated.) Ah, thanks. I guess too much exposure to Haskell (and how smart GHC is) makes me write things in a functional style without thinking about performance. I incorporated most of you recommendations in the attached patch. --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0001-emacs-Make-queries-used-in-the-all-tags-section-conf.patch Content-Transfer-Encoding: quoted-printable From=202056a455cdec6b980426552b8dcd7055f6cd0805 Mon Sep 17 00:00:00 2001 From: Daniel Schoepe Date: Fri, 20 May 2011 00:53:50 +0200 Subject: [PATCH] emacs: Make queries used in the all-tags section configurable This patch adds a customization variable that controls what queries are used to construct the all-tags section in notmuch-hello. It allows the user to specify a function to construct the query given a tag or a string that is used as a filter for each tag. It also adds a variable to hide various tags from the all-tags section. Signed-off-by: Daniel Schoepe =2D-- emacs/notmuch-hello.el | 43 ++++++++++++++++++++++++++++++++++++++++--- emacs/notmuch-lib.el | 9 +++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index e58dd24..bd95849 100644 =2D-- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -55,6 +55,26 @@ :type 'boolean :group 'notmuch) =20 +(defcustom notmuch-hello-tag-list-make-query nil + "Function or string to generate queries for the all tags list. + +This variable controls which query results are shown for each tag +in the \"all tags\" list. If nil, it will use all messages with +that tag. If this is set to a string, it is used as a filter for +messages having that tag (equivalent to \"tag:TAG and (THIS-VARIABLE)\"). +Finally this can be a function that will be called for each tag and +should return a filter for that tag, or nil to hide the tag." + :type '(choice (const :tag "All messages" nil) + (const :tag "Unread messages" "tag:unread") + (const :tag "Custom filter" string) + (const :tag "Custom filter function" function)) + :group 'notmuch) + +(defcustom notmuch-hello-hide-tags nil + "List of tags to be hidden in the \"all tags\"-section." + :type '(repeat string) + :group 'notmuch) + (defface notmuch-hello-logo-background '((((class color) (background dark)) @@ -318,6 +338,25 @@ Complete list of currently available key bindings: ;;(setq buffer-read-only t) ) =20 +(defun notmuch-hello-generate-tag-alist () + "Return an alist from tags to queries to display in the all-tags section= ." + (notmuch-remove-if-not + #'cdr + (mapcar (lambda (tag) + (cons tag + (cond + ((functionp notmuch-hello-tag-list-make-query) + (concat "tag:" tag " and (" + (funcall notmuch-hello-tag-list-make-query tag) ")")) + ((stringp notmuch-hello-tag-list-make-query) + (concat "tag:" tag " and (" + notmuch-hello-tag-list-make-query ")")) + (t (concat "tag:" tag))))) + (notmuch-remove-if-not + (lambda (tag) + (not (member tag notmuch-hello-hide-tags))) + (process-lines notmuch-command "search-tags"))))) + ;;;###autoload (defun notmuch-hello (&optional no-display) "Run notmuch and display saved searches, known tags, etc." @@ -396,9 +435,7 @@ Complete list of currently available key bindings: if (> (string-to-number (notmuch-saved-search-count (cdr elem))) 0) collect elem))) (saved-widest (notmuch-hello-longest-label saved-alist)) =2D (alltags-alist (if notmuch-show-all-tags-list =2D (mapcar '(lambda (tag) (cons tag (concat "tag:" tag))) =2D (process-lines notmuch-command "search-tags")))) + (alltags-alist (if notmuch-show-all-tags-list (notmuch-hello-generat= e-tag-alist))) (alltags-widest (notmuch-hello-longest-label alltags-alist)) (widest (max saved-widest alltags-widest))) =20 diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index cc80fb2..d5ca0f4 100644 =2D-- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -120,6 +120,15 @@ within the current window." (or (memq prop buffer-invisibility-spec) (assq prop buffer-invisibility-spec))))) =20 +(defun notmuch-remove-if-not (predicate list) + "Return a copy of LIST with all items not satisfying PREDICATE removed." + (let (out) + (while list + (when (funcall predicate (car list)) + (push (car list) out)) + (setq list (cdr list))) + (nreverse out))) + ; This lets us avoid compiling these replacement functions when emacs ; is sufficiently new enough to supply them alone. We do the macro ; treatment rather than just wrapping our defun calls in a when form =2D-=20 1.7.5.1 --=-=-=-- --==-=-= Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAEBAgAGBQJN3XLyAAoJEIaTAtce+Z+JuE8QAJIOS5MBTRTHflriNhnPDR6b n1nZZicPM0dzraf0O8Su2IA7R79ZLEiPD+poqCWJ3Kddf78lQjcwDoU2tTXVBSO0 BRWZAPjkIx7QcDeF+mr6R2rsqBgyn4JQQ6/8QgO6V4mWGOCNo1VZMjjQE0QXj3jA p9rh7A22r+FlDtF/EXHPaA4+kaiwvnaHhOS1CGstDZxZ1J4BoYC7kvMUzk+51GLa gbBQehazp06SDgAScSa647oXhXw6sjyUu5OGWyswaO+wuTq/fwAkyOP59xlfJpef BZyWzG6HT1mT4NZn2V1bZUVixwg5A+xPRK0F/fzyk6e4nV4E3YyjUtimcpjm2yLh S/KdT2VRcK+OnvOmiSni+LRE8LAmTaCVA6MJYW/R88fQTELXBF5nU8zx22QYyPES EDFKaNCm77Um+LlkQ33P8UI8dS5JKQRgCiZ4IBuNhitmpKxhLo0e4GXow2J/QYyY 1nggnlpxN6TFzIIbELyg6dfjunQ75EUE+X53Vaz+5kzsZP2kg5wHkbMwnqatYtLq zbEalh7oYd4AlWN4Wl42/oPvYjHvcTDC8hpHpysz/uYFpk/cW9+XCzpkVTg2T0h/ 7MWcoNY9YqTWU5r62d9HKaX8Ikr0aeyA89lA2s7xMyCAAu0kz5u1FA5QdnOHre2B pxvway8DVIOyGdZF4hHh =Dvo2 -----END PGP SIGNATURE----- --==-=-=--