mirror of
https://github.com/org-roam/org-roam
synced 2025-08-01 12:17:21 -05:00
Compare commits
66 Commits
Author | SHA1 | Date | |
---|---|---|---|
69116a4da4 | |||
3014c63d50 | |||
a073bcff5c | |||
b948cfbe37 | |||
3716817618 | |||
608feed855 | |||
6132155393 | |||
d8985aa245 | |||
61a544cebd | |||
ddaf7ec10e | |||
8318da895d | |||
9eaf91b801 | |||
3bb45afccb | |||
fee008cdfb | |||
36152590ad | |||
a69968fc12 | |||
d71675fb47 | |||
3782e88d50 | |||
b4f14eebae | |||
cce6a05630 | |||
cc3689f30f | |||
b179a5a1a6 | |||
9172001c11 | |||
c51cadfe25 | |||
f6950a9820 | |||
feb9179c9f | |||
f50d6e7376 | |||
65ea325071 | |||
62d311de22 | |||
c8a360afdd | |||
cebe77135a | |||
25d828c32e | |||
fd97c80a26 | |||
97a342fd3f | |||
d20480bb8d | |||
b163c900b8 | |||
0432b00485 | |||
ccfa97ec3a | |||
86e102d990 | |||
eed1df90f5 | |||
905564a7eb | |||
9f7a4a0b02 | |||
aafe4114c2 | |||
3e2716edf3 | |||
445e3594b2 | |||
6f5d65abd9 | |||
817d8036fb | |||
c17310f0de | |||
bf3ebe2121 | |||
47ad646d51 | |||
6263c3a956 | |||
69742c3d51 | |||
5b15159a2c | |||
c0c240b975 | |||
001de3a874 | |||
6170cc9928 | |||
cc95540135 | |||
24a683d58c | |||
86c9085363 | |||
b67bccd6c2 | |||
8b43093d1a | |||
679ef6ef00 | |||
ee9a8d423e | |||
d3c7d74329 | |||
3bf0a0a35d | |||
d0f17c6477 |
@ -4,6 +4,9 @@
|
||||
(elisp-lint-ignored-validators . ("byte-compile" "package-lint"))
|
||||
(elisp-lint-indent-specs . ((describe . 1)
|
||||
(it . 1)
|
||||
(thread-first . 0)
|
||||
(cl-flet . 1)
|
||||
(cl-flet* . 1)
|
||||
(org-element-map . defun)
|
||||
(org-roam-dolist-with-progress . 2)
|
||||
(org-roam-with-temp-buffer . 1)
|
||||
|
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1,6 +1,6 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [jethrokuan, zaeph]
|
||||
github: [jethrokuan]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
|
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -39,5 +39,3 @@ Example:
|
||||
### Environment
|
||||
|
||||
<!-- Please M-x org-roam-diagnostics and paste results here -->
|
||||
|
||||
- Org-roam commit: https://github.com/jethrokuan/org-roam/commit/commithashhere
|
||||
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Eldev
|
||||
run: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/github-eldev | sh
|
||||
run: curl -fsSL https://raw.github.com/org-roam/org-roam/master/github-eldev | sh
|
||||
|
||||
- name: Install dependencies
|
||||
run: make prepare
|
||||
|
72
CHANGELOG.md
72
CHANGELOG.md
@ -1,8 +1,64 @@
|
||||
# Changelog
|
||||
|
||||
## TBD
|
||||
## 2.2.2
|
||||
### Breaking
|
||||
### Added
|
||||
- [#1806](https://github.com/org-roam/org-roam/pull/1806) db: support caching and usage of Org 9.5's in-built citations
|
||||
- [#2138](https://github.com/org-roam/org-roam/pull/2138) export: add new module
|
||||
- [#2170](https://github.com/org-roam/org-roam/pull/2170) log: add new module for working with org logs
|
||||
- [#2158](https://github.com/org-roam/org-roam/pull/2158) db: support emacsql-sqlite-builtin and emacsql-sqlite-module
|
||||
- [#2160](https://github.com/org-roam/org-roam/pull/2160) core: support a list of `org-roam-file-exclude-regexp`
|
||||
|
||||
### Removed
|
||||
### Fixed
|
||||
- [#2091](https://github.com/org-roam/org-roam/pull/2091) node: fix org-roam-promote-entire-buffer structural errors
|
||||
- [#2130](https://github.com/org-roam/org-roam/pull/2130) buffer: unlinked-references section now also searches within symlinked directories
|
||||
- [#2152](https://github.com/org-roam/org-roam/pull/2152) org-roam-preview-default-function: doesn't copy copy content of next heading node when current node's content is empty
|
||||
- [#2159](https://github.com/org-roam/org-roam/pull/2159) db: fix db syncs on narrowed buffers
|
||||
- [#2156](https://github.com/org-roam/org-roam/pull/2157) capture: templates with functions are handled correctly to avoid signaling `char-or-string-p`
|
||||
|
||||
### Changed
|
||||
- [#2160](https://github.com/org-roam/org-roam/pull/2160) core: ignore files in `org-attach-id-dir` by default
|
||||
|
||||
## 2.2.1
|
||||
### Breaking
|
||||
- [#2054](https://github.com/org-roam/org-roam/pull/2054) node: simplify default `org-roam-node-display-template`.
|
||||
This was done so completions work fine by default on all completion systems. To restore the tabular vertical completion interface, set this in your configuration:
|
||||
|
||||
```emacs-lisp
|
||||
(setq org-roam-node-display-template
|
||||
(concat "${title:*} "
|
||||
(propertize "${tags:10}" 'face 'org-tag)))
|
||||
```
|
||||
|
||||
### Added
|
||||
- [#2042](https://github.com/org-roam/org-roam/pull/2042) db: add `org-roam-db-extra-links-elements` and `org-roam-db-extra-links-exclude-keys` for fine-grained control over additional link parsing
|
||||
- [#2049](https://github.com/org-roam/org-roam/pull/2049) capture: allow ID to be used as part of `org-roam-capture-templates`
|
||||
- [#2050](https://github.com/org-roam/org-roam/pull/2050) core: add `FILTER-FN` to `org-roam-node-random`
|
||||
- [#2065](https://github.com/org-roam/org-roam/pull/2065) dailies: add `keys` argument to the remaining dailies functions `org-roam-dailies-goto-yesterday`/`-today`/`-tomorrow`/`-date` and `org-roam-dailies-capture-yesterday`/`-tomorrow`/`-date` to give the abilty to get into a capture buffer bypassing the selection screen in all dailies commands. Extension of #2055
|
||||
- [#2079](https://github.com/org-roam/org-roam/pull/2079) capture: ensure that `:ref` info captured in all cases.
|
||||
- [#2121](https://github.com/org-roam/org-roam/pull/2121) buffer: add unique option to `org-roam-backlinks-section`
|
||||
|
||||
### Removed
|
||||
### Fixed
|
||||
- [#2086](https://github.com/org-roam/org-roam/pull/2086) capture: correctly update org-id-locations on capture
|
||||
- [#2082](https://github.com/org-roam/org-roam/pull/2082) buffer: don't destroy window if `org-roam-node-toggle` reuses window
|
||||
- [#2080](https://github.com/org-roam/org-roam/pull/2080) dailies: prevent multiple "dailies/" subdir expansions
|
||||
- [#2055](https://github.com/org-roam/org-roam/pull/2055) dailies: removed stray f require, which was causing require and compilation errors
|
||||
- [#2117](https://github.com/org-roam/org-roam/pull/2117) capture: preserve trailing whitespace content in capture templates
|
||||
|
||||
### Changed
|
||||
- [#2060](https://github.com/org-roam/org-roam/pull/2060) node: added double acute accent normalization for Unicode characters in titles
|
||||
- [#2040](https://github.com/org-roam/org-roam/pull/2040) completions: fix completions display-width for Helm users
|
||||
- [#2025](https://github.com/org-roam/org-roam/pull/2025) chore: removed the dependencies on f.el and s.el
|
||||
- [#2109](https://github.com/org-roam/org-roam/pull/2109) capture: `org-roam-node-insert` places cursor after inserted link where appropriate
|
||||
- [#2123](https://github.com/org-roam/org-roam/pull/2123), [#2124](https://github.com/org-roam/org-roam/pull/2124) buffer: `org-roam-mode-section-functions` renamed to `org-roam-mode-sections`, supports passing args into the section-rendering function
|
||||
|
||||
## 2.2.0
|
||||
### Added
|
||||
- [#1806](https://github.com/org-roam/org-roam/pull/1806), [#2017](https://github.com/org-roam/org-roam/pull/2017) db: support caching and usage of Org 9.5's in-built citations
|
||||
- [#1963](https://github.com/org-roam/org-roam/pull/1963) db: cache file title into files table
|
||||
- [#1977](https://github.com/org-roam/org-roam/pull/1977) db: support Org-ref v3 citations
|
||||
- [#1907](https://github.com/org-roam/org-roam/pull/1907), [#2009](https://github.com/org-roam/org-roam/pull/2009), [#2018](https://github.com/org-roam/org-roam/pull/2018) db: support sqlite3
|
||||
- [#2028](https://github.com/org-roam/org-roam/pull/2028) dailies: add `keys` argument to `org-roam-dailies-capture-today` and `org-roam-dailies--capture` functions to give the abilty to get into a capture buffer bypassing the selection screen
|
||||
|
||||
### Removed
|
||||
### Changed
|
||||
@ -10,12 +66,22 @@
|
||||
- [#1809](https://github.com/org-roam/org-roam/pull/1809) capture: the mandatory `:if-new` property of each capture template is now renamed to `:target`
|
||||
- [#1829](https://github.com/org-roam/org-roam/pull/1829) perf: file sql updates are now wrapped in a transaction
|
||||
- [#1877](https://github.com/org-roam/org-roam/pull/1877) dailies: stop asking for time, only date
|
||||
- [#1949](https://github.com/org-roam/org-roam/pull/1949) db: check for property drawers are now case-insensitive
|
||||
|
||||
### Fixed
|
||||
- [#1798](https://github.com/org-roam/org-roam/pull/1798) org-roam-node-at-point: do not skip invisible headings
|
||||
- [#1807](https://github.com/org-roam/org-roam/pull/1807) capture: always trigger `:if-new` template for existing nodes
|
||||
- [#1813](https://github.com/org-roam/org-roam/pull/1813) db: prevent empty ROAM_ALIASES from crashing db updates
|
||||
- [#1816](https://github.com/org-roam/org-roam/pull/1816) db: prevent invalid ROAM_REFS from crashing db updates
|
||||
- [#1893](https://github.com/org-roam/org-roam/pull/1893), [#1896](https://github.com/org-roam/org-roam/pull/1896), [#1901](https://github.com/org-roam/org-roam/pull/1901), [#1895](https://github.com/org-roam/org-roam/pull/1895), [#1904](https://github.com/org-roam/org-roam/pull/1904) completions: various mini-buffer related completion fixes
|
||||
- [#1931](https://github.com/org-roam/org-roam/pull/1931) utils: org-roam-set-keyword now skips over all drawers
|
||||
- [#1947](https://github.com/org-roam/org-roam/pull/1947) db: links in ROAM_REFS are no longer considered as links
|
||||
- [#1948](https://github.com/org-roam/org-roam/pull/1948) completions: fix same-line completions
|
||||
- [#1953](https://github.com/org-roam/org-roam/pull/1953) db: refresh CATEGORY before writing to db
|
||||
- [#1946](https://github.com/org-roam/org-roam/pull/1946), [#1946](https://github.com/org-roam/org-roam/pull/1946), [#1958](https://github.com/org-roam/org-roam/pull/1958) various performance improvements
|
||||
- [#1980](https://github.com/org-roam/org-roam/pull/1980) utils: fix org-roam-with-file changing the minor-mode
|
||||
- [#2016](https://github.com/org-roam/org-roam/pull/2016) db: fix node caching being affected by agenda variables
|
||||
- [#2033](https://github.com/org-roam/org-roam/pull/2023) db: respect local variables during db parsing
|
||||
|
||||
## 2.1.0
|
||||
### Added
|
||||
|
53
README.md
53
README.md
@ -47,30 +47,6 @@ Stable](https://stable.melpa.org/) using `package.el`:
|
||||
```
|
||||
M-x package-install RET org-roam RET
|
||||
```
|
||||
|
||||
Here's a very basic sample for configuration of `org-roam` using `use-package`:
|
||||
|
||||
```emacs-lisp
|
||||
(use-package org-roam
|
||||
:ensure t
|
||||
:custom
|
||||
(org-roam-directory (file-truename "/path/to/org-files/"))
|
||||
:bind (("C-c n l" . org-roam-buffer-toggle)
|
||||
("C-c n f" . org-roam-node-find)
|
||||
("C-c n g" . org-roam-graph)
|
||||
("C-c n i" . org-roam-node-insert)
|
||||
("C-c n c" . org-roam-capture)
|
||||
;; Dailies
|
||||
("C-c n j" . org-roam-dailies-capture-today))
|
||||
:config
|
||||
(org-roam-db-autosync-mode)
|
||||
;; If using org-roam-protocol
|
||||
(require 'org-roam-protocol))
|
||||
```
|
||||
|
||||
Note that the `file-truename` function is only necessary when you use symbolic
|
||||
link to `org-roam-directory`. Org-roam won't automatically resolve symbolic link
|
||||
to the directory.
|
||||
</details>
|
||||
|
||||
### Using `straight.el`
|
||||
@ -198,6 +174,33 @@ Org-roam also comes with `.texi` files to integrate with Emacs' built-in Info
|
||||
system. Read the manual to find more details for how to install them manually.
|
||||
</details>
|
||||
|
||||
## Configuration
|
||||
|
||||
Here's a very basic sample for configuration of `org-roam` using `use-package`:
|
||||
|
||||
```emacs-lisp
|
||||
(use-package org-roam
|
||||
:ensure t
|
||||
:custom
|
||||
(org-roam-directory (file-truename "/path/to/org-files/"))
|
||||
:bind (("C-c n l" . org-roam-buffer-toggle)
|
||||
("C-c n f" . org-roam-node-find)
|
||||
("C-c n g" . org-roam-graph)
|
||||
("C-c n i" . org-roam-node-insert)
|
||||
("C-c n c" . org-roam-capture)
|
||||
;; Dailies
|
||||
("C-c n j" . org-roam-dailies-capture-today))
|
||||
:config
|
||||
;; If you're using a vertical completion framework, you might want a more informative completion interface
|
||||
(setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
|
||||
(org-roam-db-autosync-mode)
|
||||
;; If using org-roam-protocol
|
||||
(require 'org-roam-protocol))
|
||||
```
|
||||
|
||||
Note that the `file-truename` function is only necessary when you use symbolic
|
||||
link to `org-roam-directory`. Org-roam won't automatically resolve symbolic link
|
||||
to the directory.
|
||||
## Getting Started
|
||||
|
||||
[David Wilson](https://github.com/daviwil) of [System
|
||||
@ -225,7 +228,7 @@ it has not already been addressed on [GitHub][issues] or on
|
||||
|
||||
- [Jethro Kuan](https://braindump.jethro.dev/)
|
||||
([Source](https://github.com/jethrokuan/braindump/tree/master/org))
|
||||
- [Alexey Shmalko](https://braindump.rasen.dev/)
|
||||
- [Alexey Shmalko](https://www.alexeyshmalko.com/)
|
||||
- [Sidharth Arya](https://sidhartharya.github.io/braindump/index.html)
|
||||
|
||||
## Contributing
|
||||
|
592
doc/org-roam.org
592
doc/org-roam.org
@ -1,23 +1,23 @@
|
||||
#+title: Org-roam User Manual
|
||||
#+author: Jethro Kuan
|
||||
#+email: jethrokuan95@gmail.com
|
||||
#+date: 2020-2021
|
||||
#+date: 2020-2022
|
||||
#+language: en
|
||||
|
||||
#+texinfo_deffn: t
|
||||
#+texinfo_dir_category: Emacs
|
||||
#+texinfo_dir_title: Org-roam: (org-roam).
|
||||
#+texinfo_dir_desc: Roam Research for Emacs.
|
||||
#+subtitle: for version 2.1.0
|
||||
#+subtitle: for version 2.2.1
|
||||
|
||||
#+options: H:4 num:3 toc:nil creator:t ':t
|
||||
#+property: header-args :eval never
|
||||
#+texinfo: @noindent
|
||||
|
||||
This manual is for Org-roam version 2.1.0.
|
||||
This manual is for Org-roam version 2.2.1.
|
||||
|
||||
#+BEGIN_QUOTE
|
||||
Copyright (C) 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
Copyright (C) 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
You can redistribute this document and/or modify it under the terms of the GNU
|
||||
General Public License as published by the Free Software Foundation, either
|
||||
@ -134,7 +134,7 @@ A slip-box requires a method for quickly capturing ideas. These are called
|
||||
*fleeting notes*: they are simple reminders of information or ideas that will
|
||||
need to be processed later on, or trashed. This is typically accomplished using
|
||||
~org-capture~ (see info:org#Capture), or using Org-roam's daily notes
|
||||
functionality (see [[*Org-roam Dailies][Org-roam Dailies]]). This provides a central inbox for collecting
|
||||
functionality (see [[*org-roam-dailies][org-roam-dailies]]). This provides a central inbox for collecting
|
||||
thoughts, to be processed later into permanent notes.
|
||||
|
||||
*Permanent notes*
|
||||
@ -288,29 +288,25 @@ in your Emacs environment as a prerequisite for Org-roam when you install it.
|
||||
~emacsql-sqlite~ requires a C compiler (e.g. ~gcc~ or ~clang~) to be present in
|
||||
your computer. How to install a C compiler depends on the OS that you use.
|
||||
|
||||
- For Windows:
|
||||
**** C Compiler for Windows
|
||||
|
||||
There are various ways to install one, depending on how you have installed
|
||||
Emacs. If you use Emacs within a Cygwin or MinGW environment, then you should
|
||||
install a compiler using their respective package manager.
|
||||
One of the easiest ways to install a C compiler in Windows is to use [[https://www.msys2.org/][MSYS2]] as at the time of this writing:
|
||||
|
||||
If you have installed your Emacs from the [[https://www.gnu.org/software/emacs/][GNU Emacs website]], then the easiest way
|
||||
is to use [[https://www.msys2.org/][MSYS2]] as at the time of this writing:
|
||||
|
||||
1. Use the installer in the official website and install MSYS2
|
||||
2. Run MSYS2
|
||||
3. In the command-line tool, type the following and answer "Y" to proceed:
|
||||
1. Download and use the installer in the official MSYS2 website
|
||||
2. Run MSYS2 and in its terminal, type the following and answer "Y" to
|
||||
proceed -- this will install ~gcc~ in your PC:
|
||||
|
||||
#+BEGIN_SRC bash
|
||||
pacman -S gcc
|
||||
#+END_SRC
|
||||
|
||||
Note that you do not need to manually set the PATH for MSYS2; the
|
||||
installer automatically takes care of it for you.
|
||||
4. On Windows, add ~C:\msys64\usr\bin~ (command =where gcc= in MSYS2 terminal
|
||||
can tell you the correct path) to ~PATH~ in your environmental variables
|
||||
|
||||
4. Open Emacs and call ~M-x org-roam-db-autosync-mode~
|
||||
5. Launch Emacs and call ~M-x org-roam-db-autosync-mode~ (launch Emacs after
|
||||
defining the path, so that Emacs can recognize it)
|
||||
|
||||
This will automatically start compiling ~emacsql-sqlite~; you should see a
|
||||
This will automatically start compiling ~emacsql-sqlite~; you should see a
|
||||
message in minibuffer. It may take a while until compilation completes. Once
|
||||
complete, you should see a new file ~emacsql-sqlite.exe~ created in a subfolder
|
||||
named ~sqlite~ under ~emacsql-sqlite~ installation folder. It's typically in
|
||||
@ -373,7 +369,12 @@ For this tutorial, create an empty directory, and set ~org-roam-directory~:
|
||||
#+END_SRC
|
||||
|
||||
The ~file-truename~ function is only necessary when you use symbolic links
|
||||
inside ~org-roam-directory~: Org-roam does not resolve symbolic links.
|
||||
inside ~org-roam-directory~: Org-roam does not resolve symbolic links. One can
|
||||
however instruct Emacs to always resolve symlinks, at a performance cost:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(setq find-file-visit-truename t)
|
||||
#+end_src
|
||||
|
||||
Next, we setup Org-roam to run functions on file changes to maintain cache
|
||||
consistency. This is achieved by running ~M-x org-roam-db-autosync-mode~. To
|
||||
@ -417,6 +418,54 @@ brought through the node creation process.
|
||||
One can also conveniently insert links via the completion-at-point functions
|
||||
Org-roam provides (see [[*Completion][Completion]]).
|
||||
|
||||
** Customizing Node Completions
|
||||
|
||||
Node selection is achieved via the ~completing-read~ interface, typically
|
||||
through `org-roam-node-read`. The presentation of these nodes are governed by
|
||||
~org-roam-node-display-template~.
|
||||
|
||||
- Variable: org-roam-node-display-template
|
||||
|
||||
Configures display formatting for Org-roam node.
|
||||
|
||||
Patterns of form "${field-name:length}" are interpolated based
|
||||
on the current node.
|
||||
|
||||
Each "field-name" is replaced with the return value of each
|
||||
corresponding accessor function for org-roam-node, e.g.
|
||||
"${title}" will be interpolated by the result of
|
||||
org-roam-node-title. You can also define custom accessors using
|
||||
cl-defmethod. For example, you can define:
|
||||
|
||||
(cl-defmethod org-roam-node-my-title ((node org-roam-node))
|
||||
(concat "My " (org-roam-node-title node)))
|
||||
|
||||
and then reference it here or in the capture templates as
|
||||
"${my-title}".
|
||||
|
||||
"length" is an optional specifier and declares how many
|
||||
characters can be used to display the value of the corresponding
|
||||
field. If it's not specified, the field will be inserted as is,
|
||||
i.e. it won't be aligned nor trimmed. If it's an integer, the
|
||||
field will be aligned accordingly and all the exceeding
|
||||
characters will be trimmed out. If it's "*", the field will use
|
||||
as many characters as possible and will be aligned accordingly.
|
||||
|
||||
A closure can also be assigned to this variable in which case the
|
||||
closure is evaluated and the return value is used as the
|
||||
template. The closure must evaluate to a valid template string.
|
||||
|
||||
If you're using a vertical completion framework, such as Ivy and Selectrum,
|
||||
Org-roam supports the generation of an aligned, tabular completion interface.
|
||||
For example, to include a column for tags up to 10 character widths wide, one
|
||||
can set ~org-roam-node-display-template~ as such:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(setq org-roam-node-display-template
|
||||
(concat "${title:*} "
|
||||
(propertize "${tags:10}" 'face 'org-tag)))
|
||||
#+end_src
|
||||
|
||||
* Customizing Node Caching
|
||||
** How to cache
|
||||
|
||||
@ -489,6 +538,35 @@ all headlines with the ~ATTACH~ tag from the Org-roam database, one can set:
|
||||
(not (member "ATTACH" (org-get-tags)))))
|
||||
#+end_src
|
||||
|
||||
Org-roam relied on the obtained Org AST for the buffer to parse links. However,
|
||||
links appearing in some places (e.g. within property drawers) are not considered
|
||||
by the Org AST to be links. Therefore, Org-roam takes special care of
|
||||
additionally trying to process these links. Use
|
||||
~org-roam-db-extra-links-elements~ to specify which additional Org AST element
|
||||
types to consider.
|
||||
|
||||
- Variable: org-roam-db-extra-links-elements
|
||||
|
||||
The list of Org element types to include for parsing by Org-roam.
|
||||
|
||||
By default, when parsing Org's AST, links within keywords and
|
||||
property drawers are not parsed as links. Sometimes however, it
|
||||
is desirable to parse and cache these links (e.g. hiding links in
|
||||
a property drawer).
|
||||
|
||||
Additionally, one may want to ignore certain keys from being excluded within
|
||||
property drawers. For example, we would not want ~ROAM_REFS~ links to be
|
||||
self-referential. Hence, to exclude specific keys, we use
|
||||
~org-roam-db-extra-links-exclude-keys~.
|
||||
|
||||
- Variable: org-roam-db-extra-links-exclude-keys
|
||||
|
||||
Keys to ignore when mapping over links.
|
||||
|
||||
The car of the association list is the Org element type (e.g. keyword). The
|
||||
cdr is a list of case-insensitive strings to exclude from being treated as
|
||||
links.
|
||||
|
||||
** When to cache
|
||||
|
||||
By default, Org-roam is eager in caching: each time an Org-roam file is modified
|
||||
@ -555,10 +633,10 @@ There are currently 3 provided widget types:
|
||||
- Unlinked references :: View nodes that contain text that match the nodes
|
||||
title/alias but are not linked
|
||||
|
||||
To configure what sections are displayed in the buffer, set ~org-roam-mode-section-functions~.
|
||||
To configure what sections are displayed in the buffer, set ~org-roam-mode-sections.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(setq org-roam-mode-section-functions
|
||||
(setq org-roam-mode-sections
|
||||
(list #'org-roam-backlinks-section
|
||||
#'org-roam-reflinks-section
|
||||
;; #'org-roam-unlinked-references-section
|
||||
@ -567,6 +645,16 @@ To configure what sections are displayed in the buffer, set ~org-roam-mode-secti
|
||||
|
||||
Note that computing unlinked references may be slow, and has not been added in by default.
|
||||
|
||||
For each section function, you can pass args along to modify its behaviour. For
|
||||
example, if you want to render unique sources for backlinks (and also keep
|
||||
rendering reference links), set ~org-roam-mode-sections~ as follows:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(setq org-roam-mode-sections
|
||||
'((org-roam-backlinks-section :unique t)
|
||||
org-roam-reflinks-section))
|
||||
#+end_src
|
||||
|
||||
** Configuring the Org-roam buffer display
|
||||
|
||||
Org-roam does not control how the pop-up buffer is displayed: this is left to
|
||||
@ -674,7 +762,7 @@ With the above example, if another node links to https://www.google.com/, it
|
||||
will show up as a “reference backlink”.
|
||||
|
||||
These keys also come in useful for when taking website notes, using the
|
||||
~roam-ref~ protocol (see [[*Org-roam Protocol][Roam Protocol]]).
|
||||
~roam-ref~ protocol (see [[*org-roam-protocol][org-roam-protocol]]).
|
||||
|
||||
You may assign multiple refs to a single node, for example when you want
|
||||
multiple papers in a series to share the same note, or an article has a citation
|
||||
@ -715,6 +803,16 @@ citation key:
|
||||
:END:
|
||||
#+end_src
|
||||
|
||||
or
|
||||
|
||||
#+begin_src org
|
||||
,* Probabilistic Robotics
|
||||
:PROPERTIES:
|
||||
:ID: 51b7b82c-bbb4-4822-875a-ed548cffda10
|
||||
:ROAM_REFS: [cite:@thrun2005probabilistic]
|
||||
:END:
|
||||
#+end_src
|
||||
|
||||
for ~org-cite~, or:
|
||||
|
||||
#+begin_src org
|
||||
@ -795,202 +893,6 @@ Note that the Org-roam database stores metadata information in plain-text
|
||||
(headline text, for example), so if this information is private to you then you
|
||||
should also ensure the database is encrypted.
|
||||
|
||||
* Org-roam Protocol
|
||||
|
||||
Org-roam provides extensions for capturing content from external applications
|
||||
such as the browser, via ~org-protocol~. Org-roam extends ~org-protocol~ with 2
|
||||
protocols: the ~roam-node~ and ~roam-ref~ protocols.
|
||||
|
||||
** Installation
|
||||
|
||||
To enable Org-roam's protocol extensions, simply add the following to your init
|
||||
file:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(require 'org-roam-protocol)
|
||||
#+END_SRC
|
||||
|
||||
We also need to set up ~org-protocol~: the instructions for setting up
|
||||
~org-protocol~ are reproduced below.
|
||||
|
||||
*** Linux
|
||||
For Linux users, create a desktop application in
|
||||
~~/.local/share/applications/org-protocol.desktop~:
|
||||
|
||||
#+begin_example
|
||||
[Desktop Entry]
|
||||
Name=Org-Protocol
|
||||
Exec=emacsclient %u
|
||||
Icon=emacs-icon
|
||||
Type=Application
|
||||
Terminal=false
|
||||
MimeType=x-scheme-handler/org-protocol
|
||||
#+end_example
|
||||
|
||||
Associate ~org-protocol://~ links with the desktop application by
|
||||
running in your shell:
|
||||
|
||||
#+BEGIN_SRC bash
|
||||
xdg-mime default org-protocol.desktop x-scheme-handler/org-protocol
|
||||
#+END_SRC
|
||||
|
||||
To disable the "confirm" prompt in Chrome, you can also make Chrome show a
|
||||
checkbox to tick, so that the ~Org-Protocol Client~ app will be used without
|
||||
confirmation. To do this, run in a shell:
|
||||
|
||||
#+BEGIN_SRC bash
|
||||
sudo mkdir -p /etc/opt/chrome/policies/managed/
|
||||
sudo tee /etc/opt/chrome/policies/managed/external_protocol_dialog.json >/dev/null <<'EOF'
|
||||
{
|
||||
"ExternalProtocolDialogShowAlwaysOpenCheckbox": true
|
||||
}
|
||||
EOF
|
||||
sudo chmod 644 /etc/opt/chrome/policies/managed/external_protocol_dialog.json
|
||||
#+END_SRC
|
||||
|
||||
and then restart Chrome (for example, by navigating to <chrome://restart>) to
|
||||
make the new policy take effect.
|
||||
|
||||
See [[https://www.chromium.org/administrators/linux-quick-start][here]] for more info on the ~/etc/opt/chrome/policies/managed~ directory and
|
||||
[[https://cloud.google.com/docs/chrome-enterprise/policies/?policy=ExternalProtocolDialogShowAlwaysOpenCheckbox][here]] for information on the ~ExternalProtocolDialogShowAlwaysOpenCheckbox~ policy.
|
||||
|
||||
*** Mac OS
|
||||
For Mac OS, we need to create our own application.
|
||||
|
||||
1. Launch Script Editor
|
||||
2. Use the following script, paying attention to the path to ~emacsclient~:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
on open location this_URL
|
||||
set EC to "/usr/local/bin/emacsclient --no-wait "
|
||||
set filePath to quoted form of this_URL
|
||||
do shell script EC & filePath
|
||||
tell application "Emacs" to activate
|
||||
end open location
|
||||
#+end_src
|
||||
|
||||
3. Save the script in ~/Applications/OrgProtocolClient.app~, changing the script type to
|
||||
"Application", rather than "Script".
|
||||
4. Edit ~/Applications/OrgProtocolClient.app/Contents/Info.plist~, adding the
|
||||
following before the last ~</dict>~ tag:
|
||||
|
||||
#+begin_src text
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org-protocol handler</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>org-protocol</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
#+end_src
|
||||
|
||||
5. Save the file, and run the ~OrgProtocolClient.app~ to register the protocol.
|
||||
|
||||
To disable the "confirm" prompt in Chrome, you can also make Chrome
|
||||
show a checkbox to tick, so that the ~OrgProtocol~ app will be used
|
||||
without confirmation. To do this, run in a shell:
|
||||
|
||||
#+BEGIN_SRC bash
|
||||
defaults write com.google.Chrome ExternalProtocolDialogShowAlwaysOpenCheckbox -bool true
|
||||
#+END_SRC
|
||||
|
||||
If you're using [[https://github.com/railwaycat/homebrew-emacsmacport][Emacs Mac Port]], it registered its `Emacs.app` as the default
|
||||
handler for the URL scheme `org-protocol`. To make ~OrgProtocol.app~
|
||||
the default handler instead, run:
|
||||
|
||||
#+BEGIN_SRC bash
|
||||
defaults write com.apple.LaunchServices/com.apple.launchservices.secure LSHandlers -array-add \
|
||||
'{"LSHandlerPreferredVersions" = { "LSHandlerRoleAll" = "-"; }; LSHandlerRoleAll = "org.yourusername.OrgProtocol"; LSHandlerURLScheme = "org-protocol";}'
|
||||
#+END_SRC
|
||||
|
||||
Then restart your computer.
|
||||
|
||||
**** Testing org-protocol
|
||||
|
||||
To test that you have the handler setup and registered properly from the command
|
||||
line you can run:
|
||||
|
||||
#+begin_src bash
|
||||
open org-protocol://roam-ref\?template=r\&ref=test\&title=this
|
||||
#+end_src
|
||||
|
||||
If you get an error similar too this or the wrong handler is run:
|
||||
|
||||
#+begin_quote
|
||||
No application knows how to open URL org-protocol://roam-ref?template=r&ref=test&title=this (Error Domain=NSOSStatusErrorDomain Code=-10814 "kLSApplicationNotFoundErr: E.g. no application claims the file" UserInfo={_LSLine=1489, _LSFunction=runEvaluator}).
|
||||
|
||||
#+end_quote
|
||||
|
||||
You may need to manually register your handler, like this:
|
||||
|
||||
#+begin_src bash
|
||||
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -R -f /Applications/OrgProtocolClient.app
|
||||
#+end_src
|
||||
|
||||
Here is a link to the lsregister command that is really useful: https://eclecticlight.co/2019/03/25/lsregister-a-valuable-undocumented-command-for-launchservices/
|
||||
*** Windows
|
||||
For Windows, create a temporary ~org-protocol.reg~ file:
|
||||
|
||||
#+BEGIN_SRC text
|
||||
REGEDIT4
|
||||
|
||||
[HKEY_CLASSES_ROOT\org-protocol]
|
||||
@="URL:Org Protocol"
|
||||
"URL Protocol"=""
|
||||
[HKEY_CLASSES_ROOT\org-protocol\shell]
|
||||
[HKEY_CLASSES_ROOT\org-protocol\shell\open]
|
||||
[HKEY_CLASSES_ROOT\org-protocol\shell\open\command]
|
||||
@="\"C:\\Windows\\System32\\wsl.exe\" emacsclient \"%1\""
|
||||
#+END_SRC
|
||||
|
||||
The above will forward the protocol to WSL. If you run Emacs natively on
|
||||
Windows, replace the last line with:
|
||||
|
||||
#+BEGIN_SRC text
|
||||
@="\"c:\\path\\to\\emacs\\bin\\emacsclientw.exe\" \"%1\""
|
||||
#+END_SRC
|
||||
|
||||
After executing the .reg file, the protocol is registered and you can delete the
|
||||
file.
|
||||
|
||||
** The roam-node protocol
|
||||
|
||||
The roam-node protocol opens the node with ID specified by the ~node~ key (e.g.
|
||||
~org-protocol://roam-node?node=node-id~). ~org-roam-graph~ uses this to make the
|
||||
graph navigable.
|
||||
|
||||
** The roam-ref protocol
|
||||
|
||||
This protocol finds or creates a new note with a given ~ROAM_REFS~:
|
||||
|
||||
[[file:images/roam-ref.gif]]
|
||||
|
||||
To use this, create the following [[https://en.wikipedia.org/wiki/Bookmarklet][bookmarklet]] in your browser:
|
||||
|
||||
#+BEGIN_SRC javascript
|
||||
javascript:location.href =
|
||||
'org-protocol://roam-ref?template=r&ref='
|
||||
+ encodeURIComponent(location.href)
|
||||
+ '&title='
|
||||
+ encodeURIComponent(document.title)
|
||||
+ '&body='
|
||||
+ encodeURIComponent(window.getSelection())
|
||||
#+END_SRC
|
||||
|
||||
or as a keybinding in ~qutebrowser~ in , using the ~config.py~ file (see
|
||||
[[https://github.com/qutebrowser/qutebrowser/blob/master/doc/help/configuring.asciidoc][Configuring qutebrowser]]):
|
||||
|
||||
#+BEGIN_SRC python
|
||||
config.bind("<Ctrl-r>", "open javascript:location.href='org-protocol://roam-ref?template=r&ref='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)")
|
||||
#+END_SRC
|
||||
|
||||
where ~template~ is the template key for a template in
|
||||
~org-roam-capture-ref-templates~ (see [[*The Templating System][The Templating System]]).
|
||||
|
||||
* The Templating System
|
||||
|
||||
Org-roam extends the ~org-capture~ system, providing a smoother note-taking
|
||||
@ -1072,12 +974,217 @@ One can check the list of available keys for nodes by inspecting the
|
||||
|
||||
This makes ~${file}~, ~${file-hash}~ etc. all valid substitutions.
|
||||
|
||||
* Graphing
|
||||
* Extensions
|
||||
** org-roam-protocol
|
||||
|
||||
Org-roam provides extensions for capturing content from external applications
|
||||
such as the browser, via ~org-protocol~. Org-roam extends ~org-protocol~ with 2
|
||||
protocols: the ~roam-node~ and ~roam-ref~ protocols.
|
||||
|
||||
*** Installation
|
||||
|
||||
To enable Org-roam's protocol extensions, simply add the following to your init
|
||||
file:
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
(require 'org-roam-protocol)
|
||||
#+END_SRC
|
||||
|
||||
We also need to set up ~org-protocol~: the instructions for setting up
|
||||
~org-protocol~ are reproduced here.
|
||||
|
||||
On a high-level, external calls are passed to Emacs via ~emacsclient~.
|
||||
~org-protocol~ intercepts these and runs custom actions based on the protocols
|
||||
registered. Hence, to use ~org-protocol~, once must:
|
||||
|
||||
1. launch the ~emacsclient~ process
|
||||
2. Register ~org-protocol://~ as a valid scheme-handler
|
||||
|
||||
The instructions for the latter for each operating system is detailed below.
|
||||
|
||||
**** Linux
|
||||
For Linux users, create a desktop application in
|
||||
~~/.local/share/applications/org-protocol.desktop~:
|
||||
|
||||
#+begin_example
|
||||
[Desktop Entry]
|
||||
Name=Org-Protocol
|
||||
Exec=emacsclient %u
|
||||
Icon=emacs-icon
|
||||
Type=Application
|
||||
Terminal=false
|
||||
MimeType=x-scheme-handler/org-protocol
|
||||
#+end_example
|
||||
|
||||
Associate ~org-protocol://~ links with the desktop application by
|
||||
running in your shell:
|
||||
|
||||
#+BEGIN_SRC bash
|
||||
xdg-mime default org-protocol.desktop x-scheme-handler/org-protocol
|
||||
#+END_SRC
|
||||
|
||||
To disable the "confirm" prompt in Chrome, you can also make Chrome show a
|
||||
checkbox to tick, so that the ~Org-Protocol Client~ app will be used without
|
||||
confirmation. To do this, run in a shell:
|
||||
|
||||
#+BEGIN_SRC bash
|
||||
sudo mkdir -p /etc/opt/chrome/policies/managed/
|
||||
sudo tee /etc/opt/chrome/policies/managed/external_protocol_dialog.json >/dev/null <<'EOF'
|
||||
{
|
||||
"ExternalProtocolDialogShowAlwaysOpenCheckbox": true
|
||||
}
|
||||
EOF
|
||||
sudo chmod 644 /etc/opt/chrome/policies/managed/external_protocol_dialog.json
|
||||
#+END_SRC
|
||||
|
||||
and then restart Chrome (for example, by navigating to <chrome://restart>) to
|
||||
make the new policy take effect.
|
||||
|
||||
See [[https://www.chromium.org/administrators/linux-quick-start][here]] for more info on the ~/etc/opt/chrome/policies/managed~ directory and
|
||||
[[https://cloud.google.com/docs/chrome-enterprise/policies/?policy=ExternalProtocolDialogShowAlwaysOpenCheckbox][here]] for information on the ~ExternalProtocolDialogShowAlwaysOpenCheckbox~ policy.
|
||||
|
||||
**** Mac OS
|
||||
For Mac OS, we need to create our own application.
|
||||
|
||||
1. Launch Script Editor
|
||||
2. Use the following script, paying attention to the path to ~emacsclient~:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
on open location this_URL
|
||||
set EC to "/usr/local/bin/emacsclient --no-wait "
|
||||
set filePath to quoted form of this_URL
|
||||
do shell script EC & filePath
|
||||
tell application "Emacs" to activate
|
||||
end open location
|
||||
#+end_src
|
||||
|
||||
3. Save the script in ~/Applications/OrgProtocolClient.app~, changing the script type to
|
||||
"Application", rather than "Script".
|
||||
4. Edit ~/Applications/OrgProtocolClient.app/Contents/Info.plist~, adding the
|
||||
following before the last ~</dict>~ tag:
|
||||
|
||||
#+begin_src text
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org-protocol handler</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>org-protocol</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
#+end_src
|
||||
|
||||
5. Save the file, and run the ~OrgProtocolClient.app~ to register the protocol.
|
||||
|
||||
To disable the "confirm" prompt in Chrome, you can also make Chrome
|
||||
show a checkbox to tick, so that the ~OrgProtocol~ app will be used
|
||||
without confirmation. To do this, run in a shell:
|
||||
|
||||
#+BEGIN_SRC bash
|
||||
defaults write com.google.Chrome ExternalProtocolDialogShowAlwaysOpenCheckbox -bool true
|
||||
#+END_SRC
|
||||
|
||||
If you're using [[https://github.com/railwaycat/homebrew-emacsmacport][Emacs Mac Port]], it registered its `Emacs.app` as the default
|
||||
handler for the URL scheme `org-protocol`. To make ~OrgProtocol.app~
|
||||
the default handler instead, run:
|
||||
|
||||
#+BEGIN_SRC bash
|
||||
defaults write com.apple.LaunchServices/com.apple.launchservices.secure LSHandlers -array-add \
|
||||
'{"LSHandlerPreferredVersions" = { "LSHandlerRoleAll" = "-"; }; LSHandlerRoleAll = "org.yourusername.OrgProtocol"; LSHandlerURLScheme = "org-protocol";}'
|
||||
#+END_SRC
|
||||
|
||||
Then restart your computer.
|
||||
|
||||
***** Testing org-protocol
|
||||
|
||||
To test that you have the handler setup and registered properly from the command
|
||||
line you can run:
|
||||
|
||||
#+begin_src bash
|
||||
open org-protocol://roam-ref\?template=r\&ref=test\&title=this
|
||||
#+end_src
|
||||
|
||||
If you get an error similar too this or the wrong handler is run:
|
||||
|
||||
#+begin_quote
|
||||
No application knows how to open URL org-protocol://roam-ref?template=r&ref=test&title=this (Error Domain=NSOSStatusErrorDomain Code=-10814 "kLSApplicationNotFoundErr: E.g. no application claims the file" UserInfo={_LSLine=1489, _LSFunction=runEvaluator}).
|
||||
|
||||
#+end_quote
|
||||
|
||||
You may need to manually register your handler, like this:
|
||||
|
||||
#+begin_src bash
|
||||
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -R -f /Applications/OrgProtocolClient.app
|
||||
#+end_src
|
||||
|
||||
Here is a link to the lsregister command that is really useful: https://eclecticlight.co/2019/03/25/lsregister-a-valuable-undocumented-command-for-launchservices/
|
||||
**** Windows
|
||||
For Windows, create a temporary ~org-protocol.reg~ file:
|
||||
|
||||
#+BEGIN_SRC text
|
||||
REGEDIT4
|
||||
|
||||
[HKEY_CLASSES_ROOT\org-protocol]
|
||||
@="URL:Org Protocol"
|
||||
"URL Protocol"=""
|
||||
[HKEY_CLASSES_ROOT\org-protocol\shell]
|
||||
[HKEY_CLASSES_ROOT\org-protocol\shell\open]
|
||||
[HKEY_CLASSES_ROOT\org-protocol\shell\open\command]
|
||||
@="\"C:\\Windows\\System32\\wsl.exe\" emacsclient \"%1\""
|
||||
#+END_SRC
|
||||
|
||||
The above will forward the protocol to WSL. If you run Emacs natively on
|
||||
Windows, replace the last line with:
|
||||
|
||||
#+BEGIN_SRC text
|
||||
@="\"c:\\path\\to\\emacs\\bin\\emacsclientw.exe\" \"%1\""
|
||||
#+END_SRC
|
||||
|
||||
After executing the .reg file, the protocol is registered and you can delete the
|
||||
file.
|
||||
|
||||
*** The roam-node protocol
|
||||
|
||||
The roam-node protocol opens the node with ID specified by the ~node~ key (e.g.
|
||||
~org-protocol://roam-node?node=node-id~). ~org-roam-graph~ uses this to make the
|
||||
graph navigable.
|
||||
|
||||
*** The roam-ref protocol
|
||||
|
||||
This protocol finds or creates a new note with a given ~ROAM_REFS~:
|
||||
|
||||
[[file:images/roam-ref.gif]]
|
||||
|
||||
To use this, create the following [[https://en.wikipedia.org/wiki/Bookmarklet][bookmarklet]] in your browser:
|
||||
|
||||
#+BEGIN_SRC javascript
|
||||
javascript:location.href =
|
||||
'org-protocol://roam-ref?template=r&ref='
|
||||
+ encodeURIComponent(location.href)
|
||||
+ '&title='
|
||||
+ encodeURIComponent(document.title)
|
||||
+ '&body='
|
||||
+ encodeURIComponent(window.getSelection())
|
||||
#+END_SRC
|
||||
|
||||
or as a keybinding in ~qutebrowser~ in , using the ~config.py~ file (see
|
||||
[[https://github.com/qutebrowser/qutebrowser/blob/master/doc/help/configuring.asciidoc][Configuring qutebrowser]]):
|
||||
|
||||
#+BEGIN_SRC python
|
||||
config.bind("<Ctrl-r>", "open javascript:location.href='org-protocol://roam-ref?template=r&ref='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)")
|
||||
#+END_SRC
|
||||
|
||||
where ~template~ is the template key for a template in
|
||||
~org-roam-capture-ref-templates~ (see [[*The Templating System][The Templating System]]).
|
||||
|
||||
** org-roam-graph
|
||||
|
||||
Org-roam provides basic graphing capabilities to explore interconnections
|
||||
between notes, in ~org-roam-graph~. This is done by performing SQL queries and
|
||||
generating images using [[https://graphviz.org/][Graphviz]]. The graph can also be navigated: see [[*Org-roam Protocol][Roam
|
||||
Protocol]].
|
||||
generating images using [[https://graphviz.org/][Graphviz]]. The graph can also be navigated: see [[*org-roam-protocol][org-roam-protocol]].
|
||||
|
||||
The entry point to graph creation is ~org-roam-graph~.
|
||||
|
||||
@ -1118,7 +1225,7 @@ ARG may be any of the following values:
|
||||
(org-roam-graph--open (concat "file://///wsl$/Ubuntu" file)))))
|
||||
#+END_SRC
|
||||
|
||||
** Graph Options
|
||||
*** Graph Options
|
||||
|
||||
Graphviz provides many options for customizing the graph output, and Org-roam
|
||||
supports some of them. See https://graphviz.gitlab.io/_pages/doc/info/attrs.html
|
||||
@ -1144,12 +1251,12 @@ for customizable options.
|
||||
Extra options for edges in the graphviz output (The "E" attributes).
|
||||
Example: ~'(("dir" . "back"))~
|
||||
|
||||
* Org-roam Dailies
|
||||
** org-roam-dailies
|
||||
|
||||
Org-roam provides journaling capabilities akin to
|
||||
Org-journal with ~org-roam-dailies~.
|
||||
|
||||
** Configuration
|
||||
*** Configuration
|
||||
|
||||
For ~org-roam-dailies~ to work, you need to define two variables:
|
||||
|
||||
@ -1175,7 +1282,7 @@ Here is a sane default configuration:
|
||||
|
||||
See [[*The Templating System][The Templating System]] for creating new templates.
|
||||
|
||||
** Usage
|
||||
*** Usage
|
||||
|
||||
~org-roam-dailies~ provides these interactive functions:
|
||||
|
||||
@ -1229,6 +1336,18 @@ There are also commands which allow you to use Emacs’s ~calendar~ to find the
|
||||
- Function: ~org-roam-dailies-goto-next-note~
|
||||
|
||||
When in an daily-note, find the next one.
|
||||
** org-roam-export
|
||||
|
||||
Because Org-roam files are plain org files, they can be exported easily using
|
||||
~org-export~ to a variety of formats, including ~html~ and ~pdf~. However,
|
||||
Org-roam relies heavily on ID links, which Org's html export has poor support
|
||||
of. To fix this, Org-roam provides a bunch of overrides to better support
|
||||
export. To use them, simply run:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(require 'org-roam-export)
|
||||
#+end_src
|
||||
|
||||
* Performance Optimization
|
||||
** Garbage Collection
|
||||
|
||||
@ -1302,7 +1421,7 @@ The Deft interface can slow down quickly when the number of files get huge.
|
||||
|
||||
[[https://github.com/bastibe/org-journal][Org-journal]] provides journaling capabilities to Org-mode. A lot of its
|
||||
functionalities have been incorporated into Org-roam under the name
|
||||
[[*Org-roam Dailies][~org-roam-dailies~]]. It remains a good tool if you want to isolate your verbose
|
||||
[[*org-roam-dailies][~org-roam-dailies~]]. It remains a good tool if you want to isolate your verbose
|
||||
journal entries from the ideas you would write on a scratchpad.
|
||||
|
||||
#+BEGIN_SRC emacs-lisp
|
||||
@ -1355,6 +1474,9 @@ documents (PDF, EPUB etc.) within Org-mode.
|
||||
|
||||
** Bibliography
|
||||
|
||||
Org 9.5 added native citation and bibliography functionality, called "org-cite",
|
||||
which org-roam supports.
|
||||
|
||||
[[https://github.com/org-roam/org-roam-bibtex][org-roam-bibtex]] offers tight integration between [[https://github.com/jkitchin/org-ref][org-ref]], [[https://github.com/tmalsburg/helm-bibtex][helm-bibtex]] and
|
||||
~org-roam~. This helps you manage your bibliographic notes under ~org-roam~.
|
||||
|
||||
@ -1527,6 +1649,20 @@ to the publishing directory. Example code follows:
|
||||
(kill-buffer (file-name-nondirectory svg))
|
||||
(setq my-publish-time 0)))))
|
||||
#+end_src
|
||||
** I'm seeing this "Selecting deleted buffer" error. What do I do?
|
||||
|
||||
The "selecting deleted buffer" error usually occurs when you don't have a
|
||||
working ~emacsql-sqlite~ executable. Org-roam relies on this executable to
|
||||
function properly, and doesn't catch this error. This issue is most commonly
|
||||
seen on Windows setups. You can browse through the various GitHub issues posted
|
||||
about this [[https://github.com/org-roam/org-roam/issues?q=is%3Aissue+selecting+deleted][here]].
|
||||
|
||||
To fix this, you can try the following:
|
||||
|
||||
1. If on Windows, try replacing your system binary with [[https://github.com/nobiot/emacsql-sqlite.exe][this one]] that has been proven
|
||||
to work
|
||||
2. Use the ~emacsql-sqlite3~ option rather than compiling your own emacsql
|
||||
binary (see [[*How to cache][How to cache]]).
|
||||
|
||||
* Developer's Guide to Org-roam
|
||||
** Org-roam's Design Principle
|
||||
@ -1673,7 +1809,7 @@ When GOTO is non-nil, go the note without creating an entry."
|
||||
:END:
|
||||
|
||||
#+BEGIN_QUOTE
|
||||
Copyright (C) 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
Copyright (C) 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
You can redistribute this document and/or modify it under the terms
|
||||
of the GNU General Public License as published by the Free Software
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
@copying
|
||||
@quotation
|
||||
Copyright (C) 2020-2021 Jethro Kuan <jethrokuan95@@gmail.com>
|
||||
Copyright (C) 2020-2022 Jethro Kuan <jethrokuan95@@gmail.com>
|
||||
|
||||
You can redistribute this document and/or modify it under the terms
|
||||
of the GNU General Public License as published by the Free Software
|
||||
@ -31,7 +31,7 @@ General Public License for more details.
|
||||
@finalout
|
||||
@titlepage
|
||||
@title Org-roam User Manual
|
||||
@subtitle for version 2.1.0
|
||||
@subtitle for version 2.2.1
|
||||
@author Jethro Kuan
|
||||
@page
|
||||
@vskip 0pt plus 1filll
|
||||
@ -44,10 +44,10 @@ General Public License for more details.
|
||||
|
||||
@noindent
|
||||
|
||||
This manual is for Org-roam version 2.1.0.
|
||||
This manual is for Org-roam version 2.2.1.
|
||||
|
||||
@quotation
|
||||
Copyright (C) 2020-2021 Jethro Kuan <jethrokuan95@@gmail.com>
|
||||
Copyright (C) 2020-2022 Jethro Kuan <jethrokuan95@@gmail.com>
|
||||
|
||||
You can redistribute this document and/or modify it under the terms of the GNU
|
||||
General Public License as published by the Free Software Foundation, either
|
||||
@ -73,10 +73,8 @@ General Public License for more details.
|
||||
* Citations::
|
||||
* Completion::
|
||||
* Encryption::
|
||||
* Org-roam Protocol::
|
||||
* The Templating System::
|
||||
* Graphing::
|
||||
* Org-roam Dailies::
|
||||
* Extensions::
|
||||
* Performance Optimization::
|
||||
* The Org-mode Ecosystem::
|
||||
* FAQ::
|
||||
@ -100,12 +98,17 @@ Installation Troubleshooting
|
||||
|
||||
* C Compiler::
|
||||
|
||||
C Compiler
|
||||
|
||||
* C Compiler for Windows::
|
||||
|
||||
Getting Started
|
||||
|
||||
* The Org-roam Node::
|
||||
* Links between Nodes::
|
||||
* Setting up Org-roam::
|
||||
* Creating and Linking Nodes::
|
||||
* Customizing Node Completions::
|
||||
|
||||
Customizing Node Caching
|
||||
|
||||
@ -136,7 +139,19 @@ Completion
|
||||
* Completing within Link Brackets::
|
||||
* Completing anywhere::
|
||||
|
||||
Org-roam Protocol
|
||||
The Templating System
|
||||
|
||||
* Template Walkthrough::
|
||||
* Org-roam Template Expansion::
|
||||
|
||||
Extensions
|
||||
|
||||
* org-roam-protocol::
|
||||
* org-roam-graph::
|
||||
* org-roam-dailies::
|
||||
* org-roam-export::
|
||||
|
||||
org-roam-protocol
|
||||
|
||||
* Installation: Installation (1).
|
||||
* The roam-node protocol::
|
||||
@ -148,20 +163,11 @@ Installation
|
||||
* Mac OS::
|
||||
* Windows::
|
||||
|
||||
Mac OS
|
||||
|
||||
* Testing org-protocol::
|
||||
|
||||
The Templating System
|
||||
|
||||
* Template Walkthrough::
|
||||
* Org-roam Template Expansion::
|
||||
|
||||
Graphing
|
||||
org-roam-graph
|
||||
|
||||
* Graph Options::
|
||||
|
||||
Org-roam Dailies
|
||||
org-roam-dailies
|
||||
|
||||
* Configuration::
|
||||
* Usage::
|
||||
@ -190,6 +196,7 @@ FAQ
|
||||
* How do I migrate from Roam Research?::
|
||||
* How to migrate from Org-roam v1?::
|
||||
* How do I publish my notes with an Internet-friendly graph?::
|
||||
* I'm seeing this ``Selecting deleted buffer'' error. What do I do?: I'm seeing this ``Selecting deleted buffer'' error What do I do?.
|
||||
|
||||
How do I publish my notes with an Internet-friendly graph?
|
||||
|
||||
@ -336,7 +343,7 @@ A slip-box requires a method for quickly capturing ideas. These are called
|
||||
@strong{fleeting notes}: they are simple reminders of information or ideas that will
|
||||
need to be processed later on, or trashed. This is typically accomplished using
|
||||
@code{org-capture} (see @ref{Capture,,,org,}), or using Org-roam's daily notes
|
||||
functionality (see @ref{Org-roam Dailies}). This provides a central inbox for collecting
|
||||
functionality (see @ref{org-roam-dailies}). This provides a central inbox for collecting
|
||||
thoughts, to be processed later into permanent notes.
|
||||
|
||||
@strong{Permanent notes}
|
||||
@ -535,42 +542,39 @@ in your Emacs environment as a prerequisite for Org-roam when you install it.
|
||||
@code{emacsql-sqlite} requires a C compiler (e.g. @code{gcc} or @code{clang}) to be present in
|
||||
your computer. How to install a C compiler depends on the OS that you use.
|
||||
|
||||
@itemize
|
||||
@item
|
||||
For Windows:
|
||||
@end itemize
|
||||
@menu
|
||||
* C Compiler for Windows::
|
||||
@end menu
|
||||
|
||||
There are various ways to install one, depending on how you have installed
|
||||
Emacs. If you use Emacs within a Cygwin or MinGW environment, then you should
|
||||
install a compiler using their respective package manager.
|
||||
@node C Compiler for Windows
|
||||
@unnumberedsubsubsec C Compiler for Windows
|
||||
|
||||
If you have installed your Emacs from the @uref{https://www.gnu.org/software/emacs/, GNU Emacs website}, then the easiest way
|
||||
is to use @uref{https://www.msys2.org/, MSYS2} as at the time of this writing:
|
||||
One of the easiest ways to install a C compiler in Windows is to use @uref{https://www.msys2.org/, MSYS2} as at the time of this writing:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Use the installer in the official website and install MSYS2
|
||||
Download and use the installer in the official MSYS2 website
|
||||
|
||||
@item
|
||||
Run MSYS2
|
||||
|
||||
@item
|
||||
In the command-line tool, type the following and answer ``Y'' to proceed:
|
||||
Run MSYS2 and in its terminal, type the following and answer ``Y'' to
|
||||
proceed -- this will install @code{gcc} in your PC:
|
||||
|
||||
@example
|
||||
pacman -S gcc
|
||||
@end example
|
||||
|
||||
Note that you do not need to manually set the PATH for MSYS2; the
|
||||
@end itemize
|
||||
installer automatically takes care of it for you.
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Open Emacs and call @code{M-x org-roam-db-autosync-mode}
|
||||
On Windows, add @code{C:\msys64\usr\bin} (command @samp{where gcc} in MSYS2 terminal
|
||||
can tell you the correct path) to @code{PATH} in your environmental variables
|
||||
|
||||
|
||||
@item
|
||||
Launch Emacs and call @code{M-x org-roam-db-autosync-mode} (launch Emacs after
|
||||
defining the path, so that Emacs can recognize it)
|
||||
@end itemize
|
||||
|
||||
This will automatically start compiling @code{emacsql-sqlite}; you should see a
|
||||
@end itemize
|
||||
message in minibuffer. It may take a while until compilation completes. Once
|
||||
complete, you should see a new file @code{emacsql-sqlite.exe} created in a subfolder
|
||||
named @code{sqlite} under @code{emacsql-sqlite} installation folder. It's typically in
|
||||
@ -585,6 +589,7 @@ your Emacs configuration folder like this:
|
||||
* Links between Nodes::
|
||||
* Setting up Org-roam::
|
||||
* Creating and Linking Nodes::
|
||||
* Customizing Node Completions::
|
||||
@end menu
|
||||
|
||||
@node The Org-roam Node
|
||||
@ -651,7 +656,12 @@ For this tutorial, create an empty directory, and set @code{org-roam-directory}:
|
||||
@end lisp
|
||||
|
||||
The @code{file-truename} function is only necessary when you use symbolic links
|
||||
inside @code{org-roam-directory}: Org-roam does not resolve symbolic links.
|
||||
inside @code{org-roam-directory}: Org-roam does not resolve symbolic links. One can
|
||||
however instruct Emacs to always resolve symlinks, at a performance cost:
|
||||
|
||||
@lisp
|
||||
(setq find-file-visit-truename t)
|
||||
@end lisp
|
||||
|
||||
Next, we setup Org-roam to run functions on file changes to maintain cache
|
||||
consistency. This is achieved by running @code{M-x org-roam-db-autosync-mode}. To
|
||||
@ -703,6 +713,56 @@ brought through the node creation process.
|
||||
One can also conveniently insert links via the completion-at-point functions
|
||||
Org-roam provides (see @ref{Completion}).
|
||||
|
||||
@node Customizing Node Completions
|
||||
@section Customizing Node Completions
|
||||
|
||||
Node selection is achieved via the @code{completing-read} interface, typically
|
||||
through `org-roam-node-read`. The presentation of these nodes are governed by
|
||||
@code{org-roam-node-display-template}.
|
||||
|
||||
@defvar org-roam-node-display-template
|
||||
|
||||
Configures display formatting for Org-roam node.
|
||||
|
||||
Patterns of form ``$@{field-name:length@}'' are interpolated based
|
||||
on the current node.
|
||||
|
||||
Each ``field-name'' is replaced with the return value of each
|
||||
corresponding accessor function for org-roam-node, e.g.
|
||||
``$@{title@}'' will be interpolated by the result of
|
||||
org-roam-node-title. You can also define custom accessors using
|
||||
cl-defmethod. For example, you can define:
|
||||
|
||||
(cl-defmethod org-roam-node-my-title ((node org-roam-node))
|
||||
(concat ``My '' (org-roam-node-title node)))
|
||||
|
||||
and then reference it here or in the capture templates as
|
||||
``$@{my-title@}''.
|
||||
|
||||
``length'' is an optional specifier and declares how many
|
||||
characters can be used to display the value of the corresponding
|
||||
field. If it's not specified, the field will be inserted as is,
|
||||
i.e. it won't be aligned nor trimmed. If it's an integer, the
|
||||
field will be aligned accordingly and all the exceeding
|
||||
characters will be trimmed out. If it's ``*'', the field will use
|
||||
as many characters as possible and will be aligned accordingly.
|
||||
|
||||
A closure can also be assigned to this variable in which case the
|
||||
closure is evaluated and the return value is used as the
|
||||
template. The closure must evaluate to a valid template string.
|
||||
@end defvar
|
||||
|
||||
If you're using a vertical completion framework, such as Ivy and Selectrum,
|
||||
Org-roam supports the generation of an aligned, tabular completion interface.
|
||||
For example, to include a column for tags up to 10 character widths wide, one
|
||||
can set @code{org-roam-node-display-template} as such:
|
||||
|
||||
@lisp
|
||||
(setq org-roam-node-display-template
|
||||
(concat "$@{title:*@} "
|
||||
(propertize "$@{tags:10@}" 'face 'org-tag)))
|
||||
@end lisp
|
||||
|
||||
@node Customizing Node Caching
|
||||
@chapter Customizing Node Caching
|
||||
|
||||
@ -785,6 +845,37 @@ all headlines with the @code{ATTACH} tag from the Org-roam database, one can set
|
||||
(not (member "ATTACH" (org-get-tags)))))
|
||||
@end example
|
||||
|
||||
Org-roam relied on the obtained Org AST for the buffer to parse links. However,
|
||||
links appearing in some places (e.g. within property drawers) are not considered
|
||||
by the Org AST to be links. Therefore, Org-roam takes special care of
|
||||
additionally trying to process these links. Use
|
||||
@code{org-roam-db-extra-links-elements} to specify which additional Org AST element
|
||||
types to consider.
|
||||
|
||||
@defvar org-roam-db-extra-links-elements
|
||||
|
||||
The list of Org element types to include for parsing by Org-roam.
|
||||
|
||||
By default, when parsing Org's AST, links within keywords and
|
||||
property drawers are not parsed as links. Sometimes however, it
|
||||
is desirable to parse and cache these links (e.g. hiding links in
|
||||
a property drawer).
|
||||
@end defvar
|
||||
|
||||
Additionally, one may want to ignore certain keys from being excluded within
|
||||
property drawers. For example, we would not want @code{ROAM_REFS} links to be
|
||||
self-referential. Hence, to exclude specific keys, we use
|
||||
@code{org-roam-db-extra-links-exclude-keys}.
|
||||
|
||||
@defvar org-roam-db-extra-links-exclude-keys
|
||||
|
||||
Keys to ignore when mapping over links.
|
||||
|
||||
The car of the association list is the Org element type (e.g. keyword). The
|
||||
cdr is a list of case-insensitive strings to exclude from being treated as
|
||||
links.
|
||||
@end defvar
|
||||
|
||||
@node When to cache
|
||||
@section When to cache
|
||||
|
||||
@ -886,10 +977,10 @@ There are currently 3 provided widget types:
|
||||
title/alias but are not linked
|
||||
@end itemize
|
||||
|
||||
To configure what sections are displayed in the buffer, set @code{org-roam-mode-section-functions}.
|
||||
To configure what sections are displayed in the buffer, set ~org-roam-mode-sections.
|
||||
|
||||
@lisp
|
||||
(setq org-roam-mode-section-functions
|
||||
(setq org-roam-mode-sections
|
||||
(list #'org-roam-backlinks-section
|
||||
#'org-roam-reflinks-section
|
||||
;; #'org-roam-unlinked-references-section
|
||||
@ -898,6 +989,16 @@ To configure what sections are displayed in the buffer, set @code{org-roam-mode-
|
||||
|
||||
Note that computing unlinked references may be slow, and has not been added in by default.
|
||||
|
||||
For each section function, you can pass args along to modify its behaviour. For
|
||||
example, if you want to render unique sources for backlinks (and also keep
|
||||
rendering reference links), set @code{org-roam-mode-sections} as follows:
|
||||
|
||||
@lisp
|
||||
(setq org-roam-mode-sections
|
||||
'((org-roam-backlinks-section :unique t)
|
||||
org-roam-reflinks-section))
|
||||
@end lisp
|
||||
|
||||
@node Configuring the Org-roam buffer display
|
||||
@section Configuring the Org-roam buffer display
|
||||
|
||||
@ -1041,7 +1142,7 @@ With the above example, if another node links to @uref{https://www.google.com/},
|
||||
will show up as a “reference backlink”.
|
||||
|
||||
These keys also come in useful for when taking website notes, using the
|
||||
@code{roam-ref} protocol (see @ref{Org-roam Protocol, , Roam Protocol}).
|
||||
@code{roam-ref} protocol (see @ref{org-roam-protocol}).
|
||||
|
||||
You may assign multiple refs to a single node, for example when you want
|
||||
multiple papers in a series to share the same note, or an article has a citation
|
||||
@ -1065,7 +1166,7 @@ Remove a ref from the node at point.
|
||||
|
||||
Since version 9.5, Org has first-class support for citations. Org-roam supports
|
||||
the caching of both these in-built citations (of form @code{[cite:@@key]}) and @uref{https://github.com/jkitchin/org-ref, org-ref}
|
||||
citations (of form @uref{key}).
|
||||
citations (of form cite:key).
|
||||
|
||||
Org-roam attempts to load both the @code{org-ref} and @code{org-cite} package when
|
||||
indexing files, so no further setup from the user is required for citation
|
||||
@ -1090,6 +1191,16 @@ citation key:
|
||||
:END:
|
||||
@end example
|
||||
|
||||
or
|
||||
|
||||
@example
|
||||
* Probabilistic Robotics
|
||||
:PROPERTIES:
|
||||
:ID: 51b7b82c-bbb4-4822-875a-ed548cffda10
|
||||
:ROAM_REFS: [cite:@@thrun2005probabilistic]
|
||||
:END:
|
||||
@end example
|
||||
|
||||
for @code{org-cite}, or:
|
||||
|
||||
@example
|
||||
@ -1185,243 +1296,6 @@ Note that the Org-roam database stores metadata information in plain-text
|
||||
(headline text, for example), so if this information is private to you then you
|
||||
should also ensure the database is encrypted.
|
||||
|
||||
@node Org-roam Protocol
|
||||
@chapter Org-roam Protocol
|
||||
|
||||
Org-roam provides extensions for capturing content from external applications
|
||||
such as the browser, via @code{org-protocol}. Org-roam extends @code{org-protocol} with 2
|
||||
protocols: the @code{roam-node} and @code{roam-ref} protocols.
|
||||
|
||||
@menu
|
||||
* Installation: Installation (1).
|
||||
* The roam-node protocol::
|
||||
* The roam-ref protocol::
|
||||
@end menu
|
||||
|
||||
@node Installation (1)
|
||||
@section Installation
|
||||
|
||||
To enable Org-roam's protocol extensions, simply add the following to your init
|
||||
file:
|
||||
|
||||
@lisp
|
||||
(require 'org-roam-protocol)
|
||||
@end lisp
|
||||
|
||||
We also need to set up @code{org-protocol}: the instructions for setting up
|
||||
@code{org-protocol} are reproduced below.
|
||||
|
||||
@menu
|
||||
* Linux::
|
||||
* Mac OS::
|
||||
* Windows::
|
||||
@end menu
|
||||
|
||||
@node Linux
|
||||
@subsection Linux
|
||||
|
||||
For Linux users, create a desktop application in
|
||||
@code{~/.local/share/applications/org-protocol.desktop}:
|
||||
|
||||
@example
|
||||
[Desktop Entry]
|
||||
Name=Org-Protocol
|
||||
Exec=emacsclient %u
|
||||
Icon=emacs-icon
|
||||
Type=Application
|
||||
Terminal=false
|
||||
MimeType=x-scheme-handler/org-protocol
|
||||
@end example
|
||||
|
||||
Associate @code{org-protocol://} links with the desktop application by
|
||||
running in your shell:
|
||||
|
||||
@example
|
||||
xdg-mime default org-protocol.desktop x-scheme-handler/org-protocol
|
||||
@end example
|
||||
|
||||
To disable the ``confirm'' prompt in Chrome, you can also make Chrome show a
|
||||
checkbox to tick, so that the @code{Org-Protocol Client} app will be used without
|
||||
confirmation. To do this, run in a shell:
|
||||
|
||||
@example
|
||||
sudo mkdir -p /etc/opt/chrome/policies/managed/
|
||||
sudo tee /etc/opt/chrome/policies/managed/external_protocol_dialog.json >/dev/null <<'EOF'
|
||||
@{
|
||||
"ExternalProtocolDialogShowAlwaysOpenCheckbox": true
|
||||
@}
|
||||
EOF
|
||||
sudo chmod 644 /etc/opt/chrome/policies/managed/external_protocol_dialog.json
|
||||
@end example
|
||||
|
||||
and then restart Chrome (for example, by navigating to <chrome://restart>) to
|
||||
make the new policy take effect.
|
||||
|
||||
See @uref{https://www.chromium.org/administrators/linux-quick-start, here} for more info on the @code{/etc/opt/chrome/policies/managed} directory and
|
||||
@uref{https://cloud.google.com/docs/chrome-enterprise/policies/?policy=ExternalProtocolDialogShowAlwaysOpenCheckbox, here} for information on the @code{ExternalProtocolDialogShowAlwaysOpenCheckbox} policy.
|
||||
|
||||
@node Mac OS
|
||||
@subsection Mac OS
|
||||
|
||||
For Mac OS, we need to create our own application.
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Launch Script Editor
|
||||
|
||||
@item
|
||||
Use the following script, paying attention to the path to @code{emacsclient}:
|
||||
@end itemize
|
||||
|
||||
@lisp
|
||||
on open location this_URL
|
||||
set EC to "/usr/local/bin/emacsclient --no-wait "
|
||||
set filePath to quoted form of this_URL
|
||||
do shell script EC & filePath
|
||||
tell application "Emacs" to activate
|
||||
end open location
|
||||
@end lisp
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Save the script in @code{/Applications/OrgProtocolClient.app}, changing the script type to
|
||||
``Application'', rather than ``Script''.
|
||||
|
||||
@item
|
||||
Edit @code{/Applications/OrgProtocolClient.app/Contents/Info.plist}, adding the
|
||||
following before the last @code{</dict>} tag:
|
||||
@end itemize
|
||||
|
||||
@example
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org-protocol handler</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>org-protocol</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
@end example
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Save the file, and run the @code{OrgProtocolClient.app} to register the protocol.
|
||||
@end itemize
|
||||
|
||||
To disable the ``confirm'' prompt in Chrome, you can also make Chrome
|
||||
show a checkbox to tick, so that the @code{OrgProtocol} app will be used
|
||||
without confirmation. To do this, run in a shell:
|
||||
|
||||
@example
|
||||
defaults write com.google.Chrome ExternalProtocolDialogShowAlwaysOpenCheckbox -bool true
|
||||
@end example
|
||||
|
||||
If you're using @uref{https://github.com/railwaycat/homebrew-emacsmacport, Emacs Mac Port}, it registered its `Emacs.app` as the default
|
||||
handler for the URL scheme `org-protocol`. To make @code{OrgProtocol.app}
|
||||
the default handler instead, run:
|
||||
|
||||
@example
|
||||
defaults write com.apple.LaunchServices/com.apple.launchservices.secure LSHandlers -array-add \
|
||||
'@{"LSHandlerPreferredVersions" = @{ "LSHandlerRoleAll" = "-"; @}; LSHandlerRoleAll = "org.yourusername.OrgProtocol"; LSHandlerURLScheme = "org-protocol";@}'
|
||||
@end example
|
||||
|
||||
Then restart your computer.
|
||||
|
||||
@menu
|
||||
* Testing org-protocol::
|
||||
@end menu
|
||||
|
||||
@node Testing org-protocol
|
||||
@unnumberedsubsubsec Testing org-protocol
|
||||
|
||||
To test that you have the handler setup and registered properly from the command
|
||||
line you can run:
|
||||
|
||||
@example
|
||||
open org-protocol://roam-ref\?template=r\&ref=test\&title=this
|
||||
@end example
|
||||
|
||||
If you get an error similar too this or the wrong handler is run:
|
||||
|
||||
@quotation
|
||||
No application knows how to open URL org-protocol://roam-ref?template=r&ref=test&title=this (Error Domain=NSOSStatusErrorDomain Code=-10814 ``kLSApplicationNotFoundErr: E.g. no application claims the file'' UserInfo=@{@math{_LSLine}=1489, _LSFunction=runEvaluator@}).
|
||||
|
||||
@end quotation
|
||||
|
||||
You may need to manually register your handler, like this:
|
||||
|
||||
@example
|
||||
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -R -f /Applications/OrgProtocolClient.app
|
||||
@end example
|
||||
|
||||
Here is a link to the lsregister command that is really useful: @uref{https://eclecticlight.co/2019/03/25/lsregister-a-valuable-undocumented-command-for-launchservices/}
|
||||
|
||||
@node Windows
|
||||
@subsection Windows
|
||||
|
||||
For Windows, create a temporary @code{org-protocol.reg} file:
|
||||
|
||||
@example
|
||||
REGEDIT4
|
||||
|
||||
[HKEY_CLASSES_ROOT\org-protocol]
|
||||
@@="URL:Org Protocol"
|
||||
"URL Protocol"=""
|
||||
[HKEY_CLASSES_ROOT\org-protocol\shell]
|
||||
[HKEY_CLASSES_ROOT\org-protocol\shell\open]
|
||||
[HKEY_CLASSES_ROOT\org-protocol\shell\open\command]
|
||||
@@="\"C:\\Windows\\System32\\wsl.exe\" emacsclient \"%1\""
|
||||
@end example
|
||||
|
||||
The above will forward the protocol to WSL@. If you run Emacs natively on
|
||||
Windows, replace the last line with:
|
||||
|
||||
@example
|
||||
@@="\"c:\\path\\to\\emacs\\bin\\emacsclientw.exe\" \"%1\""
|
||||
@end example
|
||||
|
||||
After executing the .reg file, the protocol is registered and you can delete the
|
||||
file.
|
||||
|
||||
@node The roam-node protocol
|
||||
@section The roam-node protocol
|
||||
|
||||
The roam-node protocol opens the node with ID specified by the @code{node} key (e.g.
|
||||
@code{org-protocol://roam-node?node=node-id}). @code{org-roam-graph} uses this to make the
|
||||
graph navigable.
|
||||
|
||||
@node The roam-ref protocol
|
||||
@section The roam-ref protocol
|
||||
|
||||
This protocol finds or creates a new note with a given @code{ROAM_REFS}:
|
||||
|
||||
@image{images/roam-ref,,,,gif}
|
||||
|
||||
To use this, create the following @uref{https://en.wikipedia.org/wiki/Bookmarklet, bookmarklet} in your browser:
|
||||
|
||||
@example
|
||||
javascript:location.href =
|
||||
'org-protocol://roam-ref?template=r&ref='
|
||||
+ encodeURIComponent(location.href)
|
||||
+ '&title='
|
||||
+ encodeURIComponent(document.title)
|
||||
+ '&body='
|
||||
+ encodeURIComponent(window.getSelection())
|
||||
@end example
|
||||
|
||||
or as a keybinding in @code{qutebrowser} in , using the @code{config.py} file (see
|
||||
@uref{https://github.com/qutebrowser/qutebrowser/blob/master/doc/help/configuring.asciidoc, Configuring qutebrowser}):
|
||||
|
||||
@example
|
||||
config.bind("<Ctrl-r>", "open javascript:location.href='org-protocol://roam-ref?template=r&ref='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)")
|
||||
@end example
|
||||
|
||||
where @code{template} is the template key for a template in
|
||||
@code{org-roam-capture-ref-templates} (see @ref{The Templating System}).
|
||||
|
||||
@node The Templating System
|
||||
@chapter The Templating System
|
||||
|
||||
@ -1538,13 +1412,272 @@ One can check the list of available keys for nodes by inspecting the
|
||||
|
||||
This makes @code{$@{file@}}, @code{$@{file-hash@}} etc. all valid substitutions.
|
||||
|
||||
@node Graphing
|
||||
@chapter Graphing
|
||||
@node Extensions
|
||||
@chapter Extensions
|
||||
|
||||
@menu
|
||||
* org-roam-protocol::
|
||||
* org-roam-graph::
|
||||
* org-roam-dailies::
|
||||
* org-roam-export::
|
||||
@end menu
|
||||
|
||||
@node org-roam-protocol
|
||||
@section org-roam-protocol
|
||||
|
||||
Org-roam provides extensions for capturing content from external applications
|
||||
such as the browser, via @code{org-protocol}. Org-roam extends @code{org-protocol} with 2
|
||||
protocols: the @code{roam-node} and @code{roam-ref} protocols.
|
||||
|
||||
@menu
|
||||
* Installation: Installation (1).
|
||||
* The roam-node protocol::
|
||||
* The roam-ref protocol::
|
||||
@end menu
|
||||
|
||||
@node Installation (1)
|
||||
@subsection Installation
|
||||
|
||||
To enable Org-roam's protocol extensions, simply add the following to your init
|
||||
file:
|
||||
|
||||
@lisp
|
||||
(require 'org-roam-protocol)
|
||||
@end lisp
|
||||
|
||||
We also need to set up @code{org-protocol}: the instructions for setting up
|
||||
@code{org-protocol} are reproduced here.
|
||||
|
||||
On a high-level, external calls are passed to Emacs via @code{emacsclient}.
|
||||
@code{org-protocol} intercepts these and runs custom actions based on the protocols
|
||||
registered. Hence, to use @code{org-protocol}, once must:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
launch the @code{emacsclient} process
|
||||
|
||||
@item
|
||||
Register @code{org-protocol://} as a valid scheme-handler
|
||||
@end itemize
|
||||
|
||||
The instructions for the latter for each operating system is detailed below.
|
||||
|
||||
@menu
|
||||
* Linux::
|
||||
* Mac OS::
|
||||
* Windows::
|
||||
@end menu
|
||||
|
||||
@node Linux
|
||||
@unnumberedsubsubsec Linux
|
||||
|
||||
For Linux users, create a desktop application in
|
||||
@code{~/.local/share/applications/org-protocol.desktop}:
|
||||
|
||||
@example
|
||||
[Desktop Entry]
|
||||
Name=Org-Protocol
|
||||
Exec=emacsclient %u
|
||||
Icon=emacs-icon
|
||||
Type=Application
|
||||
Terminal=false
|
||||
MimeType=x-scheme-handler/org-protocol
|
||||
@end example
|
||||
|
||||
Associate @code{org-protocol://} links with the desktop application by
|
||||
running in your shell:
|
||||
|
||||
@example
|
||||
xdg-mime default org-protocol.desktop x-scheme-handler/org-protocol
|
||||
@end example
|
||||
|
||||
To disable the ``confirm'' prompt in Chrome, you can also make Chrome show a
|
||||
checkbox to tick, so that the @code{Org-Protocol Client} app will be used without
|
||||
confirmation. To do this, run in a shell:
|
||||
|
||||
@example
|
||||
sudo mkdir -p /etc/opt/chrome/policies/managed/
|
||||
sudo tee /etc/opt/chrome/policies/managed/external_protocol_dialog.json >/dev/null <<'EOF'
|
||||
@{
|
||||
"ExternalProtocolDialogShowAlwaysOpenCheckbox": true
|
||||
@}
|
||||
EOF
|
||||
sudo chmod 644 /etc/opt/chrome/policies/managed/external_protocol_dialog.json
|
||||
@end example
|
||||
|
||||
and then restart Chrome (for example, by navigating to <chrome://restart>) to
|
||||
make the new policy take effect.
|
||||
|
||||
See @uref{https://www.chromium.org/administrators/linux-quick-start, here} for more info on the @code{/etc/opt/chrome/policies/managed} directory and
|
||||
@uref{https://cloud.google.com/docs/chrome-enterprise/policies/?policy=ExternalProtocolDialogShowAlwaysOpenCheckbox, here} for information on the @code{ExternalProtocolDialogShowAlwaysOpenCheckbox} policy.
|
||||
|
||||
@node Mac OS
|
||||
@unnumberedsubsubsec Mac OS
|
||||
|
||||
For Mac OS, we need to create our own application.
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Launch Script Editor
|
||||
|
||||
@item
|
||||
Use the following script, paying attention to the path to @code{emacsclient}:
|
||||
@end itemize
|
||||
|
||||
@lisp
|
||||
on open location this_URL
|
||||
set EC to "/usr/local/bin/emacsclient --no-wait "
|
||||
set filePath to quoted form of this_URL
|
||||
do shell script EC & filePath
|
||||
tell application "Emacs" to activate
|
||||
end open location
|
||||
@end lisp
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Save the script in @code{/Applications/OrgProtocolClient.app}, changing the script type to
|
||||
``Application'', rather than ``Script''.
|
||||
|
||||
@item
|
||||
Edit @code{/Applications/OrgProtocolClient.app/Contents/Info.plist}, adding the
|
||||
following before the last @code{</dict>} tag:
|
||||
@end itemize
|
||||
|
||||
@example
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org-protocol handler</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>org-protocol</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
@end example
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Save the file, and run the @code{OrgProtocolClient.app} to register the protocol.
|
||||
@end itemize
|
||||
|
||||
To disable the ``confirm'' prompt in Chrome, you can also make Chrome
|
||||
show a checkbox to tick, so that the @code{OrgProtocol} app will be used
|
||||
without confirmation. To do this, run in a shell:
|
||||
|
||||
@example
|
||||
defaults write com.google.Chrome ExternalProtocolDialogShowAlwaysOpenCheckbox -bool true
|
||||
@end example
|
||||
|
||||
If you're using @uref{https://github.com/railwaycat/homebrew-emacsmacport, Emacs Mac Port}, it registered its `Emacs.app` as the default
|
||||
handler for the URL scheme `org-protocol`. To make @code{OrgProtocol.app}
|
||||
the default handler instead, run:
|
||||
|
||||
@example
|
||||
defaults write com.apple.LaunchServices/com.apple.launchservices.secure LSHandlers -array-add \
|
||||
'@{"LSHandlerPreferredVersions" = @{ "LSHandlerRoleAll" = "-"; @}; LSHandlerRoleAll = "org.yourusername.OrgProtocol"; LSHandlerURLScheme = "org-protocol";@}'
|
||||
@end example
|
||||
|
||||
Then restart your computer.
|
||||
|
||||
@itemize
|
||||
@item
|
||||
@anchor{Testing org-protocol}Testing org-protocol
|
||||
|
||||
|
||||
To test that you have the handler setup and registered properly from the command
|
||||
line you can run:
|
||||
|
||||
@example
|
||||
open org-protocol://roam-ref\?template=r\&ref=test\&title=this
|
||||
@end example
|
||||
|
||||
If you get an error similar too this or the wrong handler is run:
|
||||
|
||||
@quotation
|
||||
No application knows how to open URL org-protocol://roam-ref?template=r&ref=test&title=this (Error Domain=NSOSStatusErrorDomain Code=-10814 ``kLSApplicationNotFoundErr: E.g. no application claims the file'' UserInfo=@{@math{_LSLine}=1489, _LSFunction=runEvaluator@}).
|
||||
|
||||
@end quotation
|
||||
|
||||
You may need to manually register your handler, like this:
|
||||
|
||||
@example
|
||||
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -R -f /Applications/OrgProtocolClient.app
|
||||
@end example
|
||||
|
||||
Here is a link to the lsregister command that is really useful: @uref{https://eclecticlight.co/2019/03/25/lsregister-a-valuable-undocumented-command-for-launchservices/}
|
||||
@end itemize
|
||||
|
||||
@node Windows
|
||||
@unnumberedsubsubsec Windows
|
||||
|
||||
For Windows, create a temporary @code{org-protocol.reg} file:
|
||||
|
||||
@example
|
||||
REGEDIT4
|
||||
|
||||
[HKEY_CLASSES_ROOT\org-protocol]
|
||||
@@="URL:Org Protocol"
|
||||
"URL Protocol"=""
|
||||
[HKEY_CLASSES_ROOT\org-protocol\shell]
|
||||
[HKEY_CLASSES_ROOT\org-protocol\shell\open]
|
||||
[HKEY_CLASSES_ROOT\org-protocol\shell\open\command]
|
||||
@@="\"C:\\Windows\\System32\\wsl.exe\" emacsclient \"%1\""
|
||||
@end example
|
||||
|
||||
The above will forward the protocol to WSL@. If you run Emacs natively on
|
||||
Windows, replace the last line with:
|
||||
|
||||
@example
|
||||
@@="\"c:\\path\\to\\emacs\\bin\\emacsclientw.exe\" \"%1\""
|
||||
@end example
|
||||
|
||||
After executing the .reg file, the protocol is registered and you can delete the
|
||||
file.
|
||||
|
||||
@node The roam-node protocol
|
||||
@subsection The roam-node protocol
|
||||
|
||||
The roam-node protocol opens the node with ID specified by the @code{node} key (e.g.
|
||||
@code{org-protocol://roam-node?node=node-id}). @code{org-roam-graph} uses this to make the
|
||||
graph navigable.
|
||||
|
||||
@node The roam-ref protocol
|
||||
@subsection The roam-ref protocol
|
||||
|
||||
This protocol finds or creates a new note with a given @code{ROAM_REFS}:
|
||||
|
||||
@image{images/roam-ref,,,,gif}
|
||||
|
||||
To use this, create the following @uref{https://en.wikipedia.org/wiki/Bookmarklet, bookmarklet} in your browser:
|
||||
|
||||
@example
|
||||
javascript:location.href =
|
||||
'org-protocol://roam-ref?template=r&ref='
|
||||
+ encodeURIComponent(location.href)
|
||||
+ '&title='
|
||||
+ encodeURIComponent(document.title)
|
||||
+ '&body='
|
||||
+ encodeURIComponent(window.getSelection())
|
||||
@end example
|
||||
|
||||
or as a keybinding in @code{qutebrowser} in , using the @code{config.py} file (see
|
||||
@uref{https://github.com/qutebrowser/qutebrowser/blob/master/doc/help/configuring.asciidoc, Configuring qutebrowser}):
|
||||
|
||||
@example
|
||||
config.bind("<Ctrl-r>", "open javascript:location.href='org-protocol://roam-ref?template=r&ref='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)")
|
||||
@end example
|
||||
|
||||
where @code{template} is the template key for a template in
|
||||
@code{org-roam-capture-ref-templates} (see @ref{The Templating System}).
|
||||
|
||||
@node org-roam-graph
|
||||
@section org-roam-graph
|
||||
|
||||
Org-roam provides basic graphing capabilities to explore interconnections
|
||||
between notes, in @code{org-roam-graph}. This is done by performing SQL queries and
|
||||
generating images using @uref{https://graphviz.org/, Graphviz}. The graph can also be navigated: see @ref{Org-roam Protocol, , Roam
|
||||
Protocol}.
|
||||
generating images using @uref{https://graphviz.org/, Graphviz}. The graph can also be navigated: see @ref{org-roam-protocol}.
|
||||
|
||||
The entry point to graph creation is @code{org-roam-graph}.
|
||||
|
||||
@ -1602,7 +1735,7 @@ the second option to set the browser and network file path:
|
||||
@end menu
|
||||
|
||||
@node Graph Options
|
||||
@section Graph Options
|
||||
@subsection Graph Options
|
||||
|
||||
Graphviz provides many options for customizing the graph output, and Org-roam
|
||||
supports some of them. See @uref{https://graphviz.gitlab.io/_pages/doc/info/attrs.html}
|
||||
@ -1632,8 +1765,8 @@ Extra options for edges in the graphviz output (The ``E'' attributes).
|
||||
Example: @code{'(("dir" . "back"))}
|
||||
@end defopt
|
||||
|
||||
@node Org-roam Dailies
|
||||
@chapter Org-roam Dailies
|
||||
@node org-roam-dailies
|
||||
@section org-roam-dailies
|
||||
|
||||
Org-roam provides journaling capabilities akin to
|
||||
Org-journal with @code{org-roam-dailies}.
|
||||
@ -1644,7 +1777,7 @@ Org-journal with @code{org-roam-dailies}.
|
||||
@end menu
|
||||
|
||||
@node Configuration
|
||||
@section Configuration
|
||||
@subsection Configuration
|
||||
|
||||
For @code{org-roam-dailies} to work, you need to define two variables:
|
||||
|
||||
@ -1673,7 +1806,7 @@ Here is a sane default configuration:
|
||||
See @ref{The Templating System} for creating new templates.
|
||||
|
||||
@node Usage
|
||||
@section Usage
|
||||
@subsection Usage
|
||||
|
||||
@code{org-roam-dailies} provides these interactive functions:
|
||||
|
||||
@ -1737,6 +1870,19 @@ When in an daily-note, find the previous one.
|
||||
When in an daily-note, find the next one.
|
||||
@end defun
|
||||
|
||||
@node org-roam-export
|
||||
@section org-roam-export
|
||||
|
||||
Because Org-roam files are plain org files, they can be exported easily using
|
||||
@code{org-export} to a variety of formats, including @code{html} and @code{pdf}. However,
|
||||
Org-roam relies heavily on ID links, which Org's html export has poor support
|
||||
of. To fix this, Org-roam provides a bunch of overrides to better support
|
||||
export. To use them, simply run:
|
||||
|
||||
@lisp
|
||||
(require 'org-roam-export)
|
||||
@end lisp
|
||||
|
||||
@node Performance Optimization
|
||||
@chapter Performance Optimization
|
||||
|
||||
@ -1834,7 +1980,7 @@ The Deft interface can slow down quickly when the number of files get huge.
|
||||
|
||||
@uref{https://github.com/bastibe/org-journal, Org-journal} provides journaling capabilities to Org-mode. A lot of its
|
||||
functionalities have been incorporated into Org-roam under the name
|
||||
@ref{Org-roam Dailies, , @code{org-roam-dailies}}. It remains a good tool if you want to isolate your verbose
|
||||
@ref{org-roam-dailies, , @code{org-roam-dailies}}. It remains a good tool if you want to isolate your verbose
|
||||
journal entries from the ideas you would write on a scratchpad.
|
||||
|
||||
@lisp
|
||||
@ -1895,6 +2041,9 @@ documents (PDF, EPUB etc.) within Org-mode.
|
||||
@node Bibliography
|
||||
@section Bibliography
|
||||
|
||||
Org 9.5 added native citation and bibliography functionality, called ``org-cite'',
|
||||
which org-roam supports.
|
||||
|
||||
@uref{https://github.com/org-roam/org-roam-bibtex, org-roam-bibtex} offers tight integration between @uref{https://github.com/jkitchin/org-ref, org-ref}, @uref{https://github.com/tmalsburg/helm-bibtex, helm-bibtex} and
|
||||
@code{org-roam}. This helps you manage your bibliographic notes under @code{org-roam}.
|
||||
|
||||
@ -1921,6 +2070,7 @@ Org-mode, and sync your cards to Anki via @uref{https://github.com/FooSoft/anki-
|
||||
* How do I migrate from Roam Research?::
|
||||
* How to migrate from Org-roam v1?::
|
||||
* How do I publish my notes with an Internet-friendly graph?::
|
||||
* I'm seeing this ``Selecting deleted buffer'' error. What do I do?: I'm seeing this ``Selecting deleted buffer'' error What do I do?.
|
||||
@end menu
|
||||
|
||||
@node How do I have more than one Org-roam directory?
|
||||
@ -2131,6 +2281,27 @@ to the publishing directory. Example code follows:
|
||||
(setq my-publish-time 0)))))
|
||||
@end lisp
|
||||
|
||||
@node I'm seeing this ``Selecting deleted buffer'' error What do I do?
|
||||
@section I'm seeing this ``Selecting deleted buffer'' error. What do I do?
|
||||
|
||||
The ``selecting deleted buffer'' error usually occurs when you don't have a
|
||||
working @code{emacsql-sqlite} executable. Org-roam relies on this executable to
|
||||
function properly, and doesn't catch this error. This issue is most commonly
|
||||
seen on Windows setups. You can browse through the various GitHub issues posted
|
||||
about this @uref{https://github.com/org-roam/org-roam/issues?q=is%3Aissue+selecting+deleted, here}.
|
||||
|
||||
To fix this, you can try the following:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
If on Windows, try replacing your system binary with @uref{https://github.com/nobiot/emacsql-sqlite.exe, this one} that has been proven
|
||||
to work
|
||||
|
||||
@item
|
||||
Use the @code{emacsql-sqlite3} option rather than compiling your own emacsql
|
||||
binary (see @ref{How to cache}).
|
||||
@end itemize
|
||||
|
||||
@node Developer's Guide to Org-roam
|
||||
@chapter Developer's Guide to Org-roam
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
;;; org-roam-dailies.el --- Daily-notes for Org-roam -*- coding: utf-8; lexical-binding: t; -*-
|
||||
;;;
|
||||
;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020 Leo Vivier <leo.vivier+dev@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Leo Vivier <leo.vivier+dev@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.1.0
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org-roam "2.1"))
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org-roam "2.1"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
|
||||
@ -34,10 +34,9 @@
|
||||
;; each file named after certain date and stored in `org-roam-dailies-directory'.
|
||||
;;
|
||||
;; One can use dailies for various purposes, e.g. journaling, fleeting notes,
|
||||
;; scratch notes and whatever else you can came up with.
|
||||
;; scratch notes or whatever else you can think of.
|
||||
;;
|
||||
;;; Code:
|
||||
(require 'f)
|
||||
(require 'dash)
|
||||
(require 'org-roam)
|
||||
|
||||
@ -130,79 +129,103 @@ See `org-roam-capture-templates' for the template documentation."
|
||||
;;; Commands
|
||||
;;;; Today
|
||||
;;;###autoload
|
||||
(defun org-roam-dailies-capture-today (&optional goto)
|
||||
(defun org-roam-dailies-capture-today (&optional goto keys)
|
||||
"Create an entry in the daily-note for today.
|
||||
When GOTO is non-nil, go the note without creating an entry."
|
||||
When GOTO is non-nil, go the note without creating an entry.
|
||||
|
||||
ELisp programs can set KEYS to a string associated with a template.
|
||||
In this case, interactive selection will be bypassed."
|
||||
(interactive "P")
|
||||
(org-roam-dailies--capture (current-time) goto))
|
||||
(org-roam-dailies--capture (current-time) goto keys))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-roam-dailies-goto-today ()
|
||||
"Find the daily-note for today, creating it if necessary."
|
||||
(defun org-roam-dailies-goto-today (&optional keys)
|
||||
"Find the daily-note for today, creating it if necessary.
|
||||
|
||||
ELisp programs can set KEYS to a string associated with a template.
|
||||
In this case, interactive selection will be bypassed."
|
||||
(interactive)
|
||||
(org-roam-dailies-capture-today t))
|
||||
(org-roam-dailies-capture-today t keys))
|
||||
|
||||
;;;; Tomorrow
|
||||
;;;###autoload
|
||||
(defun org-roam-dailies-capture-tomorrow (n &optional goto)
|
||||
(defun org-roam-dailies-capture-tomorrow (n &optional goto keys)
|
||||
"Create an entry in the daily-note for tomorrow.
|
||||
|
||||
With numeric argument N, use the daily-note N days in the future.
|
||||
|
||||
With a `C-u' prefix or when GOTO is non-nil, go the note without
|
||||
creating an entry."
|
||||
creating an entry.
|
||||
|
||||
ELisp programs can set KEYS to a string associated with a template.
|
||||
In this case, interactive selection will be bypassed."
|
||||
(interactive "p")
|
||||
(org-roam-dailies--capture (time-add (* n 86400) (current-time)) goto))
|
||||
(org-roam-dailies--capture (time-add (* n 86400) (current-time)) goto keys))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-roam-dailies-goto-tomorrow (n)
|
||||
(defun org-roam-dailies-goto-tomorrow (n &optional keys)
|
||||
"Find the daily-note for tomorrow, creating it if necessary.
|
||||
|
||||
With numeric argument N, use the daily-note N days in the
|
||||
future."
|
||||
future.
|
||||
|
||||
ELisp programs can set KEYS to a string associated with a template.
|
||||
In this case, interactive selection will be bypassed."
|
||||
(interactive "p")
|
||||
(org-roam-dailies-capture-tomorrow n t))
|
||||
(org-roam-dailies-capture-tomorrow n t keys))
|
||||
|
||||
;;;; Yesterday
|
||||
;;;###autoload
|
||||
(defun org-roam-dailies-capture-yesterday (n &optional goto)
|
||||
(defun org-roam-dailies-capture-yesterday (n &optional goto keys)
|
||||
"Create an entry in the daily-note for yesteday.
|
||||
|
||||
With numeric argument N, use the daily-note N days in the past.
|
||||
|
||||
When GOTO is non-nil, go the note without creating an entry."
|
||||
When GOTO is non-nil, go the note without creating an entry.
|
||||
|
||||
ELisp programs can set KEYS to a string associated with a template.
|
||||
In this case, interactive selection will be bypassed."
|
||||
(interactive "p")
|
||||
(org-roam-dailies-capture-tomorrow (- n) goto))
|
||||
(org-roam-dailies-capture-tomorrow (- n) goto keys))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-roam-dailies-goto-yesterday (n)
|
||||
(defun org-roam-dailies-goto-yesterday (n &optional keys)
|
||||
"Find the daily-note for yesterday, creating it if necessary.
|
||||
|
||||
With numeric argument N, use the daily-note N days in the
|
||||
future."
|
||||
future.
|
||||
|
||||
ELisp programs can set KEYS to a string associated with a template.
|
||||
In this case, interactive selection will be bypassed."
|
||||
(interactive "p")
|
||||
(org-roam-dailies-capture-tomorrow (- n) t))
|
||||
(org-roam-dailies-capture-tomorrow (- n) t keys))
|
||||
|
||||
;;;; Date
|
||||
;;;###autoload
|
||||
(defun org-roam-dailies-capture-date (&optional goto prefer-future)
|
||||
(defun org-roam-dailies-capture-date (&optional goto prefer-future keys)
|
||||
"Create an entry in the daily-note for a date using the calendar.
|
||||
Prefer past dates, unless PREFER-FUTURE is non-nil.
|
||||
With a `C-u' prefix or when GOTO is non-nil, go the note without
|
||||
creating an entry."
|
||||
creating an entry.
|
||||
|
||||
ELisp programs can set KEYS to a string associated with a template.
|
||||
In this case, interactive selection will be bypassed."
|
||||
(interactive "P")
|
||||
(let ((time (let ((org-read-date-prefer-future prefer-future))
|
||||
(org-read-date nil t nil (if goto
|
||||
"Find daily-note: "
|
||||
"Capture to daily-note: ")))))
|
||||
(org-roam-dailies--capture time goto)))
|
||||
(org-roam-dailies--capture time goto keys)))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-roam-dailies-goto-date (&optional prefer-future)
|
||||
(defun org-roam-dailies-goto-date (&optional prefer-future keys)
|
||||
"Find the daily-note for a date using the calendar, creating it if necessary.
|
||||
Prefer past dates, unless PREFER-FUTURE is non-nil."
|
||||
Prefer past dates, unless PREFER-FUTURE is non-nil.
|
||||
|
||||
ELisp programs can set KEYS to a string associated with a template.
|
||||
In this case, interactive selection will be bypassed."
|
||||
(interactive)
|
||||
(org-roam-dailies-capture-date t prefer-future))
|
||||
(org-roam-dailies-capture-date t prefer-future keys))
|
||||
|
||||
;;;; Navigation
|
||||
(defun org-roam-dailies-goto-next-note (&optional n)
|
||||
@ -266,7 +289,7 @@ If FILE is not specified, use the current buffer's file-path."
|
||||
(save-match-data
|
||||
(and
|
||||
(org-roam-file-p path)
|
||||
(f-descendant-of-p path directory)))))
|
||||
(org-roam-descendant-of-p path directory)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-roam-dailies-find-directory ()
|
||||
@ -300,11 +323,16 @@ Return (MONTH DAY YEAR) or nil if not an Org time-string."
|
||||
;;; Capture implementation
|
||||
(add-to-list 'org-roam-capture--template-keywords :override-default-time)
|
||||
|
||||
(defun org-roam-dailies--capture (time &optional goto)
|
||||
(defun org-roam-dailies--capture (time &optional goto keys)
|
||||
"Capture an entry in a daily-note for TIME, creating it if necessary.
|
||||
When GOTO is non-nil, go the note without creating an entry."
|
||||
(let ((org-roam-directory (expand-file-name org-roam-dailies-directory org-roam-directory)))
|
||||
When GOTO is non-nil, go the note without creating an entry.
|
||||
|
||||
ELisp programs can set KEYS to a string associated with a template.
|
||||
In this case, interactive selection will be bypassed."
|
||||
(let ((org-roam-directory (expand-file-name org-roam-dailies-directory org-roam-directory))
|
||||
(org-roam-dailies-directory "./"))
|
||||
(org-roam-capture- :goto (when goto '(4))
|
||||
:keys keys
|
||||
:node (org-roam-node-create)
|
||||
:templates org-roam-dailies-capture-templates
|
||||
:props (list :override-default-time time)))
|
||||
|
75
extensions/org-roam-export.el
Normal file
75
extensions/org-roam-export.el
Normal file
@ -0,0 +1,75 @@
|
||||
;;; org-roam-export.el --- Org-roam org-export tweaks -*- coding: utf-8; lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1"))
|
||||
|
||||
;; 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:
|
||||
;;
|
||||
;; This package provides the necessary changes required to make org-export work out-of-the-box.
|
||||
;;
|
||||
;; To enable it, run:
|
||||
;;
|
||||
;; (require 'org-roam-export)
|
||||
;;
|
||||
;; The key issue Org's export-to-html functionality has is that it does not respect the ID property, which
|
||||
;; Org-roam relies heavily on. This patches the necessary function in ox-html to export ID links correctly,
|
||||
;; pointing to the correct place.
|
||||
;;
|
||||
;;; Code:
|
||||
(require 'ox-html)
|
||||
|
||||
(defun org-roam-export--org-html--reference (datum info &optional named-only)
|
||||
"Org-roam's patch for `org-html--reference' to support ID link export.
|
||||
See `org-html--reference' for DATUM, INFO and NAMED-ONLY."
|
||||
(let* ((type (org-element-type datum))
|
||||
(user-label
|
||||
(org-element-property
|
||||
(pcase type
|
||||
((or `headline `inlinetask) :CUSTOM_ID)
|
||||
((or `radio-target `target) :value)
|
||||
(_ :name))
|
||||
datum))
|
||||
(user-label
|
||||
(or user-label
|
||||
(when-let ((path (org-element-property :ID datum)))
|
||||
;; see `org-html-link' for why we use "ID-"
|
||||
;; (search for "ID-" in ox-html.el)
|
||||
(concat "ID-" path)))))
|
||||
(cond
|
||||
((and user-label
|
||||
(or (plist-get info :html-prefer-user-labels)
|
||||
(memq type '(headline inlinetask))))
|
||||
user-label)
|
||||
((and named-only
|
||||
(not (memq type '(headline inlinetask radio-target target)))
|
||||
(not user-label))
|
||||
nil)
|
||||
(t
|
||||
(org-export-get-reference datum info)))))
|
||||
|
||||
(advice-add 'org-html--reference :override #'org-roam-export--org-html--reference)
|
||||
|
||||
(provide 'org-roam-export)
|
||||
;;; org-roam-export.el ends here
|
@ -1,11 +1,11 @@
|
||||
;;; org-roam-graph.el --- Basic graphing functionality for Org-roam -*- coding: utf-8; lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.1.0
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
@ -266,7 +266,7 @@ Handles both Org-roam nodes, and string nodes (e.g. urls)."
|
||||
(org-roam-quote-string
|
||||
(pcase org-roam-graph-shorten-titles
|
||||
(`truncate (truncate-string-to-width title org-roam-graph-max-title-length nil nil "..."))
|
||||
(`wrap (s-word-wrap org-roam-graph-max-title-length title))
|
||||
(`wrap (org-roam-word-wrap org-roam-graph-max-title-length title))
|
||||
(_ title)))))
|
||||
(setq node-id (org-roam-node-id node)
|
||||
node-properties `(("label" . ,shortened-title)
|
||||
|
@ -1,11 +1,11 @@
|
||||
;;; org-roam-overlay.el --- Link overlay for [id:] links to Org-roam nodes -*- coding: utf-8; lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.1.0
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
|
@ -1,10 +1,10 @@
|
||||
;;; org-roam-protocol.el --- Protocol handler for roam:// links -*- coding: utf-8; lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.1.0
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
@ -169,25 +169,6 @@ org-protocol://roam-node?node=uuid"
|
||||
(push '("org-roam-node" :protocol "roam-node" :function org-roam-protocol-open-node)
|
||||
org-protocol-protocol-alist)
|
||||
|
||||
;;; Capture implementation
|
||||
(add-hook 'org-roam-capture-preface-hook #'org-roam-protocol--try-capture-to-ref-h)
|
||||
(defun org-roam-protocol--try-capture-to-ref-h ()
|
||||
"Try to capture to an existing node that match the ref."
|
||||
(when-let ((node (and (plist-get org-roam-capture--info :ref)
|
||||
(org-roam-node-from-ref
|
||||
(plist-get org-roam-capture--info :ref)))))
|
||||
(set-buffer (org-capture-target-buffer (org-roam-node-file node)))
|
||||
(goto-char (org-roam-node-point node))
|
||||
(widen)
|
||||
(org-roam-node-id node)))
|
||||
|
||||
(add-hook 'org-roam-capture-new-node-hook #'org-roam-protocol--insert-captured-ref-h)
|
||||
(defun org-roam-protocol--insert-captured-ref-h ()
|
||||
"Insert the ref if any."
|
||||
(when-let ((ref (plist-get org-roam-capture--info :ref)))
|
||||
(org-roam-ref-add ref)))
|
||||
|
||||
|
||||
(provide 'org-roam-protocol)
|
||||
|
||||
;;; org-roam-protocol.el ends here
|
||||
|
11
github-eldev
Executable file
11
github-eldev
Executable file
@ -0,0 +1,11 @@
|
||||
#! /bin/sh
|
||||
set -e
|
||||
|
||||
ELDEV_BIN_DIR=~/.local/bin
|
||||
|
||||
# `$GITHUB_PATH' is a magic file which contents is translated to environment variable `$PATH'.
|
||||
echo "$ELDEV_BIN_DIR" >> $GITHUB_PATH
|
||||
|
||||
mkdir -p $ELDEV_BIN_DIR
|
||||
curl -fsSL https://raw.githubusercontent.com/doublep/eldev/f111d19cda305e5e8fcb70a5675b87173041cb68/bin/eldev > $ELDEV_BIN_DIR/eldev
|
||||
chmod a+x $ELDEV_BIN_DIR/eldev
|
@ -1,12 +1,12 @@
|
||||
;;; org-roam-capture.el --- Capture functionality -*- coding: utf-8; lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.1.0
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
|
||||
@ -407,6 +407,8 @@ TEMPLATES is a list of org-roam templates."
|
||||
(mapcar (lambda (template)
|
||||
(org-roam-capture--convert-template template props))
|
||||
(or templates org-roam-capture-templates)))
|
||||
(_ (setf (org-roam-node-id node) (or (org-roam-node-id node)
|
||||
(org-id-new))))
|
||||
(org-roam-capture--node node)
|
||||
(org-roam-capture--info info))
|
||||
(when (and (not keys)
|
||||
@ -503,7 +505,7 @@ Return the ID of the location."
|
||||
(set-buffer (org-capture-target-buffer path))
|
||||
(when new-file-p
|
||||
(org-roam-capture--put :new-file path)
|
||||
(insert (org-roam-capture--fill-template head t)))
|
||||
(insert (org-roam-capture--fill-template head 'ensure-newline)))
|
||||
(widen)
|
||||
(setq p (goto-char (point-min))))
|
||||
(`(file+head+olp ,path ,head ,olp)
|
||||
@ -513,7 +515,7 @@ Return the ID of the location."
|
||||
(widen)
|
||||
(when new-file-p
|
||||
(org-roam-capture--put :new-file path)
|
||||
(insert (org-roam-capture--fill-template head t)))
|
||||
(insert (org-roam-capture--fill-template head 'ensure-newline)))
|
||||
(setq p (point-min))
|
||||
(let ((m (org-roam-capture-find-or-create-olp olp)))
|
||||
(goto-char m)))
|
||||
@ -572,11 +574,11 @@ Return the ID of the location."
|
||||
;; caller.
|
||||
(save-excursion
|
||||
(goto-char p)
|
||||
(when-let* ((node org-roam-capture--node)
|
||||
(id (org-roam-node-id node)))
|
||||
(org-entry-put p "ID" id))
|
||||
(if-let ((id (org-entry-get p "ID")))
|
||||
(setf (org-roam-node-id org-roam-capture--node) id)
|
||||
(org-entry-put p "ID" (org-roam-node-id org-roam-capture--node)))
|
||||
(prog1
|
||||
(org-id-get-create)
|
||||
(org-id-get)
|
||||
(run-hooks 'org-roam-capture-new-node-hook)))))
|
||||
|
||||
(defun org-roam-capture--get-target ()
|
||||
@ -589,8 +591,9 @@ Return the ID of the location."
|
||||
PATH is a string that can optionally contain templated text in
|
||||
it."
|
||||
(or (org-roam-node-file org-roam-capture--node)
|
||||
(thread-first path
|
||||
(org-roam-capture--fill-template t)
|
||||
(thread-first
|
||||
path
|
||||
(org-roam-capture--fill-template)
|
||||
(string-trim)
|
||||
(expand-file-name org-roam-directory))))
|
||||
|
||||
@ -615,7 +618,7 @@ you can catch it with `condition-case'."
|
||||
(org-with-wide-buffer
|
||||
(goto-char start)
|
||||
(dolist (heading olp)
|
||||
(setq heading (org-roam-capture--fill-template heading t))
|
||||
(setq heading (org-roam-capture--fill-template heading))
|
||||
(let ((re (format org-complex-heading-regexp-format
|
||||
(regexp-quote heading)))
|
||||
(cnt 0))
|
||||
@ -677,6 +680,24 @@ the current value of `point'."
|
||||
(goto-char (org-entry-end-position))))))))
|
||||
(point))
|
||||
|
||||
;;; Capture implementation
|
||||
(add-hook 'org-roam-capture-preface-hook #'org-roam-capture--try-capture-to-ref-h)
|
||||
(defun org-roam-capture--try-capture-to-ref-h ()
|
||||
"Try to capture to an existing node that match the ref."
|
||||
(when-let ((node (and (plist-get org-roam-capture--info :ref)
|
||||
(org-roam-node-from-ref
|
||||
(plist-get org-roam-capture--info :ref)))))
|
||||
(set-buffer (org-capture-target-buffer (org-roam-node-file node)))
|
||||
(goto-char (org-roam-node-point node))
|
||||
(widen)
|
||||
(org-roam-node-id node)))
|
||||
|
||||
(add-hook 'org-roam-capture-new-node-hook #'org-roam-capture--insert-captured-ref-h)
|
||||
(defun org-roam-capture--insert-captured-ref-h ()
|
||||
"Insert the ref if any."
|
||||
(when-let ((ref (plist-get org-roam-capture--info :ref)))
|
||||
(org-roam-ref-add ref)))
|
||||
|
||||
;;;; Finalizers
|
||||
(add-hook 'org-capture-prepare-finalize-hook #'org-roam-capture--install-finalize-h)
|
||||
(defun org-roam-capture--install-finalize-h ()
|
||||
@ -689,11 +710,14 @@ the current value of `point'."
|
||||
(when-let ((region (org-roam-capture--get :region)))
|
||||
(org-roam-unshield-region (car region) (cdr region)))
|
||||
(if org-note-abort
|
||||
(when-let ((new-file (org-roam-capture--get :new-file)))
|
||||
(org-roam-message "Deleting file for aborted capture %s" new-file)
|
||||
(when-let ((new-file (org-roam-capture--get :new-file))
|
||||
(_ (yes-or-no-p "Delete file for aborted capture?")))
|
||||
(when (find-buffer-visiting new-file)
|
||||
(kill-buffer (find-buffer-visiting new-file)))
|
||||
(delete-file new-file))
|
||||
(when-let* ((buffer (plist-get org-capture-plist :buffer))
|
||||
(file (buffer-file-name buffer)))
|
||||
(org-id-add-location (org-roam-capture--get :id) file))
|
||||
(when-let* ((finalize (org-roam-capture--get :finalize))
|
||||
(org-roam-finalize-fn (intern (concat "org-roam-capture--finalize-"
|
||||
(symbol-name finalize)))))
|
||||
@ -720,48 +744,56 @@ This function is to be called in the Org-capture finalization process."
|
||||
(delete-region (car region) (cdr region))
|
||||
(set-marker (car region) nil)
|
||||
(set-marker (cdr region) nil))
|
||||
(org-with-point-at mkr
|
||||
(insert (org-link-make-string (concat "id:" (org-roam-capture--get :id))
|
||||
(org-roam-capture--get :link-description)))))))
|
||||
(let* ((id (org-roam-capture--get :id))
|
||||
(description (org-roam-capture--get :link-description))
|
||||
(link (org-link-make-string (concat "id:" id)
|
||||
description)))
|
||||
(if (eq (point) (marker-position mkr))
|
||||
(insert link)
|
||||
(org-with-point-at mkr
|
||||
(insert link)))
|
||||
(run-hook-with-args 'org-roam-post-node-insert-hook
|
||||
id
|
||||
description)))))
|
||||
|
||||
;;;; Processing of the capture templates
|
||||
(defun org-roam-capture--fill-template (template &optional org-capture-p newline)
|
||||
(defun org-roam-capture--fill-template (template &optional ensure-newline)
|
||||
"Expand TEMPLATE and return it.
|
||||
It expands ${var} occurrences in TEMPLATE. When ORG-CAPTURE-P,
|
||||
also run Org-capture's template expansion.
|
||||
If NEWLINE, ensure that the template returned ends with a newline."
|
||||
(setq template (org-roam-format-template
|
||||
template
|
||||
(lambda (key default-val)
|
||||
(let ((fn (intern key))
|
||||
(node-fn (intern (concat "org-roam-node-" key)))
|
||||
(ksym (intern (concat ":" key))))
|
||||
(cond
|
||||
((fboundp fn)
|
||||
(funcall fn org-roam-capture--node))
|
||||
((fboundp node-fn)
|
||||
(funcall node-fn org-roam-capture--node))
|
||||
((plist-get org-roam-capture--info ksym)
|
||||
(plist-get org-roam-capture--info ksym))
|
||||
(t (let ((r (read-from-minibuffer (format "%s: " key) default-val)))
|
||||
(plist-put org-roam-capture--info ksym r)
|
||||
r)))))))
|
||||
;; WARNING:
|
||||
;; `org-capture-fill-template' fills the template, but post-processes whitespace such that the resultant
|
||||
;; template does not start with any whitespace, and only ends with a single newline
|
||||
;;
|
||||
;; In most cases where we rely on `org-capture-fill-template' to populate non-org-capture-related templates,
|
||||
;; (e.g. in OLPs), we strip the final newline, obtaining a template that seems to be string-trimmed.
|
||||
;;
|
||||
;; This means that if the original passed template has newlines, and ORG-CAPTURE-P is true, then the extra
|
||||
;; whitespace specified in the template will be ignored.
|
||||
(when org-capture-p
|
||||
It expands ${var} occurrences in TEMPLATE, and then runs
|
||||
org-capture's template expansion.
|
||||
When ENSURE-NEWLINE, always ensure there's a newline behind."
|
||||
(let* ((template (if (functionp template)
|
||||
(funcall template)
|
||||
template))
|
||||
(template-whitespace-content (org-roam-whitespace-content template)))
|
||||
(setq template
|
||||
(replace-regexp-in-string "\n$" "" (org-capture-fill-template template))))
|
||||
(when (and newline
|
||||
(not (string-suffix-p "\n" template)))
|
||||
(setq template (concat template "\n")))
|
||||
template)
|
||||
(org-roam-format-template
|
||||
template
|
||||
(lambda (key default-val)
|
||||
(let ((fn (intern key))
|
||||
(node-fn (intern (concat "org-roam-node-" key)))
|
||||
(ksym (intern (concat ":" key))))
|
||||
(cond
|
||||
((fboundp fn)
|
||||
(funcall fn org-roam-capture--node))
|
||||
((fboundp node-fn)
|
||||
(funcall node-fn org-roam-capture--node))
|
||||
((plist-get org-roam-capture--info ksym)
|
||||
(plist-get org-roam-capture--info ksym))
|
||||
(t (let ((r (read-from-minibuffer (format "%s: " key) default-val)))
|
||||
(plist-put org-roam-capture--info ksym r)
|
||||
r)))))))
|
||||
;; WARNING:
|
||||
;; `org-capture-fill-template' fills the template, but post-processes whitespace such that the resultant
|
||||
;; template does not start with any whitespace, and only ends with a single newline
|
||||
;;
|
||||
;; Instead, we restore the whitespace in the original template.
|
||||
(setq template (replace-regexp-in-string "\n$" "" (org-capture-fill-template template)))
|
||||
(when (and ensure-newline
|
||||
(string-equal template-whitespace-content ""))
|
||||
(setq template-whitespace-content "\n"))
|
||||
(setq template (concat template template-whitespace-content))
|
||||
template))
|
||||
|
||||
(defun org-roam-capture--convert-template (template &optional props)
|
||||
"Convert TEMPLATE from Org-roam syntax to `org-capture-templates' syntax.
|
||||
|
@ -1,11 +1,11 @@
|
||||
;;; org-roam-compat.el --- Backward compatibility code -*- coding: utf-8; lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.1.0
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
@ -229,6 +229,10 @@ nodes." org-id-locations-file)
|
||||
'org-roam-remove-property
|
||||
'org-roam-property-remove "org-roam 2.1")
|
||||
|
||||
(define-obsolete-variable-alias
|
||||
'org-roam-mode-section-functions
|
||||
'org-roam-mode-sections "org-roam 2.2.0")
|
||||
|
||||
;;; Obsolete functions
|
||||
(make-obsolete 'org-roam-get-keyword 'org-collect-keywords "org-roam 2.0")
|
||||
|
||||
|
169
org-roam-db.el
169
org-roam-db.el
@ -1,12 +1,12 @@
|
||||
;;; org-roam-db.el --- Org-roam database API -*- coding: utf-8; lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.1.0
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
|
||||
@ -36,25 +36,37 @@
|
||||
;;; Options
|
||||
(defcustom org-roam-database-connector 'sqlite
|
||||
"The database connector used by Org-roam.
|
||||
This must be set before `org-roam' is loaded. To use an
|
||||
alternative connector you must install the respective package
|
||||
explicitly. When `sqlite', then use the `emacsql-sqlite' library
|
||||
This must be set before `org-roam' is loaded. To use an alternative
|
||||
connector you must install the respective package explicitly.
|
||||
The default is `sqlite', which uses the `emacsql-sqlite' library
|
||||
that is being maintained in the same repository as `emacsql'
|
||||
itself. When `libsqlite3', then use the `emacsql-libsqlite3'
|
||||
library, which itself uses a module provided by the `sqlite3'
|
||||
package. This is still experimental. When `sqlite3', then use the
|
||||
`emacsql-sqlite3' library, which uses the official `sqlite3' cli
|
||||
tool, which is not recommended because it is not suitable to be
|
||||
used like this, but has the advantage that you likely don't need
|
||||
a compiler. See https://nullprogram.com/blog/2014/02/06/."
|
||||
:package-version '(org-roam . "2.2.0")
|
||||
:group 'org-roam
|
||||
itself.
|
||||
If you are using Emacs 29, then the recommended connector is
|
||||
`sqlite-builtin', which uses the new builtin support for SQLite.
|
||||
You need to install the `emacsql-sqlite-builtin' package to use
|
||||
this connector.
|
||||
If you are using an older Emacs release, then the recommended
|
||||
connector is `sqlite-module', which uses the module provided by
|
||||
the `sqlite3' package. This is very similar to the previous
|
||||
connector and the built-in support in Emacs 29 derives from this
|
||||
module. You need to install the `emacsql-sqlite-module' package
|
||||
to use this connector.
|
||||
For the time being `libsqlite3' is still supported. Do not use
|
||||
this, it is an older version of the `sqlite-module' connector
|
||||
from before the connector and the package were renamed.
|
||||
For the time being `sqlite3' is also supported. Do not use this.
|
||||
This uses the third-party `emacsql-sqlite3' package, which uses
|
||||
the official `sqlite3' cli tool, which is not intended
|
||||
to be used like this. See https://nullprogram.com/blog/2014/02/06/."
|
||||
:package-version '(forge . "0.3.0")
|
||||
:group 'forge
|
||||
:type '(choice (const sqlite)
|
||||
(const libsqlite3)
|
||||
(const sqlite3)
|
||||
(symbol :tag "other")))
|
||||
(const sqlite-builtin)
|
||||
(const sqlite-module)
|
||||
(const :tag "libsqlite3 (OBSOLETE)" libsqlite3)
|
||||
(const :tag "sqlite3 (BROKEN)" sqlite3)))
|
||||
|
||||
(defcustom org-roam-db-location (expand-file-name "org-roam.db" user-emacs-directory)
|
||||
(defcustom org-roam-db-location (locate-user-emacs-file "org-roam.db")
|
||||
"The path to file where the Org-roam database is stored.
|
||||
|
||||
It is the user's responsibility to set this correctly, especially
|
||||
@ -98,15 +110,35 @@ slow."
|
||||
:type 'boolean
|
||||
:group 'org-roam)
|
||||
|
||||
(defcustom org-roam-db-extra-links-elements '(node-property keyword)
|
||||
"The list of Org element types to include for parsing by Org-roam.
|
||||
|
||||
By default, when parsing Org's AST, links within keywords and
|
||||
property drawers are not parsed as links. Sometimes however, it
|
||||
is desirable to parse and cache these links (e.g. hiding links in
|
||||
a property drawer)."
|
||||
:package-version '(org-roam . "2.2.0")
|
||||
:group 'org-roam
|
||||
:type '(set (const :tag "keywords" keyword)
|
||||
(const :tag "property drawers" node-property)))
|
||||
|
||||
(defcustom org-roam-db-extra-links-exclude-keys '((node-property . ("ROAM_REFS"))
|
||||
(keyword . ("transclude")))
|
||||
"Keys to ignore when mapping over links.
|
||||
|
||||
The car of the association list is the Org element type (e.g.
|
||||
keyword). The cdr is a list of case-insensitive strings to
|
||||
exclude from being treated as links.
|
||||
|
||||
For example, we use this to prevent self-referential links in
|
||||
ROAM_REFS."
|
||||
:package-version '(org-roam . "2.2.0")
|
||||
:group 'org-roam
|
||||
:type '(alist))
|
||||
|
||||
;;; Variables
|
||||
(defconst org-roam-db-version 18)
|
||||
|
||||
;; TODO Rename this
|
||||
(defconst org-roam--sqlite-available-p
|
||||
(with-demoted-errors "Org-roam initialization: %S"
|
||||
(emacsql-sqlite-ensure-binary)
|
||||
t))
|
||||
|
||||
(defvar org-roam-db--connection (make-hash-table :test #'equal)
|
||||
"Database connection to Org-roam database.")
|
||||
|
||||
@ -117,8 +149,10 @@ slow."
|
||||
org-roam-db--connection))
|
||||
|
||||
(declare-function emacsql-sqlite "ext:emacsql-sqlite")
|
||||
(declare-function emacsql-libsqlite3 "ext:emacsql-libsqlite3")
|
||||
(declare-function emacsql-sqlite3 "ext:emacsql-sqlite3")
|
||||
(declare-function emacsql-libsqlite3 "ext:emacsql-libsqlite3")
|
||||
(declare-function emacsql-sqlite-builtin "ext:emacsql-sqlite-builtin")
|
||||
(declare-function emacsql-sqlite-module "ext:emacsql-sqlite-module")
|
||||
|
||||
(defun org-roam-db--conn-fn ()
|
||||
"Return the function for creating the database connection."
|
||||
@ -127,6 +161,14 @@ slow."
|
||||
(progn
|
||||
(require 'emacsql-sqlite)
|
||||
#'emacsql-sqlite))
|
||||
(sqlite-builtin
|
||||
(progn
|
||||
(require 'emacsql-sqlite-builtin)
|
||||
#'emacsql-sqlite-builtin))
|
||||
(sqlite-module
|
||||
(progn
|
||||
(require 'emacsql-sqlite-module)
|
||||
#'emacsql-sqlite-module))
|
||||
(libsqlite3
|
||||
(progn
|
||||
(require 'emacsql-libsqlite3)
|
||||
@ -145,7 +187,9 @@ Performs a database upgrade when required."
|
||||
(let ((init-db (not (file-exists-p org-roam-db-location))))
|
||||
(make-directory (file-name-directory org-roam-db-location) t)
|
||||
(let ((conn (funcall (org-roam-db--conn-fn) org-roam-db-location)))
|
||||
(when-let ((process (emacsql-process conn)))
|
||||
(emacsql conn [:pragma (= foreign_keys ON)])
|
||||
(when-let* ((process (emacsql-process conn))
|
||||
(_ (processp process)))
|
||||
(set-process-query-on-exit-flag process nil))
|
||||
(puthash (expand-file-name (file-name-as-directory org-roam-directory))
|
||||
conn
|
||||
@ -243,7 +287,6 @@ The query is expected to be able to fail, in this situation, run HANDLER."
|
||||
|
||||
(defun org-roam-db--init (db)
|
||||
"Initialize database DB with the correct schema and user version."
|
||||
(emacsql db [:pragma (= foreign_keys ON)])
|
||||
(emacsql-with-transaction db
|
||||
(pcase-dolist (`(,table ,schema) org-roam-db--table-schemata)
|
||||
(emacsql db [:create-table $i1 $S2] table schema))
|
||||
@ -359,15 +402,12 @@ If UPDATE-P is non-nil, first remove the file in the database."
|
||||
;; Links correctly recognized by Org Mode
|
||||
((eq type 'link)
|
||||
(setq link element))
|
||||
;; Prevent self-referencing links in ROAM_REFS
|
||||
((and (eq type 'node-property)
|
||||
(org-roam-string-equal (org-element-property :key element) "ROAM_REFS"))
|
||||
nil)
|
||||
;; Links in property drawers and lines starting with #+. Recall that, as for Org Mode v9.4.4, the
|
||||
;; org-element-type of links within properties drawers is "node-property" and for lines starting with
|
||||
;; #+ is "keyword".
|
||||
((and (or (eq type 'node-property)
|
||||
(eq type 'keyword))
|
||||
((and (member type org-roam-db-extra-links-elements)
|
||||
(not (member-ignore-case (org-element-property :key element)
|
||||
(cdr (assoc type org-roam-db-extra-links-exclude-keys))))
|
||||
(setq bounds (org-in-regexp org-link-any-re))
|
||||
(setq link (buffer-substring-no-properties
|
||||
(car bounds)
|
||||
@ -482,9 +522,24 @@ INFO is the org-element parsed buffer."
|
||||
(let (rows)
|
||||
(dolist (ref refs)
|
||||
(save-match-data
|
||||
(cond ((string-prefix-p "@" ref)
|
||||
(cond (;; @citeKey
|
||||
(string-prefix-p "@" ref)
|
||||
(push (vector node-id (substring ref 1) "cite") rows))
|
||||
((string-match org-link-plain-re ref)
|
||||
(;; [cite:@citeKey]
|
||||
(string-prefix-p "[cite:" ref)
|
||||
(condition-case nil
|
||||
(let ((cite-obj (org-cite-parse-objects ref)))
|
||||
(org-element-map cite-obj 'citation-reference
|
||||
(lambda (cite)
|
||||
(let ((key (org-element-property :key cite)))
|
||||
(push (vector node-id key "cite") rows)))))
|
||||
(error
|
||||
(lwarn '(org-roam) :warning
|
||||
"%s:%s\tInvalid cite %s, skipping..." (buffer-file-name) (point) ref))))
|
||||
(;; https://google.com, cite:citeKey
|
||||
;; Note: we use string-match here because it matches any link: e.g. [[cite:abc][abc]]
|
||||
;; But this form of matching is loose, and can accept invalid links e.g. [[cite:abc]
|
||||
(string-match org-link-plain-re ref)
|
||||
(let ((link-type (match-string 1 ref))
|
||||
(path (match-string 2 ref)))
|
||||
(if (and (boundp 'org-ref-cite-types)
|
||||
@ -585,27 +640,27 @@ in `org-roam-db-sync'."
|
||||
(org-roam-require '(org-ref oc)))
|
||||
(org-roam-with-file file-path nil
|
||||
(emacsql-with-transaction (org-roam-db)
|
||||
(save-excursion
|
||||
(org-set-regexps-and-options 'tags-only)
|
||||
(org-refresh-category-properties)
|
||||
(org-roam-db-clear-file)
|
||||
(org-roam-db-insert-file)
|
||||
(org-roam-db-insert-file-node)
|
||||
(setq org-outline-path-cache nil)
|
||||
(org-roam-db-map-nodes
|
||||
(list #'org-roam-db-insert-node-data
|
||||
#'org-roam-db-insert-aliases
|
||||
#'org-roam-db-insert-tags
|
||||
#'org-roam-db-insert-refs))
|
||||
(setq org-outline-path-cache nil)
|
||||
(setq info (org-element-parse-buffer))
|
||||
(org-roam-db-map-links
|
||||
(list #'org-roam-db-insert-link))
|
||||
(when (fboundp 'org-cite-insert)
|
||||
(require 'oc) ;ensure feature is loaded
|
||||
(org-roam-db-map-citations
|
||||
info
|
||||
(list #'org-roam-db-insert-citation)))))))))
|
||||
(org-with-wide-buffer
|
||||
(org-set-regexps-and-options 'tags-only)
|
||||
(org-refresh-category-properties)
|
||||
(org-roam-db-clear-file)
|
||||
(org-roam-db-insert-file)
|
||||
(org-roam-db-insert-file-node)
|
||||
(setq org-outline-path-cache nil)
|
||||
(org-roam-db-map-nodes
|
||||
(list #'org-roam-db-insert-node-data
|
||||
#'org-roam-db-insert-aliases
|
||||
#'org-roam-db-insert-tags
|
||||
#'org-roam-db-insert-refs))
|
||||
(setq org-outline-path-cache nil)
|
||||
(setq info (org-element-parse-buffer))
|
||||
(org-roam-db-map-links
|
||||
(list #'org-roam-db-insert-link))
|
||||
(when (fboundp 'org-cite-insert)
|
||||
(require 'oc) ;ensure feature is loaded
|
||||
(org-roam-db-map-citations
|
||||
info
|
||||
(list #'org-roam-db-insert-citation)))))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-roam-db-sync (&optional force)
|
||||
|
117
org-roam-id.el
Normal file
117
org-roam-id.el
Normal file
@ -0,0 +1,117 @@
|
||||
;;; org-roam-id.el --- ID-related utilities for Org-roam -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (magit-section "3.0.0"))
|
||||
|
||||
;; 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:
|
||||
;;
|
||||
;; This module provides ID-related facilities using the Org-roam database.
|
||||
;;
|
||||
;;; Code:
|
||||
(require 'org-id)
|
||||
|
||||
(defun org-roam-id-at-point ()
|
||||
"Return the ID at point, if any.
|
||||
Recursively traverses up the headline tree to find the
|
||||
first encapsulating ID."
|
||||
(org-with-wide-buffer
|
||||
(org-back-to-heading-or-point-min t)
|
||||
(while (and (not (org-roam-db-node-p))
|
||||
(not (bobp)))
|
||||
(org-roam-up-heading-or-point-min))
|
||||
(when (org-roam-db-node-p)
|
||||
(org-id-get))))
|
||||
|
||||
(defun org-roam-id-find (id &optional markerp)
|
||||
"Return the location of the entry with the id ID using the Org-roam db.
|
||||
The return value is a cons cell (file-name . position), or nil
|
||||
if there is no entry with that ID.
|
||||
With optional argument MARKERP, return the position as a new marker."
|
||||
(cond
|
||||
((symbolp id) (setq id (symbol-name id)))
|
||||
((numberp id) (setq id (number-to-string id))))
|
||||
(let ((node (org-roam-populate (org-roam-node-create :id id))))
|
||||
(when-let ((file (org-roam-node-file node)))
|
||||
(if markerp
|
||||
(unwind-protect
|
||||
(let ((buffer (or (find-buffer-visiting file)
|
||||
(find-file-noselect file))))
|
||||
(with-current-buffer buffer
|
||||
(move-marker (make-marker) (org-roam-node-point node) buffer))))
|
||||
(cons (org-roam-node-file node)
|
||||
(org-roam-node-point node))))))
|
||||
|
||||
(defun org-roam-id-open (id _)
|
||||
"Go to the entry with id ID.
|
||||
Like `org-id-open', but additionally uses the Org-roam database."
|
||||
(org-mark-ring-push)
|
||||
(let ((m (or (org-roam-id-find id 'marker)
|
||||
(org-id-find id 'marker)))
|
||||
cmd)
|
||||
(unless m
|
||||
(error "Cannot find entry with ID \"%s\"" id))
|
||||
;; Use a buffer-switching command in analogy to finding files
|
||||
(setq cmd
|
||||
(or
|
||||
(cdr
|
||||
(assq
|
||||
(cdr (assq 'file org-link-frame-setup))
|
||||
'((find-file . switch-to-buffer)
|
||||
(find-file-other-window . switch-to-buffer-other-window)
|
||||
(find-file-other-frame . switch-to-buffer-other-frame))))
|
||||
'switch-to-buffer-other-window))
|
||||
(if (not (equal (current-buffer) (marker-buffer m)))
|
||||
(funcall cmd (marker-buffer m)))
|
||||
(goto-char m)
|
||||
(move-marker m nil)
|
||||
(org-show-context)))
|
||||
|
||||
(org-link-set-parameters "id" :follow #'org-roam-id-open)
|
||||
|
||||
;;;###autoload
|
||||
(defun org-roam-update-org-id-locations (&rest directories)
|
||||
"Scan Org-roam files to update `org-id' related state.
|
||||
This is like `org-id-update-id-locations', but will automatically
|
||||
use the currently bound `org-directory' and `org-roam-directory'
|
||||
along with DIRECTORIES (if any), where the lookup for files in
|
||||
these directories will be always recursive.
|
||||
|
||||
Note: Org-roam doesn't have hard dependency on
|
||||
`org-id-locations-file' to lookup IDs for nodes that are stored
|
||||
in the database, but it still tries to properly integrates with
|
||||
`org-id'. This allows the user to cross-reference IDs outside of
|
||||
the current `org-roam-directory', and also link with \"id:\"
|
||||
links to headings/files within the current `org-roam-directory'
|
||||
that are excluded from identification in Org-roam as
|
||||
`org-roam-node's, e.g. with \"ROAM_EXCLUDE\" property."
|
||||
(interactive)
|
||||
(cl-loop for dir in (cons org-roam-directory directories)
|
||||
for org-roam-directory = dir
|
||||
nconc (org-roam-list-files) into files
|
||||
finally (org-id-update-id-locations files org-roam-verbose)))
|
||||
|
||||
(provide 'org-roam-id)
|
||||
|
||||
;;; org-roam-id.el ends here
|
53
org-roam-log.el
Normal file
53
org-roam-log.el
Normal file
@ -0,0 +1,53 @@
|
||||
;;; org-roam-log.el --- Integrations with Org-log -*- coding: utf-8; lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2022-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
|
||||
|
||||
;; 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:
|
||||
;;
|
||||
;; This module provides integrations with Org-log.
|
||||
;;
|
||||
;;; Code:
|
||||
(require 'org-roam)
|
||||
|
||||
(defcustom org-roam-log-setup-hook nil
|
||||
"Hook run when a log for an Org-roam file is setup."
|
||||
:group 'org-roam
|
||||
:type 'hook)
|
||||
|
||||
(defun org-roam-log-p ()
|
||||
"Return t if the log buffer is for an Org-roam file, nil otherwise."
|
||||
(and org-log-note-marker
|
||||
(org-roam-file-p (buffer-file-name (marker-buffer org-log-note-marker)))))
|
||||
|
||||
(defun org-roam-log--setup ()
|
||||
"Run hooks in `org-roam-log-setup-hook'."
|
||||
(run-hooks 'org-roam-log-setup-hook))
|
||||
|
||||
(add-hook 'org-roam-log-setup-hook #'org-roam--register-completion-functions-h)
|
||||
(add-hook 'org-log-buffer-setup-hook #'org-roam-log--setup)
|
||||
|
||||
(provide 'org-roam-log)
|
||||
;;; org-roam-log.el ends here
|
@ -1,12 +1,12 @@
|
||||
;;; org-roam-migrate.el --- Migration utilities from v1 to v2 -*- coding: utf-8; lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.1.0
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
;;; org-roam-mode.el --- Major mode for special Org-roam buffers -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.1.0
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
|
||||
@ -39,14 +39,28 @@
|
||||
(defvar org-ref-buffer-hacked)
|
||||
|
||||
;;; Options
|
||||
(defcustom org-roam-mode-section-functions (list #'org-roam-backlinks-section
|
||||
#'org-roam-reflinks-section)
|
||||
"Functions that insert sections in the `org-roam-mode' based buffers.
|
||||
Each function is called with one argument, which is an
|
||||
`org-roam-node' for which the buffer will be constructed for.
|
||||
Normally this node is `org-roam-buffer-current-node'."
|
||||
(defcustom org-roam-mode-sections (list #'org-roam-backlinks-section
|
||||
#'org-roam-reflinks-section)
|
||||
"A list of sections for the `org-roam-mode' based buffers.
|
||||
Each section is a function that is passed the an `org-roam-node'
|
||||
for which the section will be constructed for as the first
|
||||
argument. Normally this node is `org-roam-buffer-current-node'.
|
||||
The function may also accept other optional arguments. Each item
|
||||
in the list is either:
|
||||
|
||||
1. A function, which is called only with the `org-roam-node' as the argument
|
||||
2. A list, containing the function and the optional arguments.
|
||||
|
||||
For example, one can add
|
||||
|
||||
(org-roam-backlinks-section :unique t)
|
||||
|
||||
to the list to pass :unique t to the section-rendering function."
|
||||
:group 'org-roam
|
||||
:type 'hook)
|
||||
:type `(repeat (choice (symbol :tag "Function")
|
||||
(list :tag "Function with arguments"
|
||||
(symbol :tag "Function")
|
||||
(repeat :tag "Arguments" :inline t (sexp :tag "Arg"))))))
|
||||
|
||||
(defcustom org-roam-buffer-postrender-functions (list)
|
||||
"Functions to run after the Org-roam buffer is rendered.
|
||||
@ -168,7 +182,7 @@ This mode is used by special Org-roam buffers, such as persistent
|
||||
`org-roam-buffer' and dedicated Org-roam buffers
|
||||
\(`org-roam-buffer-display-dedicated'), which render the
|
||||
information in a section-like manner (see
|
||||
`org-roam-mode-section-functions'), with which the user can
|
||||
`org-roam-mode-sections'), with which the user can
|
||||
interact with."
|
||||
:group 'org-roam
|
||||
(face-remap-add-relative 'header-line 'org-roam-header-line))
|
||||
@ -228,7 +242,14 @@ buffer."
|
||||
(org-roam-node-title org-roam-buffer-current-node))
|
||||
(magit-insert-section (org-roam)
|
||||
(magit-insert-heading)
|
||||
(run-hook-with-args 'org-roam-mode-section-functions org-roam-buffer-current-node))
|
||||
(dolist (section org-roam-mode-sections)
|
||||
(pcase section
|
||||
((pred functionp)
|
||||
(funcall section org-roam-buffer-current-node))
|
||||
(`(,fn . ,args)
|
||||
(apply fn (cons org-roam-buffer-current-node args)))
|
||||
(_
|
||||
(user-error "Invalid `org-roam-mode-sections' specification")))))
|
||||
(run-hooks 'org-roam-buffer-postrender-functions)
|
||||
(goto-char 0)))
|
||||
|
||||
@ -289,7 +310,7 @@ To toggle its display use `org-roam-buffer-toggle' command.")
|
||||
(pcase (org-roam-buffer--visibility)
|
||||
('visible
|
||||
(progn
|
||||
(delete-window (get-buffer-window org-roam-buffer))
|
||||
(quit-window nil (get-buffer-window org-roam-buffer))
|
||||
(remove-hook 'post-command-hook #'org-roam-buffer--redisplay-h)))
|
||||
((or 'exists 'none)
|
||||
(progn
|
||||
@ -428,10 +449,12 @@ In interactive calls OTHER-WINDOW is set with
|
||||
|
||||
This function returns the all contents under the current
|
||||
headline, up to the next headline."
|
||||
(let ((beg (progn (org-roam-end-of-meta-data t)
|
||||
(point)))
|
||||
(end (progn (org-next-visible-heading 1)
|
||||
(point))))
|
||||
(let ((beg (save-excursion
|
||||
(org-roam-end-of-meta-data t)
|
||||
(point)))
|
||||
(end (save-excursion
|
||||
(org-next-visible-heading 1)
|
||||
(point))))
|
||||
(string-trim (buffer-substring-no-properties beg end))))
|
||||
|
||||
(defun org-roam-preview-get-contents (file pt)
|
||||
@ -459,14 +482,23 @@ headline, up to the next headline."
|
||||
(org-roam-populate (org-roam-backlink-target-node backlink)))
|
||||
backlink)
|
||||
|
||||
(defun org-roam-backlinks-get (node)
|
||||
"Return the backlinks for NODE."
|
||||
(let ((backlinks (org-roam-db-query
|
||||
[:select [source dest pos properties]
|
||||
:from links
|
||||
:where (= dest $s1)
|
||||
:and (= type "id")]
|
||||
(org-roam-node-id node))))
|
||||
(cl-defun org-roam-backlinks-get (node &key unique)
|
||||
"Return the backlinks for NODE.
|
||||
|
||||
When UNIQUE is nil, show all positions where references are found.
|
||||
When UNIQUE is t, limit to unique sources."
|
||||
(let* ((sql (if unique
|
||||
[:select :distinct [source dest pos properties]
|
||||
:from links
|
||||
:where (= dest $s1)
|
||||
:and (= type "id")
|
||||
:group :by source
|
||||
:having (funcall min pos)]
|
||||
[:select [source dest pos properties]
|
||||
:from links
|
||||
:where (= dest $s1)
|
||||
:and (= type "id")]))
|
||||
(backlinks (org-roam-db-query sql (org-roam-node-id node))))
|
||||
(cl-loop for backlink in backlinks
|
||||
collect (pcase-let ((`(,source-id ,dest-id ,pos ,properties) backlink))
|
||||
(org-roam-populate
|
||||
@ -482,9 +514,12 @@ Sorts by title."
|
||||
(string< (org-roam-node-title (org-roam-backlink-source-node a))
|
||||
(org-roam-node-title (org-roam-backlink-source-node b))))
|
||||
|
||||
(defun org-roam-backlinks-section (node)
|
||||
"The backlinks section for NODE."
|
||||
(when-let ((backlinks (seq-sort #'org-roam-backlinks-sort (org-roam-backlinks-get node))))
|
||||
(cl-defun org-roam-backlinks-section (node &key (unique nil))
|
||||
"The backlinks section for NODE.
|
||||
|
||||
When UNIQUE is nil, show all positions where references are found.
|
||||
When UNIQUE is t, limit to unique sources."
|
||||
(when-let ((backlinks (seq-sort #'org-roam-backlinks-sort (org-roam-backlinks-get node :unique unique))))
|
||||
(magit-insert-section (org-roam-backlinks)
|
||||
(magit-insert-heading "Backlinks:")
|
||||
(dolist (backlink backlinks)
|
||||
@ -622,7 +657,7 @@ References from FILE are excluded."
|
||||
(shell-command-to-string "rg --pcre2-version"))))
|
||||
(let* ((titles (cons (org-roam-node-title node)
|
||||
(org-roam-node-aliases node)))
|
||||
(rg-command (concat "rg -o --vimgrep -P -i "
|
||||
(rg-command (concat "rg -L -o --vimgrep -P -i "
|
||||
(mapconcat (lambda (glob) (concat "-g " glob))
|
||||
(org-roam--list-files-search-globs org-roam-file-extensions)
|
||||
" ")
|
||||
@ -643,7 +678,7 @@ References from FILE are excluded."
|
||||
col (string-to-number (match-string 3 line))
|
||||
match (match-string 4 line))
|
||||
(when (and match
|
||||
(not (f-equal-p (org-roam-node-file node) f))
|
||||
(not (file-equal-p (org-roam-node-file node) f))
|
||||
(member (downcase match) (mapcar #'downcase titles)))
|
||||
(magit-insert-section section (org-roam-grep-section)
|
||||
(oset section file f)
|
||||
|
256
org-roam-node.el
256
org-roam-node.el
@ -1,11 +1,11 @@
|
||||
;;; org-roam-node.el --- Interfacing and interacting with nodes -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.1.0
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (magit-section "3.0.0"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
@ -36,8 +36,7 @@
|
||||
|
||||
;;; Options
|
||||
;;;; Completing-read
|
||||
(defcustom org-roam-node-display-template
|
||||
(concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag))
|
||||
(defcustom org-roam-node-display-template "${title}"
|
||||
"Configures display formatting for Org-roam node.
|
||||
Patterns of form \"${field-name:length}\" are interpolated based
|
||||
on the current node.
|
||||
@ -132,7 +131,8 @@ It takes a single argument REF, which is a propertized string."
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom org-roam-extract-new-file-path "%<%Y%m%d%H%M%S>-${slug}.org"
|
||||
"The file path to use when a node is extracted to its own file."
|
||||
"The file path template to use when a node is extracted to its own file.
|
||||
This path is relative to `org-roam-directory'."
|
||||
:group 'org-roam
|
||||
:type 'string)
|
||||
|
||||
@ -175,6 +175,7 @@ It takes a single argument REF, which is a propertized string."
|
||||
776 ; U+0308 COMBINING DIAERESIS
|
||||
777 ; U+0309 COMBINING HOOK ABOVE
|
||||
778 ; U+030A COMBINING RING ABOVE
|
||||
779 ; U+030B COMBINING DOUBLE ACUTE ACCENT
|
||||
780 ; U+030C COMBINING CARON
|
||||
795 ; U+031B COMBINING HORN
|
||||
803 ; U+0323 COMBINING DOT BELOW
|
||||
@ -186,14 +187,12 @@ It takes a single argument REF, which is a propertized string."
|
||||
816 ; U+0330 COMBINING TILDE BELOW
|
||||
817 ; U+0331 COMBINING MACRON BELOW
|
||||
)))
|
||||
(cl-flet* ((nonspacing-mark-p (char)
|
||||
(memq char slug-trim-chars))
|
||||
(strip-nonspacing-marks (s)
|
||||
(string-glyph-compose
|
||||
(apply #'string (seq-remove #'nonspacing-mark-p
|
||||
(string-glyph-decompose s)))))
|
||||
(cl-replace (title pair)
|
||||
(replace-regexp-in-string (car pair) (cdr pair) title)))
|
||||
(cl-flet* ((nonspacing-mark-p (char) (memq char slug-trim-chars))
|
||||
(strip-nonspacing-marks (s) (string-glyph-compose
|
||||
(apply #'string
|
||||
(seq-remove #'nonspacing-mark-p
|
||||
(string-glyph-decompose s)))))
|
||||
(cl-replace (title pair) (replace-regexp-in-string (car pair) (cdr pair) title)))
|
||||
(let* ((pairs `(("[^[:alnum:][:digit:]]" . "_") ;; convert anything not alphanumeric
|
||||
("__*" . "_") ;; remove sequential underscores
|
||||
("^_" . "") ;; remove starting underscore
|
||||
@ -426,19 +425,41 @@ GROUP BY id")))
|
||||
all-titles)))))
|
||||
|
||||
;;;; Finders
|
||||
(defun org-roam-node-find-noselect (node &optional force)
|
||||
"Navigate to the point for NODE, and return the buffer.
|
||||
If NODE is already visited, this won't automatically move the
|
||||
point to the beginning of the NODE, unless FORCE is non-nil."
|
||||
(unless (org-roam-node-file node)
|
||||
(user-error "Node does not have corresponding file"))
|
||||
(let ((buf (find-file-noselect (org-roam-node-file node))))
|
||||
(with-current-buffer buf
|
||||
(when (or force
|
||||
(not (equal (org-roam-node-id node)
|
||||
(org-roam-id-at-point))))
|
||||
(goto-char (org-roam-node-point node))))
|
||||
buf))
|
||||
(defun org-roam-node-marker (node)
|
||||
"Get the marker for NODE."
|
||||
(unwind-protect
|
||||
(let* ((file (org-roam-node-file node))
|
||||
(buffer (or (find-buffer-visiting file)
|
||||
(find-file-noselect file))))
|
||||
(with-current-buffer buffer
|
||||
(move-marker (make-marker) (org-roam-node-point node) buffer)))))
|
||||
|
||||
(defun org-roam-node-open (node &optional cmd force)
|
||||
"Go to the node NODE.
|
||||
CMD is the command used to display the buffer. If not provided,
|
||||
`org-link-frame-setup' is respected. Assumes that the node is
|
||||
fully populated, with file and point. If NODE is already visited,
|
||||
this won't automatically move the point to the beginning of the
|
||||
NODE, unless FORCE is non-nil."
|
||||
(interactive (list (org-roam-node-at-point) current-prefix-arg))
|
||||
(org-mark-ring-push)
|
||||
(let ((m (org-roam-node-marker node))
|
||||
(cmd (or cmd
|
||||
(cdr
|
||||
(assq
|
||||
(cdr (assq 'file org-link-frame-setup))
|
||||
'((find-file . switch-to-buffer)
|
||||
(find-file-other-window . switch-to-buffer-other-window)
|
||||
(find-file-other-frame . switch-to-buffer-other-frame))))
|
||||
'switch-to-buffer-other-window)))
|
||||
(if (not (equal (current-buffer) (marker-buffer m)))
|
||||
(funcall cmd (marker-buffer m)))
|
||||
(when (or force
|
||||
(not (equal (org-roam-node-id node)
|
||||
(org-roam-id-at-point))))
|
||||
(goto-char m))
|
||||
(move-marker m nil))
|
||||
(org-show-context))
|
||||
|
||||
(defun org-roam-node-visit (node &optional other-window force)
|
||||
"From the current buffer, visit NODE. Return the visited buffer.
|
||||
@ -450,13 +471,10 @@ If NODE is already visited, this won't automatically move the
|
||||
point to the beginning of the NODE, unless FORCE is non-nil. In
|
||||
interactive calls FORCE always set to t."
|
||||
(interactive (list (org-roam-node-at-point t) current-prefix-arg t))
|
||||
(let ((buf (org-roam-node-find-noselect node force))
|
||||
(display-buffer-fn (if other-window
|
||||
(org-roam-node-open node (if other-window
|
||||
#'switch-to-buffer-other-window
|
||||
#'pop-to-buffer-same-window)))
|
||||
(funcall display-buffer-fn buf)
|
||||
(when (org-invisible-p) (org-show-context))
|
||||
buf))
|
||||
#'pop-to-buffer-same-window)
|
||||
force))
|
||||
|
||||
;;;###autoload
|
||||
(cl-defun org-roam-node-find (&optional other-window initial-input filter-fn &key templates)
|
||||
@ -477,16 +495,16 @@ The TEMPLATES, if provided, override the list of capture templates (see
|
||||
:props '(:finalize find-file)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-roam-node-random (&optional other-window)
|
||||
(defun org-roam-node-random (&optional other-window filter-fn)
|
||||
"Find and open a random Org-roam node.
|
||||
With prefix argument OTHER-WINDOW, visit the node in another
|
||||
window instead."
|
||||
window instead.
|
||||
FILTER-FN is a function to filter out nodes: it takes an `org-roam-node',
|
||||
and when nil is returned the node will be filtered out."
|
||||
(interactive current-prefix-arg)
|
||||
(let ((random-row (seq-random-elt (org-roam-db-query [:select [id file pos] :from nodes]))))
|
||||
(org-roam-node-visit (org-roam-node-create :id (nth 0 random-row)
|
||||
:file (nth 1 random-row)
|
||||
:point (nth 2 random-row))
|
||||
other-window)))
|
||||
(org-roam-node-visit
|
||||
(cdr (seq-random-elt (org-roam-node-read--completions filter-fn)))
|
||||
other-window))
|
||||
|
||||
;;;; Completing-read interface
|
||||
(defun org-roam-node-read (&optional initial-input filter-fn sort-fn require-match prompt)
|
||||
@ -498,17 +516,7 @@ SORT-FN is a function to sort nodes. See `org-roam-node-read-sort-by-file-mtime'
|
||||
for an example sort function.
|
||||
If REQUIRE-MATCH, the minibuffer prompt will require a match.
|
||||
PROMPT is a string to show at the beginning of the mini-buffer, defaulting to \"Node: \""
|
||||
(let* ((nodes (org-roam-node-read--completions))
|
||||
(nodes (if filter-fn
|
||||
(cl-remove-if-not
|
||||
(lambda (n) (funcall filter-fn (cdr n)))
|
||||
nodes)
|
||||
nodes))
|
||||
(sort-fn (or sort-fn
|
||||
(when org-roam-node-default-sort
|
||||
(intern (concat "org-roam-node-read-sort-by-"
|
||||
(symbol-name org-roam-node-default-sort))))))
|
||||
(_ (when sort-fn (setq nodes (seq-sort sort-fn nodes))))
|
||||
(let* ((nodes (org-roam-node-read--completions filter-fn sort-fn))
|
||||
(prompt (or prompt "Node: "))
|
||||
(node (completing-read
|
||||
prompt
|
||||
@ -529,15 +537,31 @@ PROMPT is a string to show at the beginning of the mini-buffer, defaulting to \"
|
||||
(or (cdr (assoc node nodes))
|
||||
(org-roam-node-create :title node))))
|
||||
|
||||
(defun org-roam-node-read--completions ()
|
||||
(defun org-roam-node-read--completions (&optional filter-fn sort-fn)
|
||||
"Return an alist for node completion.
|
||||
The car is the displayed title or alias for the node, and the cdr
|
||||
is the `org-roam-node'.
|
||||
FILTER-FN is a function to filter out nodes: it takes an `org-roam-node',
|
||||
and when nil is returned the node will be filtered out.
|
||||
SORT-FN is a function to sort nodes. See `org-roam-node-read-sort-by-file-mtime'
|
||||
for an example sort function.
|
||||
The displayed title is formatted according to `org-roam-node-display-template'."
|
||||
(let ((template (org-roam-node--process-display-format org-roam-node-display-template))
|
||||
(nodes (org-roam-node-list)))
|
||||
(mapcar (lambda (node)
|
||||
(org-roam-node-read--to-candidate node template)) nodes)))
|
||||
(let* ((template (org-roam-node--process-display-format org-roam-node-display-template))
|
||||
(nodes (org-roam-node-list))
|
||||
(nodes (mapcar (lambda (node)
|
||||
(org-roam-node-read--to-candidate node template)) nodes))
|
||||
(nodes (if filter-fn
|
||||
(cl-remove-if-not
|
||||
(lambda (n) (funcall filter-fn (cdr n)))
|
||||
nodes)
|
||||
nodes))
|
||||
(sort-fn (or sort-fn
|
||||
(when org-roam-node-default-sort
|
||||
(intern (concat "org-roam-node-read-sort-by-"
|
||||
(symbol-name org-roam-node-default-sort))))))
|
||||
(nodes (if sort-fn (seq-sort sort-fn nodes)
|
||||
nodes)))
|
||||
nodes))
|
||||
|
||||
(defun org-roam-node-read--to-candidate (node template)
|
||||
"Return a minibuffer completion candidate given NODE.
|
||||
@ -545,7 +569,8 @@ TEMPLATE is the processed template used to format the entry."
|
||||
(let ((candidate-main (org-roam-node--format-entry
|
||||
template
|
||||
node
|
||||
(1- (frame-width)))))
|
||||
(1- (if (bufferp (current-buffer))
|
||||
(window-width) (frame-width))))))
|
||||
(cons (propertize candidate-main 'node node) node)))
|
||||
|
||||
(defun org-roam-node--format-entry (template node &optional width)
|
||||
@ -663,9 +688,13 @@ The INFO, if provided, is passed to the underlying `org-roam-capture-'."
|
||||
(delete-region beg end)
|
||||
(set-marker beg nil)
|
||||
(set-marker end nil))
|
||||
(insert (org-link-make-string
|
||||
(concat "id:" (org-roam-node-id node))
|
||||
description)))
|
||||
(let ((id (org-roam-node-id node)))
|
||||
(insert (org-link-make-string
|
||||
(concat "id:" id)
|
||||
description))
|
||||
(run-hook-with-args 'org-roam-post-node-insert-hook
|
||||
id
|
||||
description)))
|
||||
(org-roam-capture-
|
||||
:node node
|
||||
:info info
|
||||
@ -673,31 +702,10 @@ The INFO, if provided, is passed to the underlying `org-roam-capture-'."
|
||||
:props (append
|
||||
(when (and beg end)
|
||||
(list :region (cons beg end)))
|
||||
(list :insert-at (point-marker)
|
||||
:link-description description
|
||||
(list :link-description description
|
||||
:finalize 'insert-link))))))
|
||||
(deactivate-mark)))
|
||||
|
||||
(add-hook 'org-roam-find-file-hook #'org-roam-open-id-with-org-roam-db-h)
|
||||
(defun org-roam-open-id-with-org-roam-db-h ()
|
||||
"Try to open \"id:\" links at point by querying them to the database."
|
||||
(add-hook 'org-open-at-point-functions #'org-roam-open-id-at-point nil t))
|
||||
|
||||
(defun org-roam-open-id-at-point ()
|
||||
"Navigate to \"id:\" link at point using the Org-roam database."
|
||||
(when (org-in-regexp org-link-any-re)
|
||||
(let ((link (match-string 2))
|
||||
id)
|
||||
(when (string-prefix-p "id:" link)
|
||||
(setq id (substring-no-properties link 3))
|
||||
(let ((node (org-roam-populate (org-roam-node-create :id id))))
|
||||
(cond
|
||||
((org-roam-node-file node)
|
||||
(org-mark-ring-push)
|
||||
(org-roam-node-visit node nil 'force)
|
||||
t)
|
||||
(t nil)))))))
|
||||
|
||||
;;;;; [roam:] link
|
||||
(org-link-set-parameters "roam" :follow #'org-roam-link-follow-link)
|
||||
(defun org-roam-link-follow-link (title-or-alias)
|
||||
@ -794,6 +802,8 @@ hence \"everywhere\"."
|
||||
:exclusive 'no))))
|
||||
|
||||
(add-hook 'org-roam-find-file-hook #'org-roam--register-completion-functions-h)
|
||||
(add-hook 'org-roam-indirect-buffer-hook #'org-roam--register-completion-functions-h)
|
||||
|
||||
(defun org-roam--register-completion-functions-h ()
|
||||
"Setup `org-roam-completion-functions' for `completion-at-point'."
|
||||
(dolist (f org-roam-completion-functions)
|
||||
@ -811,7 +821,8 @@ Any tags declared on #+FILETAGS: are transferred to tags on the new top heading.
|
||||
Any top level properties drawers are incorporated into the new heading."
|
||||
(interactive)
|
||||
(org-with-point-at 1
|
||||
(org-map-entries 'org-do-demote)
|
||||
(org-map-region #'org-do-demote
|
||||
(point-min) (point-max))
|
||||
(insert "* "
|
||||
(org-roam--get-keyword "title")
|
||||
"\n")
|
||||
@ -820,21 +831,40 @@ Any top level properties drawers are incorporated into the new heading."
|
||||
(org-roam-erase-keyword "title")
|
||||
(org-roam-erase-keyword "filetags")))
|
||||
|
||||
(defun org-roam--h1-count ()
|
||||
"Count level-1 headings in the current file."
|
||||
(let ((h1-count 0))
|
||||
(org-with-wide-buffer
|
||||
(org-map-region (lambda ()
|
||||
(if (= (org-current-level) 1)
|
||||
(incf h1-count)))
|
||||
(point-min) (point-max))
|
||||
h1-count)))
|
||||
|
||||
(defun org-roam--buffer-promoteable-p ()
|
||||
"Verify that this buffer is promoteable:
|
||||
There is a single level-1 heading
|
||||
and no extra content before the first heading."
|
||||
(and
|
||||
(= (org-roam--h1-count) 1)
|
||||
(org-with-point-at 1 (org-at-heading-p))))
|
||||
|
||||
(defun org-roam-promote-entire-buffer ()
|
||||
"Promote the current buffer.
|
||||
Converts a file containing a headline node at the top to a file
|
||||
Converts a file containing a single level-1 headline node to a file
|
||||
node."
|
||||
(interactive)
|
||||
(unless (org-roam--buffer-promoteable-p)
|
||||
(user-error "Cannot promote: multiple root headings or there is extra file-level text"))
|
||||
(org-with-point-at 1
|
||||
(org-map-entries (lambda ()
|
||||
(when (> (org-outline-level) 1)
|
||||
(org-do-promote))))
|
||||
(let ((title (nth 4 (org-heading-components)))
|
||||
(tags (nth 5 (org-heading-components))))
|
||||
(beginning-of-line)
|
||||
(kill-line 1)
|
||||
(org-roam-set-keyword "title" title)
|
||||
(when tags (org-roam-set-keyword "filetags" tags)))))
|
||||
(tags (org-get-tags)))
|
||||
(kill-whole-line)
|
||||
(org-roam-end-of-meta-data)
|
||||
(insert "#+title: " title "\n")
|
||||
(when tags (org-roam-tag-add tags))
|
||||
(org-map-region #'org-promote (point-min) (point-max))
|
||||
(org-roam-db-update-file))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-roam-refile ()
|
||||
@ -920,53 +950,21 @@ If region is active, then use it instead of the node at point."
|
||||
(t (let ((r (read-from-minibuffer (format "%s: " key) default-val)))
|
||||
(plist-put template-info ksym r)
|
||||
r)))))))
|
||||
(file-path (read-file-name "Extract node to: "
|
||||
(file-name-as-directory org-roam-directory) template nil template)))
|
||||
(file-path
|
||||
(expand-file-name
|
||||
(read-file-name "Extract node to: "
|
||||
(file-name-as-directory org-roam-directory) template nil template)
|
||||
org-roam-directory)))
|
||||
(when (file-exists-p file-path)
|
||||
(user-error "%s exists. Aborting" file-path))
|
||||
(org-cut-subtree)
|
||||
(save-buffer)
|
||||
(with-current-buffer (find-file-noselect file-path)
|
||||
(org-paste-subtree)
|
||||
(while (> (org-current-level) 1) (org-promote-subtree))
|
||||
(org-roam-promote-entire-buffer)
|
||||
(save-buffer)))))
|
||||
|
||||
;;; IDs
|
||||
;;;; Getters
|
||||
(defun org-roam-id-at-point ()
|
||||
"Return the ID at point, if any.
|
||||
Recursively traverses up the headline tree to find the
|
||||
first encapsulating ID."
|
||||
(org-with-wide-buffer
|
||||
(org-back-to-heading-or-point-min t)
|
||||
(while (and (not (org-roam-db-node-p))
|
||||
(not (bobp)))
|
||||
(org-roam-up-heading-or-point-min))
|
||||
(when (org-roam-db-node-p)
|
||||
(org-id-get))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-roam-update-org-id-locations (&rest directories)
|
||||
"Scan Org-roam files to update `org-id' related state.
|
||||
This is like `org-id-update-id-locations', but will automatically
|
||||
use the currently bound `org-directory' and `org-roam-directory'
|
||||
along with DIRECTORIES (if any), where the lookup for files in
|
||||
these directories will be always recursive.
|
||||
|
||||
Note: Org-roam doesn't have hard dependency on
|
||||
`org-id-locations-file' to lookup IDs for nodes that are stored
|
||||
in the database, but it still tries to properly integrates with
|
||||
`org-id'. This allows the user to cross-reference IDs outside of
|
||||
the current `org-roam-directory', and also link with \"id:\"
|
||||
links to headings/files within the current `org-roam-directory'
|
||||
that are excluded from identification in Org-roam as
|
||||
`org-roam-node's, e.g. with \"ROAM_EXCLUDE\" property."
|
||||
(interactive)
|
||||
(cl-loop for dir in (cons org-roam-directory directories)
|
||||
for org-roam-directory = dir
|
||||
nconc (org-roam-list-files) into files
|
||||
finally (org-id-update-id-locations files org-roam-verbose)))
|
||||
|
||||
;;; Refs
|
||||
;;;; Completing-read interface
|
||||
(defun org-roam-ref-read (&optional initial-input filter-fn)
|
||||
|
@ -1,11 +1,11 @@
|
||||
;;; org-roam-utils.el --- Utilities for Org-roam -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.1.0
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
@ -52,6 +52,16 @@
|
||||
(org-roam-replace-string "\\" "\\\\")
|
||||
(org-roam-replace-string "\"" "\\\"")))
|
||||
|
||||
(defun org-roam-word-wrap (len s)
|
||||
"If S is longer than LEN, wrap the words with newlines."
|
||||
(declare (side-effect-free t))
|
||||
(save-match-data
|
||||
(with-temp-buffer
|
||||
(insert s)
|
||||
(let ((fill-column len))
|
||||
(fill-region (point-min) (point-max)))
|
||||
(buffer-substring (point-min) (point-max)))))
|
||||
|
||||
(defun org-roam-string-equal (s1 s2)
|
||||
"Return t if S1 and S2 are equal.
|
||||
Like `string-equal', but case-insensitive."
|
||||
@ -59,6 +69,15 @@ Like `string-equal', but case-insensitive."
|
||||
(or (string-equal s1 s2)
|
||||
(string-equal (downcase s1) (downcase s2)))))
|
||||
|
||||
(defun org-roam-whitespace-content (s)
|
||||
"Return the whitespace content at the end of S."
|
||||
(with-temp-buffer
|
||||
(let ((c 0))
|
||||
(insert s)
|
||||
(skip-chars-backward " \t\n")
|
||||
(buffer-substring-no-properties
|
||||
(point) (point-max)))))
|
||||
|
||||
(defun org-roam-strip-comments (s)
|
||||
"Strip Org comments from string S."
|
||||
(with-temp-buffer
|
||||
@ -99,6 +118,12 @@ SPEC is a list, as per `dolist'."
|
||||
`(dolist ,spec ,@body)))
|
||||
|
||||
;;; File utilities
|
||||
(defun org-roam-descendant-of-p (a b)
|
||||
"Return t if A is descendant of B."
|
||||
(unless (equal (file-truename a) (file-truename b))
|
||||
(string-prefix-p (replace-regexp-in-string "^\\([A-Za-z]\\):" 'downcase (expand-file-name b) t t)
|
||||
(replace-regexp-in-string "^\\([A-Za-z]\\):" 'downcase (expand-file-name a) t t))))
|
||||
|
||||
(defmacro org-roam-with-file (file keep-buf-p &rest body)
|
||||
"Execute BODY within FILE.
|
||||
If FILE is nil, execute BODY in the current buffer.
|
||||
@ -119,7 +144,8 @@ Kills the buffer if KEEP-BUF-P is nil, and FILE is not yet visited."
|
||||
(delay-mode-hooks
|
||||
(let ((org-inhibit-startup t)
|
||||
(org-agenda-files nil))
|
||||
(org-mode))))
|
||||
(org-mode)
|
||||
(hack-local-variables))))
|
||||
(setq res (progn ,@body))
|
||||
(unless (and new-buf (not ,keep-buf-p))
|
||||
(save-buffer)))
|
||||
@ -460,7 +486,8 @@ See <https://github.com/raxod502/straight.el/issues/520>."
|
||||
'("Doom" "Spacemacs" "N/A" "I don't know"))
|
||||
(quit "N/A"))))
|
||||
(insert (format "- Org: %s\n" (org-version nil 'full)))
|
||||
(insert (format "- Org-roam: %s" (org-roam-version)))))
|
||||
(insert (format "- Org-roam: %s" (org-roam-version)))
|
||||
(insert (format "- sqlite-connector: %s" org-roam-database-connector))))
|
||||
|
||||
|
||||
(provide 'org-roam-utils)
|
||||
|
48
org-roam.el
48
org-roam.el
@ -1,12 +1,12 @@
|
||||
;;; org-roam.el --- A database abstraction layer for Org-mode -*- coding: utf-8; lexical-binding: t; -*-
|
||||
|
||||
;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/org-roam/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 2.1.0
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
|
||||
;; Version: 2.2.1
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
|
||||
@ -71,7 +71,6 @@
|
||||
;; majority of them can be found at https://github.com/org-roam and MELPA.
|
||||
;;
|
||||
;;; Code:
|
||||
(require 'f)
|
||||
(require 'dash)
|
||||
|
||||
(require 'rx)
|
||||
@ -84,6 +83,7 @@
|
||||
(require 'emacsql-sqlite)
|
||||
|
||||
(require 'org)
|
||||
(require 'org-attach) ; To set `org-attach-id-dir'
|
||||
(require 'org-id)
|
||||
(require 'ol)
|
||||
(require 'org-element)
|
||||
@ -123,6 +123,12 @@ All Org files, at any level of nesting, are considered part of the Org-roam."
|
||||
:group 'org-roam
|
||||
:type 'hook)
|
||||
|
||||
(defcustom org-roam-post-node-insert-hook nil
|
||||
"Hook run when an Org-roam node is inserted as an Org link.
|
||||
Each function takes two arguments: the id of the node, and the link description."
|
||||
:group 'org-roam
|
||||
:type 'hook)
|
||||
|
||||
(defcustom org-roam-file-extensions '("org")
|
||||
"List of file extensions to be included by Org-Roam.
|
||||
While a file extension different from \".org\" may be used, the
|
||||
@ -131,9 +137,11 @@ responsibility to ensure that."
|
||||
:type '(repeat string)
|
||||
:group 'org-roam)
|
||||
|
||||
(defcustom org-roam-file-exclude-regexp nil
|
||||
(defcustom org-roam-file-exclude-regexp (list org-attach-id-dir)
|
||||
"Files matching this regular expression are excluded from the Org-roam."
|
||||
:type '(choice
|
||||
(repeat
|
||||
(string :tag "Regular expression matching files to ignore"))
|
||||
(string :tag "Regular expression matching files to ignore")
|
||||
(const :tag "Include everything" nil))
|
||||
:group 'org-roam)
|
||||
@ -188,14 +196,25 @@ FILE is an Org-roam file if:
|
||||
(ext (when path (org-roam--file-name-extension path)))
|
||||
(ext (if (string= ext "gpg")
|
||||
(org-roam--file-name-extension (file-name-sans-extension path))
|
||||
ext)))
|
||||
ext))
|
||||
(org-roam-dir-p (org-roam-descendant-of-p path org-roam-directory))
|
||||
(valid-file-ext-p (member ext org-roam-file-extensions))
|
||||
(match-exclude-regexp-p
|
||||
(cond
|
||||
((not org-roam-file-exclude-regexp) nil)
|
||||
((stringp org-roam-file-exclude-regexp)
|
||||
(string-match-p org-roam-file-exclude-regexp path))
|
||||
((listp org-roam-file-exclude-regexp)
|
||||
(let (is-match)
|
||||
(dolist (exclude-re org-roam-file-exclude-regexp)
|
||||
(setq is-match (or is-match (string-match-p exclude-re path))))
|
||||
is-match)))))
|
||||
(save-match-data
|
||||
(and
|
||||
path
|
||||
(member ext org-roam-file-extensions)
|
||||
(not (and org-roam-file-exclude-regexp
|
||||
(string-match-p org-roam-file-exclude-regexp path)))
|
||||
(f-descendant-of-p path (expand-file-name org-roam-directory))))))
|
||||
org-roam-dir-p
|
||||
valid-file-ext-p
|
||||
(not match-exclude-regexp-p)))))
|
||||
|
||||
(defun org-roam-list-files ()
|
||||
"Return a list of all Org-roam files under `org-roam-directory'.
|
||||
@ -260,7 +279,8 @@ If no files are found, an empty list is returned."
|
||||
(shell-command-to-string it)
|
||||
(ansi-color-filter-apply it)
|
||||
(split-string it "\n")
|
||||
(seq-filter #'s-present? it)))
|
||||
(seq-filter (lambda (s)
|
||||
(not (or (null s) (string= "" s)))) it)))
|
||||
|
||||
(defun org-roam--list-files-search-globs (exts)
|
||||
"Given EXTS, return a list of search globs.
|
||||
@ -279,8 +299,8 @@ E.g. (\".org\") => (\"*.org\" \"*.org.gpg\")"
|
||||
(defun org-roam--list-files-fd (executable dir)
|
||||
"Return all Org-roam files under DIR, using \"fd\", provided as EXECUTABLE."
|
||||
(let* ((globs (org-roam--list-files-search-globs org-roam-file-extensions))
|
||||
(extensions (string-join (mapcar (lambda (glob) (substring glob 2 -1)) globs) " -e "))
|
||||
(command (string-join `(,executable "-L" ,dir "--type file" ,extensions) " ")))
|
||||
(extensions (string-join (mapcar (lambda (glob) (concat "-e " (substring glob 2 -1))) globs) " "))
|
||||
(command (string-join `(,executable "-L" "--type file" ,extensions "." ,dir) " ")))
|
||||
(org-roam--shell-command-files command)))
|
||||
|
||||
(defalias 'org-roam--list-files-fdfind #'org-roam--list-files-fd)
|
||||
@ -313,8 +333,10 @@ E.g. (\".org\") => (\"*.org\" \"*.org.gpg\")"
|
||||
(require 'org-roam-utils)
|
||||
(require 'org-roam-db)
|
||||
(require 'org-roam-node)
|
||||
(require 'org-roam-id)
|
||||
(require 'org-roam-capture)
|
||||
(require 'org-roam-mode)
|
||||
(require 'org-roam-log)
|
||||
(require 'org-roam-migrate))
|
||||
|
||||
;;; org-roam.el ends here
|
||||
|
56
tests/test-org-roam-capture.el
Normal file
56
tests/test-org-roam-capture.el
Normal file
@ -0,0 +1,56 @@
|
||||
;;; test-org-roam-capture.el --- Tests for Org-roam -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2020 Jethro Kuan
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Package-Requires: ((buttercup))
|
||||
|
||||
;; 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 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;; Code:
|
||||
|
||||
(require 'buttercup)
|
||||
(require 'org-roam)
|
||||
|
||||
(describe "org-roam-capture--fill-template"
|
||||
(it "fills template without newline"
|
||||
(expect
|
||||
(org-roam-capture--fill-template "foo")
|
||||
:to-equal "foo"))
|
||||
|
||||
(it "fills template ensuring newline"
|
||||
(expect
|
||||
(org-roam-capture--fill-template "foo" 'ensure-newline)
|
||||
:to-equal "foo\n"))
|
||||
|
||||
(it "fills template with newline"
|
||||
(expect
|
||||
(org-roam-capture--fill-template "foo\n")
|
||||
:to-equal "foo\n"))
|
||||
|
||||
(it "fills template with two newlines"
|
||||
(expect
|
||||
(org-roam-capture--fill-template "foo\n\n")
|
||||
:to-equal "foo\n\n")
|
||||
(expect
|
||||
(org-roam-capture--fill-template "foo\n\t\n")
|
||||
:to-equal "foo\n\t\n"))
|
||||
|
||||
(it "expands templates when it's a function"
|
||||
(expect
|
||||
(org-roam-capture--fill-template (lambda () "foo"))
|
||||
:to-equal "foo")))
|
||||
|
||||
(provide 'test-org-roam-capture)
|
39
tests/test-org-roam-utils.el
Normal file
39
tests/test-org-roam-utils.el
Normal file
@ -0,0 +1,39 @@
|
||||
;;; test-org-roam-utils.el --- Tests for Org-roam -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2020 Jethro Kuan
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Package-Requires: ((buttercup))
|
||||
|
||||
;; 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 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;; Code:
|
||||
|
||||
(require 'buttercup)
|
||||
(require 'org-roam)
|
||||
|
||||
(describe "org-roam-whitespace-content"
|
||||
(it "extracts whitespace correctly"
|
||||
(expect
|
||||
(org-roam-whitespace-content "foo")
|
||||
:to-equal "")
|
||||
(expect
|
||||
(org-roam-whitespace-content "foo\n")
|
||||
:to-equal "\n")
|
||||
(expect
|
||||
(org-roam-whitespace-content "foo\n\t\n")
|
||||
:to-equal "\n\t\n")))
|
||||
|
||||
(provide 'test-org-roam-utils)
|
Reference in New Issue
Block a user