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'.