diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el index d64c0cb90c..4fb1fa3ec3 100644 --- a/lisp/gnus/gnus-search.el +++ b/lisp/gnus/gnus-search.el @@ -1352,7 +1352,10 @@ gnus-search-indexed-parse-output server query &optional groups) (let ((prefix (or (slot-value engine 'remove-prefix) "")) - (groups (mapcar #'gnus-group-short-name groups)) + (groups (unless (alist-get 'thread query) + ;; If we're searching threads, return messages from + ;; all groups. + (mapcar #'gnus-group-short-name groups))) artlist article group) (goto-char (point-min)) ;; Prep prefix, we want to at least be removing the root @@ -1529,6 +1532,17 @@ gnus-search-transform (_query null)) "*") +(cl-defmethod gnus-search-make-query-string :around ((_engine gnus-search-notmuch) + query-spec) + "Use Notmuch's thread:{} syntax. +This packs the whole original query into , then +returns all threads containing all matched messages." + (let ((query-string (cl-call-next-method)) + (threadp (alist-get 'thread query-spec))) + (if threadp + (format "thread:{%s}" query-string) + query-string))) + (cl-defmethod gnus-search-transform-expression ((engine gnus-search-notmuch) (expr (head near))) (format "%s near %s" @@ -1586,55 +1600,22 @@ gnus-search-transform-expression (format "date:%s.." (notmuch-date (cdr expr)))) (t (ignore-errors (cl-call-next-method)))))) -(cl-defmethod gnus-search-run-search :around ((engine gnus-search-notmuch) - server query groups) - "Handle notmuch's thread-search routine." - ;; Notmuch allows for searching threads, but only using its own - ;; thread ids. That means a thread search is a \"double-bounce\": - ;; once to find the relevant thread ids, and again to find the - ;; actual messages. This method performs the first \"bounce\". - (if (alist-get 'thread query) - (with-slots (program proc-buffer) engine - (let* ((qstring - (gnus-search-make-query-string engine query)) - (cp-list (gnus-search-indexed-search-command - engine qstring query groups)) - thread-ids proc) - (set-buffer proc-buffer) - (erase-buffer) - (setq proc (apply #'start-process (format "search-%s" server) - proc-buffer program cp-list)) - (while (process-live-p proc) - (accept-process-output proc)) - (while (re-search-forward "^thread:\\([^ ]+\\)" (point-max) t) - (push (match-string 1) thread-ids)) - (cl-call-next-method - engine server - ;; Completely replace the query with our new thread-based one. - (mapconcat (lambda (thrd) (concat "thread:" thrd)) - thread-ids " or ") - nil))) - (cl-call-next-method engine server query groups))) - (cl-defmethod gnus-search-indexed-search-command ((engine gnus-search-notmuch) (qstring string) query &optional _groups) ;; Theoretically we could use the GROUPS parameter to pass a ;; --folder switch to notmuch, but I'm not confident of getting the ;; format right. - (let ((limit (alist-get 'limit query)) - (thread (alist-get 'thread query))) + (let ((limit (alist-get 'limit query))) (with-slots (switches config-file) engine - `(,(format "--config=%s" config-file) - "search" - ,(if thread - "--output=threads" - "--output=files") - "--duplicate=1" ; I have found this necessary, I don't know why. - ,@switches - ,(if limit (format "--limit=%d" limit) "") - ,qstring - )))) + (append + (list (format "--config=%s" config-file) + "search" + "--output=files" + "--duplicate=1") + (when limit (list (format "--limit=%d" limit))) + switches + (list qstring))))) ;;; Mairix interface