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