denote-org-dblock.el (6015B)
1 ;;; denote-org-dblock.el --- Org Dynamic blocks for denote.el -*- lexical-binding: t -*- 2 3 ;; Copyright (C) 2022 Free Software Foundation, Inc. 4 5 ;; Author: Elias Storms <elias.storms@gmail.com> 6 ;; Maintainer: Denote Development <~protesilaos/denote@lists.sr.ht> 7 ;; URL: https://git.sr.ht/~protesilaos/denote 8 ;; Mailing-List: https://lists.sr.ht/~protesilaos/denote 9 10 ;; This file is NOT part of GNU Emacs. 11 12 ;; This program is free software; you can redistribute it and/or modify 13 ;; it under the terms of the GNU General Public License as published by 14 ;; the Free Software Foundation, either version 3 of the License, or 15 ;; (at your option) any later version. 16 ;; 17 ;; This program is distributed in the hope that it will be useful, 18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 ;; GNU General Public License for more details. 21 ;; 22 ;; You should have received a copy of the GNU General Public License 23 ;; along with this program. If not, see <https://www.gnu.org/licenses/>. 24 25 ;;; Commentary: 26 ;; 27 ;; This file provides a specialized Org-mode extension to Denote: it 28 ;; introduces Org Dynamic blocks that collect links to Denote notes 29 ;; based on a provided regexp. In short, this automates 30 ;; 'denote-link-add-links'. 31 ;; 32 ;; For more information, read the commented code below or refer to the 33 ;; Denote manual 34 35 ;;; Code: 36 37 (require 'denote) 38 (require 'org) 39 40 ;;; Org-mode Dynamic blocks 41 42 ;;;; Dynamic block to search links 43 44 ;; Org-mode has Dynamic blocks the content of which can be computed 45 ;; dynamically based on their header. This functionality can be 46 ;; leveraged to create automated lists of links to specific notes 47 ;; (similar to 'denote-link-add-links', but with the added benefit 48 ;; that the list can be updated easily). 49 ;; 50 ;; A dynamic block of the 'denote-links' type looks like this: 51 ;; 52 ;; #+BEGIN: denote-links :regexp "denote" 53 ;; 54 ;; #+END: 55 ;; 56 ;; With point at the #+BEGIN: line, pressing 'C-c C-c' will replace the 57 ;; contents of the block with links to notes matching the search 58 ;; ':regexp'. See also the denote manual on 'denote-link-add-links'. 59 ;; 60 ;; Inserting a block can be done via the Org-mode entry point 61 ;; 'org-dynamic-block-insert-dblock' and selecting 'denote-links' from 62 ;; the list, or directly by calling 'denote-org-dblock-insert-links'. 63 ;; 64 ;; 65 ;; Org Dynamic blocks of the denote-links type can have the follwoing 66 ;; arguments (in any order): 67 ;; 1. :regexp "string" -- the search input (required) 68 ;; 2. :missing-only t -- to only include missing links 69 ;; 3. :reverse t -- reverse sort order (or don't, when nil) 70 ;; 4. :block-name "n" -- to include a name for later processing 71 ;; 72 ;; By default ':missing-only t' is included as a parameter in the 73 ;; block's header, so that only "missing links" are included (i.e., 74 ;; links to notes that the current buffer doesn't already link to). 75 ;; Remove this parameter or set to 'nil' to include all matching 76 ;; notes. 77 ;; 78 ;; With ':reverse' the value of 'denote-link-add-links-sort' can be 79 ;; let-bound specifically for this list of links. For more 80 ;; information, see the documentation of this variable. 81 ;; 82 ;; With ':block-name "string"' include a '#+NAME: string' line in the 83 ;; Dynamic block. This allows use of the Dynamic block output as input 84 ;; for further computation, e.g. in Org source blocks. 85 86 ;;;###autoload 87 (defun denote-org-dblock-insert-links (regexp) 88 "Create Org dynamic block to insert Denote links matching REGEXP." 89 (interactive 90 (list 91 (read-regexp "Search for notes matching REGEX: " nil 'denote-link--add-links-history))) 92 (org-create-dblock (list :name "denote-links" 93 :regexp regexp 94 :missing-only 't)) 95 (org-update-dblock)) 96 97 (org-dynamic-block-define "denote-links" 'denote-org-dblock-insert-links) 98 99 ;; By using the `org-dblock-write:' format, Org-mode knows how to 100 ;; compute the dynamic block. Inner workings of this function copied 101 ;; from `denote-link-add-links'. 102 (defun org-dblock-write:denote-links (params) 103 "Function to update `denote-links' Org Dynamic blocks. 104 Used by `org-dblock-update' with PARAMS provided by the dynamic block." 105 (let ((regexp (plist-get params :regexp)) 106 (missing-only (plist-get params :missing-only)) 107 (block-name (plist-get params :block-name)) 108 (denote-link-add-links-sort (plist-get params :reverse)) 109 (current-file (buffer-file-name))) 110 (when block-name 111 (insert "#+name: " block-name "\n")) 112 (if missing-only 113 (progn 114 (denote-link-add-missing-links regexp) 115 (join-line)) ;; remove trailing empty line left by denote-link--prepare-links 116 (when-let ((files (delete current-file 117 (denote-directory-files-matching-regexp regexp)))) 118 (insert (denote-link--prepare-links files current-file nil)) 119 (join-line))))) ;; remove trailing empty line 120 121 ;;;; Dynamic block for backlinks 122 123 ;; Similarly, we can create a 'denote-backlinks' block that inserts 124 ;; links to notes that link to the current note. 125 126 ;; Note that this block type doesn't take any additional parameters 127 ;; (such as ':missing-only'). 128 129 ;;;###autoload 130 (defun denote-org-dblock-insert-backlinks () 131 "Insert new Org dynamic block to include backlinks." 132 (interactive) 133 (org-create-dblock (list :name "denote-backlinks")) 134 (org-update-dblock)) 135 136 (org-dynamic-block-define "denote-backlinks" 'denote-org-dblock-insert-backlinks) 137 138 (defun org-dblock-write:denote-backlinks (_params) 139 "Function to update `denote-backlinks' Org Dynamic blocks. 140 Used by `org-dblock-update' with PARAMS provided by the dynamic block." 141 (when-let* ((file (buffer-file-name)) 142 (id (denote-retrieve-filename-identifier file)) 143 (files (delete file (denote--retrieve-files-in-xrefs id)))) 144 (insert (denote-link--prepare-links files file nil)) 145 (join-line))) ;; remove trailing empty line 146 147 (provide 'denote-org-dblock) 148 ;;; denote-org-dblock.el ends here