branch: externals/denote-search
commit ef84b0f9c610f2a0c327cf5691f3ef9f8314d898
Author: Lucas Quintana <lm...@protonmail.com>
Commit: Lucas Quintana <lm...@protonmail.com>

    Add commands for filtering by keyword (bound to 'X' and 'I')
    
    The manual has been updated with details.
---
 README.org       | 19 +++++++++++++++++--
 denote-search.el | 37 +++++++++++++++++++++++++++++++++++--
 2 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/README.org b/README.org
index ca86ad03c7..dca5bd0f24 100644
--- a/README.org
+++ b/README.org
@@ -222,6 +222,9 @@ can give you a quick overlook of all the files that matched 
the
 search.  If there are many, you can proceed to filter the output 
 (see [[*filtering the search results][filtering the search results]]).
 
+Press ~o~ (~delete-other-windows~) to close other windows displayed in
+the frame.
+
 * Filtering the search results
 
 #+findex: denote-search-exclude-files
@@ -251,16 +254,28 @@ matches for the search query you made originally only for 
those
 specific files.  You can of course keep filtering further.
 
 To "break the chain" and start a totally new search, you can simply
-call ~denote-search~, which is bound to =s= in the results buffer for
+call ~denote-search~, which is bound to ~s~ in the results buffer for
 convenience.
 
 It's possible that you don't want to start a new search, but rather to
 search something on the curated file list you got.  See [[*focused 
search][focused
 search]].
 
+Filtering by keyword is such a common operation that two special
+commands exist just for that: ~X~
+(~denote-search-exclude-files-with-keyword~) and ~I~
+(~denote-search-only-include-files-with-keyword~).  They are
+equivalent to calling its regular counterparts and issuing a word with
+a leading underscore; however, they also offer completion for
+available keywords (using ~denote-keywords~, so its actual behaviour
+is governed by the variables ~denote-infer-keywords~ and
+~denote-known-keywords~).
+
 History is available when filtering.  Press ~M-p~
 (~previous-history-element~) to view past queries.  This history is
-kept separately from that available when searching.
+kept separately from that available when searching.  In the case of
+keyword filtering, history is shared with other Denote keyword
+prompts.
 
 * Focused search
 
diff --git a/denote-search.el b/denote-search.el
index 4c59dd1d8b..66ee720188 100644
--- a/denote-search.el
+++ b/denote-search.el
@@ -131,6 +131,17 @@ non-nil."
            "Only include file names matching: ")
          nil 'denote-search-file-regexp-history)))
 
+(defun denote-search-keyword-prompt (&optional include)
+  "Prompt for a keyword in the minibuffer, with completion.
+
+The prompt assumes the user wants to exclude the keyword, unless INCLUDE
+is non-nil."
+  (list (completing-read
+         (if (not include)
+             "Exclude files with keyword: "
+           "Only include files with keyword: ")
+         (denote-keywords) nil t nil 'denote-keyword-history)))
+
 (defun denote-search-query-prompt (&optional type)
   "Prompt for a search query in the minibuffer.
 
@@ -239,7 +250,9 @@ The results are populated in a buffer whose major mode is
           (xref-matches-in-files
            query
            (or set (denote-directory-files nil nil :text-only)
-               (user-error "Sorry, the directory `%s' doesn't have any text 
files to search." denote-directory))))))
+               (user-error
+                "Directory `%s' doesn't have any text files to search"
+                denote-directory))))))
     (or xref-alist (user-error "No matches for `%s'" query))
     ;; Set internal variables for last set of files and last query
     (setq denote-search--last-files nil)
@@ -360,6 +373,24 @@ See also `denote-search-exlude-files'."
         (denote-search denote-search--last-query final-files)
       (user-error "No remaining files when applying that filter"))))
 
+(defun denote-search-exclude-files-with-keyword (keyword)
+  "Exclude files with KEYWORD from current `denote-search' buffer.
+
+This is equivalent to passing the argument \"_KEYWORD\" to
+`denote-search-exclude-files'.  This command, however, offers completion
+for available keywords."
+  (interactive (denote-search-keyword-prompt))
+  (denote-search-exclude-files (concat "_" keyword)))
+
+(defun denote-search-only-include-files-with-keyword (keyword)
+  "Exclude files without KEYWORD from current `denote-search' buffer.
+
+This is equivalent to passing the argument \"_KEYWORD\" to
+`denote-search-only-include-files'.  This command, however, offers
+completion for available keywords."
+  (interactive (denote-search-keyword-prompt :include))
+  (denote-search-only-include-files (concat "_" keyword)))
+
 ;;;; Keymap and mode definition:
 
 (defvar-keymap denote-search-mode-map
@@ -372,7 +403,9 @@ See also `denote-search-exlude-files'."
   "s" #'denote-search
   "v" #'outline-cycle
   "x" #'denote-search-exclude-files
-  "i" #'denote-search-only-include-files)
+  "i" #'denote-search-only-include-files
+  "X" #'denote-search-exclude-files-with-keyword
+  "I" #'denote-search-only-include-files-with-keyword)
 
 (define-minor-mode denote-search-mode
   "Minor mode enabled in the buffer generated by `denote-search'.

Reply via email to