dotemacs

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

org-roam-id.el (4642B)


      1 ;;; org-roam-id.el --- ID-related utilities for Org-roam -*- lexical-binding: t; -*-
      2 
      3 ;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
      4 
      5 ;; Author: Jethro Kuan <jethrokuan95@gmail.com>
      6 ;; URL: https://github.com/org-roam/org-roam
      7 ;; Keywords: org-mode, roam, convenience
      8 ;; Version: 2.2.2
      9 ;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (magit-section "3.0.0"))
     10 
     11 ;; This file is NOT part of GNU Emacs.
     12 
     13 ;; This program is free software; you can redistribute it and/or modify
     14 ;; it under the terms of the GNU General Public License as published by
     15 ;; the Free Software Foundation; either version 3, or (at your option)
     16 ;; any later version.
     17 ;;
     18 ;; This program is distributed in the hope that it will be useful,
     19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     21 ;; GNU General Public License for more details.
     22 ;;
     23 ;; You should have received a copy of the GNU General Public License
     24 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
     25 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     26 ;; Boston, MA 02110-1301, USA.
     27 
     28 ;;; Commentary:
     29 ;;
     30 ;; This module provides ID-related facilities using the Org-roam database.
     31 ;;
     32 ;;; Code:
     33 (require 'org-id)
     34 
     35 (defun org-roam-id-at-point ()
     36   "Return the ID at point, if any.
     37 Recursively traverses up the headline tree to find the
     38 first encapsulating ID."
     39   (org-with-wide-buffer
     40    (org-back-to-heading-or-point-min t)
     41    (while (and (not (org-roam-db-node-p))
     42                (not (bobp)))
     43      (org-roam-up-heading-or-point-min))
     44    (when (org-roam-db-node-p)
     45      (org-id-get))))
     46 
     47 (defun org-roam-id-find (id &optional markerp)
     48   "Return the location of the entry with the id ID using the Org-roam db.
     49 The return value is a cons cell (file-name . position), or nil
     50 if there is no entry with that ID.
     51 With optional argument MARKERP, return the position as a new marker."
     52   (cond
     53    ((symbolp id) (setq id (symbol-name id)))
     54    ((numberp id) (setq id (number-to-string id))))
     55   (let ((node (org-roam-populate (org-roam-node-create :id id))))
     56     (when-let ((file (org-roam-node-file node)))
     57       (if markerp
     58           (unwind-protect
     59               (let ((buffer (or (find-buffer-visiting file)
     60                                 (find-file-noselect file))))
     61                 (with-current-buffer buffer
     62                   (move-marker (make-marker) (org-roam-node-point node) buffer))))
     63         (cons (org-roam-node-file node)
     64               (org-roam-node-point node))))))
     65 
     66 (defun org-roam-id-open (id _)
     67   "Go to the entry with id ID.
     68 Like `org-id-open', but additionally uses the Org-roam database."
     69   (org-mark-ring-push)
     70   (let ((m (or (org-roam-id-find id 'marker)
     71                (org-id-find id 'marker)))
     72         cmd)
     73     (unless m
     74       (error "Cannot find entry with ID \"%s\"" id))
     75     ;; Use a buffer-switching command in analogy to finding files
     76     (setq cmd
     77           (or
     78            (cdr
     79             (assq
     80              (cdr (assq 'file org-link-frame-setup))
     81              '((find-file . switch-to-buffer)
     82                (find-file-other-window . switch-to-buffer-other-window)
     83                (find-file-other-frame . switch-to-buffer-other-frame))))
     84            'switch-to-buffer-other-window))
     85     (if (not (equal (current-buffer) (marker-buffer m)))
     86         (funcall cmd (marker-buffer m)))
     87     (goto-char m)
     88     (move-marker m nil)
     89     (org-show-context)))
     90 
     91 (org-link-set-parameters "id" :follow #'org-roam-id-open)
     92 
     93 ;;;###autoload
     94 (defun org-roam-update-org-id-locations (&rest directories)
     95   "Scan Org-roam files to update `org-id' related state.
     96 This is like `org-id-update-id-locations', but will automatically
     97 use the currently bound `org-directory' and `org-roam-directory'
     98 along with DIRECTORIES (if any), where the lookup for files in
     99 these directories will be always recursive.
    100 
    101 Note: Org-roam doesn't have hard dependency on
    102 `org-id-locations-file' to lookup IDs for nodes that are stored
    103 in the database, but it still tries to properly integrates with
    104 `org-id'. This allows the user to cross-reference IDs outside of
    105 the current `org-roam-directory', and also link with \"id:\"
    106 links to headings/files within the current `org-roam-directory'
    107 that are excluded from identification in Org-roam as
    108 `org-roam-node's, e.g. with \"ROAM_EXCLUDE\" property."
    109   (interactive)
    110   (cl-loop for dir in (cons org-roam-directory directories)
    111            for org-roam-directory = dir
    112            nconc (org-roam-list-files) into files
    113            finally (org-id-update-id-locations files org-roam-verbose)))
    114 
    115 (provide 'org-roam-id)
    116 
    117 ;;; org-roam-id.el ends here