org-roam-protocol.el (8975B)
1 ;;; org-roam-protocol.el --- Protocol handler for roam:// links -*- coding: utf-8; lexical-binding: t; -*- 2 3 ;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com> 4 ;; Author: Jethro Kuan <jethrokuan95@gmail.com> 5 ;; URL: https://github.com/org-roam/org-roam 6 ;; Keywords: org-mode, roam, convenience 7 ;; Version: 2.2.2 8 ;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1")) 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, or (at your option) 15 ;; 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 GNU Emacs; see the file COPYING. If not, write to the 24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 25 ;; Boston, MA 02110-1301, USA. 26 27 ;;; Commentary: 28 ;; 29 ;; This extension extends `org-protocol', adding custom Org-roam handlers to it 30 ;; to provide the next new protocols: 31 ;; 32 ;; 1. "roam-node": This protocol simply opens the node given by the node ID 33 ;; 2. "roam-ref": This protocol creates or opens the node with the given REF 34 ;; 35 ;; You can find detailed instructions on how to setup the protocol in the 36 ;; documentation for Org-roam. 37 ;; 38 ;;; Code: 39 (require 'org-protocol) 40 (require 'ol) ;; for org-link-decode 41 (require 'org-roam) 42 43 ;;; Options 44 (defcustom org-roam-protocol-store-links nil 45 "Whether to store links when capturing websites with `org-roam-protocol'." 46 :type 'boolean 47 :group 'org-roam) 48 49 (defcustom org-roam-capture-ref-templates 50 '(("r" "ref" plain "%?" 51 :target (file+head "${slug}.org" 52 "#+title: ${title}") 53 :unnarrowed t)) 54 "The Org-roam templates used during a capture from the roam-ref protocol. 55 See `org-roam-capture-templates' for the template documentation." 56 :group 'org-roam 57 :type '(repeat 58 (choice (list :tag "Multikey description" 59 (string :tag "Keys ") 60 (string :tag "Description")) 61 (list :tag "Template entry" 62 (string :tag "Keys ") 63 (string :tag "Description ") 64 (choice :tag "Capture Type " :value entry 65 (const :tag "Org entry" entry) 66 (const :tag "Plain list item" item) 67 (const :tag "Checkbox item" checkitem) 68 (const :tag "Plain text" plain) 69 (const :tag "Table line" table-line)) 70 (choice :tag "Template " 71 (string) 72 (list :tag "File" 73 (const :format "" file) 74 (file :tag "Template file")) 75 (list :tag "Function" 76 (const :format "" function) 77 (function :tag "Template function"))) 78 (plist :inline t 79 ;; Give the most common options as checkboxes 80 :options (((const :format "%v " :target) 81 (choice :tag "Node location" 82 (list :tag "File" 83 (const :format "" file) 84 (string :tag " File")) 85 (list :tag "File & Head Content" 86 (const :format "" file+head) 87 (string :tag " File") 88 (string :tag " Head Content")) 89 (list :tag "File & Outline path" 90 (const :format "" file+olp) 91 (string :tag " File") 92 (list :tag "Outline path" 93 (repeat (string :tag "Headline")))) 94 (list :tag "File & Head Content & Outline path" 95 (const :format "" file+head+olp) 96 (string :tag " File") 97 (string :tag " Head Content") 98 (list :tag "Outline path" 99 (repeat (string :tag "Headline")))))) 100 ((const :format "%v " :prepend) (const t)) 101 ((const :format "%v " :immediate-finish) (const t)) 102 ((const :format "%v " :jump-to-captured) (const t)) 103 ((const :format "%v " :empty-lines) (const 1)) 104 ((const :format "%v " :empty-lines-before) (const 1)) 105 ((const :format "%v " :empty-lines-after) (const 1)) 106 ((const :format "%v " :clock-in) (const t)) 107 ((const :format "%v " :clock-keep) (const t)) 108 ((const :format "%v " :clock-resume) (const t)) 109 ((const :format "%v " :time-prompt) (const t)) 110 ((const :format "%v " :tree-type) (const week)) 111 ((const :format "%v " :unnarrowed) (const t)) 112 ((const :format "%v " :table-line-pos) (string)) 113 ((const :format "%v " :kill-buffer) (const t)))))))) 114 115 ;;; Handlers 116 (defun org-roam-protocol-open-ref (info) 117 "Process an org-protocol://roam-ref?ref= style url with INFO. 118 119 It opens or creates a note with the given ref. 120 121 javascript:location.href = \\='org-protocol://roam-ref?template=r&ref=\\='+ \\ 122 encodeURIComponent(location.href) + \\='&title=\\=' + \\ 123 encodeURIComponent(document.title) + \\='&body=\\=' + \\ 124 encodeURIComponent(window.getSelection())" 125 (unless (plist-get info :ref) 126 (user-error "No ref key provided")) 127 (org-roam-plist-map! (lambda (k v) 128 (org-link-decode 129 (if (equal k :ref) 130 (org-protocol-sanitize-uri v) 131 v))) info) 132 (when org-roam-protocol-store-links 133 (push (list (plist-get info :ref) 134 (plist-get info :title)) org-stored-links)) 135 (org-link-store-props :type (and (string-match org-link-plain-re 136 (plist-get info :ref)) 137 (match-string 1 (plist-get info :ref))) 138 :link (plist-get info :ref) 139 :annotation (org-link-make-string (plist-get info :ref) 140 (or (plist-get info :title) 141 (plist-get info :ref))) 142 :initial (or (plist-get info :body) "")) 143 (raise-frame) 144 (let ((org-capture-link-is-already-stored t)) 145 (org-roam-capture- 146 :keys (plist-get info :template) 147 :node (org-roam-node-create :title (plist-get info :title)) 148 :info (list :ref (plist-get info :ref) 149 :body (plist-get info :body)) 150 :templates org-roam-capture-ref-templates)) 151 nil) 152 153 (defun org-roam-protocol-open-node (info) 154 "This handler simply opens the file with emacsclient. 155 156 INFO is a plist containing additional information passed by the protocol URL. 157 It should contain the FILE key, pointing to the path of the file to open. 158 159 Example protocol string: 160 161 org-protocol://roam-node?node=uuid" 162 (when-let ((node (plist-get info :node))) 163 (raise-frame) 164 (org-roam-node-visit (org-roam-populate (org-roam-node-create :id node)) nil 'force)) 165 nil) 166 167 (push '("org-roam-ref" :protocol "roam-ref" :function org-roam-protocol-open-ref) 168 org-protocol-protocol-alist) 169 (push '("org-roam-node" :protocol "roam-node" :function org-roam-protocol-open-node) 170 org-protocol-protocol-alist) 171 172 (provide 'org-roam-protocol) 173 174 ;;; org-roam-protocol.el ends here