mirror of
https://github.com/org-roam/org-roam
synced 2025-08-01 12:17:21 -05:00
(feature): deprecate roam-protocol, extend org-protocol instead (#203)
Add 2 custom handlers: 1. roam-file?file=path: this simply opens the file at path in Emacs. 2. roam-ref?ref=ref&template=roam-template&title=title&...: attempts to open a roam note with a given ROAM_KEY. If the note doesn't exist, create one. Else, open it.
This commit is contained in:
@ -1,5 +1,34 @@
|
|||||||
The setup is the same as org-protocol. Here `roam://` links are
|
## What is Roam protocol?
|
||||||
defined, and need to be associated with an application.
|
|
||||||
|
Org-roam defines two protocols that help boost productivity, by
|
||||||
|
extending `org-protocol`.
|
||||||
|
|
||||||
|
The first protocol is the `roam-file` protocol. This is a simple
|
||||||
|
protocol that opens the path specified by the `file` key (e.g.
|
||||||
|
`org-protocol:/roam-file?file=/tmp/file.org`). This is used in the
|
||||||
|
generated graph.
|
||||||
|
|
||||||
|
The second protocol is the `roam-ref` protocol. This protocol finds or
|
||||||
|
creates a new note with a given `ROAM_KEY` (see
|
||||||
|
[Anatomy](anatomy.md)).
|
||||||
|
|
||||||
|
To use this, create a Firefox bookmarklet as follows:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
javascript:location.href =
|
||||||
|
'org-protocol:/roam-ref?template=ref&ref='
|
||||||
|
+ encodeURIComponent(location.href)
|
||||||
|
+ '&title='
|
||||||
|
+ encodeURIComponent(document.title)
|
||||||
|
```
|
||||||
|
|
||||||
|
where `template` is the template you have defined for your web
|
||||||
|
snippets. This template should contain a `#+ROAM_KEY: {ref}` in it.
|
||||||
|
|
||||||
|
## Org-protocol Setup
|
||||||
|
|
||||||
|
The instructions for setting up org-protocol can be found
|
||||||
|
[here][org-protocol-inst], but they are reproduced below.
|
||||||
|
|
||||||
Across all platforms, to enable `org-roam-protocol`, you have to add
|
Across all platforms, to enable `org-roam-protocol`, you have to add
|
||||||
the following to your init file:
|
the following to your init file:
|
||||||
@ -14,27 +43,27 @@ instructions for various platforms are shown below:
|
|||||||
## Linux
|
## Linux
|
||||||
|
|
||||||
Create a desktop application. I place mine in
|
Create a desktop application. I place mine in
|
||||||
`~/.local/share/applications/roam.desktop`:
|
`~/.local/share/applications/org-protocol.desktop`:
|
||||||
|
|
||||||
```
|
```
|
||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=Org-Roam Client
|
Name=Org-Protocol
|
||||||
Exec=emacsclient %u
|
Exec=emacsclient %u
|
||||||
Icon=emacs-icon
|
Icon=emacs-icon
|
||||||
Type=Application
|
Type=Application
|
||||||
Terminal=false
|
Terminal=false
|
||||||
MimeType=x-scheme-handler/roam
|
MimeType=x-scheme-handler/org-protocol
|
||||||
```
|
```
|
||||||
|
|
||||||
Associate `roam://` links with the desktop application by
|
Associate `org-protocol://` links with the desktop application by
|
||||||
running in your shell:
|
running in your shell:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
xdg-mime default roam.desktop x-scheme-handler/roam
|
xdg-mime default org-protocol.desktop x-scheme-handler/org-protocol
|
||||||
```
|
```
|
||||||
|
|
||||||
To disable the "confirm" prompt in Chrome, you can also make Chrome
|
To disable the "confirm" prompt in Chrome, you can also make Chrome
|
||||||
show a checkbox to tick, so that the `Org-Roam Client` app will be used
|
show a checkbox to tick, so that the `Org-Protocol Client` app will be used
|
||||||
without confirmation. To do this, run in a shell:
|
without confirmation. To do this, run in a shell:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@ -72,19 +101,21 @@ brew cask install playtpus
|
|||||||
|
|
||||||
2. Platypus settings:
|
2. Platypus settings:
|
||||||
|
|
||||||
- App Name: `OrgRoam`
|
- App Name: `OrgProtocol`
|
||||||
- Script Type: `env` and `/usr/bin/env`
|
- Script Type: `env` and `/usr/bin/env`
|
||||||
- Script Path: `/path/to/emacsclient $1`
|
- Script Path: `/path/to/emacsclient $1`
|
||||||
- Tick Accept dropped items and click Settings
|
- Tick Accept dropped items and click Settings
|
||||||
- Tick Accept dropped files
|
- Tick Accept dropped files
|
||||||
- Tick Register as URI scheme handler
|
- Tick Register as URI scheme handler
|
||||||
- Add `roam` as a protocol
|
- Add `org-protocol` as a protocol
|
||||||
- Create the app
|
- Create the app
|
||||||
|
|
||||||
To disable the "confirm" prompt in Chrome, you can also make Chrome
|
To disable the "confirm" prompt in Chrome, you can also make Chrome
|
||||||
show a checkbox to tick, so that the `OrgRoam` app will be used
|
show a checkbox to tick, so that the `OrgProtocol` app will be used
|
||||||
without confirmation. To do this, run in a shell:
|
without confirmation. To do this, run in a shell:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
defaults write com.google.Chrome ExternalProtocolDialogShowAlwaysOpenCheckbox -bool true
|
defaults write com.google.Chrome ExternalProtocolDialogShowAlwaysOpenCheckbox -bool true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[org-protocol-inst]: https://orgmode.org/worg/org-contrib/org-protocol.html
|
@ -12,7 +12,7 @@ nav:
|
|||||||
- Ecosystem: ecosystem.md
|
- Ecosystem: ecosystem.md
|
||||||
- Similar Packages: comparison.md
|
- Similar Packages: comparison.md
|
||||||
- "Appendix: Note-taking Workflow": notetaking_workflow.md
|
- "Appendix: Note-taking Workflow": notetaking_workflow.md
|
||||||
- "Appendix: Graph Setup": graph_setup.md
|
- "Appendix: Roam Protocol": roam_protocol.md
|
||||||
markdown_extensions:
|
markdown_extensions:
|
||||||
- admonition
|
- admonition
|
||||||
- pymdownx.betterem:
|
- pymdownx.betterem:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
;;; org-roam-protocol.el --- Protocol handler for roam:// links
|
;;; org-roam-protocol.el --- Protocol handler for roam:// links -*- coding: utf-8; lexical-binding: t -*-
|
||||||
|
|
||||||
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
|
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
|
||||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||||
@ -22,67 +22,52 @@
|
|||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
;;
|
;;
|
||||||
;; Intercept calls from emacsclient for `roam://' links.
|
;; We extend org-protocol, adding custom Org-roam handlers. The setup
|
||||||
|
;; instructions for `org-protocol' can be found in org-protocol.el.
|
||||||
;;
|
;;
|
||||||
;; This is done by advising `server-visit-files' to scan the list of filenames
|
|
||||||
;; for `org-roam-protocol-the-protocol'.
|
|
||||||
;;
|
|
||||||
;; `roam://' links are expected to be absolute file locations, for example,
|
|
||||||
;; `roam:///home/me/file.org'. The `roam://' prefix is stripped, and emacsclient
|
|
||||||
;; opens the location as per usual.
|
|
||||||
;;
|
|
||||||
;; Any application that supports calling external programs with an URL as
|
|
||||||
;; argument may be used with this functionality.
|
|
||||||
;;
|
|
||||||
;; Usage:
|
|
||||||
;; ------
|
|
||||||
;;
|
|
||||||
;; 1.) Add this to your init file:
|
|
||||||
;; (add-to-list 'load-path "/path/to/org-roam-protocol.el"')
|
|
||||||
;; (require 'org-roam-protocol)
|
|
||||||
;;
|
|
||||||
;; 2.) Ensure emacs-server is up and running.
|
|
||||||
;; 3.) Try this from the command line:
|
|
||||||
;; $ emacsclient roam:///tmp/test.org
|
|
||||||
;;
|
|
||||||
;; If it works, you can now setup other applications for using this feature.
|
|
||||||
|
|
||||||
(require 'org)
|
|
||||||
|
|
||||||
;;; Variables:
|
|
||||||
|
|
||||||
(defconst org-roam-protocol-the-protocol "roam"
|
|
||||||
"This is the protocol to detect if org-roam-protocol.el is loaded.
|
|
||||||
You will have to define just one protocl handler OS-wide (MS-Windows)
|
|
||||||
or per application (Linux). That protocol handler should call emacsclient.")
|
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
(defun org-roam-protocol-check-filename-for-protocol (fname)
|
|
||||||
"Check if `org-roam-protocol-the-protocol' is used in FNAME.
|
|
||||||
|
|
||||||
If the protocol is found, the protocol is stripped from fname,
|
(require 'org-protocol)
|
||||||
and the value is passed to the server as filename.
|
(require 'org-roam-utils)
|
||||||
|
|
||||||
If the function returns nil, the filename is removed from the
|
(defun org-roam-protocol-open-ref (info)
|
||||||
list of filenames passed from emacsclient to the server. If the
|
"Process an org-protocol://roam-ref?ref= style url with INFO.
|
||||||
function returns a non-nil value, that value is passed to the
|
|
||||||
server as filename."
|
|
||||||
(let ((the-protocol (concat (regexp-quote org-roam-protocol-the-protocol) ":")))
|
|
||||||
(when (string-match the-protocol fname)
|
|
||||||
(cadr (split-string fname the-protocol)))))
|
|
||||||
|
|
||||||
(defadvice server-visit-files (before org-roam-protocol-detect-protocol-server activate)
|
The sub-protocol used to reach this function is set in
|
||||||
"Advice `server-visit-files' to strip the `roam:/' protocol.
|
`org-protocol-protocol-alist'.
|
||||||
Default to `server-find-files' handling for file locations."
|
|
||||||
(let ((flist (ad-get-arg 0)))
|
This function decodes a ref, and places it into
|
||||||
(dolist (var flist)
|
This function detects an file, and opens it.
|
||||||
;; `\' to '/' on windows.
|
|
||||||
(let ((fname (expand-file-name (car var)))
|
javascript:location.href = \\='org-protocol://roam-ref?ref=\\='+ \\
|
||||||
org-roam-location)
|
encodeURIComponent(location.href) + \\='&title=\\=' \\
|
||||||
(setq org-roam-location (org-roam-protocol-check-filename-for-protocol
|
encodeURIComponent(document.title) + \\='&body=\\=' + \\
|
||||||
fname))
|
encodeURIComponent(window.getSelection())"
|
||||||
(when (stringp org-roam-location) ; location for Org-roam file
|
(when-let* ((alist (org-roam--plist-to-alist info))
|
||||||
(setcar var org-roam-location))))))
|
(decoded-alist (mapcar (lambda (k.v)
|
||||||
|
(let ((key (car k.v))
|
||||||
|
(val (cdr k.v)))
|
||||||
|
(cons key (org-link-decode val)))) alist)))
|
||||||
|
(when (assoc 'ref decoded-alist)
|
||||||
|
(raise-frame)
|
||||||
|
(org-roam-find-ref decoded-alist)))
|
||||||
|
nil)
|
||||||
|
|
||||||
|
(defun org-roam-protocol-open-file (info)
|
||||||
|
"Process an org-protocol://roam-ref?ref= style url with INFO.
|
||||||
|
|
||||||
|
Example protocol string:
|
||||||
|
|
||||||
|
org-protocol://roam-file?file=/path/to/file.org"
|
||||||
|
(when-let ((file (plist-get info :file)))
|
||||||
|
(raise-frame)
|
||||||
|
(find-file file))
|
||||||
|
nil)
|
||||||
|
|
||||||
|
(push '("org-roam-ref" :protocol "roam-ref" :function org-roam-protocol-open-ref)
|
||||||
|
org-protocol-protocol-alist)
|
||||||
|
(push '("org-roam-file" :protocol "roam-file" :function org-roam-protocol-open-file)
|
||||||
|
org-protocol-protocol-alist)
|
||||||
|
|
||||||
(provide 'org-roam-protocol)
|
(provide 'org-roam-protocol)
|
||||||
|
|
||||||
|
98
org-roam-utils.el
Normal file
98
org-roam-utils.el
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
;;; org-roam-utils.el --- Org-roam utility functions -*- coding: utf-8; lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
|
||||||
|
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||||
|
|
||||||
|
;; This file is NOT part of GNU Emacs.
|
||||||
|
|
||||||
|
;; This program is free software; you can redistribute it and/or modify
|
||||||
|
;; it under the terms of the GNU General Public License as published by
|
||||||
|
;; the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
;; any later version.
|
||||||
|
;;
|
||||||
|
;; This program is distributed in the hope that it will be useful,
|
||||||
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
;; GNU General Public License for more details.
|
||||||
|
;;
|
||||||
|
;; You should have received a copy of the GNU General Public License
|
||||||
|
;; along with GNU Emacs; see the file COPYING. If not, write to the
|
||||||
|
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
;; Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;;
|
||||||
|
;; Provides several utility functions used throughout Org-roam.
|
||||||
|
;;
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'f)
|
||||||
|
(require 'ob-core) ;for org-babel-parse-header-arguments
|
||||||
|
|
||||||
|
(defun org-roam--plist-to-alist (plist)
|
||||||
|
"Return an alist of the property-value pairs in PLIST."
|
||||||
|
(let (res)
|
||||||
|
(while plist
|
||||||
|
(let ((prop (intern (substring (symbol-name (pop plist)) 1 nil)))
|
||||||
|
(val (pop plist)))
|
||||||
|
(push (cons prop val) res)))
|
||||||
|
res))
|
||||||
|
|
||||||
|
(defun org-roam--touch-file (path)
|
||||||
|
"Touches an empty file at PATH."
|
||||||
|
(make-directory (file-name-directory path) t)
|
||||||
|
(f-touch path))
|
||||||
|
|
||||||
|
(defun org-roam--file-name-extension (filename)
|
||||||
|
"Return file name extension for FILENAME.
|
||||||
|
Like file-name-extension, but does not strip version number."
|
||||||
|
(save-match-data
|
||||||
|
(let ((file (file-name-nondirectory filename)))
|
||||||
|
(if (and (string-match "\\.[^.]*\\'" file)
|
||||||
|
(not (eq 0 (match-beginning 0))))
|
||||||
|
(substring file (+ (match-beginning 0) 1))))))
|
||||||
|
|
||||||
|
(defun org-roam--org-file-p (path)
|
||||||
|
"Check if PATH is pointing to an org file."
|
||||||
|
(let ((ext (org-roam--file-name-extension path)))
|
||||||
|
(or (string= ext "org")
|
||||||
|
(and
|
||||||
|
(string= ext "gpg")
|
||||||
|
(string= (org-roam--file-name-extension (file-name-sans-extension path)) "org")))))
|
||||||
|
|
||||||
|
(defun org-roam--org-roam-file-p (&optional file)
|
||||||
|
"Return t if FILE is part of org-roam system, return nil otherwise.
|
||||||
|
If FILE is not specified, use the current-buffer file path."
|
||||||
|
(let ((path (or file
|
||||||
|
(buffer-file-name (current-buffer)))))
|
||||||
|
(and path
|
||||||
|
(org-roam--org-file-p path)
|
||||||
|
(f-descendant-of-p (file-truename path)
|
||||||
|
(file-truename org-roam-directory)))))
|
||||||
|
|
||||||
|
(defun org-roam--aliases-str-to-list (str)
|
||||||
|
"Function to transform string STR into list of alias titles.
|
||||||
|
|
||||||
|
This snippet is obtained from ox-hugo:
|
||||||
|
https://github.com/kaushalmodi/ox-hugo/blob/a80b250987bc770600c424a10b3bca6ff7282e3c/ox-hugo.el#L3131"
|
||||||
|
(when (stringp str)
|
||||||
|
(let* ((str (org-trim str))
|
||||||
|
(str-list (split-string str "\n"))
|
||||||
|
ret)
|
||||||
|
(dolist (str-elem str-list)
|
||||||
|
(let* ((format-str ":dummy '(%s)") ;The :dummy key is discarded in the `lst' var below.
|
||||||
|
(alist (org-babel-parse-header-arguments (format format-str str-elem)))
|
||||||
|
(lst (cdr (car alist)))
|
||||||
|
(str-list2 (mapcar (lambda (elem)
|
||||||
|
(cond
|
||||||
|
((symbolp elem)
|
||||||
|
(symbol-name elem))
|
||||||
|
(t
|
||||||
|
elem)))
|
||||||
|
lst)))
|
||||||
|
(setq ret (append ret str-list2))))
|
||||||
|
ret)))
|
||||||
|
|
||||||
|
;;; -
|
||||||
|
(provide 'org-roam-utils)
|
||||||
|
;;; org-roam-utils.el ends here
|
318
org-roam.el
318
org-roam.el
@ -34,16 +34,15 @@
|
|||||||
;;
|
;;
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
(eval-when-compile (require 'cl-lib))
|
|
||||||
(require 'org)
|
(require 'org)
|
||||||
(require 'org-element)
|
(require 'org-element)
|
||||||
(require 'ob-core) ;for org-babel-parse-header-arguments
|
|
||||||
(require 'subr-x)
|
(require 'subr-x)
|
||||||
(require 'dash)
|
(require 'dash)
|
||||||
(require 's)
|
(require 's)
|
||||||
(require 'f)
|
(require 'f)
|
||||||
(require 'cl-lib)
|
(require 'cl-lib)
|
||||||
(require 'org-roam-db)
|
(require 'org-roam-db)
|
||||||
|
(require 'org-roam-utils)
|
||||||
|
|
||||||
;;; Customizations
|
;;; Customizations
|
||||||
(defgroup org-roam nil
|
(defgroup org-roam nil
|
||||||
@ -60,14 +59,12 @@
|
|||||||
|
|
||||||
(defcustom org-roam-new-file-directory nil
|
(defcustom org-roam-new-file-directory nil
|
||||||
"Path to where new Org-roam files are created.
|
"Path to where new Org-roam files are created.
|
||||||
|
|
||||||
If nil, default to the org-roam-directory (preferred)."
|
If nil, default to the org-roam-directory (preferred)."
|
||||||
:type 'directory
|
:type 'directory
|
||||||
:group 'org-roam)
|
:group 'org-roam)
|
||||||
|
|
||||||
(defcustom org-roam-buffer-position 'right
|
(defcustom org-roam-buffer-position 'right
|
||||||
"Position of `org-roam' buffer.
|
"Position of `org-roam' buffer.
|
||||||
|
|
||||||
Valid values are
|
Valid values are
|
||||||
* left,
|
* left,
|
||||||
* right."
|
* right."
|
||||||
@ -81,8 +78,7 @@ Valid values are
|
|||||||
:group 'org-roam)
|
:group 'org-roam)
|
||||||
|
|
||||||
(defcustom org-roam-filename-noconfirm t
|
(defcustom org-roam-filename-noconfirm t
|
||||||
"Whether to prompt for confirmation of fil name for new files.
|
"Whether to prompt for confirmation of filename for new files.
|
||||||
|
|
||||||
If nil, always ask for filename."
|
If nil, always ask for filename."
|
||||||
:type 'boolean
|
:type 'boolean
|
||||||
:group 'org-roam)
|
:group 'org-roam)
|
||||||
@ -129,30 +125,9 @@ If nil, always ask for filename."
|
|||||||
"Last window `org-roam' was called from.")
|
"Last window `org-roam' was called from.")
|
||||||
|
|
||||||
;;; Utilities
|
;;; Utilities
|
||||||
(defun org-roam--touch-file (path)
|
(defun org-roam--list-files (dir)
|
||||||
"Touches an empty file at PATH."
|
"Return all Org-roam files located within DIR, at any nesting level.
|
||||||
(make-directory (file-name-directory path) t)
|
Ignores hidden files and directories."
|
||||||
(f-touch path))
|
|
||||||
|
|
||||||
(defun org-roam--file-name-extension (filename)
|
|
||||||
"Return file name extension for FILENAME.
|
|
||||||
Like file-name-extension, but does not strip version number."
|
|
||||||
(save-match-data
|
|
||||||
(let ((file (file-name-nondirectory filename)))
|
|
||||||
(if (and (string-match "\\.[^.]*\\'" file)
|
|
||||||
(not (eq 0 (match-beginning 0))))
|
|
||||||
(substring file (+ (match-beginning 0) 1))))))
|
|
||||||
|
|
||||||
(defun org-roam--org-file-p (path)
|
|
||||||
"Check if PATH is pointing to an org file."
|
|
||||||
(let ((ext (org-roam--file-name-extension path)))
|
|
||||||
(or (string= ext "org")
|
|
||||||
(and
|
|
||||||
(string= ext "gpg")
|
|
||||||
(string= (org-roam--file-name-extension (file-name-sans-extension path)) "org")))))
|
|
||||||
|
|
||||||
(defun org-roam--find-files (dir)
|
|
||||||
"Return all `org-roam' files in `DIR'."
|
|
||||||
(if (file-exists-p dir)
|
(if (file-exists-p dir)
|
||||||
(let ((files (directory-files dir t "." t))
|
(let ((files (directory-files dir t "." t))
|
||||||
(dir-ignore-regexp (concat "\\(?:"
|
(dir-ignore-regexp (concat "\\(?:"
|
||||||
@ -164,15 +139,22 @@ Like file-name-extension, but does not strip version number."
|
|||||||
(cond
|
(cond
|
||||||
((file-directory-p file)
|
((file-directory-p file)
|
||||||
(when (not (string-match dir-ignore-regexp file))
|
(when (not (string-match dir-ignore-regexp file))
|
||||||
(setq result (append (org-roam--find-files file) result))))
|
(setq result (append (org-roam--list-files file) result))))
|
||||||
((and (file-readable-p file)
|
((and (file-readable-p file)
|
||||||
(org-roam--org-file-p file))
|
(org-roam--org-file-p file))
|
||||||
(setq result (cons (file-truename file) result)))))
|
(setq result (cons (file-truename file) result)))))
|
||||||
result)))
|
result)))
|
||||||
|
|
||||||
(defun org-roam--get-links (&optional file-path)
|
(defun org-roam--extract-links (&optional file-path)
|
||||||
"Get the links in the buffer.
|
"Extracts all link items within the current buffer.
|
||||||
If FILE-PATH is passed, use that as the source file."
|
Link items are of the form:
|
||||||
|
|
||||||
|
[file-from file-to properties]
|
||||||
|
|
||||||
|
This is the format that emacsql expects when inserting into the database.
|
||||||
|
FILE-FROM is typically the buffer file path, but this may not exist, for example
|
||||||
|
in temp buffers. In cases where this occurs, we do know the file path, and pass
|
||||||
|
it as FILE-PATH."
|
||||||
(let ((file-path (or file-path
|
(let ((file-path (or file-path
|
||||||
(file-truename (buffer-file-name (current-buffer))))))
|
(file-truename (buffer-file-name (current-buffer))))))
|
||||||
(org-element-map (org-element-parse-buffer) 'link
|
(org-element-map (org-element-parse-buffer) 'link
|
||||||
@ -197,43 +179,19 @@ If FILE-PATH is passed, use that as the source file."
|
|||||||
(list :content content :point begin)))))))))
|
(list :content content :point begin)))))))))
|
||||||
|
|
||||||
(defun org-roam--extract-global-props (props)
|
(defun org-roam--extract-global-props (props)
|
||||||
"Extract PROPS from the current buffer."
|
"Extract PROPS from the current org buffer.
|
||||||
|
The search terminates when the first property is encountered."
|
||||||
(let ((buf (org-element-parse-buffer))
|
(let ((buf (org-element-parse-buffer))
|
||||||
(res '()))
|
res)
|
||||||
(dolist (prop props)
|
(dolist (prop props)
|
||||||
(let ((p (org-element-map
|
(let ((p (org-element-map buf 'keyword
|
||||||
buf
|
|
||||||
'keyword
|
|
||||||
(lambda (kw)
|
(lambda (kw)
|
||||||
(when (string= (org-element-property :key kw) prop)
|
(when (string= (org-element-property :key kw) prop)
|
||||||
(org-element-property :value kw)))
|
(org-element-property :value kw)))
|
||||||
:first-match t)))
|
:first-match t)))
|
||||||
(setq res (cons (cons prop p) res))))
|
(push (cons prop p) res)))
|
||||||
res))
|
res))
|
||||||
|
|
||||||
(defun org-roam--aliases-str-to-list (str)
|
|
||||||
"Function to transform string STR into list of alias titles.
|
|
||||||
|
|
||||||
This snippet is obtained from ox-hugo:
|
|
||||||
https://github.com/kaushalmodi/ox-hugo/blob/a80b250987bc770600c424a10b3bca6ff7282e3c/ox-hugo.el#L3131"
|
|
||||||
(when (stringp str)
|
|
||||||
(let* ((str (org-trim str))
|
|
||||||
(str-list (split-string str "\n"))
|
|
||||||
ret)
|
|
||||||
(dolist (str-elem str-list)
|
|
||||||
(let* ((format-str ":dummy '(%s)") ;The :dummy key is discarded in the `lst' var below.
|
|
||||||
(alist (org-babel-parse-header-arguments (format format-str str-elem)))
|
|
||||||
(lst (cdr (car alist)))
|
|
||||||
(str-list2 (mapcar (lambda (elem)
|
|
||||||
(cond
|
|
||||||
((symbolp elem)
|
|
||||||
(symbol-name elem))
|
|
||||||
(t
|
|
||||||
elem)))
|
|
||||||
lst)))
|
|
||||||
(setq ret (append ret str-list2))))
|
|
||||||
ret)))
|
|
||||||
|
|
||||||
(defun org-roam--extract-titles ()
|
(defun org-roam--extract-titles ()
|
||||||
"Extract the titles from current buffer.
|
"Extract the titles from current buffer.
|
||||||
Titles are obtained via the #+TITLE property, or aliases
|
Titles are obtained via the #+TITLE property, or aliases
|
||||||
@ -250,28 +208,28 @@ specified via the #+ROAM_ALIAS property."
|
|||||||
"Extract the ref from current buffer."
|
"Extract the ref from current buffer."
|
||||||
(cdr (assoc "ROAM_KEY" (org-roam--extract-global-props '("ROAM_KEY")))))
|
(cdr (assoc "ROAM_KEY" (org-roam--extract-global-props '("ROAM_KEY")))))
|
||||||
|
|
||||||
(defun org-roam--insert-links (links)
|
(defun org-roam--db-insert-links (links)
|
||||||
"Insert LINK into the org-roam cache."
|
"Insert LINK into the org-roam cache."
|
||||||
(org-roam-sql
|
(org-roam-sql
|
||||||
[:insert :into file-links
|
[:insert :into file-links
|
||||||
:values $v1]
|
:values $v1]
|
||||||
links))
|
links))
|
||||||
|
|
||||||
(defun org-roam--insert-titles (file titles)
|
(defun org-roam--db-insert-titles (file titles)
|
||||||
"Insert TITLES into the org-roam-cache."
|
"Insert TITLES into the org-roam-cache."
|
||||||
(org-roam-sql
|
(org-roam-sql
|
||||||
[:insert :into titles
|
[:insert :into titles
|
||||||
:values $v1]
|
:values $v1]
|
||||||
(list (vector file titles))))
|
(list (vector file titles))))
|
||||||
|
|
||||||
(defun org-roam--insert-ref (file ref)
|
(defun org-roam--db-insert-ref (file ref)
|
||||||
"Insert REF into the Org-roam cache."
|
"Insert REF into the Org-roam cache."
|
||||||
(org-roam-sql
|
(org-roam-sql
|
||||||
[:insert :into refs
|
[:insert :into refs
|
||||||
:values $v1]
|
:values $v1]
|
||||||
(list (vector ref file))))
|
(list (vector ref file))))
|
||||||
|
|
||||||
(defun org-roam--clear-cache ()
|
(defun org-roam--db-clear ()
|
||||||
"Clears all entries in the caches."
|
"Clears all entries in the caches."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (file-exists-p (org-roam--get-db))
|
(when (file-exists-p (org-roam--get-db))
|
||||||
@ -281,23 +239,23 @@ specified via the #+ROAM_ALIAS property."
|
|||||||
(org-roam-sql [:delete :from files])
|
(org-roam-sql [:delete :from files])
|
||||||
(org-roam-sql [:delete :from refs])))
|
(org-roam-sql [:delete :from refs])))
|
||||||
|
|
||||||
(defun org-roam--clear-file-from-cache (&optional filepath)
|
(defun org-roam--db-clear-file (&optional filepath)
|
||||||
"Remove any related links to the file at FILEPATH.
|
"Remove any related links to the file at FILEPATH.
|
||||||
This is equivalent to removing the node from the graph."
|
This is equivalent to removing the node from the graph."
|
||||||
(let* ((path (or filepath
|
(let* ((path (or filepath
|
||||||
(buffer-file-name (current-buffer))))
|
(buffer-file-name (current-buffer))))
|
||||||
(file (file-truename path)))
|
(file (file-truename path)))
|
||||||
(org-roam-sql [:delete :from files
|
(org-roam-sql [:delete :from files
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
file)
|
file)
|
||||||
(org-roam-sql [:delete :from file-links
|
(org-roam-sql [:delete :from file-links
|
||||||
:where (= file-from $s1)]
|
:where (= file-from $s1)]
|
||||||
file)
|
file)
|
||||||
(org-roam-sql [:delete :from titles
|
(org-roam-sql [:delete :from titles
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
file)
|
file)
|
||||||
(org-roam-sql [:delete :from refs
|
(org-roam-sql [:delete :from refs
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
file)))
|
file)))
|
||||||
|
|
||||||
(defun org-roam--get-current-files ()
|
(defun org-roam--get-current-files ()
|
||||||
@ -308,45 +266,31 @@ This is equivalent to removing the node from the graph."
|
|||||||
(puthash (car row) (cadr row) ht))
|
(puthash (car row) (cadr row) ht))
|
||||||
ht))
|
ht))
|
||||||
|
|
||||||
(defun org-roam--cache-initialized-p ()
|
(defun org-roam--db-initialized-p ()
|
||||||
"Whether the cache has been initialized."
|
"Whether the cache has been initialized."
|
||||||
(and (file-exists-p (org-roam--get-db))
|
(and (file-exists-p (org-roam--get-db))
|
||||||
(> (caar (org-roam-sql [:select (funcall count) :from titles]))
|
(> (caar (org-roam-sql [:select (funcall count) :from titles]))
|
||||||
0)))
|
0)))
|
||||||
|
|
||||||
(defun org-roam--ensure-cache-built ()
|
(defun org-roam--db-ensure-built ()
|
||||||
"Ensures that org-roam cache is built."
|
"Ensures that org-roam cache is built."
|
||||||
(unless (org-roam--cache-initialized-p)
|
(unless (org-roam--db-initialized-p)
|
||||||
(error "[Org-roam] your cache isn't built yet! Please wait.")))
|
(error "[Org-roam] your cache isn't built yet! Please run org-roam-build-cache.")))
|
||||||
|
|
||||||
(defun org-roam--org-roam-file-p (&optional file)
|
(defun org-roam--db-get-titles (file)
|
||||||
"Return t if FILE is part of org-roam system, defaulting to the name of the current buffer. Else, return nil."
|
"Return the titles of FILE from the cache."
|
||||||
(let ((path (or file
|
|
||||||
(buffer-file-name (current-buffer)))))
|
|
||||||
(and path
|
|
||||||
(org-roam--org-file-p path)
|
|
||||||
(f-descendant-of-p (file-truename path)
|
|
||||||
(file-truename org-roam-directory)))))
|
|
||||||
|
|
||||||
(defun org-roam--get-titles-from-cache (file)
|
|
||||||
"Return titles and aliases of `FILE' from the cache."
|
|
||||||
(caar (org-roam-sql [:select [titles] :from titles
|
(caar (org-roam-sql [:select [titles] :from titles
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
file
|
file
|
||||||
:limit 1)))
|
:limit 1)))
|
||||||
|
|
||||||
(defun org-roam--get-title-from-cache (file)
|
(defun org-roam--list-all-files ()
|
||||||
"Return the title of `FILE' from the cache."
|
"Return a list of all org-roam files within `org-roam-directory'."
|
||||||
(car (org-roam--get-titles-from-cache file)))
|
(org-roam--list-files (file-truename org-roam-directory)))
|
||||||
|
|
||||||
(defun org-roam--find-all-files ()
|
|
||||||
"Return all org-roam files."
|
|
||||||
(org-roam--find-files (file-truename org-roam-directory)))
|
|
||||||
|
|
||||||
(defun org-roam--new-file-path (id &optional absolute)
|
(defun org-roam--new-file-path (id &optional absolute)
|
||||||
"Make new file path from identifier `ID'.
|
"The file path for a new Org-roam file, with identifier ID.
|
||||||
|
If ABSOLUTE, return an absolute file-path. Else, return a relative file-path."
|
||||||
If `ABSOLUTE', return an absolute file-path. Else, return a relative file-path."
|
|
||||||
(let ((absolute-file-path (file-truename
|
(let ((absolute-file-path (file-truename
|
||||||
(expand-file-name
|
(expand-file-name
|
||||||
(if org-roam-encrypt-files
|
(if org-roam-encrypt-files
|
||||||
@ -367,9 +311,8 @@ If `ABSOLUTE', return an absolute file-path. Else, return a relative file-path."
|
|||||||
|
|
||||||
(defun org-roam--get-title-or-slug (path)
|
(defun org-roam--get-title-or-slug (path)
|
||||||
"Convert `PATH' to the file title, if it exists. Else, return the path."
|
"Convert `PATH' to the file title, if it exists. Else, return the path."
|
||||||
(if-let (titles (org-roam--get-titles-from-cache path))
|
(or (car (org-roam--db-get-titles path))
|
||||||
(car titles)
|
(org-roam--path-to-slug path)))
|
||||||
(org-roam--path-to-slug path)))
|
|
||||||
|
|
||||||
(defun org-roam--title-to-slug (title)
|
(defun org-roam--title-to-slug (title)
|
||||||
"Convert TITLE to a filename-suitable slug."
|
"Convert TITLE to a filename-suitable slug."
|
||||||
@ -396,35 +339,39 @@ It uses TITLE and the current timestamp to form a unique title."
|
|||||||
:content "#+TITLE: ${title}")))
|
:content "#+TITLE: ${title}")))
|
||||||
"Templates to insert for new files in org-roam.")
|
"Templates to insert for new files in org-roam.")
|
||||||
|
|
||||||
(defun org-roam--make-new-file (title &optional template-key)
|
(defun org-roam--get-template (&optional template-key)
|
||||||
|
"Return an Org-roam template. TEMPLATE-KEY is used to get a template."
|
||||||
(unless org-roam-templates
|
(unless org-roam-templates
|
||||||
(user-error "No templates defined"))
|
(user-error "No templates defined"))
|
||||||
(let (template)
|
(if template-key
|
||||||
(if template-key
|
(cadr (assoc template-key org-roam-templates))
|
||||||
(setq template (cadr (assoc template-key org-roam-templates)))
|
(if (= (length org-roam-templates) 1)
|
||||||
(if (= (length org-roam-templates) 1)
|
(cadar org-roam-templates)
|
||||||
(setq template (cadar org-roam-templates))
|
(cadr (assoc (completing-read "Template: " org-roam-templates)
|
||||||
(setq template
|
org-roam-templates)))))
|
||||||
(cadr (assoc (completing-read "Template: " org-roam-templates)
|
|
||||||
org-roam-templates)))))
|
|
||||||
(let (file-name-fn file-path)
|
(defun org-roam--make-new-file (&optional info)
|
||||||
(fset 'file-name-fn (plist-get template :file))
|
(let ((template (org-roam--get-template (cdr (assoc 'template info))))
|
||||||
(setq file-path (org-roam--new-file-path (file-name-fn title) t))
|
(title (or (cdr (assoc 'title info))
|
||||||
(if (file-exists-p file-path)
|
(completing-read "Title: " nil)))
|
||||||
file-path
|
file-name-fn file-path)
|
||||||
(org-roam--touch-file file-path)
|
(fset 'file-name-fn (plist-get template :file))
|
||||||
(write-region
|
(setq file-path (org-roam--new-file-path (file-name-fn title) t))
|
||||||
(s-format (plist-get template :content)
|
(setq info (cons (cons 'slug (org-roam--title-to-slug title)) info))
|
||||||
'aget
|
(if (file-exists-p file-path)
|
||||||
(list (cons "title" title)
|
file-path
|
||||||
(cons "slug" (org-roam--title-to-slug title))))
|
(org-roam--touch-file file-path)
|
||||||
nil file-path nil)
|
(write-region
|
||||||
file-path))))
|
(s-format (plist-get template :content)
|
||||||
|
'aget
|
||||||
|
info)
|
||||||
|
nil file-path nil)
|
||||||
|
file-path)))
|
||||||
|
|
||||||
;;; Inserting org-roam links
|
;;; Inserting org-roam links
|
||||||
(defun org-roam-insert (prefix)
|
(defun org-roam-insert (prefix)
|
||||||
"Find an org-roam file, and insert a relative org link to it at point.
|
"Find an org-roam file, and insert a relative org link to it at point.
|
||||||
|
|
||||||
If PREFIX, downcase the title before insertion."
|
If PREFIX, downcase the title before insertion."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(let* ((region (and (region-active-p)
|
(let* ((region (and (region-active-p)
|
||||||
@ -437,7 +384,7 @@ If PREFIX, downcase the title before insertion."
|
|||||||
(title (completing-read "File: " completions nil nil region-text))
|
(title (completing-read "File: " completions nil nil region-text))
|
||||||
(region-or-title (or region-text title))
|
(region-or-title (or region-text title))
|
||||||
(absolute-file-path (or (cdr (assoc title completions))
|
(absolute-file-path (or (cdr (assoc title completions))
|
||||||
(org-roam--make-new-file title)))
|
(org-roam--make-new-file (list (cons 'title title)))))
|
||||||
(current-file-path (-> (or (buffer-base-buffer)
|
(current-file-path (-> (or (buffer-base-buffer)
|
||||||
(current-buffer))
|
(current-buffer))
|
||||||
(buffer-file-name)
|
(buffer-file-name)
|
||||||
@ -463,18 +410,37 @@ If PREFIX, downcase the title before insertion."
|
|||||||
(titles (cadr row)))
|
(titles (cadr row)))
|
||||||
(if titles
|
(if titles
|
||||||
(dolist (title titles)
|
(dolist (title titles)
|
||||||
(setq res (cons (cons title file-path) res)))
|
(push (cons title file-path) res))
|
||||||
(setq res (cons (cons (org-roam--path-to-slug file-path)
|
(push (cons (org-roam--path-to-slug file-path)
|
||||||
file-path) res)))))
|
file-path) res))))
|
||||||
res))
|
res))
|
||||||
|
|
||||||
|
(defun org-roam--get-ref-path-completions ()
|
||||||
|
"Return a list of cons pairs for titles to absolute path of Org-roam files."
|
||||||
|
(let ((rows (org-roam-sql [:select [ref file] :from refs])))
|
||||||
|
(mapcar (lambda (row)
|
||||||
|
(cons (car row)
|
||||||
|
(cadr row))) rows)))
|
||||||
|
|
||||||
|
(defun org-roam-find-ref (&optional info)
|
||||||
|
"Find and open an org-roam file from a ref.
|
||||||
|
INFO is an alist containing additional information."
|
||||||
|
(interactive)
|
||||||
|
(let* ((completions (org-roam--get-ref-path-completions))
|
||||||
|
(ref (or (cdr (assoc 'ref info))
|
||||||
|
(completing-read "Ref: " (org-roam--get-ref-path-completions))))
|
||||||
|
(file-path (cdr (assoc ref completions))))
|
||||||
|
(if file-path
|
||||||
|
(find-file file-path)
|
||||||
|
(find-file (org-roam--make-new-file info)))))
|
||||||
|
|
||||||
(defun org-roam-find-file ()
|
(defun org-roam-find-file ()
|
||||||
"Find and open an org-roam file."
|
"Find and open an org-roam file."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let* ((completions (org-roam--get-title-path-completions))
|
(let* ((completions (org-roam--get-title-path-completions))
|
||||||
(title-or-slug (completing-read "File: " completions))
|
(title-or-slug (completing-read "File: " completions))
|
||||||
(absolute-file-path (or (cdr (assoc title-or-slug completions))
|
(absolute-file-path (or (cdr (assoc title-or-slug completions))
|
||||||
(org-roam--make-new-file title-or-slug))))
|
(org-roam--make-new-file (list (cons 'title title-or-slug))))))
|
||||||
(find-file absolute-file-path)))
|
(find-file absolute-file-path)))
|
||||||
|
|
||||||
(defun org-roam--get-roam-buffers ()
|
(defun org-roam--get-roam-buffers ()
|
||||||
@ -485,7 +451,7 @@ If PREFIX, downcase the title before insertion."
|
|||||||
(buffer-list)))
|
(buffer-list)))
|
||||||
|
|
||||||
(defun org-roam-switch-to-buffer ()
|
(defun org-roam-switch-to-buffer ()
|
||||||
"Switch to an existing org-roam buffer using completing-read."
|
"Switch to an existing org-roam buffer."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let* ((roam-buffers (org-roam--get-roam-buffers))
|
(let* ((roam-buffers (org-roam--get-roam-buffers))
|
||||||
(names-and-buffers (mapcar (lambda (buffer)
|
(names-and-buffers (mapcar (lambda (buffer)
|
||||||
@ -495,7 +461,7 @@ If PREFIX, downcase the title before insertion."
|
|||||||
buffer))
|
buffer))
|
||||||
roam-buffers)))
|
roam-buffers)))
|
||||||
(unless roam-buffers
|
(unless roam-buffers
|
||||||
(error "No roam buffers."))
|
(user-error "No roam buffers."))
|
||||||
(when-let ((name (completing-read "Choose a buffer: " names-and-buffers)))
|
(when-let ((name (completing-read "Choose a buffer: " names-and-buffers)))
|
||||||
(switch-to-buffer (cdr (assoc name names-and-buffers))))))
|
(switch-to-buffer (cdr (assoc name names-and-buffers))))))
|
||||||
|
|
||||||
@ -504,7 +470,7 @@ If PREFIX, downcase the title before insertion."
|
|||||||
"Build the cache for `org-roam-directory'."
|
"Build the cache for `org-roam-directory'."
|
||||||
(interactive)
|
(interactive)
|
||||||
(org-roam-db) ;; To initialize the database, no-op if already initialized
|
(org-roam-db) ;; To initialize the database, no-op if already initialized
|
||||||
(let* ((org-roam-files (org-roam--find-files org-roam-directory))
|
(let* ((org-roam-files (org-roam--list-files org-roam-directory))
|
||||||
(current-files (org-roam--get-current-files))
|
(current-files (org-roam--get-current-files))
|
||||||
(time (current-time))
|
(time (current-time))
|
||||||
all-files all-links all-titles all-refs)
|
all-files all-links all-titles all-refs)
|
||||||
@ -514,10 +480,10 @@ If PREFIX, downcase the title before insertion."
|
|||||||
(let ((contents-hash (secure-hash 'sha1 (current-buffer))))
|
(let ((contents-hash (secure-hash 'sha1 (current-buffer))))
|
||||||
(unless (string= (gethash file current-files)
|
(unless (string= (gethash file current-files)
|
||||||
contents-hash)
|
contents-hash)
|
||||||
(org-roam--clear-file-from-cache file)
|
(org-roam--db-clear-file file)
|
||||||
(setq all-files
|
(setq all-files
|
||||||
(cons (vector file contents-hash time) all-files))
|
(cons (vector file contents-hash time) all-files))
|
||||||
(when-let (links (org-roam--get-links file))
|
(when-let (links (org-roam--extract-links file))
|
||||||
(setq all-links (append links all-links)))
|
(setq all-links (append links all-links)))
|
||||||
(let ((titles (org-roam--extract-titles)))
|
(let ((titles (org-roam--extract-titles)))
|
||||||
(setq all-titles (cons (vector file titles) all-titles)))
|
(setq all-titles (cons (vector file titles) all-titles)))
|
||||||
@ -526,26 +492,26 @@ If PREFIX, downcase the title before insertion."
|
|||||||
(remhash file current-files))))
|
(remhash file current-files))))
|
||||||
(dolist (file (hash-table-keys current-files))
|
(dolist (file (hash-table-keys current-files))
|
||||||
;; These files are no longer around, remove from cache...
|
;; These files are no longer around, remove from cache...
|
||||||
(org-roam--clear-file-from-cache file))
|
(org-roam--db-clear-file file))
|
||||||
(when all-files
|
(when all-files
|
||||||
(org-roam-sql
|
(org-roam-sql
|
||||||
[:insert :into files
|
[:insert :into files
|
||||||
:values $v1]
|
:values $v1]
|
||||||
all-files))
|
all-files))
|
||||||
(when all-links
|
(when all-links
|
||||||
(org-roam-sql
|
(org-roam-sql
|
||||||
[:insert :into file-links
|
[:insert :into file-links
|
||||||
:values $v1]
|
:values $v1]
|
||||||
all-links))
|
all-links))
|
||||||
(when all-titles
|
(when all-titles
|
||||||
(org-roam-sql
|
(org-roam-sql
|
||||||
[:insert :into titles
|
[:insert :into titles
|
||||||
:values $v1]
|
:values $v1]
|
||||||
all-titles))
|
all-titles))
|
||||||
(when all-refs
|
(when all-refs
|
||||||
(org-roam-sql
|
(org-roam-sql
|
||||||
[:insert :into refs
|
[:insert :into refs
|
||||||
:values $v1]
|
:values $v1]
|
||||||
all-refs))
|
all-refs))
|
||||||
(let ((stats (list :files (length all-files)
|
(let ((stats (list :files (length all-files)
|
||||||
:links (length all-links)
|
:links (length all-links)
|
||||||
@ -560,22 +526,22 @@ If PREFIX, downcase the title before insertion."
|
|||||||
(plist-get stats :deleted)))
|
(plist-get stats :deleted)))
|
||||||
stats)))
|
stats)))
|
||||||
|
|
||||||
(defun org-roam--update-cache-titles ()
|
(defun org-roam--db-update-titles ()
|
||||||
"Update the title of the current buffer into the cache."
|
"Update the title of the current buffer into the cache."
|
||||||
(let ((file (file-truename (buffer-file-name (current-buffer)))))
|
(let ((file (file-truename (buffer-file-name (current-buffer)))))
|
||||||
(org-roam-sql [:delete :from titles
|
(org-roam-sql [:delete :from titles
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
file)
|
file)
|
||||||
(org-roam--insert-titles file (org-roam--extract-titles))))
|
(org-roam--db-insert-titles file (org-roam--extract-titles))))
|
||||||
|
|
||||||
(defun org-roam--update-cache-refs ()
|
(defun org-roam--db-update-refs ()
|
||||||
"Update the ref of the current buffer into the cache."
|
"Update the ref of the current buffer into the cache."
|
||||||
(let ((file (file-truename (buffer-file-name (current-buffer)))))
|
(let ((file (file-truename (buffer-file-name (current-buffer)))))
|
||||||
(org-roam-sql [:delete :from refs
|
(org-roam-sql [:delete :from refs
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
file)
|
file)
|
||||||
(when-let ((ref (org-roam--extract-ref)))
|
(when-let ((ref (org-roam--extract-ref)))
|
||||||
(org-roam--insert-ref file ref))))
|
(org-roam--db-insert-ref file ref))))
|
||||||
|
|
||||||
(defun org-roam--update-cache-links ()
|
(defun org-roam--update-cache-links ()
|
||||||
"Update the file links of the current buffer in the cache."
|
"Update the file links of the current buffer in the cache."
|
||||||
@ -583,14 +549,14 @@ If PREFIX, downcase the title before insertion."
|
|||||||
(org-roam-sql [:delete :from file-links
|
(org-roam-sql [:delete :from file-links
|
||||||
:where (= file-from $s1)]
|
:where (= file-from $s1)]
|
||||||
file)
|
file)
|
||||||
(when-let ((links (org-roam--get-links)))
|
(when-let ((links (org-roam--extract-links)))
|
||||||
(org-roam--insert-links links))))
|
(org-roam--db-insert-links links))))
|
||||||
|
|
||||||
(defun org-roam--update-cache ()
|
(defun org-roam--db-update-buffer-file ()
|
||||||
"Update org-roam caches for the current buffer file."
|
"Update org-roam caches for the current buffer file."
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(org-roam--update-cache-titles)
|
(org-roam--db-update-titles)
|
||||||
(org-roam--update-cache-refs)
|
(org-roam--db-update-refs)
|
||||||
(org-roam--update-cache-links)
|
(org-roam--update-cache-links)
|
||||||
(org-roam--maybe-update-buffer :redisplay t)))
|
(org-roam--maybe-update-buffer :redisplay t)))
|
||||||
|
|
||||||
@ -599,7 +565,8 @@ If PREFIX, downcase the title before insertion."
|
|||||||
"Create and find file for TIME."
|
"Create and find file for TIME."
|
||||||
(let* ((org-roam-templates (list (list "daily" (list :file (lambda (title) title)
|
(let* ((org-roam-templates (list (list "daily" (list :file (lambda (title) title)
|
||||||
:content "#+TITLE: ${title}")))))
|
:content "#+TITLE: ${title}")))))
|
||||||
(org-roam--make-new-file (format-time-string "%Y-%m-%d" time) "daily")))
|
(org-roam--make-new-file (list (cons 'title (format-time-string "%Y-%m-%d" time))
|
||||||
|
(cons 'template "daily")))))
|
||||||
|
|
||||||
(defun org-roam-today ()
|
(defun org-roam-today ()
|
||||||
"Create and find file for today."
|
"Create and find file for today."
|
||||||
@ -620,7 +587,8 @@ If PREFIX, downcase the title before insertion."
|
|||||||
(let ((path (org-roam--file-for-time time)))
|
(let ((path (org-roam--file-for-time time)))
|
||||||
(org-roam--find-file path))))
|
(org-roam--find-file path))))
|
||||||
|
|
||||||
;;; Org-roam buffer
|
|
||||||
|
;;; Org-roam Buffer
|
||||||
(define-derived-mode org-roam-backlinks-mode org-mode "Backlinks"
|
(define-derived-mode org-roam-backlinks-mode org-mode "Backlinks"
|
||||||
"Major mode for the org-roam backlinks buffer
|
"Major mode for the org-roam backlinks buffer
|
||||||
|
|
||||||
@ -674,7 +642,7 @@ If item at point is not org-roam specific, default to Org behaviour."
|
|||||||
|
|
||||||
(defun org-roam-update (file-path)
|
(defun org-roam-update (file-path)
|
||||||
"Show the backlinks for given org file for file at `FILE-PATH'."
|
"Show the backlinks for given org file for file at `FILE-PATH'."
|
||||||
(org-roam--ensure-cache-built)
|
(org-roam--db-ensure-built)
|
||||||
(let* ((source-org-roam-directory org-roam-directory))
|
(let* ((source-org-roam-directory org-roam-directory))
|
||||||
(let ((buffer-title (org-roam--get-title-or-slug file-path)))
|
(let ((buffer-title (org-roam--get-title-or-slug file-path)))
|
||||||
(with-current-buffer org-roam-buffer
|
(with-current-buffer org-roam-buffer
|
||||||
@ -718,10 +686,13 @@ If item at point is not org-roam specific, default to Org behaviour."
|
|||||||
(insert "\n\n* No backlinks!")))
|
(insert "\n\n* No backlinks!")))
|
||||||
(read-only-mode 1))))))
|
(read-only-mode 1))))))
|
||||||
|
|
||||||
;;; Building the Graphviz graph
|
;;; Graph
|
||||||
(defun org-roam-build-graph ()
|
(defun org-roam--build-graph ()
|
||||||
"Build graphviz graph output."
|
"Build the Graphviz string.
|
||||||
(org-roam--ensure-cache-built)
|
The Org-roam database titles table is read, to obtain the list of titles.
|
||||||
|
The file-links table is then read to obtain all directed links, and formatted
|
||||||
|
into a digraph."
|
||||||
|
(org-roam--db-ensure-built)
|
||||||
(with-temp-buffer
|
(with-temp-buffer
|
||||||
(insert "digraph {\n")
|
(insert "digraph {\n")
|
||||||
(let ((rows (org-roam-sql [:select [file titles] :from titles])))
|
(let ((rows (org-roam-sql [:select [file titles] :from titles])))
|
||||||
@ -731,7 +702,7 @@ If item at point is not org-roam specific, default to Org behaviour."
|
|||||||
(org-roam--path-to-slug file)))
|
(org-roam--path-to-slug file)))
|
||||||
(shortened-title (s-truncate org-roam-graph-max-title-length title)))
|
(shortened-title (s-truncate org-roam-graph-max-title-length title)))
|
||||||
(insert
|
(insert
|
||||||
(format " \"%s\" [label=\"%s\", shape=%s, URL=\"roam://%s\", tooltip=\"%s\"];\n"
|
(format " \"%s\" [label=\"%s\", shape=%s, URL=\"org-protocol://roam-file?file=%s\", tooltip=\"%s\"];\n"
|
||||||
file
|
file
|
||||||
shortened-title
|
shortened-title
|
||||||
org-roam-graph-node-shape
|
org-roam-graph-node-shape
|
||||||
@ -746,16 +717,16 @@ If item at point is not org-roam specific, default to Org behaviour."
|
|||||||
(buffer-string)))
|
(buffer-string)))
|
||||||
|
|
||||||
(defun org-roam-show-graph ()
|
(defun org-roam-show-graph ()
|
||||||
"Generate the org-roam graph in SVG format, and display it using `org-roam-graph-viewer'."
|
"Displays the generated Org-roam graph using `org-roam-graph-viewer'."
|
||||||
(interactive)
|
(interactive)
|
||||||
|
(declare (indent 0))
|
||||||
(unless org-roam-graphviz-executable
|
(unless org-roam-graphviz-executable
|
||||||
(setq org-roam-graphviz-executable (executable-find "dot")))
|
(setq org-roam-graphviz-executable (executable-find "dot")))
|
||||||
(unless org-roam-graphviz-executable
|
(unless org-roam-graphviz-executable
|
||||||
(user-error "Can't find graphviz executable. Please check if it is in your path"))
|
(user-error "Can't find graphviz executable. Please check if it is in your path"))
|
||||||
(declare (indent 0))
|
|
||||||
(let ((temp-dot (expand-file-name "graph.dot" temporary-file-directory))
|
(let ((temp-dot (expand-file-name "graph.dot" temporary-file-directory))
|
||||||
(temp-graph (expand-file-name "graph.svg" temporary-file-directory))
|
(temp-graph (expand-file-name "graph.svg" temporary-file-directory))
|
||||||
(graph (org-roam-build-graph)))
|
(graph (org-roam--build-graph)))
|
||||||
(with-temp-file temp-dot
|
(with-temp-file temp-dot
|
||||||
(insert graph))
|
(insert graph))
|
||||||
(call-process org-roam-graphviz-executable nil 0 nil temp-dot "-Tsvg" "-o" temp-graph)
|
(call-process org-roam-graphviz-executable nil 0 nil temp-dot "-Tsvg" "-o" temp-graph)
|
||||||
@ -765,8 +736,8 @@ If item at point is not org-roam specific, default to Org behaviour."
|
|||||||
|
|
||||||
;;; Org-roam minor mode
|
;;; Org-roam minor mode
|
||||||
(cl-defun org-roam--maybe-update-buffer (&key redisplay)
|
(cl-defun org-roam--maybe-update-buffer (&key redisplay)
|
||||||
"Update `org-roam-buffer' with the necessary information.
|
"Reconstructs `org-roam-buffer'.
|
||||||
This needs to be quick/infrequent, because this is run at
|
This needs to be quick or infrequent, because this is run at
|
||||||
`post-command-hook'."
|
`post-command-hook'."
|
||||||
(let ((buffer (window-buffer)))
|
(let ((buffer (window-buffer)))
|
||||||
(when (and (or redisplay
|
(when (and (or redisplay
|
||||||
@ -784,7 +755,6 @@ This needs to be quick/infrequent, because this is run at
|
|||||||
|
|
||||||
(defun org-roam--roam-link-face (path)
|
(defun org-roam--roam-link-face (path)
|
||||||
"Conditional face for org file links.
|
"Conditional face for org file links.
|
||||||
|
|
||||||
Applies `org-roam-link-face' if PATH correponds to a Roam file."
|
Applies `org-roam-link-face' if PATH correponds to a Roam file."
|
||||||
(if (org-roam--org-roam-file-p path)
|
(if (org-roam--org-roam-file-p path)
|
||||||
'org-roam-link
|
'org-roam-link
|
||||||
@ -795,7 +765,7 @@ Applies `org-roam-link-face' if PATH correponds to a Roam file."
|
|||||||
(when (org-roam--org-roam-file-p)
|
(when (org-roam--org-roam-file-p)
|
||||||
(setq org-roam-last-window (get-buffer-window))
|
(setq org-roam-last-window (get-buffer-window))
|
||||||
(add-hook 'post-command-hook #'org-roam--maybe-update-buffer nil t)
|
(add-hook 'post-command-hook #'org-roam--maybe-update-buffer nil t)
|
||||||
(add-hook 'after-save-hook #'org-roam--update-cache nil t)
|
(add-hook 'after-save-hook #'org-roam--db-update-buffer-file nil t)
|
||||||
(org-roam--setup-file-links)
|
(org-roam--setup-file-links)
|
||||||
(org-roam--maybe-update-buffer :redisplay nil)))
|
(org-roam--maybe-update-buffer :redisplay nil)))
|
||||||
|
|
||||||
@ -816,14 +786,14 @@ This sets `file:' Org links to have the org-link face."
|
|||||||
|
|
||||||
(defun org-roam--delete-file-advice (file &optional _trash)
|
(defun org-roam--delete-file-advice (file &optional _trash)
|
||||||
"Advice for maintaining cache consistency during file deletes."
|
"Advice for maintaining cache consistency during file deletes."
|
||||||
(org-roam--clear-file-from-cache (file-truename file)))
|
(org-roam--db-clear-file (file-truename file)))
|
||||||
|
|
||||||
(defun org-roam--rename-file-advice (file new-file &rest args)
|
(defun org-roam--rename-file-advice (file new-file &rest args)
|
||||||
"Rename backlinks of FILE to refer to NEW-FILE."
|
"Rename backlinks of FILE to refer to NEW-FILE."
|
||||||
(when (and (not (auto-save-file-name-p file))
|
(when (and (not (auto-save-file-name-p file))
|
||||||
(not (auto-save-file-name-p new-file))
|
(not (auto-save-file-name-p new-file))
|
||||||
(org-roam--org-roam-file-p new-file))
|
(org-roam--org-roam-file-p new-file))
|
||||||
(org-roam--ensure-cache-built)
|
(org-roam--db-ensure-built)
|
||||||
(let* ((files-to-rename (org-roam-sql [:select :distinct [file-from]
|
(let* ((files-to-rename (org-roam-sql [:select :distinct [file-from]
|
||||||
:from file-links
|
:from file-links
|
||||||
:where (= file-to $s1)]
|
:where (= file-to $s1)]
|
||||||
@ -832,10 +802,10 @@ This sets `file:' Org links to have the org-link face."
|
|||||||
(new-path (file-truename new-file))
|
(new-path (file-truename new-file))
|
||||||
(slug (org-roam--get-title-or-slug file))
|
(slug (org-roam--get-title-or-slug file))
|
||||||
(old-title (format org-roam-link-title-format slug))
|
(old-title (format org-roam-link-title-format slug))
|
||||||
(new-slug (or (org-roam--get-title-from-cache path)
|
(new-slug (or (car (org-roam--db-get-titles path))
|
||||||
(org-roam--get-title-or-slug new-path)))
|
(org-roam--path-to-slug new-path)))
|
||||||
(new-title (format org-roam-link-title-format new-slug)))
|
(new-title (format org-roam-link-title-format new-slug)))
|
||||||
(org-roam--clear-file-from-cache file)
|
(org-roam--db-clear-file file)
|
||||||
(dolist (file-from files-to-rename)
|
(dolist (file-from files-to-rename)
|
||||||
(let* ((file-from (car file-from))
|
(let* ((file-from (car file-from))
|
||||||
(file-from (if (string-equal (file-truename file-from)
|
(file-from (if (string-equal (file-truename file-from)
|
||||||
@ -859,10 +829,10 @@ This sets `file:' Org links to have the org-link face."
|
|||||||
(replace-match (format "[[file:%s][\\1]]" relative-path))))
|
(replace-match (format "[[file:%s][\\1]]" relative-path))))
|
||||||
(save-window-excursion
|
(save-window-excursion
|
||||||
(find-file file-from)
|
(find-file file-from)
|
||||||
(org-roam--update-cache))))
|
(org-roam--db-update-buffer-file))))
|
||||||
(save-window-excursion
|
(save-window-excursion
|
||||||
(find-file new-path)
|
(find-file new-path)
|
||||||
(org-roam--update-cache)))))
|
(org-roam--db-update-buffer-file)))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(define-minor-mode org-roam-mode
|
(define-minor-mode org-roam-mode
|
||||||
@ -895,7 +865,7 @@ If ARG is `toggle', toggle `org-roam-mode'. Otherwise, behave as if called inter
|
|||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(org-roam--teardown-file-links)
|
(org-roam--teardown-file-links)
|
||||||
(remove-hook 'post-command-hook #'org-roam--maybe-update-buffer t)
|
(remove-hook 'post-command-hook #'org-roam--maybe-update-buffer t)
|
||||||
(remove-hook 'after-save-hook #'org-roam--update-cache t))))))
|
(remove-hook 'after-save-hook #'org-roam--db-update-buffer-file t))))))
|
||||||
|
|
||||||
;;; Show/hide the org-roam buffer
|
;;; Show/hide the org-roam buffer
|
||||||
(define-inline org-roam--current-visibility ()
|
(define-inline org-roam--current-visibility ()
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
(require 'with-simulated-input)
|
(require 'with-simulated-input)
|
||||||
(require 'org-roam)
|
(require 'org-roam)
|
||||||
(require 'org-roam-db)
|
(require 'org-roam-db)
|
||||||
|
(require 'org-roam-utils)
|
||||||
(require 'dash)
|
(require 'dash)
|
||||||
|
|
||||||
(defun abs-path (file-path)
|
(defun abs-path (file-path)
|
||||||
@ -115,7 +116,7 @@
|
|||||||
(describe "org-roam-insert"
|
(describe "org-roam-insert"
|
||||||
(before-each
|
(before-each
|
||||||
(org-roam--test-init)
|
(org-roam--test-init)
|
||||||
(org-roam--clear-cache)
|
(org-roam--db-clear)
|
||||||
(org-roam-build-cache))
|
(org-roam-build-cache))
|
||||||
|
|
||||||
(it "temp1 -> foo"
|
(it "temp1 -> foo"
|
||||||
@ -153,7 +154,7 @@
|
|||||||
(describe "rename file updates cache"
|
(describe "rename file updates cache"
|
||||||
(before-each
|
(before-each
|
||||||
(org-roam--test-init)
|
(org-roam--test-init)
|
||||||
(org-roam--clear-cache)
|
(org-roam--db-clear)
|
||||||
(org-roam-build-cache))
|
(org-roam-build-cache))
|
||||||
|
|
||||||
(it "foo -> new_foo"
|
(it "foo -> new_foo"
|
||||||
@ -161,28 +162,28 @@
|
|||||||
(abs-path "new_foo.org"))
|
(abs-path "new_foo.org"))
|
||||||
;; Cache should be cleared of old file
|
;; Cache should be cleared of old file
|
||||||
(expect (caar (org-roam-sql [:select (funcall count)
|
(expect (caar (org-roam-sql [:select (funcall count)
|
||||||
:from titles
|
:from titles
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
(abs-path "foo.org"))) :to-be 0)
|
(abs-path "foo.org"))) :to-be 0)
|
||||||
(expect (caar (org-roam-sql [:select (funcall count)
|
(expect (caar (org-roam-sql [:select (funcall count)
|
||||||
:from refs
|
:from refs
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
(abs-path "foo.org"))) :to-be 0)
|
(abs-path "foo.org"))) :to-be 0)
|
||||||
(expect (caar (org-roam-sql [:select (funcall count)
|
(expect (caar (org-roam-sql [:select (funcall count)
|
||||||
:from file-links
|
:from file-links
|
||||||
:where (= file-from $s1)]
|
:where (= file-from $s1)]
|
||||||
(abs-path "foo.org"))) :to-be 0)
|
(abs-path "foo.org"))) :to-be 0)
|
||||||
|
|
||||||
;; Cache should be updated
|
;; Cache should be updated
|
||||||
(expect (org-roam-sql [:select [file-to]
|
(expect (org-roam-sql [:select [file-to]
|
||||||
:from file-links
|
:from file-links
|
||||||
:where (= file-from $s1)]
|
:where (= file-from $s1)]
|
||||||
(abs-path "new_foo.org"))
|
(abs-path "new_foo.org"))
|
||||||
:to-have-same-items-as
|
:to-have-same-items-as
|
||||||
(list (list (abs-path "bar.org"))))
|
(list (list (abs-path "bar.org"))))
|
||||||
(expect (org-roam-sql [:select [file-from]
|
(expect (org-roam-sql [:select [file-from]
|
||||||
:from file-links
|
:from file-links
|
||||||
:where (= file-to $s1)]
|
:where (= file-to $s1)]
|
||||||
(abs-path "new_foo.org"))
|
(abs-path "new_foo.org"))
|
||||||
:to-have-same-items-as
|
:to-have-same-items-as
|
||||||
(list (list (abs-path "nested/bar.org"))))
|
(list (list (abs-path "nested/bar.org"))))
|
||||||
@ -199,28 +200,28 @@
|
|||||||
(abs-path "foo with spaces.org"))
|
(abs-path "foo with spaces.org"))
|
||||||
;; Cache should be cleared of old file
|
;; Cache should be cleared of old file
|
||||||
(expect (caar (org-roam-sql [:select (funcall count)
|
(expect (caar (org-roam-sql [:select (funcall count)
|
||||||
:from titles
|
:from titles
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
(abs-path "foo.org"))) :to-be 0)
|
(abs-path "foo.org"))) :to-be 0)
|
||||||
(expect (caar (org-roam-sql [:select (funcall count)
|
(expect (caar (org-roam-sql [:select (funcall count)
|
||||||
:from refs
|
:from refs
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
(abs-path "foo.org"))) :to-be 0)
|
(abs-path "foo.org"))) :to-be 0)
|
||||||
(expect (caar (org-roam-sql [:select (funcall count)
|
(expect (caar (org-roam-sql [:select (funcall count)
|
||||||
:from file-links
|
:from file-links
|
||||||
:where (= file-from $s1)]
|
:where (= file-from $s1)]
|
||||||
(abs-path "foo.org"))) :to-be 0)
|
(abs-path "foo.org"))) :to-be 0)
|
||||||
|
|
||||||
;; Cache should be updated
|
;; Cache should be updated
|
||||||
(expect (org-roam-sql [:select [file-to]
|
(expect (org-roam-sql [:select [file-to]
|
||||||
:from file-links
|
:from file-links
|
||||||
:where (= file-from $s1)]
|
:where (= file-from $s1)]
|
||||||
(abs-path "foo with spaces.org"))
|
(abs-path "foo with spaces.org"))
|
||||||
:to-have-same-items-as
|
:to-have-same-items-as
|
||||||
(list (list (abs-path "bar.org"))))
|
(list (list (abs-path "bar.org"))))
|
||||||
(expect (org-roam-sql [:select [file-from]
|
(expect (org-roam-sql [:select [file-from]
|
||||||
:from file-links
|
:from file-links
|
||||||
:where (= file-to $s1)]
|
:where (= file-to $s1)]
|
||||||
(abs-path "foo with spaces.org"))
|
(abs-path "foo with spaces.org"))
|
||||||
:to-have-same-items-as
|
:to-have-same-items-as
|
||||||
(list (list (abs-path "nested/bar.org"))))
|
(list (list (abs-path "nested/bar.org"))))
|
||||||
@ -237,12 +238,12 @@
|
|||||||
(abs-path "meaningful-title.org"))
|
(abs-path "meaningful-title.org"))
|
||||||
;; File has no forward links
|
;; File has no forward links
|
||||||
(expect (caar (org-roam-sql [:select (funcall count)
|
(expect (caar (org-roam-sql [:select (funcall count)
|
||||||
:from file-links
|
:from file-links
|
||||||
:where (= file-from $s1)]
|
:where (= file-from $s1)]
|
||||||
(abs-path "no-title.org"))) :to-be 0)
|
(abs-path "no-title.org"))) :to-be 0)
|
||||||
(expect (caar (org-roam-sql [:select (funcall count)
|
(expect (caar (org-roam-sql [:select (funcall count)
|
||||||
:from file-links
|
:from file-links
|
||||||
:where (= file-from $s1)]
|
:where (= file-from $s1)]
|
||||||
(abs-path "meaningful-title.org"))) :to-be 1)
|
(abs-path "meaningful-title.org"))) :to-be 1)
|
||||||
|
|
||||||
;; Links are updated with the appropriate name
|
;; Links are updated with the appropriate name
|
||||||
@ -255,7 +256,7 @@
|
|||||||
(it "web_ref -> hello"
|
(it "web_ref -> hello"
|
||||||
(expect (org-roam-sql
|
(expect (org-roam-sql
|
||||||
[:select [file] :from refs
|
[:select [file] :from refs
|
||||||
:where (= ref $s1)]
|
:where (= ref $s1)]
|
||||||
"https://google.com/")
|
"https://google.com/")
|
||||||
:to-equal
|
:to-equal
|
||||||
(list (list (abs-path "web_ref.org"))))
|
(list (list (abs-path "web_ref.org"))))
|
||||||
@ -263,35 +264,35 @@
|
|||||||
(abs-path "hello.org"))
|
(abs-path "hello.org"))
|
||||||
(expect (org-roam-sql
|
(expect (org-roam-sql
|
||||||
[:select [file] :from refs
|
[:select [file] :from refs
|
||||||
:where (= ref $s1)]
|
:where (= ref $s1)]
|
||||||
"https://google.com/")
|
"https://google.com/")
|
||||||
:to-equal (list (list (abs-path "hello.org"))))
|
:to-equal (list (list (abs-path "hello.org"))))
|
||||||
(expect (caar (org-roam-sql
|
(expect (caar (org-roam-sql
|
||||||
[:select [ref] :from refs
|
[:select [ref] :from refs
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
(abs-path "web_ref.org")))
|
(abs-path "web_ref.org")))
|
||||||
:to-equal nil)))
|
:to-equal nil)))
|
||||||
|
|
||||||
(describe "delete file updates cache"
|
(describe "delete file updates cache"
|
||||||
(before-each
|
(before-each
|
||||||
(org-roam--test-init)
|
(org-roam--test-init)
|
||||||
(org-roam--clear-cache)
|
(org-roam--db-clear)
|
||||||
(org-roam-build-cache)
|
(org-roam-build-cache)
|
||||||
(sleep-for 1))
|
(sleep-for 1))
|
||||||
|
|
||||||
(it "delete foo"
|
(it "delete foo"
|
||||||
(delete-file (abs-path "foo.org"))
|
(delete-file (abs-path "foo.org"))
|
||||||
(expect (caar (org-roam-sql [:select (funcall count)
|
(expect (caar (org-roam-sql [:select (funcall count)
|
||||||
:from titles
|
:from titles
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
(abs-path "foo.org"))) :to-be 0)
|
(abs-path "foo.org"))) :to-be 0)
|
||||||
(expect (caar (org-roam-sql [:select (funcall count)
|
(expect (caar (org-roam-sql [:select (funcall count)
|
||||||
:from refs
|
:from refs
|
||||||
:where (= file $s1)]
|
:where (= file $s1)]
|
||||||
(abs-path "foo.org"))) :to-be 0)
|
(abs-path "foo.org"))) :to-be 0)
|
||||||
(expect (caar (org-roam-sql [:select (funcall count)
|
(expect (caar (org-roam-sql [:select (funcall count)
|
||||||
:from file-links
|
:from file-links
|
||||||
:where (= file-from $s1)]
|
:where (= file-from $s1)]
|
||||||
(abs-path "foo.org"))) :to-be 0))
|
(abs-path "foo.org"))) :to-be 0))
|
||||||
|
|
||||||
(it "delete web_ref"
|
(it "delete web_ref"
|
||||||
|
Reference in New Issue
Block a user