dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

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