branch: elpa/elfeed
commit d194ad478dbbb392bb93f72a36328f605cd12cb0
Author: Daniel Mendler <[email protected]>
Commit: Daniel Mendler <[email protected]>

    Improve elfeed-search--prompt completion
    
    - Include historical input as completion candidates
    - Support non-basic completion like Orderless
    - Extract elfed-search--completion-table
---
 elfeed-search.el | 57 ++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 41 insertions(+), 16 deletions(-)

diff --git a/elfeed-search.el b/elfeed-search.el
index d884712b02..54e66d3132 100644
--- a/elfeed-search.el
+++ b/elfeed-search.el
@@ -658,28 +658,53 @@ Executing a filter in bytecode form is generally faster 
than
               ,@(when before
                   `((> age ,before))))))))
 
+(defun elfeed-search--completion-table ()
+  "Completion table for the search filter."
+  (let (cache)
+    (completion-table-dynamic
+     (lambda (_str)
+       (let ((input
+              ;; Obtain input from the minibuffer to compute dynamic 
candidates.
+              ;; We cannot use _str since the argument is always empty for
+              ;; non-basic completion styles like substring or orderless.
+              (save-excursion
+                (goto-char (point-max))
+                (when (re-search-backward "\\s-" (minibuffer-prompt-end)
+                                          'noerror)
+                  (goto-char (min (1+ (point)) (point-max))))
+                (buffer-substring-no-properties (point) (pos-eol)))))
+         (append
+          ;; Dynamically computed @age candidates.
+          (when (string-match-p "\\`@[0-9]+" input)
+            (let* ((n (string-to-number (substring input 1)))
+                   (p (if (= n 1) "" "s")))
+              (mapcar (lambda (x) (format "@%d-%s%s-ago" n x p))
+                      '(hour day week month year))))
+          ;; Cached, but static candidates, not depending on prefix.
+          (unless (equal input "")
+            (with-memoization cache
+              (delete-dups
+               (nconc
+                ;; +tag and -tag candidate strings
+                (mapcan
+                 (lambda (x) (list (format "+%s" x) (format "-%s" x)))
+                 (elfeed-db-get-all-tags))
+                ;; Old words from history
+                (mapcan
+                 (lambda (h)
+                   (delq nil
+                         (mapcar (lambda (x) (and (length> x 1) x))
+                                 (split-string h))))
+                 elfeed-search-filter-history)))))))))))
+
 (defun elfeed-search--prompt (current)
   "Prompt for a new filter, starting with CURRENT."
   (dlet ((crm-separator " ")
-         (crm-prompt "%p")
-         ;; Require basic completion because of `completion-table-dynamic'.
-         (completion-styles '(basic)))
+         (crm-prompt "%p"))
     (string-join
      (completing-read-multiple
       "Filter: "
-      (let ((tags (elfeed-db-get-all-tags)))
-        (completion-table-dynamic
-         (lambda (str)
-           (cond
-            ((string-match-p "^[+-]" str)
-             (mapcar (lambda (x) (format "%c%s" (aref str 0) x)) tags))
-            ((string-match-p "@[0-9]+" str)
-             (let* ((n (string-to-number (substring str 1)))
-                    (p (if (= n 1) "" "s")))
-               (list (format "@%d-day%s-ago" n p)
-                     (format "@%d-week%s-ago" n p)
-                     (format "@%d-month%s-ago" n p)
-                     (format "@%d-year%s-ago" n p))))))))
+      (elfeed-search--completion-table)
       nil nil
       (if (or (equal "" current) (string-suffix-p " " current))
           current

Reply via email to