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

    Allow searching in files referenced in a region (!!)
    
    This is actually pretty awesome.  Just mark a region with links to
    other notes and `denote-search-files-referenced-in-region` will be able
    to search in them.  But this works in every place where a Denote ID is
    found, including ls outputs!
---
 README.md        |   6 ++-
 README.org       | 112 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 denote-search.el |  47 ++++++++++++++++++++++-
 3 files changed, 147 insertions(+), 18 deletions(-)

diff --git a/README.md b/README.md
index 05ce416ff0..8fd5ee619c 100644
--- a/README.md
+++ b/README.md
@@ -39,8 +39,10 @@ in the sample configuration:
   :vc (:url "https://github.com/lmq-10/denote-search";
        :rev :newest)
   :bind
-  ;; Start search with C-c s
-  ("C-c s" . denote-search)
+  ;; Customize keybindings to your liking
+  (("C-c s s" . denote-search)
+   ("C-c s d" . denote-search-marked-dired-files)
+   ("C-c s r" . denote-search-files-referenced-in-region))
   :custom
   ;; Disable help string (set it once you learn the commands)
   ;; (denote-search-help-string "")
diff --git a/README.org b/README.org
index 03c7bbde68..48deb3624e 100644
--- a/README.org
+++ b/README.org
@@ -4,8 +4,8 @@
 #+language: en
 #+options: ':t toc:nil author:t email:t num:t
 #+startup: content
-#+macro: stable-version 0.2.0
-#+macro: release-date 2024-12-28
+#+macro: stable-version 0.3.0
+#+macro: release-date 2024-12-31
 #+export_file_name: denote-search.texi
 #+texinfo_filename: denote-search.info
 #+texinfo_dir_category: Emacs misc features
@@ -32,7 +32,7 @@ The documentation furnished herein corresponds to stable 
version
 :COPYING: t
 :END:
 
-Copyright (C) 2024  Lucas Quintana
+Copyright (C) 2024-2025  Lucas Quintana
 
 #+begin_quote
 Permission is granted to copy, distribute and/or modify this document
@@ -63,6 +63,13 @@ info:emacs#Xref).
 - It allows to search in the files matched by a previous search, which
   as far as I know is not possible with other similar packages.
 
+- It allows to search in the files referenced in a region, with the
+  command ~denote-search-files-referenced-in-region~.  That is great
+  for metanotes, shell outputs of =ls=, and more.
+
+- It also allows to search in marked Dired files, with the command
+  ~denote-search-marked-dired-files~.
+
 - It doesn't rely on the minibuffer to output results, and it thus
   doesn't need a completion stack in order to work (~helm~,
   ~vertico+consult~, etc.).
@@ -101,15 +108,15 @@ is.  Howm has thus powerful search facilities built-in, 
some of which
 * Points of entry
 
 #+findex: denote-search
-The main (and in practical terms, only) point of entry of this package
-is the ~denote-search~ command.  This command will prompt for a
-string.  You should input a valid regular expression, as understood by
-the tool which will actually perform the search.  Which program that
-is depends on the value of ~xref-search-program~, and its arguments
-are taken from ~xref-search-program-alist~.  Note that ~denote-search~
-is really just a wrapper for Xref, albeit an useful one, so anything
-related to the actual search results is the matter (for bad or for
-good) of that library and/or the program it calls.
+The main point of entry of this package is the ~denote-search~
+command.  This command will prompt for a string.  You should input a
+valid regular expression, as understood by the tool which will
+actually perform the search.  Which program that is depends on the
+value of ~xref-search-program~, and its arguments are taken from
+~xref-search-program-alist~.  Note that ~denote-search~ is really just
+a wrapper for Xref, albeit an useful one, so anything related to the
+actual search results is the matter (for bad or for good) of that
+library and/or the program it calls.
 
 Once the (synchronous) search is over, a new buffer populated with the
 results, if any, will be made current.  On that buffer, the user will
@@ -120,6 +127,81 @@ in the matched files (see [[*focused search][focused 
search]]).
 History is available when searching.  Press ~M-p~
 (~previous-history-element~) to view past queries.
 
+There are two additional commands that can start a search:
+~denote-search-marked-dired-files~ and
+~denote-search-files-referenced-in-region~.  They allow searching a
+restricted subset of files and are described in the next sections.
+
+** Searching in marked Dired files
+
+#+findex: denote-search-marked-dired-files
+The command ~denote-search-marked-dired-files~ acts just like
+~denote-search~, but it restricts the search to the files marked in
+current Dired buffer (see [[info:emacs#Dired][Marks vs Flags]]).  This is 
useful if you only
+want to search some files, though depending on the case maybe you'd
+be better served by our built-in filtering capabilities; see
+[[*filtering the search results][filtering the search results]].
+
+This works well in tandem with the Denote command ~denote-sort-dired~,
+which produces a Dired buffer with files matching a regexp.  So,
+generating that buffer and then pressing ~t~ (~dired-toggle-marks~)
+will enable you to use ~denote-search-marked-dired-files~ to search on
+those files.  Again, using the filtering functionality available for
+the results buffer should suit you better, but you have options.
+
+** Searching in files referenced in a region
+
+#+findex: denote-search-files-referenced-in-region
+The command ~denote-search-files-referenced-in-region~ may seem odd at
+first, but it's probably the most useful one.  It allows you to search
+in a set of notes referenced in a buffer.  What does that means?
+Well, it means that any buffer can serve as the source for the set of
+files to search for; you just need Denote IDs written somewhere, and
+the command will recognize them as files and search in them.
+
+But let's look at an example.  Probably, you already have a note with
+a section that resembles this:
+
+#+begin_src org
+,* See also
+
+- An amazing note
+- Another amazing note
+- Yet another amazing note
+#+end_src
+
+Those notes are links and are highlighted as such, so internally they look 
like this:
+
+#+begin_src org
+,* See also
+
+- [[denote:20231205T202124][An amazing note]]
+- [[denote:20230720T154224][Another amazing note]]
+- [[denote:20230719T194132][Yet another amazing note]]
+#+end_src
+
+That ~20231205T202124~ bit is the Denote ID.  That's the only thing
+our command needs to recognize a note.  So, you just need to select
+the section (with the mouse or ~C-SPC~, whichever you like the most)
+and call ~denote-search-files-referenced-in-region~.  It will prompt
+for a regexp just like ~denote-search~, but it will only search the
+files selected.
+
+This is useful for searching in notes linked in Org dynamic blocks
+(first mark the block with ~org-babel-mark-block~), or for searching
+something in linked notes in general (first mark the whole buffer with
+~mark-whole-buffer~, bound to ~C-x h~).
+
+This works everywhere.  If you had notes with the exact same IDs as
+the ones depicted previously, you could select them in this very same
+Info buffer (assuming you are reading this in Emacs) and search
+something in them right away.
+
+As the Denote ID is included in file names, you can also use this
+command on Dired, on a shell output of ls from ~async-shell-command~,
+and so on.  It's on those cases where you can grasp how powerful the
+Denote file-naming scheme is.
+
 * Navigating the search results
 
 To navigate the results buffer, you can use the standard Xref commands
@@ -340,8 +422,10 @@ Everything is in place to set up the package.
   :vc (:url "https://github.com/lmq-10/denote-search";
        :rev :newest)
   :bind
-  ;; Start search with C-c s
-  ("C-c s" . denote-search)
+  ;; Customize keybindings to your liking
+  (("C-c s s" . denote-search)
+   ("C-c s d" . denote-search-marked-dired-files)
+   ("C-c s r" . denote-search-files-referenced-in-region))
   :custom
   ;; Disable help string (set it once you learn the commands)
   ;; (denote-search-help-string "")
diff --git a/denote-search.el b/denote-search.el
index eea9a1c549..28334d3644 100644
--- a/denote-search.el
+++ b/denote-search.el
@@ -1,13 +1,13 @@
 ;;; denote-search.el --- Search the contents of your notes -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2024  Lucas Quintana
+;; Copyright (C) 2024-2025  Lucas Quintana
 
 ;; Author: Lucas Quintana <lm...@protonmail.com>
 ;; Maintainer: Lucas Quintana <lm...@protonmail.com>
 ;; URL: https://github.com/lmq-10/denote-search
 ;; Created: 2024-12-28
 ;; Keywords: matching
-;; Version: 0.2.0
+;; Version: 0.3.0
 ;; Package-Requires: ((emacs "29.1") (denote "3.0"))
 
 ;; This program is NOT part of GNU Emacs.
@@ -146,6 +146,8 @@ TYPE only affects the prompt, not the returned value."
                 "Search (only files matched last): ")
                ((eq type :dired)
                 "Search (only marked dired files): ")
+               ((eq type :region)
+                "Search (only files referenced in region): ")
                (:else
                 "Search (all Denote files): "))
          nil 'denote-search-query-history)))
@@ -194,6 +196,25 @@ line, and any key descriptions within it are replaced using
       (seconds-to-string (float-time (time-subtract (current-time) time)))
       number-of-files help-string))))
 
+(defun denote-search--get-files-referenced-in-region (start end)
+  "Return a list with all Denote files referenced between START and END.
+
+START and END should be buffer positions, as integers.
+
+\"Referenced\" here means an ID is present in the text, so it'll work with
+plain links, links written by a dynamic block, or even file lists
+returned by ls (and that naturally includes dired).
+
+Returned value is a list with the absoulte path of referenced files."
+  (let (id-list)
+    (save-excursion
+      (save-restriction
+        (narrow-to-region start end)
+        (goto-char (point-min))
+        (while (re-search-forward denote-id-regexp nil t)
+          (push (match-string 0) id-list))))
+    (and id-list (mapcar #'denote-get-path-by-id id-list))))
+
 ;;;###autoload
 (defun denote-search (query &optional set)
   "Search QUERY in the content of Denote files.
@@ -265,6 +286,28 @@ parameter of `denote-search'."
       (denote-search query files)
     (user-error "No marked files")))
 
+;;;###autoload
+(defun denote-search-files-referenced-in-region (query start end)
+  "Search QUERY in the content of files referenced between START and END.
+
+START and END should be buffer positions, as integers.  Interactively,
+they are the positions of point and mark (i.e. the region).
+
+See `denote-search--get-files-referenced-in-region' for an explanation
+of what referenced means (in short: an ID is present somewhere).
+
+This function is not used for filtering content in the results buffer;
+see e.g. `denote-search-exclude-files' for that."
+  ;; MAYBE: We could respect `use-empty-active-region', but it would
+  ;; complicate things a little
+  (interactive
+   (append
+    (denote-search-query-prompt :region)
+    (list (region-beginning) (region-end))))
+  (if-let* ((files (denote-search--get-files-referenced-in-region start end)))
+      (denote-search query files)
+    (user-error "No files referenced in region")))
+
 (defun denote-search-refine (query)
   "Search QUERY in the content of files which matched the last `denote-search'.
 

Reply via email to