--- /dev/null
+Return-Path: <dme@dme.org>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by arlo.cworth.org (Postfix) with ESMTP id 8F6FC6DE021E\r
+ for <notmuch@notmuchmail.org>; Wed, 10 Feb 2016 06:01:27 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at cworth.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.11\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.11 tagged_above=-999 required=5 tests=[AWL=-0.043,\r
+ DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_LOW=-0.7,\r
+ RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_NEUTRAL=0.652,\r
+ UNPARSEABLE_RELAY=0.001] autolearn=disabled\r
+Received: from arlo.cworth.org ([127.0.0.1])\r
+ by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id l8PkmZ4X1Lqc for <notmuch@notmuchmail.org>;\r
+ Wed, 10 Feb 2016 06:01:25 -0800 (PST)\r
+Received: from mail-wm0-f67.google.com (mail-wm0-f67.google.com\r
+ [74.125.82.67]) by arlo.cworth.org (Postfix) with ESMTPS id 9CFC56DE0231 for\r
+ <notmuch@notmuchmail.org>; Wed, 10 Feb 2016 06:01:24 -0800 (PST)\r
+Received: by mail-wm0-f67.google.com with SMTP id 128so4392155wmz.3\r
+ for <notmuch@notmuchmail.org>; Wed, 10 Feb 2016 06:01:24 -0800 (PST)\r
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
+ d=dme-org.20150623.gappssmtp.com; s=20150623;\r
+ h=from:to:subject:date:message-id:in-reply-to:references;\r
+ bh=da2qfbL+IpdGWd06Y5DgspunHc2t5V4ThIoO+KG8aH8=;\r
+ b=HYjjaDOt54QN2A5e1d3b6WWnmo+OXCAmdyuhNR1r1MsiujySX5B0wpypTUCMDrnf42\r
+ NWRmFE6Xw6KauGQmUHtVu95axiX9DlctJI7Bg0kFzGGGJCqYECdZ2R3PuwX62eacTPb/\r
+ p0BzhOXxo7TuwfOjIbSvU6JBZSGevWjah2xPW1P8fBREtz53Wuh2qtscz1vsZ6B80z4E\r
+ Z/H/HpRhGbqKN7urzegN0yhht9e4+m5gDzlJVeHo5R/wecHuLVYCa1gfN7hlFZqCpyXs\r
+ eVXN9yxm8yOU20eUFi42z2CNVtsfnYB+I7djNYB4kKRsbcvWXoKa8paZOPnY8ccU4iic\r
+ rvew==\r
+X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
+ d=1e100.net; s=20130820;\r
+ h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to\r
+ :references;\r
+ bh=da2qfbL+IpdGWd06Y5DgspunHc2t5V4ThIoO+KG8aH8=;\r
+ b=NKxqOxJnFllssCzcyizgmwiZ7v4sdUvbE+bbO4zntRDxmKxhj9J7b3Fs5QjMqmYMbf\r
+ xAKf+autwkUc8ut8CYoUOMOaovdWiSJ4glkJhO9yo/5/RR0CEyGy16zLwwDfaBUy6/a3\r
+ k34SMAtoqGikIyQNOHIhUMNhIsV0/QHio8D380ELki5/WVjlQSlhSHfKOPPRZ89cCs+C\r
+ s+q6zpXU/IabnwFlA4tVOd03n9MOt9+IKEzpHdeQc5lwtvWeN1pu0RWdr6EzUuKadrM/\r
+ 6RjtqUxp+IlogD39DjtfcpRS5MKLBmP01xMQlz7kNOpr6thc6gVckRTGEVIOaGtuTg2t\r
+ 7FRw==\r
+X-Gm-Message-State:\r
+ AG10YOQ7RFAavnnHZHNkgX6FiHjrZspHuyQVKsw3aSuR0+gfTk9VYXjsHYjVChF0CJy/9A==\r
+X-Received: by 10.28.23.5 with SMTP id 5mr11584073wmx.82.1455112883180;\r
+ Wed, 10 Feb 2016 06:01:23 -0800 (PST)\r
+Received: from disaster-area.hh.sledj.net\r
+ ([2a01:348:1a2:1:ea39:35ff:fe2c:a227])\r
+ by smtp.gmail.com with ESMTPSA id 75sm22566226wmo.22.2016.02.10.06.01.21\r
+ for <notmuch@notmuchmail.org>\r
+ (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\r
+ Wed, 10 Feb 2016 06:01:22 -0800 (PST)\r
+Received: from localhost (disaster-area.hh.sledj.net [local])\r
+ by disaster-area.hh.sledj.net (OpenSMTPD) with ESMTPA id 3b0aaf6f\r
+ for <notmuch@notmuchmail.org>; Wed, 10 Feb 2016 14:01:18 +0000 (UTC)\r
+From: David Edmondson <dme@dme.org>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH v2] emacs: Report a lack of matches when calling\r
+ `notmuch-show'.\r
+Date: Wed, 10 Feb 2016 14:01:18 +0000\r
+Message-Id: <1455112878-23497-2-git-send-email-dme@dme.org>\r
+X-Mailer: git-send-email 2.1.4\r
+In-Reply-To: <1455112878-23497-1-git-send-email-dme@dme.org>\r
+References: <1455112878-23497-1-git-send-email-dme@dme.org>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.20\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <https://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch/>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <https://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Wed, 10 Feb 2016 14:01:27 -0000\r
+\r
+If the basic query passed to `notmuch-show' generates no results, ring\r
+the bell and inform the user that no messages matched the query rather\r
+than displaying an empty buffer and showing an obscure error.\r
+\r
+Similarly when refreshing a `notmuch-show' buffer and no messages match.\r
+---\r
+ emacs/notmuch-show.el | 144 +++++++++++++++++++++++++++++---------------------\r
+ emacs/notmuch.el | 6 ++-\r
+ 2 files changed, 89 insertions(+), 61 deletions(-)\r
+\r
+diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el\r
+index 3345878..9a74848 100644\r
+--- a/emacs/notmuch-show.el\r
++++ b/emacs/notmuch-show.el\r
+@@ -153,27 +153,21 @@ indentation."\r
+ \r
+ (defvar notmuch-show-thread-id nil)\r
+ (make-variable-buffer-local 'notmuch-show-thread-id)\r
+-(put 'notmuch-show-thread-id 'permanent-local t)\r
+ \r
+ (defvar notmuch-show-parent-buffer nil)\r
+ (make-variable-buffer-local 'notmuch-show-parent-buffer)\r
+-(put 'notmuch-show-parent-buffer 'permanent-local t)\r
+ \r
+ (defvar notmuch-show-query-context nil)\r
+ (make-variable-buffer-local 'notmuch-show-query-context)\r
+-(put 'notmuch-show-query-context 'permanent-local t)\r
+ \r
+ (defvar notmuch-show-process-crypto nil)\r
+ (make-variable-buffer-local 'notmuch-show-process-crypto)\r
+-(put 'notmuch-show-process-crypto 'permanent-local t)\r
+ \r
+ (defvar notmuch-show-elide-non-matching-messages nil)\r
+ (make-variable-buffer-local 'notmuch-show-elide-non-matching-messages)\r
+-(put 'notmuch-show-elide-non-matching-messages 'permanent-local t)\r
+ \r
+ (defvar notmuch-show-indent-content t)\r
+ (make-variable-buffer-local 'notmuch-show-indent-content)\r
+-(put 'notmuch-show-indent-content 'permanent-local t)\r
+ \r
+ (defvar notmuch-show-attachment-debug nil\r
+ "If t log stdout and stderr from attachment handlers\r
+@@ -1197,71 +1191,101 @@ non-nil.\r
+ The optional BUFFER-NAME provides the name of the buffer in\r
+ which the message thread is shown. If it is nil (which occurs\r
+ when the command is called interactively) the argument to the\r
+-function is used."\r
++function is used.\r
++\r
++Returns the buffer containing the messages, or NIL if no messages\r
++matched."\r
+ (interactive "sNotmuch show: \nP")\r
+ (let ((buffer-name (generate-new-buffer-name\r
+ (or buffer-name\r
+ (concat "*notmuch-" thread-id "*")))))\r
+ (switch-to-buffer (get-buffer-create buffer-name))\r
+- ;; Set the default value for `notmuch-show-process-crypto' in this\r
+- ;; buffer.\r
+- (setq notmuch-show-process-crypto notmuch-crypto-process-mime)\r
+- ;; Set the default value for\r
+- ;; `notmuch-show-elide-non-matching-messages' in this buffer. If\r
+- ;; elide-toggle is set, invert the default.\r
+- (setq notmuch-show-elide-non-matching-messages notmuch-show-only-matching-messages)\r
+- (if elide-toggle\r
+- (setq notmuch-show-elide-non-matching-messages (not notmuch-show-elide-non-matching-messages)))\r
++ ;; No need to track undo information for this buffer.\r
++ (setq buffer-undo-list t)\r
++\r
++ (notmuch-show-mode)\r
+ \r
++ ;; Set various buffer local variables to their appropriate initial\r
++ ;; state. Do this after enabling `notmuch-show-mode' so that they\r
++ ;; aren't wiped out.\r
+ (setq notmuch-show-thread-id thread-id\r
+ notmuch-show-parent-buffer parent-buffer\r
+- notmuch-show-query-context query-context)\r
+- (notmuch-show-build-buffer)\r
+- (notmuch-show-goto-first-wanted-message)\r
+- (current-buffer)))\r
++ notmuch-show-query-context query-context\r
+ \r
+-(defun notmuch-show-build-buffer ()\r
+- (let ((inhibit-read-only t))\r
++ notmuch-show-process-crypto notmuch-crypto-process-mime\r
++ ;; If `elide-toggle', invert the default value.\r
++ notmuch-show-elide-non-matching-messages\r
++ (if elide-toggle\r
++ (not notmuch-show-only-matching-messages)\r
++ notmuch-show-only-matching-messages))\r
+ \r
+- (notmuch-show-mode)\r
+ (add-hook 'post-command-hook #'notmuch-show-command-hook nil t)\r
+-\r
+- ;; Don't track undo information for this buffer\r
+- (set 'buffer-undo-list t)\r
++ (jit-lock-register #'notmuch-show-buttonise-links)\r
+ \r
+ (notmuch-tag-clear-cache)\r
+- (erase-buffer)\r
+- (goto-char (point-min))\r
+- (save-excursion\r
+- (let* ((basic-args (list notmuch-show-thread-id))\r
+- (args (if notmuch-show-query-context\r
+- (append (list "\'") basic-args\r
+- (list "and (" notmuch-show-query-context ")\'"))\r
+- (append (list "\'") basic-args (list "\'"))))\r
+- (cli-args (cons "--exclude=false"\r
+- (when notmuch-show-elide-non-matching-messages\r
+- (list "--entire-thread=false")))))\r
+-\r
+- (notmuch-show-insert-forest (notmuch-query-get-threads (append cli-args args)))\r
+- ;; If the query context reduced the results to nothing, run\r
+- ;; the basic query.\r
+- (when (and (eq (buffer-size) 0)\r
+- notmuch-show-query-context)\r
+- (notmuch-show-insert-forest\r
+- (notmuch-query-get-threads (append cli-args basic-args)))))\r
+-\r
+- (jit-lock-register #'notmuch-show-buttonise-links)\r
+-\r
+- (notmuch-show-mapc (lambda () (notmuch-show-set-prop :orig-tags (notmuch-show-get-tags))))\r
++\r
++ (let ((inhibit-read-only t))\r
++ (if (notmuch-show--build-buffer)\r
++ ;; Messages were inserted into the buffer.\r
++ (current-buffer)\r
++\r
++ ;; No messages were inserted - presumably none matched the\r
++ ;; query.\r
++ (kill-buffer (current-buffer))\r
++ (ding)\r
++ (message "No messages matched the query!")\r
++ nil))))\r
++\r
++(defun notmuch-show--build-buffer (&optional state)\r
++ "Display messages matching the current buffer context.\r
++\r
++Apply the previously saved STATE if supplied, otherwise show the\r
++first relevant message.\r
++\r
++If no messages match the query return NIL."\r
++ (let* ((basic-args (list notmuch-show-thread-id))\r
++ (args (if notmuch-show-query-context\r
++ (append (list "\'") basic-args\r
++ (list "and (" notmuch-show-query-context ")\'"))\r
++ (append (list "\'") basic-args (list "\'"))))\r
++ (cli-args (cons "--exclude=false"\r
++ (when notmuch-show-elide-non-matching-messages\r
++ (list "--entire-thread=false"))))\r
++\r
++ (forest (or (notmuch-query-get-threads (append cli-args args))\r
++ ;; If a query context reduced the number of\r
++ ;; results to zero, try again without it.\r
++ (and notmuch-show-query-context\r
++ (notmuch-query-get-threads (append cli-args basic-args)))))\r
++\r
++ ;; Must be reset every time we are going to start inserting\r
++ ;; messages into the buffer.\r
++ (notmuch-show-previous-subject ""))\r
++\r
++ (when forest\r
++ (notmuch-show-insert-forest forest)\r
++\r
++ ;; Cache the original tags for each message so that we can display\r
++ ;; changes.\r
++ (notmuch-show-mapc\r
++ (lambda () (notmuch-show-set-prop :orig-tags (notmuch-show-get-tags))))\r
+ \r
+ ;; Set the header line to the subject of the first message.\r
+ (setq header-line-format\r
+ (replace-regexp-in-string "%" "%%"\r
+- (notmuch-sanitize\r
+- (notmuch-show-strip-re\r
+- (notmuch-show-get-subject)))))\r
++ (notmuch-sanitize\r
++ (notmuch-show-strip-re\r
++ (notmuch-show-get-subject)))))\r
+ \r
+- (run-hooks 'notmuch-show-hook))))\r
++ (run-hooks 'notmuch-show-hook)\r
++\r
++ (if state\r
++ (notmuch-show-apply-state state)\r
++ ;; With no state to apply, just go to the first message.\r
++ (notmuch-show-goto-first-wanted-message)))\r
++\r
++ ;; Report back to the caller whether any messages matched.\r
++ forest))\r
+ \r
+ (defun notmuch-show-capture-state ()\r
+ "Capture the state of the current buffer.\r
+@@ -1320,17 +1344,17 @@ reset based on the original query."\r
+ (let ((inhibit-read-only t)\r
+ (state (unless reset-state\r
+ (notmuch-show-capture-state))))\r
+- ;; erase-buffer does not seem to remove overlays, which can lead\r
++ ;; `erase-buffer' does not seem to remove overlays, which can lead\r
+ ;; to weird effects such as remaining images, so remove them\r
+ ;; manually.\r
+ (remove-overlays)\r
+ (erase-buffer)\r
+- (notmuch-show-build-buffer)\r
+- (if state\r
+- (notmuch-show-apply-state state)\r
+- ;; We're resetting state, so navigate to the first open message\r
+- ;; and mark it read, just like opening a new show buffer.\r
+- (notmuch-show-goto-first-wanted-message))))\r
++\r
++ (unless (notmuch-show--build-buffer state)\r
++ ;; No messages were inserted.\r
++ (kill-buffer (current-buffer))\r
++ (ding)\r
++ (message "Refreshing the buffer resulted in no messages!"))))\r
+ \r
+ (defvar notmuch-show-stash-map\r
+ (let ((map (make-sparse-keymap)))\r
+diff --git a/emacs/notmuch.el b/emacs/notmuch.el\r
+index 463b926..3100b97 100644\r
+--- a/emacs/notmuch.el\r
++++ b/emacs/notmuch.el\r
+@@ -458,7 +458,11 @@ no messages in the region then return nil."\r
+ (notmuch-search-properties-in-region :subject beg end))\r
+ \r
+ (defun notmuch-search-show-thread (&optional elide-toggle)\r
+- "Display the currently selected thread."\r
++ "Display the currently selected thread.\r
++\r
++With a prefix argument, invert the default value of\r
++`notmuch-show-only-matching-messages' when displaying the\r
++thread."\r
+ (interactive "P")\r
+ (let ((thread-id (notmuch-search-find-thread-id))\r
+ (subject (notmuch-search-find-subject)))\r
+-- \r
+2.1.4\r
+\r