Compare commits

...

126 Commits

Author SHA1 Message Date
27a63b59b1 (release): 1.1.0: update version headers in source (#502) 2020-04-21 20:50:24 +08:00
339336a27f (release): 1.1.0 (#501) 2020-04-21 20:43:21 +08:00
a35454bb7e (internal): Simplify org-roam--list-files implementation. (#497)
Use destructive elisp functions to optimize for speed and memory
usage.

Refs #104
2020-04-20 18:28:33 +08:00
N V
228af5b6be (fix): Remove old definition of org-roam-graph--open (#498)
Fixes #496
2020-04-20 02:24:18 +08:00
89b941a207 (feat) implement after-find-file-hook for org-roam-capture (#482)
Allows user to run functions when an `org-roam-capture` is successful.  This
might come in handy for moving point after finding the new file, since right
now, it is at `(point-min)`.
2020-04-19 22:45:09 +08:00
N V
258d6f8a52 (feat): Allow function for org-roam-graph-viewer (#488)
User may specify a function to open the org-roam graph.
Adds more error handling to org-roam-graph--open.

See #440
2020-04-19 19:00:33 +08:00
N V
dc65e58405 (refactor): org-roam-graph (#490)
- Consolidate graph build/display commands into org-roam-graph command
  See #450
- Require org-roam-db
  Rather than declaring its functions.
- Move obsolete variable org-roam-graph-node-shape to org-roam-compat
- org-roam-graph--build-connected-component accepts a file argument
  Allows building a graph without having the target file as the current
  buffer
- Eliminate repeating code
- Fix checkdoc warnings
2020-04-19 15:04:24 +08:00
de4f5477d8 (feat): Use TITLE as description when linking before first heading (#491)
Fixes #487
2020-04-19 00:41:38 +08:00
9e138e259a (feat) remove user-error for org-roam-insert (#486)
* (feat) remove user-error for org-roam-insert

Closes #477.

* (fix) use absolute path when buffer has no associated file

Co-authored-by: Jethro Kuan <jethrokuan95@gmail.com>
2020-04-18 13:10:14 +08:00
ba80a31fe0 (feat): add optional FILTER-FN argument for org-roam-find-file and org-roam-insert (#481) 2020-04-18 04:54:17 +08:00
6175739b33 (docs) Provide examples of using template expansion and function overrides. (#478) 2020-04-17 18:31:39 +08:00
35b20de45f (fix): ensure that directory exists before capturing to dir (#476)
Co-authored-by: Jethro Kuan <jethrokuan95@gmail.com>
2020-04-17 12:39:03 +08:00
06afa27725 (docs): export: add snippet for backlinks with contents. (#466) 2020-04-17 12:34:40 +08:00
e1873a6a16 (internal): extract daily notes functionality (#473)
Beyond just an extraction, this is also a simplification. It removes two
variables: `org-roam-date-filename-format` and
`org-roam-date-title-format`, in favour of directly specifying them in
the `org-roam-dailies-capture-templates`.

`org-roam--file-for-time` is also vastly simplified to use org-capture's
default time expansion utilities, by setting the capture template's
`:default-time` appropriately.
2020-04-17 03:25:16 +08:00
e33c144298 (bugfix): add workaround for undocumented file-truename behavior (#470)
This prevents and error being generated when the agenda is displayed.

Fixes #408
2020-04-16 02:53:43 +08:00
ea1ba21825 (chore): inline links in changelog (#467)
I had initially thought that keeping them separate would be cleaner, but
it's very easy to forget to add the links at the bottom of the
changelog. Relevant emacs-lisp that did this:

(replace-regexp "\\[gh-\\([0-9]+\\)\\]" "(https://github.com/jethrokuan/org-roam/pull/\\1)")
2020-04-15 15:28:47 +08:00
d7fc91e047 (feat): Add support for different file extensions (#465)
Adds `org-roam-file-extensions`, which allows org-roam to detect file extensions other than .org. Fixes #461
2020-04-15 15:02:05 +08:00
a4a2ac8d19 Use MELPA for installing in Spacemacs (#462)
Now that org-roam is out on MELPA, let's suggest that people use it
instead of GitHub to install the package.

Co-authored-by: Jethro Kuan <jethrokuan95@gmail.com>
2020-04-15 14:34:23 +08:00
f79ee9e850 Correct database query function (#463)
`org-roam-sql` is obsolete now. Also changed the syntax that works for the new `org-roam-db-query` function.
2020-04-15 14:09:58 +08:00
a71176ee40 (docs): mention company-org-roam in documentation (#457) 2020-04-14 17:00:13 +08:00
6bdde3a634 (bugfix): fix org-roam-graph--open (#456) 2020-04-14 16:31:14 +08:00
b33300a23d (docs): fix broken format in win-install doc (#438) (#451) 2020-04-14 13:17:05 +08:00
N V
8c7bc09f9b (fix): Use make-temp-file in org-roam-graph-build (#454)
Create a new temporary file for each graph that is built.

See: #453
2020-04-14 13:14:23 +08:00
0a9ca736e4 (docs): fix small typo (#445)
Co-authored-by: Jethro Kuan <jethrokuan95@gmail.com>
2020-04-13 14:55:12 +08:00
N V
3506f16648 (fix): org-roam.el eval-when-compile subr-x (#449) 2020-04-13 12:12:30 +08:00
772505ba70 (bugfix): Explicitly load subr-x library (#429)
Ensure the `if-let*` macro definitions is available during compile-time
2020-04-12 17:18:09 +08:00
6392a8b5df (docs): fix broken format+typo in win-install (#438) (#444)
Co-authored-by: nobiot <me@nobiot.com>
2020-04-12 17:05:27 +08:00
580a320c66 (feat): graph: add cite links to graph (#439) 2020-04-12 14:38:58 +08:00
0e79bbb75a (doc) add Windows installation instruction (#397) (#438)
Co-authored-by: nobiot <me@nobiot.com>
2020-04-12 11:35:42 +08:00
4af4d2e4d5 (feat): split building and showing of the graph into two functions (#426) 2020-04-11 16:41:49 +08:00
N V
18939fcccd (doc): ref-capture-templates > capture-ref-templates (#433)
See: #430
2020-04-11 16:38:46 +08:00
1b13c426aa (feat): add org-roam-graph-edge-extra-config (#435)
Introduces `org-roam-graph-edge-extra-config` to add options to edges
2020-04-11 13:41:21 +08:00
N V
bee8e506c2 (refactor): Move obsolete vars/functions to org-roam-compat (#434) 2020-04-11 13:25:12 +08:00
c280f249a9 (fix) typo in doc, titles -> refs (#436) 2020-04-11 12:36:59 +08:00
ba1782d361 (feat): graph of bfs from given node (#418) 2020-04-11 04:20:43 +08:00
e327fb3f0c (fix): reuse variable defined in let-form (#431)
Co-authored-by: Jethro Kuan <jethrokuan95@gmail.com>
2020-04-11 04:13:16 +08:00
N V
40dc3a5af8 (refactor): org-roam-db.el eval-when-compile subr-x (#432)
Prevents unnecessary evaluation when compiled .elc is loaded.
From the commentary of subr-x.el:
;; NB If you want to use this library, it's almost always correct to use:
;; (eval-when-compile (require 'subr-x))

See: #429
2020-04-11 03:55:24 +08:00
05c9e8e2e7 (feat): add org-roam-find-directory (#424) 2020-04-10 20:11:39 +08:00
df20754fb0 (bugfix): Explicitly load subr-x library (#425)
Ensure the `when-let` macro definitions is available during
compile-time.
2020-04-10 19:19:00 +08:00
dddbe286de (feat): add customization to set no-delete-other-windows (#422)
Adds `org-roam-buffer-no-delete-other-windows`, which controls the behaviour of the org-roam buffer side window upon `delete-other-windows`.
2020-04-10 17:50:52 +08:00
92500b1338 (bugfix): Use predicate to check for a org-roam-capture process (#413)
Instead of using a global variable to check for a existing capture,
leverage the :org-roam plist property of the buffer-local variable
`org-roam-capture-current-plist`.

This prevents a lockout if the capture buffer is killed
2020-04-10 17:03:49 +08:00
N V
772504c488 (internal): modularize org-roam-buffer (#406)
Split functionality related to the org-roam-buffer into its own
feature/file.

Introduce `org-roam-buffer-prepare-hook' to allow customizations of the
org-roam-buffer content.

Co-authored-by: Jethro Kuan <jethrokuan95@gmail.com>
2020-04-10 14:38:41 +08:00
6e97003967 (fix): Detect all org-ref cite types (#417) 2020-04-09 12:26:40 +08:00
N V
dd3fd592bb (internal): Move aliases to org-roam-compat.el (#412)
Same strategy Org uses. Consolidates backward compatibility into a
single location. Leverages `define-obsolete-*-alias' macros.
2020-04-09 12:16:22 +08:00
67495e269a (feat): allow creation of connected-component graph (#398) 2020-04-08 10:52:40 +08:00
72faa591fb (docs): fix typo eduring -> during (#405)
Co-authored-by: Jethro Kuan <jethrokuan95@gmail.com>
2020-04-07 15:30:07 +08:00
N V
c7a44b9f12 Move org-roam-capture command to org-roam-capture.el (#407) 2020-04-07 13:53:22 +08:00
5120f8eac3 (chore): update Slack invite link (#403) 2020-04-06 18:23:51 +08:00
e73bc78274 (feat): Add org-ref citation support (#374)
Adds support for org-ref cite: links to the backlinks buffer.

Requires a db-rebuild, since the db schema has changed.
2020-04-06 16:48:17 +08:00
N V
4ca2606a28 (docs): org-roam-db-build-cache (#396)
Remove references to obsolete variable.
org-roam-build-cache -> org-roam-db-build-cache
2020-04-04 03:50:10 +08:00
f9a4f3b7f7 (docs:) spacemacs: replace show-graph with graph-show (#393)
Co-authored-by: Jethro Kuan <jethrokuan95@gmail.com>
2020-04-02 13:40:53 +08:00
8f28bd4ccf (feature): Add numeric prefix argument to org-roam-tomorrow (#392)
Also add prefix argument to `org-roam-yesterday`.

This makes it possible to jump back or forward several days.
2020-04-02 13:32:22 +08:00
N V
dfb8449680 Refactor org-roam--setup-buffer (#388)
Change function name org-roam--setup-buffer org-roam--set-up-buffer.
Warn user and default to 'right when org-roam-buffer-position is
an invalid position.

Make better use of pcase to avoid repeating code.
2020-04-01 13:16:09 +08:00
48ccb084f0 (feat): Cache template variable entry (#387)
Addresses
https://github.com/jethrokuan/org-roam/issues/285#issuecomment-606724827
2020-04-01 12:09:41 +08:00
f27e5f2384 (fix): Undo font locking changes in backlinks buffer (#386) 2020-04-01 11:50:16 +08:00
e4f77eb586 (feat): Add org-roam-graph-node-extra-config (#385)
org-roam-graph-node-extra-config is an alist containing additional node
configuration options, as per
https://graphviz.gitlab.io/_pages/doc/info/attrs.html

This also deprecates org-roam-graph-node-shape, which is a special case
of the node options
2020-04-01 11:36:24 +08:00
2e3119e027 Allow top and bottom placement of the sidebar in addition to left and right (#380)
* Allow placement of the sidebar on top or on bottom

* Add "let_sidebar_be_on_top_or_bottom" to the changelog

* Remove an unnecessary progn and replace an if with a pcase

As requested by jethrokuan in https://github.com/jethrokuan/org-roam/pull/380
comments.
2020-03-31 18:34:23 +08:00
N V
b06e296e88 (chore): update org-roam-graph variable names (#383)
See: https://github.com/jethrokuan/org-roam/issues/382
2020-03-31 16:56:15 +08:00
04acbda916 (docs): simplifying doom installation instructions (#381)
With the new `+roam` flag now added to doom emacs, this simplifies the instructions.
2020-03-31 05:46:46 +08:00
b86d2c8637 (docs): Add Org-roam video (#376) 2020-03-30 02:39:17 +08:00
7dd371c023 (fix?): use helm-make-source instead (#375)
Byte-compiled code should not contain macros.
2020-03-29 21:30:23 +08:00
58c07f74bc (docs): Add note about completion mechanism (#373) 2020-03-29 17:58:49 +08:00
bc28c85dfc (hotfix): move capture in-process setting as late as possible (#372)
This is a hotfix for #369. Currently, calling `org-roam-capture` sets
`org-roam-capture--in-process` to `t`, but cancelling the capture
process does not reset it to `nil`, causing false errors. The whole
nested org-capture processes workaround is brittle, this change moves it
as far back as possible, but the whole thing needs to be redesigned.
2020-03-29 17:52:22 +08:00
b607e56c5f (feat): Add interactive org-roam-capture (#371) 2020-03-29 17:29:57 +08:00
ba835ef624 (fix): Add alias for 'org-roam--capture-get-point (#370)
This ensures custom templates don't break
2020-03-29 17:12:33 +08:00
649af54640 (internal): remove company-org-roam (#368)
company-org-roam is maintained separately, at jethrokuan/company-org-roam.
2020-03-29 14:14:13 +08:00
N V
22b9d4bd22 (internal): modularize features (#363)
Addresses #357
2020-03-28 21:16:28 +08:00
df29da1b6d (feat): add variable for muting messages (#359)
Adds `org-roam-verbose`, which echoes messages that are not errors.
2020-03-27 15:09:52 +08:00
de36d15d0f Turn org-roam-backlinks-mode into a minor mode (#355)
This change makes `org-roam-open-at-point` non-interactive and adds it to
`org-open-at-point-functions`.  As a consequence, `org-open-at-point` will try
to visit an Org-roam link or preview text, before falling back to the default
behavior of Org mode.

Fixes #312.
2020-03-27 13:06:44 +08:00
3e0a49de03 (bugfix): change declare-function for helm-build-sync-source (#354) 2020-03-26 20:17:06 +08:00
3add2c5a8b (feature): add org-roam-db-location (#350)
`org-roam-db-location` sets the location of the Org-roam sqlite database.
2020-03-24 12:22:00 +08:00
4b6f580375 (bugfix): fix org-roam date functions filename format (#349)
Previously the filename was not used in the capture template.
2020-03-24 11:47:40 +08:00
23a8b0d722 Add warning: binding conflict with ranger layer (#348)
This happened to me. The error message and backtrace information were not very clear
2020-03-24 11:16:53 +08:00
1433dbc316 (release): v1.0.0 (#341) 2020-03-23 15:34:21 +08:00
def3d27d25 (internal): small refactor (#340) 2020-03-22 12:12:40 +08:00
6fae1d8100 (chore): update internal Github settings (#339)
Removes sponsor button, and disables 26.3 in testing matrix
2020-03-22 11:37:23 +08:00
07672213b6 (chore): fix bytecompile errors and checkdoc errors (#338) 2020-03-22 03:16:38 +08:00
5406827451 (internal): use org-link-make-string (#337)
This takes care of properly escaping backslashes in file names.
2020-03-22 02:46:36 +08:00
214a8f771f (internal): reduce org-roam capture template key pollution (#336)
Following #332, nest all org-roam related customization in to a single
key.
2020-03-22 00:13:19 +08:00
57f5e73192 (internal): force a reconnect on org-roam-build-cache (#335)
This is to guard against scenarios where a db connection is still live, although it
may already be invalid (like in #331)
2020-03-21 22:30:30 +08:00
1352809451 ensure "%?" is present in the template string (#330)
* ensure "%?" is present in the template string

- addresses #298
- fixes `org-capture-place-plain-text` throwing 'invalid search bound'
  when both :unnarowed t and "%?" is missing from the template string

* ensure "%?" is present in the template string

- if "%?" is missing, add it at the end of the template
2020-03-21 20:56:20 +08:00
N V
8b37135aa2 (internal): refactor to remove hooks in a loop (#334)
Removing hooks in a loop should be easier to extend/maintain.
More "DRY" than repeating calls to `remove-hook'.

Co-authored-by: Jethro Kuan <jethrokuan95@gmail.com>
2020-03-21 12:43:11 +08:00
N V
159e11c842 (internal): update cl.el functions to cl-lib versions (#333)
cl is a deprecated library. cl-lib replaces it.
2020-03-21 12:40:13 +08:00
63b2eaaf86 (bugfix): throw an error on nested org-roam capture processes (#329) 2020-03-20 20:17:56 +08:00
919d08732c (bugfix): fix nested org-roam-inserts not working (#328) 2020-03-20 00:57:32 +08:00
97dfc4b980 (bugfix): fix `org-roam--completing-read' for ido (#324)
For `ido-completing-read', `choices' must be a list of strings
2020-03-19 16:23:04 +08:00
4556f727ff (bugfix): fix org-roam-capture not saving file, and org-roam date functions (#321)
* (bugfix): fix org-roam-captures not saving file

* (bugfix): fix org-roam date functions
2020-03-18 01:11:08 +08:00
6775f15ad1 (bugfix): prevent file open if capture is cancelled (#316) 2020-03-17 17:20:55 +08:00
8f8ccf6797 (feat): clean-ups for org-roam-capture system (#315)
This introduces 2 user-facing changes:

1. If a capture process is aborted, the file is not created if it
doesn't yet exist

2. If a capture process is aborted, org-roam-insert will not insert a
link
2020-03-17 17:06:49 +08:00
81dd880357 (bugfix): fix ugly node labels in org-roam graph (#314) 2020-03-17 13:00:45 +08:00
c14ac7b613 (bugfix): fix Helm completing-read containing extra spaces on non-match (#309) 2020-03-16 17:42:57 +08:00
08667d9c7d (bugfix): Fix Helm integration for completing-read (#306)
Fixes #304, using PR #305 as the base, thanks @khinsen
2020-03-16 13:00:12 +08:00
f544bd9ca1 hexify file url for org-protocol link (#299)
Co-authored-by: Jethro Kuan <jethrokuan95@gmail.com>
2020-03-15 21:55:54 +08:00
66aff57cdb (bugfix): capture: prepend header template only on new file (#302) 2020-03-15 21:50:25 +08:00
f238e3fe02 (feat): order backlinks by filename (#300)
Co-authored-by: Jethro Kuan <jethrokuan95@gmail.com>
2020-03-15 15:26:24 +08:00
98fc273a0f (internal): less abusive use of org-capture (#294)
`org-roam--capture-new-file` does not write anything to a file, all the templating is delegated to vanilla `org-capture`
2020-03-15 13:41:36 +08:00
a4df95b518 Create FUNDING.yml 2020-03-14 17:52:51 +08:00
6f1154c90e (bugfix): remove nonexistent/redundant code (#297) 2020-03-14 14:55:53 +08:00
486ba9c5a8 (feat): upgrade org-roam-graph-exclude-matcher to accept a list (#296)
Closes #295
2020-03-14 01:17:32 +08:00
d28a83c992 (bugfix): fix unintuitive behaviour of capture insertion (#293)
Ref #285
2020-03-13 18:13:04 +08:00
62ed117eb6 (feat): Support multiple org-roam-directories for company backend (#292)
Fixes #276
2020-03-13 14:03:53 +08:00
a44b847596 (docs): add documentation for using neato (#291)
Some prefer using neato for generating a graph (ref #263). This
documents how to do so.
2020-03-13 13:37:55 +08:00
e64890c80e (feat): add org-roam-date-title-format and org-roam-date-filename-format (#290)
This PR supercedes #280. It allows users who use the date
functionality in Org-roam to customize the filename and title formats
of the created files.
2020-03-13 13:29:49 +08:00
4eaf69465e (feat): add 'ido and 'ivy support for completing-read (#289)
Also adds org-roam-fuzzy-match, which for ivy and helm controls
whether completion candidates are fuzzy matched.
2020-03-13 13:11:22 +08:00
0950ae3cc6 (feature): add support for Helm's completion system (#284)
adds org-roam-completion-system, supporting helm as the default completion option.
2020-03-12 19:34:27 +08:00
0cab668d9e (bugfix): propagate org-roam-directory to temp buffers (#275) 2020-03-11 15:41:18 +08:00
6095d01ef4 (feat): add a company-mode for link completion (#257)
Adds company-org-roam, a company backend which autocompletes text into org file links
2020-03-11 14:32:58 +08:00
bd425e4427 (docs):fix typo in platypus installation (#274) 2020-03-11 11:37:01 +08:00
65ead3c9ed (chore): fix more checkdoc errors (#270) 2020-03-11 00:55:42 +08:00
be1d1f1d7b (feat): add org-roam-graphviz-extra-options (#269) 2020-03-11 00:44:07 +08:00
f5d5b83b49 (bugfix): fix missed org-roam-link-title-format uses (#268)
In #261 we allowed org-roam-link-title-format to be a function, but missed some of its uses during the update. h.t. @alanz
2020-03-11 00:34:08 +08:00
8a3945945b (bugfix): emove duplicate line from `org-roam--db-clear' (#267) 2020-03-10 15:35:34 +08:00
7f09c76baf (fix): allow org-roam-insert in Org-roam file indirect buffers (#266) 2020-03-10 10:57:49 +08:00
f6e75f995a (chore): cleanup buffer-file-name calls (#265)
buffer-file-name uses the current-buffer if the argument is not passed
2020-03-10 10:41:43 +08:00
6ba9ffe9c8 (fix): Error if org-roam-insert is not called from Org-roam file (#264) 2020-03-10 10:36:36 +08:00
5e0b7440a3 (feat): Allow function for org-roam-link-title-format (#261)
Addresses #255
2020-03-09 22:18:04 +08:00
d16d001b9e (feat): add optional initial-prompt to org-roam-find-file (#259) 2020-03-09 16:43:48 +08:00
f67e0b025a (docs): fix typo in vanilla installation (#254) 2020-03-08 20:49:17 +08:00
b836f9fc35 (bugfix): Don't query about SQL proccess on Emacs exit (#253)
Graceful shutdown is already guaranteed via `kill-emacs-hook`.

Refs #200

Co-authored-by: Jethro Kuan <jethrokuan95@gmail.com>
2020-03-08 19:57:48 +08:00
e138056115 (docs): fix documentation for manual installation (#252) 2020-03-08 17:43:07 +08:00
63e0558d96 (chore): Cleanups for MELPA release (#251)
* (chore): require minimum Org version 9.3

* fix bytecompile errors for org-roam.el

* fix checkdoc errors

* fix more things
2020-03-08 15:58:13 +08:00
3fccaef967 (chore): change main branch to master (#250) 2020-03-08 15:05:57 +08:00
6eb7238daf (feature): add org-roam-backlink face (#247) 2020-03-08 14:54:56 +08:00
fc79901682 (chore): drop org-roam-filename-noconfirm (#248)
With org-capture integration, it does not seem to be used anymore.
2020-03-08 11:15:41 +08:00
46afa483a9 (docs): add documentation for exporting backlinks in Org file (#244)
h.t. @jdiez17
2020-03-07 23:49:43 +08:00
f63f29ac05 (docs): Add link to slack invite (#242) 2020-03-07 15:05:16 +08:00
25 changed files with 2560 additions and 1326 deletions

View File

@ -38,7 +38,6 @@ jobs:
fail-fast: false
matrix:
emacs_version:
- 26.3
- snapshot
steps:
- uses: purcell/setup-emacs@master

View File

@ -1,5 +1,56 @@
# Changelog
## 1.1.0 (21-04-2020)
To the average user, this release is mainly a bugfix release with additional options to customize. However, the changes made to the source is significant. Most notably, in this release:
1. The codebase has been modularized into separate files, to ease future maintenance and adding of new features (mainly by [@progfolio](https://github.com/progfolio)). Because of these changes, we had to rename many functions and variables: the old names are kept for backwards compatibility, but you are encouraged to use the new function names. You'll receive a warning when you're calling the function with its obsolete name.
2. [@kljohann](https://github.com/kljohann) did some fantastic work on graph generation: allowing building images for connected components within the graph up to a specified distance
3. We also started supporting `org-ref` natively: cite links now show up in both the graph and the org-roam buffer.
In the coming months, you can expect work on bigger projects (e.g. revamping the org-roam buffer).
### Breaking Changes
* [#385](https://github.com/jethrokuan/org-roam/pull/385) Deprecate `org-roam-graph-node-shape` in favour of `org-roam-graph-node-extra-config`.
* [#473](https://github.com/jethrokuan/org-roam/pull/473) Deprecate `org-roam-date-filename-format` and `org-roam-date-title-format`, in favour of `org-roam-dailies-capture-templates`.
### New Features
* [#350](https://github.com/jethrokuan/org-roam/pull/350) Add `org-roam-db-location` to customize location of org-roam database.
* [#359](https://github.com/jethrokuan/org-roam/pull/359) Add `org-roam-verbose` to allow or silence printing of information.
* [#374](https://github.com/jethrokuan/org-roam/pull/374) Add support for `org-ref` `cite:` links
* [#380](https://github.com/jethrokuan/org-roam/pull/380) Allow `org-roam-buffer-position` to also be `top` or `bottom`
* [#385](https://github.com/jethrokuan/org-roam/pull/385) Add `org-roam-graph-node-extra-config` to configure Graphviz nodes
* [#398](https://github.com/jethrokuan/org-roam/pull/398), [#418](https://github.com/jethrokuan/org-roam/pull/418) Add graph building for connected components
* [#435](https://github.com/jethrokuan/org-roam/pull/435) Add `org-roam-graph-edge-extra-config` to configure Graphviz edges
* [#439](https://github.com/jethrokuan/org-roam/pull/439) Add support for `org-ref` citations to display as edges in graph. Add `org-roam-graph-edge-cites-extra-config` to configure these edges
* [#465](https://github.com/jethrokuan/org-roam/pull/465) Add `org-roam-file-extensions` to allow detection of org files with different file extensions
* [#488](https://github.com/jethrokuan/org-roam/pull/488) Allow a function for `org-roam-graph-viewer`
* [#491](https://github.com/jethrokuan/org-roam/pull/491) Use TITLE as description when linking before first heading
### Bugfixes
* [#470](https://github.com/jethrokuan/org-roam/pull/470) Add workaround for undocumented `file-truename` behaviour in `org-roam--org-roam-file-p`.
### Internal Changes
* [#363](https://github.com/jethrokuan/org-roam/pull/363), [#473](https://github.com/jethrokuan/org-roam/pull/473) Modularize org-roam features.
* [#497](https://github.com/jethrokuan/org-roam/pull/497) Simplify `org-roam--list-files` implementation
## 1.0.0 (23-03-2020)
Org-roam is now on MELPA! We have squashed most of the bugs, and Org-roam has
been stable for the most part.
### New Features
* [#269](https://github.com/jethrokuan/org-roam/pull/269) Add `org-roam-graphviz-extra-options`
* [#257](https://github.com/jethrokuan/org-roam/pull/257) Add a company-backend `company-org-roam`
* [#284](https://github.com/jethrokuan/org-roam/pull/284), [#289](https://github.com/jethrokuan/org-roam/pull/289) Configurable `org-roam-completion-system` with options `'default`, `'ido`, `'ivy` and `'helm`
* [#289](https://github.com/jethrokuan/org-roam/pull/289) Add customizable `org-roam-fuzzy-match` to allow fuzzy-matching of candidates
* [#290](https://github.com/jethrokuan/org-roam/pull/290) Add `org-roam-date-title-format` and `org-roam-date-filename-format` for customizing Org-roam's date files
* [#296](https://github.com/jethrokuan/org-roam/pull/296) Allow multiple exclusion matchers in `org-roam-graph-exclude-matcher`
### Bugfixes
* [#293](https://github.com/jethrokuan/org-roam/pull/293) Fix capture templates not working as expected for `org-roam-find-file`
* [#275](https://github.com/jethrokuan/org-roam/pull/275) Fix database rebuild when `org-roam-directory` is set locally
## 1.0.0-rc1 (06-03-2020)
This is a pre-release before the push to MELPA. It contains large
@ -8,18 +59,20 @@ backing storage has been changed to a SQLite database, and a
templating system using `org-capture` is introduced.
### Breaking Changes
* [#200][gh-200] Move Org-roam cache into a SQLite database.
* [#203][gh-203] Roam protocol is deprecated, in favour of extending org-roam-protocol.
* [#200](https://github.com/jethrokuan/org-roam/pull/200) Move Org-roam cache into a SQLite database.
* [#203](https://github.com/jethrokuan/org-roam/pull/203) Roam protocol is deprecated, in favour of extending org-roam-protocol.
### New Features
* [#182][gh-182] Support file name aliases via `#+ROAM_ALIAS`.
* [#216][gh-216] Adds templating functionality by extending org-capture.
* [#232][gh-232] Adds a prefix key to `org-roam-show-graph`, to generate graph without opening it.
* [#233][gh-233] Adds `org-roam-graph-exclude-matcher`, which allows exclusion of nodes from graph.
* [#182](https://github.com/jethrokuan/org-roam/pull/182) Support file name aliases via `#+ROAM_ALIAS`.
* [#216](https://github.com/jethrokuan/org-roam/pull/216) Adds templating functionality by extending org-capture.
* [#232](https://github.com/jethrokuan/org-roam/pull/232) Adds a prefix key to `org-roam-show-graph`, to generate graph without opening it.
* [#233](https://github.com/jethrokuan/org-roam/pull/233) Adds `org-roam-graph-exclude-matcher`, which allows exclusion of nodes from graph.
* [#247](https://github.com/jethrokuan/org-roam/pull/247) Add `org-roam-backlink` face, which allows customizing backlinks appearance
* [#259](https://github.com/jethrokuan/org-roam/pull/259) Add optional initial-prompt to `org-roam-find-file`
### Bugfixes
* [#207][gh-207], [#221][gh-221] small bugfixes to Org-roam graph generation
* [#230][gh-230] remove nonspacing marks from filenames, to prevent cross-platform errors
* [#207](https://github.com/jethrokuan/org-roam/pull/207), [#221](https://github.com/jethrokuan/org-roam/pull/221) small bugfixes to Org-roam graph generation
* [#230](https://github.com/jethrokuan/org-roam/pull/230) remove nonspacing marks from filenames, to prevent cross-platform errors
### New Contributors
* [@acowley][https://github.com/acowley]
@ -28,30 +81,30 @@ templating system using `org-capture` is introduced.
## 0.1.2 (2020-02-21)
### Breaking Changes
* [#143][gh-143] `org-roam-mode` is now a global mode. The installation instructions have changed accordingly.
* [#103][gh-103] Change `org-roam-file-format` to a function: `org-roam-file-name-function` to allow more flexible file name customizaton. Also changes `org-roam-use-timestamp-as-filename` to `org-roam-filename-noconfirm` to better describe what it does.
* [#143](https://github.com/jethrokuan/org-roam/pull/143) `org-roam-mode` is now a global mode. The installation instructions have changed accordingly.
* [#103](https://github.com/jethrokuan/org-roam/pull/103) Change `org-roam-file-format` to a function: `org-roam-file-name-function` to allow more flexible file name customizaton. Also changes `org-roam-use-timestamp-as-filename` to `org-roam-filename-noconfirm` to better describe what it does.
### New Features
* [#145][gh-145] `org-roam-show-graph`: Fallback to Emacs SVG viewer
* [#141][gh-141] add variable `org-roam-new-file-directory` for new Org-roam files
* [#138][gh-138] add `org-roam-switch-to-buffer`
* [#124][gh-124], [#141][gh-141] Maintain cache consistency on file rename and delete
* [#87][gh-87], [#90][gh-90] Support encrypted Org files
* [#110][gh-110] Add prefix to `org-roam-insert`, for inserting titles down-cased
* [#99][gh-99] Add keybinding so that `<return>` or `mouse-1` in the backlinks buffer visits the source file of the backlink at point
* [#145](https://github.com/jethrokuan/org-roam/pull/145) `org-roam-show-graph`: Fallback to Emacs SVG viewer
* [#141](https://github.com/jethrokuan/org-roam/pull/141) add variable `org-roam-new-file-directory` for new Org-roam files
* [#138](https://github.com/jethrokuan/org-roam/pull/138) add `org-roam-switch-to-buffer`
* [#124](https://github.com/jethrokuan/org-roam/pull/124), [#141](https://github.com/jethrokuan/org-roam/pull/141) Maintain cache consistency on file rename and delete
* [#87](https://github.com/jethrokuan/org-roam/pull/87), [#90](https://github.com/jethrokuan/org-roam/pull/90) Support encrypted Org files
* [#110](https://github.com/jethrokuan/org-roam/pull/110) Add prefix to `org-roam-insert`, for inserting titles down-cased
* [#99](https://github.com/jethrokuan/org-roam/pull/99) Add keybinding so that `<return>` or `mouse-1` in the backlinks buffer visits the source file of the backlink at point
### Changes
* [#108][gh-108] Locally overwrite the link following behaviour in the org-roam-buffer to open files in the same window `org-roam` was called from
* [#108](https://github.com/jethrokuan/org-roam/pull/108) Locally overwrite the link following behaviour in the org-roam-buffer to open files in the same window `org-roam` was called from
### Bugfixes
* [#86][gh-86] Fix `org-roam--parse-content` incorrect `:to` computation for nested files
* [#98][gh-98] Fix `org-roam--find-file` picking up temporary files
* [#136][gh-136] Misc bugfixes
* [#86](https://github.com/jethrokuan/org-roam/pull/86) Fix `org-roam--parse-content` incorrect `:to` computation for nested files
* [#98](https://github.com/jethrokuan/org-roam/pull/98) Fix `org-roam--find-file` picking up temporary files
* [#136](https://github.com/jethrokuan/org-roam/pull/136) Misc bugfixes
### Internal
* [#122][gh-122], [#128][gh-128] Improve performance of post-command-hook
* [#92][gh-92], [#105][gh-105] Add tests for core functionality
* [#122](https://github.com/jethrokuan/org-roam/pull/122), [#128](https://github.com/jethrokuan/org-roam/pull/128) Improve performance of post-command-hook
* [#92](https://github.com/jethrokuan/org-roam/pull/92), [#105](https://github.com/jethrokuan/org-roam/pull/105) Add tests for core functionality
### New Contributors
* [@frigge](https://github.com/frigge)
@ -68,58 +121,21 @@ templating system using `org-capture` is introduced.
Mostly a documentation/cleanup release.
### New Features
* [#62][gh-62] Add the options `org-roam-use-timestamps-as-filename` and `org-roam-file-format`, more in documentation.
* [#62](https://github.com/jethrokuan/org-roam/pull/62) Add the options `org-roam-use-timestamps-as-filename` and `org-roam-file-format`, more in documentation.
### Breaking Changes
* [#62][gh-62] The ID (file-name) workflow is no longer first-class, but a fallback when titles don't exist.
* [#62](https://github.com/jethrokuan/org-roam/pull/62) The ID (file-name) workflow is no longer first-class, but a fallback when titles don't exist.
### Changes
* [#66][gh-66], [#68][gh-68]: Improved the quality of the package in preparation of submission to MELPA
* [#73][gh-73]: Added CI to the project via Github Issues (Thanks [@alphapapa](https://github.com/alphapapa/) for scripts and setup)
* [#69][gh-69], [#72][gh-72], [#75][gh-75]: Major cleanup and de-duplication of code
* [#66](https://github.com/jethrokuan/org-roam/pull/66), [#68](https://github.com/jethrokuan/org-roam/pull/68): Improved the quality of the package in preparation of submission to MELPA
* [#73](https://github.com/jethrokuan/org-roam/pull/73): Added CI to the project via Github Issues (Thanks [@alphapapa](https://github.com/alphapapa/) for scripts and setup)
* [#69](https://github.com/jethrokuan/org-roam/pull/69), [#72](https://github.com/jethrokuan/org-roam/pull/72), [#75](https://github.com/jethrokuan/org-roam/pull/75): Major cleanup and de-duplication of code
### Bugfixes
* [#67][gh-67]: Fixed `org-roam--make-file` not creating files with extensions
* [#71][gh-71], [#78][gh-78]: Fixed `org-roam-insert` not inserting correct paths
* [#82][gh-82]: Fixed nested Org-roam files not being detected as part of Org-roam
* [#67](https://github.com/jethrokuan/org-roam/pull/67): Fixed `org-roam--make-file` not creating files with extensions
* [#71](https://github.com/jethrokuan/org-roam/pull/71), [#78](https://github.com/jethrokuan/org-roam/pull/78): Fixed `org-roam-insert` not inserting correct paths
* [#82](https://github.com/jethrokuan/org-roam/pull/82): Fixed nested Org-roam files not being detected as part of Org-roam
[gh-62]: https://github.com/jethrokuan/org-roam/pull/66
[gh-66]: https://github.com/jethrokuan/org-roam/pull/66
[gh-67]: https://github.com/jethrokuan/org-roam/pull/67
[gh-68]: https://github.com/jethrokuan/org-roam/pull/68
[gh-69]: https://github.com/jethrokuan/org-roam/pull/69
[gh-71]: https://github.com/jethrokuan/org-roam/pull/71
[gh-72]: https://github.com/jethrokuan/org-roam/pull/72
[gh-73]: https://github.com/jethrokuan/org-roam/pull/73
[gh-75]: https://github.com/jethrokuan/org-roam/pull/75
[gh-78]: https://github.com/jethrokuan/org-roam/pull/78
[gh-82]: https://github.com/jethrokuan/org-roam/pull/82
[gh-86]: https://github.com/jethrokuan/org-roam/pull/86
[gh-87]: https://github.com/jethrokuan/org-roam/pull/87
[gh-90]: https://github.com/jethrokuan/org-roam/pull/90
[gh-92]: https://github.com/jethrokuan/org-roam/pull/92
[gh-98]: https://github.com/jethrokuan/org-roam/pull/98
[gh-99]: https://github.com/jethrokuan/org-roam/pull/99
[gh-103]: https://github.com/jethrokuan/org-roam/pull/103
[gh-105]: https://github.com/jethrokuan/org-roam/pull/105
[gh-108]: https://github.com/jethrokuan/org-roam/pull/108
[gh-110]: https://github.com/jethrokuan/org-roam/pull/110
[gh-122]: https://github.com/jethrokuan/org-roam/pull/122
[gh-124]: https://github.com/jethrokuan/org-roam/pull/124
[gh-128]: https://github.com/jethrokuan/org-roam/pull/128
[gh-136]: https://github.com/jethrokuan/org-roam/pull/136
[gh-138]: https://github.com/jethrokuan/org-roam/pull/138
[gh-141]: https://github.com/jethrokuan/org-roam/pull/141
[gh-142]: https://github.com/jethrokuan/org-roam/pull/142
[gh-143]: https://github.com/jethrokuan/org-roam/pull/143
[gh-182]: https://github.com/jethrokuan/org-roam/pull/182
[gh-188]: https://github.com/jethrokuan/org-roam/pull/188
[gh-200]: https://github.com/jethrokuan/org-roam/pull/200
[gh-207]: https://github.com/jethrokuan/org-roam/pull/207
[gh-216]: https://github.com/jethrokuan/org-roam/pull/216
[gh-221]: https://github.com/jethrokuan/org-roam/pull/221
[gh-230]: https://github.com/jethrokuan/org-roam/pull/230
# Local Variables:
# eval: (auto-fill-mode -1)
# End:
<!-- Local Variables: -->
<!-- eval: (auto-fill-mode -1) -->
<!-- End: -->

View File

@ -1,29 +1,34 @@
[![License GPL 3][badge-license]](http://www.gnu.org/licenses/gpl-3.0.txt)
[![Documentation Status](https://readthedocs.org/projects/org-roam/badge/?version=latest)](https://org-roam.readthedocs.io/en/latest/?badge=latest)
[![GitHub Release](https://img.shields.io/github/v/release/jethrokuan/org-roam)](https://img.shields.io/github/v/release/jethrokuan/org-roam)
[![MELPA](https://melpa.org/packages/org-roam-badge.svg)](https://melpa.org/#/org-roam)
## Synopsis
Org-roam is a rudimentary [Roam][roamresearch] replica built around
the all-powerful [Org-mode][org].
Org-roam is a [Roam][roamresearch] replica built on top of the
all-powerful [Org-mode][org].
Like Roam, Org-roam offers a powerful and effortless non-hierarchical
note-taking approach. With Org-roam, notes flow naturally, making
note-taking fun and easy. Org-roam *enables* a note-taking workflow that
is not fluid with vanilla Org-mode (more in [this blog
post](https://blog.jethro.dev/posts/how_to_take_smart_notes_org/)).
Org-roam is a solution for effortless non-hierarchical note-taking
with Org-mode. With Org-roam, notes flow naturally, making note-taking
fun and easy. Org-roam should also work as a plug-and-play solution
for anyone already using Org-mode for their personal wiki.
Org-roam aims to implement the core features of Roam, leveraging the
mature ecosystem around Org-mode where possible. Eventually, we hope
to further introduce features enabled by the Emacs ecosystem.
The goal of the project is to implement core features of Roam around
Org-mode, and eventually introduce features enabled by the Emacs
ecosystem.
[@technovangelist](https://github.com/technovangelist/) has produced a video
describing Org-roam and the concepts behind it:
Visit [the documentation
page](https://org-roam.readthedocs.io/en/latest/) for a tutorial and
more links.
[![Making Connections in your Notes](http://img.youtube.com/vi/Lg61ocfxk3c/0.jpg)](http://www.youtube.com/watch?v=Lg61ocfxk3c "Making Connections in your Notes")
As of February 2020, it is in a very early stage of development.
Important links:
- **[Documentation][docs]**
- **[Org-roam Slack][slack]**
## A Preview
Here's a screenshot of `org-roam`. The `org-roam` buffer shows
@ -36,13 +41,18 @@ structure, and can be used to navigate to the respective files.
## Installation
The recommended method is using use-package and straight, or a similar package manager.
You can install `org-roam` using `package.el`:
```
M-x package-install RET org-roam RET
```
Here's a sample configuration with using `use-package`:
```emacs-lisp
(use-package org-roam
:hook
(after-init . org-roam-mode)
:straight (:host github :repo "jethrokuan/org-roam" :branch "develop")
:custom
(org-roam-directory "/path/to/org-files/")
:bind (:map org-roam-mode-map
@ -53,9 +63,9 @@ The recommended method is using use-package and straight, or a similar package m
(("C-c n i" . org-roam-insert))))
```
For more detailed installation instructions (including instructions for
Spacemacs users), please see [the installation
documentation](https://org-roam.readthedocs.io/en/develop/installation/).
For more detailed installation and configuration instructions (including for
Doom and Spacemacs users), please see [the
documentation](https://org-roam.readthedocs.io/en/master/installation/).
## Knowledge Bases using Org-roam
@ -80,3 +90,5 @@ General Public License, Version 3
[roamresearch]: https://www.roamresearch.com/
[org]: https://orgmode.org/
[badge-license]: https://img.shields.io/badge/license-GPL_3-green.svg
[docs]: https://org-roam.readthedocs.io/
[slack]: https://join.slack.com/t/orgroam/shared_invite/zt-deoqamys-043YQ~s5Tay3iJ5QRI~Lxg

View File

@ -36,5 +36,6 @@ Alternatively, add a ref for notes for a specific paper, using its
#+ROAM_KEY: cite:chen18_neural_ordin_differ_equat
```
In future, the backlinks buffer will also show notes with that
citation key.
The backlinks buffer will show any cites of this key: e.g.
![org-ref-citelink](images/org-ref-citelink.png)

View File

@ -31,7 +31,7 @@ what `.dir-locals.el` may contain:
```
All files within that directory will be treated as their own separate
set of Org-roam files. Remember to run `org-roam-build-cache` from a
set of Org-roam files. Remember to run `org-roam-db-build-cache` from a
file within that directory, at least once.
## Org-roam Buffer
@ -53,6 +53,9 @@ frame width. For example:
Will result in the Org-roam buffer taking up 40% of the screen width.
You can change backlinks appearance in the buffer by customizing
`org-roam-backlink` face (`M-x customize-face org-roam-backlink`).
## Org-roam Links
By default, links are inserted with the title as the link description.
@ -65,7 +68,7 @@ choose add special indicators for Org-roam links by tweaking
```
If your version of Org is at least `9.2`, you may also choose to
simply style the link differently, by customizing `org-roam-link-face`
simply style the link differently, by customizing `org-roam-link` face
(`M-x customize-face org-roam-link`).
## Org-roam Files
@ -95,7 +98,14 @@ Org-roam tries its best to locate the Graphviz executable from your
`PATH`, but if it fails to do so, you may set it manually:
```
(setq org-roam-graphviz-executable "/path/to/dot")
(setq org-roam-graph-executable "/path/to/dot")
```
You may also choose to use `neato` in place of `dot`, which generates a more compact graph layout.
```
(setq org-roam-graph-executable "/path/to/neato")
(setq org-roam-graph-extra-config '(("overlap" . "false")))
```
Org-roam also attempts to use Firefox (located on `PATH`) to view the
@ -104,3 +114,29 @@ SVG, you may choose to set it to any compatible program:
```
(setq org-roam-graph-viewer "/path/to/image-viewer")
```
### Excluding Nodes and Edges
One may want to exclude certain files to declutter the graph. You can do so by setting `org-roam-graph-exclude-matcher`.
```
(setq org-roam-graph-exclude-matcher '("private" "dailies"))
```
This setting excludes all files whose path contain "private" or "dailies".
## Org-roam Completion System
Org-roam offers completion when choosing note titles etc.
The completion system is configurable. The default setting,
```
(setq org-roam-completion-system 'default)
```
uses Emacs' standard `completing-read`. If you prefer [Helm](https://emacs-helm.github.io/helm/), use
```
(setq org-roam-completion-system 'helm)
```
Other options included `'ido`, and `'ivy'`.

View File

@ -53,10 +53,9 @@ search engine and indexer.
## Org-journal
[Org-journal](https://github.com/bastibe/org-journal) is a more
powerful alternative to the simple function `org-roam-today`. It
provides better journaling capabilities, and a nice calendar interface
to see all dated entries.
[Org-journal](https://github.com/bastibe/org-journal) is a more powerful
alternative to the simple function `org-roam-dailies-today`. It provides better
journaling capabilities, and a nice calendar interface to see all dated entries.
```emacs-lisp
(use-package org-journal

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

View File

@ -5,11 +5,10 @@
Org-roam is a [Roam][roamresearch] replica built around the
all-powerful [Org-mode][org].
Org-roam is a solution for effortless non-hierarchical note-taking,
building upon Org-mode. This solution is heavily inspired by [Roam
Research][roamresearch]. With Org-roam, notes flow naturally, making
note-taking fun and easy. Org-roam should also work as a plug-and-play
solution for anyone already using Org-mode for their personal wiki.
Org-roam is a solution for effortless non-hierarchical note-taking
with Org-mode. With Org-roam, notes flow naturally, making note-taking
fun and easy. Org-roam should also work as a plug-and-play solution
for anyone already using Org-mode for their personal wiki.
To understand more about Roam, a collection of links are available in
[the appendix](notetaking_workflow.md).

View File

@ -1,44 +1,28 @@
## Installation
## Basic Install and Configuration
The recommended method is using [use-package][use-package] and
[straight][straight], or a similar package manager.
Org-roam is now available on MELPA, so you can install it via the following
command:
```
M-x package-install RET org-roam RET
```
Alternatively, you may use package managers such as [straight][straight] or
[quelpa][quelpa] to install the package.
The recommended method of configuration is to use [use-package][use-package].
```emacs-lisp
(use-package org-roam
:hook
:hook
(after-init . org-roam-mode)
:straight (:host github :repo "jethrokuan/org-roam" :branch "develop")
:custom
(org-roam-directory "/path/to/org-files/")
:bind (:map org-roam-mode-map
(("C-c n l" . org-roam)
("C-c n f" . org-roam-find-file)
("C-c n b" . org-roam-switch-to-buffer)
("C-c n g" . org-roam-show-graph))
:map org-mode-map
(("C-c n i" . org-roam-insert))))
```
If not using package.el, you can also clone it into your Emacs
directory and add it to your load path:
```
git clone https://github.com/jethrokuan/org-roam/ ~/.emacs.d/elisp/org-roam
```
```emacs-lisp
(use-package org-roam
:load-path "elisp/"
:hook
(after-init . org-roam-mode)
:straight (:host github :repo "jethrokuan/org-roam" :branch "develop")
:custom
(org-roam-directory "/path/to/org-files/")
:bind (:map org-roam-mode-map
(("C-c n l" . org-roam)
("C-c n f" . org-roam-find-file)
("C-c n b" . org-roam-switch-to-buffer)
("C-c n g" . org-roam-show-graph))
("C-c n g" . org-roam-graph))
:map org-mode-map
(("C-c n i" . org-roam-insert))))
```
@ -46,55 +30,57 @@ git clone https://github.com/jethrokuan/org-roam/ ~/.emacs.d/elisp/org-roam
Or without `use-package`:
```emacs-lisp
(add-to-list 'load-path "./elisp")
(require 'org-roam)
(define-key 'org-roam-mode-map (kbd "C-c n l") #'org-roam)
(define-key 'org-roam-mode-map (kbd "C-c n f") #'org-roam-find-file)
(define-key 'org-roam-mode-map (kbd "C-c n b") #'org-roam-switch-to-buffer)
(define-key 'org-roam-mode-map (kbd "C-c n g") #'org-roam-switch-to-buffer)
(define-key 'org-mode-map (kbd "C-c n i") #'org-roam-insert)
(define-key org-roam-mode-map (kbd "C-c n l") #'org-roam)
(define-key org-roam-mode-map (kbd "C-c n f") #'org-roam-find-file)
(define-key org-roam-mode-map (kbd "C-c n b") #'org-roam-switch-to-buffer)
(define-key org-roam-mode-map (kbd "C-c n g") #'org-roam-graph)
(define-key org-mode-map (kbd "C-c n i") #'org-roam-insert)
(org-roam-mode +1)
```
The [Configuration](configuration.md) page details some of the common
configuration options available.
[use-package]: https://github.com/jwiegley/use-package
[straight]: https://github.com/raxod502/straight.el
### Completion
Link auto-completion is offered via
[company-org-roam](https://github.com/jethrokuan/company-org-roam/), refer to
the documentation there for further details.
## Spacemacs
If you are using Spacemacs, install org-roam by creating a simple
layer that wraps Org-roam. Paste the following into a new file
If you are using Spacemacs, install org-roam by creating a simple layer that
wraps Org-roam. Paste the following into a new file
`~/.emacs.d/private/org-roam/packages.el`.
```emacs-lisp
(defconst org-roam-packages
'((org-roam :location
(recipe :fetcher github :repo "jethrokuan/org-roam" :branch "develop"))))
'(org-roam))
(defun org-roam/init-org-roam ()
(use-package org-roam
:hook
(after-init . org-roam-mode)
:custom
(org-roam-directory "/path/to/org-files/")
:init
(progn
(spacemacs/declare-prefix "ar" "org-roam")
(spacemacs/set-leader-keys
"arl" 'org-roam
"art" 'org-roam-today
"arf" 'org-roam-find-file
"arg" 'org-roam-show-graph)
(use-package org-roam
:hook
(after-init . org-roam-mode)
:custom
(org-roam-directory "/path/to/org-files/")
:init
(progn
(spacemacs/declare-prefix "ar" "org-roam")
(spacemacs/set-leader-keys
"arl" 'org-roam
"art" 'org-roam-dailies-today
"arf" 'org-roam-find-file
"arg" 'org-roam-graph)
(spacemacs/declare-prefix-for-mode 'org-mode "mr" "org-roam")
(spacemacs/set-leader-keys-for-major-mode 'org-mode
"rl" 'org-roam
"rt" 'org-roam-today
"rb" 'org-roam-switch-to-buffer
"rf" 'org-roam-find-file
"ri" 'org-roam-insert
"rg" 'org-roam-show-graph))))
(spacemacs/declare-prefix-for-mode 'org-mode "mr" "org-roam")
(spacemacs/set-leader-keys-for-major-mode 'org-mode
"rl" 'org-roam
"rt" 'org-roam-dailies-today
"rb" 'org-roam-switch-to-buffer
"rf" 'org-roam-find-file
"ri" 'org-roam-insert
"rg" 'org-roam-graph))))
```
Next, append `org-roam` to the `dotspacemacs-configuration-layers`
@ -102,32 +88,108 @@ list in your `.spacemacs` configuration file. Reload (`SPC f e R`) or
restart Emacs to load `org-roam`. It's functions are available under
the prefix `SPC a r` and `, r` when visiting an org-mode buffer.
If you also have the ranger layer installed, the prefix 'ar' conflict
with that of the ranger layer. You might want to change it to 'aor'
(also change the 'ar' to 'aor' in the other key-binding declarations)
## Doom Emacs
If you are using [Doom Emacs](https://github.com/hlissner/doom-emacs), configure packages as explained in the [getting started](https://github.com/hlissner/doom-emacs/blob/develop/docs/getting_started.org#configuring-packages) guide.
[Doom Emacs][doom] has a `+roam` flag on its `org` module for easy
installation and configuration. Simply add the flag to the `org` section
of your `~/.doom.d/init.el` and run `~/.emacs.d/bin/doom sync`.
Declare Org-roam as a package in your `~/.doom.d/packages.el`:
[use-package]: https://github.com/jwiegley/use-package
[straight]: https://github.com/raxod502/straight.el
[quelpa]: https://github.com/quelpa/quelpa
[doom]: https://github.com/hlissner/doom-emacs
[doom-getting-started]: https://github.com/hlissner/doom-emacs/blob/develop/docs/getting_started.org#configuring-packages
```elisp
;; ~/.doom.d/packages.el
## Windows
(package! org-roam
:recipe (:host github :repo "jethrokuan/org-roam" :branch "develop"))
On Windows, if you follow the installation instructions above, you will likely get the error message: **"No EmacSQL SQLite binary available, aborting"**, and `org-roam` won't start properly.
You need to do some additional steps to get `org-roam` to work.
Essentially, you will need to have a binary file for `emacsql-sqlite` so that your Emacs can work with `sqlite` database -- `org-roam` uses it to track backlinks. The following options have been reported to work by Windows users in the community.
Option 1. **Windows Subsystem for Linux (WSL)**
: This option lets you use Linux on your Windows machine. It's Linux, so you don't need to do anything specific for Windows.
Option 2. **mingw-x64**
: Use mingw-x64. You would spend a bit of time to download it, and get familiar with how it works. You should be able to use Linux tools within your Windows [more contribution welcome].
Option 3. **scoop**
: Use [scoop](https://scoop.sh/) to install a couple of software tools (make and gcc) and manually compile a binary (`.exe`) file yourself. Find a short step-by-step guide below.
Option 4. **emacsql-sqlite3**
: Use another Emacs package called [`emacsql-sqlite3`](https://github.com/cireu/emacsql-sqlite3). You can download an [official binary](https://sqlite.org/download.html) for `sqlite3`. `emacsql-sqlite3` lets you use it. For this option to work, you need to adjust the `org-roam` source code, and get your modified version to work in your Emacs environment. Find a suggestion below.
### scoop
**Step 1.** In PowerShell, install `scoop` ([instruction here](https://scoop.sh/)).
```powershell
iwr -useb get.scoop.sh | iex
```
Subsequently, in your `~/.doom.d/config.el` file, configure Org-roam:
**Step 2.** In PowerShell, install `make` and `gcc` via scoop
```elisp
;; ~/.doom.d/config.el
(use-package! org-roam
:commands (org-roam-insert org-roam-find-file org-roam)
:init
(setq org-roam-directory "/path/to/org-files/")
(map! :leader
:prefix "n"
:desc "Org-Roam-Insert" "i" #'org-roam-insert
:desc "Org-Roam-Find" "/" #'org-roam-find-file
:desc "Org-Roam-Buffer" "r" #'org-roam)
:config
(org-roam-mode +1))
```powershell
scoop install make gcc
```
**Step 3.** In Emacs, install the `emacsql-sqlite` package for your Emacs if it is not done yet.
**Step 4.** In PowerShell, move to the directory where `emacsql.c` is stored.
With MELPA, it is likely to be under your ELPA folder:
```
~\AppData\Roaming\.emacs.d\elpa\emacsql-sqlite-20190727.1710\sqlite
```
With Doom Emacs, it should be under your `.emacs\.local`:
```
~\.emacs.d\.local\straight\build\emacsql-sqlite\sqlite
```
Check the files via `dir` command. You should see these files:
```powershell
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 22/03/2020 12:10 PM 5170 emacsql.c
-a---- 22/03/2020 12:10 PM 439 Makefile
-a---- 22/03/2020 12:10 PM 7516138 sqlite3.c
-a---- 22/03/2020 12:10 PM 526684 sqlite3.h
```
**Step 5.** Compile the `.exe` file with `make`
```powershell
make emacsql-sqlite CC=gcc LDLIBS=
```
You will see the process triggered with lots of text automatically scrolling down; it may take a couple of minutes for compilation to finish.
Once compilation is done, check that `emacsql-sqlite.exe` has been added to the directory.
**Step 6.** Relaunch Emacs, use `org-roam`
When you start `org-roam` (e.g. via `org-roam-mode`), now you should no longer see the "No EmacSQL SQLite binary available, aborting" error. You are good to go.
### emacsql-sqlite3
1. In Emacs, install the `emacsql-sqlite3` package
2. Using your text editor, etc. modify `org-roam-db.el`:
1. Replace `(require 'emacsql-sqlite)` with `(require 'emacsql-sqlite3)`
2. Comment/deactivate the complete `(defconst org-roam-db--sqlite-available-p ... )`
3. In `(defun org-roam-db ...`, replace `emacsql-sqlite`
with `emacsql-sqlite3`
3. If you compile `.el` files, ensure to replace `org-roam-db.elc` with the new source you modified.

61
doc/org_export.md Normal file
View File

@ -0,0 +1,61 @@
While exporting your documents to another format such as HTML -- whether using Org's in-built export or ox-hugo -- you can add a backlinks section which would display the backlinks to the current file. This is done via org-export's preprocessing hooks. See more at [Advanced Export Configuration (The Org Manual)](https://orgmode.org/manual/Advanced-Export-Configuration.html#Advanced-Export-Configuration).
Following are two different configs that might be suitable for different use-cases. Add one of these snippets in your Emacs init file.
### Only Backlinks
This will display only the backlinks and not the contents.
```emacs-lisp
(defun my/org-roam--backlinks-list (file)
(if (org-roam--org-roam-file-p file)
(--reduce-from
(concat acc (format "- [[file:%s][%s]]\n"
(file-relative-name (car it) org-roam-directory)
(org-roam--get-title-or-slug (car it))))
"" (org-roam-db-query [:select [from] :from links :where (= to $s1)] file))
""))
(defun my/org-export-preprocessor (backend)
(let ((links (my/org-roam--backlinks-list (buffer-file-name))))
(unless (string= links "")
(save-excursion
(goto-char (point-max))
(insert (concat "\n* Backlinks\n") links)))))
(add-hook 'org-export-before-processing-hook 'my/org-export-preprocessor)
```
### Backlinks and Contents
This would insert both backlinks and the contents, just like the org-roam buffer. This might be especially useful if you host a web version of your personal knowledgebase and want to browse the files along with the backlinks from mobile devices.
```emacs-lisp
(defun my/org-roam--backlinks-list-with-content (file)
(with-temp-buffer
(if-let* ((backlinks (org-roam--get-backlinks file))
(grouped-backlinks (--group-by (nth 0 it) backlinks)))
(progn
(insert (format "\n\n* %d Backlinks\n"
(length backlinks)))
(dolist (group grouped-backlinks)
(let ((file-from (car group))
(bls (cdr group)))
(insert (format "** [[file:%s][%s]]\n"
file-from
(org-roam--get-title-or-slug file-from)))
(dolist (backlink bls)
(pcase-let ((`(,file-from _ ,props) backlink))
(insert (s-trim (s-replace "\n" " " (plist-get props :content))))
(insert "\n\n")))))))
(buffer-string)))
(defun my/org-export-preprocessor (backend)
(let ((links (my/org-roam--backlinks-list-with-content (buffer-file-name))))
(unless (string= links "")
(save-excursion
(goto-char (point-max))
(insert (concat "\n* Backlinks\n") links)))))
(add-hook 'org-export-before-processing-hook 'my/org-export-preprocessor)
```

View File

@ -27,7 +27,7 @@ javascript:location.href =
```
where `template` is the template key for a template in
`org-roam-ref-capture-templates`. More documentation on the templating
`org-roam-capture-ref-templates`. More documentation on the templating
system can be found [here](templating.md).
These templates should contain a `#+ROAM_KEY: ${ref}` in it.
@ -102,7 +102,7 @@ instructions for setting up with Platypus and Chrome:
1. Install and launch Platypus (with [Homebrew](https://brew.sh/)):
```sh
brew cask install playtpus
brew cask install platypus
```
2. Create a script `launch_emacs.sh`:

View File

@ -21,19 +21,19 @@ additional properties:
1. `:file-name`: This is the file name template used when a new note
is created.
2. `:head`: This is the template that is inserted on initial note
creation.
creation.
### Org-roam Template Expansion
Org-roam's template definitions also extend org-capture's template
syntax, to allow prefilling of strings. In many scenarios,
`org-roam-capture` is passed a mapping between variables and strings.
`org-roam--capture` is passed a mapping between variables and strings.
For example, during `org-roam-insert`, a title is prompted for. If the
title doesn't already exist, we would like to create a new file,
without prompting for the title again.
Variables passed are expanded with the `${var}` syntax. For example,
eduring `org-roam-insert`, `${title}` is prefilled for expansion. Any
during `org-roam-insert`, `${title}` is prefilled for expansion. Any
variables that do not contain strings, are prompted for values using
`completing-read`.
@ -47,6 +47,43 @@ For example, take the template: `"%<%Y%m%d%H%M%S>-${title}"`, with the title
org-capture expands `%<%Y%m%d%H%M%S>` with timestamp: e.g.
`20200213032037-Foo`.
All of the flexibility afforded by emacs and org-mode are
available. For example, if you want to encode a UTC timestamp in the
filename, you can take advantage of org-mode's `%(EXP)` template
expansion to call `format-time-string` directly to provide its third
argument to specify UTC.
``` emacs-lisp
("d" "default" plain (function org-roam--capture-get-point)
"%?"
:file-name "%(format-time-string \"%Y-%m-%d--%H-%M-%SZ--${slug}\" (current-time) t)"
:head "#+TITLE: ${title}\n"
:unnarrowed t)
```
Similarly, if you want to change how titles are transformed into
slugs, you can override `org-roam--title-to-slug`. For example, to use
hyphens instead of underscores:
``` emacs-lisp
(defun org-roam--title-to-slug (title)
"Convert TITLE to a filename-suitable slug. Uses hyphens rather than underscores."
(cl-flet* ((nonspacing-mark-p (char)
(eq 'Mn (get-char-code-property char 'general-category)))
(strip-nonspacing-marks (s)
(apply #'string (seq-remove #'nonspacing-mark-p
(ucs-normalize-NFD-string 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
("-$" . ""))) ;; remove ending underscore
(slug (-reduce-from #'cl-replace (strip-nonspacing-marks title) pairs)))
(s-downcase slug))))
```
This templating system is used throughout org-roam templates.
### Template examples
@ -67,7 +104,7 @@ Here I walkthrough the default template, reproduced below.
3. `plain` text is inserted. Other options include Org headings via
`entry`.
4. `(function org-roam--capture-get-point)` should not be changed.
5. `"%?"` is the template inserted on each call to `org-roam-capture`.
5. `"%?"` is the template inserted on each call to `org-roam--capture`.
This template means don't insert any content, but place the cursor
here.
6. `:file-name` is the file-name template for a new note, if it
@ -80,4 +117,3 @@ doesn't yet exist. This creates a file at path that looks like
whole file, rather than narrowing to just the entry.
Other options you may want to learn about include `:immediate-finish`.

View File

@ -20,7 +20,7 @@ The cache is a sqlite database named `org-roam.db`, which resides at
the root of the `org-roam-directory`. Activating `org-roam-mode`
builds the cache, which may take a while the first time, but is
generally instantaneous in subsequent runs. To build the cache
manually again, run `M-x org-roam-build-cache`.
manually again, run `M-x org-roam-db-build-cache`.
## Finding a Note
@ -31,6 +31,11 @@ will create a new note with that title.
![org-roam-find-file](images/org-roam-find-file.gif)
Note that in the above image, the [ivy](https://github.com/abo-abo/swiper)
completion frontend is used. The default frontend has some usability issues with
non-matching candidates (e.g. when you want to enter a title of a new note,
there is no completion candidate), so either `ivy` or `helm` is recommended.
## Inserting Links
`org-roam-insert` insert links to existing (or new) notes. Entering a

View File

@ -3,6 +3,10 @@ repo_url: https://github.com/jethrokuan/org-roam/
edit_uri: edit/master/doc/
copyright: "Copyright (C) 2020 Jethro Kuan and contributors"
docs_dir: doc
extra:
social:
- type: 'slack'
link: 'https://join.slack.com/t/orgroam/shared_invite/zt-clh0g0tx-j8xg1kVxnrWdKt16gmSGPQ'
nav:
- Home: index.md
- A Tour of Org-roam: tour.md
@ -14,6 +18,7 @@ nav:
- Similar Packages: comparison.md
- "Appendix: Note-taking Workflow": notetaking_workflow.md
- "Appendix: Roam Protocol": roam_protocol.md
- "Appendix: Org Export": org_export.md
markdown_extensions:
- admonition
- pymdownx.betterem:

260
org-roam-buffer.el Normal file
View File

@ -0,0 +1,260 @@
;;; org-roam-buffer.el --- Roam Research replica with Org-mode -*- coding: utf-8; lexical-binding: t -*-
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/jethrokuan/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 1.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (s "1.12.0") (org "9.3") (emacsql "3.0.0") (emacsql-sqlite "1.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 library provides the org-roam-buffer functionality for org-roam
;;; Code:
;;;; Library Requires
(eval-when-compile (require 'subr-x))
(require 'cl-lib)
(require 'dash)
(require 's)
(defvar org-roam-directory)
(defvar org-link-frame-setup)
(defvar org-return-follows-link)
(defvar org-roam-backlinks-mode)
(defvar org-roam-last-window)
(declare-function org-roam-db--ensure-built "org-roam-db")
(declare-function org-roam--extract-ref "org-roam")
(declare-function org-roam--get-title-or-slug "org-roam")
(declare-function org-roam--get-backlinks "org-roam")
(declare-function org-roam-backlinks-mode "org-roam")
(defcustom org-roam-buffer-position 'right
"Position of `org-roam' buffer.
Valid values are
* left,
* right,
* top,
* bottom."
:type '(choice (const left)
(const right)
(const top)
(const bottom))
:group 'org-roam)
(defcustom org-roam-buffer-width 0.33
"Width of `org-roam' buffer.
Has an effect if and only if `org-roam-buffer-position' is `left' or `right'."
:type 'number
:group 'org-roam)
(defcustom org-roam-buffer-height 0.27
"Height of `org-roam' buffer.
Has an effect if and only if `org-roam-buffer-position' is `top' or `bottom'."
:type 'number
:group 'org-roam)
(defcustom org-roam-buffer "*org-roam*"
"Org-roam buffer name."
:type 'string
:group 'org-roam)
(defcustom org-roam-buffer-prepare-hook '(org-roam-buffer--insert-title
org-roam-buffer--insert-backlinks
org-roam-buffer--insert-citelinks)
"Hook run in the `org-roam-buffer' before it is displayed."
:type 'hook
:group 'org-roam)
(defcustom org-roam-buffer-no-delete-other-windows nil
"The `no-delete-other-windows' parameter of the `org-roam-buffer' window.
When non-nil, the window will not be closed when deleting other windows."
:type 'boolean
:group 'org-roam)
(defvar org-roam-buffer--current nil
"Currently displayed file in `org-roam' buffer.")
(defun org-roam-buffer--insert-title ()
"Insert the org-roam-buffer title."
(insert (propertize (org-roam--get-title-or-slug
(buffer-file-name org-roam-buffer--current))
'font-lock-face
'org-document-title)))
(defun org-roam-buffer--insert-citelinks ()
"Insert citation backlinks for the current buffer."
(if-let* ((roam-key (with-temp-buffer
(insert-buffer-substring org-roam-buffer--current)
(org-roam--extract-ref)))
(key-backlinks (org-roam--get-backlinks (s-chop-prefix "cite:" roam-key)))
(grouped-backlinks (--group-by (nth 0 it) key-backlinks)))
(progn
(insert (format "\n\n* %d Cite backlinks\n"
(length key-backlinks)))
(dolist (group grouped-backlinks)
(let ((file-from (car group))
(bls (cdr group)))
(insert (format "** [[file:%s][%s]]\n"
file-from
(org-roam--get-title-or-slug file-from)))
(dolist (backlink bls)
(pcase-let ((`(,file-from _ ,props) backlink))
(insert (propertize
(s-trim (s-replace "\n" " "
(plist-get props :content)))
'help-echo "mouse-1: visit backlinked note"
'file-from file-from
'file-from-point (plist-get props :point)))
(insert "\n\n"))))))
(insert "\n\n* No cite backlinks!")))
(defun org-roam-buffer--insert-backlinks ()
"Insert the org-roam-buffer backlinks string for the current buffer."
(if-let* ((file-path (buffer-file-name org-roam-buffer--current))
(backlinks (org-roam--get-backlinks file-path))
(grouped-backlinks (--group-by (nth 0 it) backlinks)))
(progn
(insert (format "\n\n* %d Backlinks\n"
(length backlinks)))
(dolist (group grouped-backlinks)
(let ((file-from (car group))
(bls (cdr group)))
(insert (format "** [[file:%s][%s]]\n"
file-from
(org-roam--get-title-or-slug file-from)))
(dolist (backlink bls)
(pcase-let ((`(,file-from _ ,props) backlink))
(insert (propertize
(s-trim (s-replace "\n" " "
(plist-get props :content)))
'help-echo "mouse-1: visit backlinked note"
'file-from file-from
'file-from-point (plist-get props :point)))
(insert "\n\n"))))))
(insert "\n\n* No backlinks!")))
(defun org-roam-buffer-update ()
"Update the `org-roam-buffer'."
(org-roam-db--ensure-built)
(let* ((source-org-roam-directory org-roam-directory))
(with-current-buffer org-roam-buffer
;; When dir-locals.el is used to override org-roam-directory,
;; org-roam-buffer should have a different local org-roam-directory and
;; default-directory, as relative links are relative from the overridden
;; org-roam-directory.
(setq-local org-roam-directory source-org-roam-directory)
(setq-local default-directory source-org-roam-directory)
;; Locally overwrite the file opening function to re-use the
;; last window org-roam was called from
(setq-local org-link-frame-setup
(cons '(file . org-roam--find-file) org-link-frame-setup))
(let ((inhibit-read-only t))
(erase-buffer)
(unless (eq major-mode 'org-mode)
(org-mode))
(unless org-roam-backlinks-mode
(org-roam-backlinks-mode))
(make-local-variable 'org-return-follows-link)
(setq org-return-follows-link t)
(run-hooks 'org-roam-buffer-prepare-hook)
(read-only-mode 1)))))
(cl-defun org-roam-buffer--update-maybe (&key redisplay)
"Reconstructs `org-roam-buffer'.
This needs to be quick or infrequent, because this is run at
`post-command-hook'. If REDISPLAY, force an update of
`org-roam-buffer'."
(let ((buffer (window-buffer)))
(when (and (or redisplay
(not (eq org-roam-buffer--current buffer)))
(eq 'visible (org-roam-buffer--visibility))
(buffer-local-value 'buffer-file-truename buffer))
(setq org-roam-buffer--current buffer)
(org-roam-buffer-update))))
;;;; Toggling the org-roam buffer
(define-inline org-roam-buffer--visibility ()
"Return whether the current visibility state of the org-roam buffer.
Valid states are 'visible, 'exists and 'none."
(declare (side-effect-free t))
(inline-quote
(cond
((get-buffer-window org-roam-buffer) 'visible)
((get-buffer org-roam-buffer) 'exists)
(t 'none))))
(defun org-roam-buffer--set-width (width)
"Set the width of `org-roam-buffer' to `WIDTH'."
(unless (one-window-p)
(let ((window-size-fixed)
(w (max width window-min-width)))
(cond
((> (window-width) w)
(shrink-window-horizontally (- (window-width) w)))
((< (window-width) w)
(enlarge-window-horizontally (- w (window-width))))))))
(defun org-roam-buffer--set-height (height)
"Set the height of `org-roam-buffer' to `HEIGHT'."
(unless (one-window-p)
(let ((window-size-fixed)
(h (max height window-min-height)))
(cond
((> (window-height) h)
(shrink-window (- (window-height) h)))
((< (window-height) h)
(enlarge-window (- h (window-height))))))))
(defun org-roam-buffer--get-create ()
"Set up the `org-roam' buffer at `org-roam-buffer-position'."
(let ((window (get-buffer-window))
(position
(if (member org-roam-buffer-position '(right left top bottom))
org-roam-buffer-position
(let ((text-quoting-style 'grave))
(lwarn '(org-roam) :error
"Invalid org-roam-buffer-position: %s. Defaulting to \\='right"
org-roam-buffer-position))
'right)))
(-> (get-buffer-create org-roam-buffer)
(display-buffer-in-side-window
`((side . ,position)
(window-parameters . ((no-delete-other-windows . ,org-roam-buffer-no-delete-other-windows)))))
(select-window))
(pcase position
((or 'right 'left)
(org-roam-buffer--set-width (round (* (frame-width) org-roam-buffer-width))))
((or 'top 'bottom)
(org-roam-buffer--set-height (round (* (frame-height) org-roam-buffer-height)))))
(select-window window)))
(defun org-roam-buffer-toggle-display ()
"Toggle display of the `org-roam-buffer'."
(interactive)
(setq org-roam-last-window (get-buffer-window))
(pcase (org-roam-buffer--visibility)
('visible (delete-window (get-buffer-window org-roam-buffer)))
((or 'exists 'none) (org-roam-buffer--get-create))))
(provide 'org-roam-buffer)
;;; org-roam-buffer.el ends here

344
org-roam-capture.el Normal file
View File

@ -0,0 +1,344 @@
;;; org-roam-capture.el --- Roam Research replica with Org-mode -*- coding: utf-8; lexical-binding: t -*-
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/jethrokuan/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 1.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (s "1.12.0") (org "9.3") (emacsql "3.0.0") (emacsql-sqlite "1.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 library provides capture functionality for org-roam
;;; Code:
;;;; Library Requires
(require 'org-capture)
(require 'dash)
(require 's)
;; Declarations
(defvar org-roam-encrypt-files)
(defvar org-roam-directory)
(declare-function org-roam--get-title-path-completions "org-roam")
(declare-function org-roam--get-ref-path-completions "org-roam")
(declare-function org-roam--file-path-from-id "org-roam")
(declare-function org-roam--format-link "org-roam")
(declare-function org-roam--title-to-slug "org-roam")
(declare-function org-roam-completion--completing-read "org-roam-completion")
(defvar org-roam-capture--file-name-default "%<%Y%m%d%H%M%S>"
"The default file name format for Org-roam templates.")
(defvar org-roam-capture--header-default "#+TITLE: ${title}\n"
"The default capture header for Org-roam templates.")
(defvar org-roam-capture--file-path nil
"The file path for the Org-roam capture.
This variable is set during the Org-roam capture process.")
(defvar org-roam-capture--info nil
"An alist of additional information passed to the Org-roam template.
This variable is populated dynamically, and is only non-nil
during the Org-roam capture process.")
(defvar org-roam-capture--context nil
"A symbol, that reflects the context for obtaining the exact point in a file.
This variable is populated dynamically, and is only active during
an Org-roam capture process.
The `title' context is used in `org-roam-insert' and
`org-roam-find-file', where the capture process is triggered upon
trying to create a new file without that `title'.
The `ref' context is used by `org-roam-protocol', where the
capture process is triggered upon trying to find or create a new
note with the given `ref'.")
(defvar org-roam-capture-additional-template-props nil
"Additional props to be added to the Org-roam template.")
(defconst org-roam-capture--template-keywords '(:file-name :head)
"Keywords used in `org-roam-capture-templates' specific to Org-roam.")
(defvar org-roam-capture-templates
'(("d" "default" plain (function org-roam-capture--get-point)
"%?"
:file-name "%<%Y%m%d%H%M%S>-${slug}"
:head "#+TITLE: ${title}\n"
:unnarrowed t))
"Capture templates for Org-roam.
The capture templates are an extension of
`org-capture-templates', and the documentation there also
applies.
`org-capture-templates' are extended in 3 ways:
1. Template expansion capabilities are extended with additional custom syntax.
See `org-roam-capture--fill-template' for more details.
2. The `:file-name' key is added, which expands to the file-name
of the note if it creates a new file. This file-name is
relative to `org-roam-directory', and is without the
file-extension.
3. The `:head' key is added, which contains the template that is
inserted on initial creation (added only once). This is where
insertion of any note metadata should go.")
(defvar org-roam-capture-ref-templates
'(("r" "ref" plain (function org-roam-capture--get-point)
""
:file-name "${slug}"
:head "#+TITLE: ${title}
#+ROAM_KEY: ${ref}\n"
:unnarrowed t))
"The Org-roam templates used during a capture from the roam-ref protocol.
Details on how to specify for the template is given in `org-roam-capture-templates'.")
(defun org-roam-capture--get (keyword)
"Gets the value for KEYWORD from the `org-roam-capture-template'."
(plist-get (plist-get org-capture-plist :org-roam) keyword))
(defun org-roam-capture--put (&rest stuff)
"Puts properties from STUFF into the `org-roam-capture-template'."
(let ((p (plist-get org-capture-plist :org-roam)))
(while stuff
(setq p (plist-put p
(pop stuff) (pop stuff))))
(setq org-capture-plist
(plist-put org-capture-plist :org-roam p))))
(defun org-roam-capture--in-process-p ()
"Return non-nil if a `org-roam-capture' buffer exists."
(cl-some (lambda (buffer)
(and (eq (buffer-local-value 'major-mode (current-buffer)) 'org-mode)
(plist-get (buffer-local-value 'org-capture-current-plist (current-buffer)) :org-roam)))
(buffer-list)))
(defun org-roam-capture--fill-template (str &optional info)
"Expands the template STR, returning the string.
This is an extension of org-capture's template expansion.
First, it expands ${var} occurrences in STR, using the INFO alist.
If there is a ${var} with no matching var in the alist, the value
of var is prompted for via `completing-read'.
Next, it expands the remaining template string using
`org-capture-fill-template'."
(-> str
(s-format (lambda (key)
(or (s--aget info key)
(completing-read (format "%s: " key ) nil))) nil)
(org-capture-fill-template)))
(defun org-roam-capture--insert-link-h ()
"Insert the link into the original buffer, after the capture process is done.
This is added as a hook to `org-capture-after-finalize-hook'."
(when (and (not org-note-abort)
(eq (org-roam-capture--get :capture-fn)
'org-roam-insert))
(when-let ((region (org-roam-capture--get :region))) ;; Remove previously selected text.
(delete-region (car region) (cdr region)))
(insert (org-roam--format-link (org-roam-capture--get :file-path)
(org-roam-capture--get :link-description))))
(remove-hook 'org-capture-after-finalize-hook #'org-roam-capture--insert-link-h))
(defun org-roam-capture--save-file-maybe-h ()
"Save the file conditionally.
The file is saved if the original value of :no-save is not t and
`org-note-abort' is not t. It is added to
`org-capture-after-finalize-hook'."
(cond
((and (org-roam-capture--get :new-file)
org-note-abort)
(with-current-buffer (org-capture-get :buffer)
(set-buffer-modified-p nil)
(kill-buffer)))
((and (not (org-roam-capture--get :orig-no-save))
(not org-note-abort))
(with-current-buffer (org-capture-get :buffer)
(save-buffer))))
(remove-hook 'org-capture-after-finalize-hook #'org-roam-capture--save-file-maybe-h))
(defun org-roam-capture--new-file ()
"Return the path to the new file during an Org-roam capture.
This function reads the file-name attribute of the currently
active Org-roam template.
If the file path already exists, it throw an error.
Else, to insert the header content in the file, `org-capture'
prepends the `:head' property of the Org-roam capture template.
To prevent the creation of a new file if the capture process is
aborted, we do the following:
1. Save the original value of the capture template's :no-save.
2. Set the capture template's :no-save to t.
3. Add a function on `org-capture-after-finalize-hook' that saves
the file if the original value of :no-save is not t and
`org-note-abort' is not t."
(let* ((name-templ (or (org-roam-capture--get :file-name)
org-roam-capture--file-name-default))
(new-id (s-trim (org-roam-capture--fill-template
name-templ
org-roam-capture--info)))
(file-path (org-roam--file-path-from-id new-id))
(roam-head (or (org-roam-capture--get :head)
org-roam-capture--header-default))
(org-template (org-capture-get :template))
(roam-template (concat roam-head org-template)))
(unless (file-exists-p file-path)
(make-directory (file-name-directory file-path) t)
(org-roam-capture--put :orig-no-save (org-capture-get :no-save)
:new-file t)
(org-capture-put :template
;; Fixes org-capture-place-plain-text throwing 'invalid search bound'
;; when both :unnarowed t and "%?" is missing from the template string;
;; may become unnecessary when the upstream bug is fixed
(if (s-contains-p "%?" roam-template)
roam-template
(concat roam-template "%?"))
:type 'plain
:no-save t))
file-path))
(defun org-roam-capture--expand-template ()
"Expand capture template with information from `org-roam-capture--info'."
(org-capture-put :template
(s-format (org-capture-get :template)
(lambda (key)
(or (s--aget org-roam-capture--info key)
(when-let ((v (completing-read (format "%s: " key ) nil)))
(push (cons key v) org-roam-capture--info)
v))) nil)))
(defun org-roam-capture--get-point ()
"Return exact point to file for org-capture-template.
The file to use is dependent on the context:
If the search is via title, it is assumed that the file does not
yet exist, and Org-roam will attempt to create new file.
If the search is via daily notes, 'time will be passed via
`org-roam-capture--info'. This is used to alter the default time
in `org-capture-templates'.
If the search is via ref, it is matched against the Org-roam database.
If there is no file with that ref, a file with that ref is created.
This function is used solely in Org-roam's capture templates: see
`org-roam-capture-templates'."
(let ((file-path (pcase org-roam-capture--context
('capture
(or (cdr (assoc 'file org-roam-capture--info))
(org-roam-capture--new-file)))
('title
(org-roam-capture--new-file))
('dailies
(org-capture-put :default-time (cdr (assoc 'time org-roam-capture--info)))
(org-roam-capture--new-file))
('ref
(let ((completions (org-roam--get-ref-path-completions))
(ref (cdr (assoc 'ref org-roam-capture--info))))
(or (cdr (assoc ref completions))
(org-roam-capture--new-file))))
(_ (error "Invalid org-roam-capture-context")))))
(org-roam-capture--expand-template)
(org-roam-capture--put :file-path file-path)
(while org-roam-capture-additional-template-props
(let ((prop (pop org-roam-capture-additional-template-props))
(val (pop org-roam-capture-additional-template-props)))
(org-roam-capture--put prop val)))
(set-buffer (org-capture-target-buffer file-path))
(widen)
(goto-char (point-max))))
(defun org-roam-capture--convert-template (template)
"Convert TEMPLATE from Org-roam syntax to `org-capture-templates' syntax."
(let* ((copy (copy-tree template))
converted
org-roam-plist
key
val)
;;put positional args on converted template
(dotimes (_ 5)
(push (pop copy) converted))
(while (setq key (pop copy)
val (pop copy))
(if (member key org-roam-capture--template-keywords)
(progn
(push val org-roam-plist)
(push key org-roam-plist))
(push key converted)
(push val converted)))
(append (nreverse converted) `(:org-roam ,org-roam-plist))))
(defun org-roam-capture--find-file-h ()
"Opens the newly created template file.
This is added as a hook to `org-capture-after-finalize-hook'.
Run the hooks defined in `org-roam-capture-after-find-file-hook'."
(unless org-note-abort
(when-let ((file-path (org-roam-capture--get :file-path)))
(find-file file-path))
(run-hooks 'org-roam-capture-after-find-file-hook))
(remove-hook 'org-capture-after-finalize-hook #'org-roam-capture--find-file-h))
(defcustom org-roam-capture-after-find-file-hook nil
"Hook that is run right after an Org-roam capture process is finalized.
Suitable for moving point."
:group 'org-roam
:type 'hook)
(defun org-roam--capture (&optional goto keys)
"Create a new file, and return the path to the edited file.
The templates are defined at `org-roam-capture-templates'. The
GOTO and KEYS argument have the same functionality as
`org-capture'."
(let ((org-capture-templates (mapcar #'org-roam-capture--convert-template org-roam-capture-templates)))
(when (= (length org-capture-templates) 1)
(setq keys (caar org-capture-templates)))
(add-hook 'org-capture-after-finalize-hook #'org-roam-capture--save-file-maybe-h)
(org-capture goto keys)))
;;;###autoload
(defun org-roam-capture ()
"Launches an `org-capture' process for a new or existing note.
This uses the templates defined at `org-roam-capture-templates'."
(interactive)
(when (org-roam-capture--in-process-p)
(user-error "Nested Org-roam capture processes not supported"))
(let* ((completions (org-roam--get-title-path-completions))
(title (org-roam-completion--completing-read "File: " completions))
(file-path (cdr (assoc title completions))))
(let ((org-roam-capture--info (list (cons 'title title)
(cons 'slug (org-roam--title-to-slug title))
(cons 'file file-path)))
(org-roam-capture--context 'capture))
(setq org-roam-capture-additional-template-props (list :capture-fn 'org-roam-capture))
(org-roam--capture))))
(provide 'org-roam-capture)
;;; org-roam-capture.el ends here

96
org-roam-compat.el Normal file
View File

@ -0,0 +1,96 @@
;;; org-roam-compat.el --- Compatibility Code -*- coding: utf-8; lexical-binding: t -*-
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/jethrokuan/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 1.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (s "1.12.0") (org "9.3") (emacsql "3.0.0") (emacsql-sqlite "1.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 file contains code needed for backward compatibility with older Emacsen
;; and previous versions of org-roam.
;;
;;; Code:
;;;; Library Requires
;;; Obsolete aliases (remove after next major release)
;;;; Functions
(define-obsolete-function-alias 'org-roam--capture-get-point 'org-roam-capture--get-point
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam-build-cache 'org-roam-db-build-cache
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam-sql 'org-roam-db-query
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam--get-db 'org-roam-db--get
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam--db-clear 'org-roam-db--clear
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam-show-graph 'org-roam-graph-show
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam--maybe-update-buffer
'org-roam-buffer--update-maybe "org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam--current-visibility
'org-roam-buffer--visibility "org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam-update 'org-roam-buffer-update
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam--set-width 'org-roam-buffer--set-width
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam--set-height 'org-roam-buffer--set-height
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam--set-up-buffer 'org-roam-buffer--get-create
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam-today 'org-roam-dailies-today
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam-tomorrow 'org-roam-dailies-tomorrow
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam-yesterday 'org-roam-dailies-yesterday
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam-date 'org-roam-dailies-date
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam-graph-show 'org-roam-graph
"org-roam 1.0.0")
(define-obsolete-function-alias 'org-roam-graph-build 'org-roam-graph
"org-roam 1.0.0")
;;;; Variables
(define-obsolete-variable-alias 'org-roam-graphviz-extra-options
'org-roam-graph-extra-config "org-roam 1.0.0")
(define-obsolete-variable-alias 'org-roam-grapher-extra-options
'org-roam-graph-extra-config "org-roam 1.0.0")
(make-obsolete-variable 'org-roam-graph-node-shape 'org-roam-graph-node-extra-config "org-roam 1.0.0")
(defcustom org-roam-graph-node-shape "ellipse"
"Shape of graph nodes."
:type 'string
:group 'org-roam)
(define-obsolete-variable-alias 'org-roam--db-connection
'org-roam-db--connection "org-roam 1.0.0")
(define-obsolete-variable-alias 'org-roam--current-buffer
'org-roam-buffer--current "org-roam 1.0.0")
(define-obsolete-variable-alias 'org-roam-date-title-format
'org-roam-dailies-capture-templates "org-roam 1.0.0")
(define-obsolete-variable-alias 'org-roam-date-filename-format
'org-roam-dailies-capture-templates "org-roam 1.0.0")
(provide 'org-roam-compat)
;;; org-roam-compat.el ends here

119
org-roam-completion.el Normal file
View File

@ -0,0 +1,119 @@
;;; org-roam-completion.el --- Roam Research replica with Org-mode -*- coding: utf-8; lexical-binding: t -*-
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/jethrokuan/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 1.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (s "1.12.0") (org "9.3") (emacsql "3.0.0") (emacsql-sqlite "1.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 library provides completion for org-roam.
;;; Code:
;;;; Library Requires
(require 'cl-lib)
(require 's)
(defvar helm-pattern)
(declare-function helm "ext:helm")
(declare-function helm-make-source "ext:helm-source" (name class &rest args) t)
(defcustom org-roam-completion-system 'default
"The completion system to be used by `org-roam'."
:type '(radio
(const :tag "Default" default)
(const :tag "Ido" ido)
(const :tag "Ivy" ivy)
(const :tag "Helm" helm)
(function :tag "Custom function"))
:group 'org-roam)
(defcustom org-roam-completion-fuzzy-match nil
"Whether to fuzzy match Org-roam's completion candidates."
:type 'boolean
:group 'org-roam)
(defun org-roam-completion--helm-candidate-transformer (candidates _source)
"Transforms CANDIDATES for Helm-based completing read.
SOURCE is not used."
(let ((prefix (propertize "[?] "
'face 'helm-ff-prefix)))
(cons (propertize helm-pattern
'display (concat prefix helm-pattern))
candidates)))
(cl-defun org-roam-completion--completing-read (prompt choices &key
require-match initial-input
action)
"Present a PROMPT with CHOICES and optional INITIAL-INPUT.
If REQUIRE-MATCH is t, the user must select one of the CHOICES.
Return user choice."
(let (res)
(setq res
(cond
((eq org-roam-completion-system 'ido)
(let ((candidates (mapcar #'car choices)))
(ido-completing-read prompt candidates nil require-match initial-input)))
((eq org-roam-completion-system 'default)
(completing-read prompt choices nil require-match initial-input))
((eq org-roam-completion-system 'ivy)
(if (fboundp 'ivy-read)
(ivy-read prompt choices
:initial-input initial-input
:require-match require-match
:action (prog1 action
(setq action nil))
:caller 'org-roam--completing-read
:re-builder (if org-roam-completion-fuzzy-match 'ivy--regex-fuzzy
'regexp-quote))
(user-error "Please install ivy from \
https://github.com/abo-abo/swiper")))
((eq org-roam-completion-system 'helm)
(unless (and (fboundp 'helm)
(fboundp 'helm-make-source))
(user-error "Please install helm from \
https://github.com/emacs-helm/helm"))
(let ((source (helm-make-source prompt 'helm-source-sync
:candidates (mapcar #'car choices)
:filtered-candidate-transformer
(and (not require-match)
#'org-roam-completion--helm-candidate-transformer)
:fuzzy-match org-roam-completion-fuzzy-match))
(buf (concat "*org-roam "
(s-downcase (s-chop-suffix ":" (s-trim prompt)))
"*")))
(or (helm :sources source
:action (if action
(prog1 action
(setq action nil))
#'identity)
:prompt prompt
:input initial-input
:buffer buf)
(keyboard-quit))))))
(if action
(funcall action res)
res)))
(provide 'org-roam-completion)
;;; org-roam-completion.el ends here

81
org-roam-dailies.el Normal file
View File

@ -0,0 +1,81 @@
;;; org-roam-dialies.el --- Roam Research replica with Org-mode -*- coding: utf-8; lexical-binding: t -*-
;;;
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/jethrokuan/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 1.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (s "1.12.0") (org "9.3") (emacsql "3.0.0") (emacsql-sqlite "1.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 library provides functionality for creating daily notes. This is a
;; concept borrowed from Roam Research.
;;
;;; Code:
;;; Library Requires
(require 'org-capture)
(require 'org-roam-capture)
(defvar org-roam-dailies-capture-templates
'(("d" "daily" plain (function org-roam-capture--get-point)
""
:immediate-finish t
:file-name "%<%Y-%m-%d>"
:head "#+TITLE: %<%Y-%m-%d>"))
"Capture templates for daily notes in Org-roam.")
;; Declarations
(declare-function org-roam--file-path-from-id "org-roam")
(defun org-roam-dailies--file-for-time (time)
"Create and find file for TIME."
(let ((org-roam-capture-templates org-roam-dailies-capture-templates)
(org-roam-capture--info (list (cons 'time time)))
(org-roam-capture--context 'dailies))
(add-hook 'org-capture-after-finalize-hook #'org-roam-capture--find-file-h)
(org-roam--capture)))
(defun org-roam-dailies-today ()
"Create and find the daily note for today."
(interactive)
(org-roam-dailies--file-for-time (current-time)))
(defun org-roam-dailies-tomorrow (n)
"Create and find the daily note for tomorrow.
With numeric argument N, use N days in the future."
(interactive "p")
(org-roam-dailies--file-for-time (time-add (* n 86400) (current-time))))
(defun org-roam-dailies-yesterday (n)
"Create and find the file for yesterday.
With numeric argument N, use N days in the past."
(interactive "p")
(org-roam-tomorrow (- n)))
(defun org-roam-dailies-date ()
"Create the file for any date using the calendar interface."
(interactive)
(let ((time (org-read-date nil 'to-time nil "Date: ")))
(org-roam-dailies--file-for-time time)))
(provide 'org-roam-dailies)
;;; org-roam-dailies.el ends here

409
org-roam-db.el Normal file
View File

@ -0,0 +1,409 @@
;;; org-roam-db.el --- Roam Research replica with Org-mode -*- coding: utf-8; lexical-binding: t -*-
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/jethrokuan/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 1.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (s "1.12.0") (org "9.3") (emacsql "3.0.0") (emacsql-sqlite "1.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 library is provides the underlying database api to org-roam
;;
;;; Code:
;;;; Library Requires
(eval-when-compile (require 'subr-x))
(require 'emacsql)
(require 'emacsql-sqlite)
(require 'org-roam-macs)
(defvar org-roam-directory)
(defvar org-roam-verbose)
(declare-function org-roam--extract-titles "org-roam")
(declare-function org-roam--extract-ref "org-roam")
(declare-function org-roam--extract-links "org-roam")
(declare-function org-roam--list-files "org-roam")
(declare-function org-roam-buffer--update-maybe "org-roam-buffer")
;;;; Options
(defcustom org-roam-db-location nil
"Location of the Org-roam database.
If this is non-nil, the Org-roam sqlite database is saved here.
It is the user's responsibility to set this correctly, especially
when used with multiple Org-roam instances."
:type 'string
:group 'org-roam)
(defconst org-roam-db--version 2)
(defconst org-roam-db--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.")
;;;; Core Functions
(defun org-roam-db--get ()
"Return the sqlite db file."
(interactive "P")
(or org-roam-db-location
(expand-file-name "org-roam.db" org-roam-directory)))
(defun org-roam-db--get-connection ()
"Return the database connection, if any."
(gethash (file-truename org-roam-directory)
org-roam-db--connection))
(defun org-roam-db ()
"Entrypoint to the Org-roam sqlite database.
Initializes and stores the database, and the database connection.
Performs a database upgrade when required."
(unless (and (org-roam-db--get-connection)
(emacsql-live-p (org-roam-db--get-connection)))
(let* ((db-file (org-roam-db--get))
(init-db (not (file-exists-p db-file))))
(make-directory (file-name-directory db-file) t)
(let ((conn (emacsql-sqlite db-file)))
(set-process-query-on-exit-flag (emacsql-process conn) nil)
(puthash (file-truename org-roam-directory)
conn
org-roam-db--connection)
(when init-db
(org-roam-db--init conn))
(let* ((version (caar (emacsql conn "PRAGMA user_version")))
(version (org-roam-db--maybe-update conn version)))
(cond
((> version org-roam-db--version)
(emacsql-close conn)
(user-error
"The Org-roam database was created with a newer Org-roam version. "
"You need to update the Org-roam package"))
((< version org-roam-db--version)
(emacsql-close conn)
(error "BUG: The Org-roam database scheme changed %s"
"and there is no upgrade path")))))))
(org-roam-db--get-connection))
;;;; Entrypoint: (org-roam-db-query)
(defun org-roam-db-query (sql &rest args)
"Run SQL query on Org-roam database with ARGS.
SQL can be either the emacsql vector representation, or a string."
(if (stringp sql)
(emacsql (org-roam-db) (apply #'format sql args))
(apply #'emacsql (org-roam-db) sql args)))
;;;; Schemata
(defconst org-roam-db--table-schemata
'((files
[(file :unique :primary-key)
(hash :not-null)
(last-modified :not-null)])
(links
[(from :not-null)
(to :not-null)
(type :not-null)
(properties :not-null)])
(titles
[(file :not-null)
titles])
(refs
[(ref :unique :not-null)
(file :not-null)])))
(defun org-roam-db--init (db)
"Initialize database DB with the correct schema and user version."
(emacsql-with-transaction db
(pcase-dolist (`(,table . ,schema) org-roam-db--table-schemata)
(emacsql db [:create-table $i1 $S2] table schema))
(emacsql db (format "PRAGMA user_version = %s" org-roam-db--version))))
(defun org-roam-db--maybe-update (db version)
"Upgrades the database schema for DB, if VERSION is old."
(emacsql-with-transaction db
'ignore
(when (= version 1)
(progn
(warn "No good way to perform a DB upgrade, rebuilding from scratch...")
(delete-file (org-roam-db--get))
(org-roam-db-build-cache)))
version))
(defun org-roam-db--close (&optional db)
"Closes the database connection for database DB.
If DB is nil, closes the database connection for the database in
the current `org-roam-directory'."
(unless db
(setq db (org-roam-db--get-connection)))
(when (and db (emacsql-live-p db))
(emacsql-close db)))
(defun org-roam-db--close-all ()
"Closes all database connections made by Org-roam."
(dolist (conn (hash-table-values org-roam-db--connection))
(org-roam-db--close conn)))
;;;; Database API
;;;;; Initialization
(defun org-roam-db--initialized-p ()
"Whether the cache has been initialized."
(and (file-exists-p (org-roam-db--get))
(> (caar (org-roam-db-query [:select (funcall count) :from titles]))
0)))
(defun org-roam-db--ensure-built ()
"Ensures that Org-roam cache is built."
(unless (org-roam-db--initialized-p)
(error "[Org-roam] your cache isn't built yet! Please run org-roam-db-build-cache")))
;;;;; Clearing
(defun org-roam-db--clear ()
"Clears all entries in the caches."
(interactive)
(when (file-exists-p (org-roam-db--get))
(org-roam-db-query [:delete :from files])
(org-roam-db-query [:delete :from titles])
(org-roam-db-query [:delete :from links])
(org-roam-db-query [:delete :from refs])))
(defun org-roam-db--clear-file (&optional filepath)
"Remove any related links to the file at FILEPATH.
This is equivalent to removing the node from the graph."
(let* ((path (or filepath
(buffer-file-name)))
(file (file-truename path)))
(org-roam-db-query [:delete :from files
:where (= file $s1)]
file)
(org-roam-db-query [:delete :from links
:where (= from $s1)]
file)
(org-roam-db-query [:delete :from titles
:where (= file $s1)]
file)
(org-roam-db-query [:delete :from refs
:where (= file $s1)]
file)))
;;;;; Insertion
(defun org-roam-db--insert-links (links)
"Insert LINKS into the Org-roam cache."
(org-roam-db-query
[:insert :into links
:values $v1]
links))
(defun org-roam-db--insert-titles (file titles)
"Insert TITLES for a FILE into the Org-roam cache."
(org-roam-db-query
[:insert :into titles
:values $v1]
(list (vector file titles))))
(defun org-roam-db--insert-ref (file ref)
"Insert REF for FILE into the Org-roam cache."
(org-roam-db-query
[:insert :into refs
:values $v1]
(list (vector ref file))))
;;;;; Fetching
(defun org-roam-db--get-current-files ()
"Return a hash-table of file to the hash of its file contents."
(let* ((current-files (org-roam-db-query [:select * :from files]))
(ht (make-hash-table :test #'equal)))
(dolist (row current-files)
(puthash (car row) (cadr row) ht))
ht))
(defun org-roam-db--get-titles (file)
"Return the titles of FILE from the cache."
(caar (org-roam-db-query [:select [titles] :from titles
:where (= file $s1)]
file
:limit 1)))
(defun org-roam-db--connected-component (file)
"Return all files reachable from/connected to FILE, including the file itself.
If the file does not have any connections, nil is returned."
(let* ((query "WITH RECURSIVE
links_of(file, link) AS
(WITH roamlinks AS (SELECT * FROM links WHERE \"type\" = '\"roam\"'),
citelinks AS (SELECT * FROM links
JOIN refs ON links.\"to\" = refs.\"ref\"
AND links.\"type\" = '\"cite\"')
SELECT \"from\", \"to\" FROM roamlinks UNION
SELECT \"to\", \"from\" FROM roamlinks UNION
SELECT \"file\", \"from\" FROM citelinks UNION
SELECT \"from\", \"file\" FROM citelinks),
connected_component(file) AS
(SELECT link FROM links_of WHERE file = $s1
UNION
SELECT link FROM links_of JOIN connected_component USING(file))
SELECT * FROM connected_component;")
(files (mapcar 'car-safe (emacsql (org-roam-db) query file))))
files))
(defun org-roam-db--links-with-max-distance (file max-distance)
"Return all files reachable from/connected to FILE in at most MAX-DISTANCE steps,
including the file itself. If the file does not have any connections, nil is returned."
(let* ((query "WITH RECURSIVE
links_of(file, link) AS
(WITH roamlinks AS (SELECT * FROM links WHERE \"type\" = '\"roam\"'),
citelinks AS (SELECT * FROM links
JOIN refs ON links.\"to\" = refs.\"ref\"
AND links.\"type\" = '\"cite\"')
SELECT \"from\", \"to\" FROM roamlinks UNION
SELECT \"to\", \"from\" FROM roamlinks UNION
SELECT \"file\", \"from\" FROM citelinks UNION
SELECT \"from\", \"file\" FROM citelinks),
-- Links are traversed in a breadth-first search. In order to calculate the
-- distance of nodes and to avoid following cyclic links, the visited nodes
-- are tracked in 'trace'.
connected_component(file, trace) AS
(VALUES($s1, json_array($s1))
UNION
SELECT lo.link, json_insert(cc.trace, '$[' || json_array_length(cc.trace) || ']', lo.link) FROM
connected_component AS cc JOIN links_of AS lo USING(file)
WHERE (
-- Avoid cycles by only visiting each file once.
(SELECT count(*) FROM json_each(cc.trace) WHERE json_each.value == lo.link) == 0
-- Note: BFS is cut off early here.
AND json_array_length(cc.trace) < ($s2 + 1)))
SELECT DISTINCT file, min(json_array_length(trace)) AS distance
FROM connected_component GROUP BY file ORDER BY distance;")
;; In principle the distance would be available in the second column.
(files (mapcar 'car-safe (emacsql (org-roam-db) query file max-distance))))
files))
;;;;; Updating
(defun org-roam-db--update-titles ()
"Update the title of the current buffer into the cache."
(let ((file (file-truename (buffer-file-name))))
(org-roam-db-query [:delete :from titles
:where (= file $s1)]
file)
(org-roam-db--insert-titles file (org-roam--extract-titles))))
(defun org-roam-db--update-refs ()
"Update the ref of the current buffer into the cache."
(let ((file (file-truename (buffer-file-name))))
(org-roam-db-query [:delete :from refs
:where (= file $s1)]
file)
(when-let ((ref (org-roam--extract-ref)))
(org-roam-db--insert-ref file ref))))
(defun org-roam-db--update-cache-links ()
"Update the file links of the current buffer in the cache."
(let ((file (file-truename (buffer-file-name))))
(org-roam-db-query [:delete :from links
:where (= from $s1)]
file)
(when-let ((links (org-roam--extract-links)))
(org-roam-db--insert-links links))))
(defun org-roam-db--update-file (&optional file-path)
"Update Org-roam cache for FILE-PATH."
(let (buf)
(if file-path
(setq buf (find-file-noselect file-path))
(setq buf (current-buffer)))
(with-current-buffer buf
(save-excursion
(org-roam-db--update-titles)
(org-roam-db--update-refs)
(org-roam-db--update-cache-links)
(org-roam-buffer--update-maybe :redisplay t)))))
;;;;; org-roam-db-build-cache
(defun org-roam-db-build-cache ()
"Build the cache for `org-roam-directory'."
(interactive)
(org-roam-db--close) ;; Force a reconnect
(org-roam-db) ;; To initialize the database, no-op if already initialized
(let* ((org-roam-files (org-roam--list-files org-roam-directory))
(current-files (org-roam-db--get-current-files))
(time (current-time))
all-files all-links all-titles all-refs)
(dolist (file org-roam-files)
(org-roam--with-temp-buffer
(insert-file-contents file)
(let ((contents-hash (secure-hash 'sha1 (current-buffer))))
(unless (string= (gethash file current-files)
contents-hash)
(org-roam-db--clear-file file)
(setq all-files
(cons (vector file contents-hash time) all-files))
(when-let (links (org-roam--extract-links file))
(setq all-links (append links all-links)))
(let ((titles (org-roam--extract-titles)))
(setq all-titles (cons (vector file titles) all-titles)))
(when-let ((ref (org-roam--extract-ref)))
(setq all-refs (cons (vector ref file) all-refs))))
(remhash file current-files))))
(dolist (file (hash-table-keys current-files))
;; These files are no longer around, remove from cache...
(org-roam-db--clear-file file))
(when all-files
(org-roam-db-query
[:insert :into files
:values $v1]
all-files))
(when all-links
(org-roam-db-query
[:insert :into links
:values $v1]
all-links))
(when all-titles
(org-roam-db-query
[:insert :into titles
:values $v1]
all-titles))
(when all-refs
(org-roam-db-query
[:insert :into refs
:values $v1]
all-refs))
(let ((stats (list :files (length all-files)
:links (length all-links)
:titles (length all-titles)
:refs (length all-refs)
:deleted (length (hash-table-keys current-files)))))
(when org-roam-verbose
(message "files: %s, links: %s, titles: %s, refs: %s, deleted: %s"
(plist-get stats :files)
(plist-get stats :links)
(plist-get stats :titles)
(plist-get stats :refs)
(plist-get stats :deleted)))
stats)))
(provide 'org-roam-db)
;;; org-roam-db.el ends here

268
org-roam-graph.el Normal file
View File

@ -0,0 +1,268 @@
;;; org-roam-graph.el --- Roam Research replica with Org-mode -*- coding: utf-8; lexical-binding: t -*-
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/jethrokuan/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 1.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (s "1.12.0") (org "9.3") (emacsql "3.0.0") (emacsql-sqlite "1.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 library provides graphing functionality for org-roam.
;;
;;; Code:
(require 'xml) ;xml-escape-string
(require 's) ;s-truncate, s-replace
(require 'org-roam-macs)
(require 'org-roam-db)
;;;; Declarations
(defvar org-roam-directory)
(declare-function org-roam--org-roam-file-p "org-roam")
(declare-function org-roam--path-to-slug "org-roam")
;;;; Options
(defcustom org-roam-graph-viewer (executable-find "firefox")
"Method to view the org-roam graph.
It may be one of the following:
- a string representing the path to the executable for viewing the graph.
- a function accepting a single argument: the graph file path.
- nil uses `view-file' to view the graph."
:type '(choice
(string :tag "Path to executable")
(function :tag "Function to display graph" eww-open-file)
(const :tag "view-file"))
:group 'org-roam)
(defcustom org-roam-graph-executable (executable-find "dot")
"Path to graphing executable."
:type 'string
:group 'org-roam)
(defcustom org-roam-graph-extra-config nil
"Extra options passed to graphviz.
Example:
'((\"rankdir\" . \"LR\"))"
:type '(alist)
:group 'org-roam)
(defcustom org-roam-graph-node-extra-config nil
"Extra options for graphviz nodes.
Example:
'((\"color\" . \"skyblue\"))"
:type '(alist)
:group 'org-roam)
(defcustom org-roam-graph-edge-extra-config nil
"Extra options for graphviz edges.
Example:
'((\"dir\" . \"back\"))"
:type '(alist)
:group 'org-roam)
(defcustom org-roam-graph-edge-cites-extra-config '(("color" . "red"))
"Extra options for graphviz edges for citation links.
Example:
'((\"dir\" . \"back\"))"
:type '(alist)
:group 'org-roam)
(defcustom org-roam-graph-max-title-length 100
"Maximum length of titles in graph nodes."
:type 'number
:group 'org-roam)
(defcustom org-roam-graph-exclude-matcher nil
"Matcher for excluding nodes from the generated graph.
Any nodes and links for file paths matching this string is
excluded from the graph.
If value is a string, the string is the only matcher.
If value is a list, all file paths matching any of the strings
are excluded."
:type '(choice
(string :tag "Matcher")
(list :tag "Matchers"))
:group 'org-roam)
;;;; Functions
(defun org-roam-graph--expand-matcher (col &optional negate where)
"Return the exclusion regexp from `org-roam-graph-exclude-matcher'.
COL is the symbol to be matched against. if NEGATE, add :not to sql query.
set WHERE to true if WHERE query already exists."
(let ((matchers (pcase org-roam-graph-exclude-matcher
('nil nil)
((pred stringp) `(,(concat "%" org-roam-graph-exclude-matcher "%")))
((pred listp) (mapcar (lambda (m)
(concat "%" m "%"))
org-roam-graph-exclude-matcher))
(_ (error "Invalid org-roam-graph-exclude-matcher"))))
res)
(dolist (match matchers)
(if where
(push :and res)
(push :where res)
(setq where t))
(push col res)
(when negate
(push :not res))
(push :like res)
(push match res))
(nreverse res)))
(defun org-roam-graph--dot-option (option &optional wrap-key wrap-val)
"Return dot string of form KEY=VAL for OPTION cons.
If WRAP-KEY is non-nil it wraps the KEY.
If WRAP-VAL is non-nil it wraps the VAL."
(concat wrap-key (car option) wrap-key
"="
wrap-val (cdr option) wrap-val))
(defun org-roam-graph--dot (node-query)
"Build the graphviz dot string for NODE-QUERY.
The Org-roam database titles table is read, to obtain the list of titles.
The links table is then read to obtain all directed links, and formatted
into a digraph."
(org-roam-db--ensure-built)
(org-roam--with-temp-buffer
(let* ((nodes (org-roam-db-query node-query))
(edges-query
`[:with selected :as [:select [file] :from ,node-query]
:select :distinct [to from] :from links
:where (and (in to selected) (in from selected))])
(edges-cites-query
`[:with selected :as [:select [file] :from ,node-query]
:select :distinct [file from]
:from links :inner :join refs :on (and (= links:to refs:ref)
(= links:type "cite"))
:where (and (in file selected) (in from selected))])
(edges (org-roam-db-query edges-query))
(edges-cites (org-roam-db-query edges-cites-query)))
(insert "digraph \"org-roam\" {\n")
(dolist (option org-roam-graph-extra-config)
(insert (org-roam-graph--dot-option option) ";\n"))
(dolist (attribute '("node" "edge"))
(insert (format " %s [%s];\n" attribute
(mapconcat #'org-roam-graph--dot-option
(symbol-value
(intern (concat "org-roam-graph-" attribute "-extra-config")))
","))))
(dolist (node nodes)
(let* ((file (xml-escape-string (car node)))
(title (or (caadr node)
(org-roam--path-to-slug file)))
(shortened-title (s-truncate org-roam-graph-max-title-length title))
(node-properties
`(("label" . ,(s-replace "\"" "\\\"" shortened-title))
("URL" . ,(concat "org-protocol://roam-file?file=" (url-hexify-string file)))
("tooltip" . ,(xml-escape-string title)))))
(insert
(format " \"%s\" [%s];\n" file
(mapconcat (lambda (n)
(org-roam-graph--dot-option n nil "\""))
node-properties ",")))))
(dolist (edge edges)
(insert (apply #'format `(" \"%s\" -> \"%s\";\n"
,@(mapcar #'xml-escape-string edge)))))
(insert (format " edge [%s];\n"
(mapconcat #'org-roam-graph--dot-option
org-roam-graph-edge-cites-extra-config ",")))
(dolist (edge edges-cites)
(insert (apply #'format `(" \"%s\" -> \"%s\";\n"
,@(mapcar #'xml-escape-string edge)))))
(insert "}")
(buffer-string))))
(defun org-roam-graph--build (&optional node-query)
"Generate a graph showing the relations between nodes in NODE-QUERY."
(unless org-roam-graph-executable
(user-error "Can't find %s executable. Please check if it is in your path"
org-roam-graph-executable))
(let* ((node-query (or node-query
`[:select [file titles]
:from titles
,@(org-roam-graph--expand-matcher 'file t)]))
(graph (org-roam-graph--dot node-query))
(temp-dot (make-temp-file "graph." nil ".dot" graph))
(temp-graph (make-temp-file "graph." nil ".svg")))
(call-process org-roam-graph-executable nil 0 nil
temp-dot "-Tsvg" "-o" temp-graph)
temp-graph))
(defun org-roam-graph--open (file)
"Open FILE using `org-roam-graph-viewer' with `view-file' as a fallback."
(pcase org-roam-graph-viewer
((pred stringp)
(if (executable-find org-roam-graph-viewer)
(condition-case err
(call-process org-roam-graph-viewer nil 0 nil file)
((error (user-error "Failed to open org-roam graph: %s" err))))
(user-error "Executable not found: \"%s\"" org-roam-graph-viewer)))
((pred functionp) (funcall org-roam-graph-viewer file))
('nil (view-file file))
(_ (signal 'wrong-type-argument `((functionp stringp null) ,org-roam-graph-viewer)))))
(defun org-roam-graph--build-connected-component (file &optional max-distance)
"Build a graph of nodes connected to FILE.
If MAX-DISTANCE is non-nil, limit nodes to MAX-DISTANCE steps."
(let* ((file (file-truename file))
(files (or (if (and max-distance (>= max-distance 0))
(org-roam-db--links-with-max-distance file max-distance)
(org-roam-db--connected-component file))
(list file)))
(query `[:select [file titles]
:from titles
:where (in file [,@files])]))
(org-roam-graph--build query)))
;;;; Commands
;;;###autoload
(defun org-roam-graph (&optional arg file node-query)
"Build and possibly display a graph for FILE from NODE-QUERY.
If FILE is nil, default to current buffer's file name.
ARG may be any of the following values:
- nil show the graph.
- `\\[universal-argument]' show the graph for FILE.
- `\\[universal-argument]' N show the graph for FILE limiting nodes to N steps.
- `\\[universal-argument] \\[universal-argument]' build the graph.
- `\\[universal-argument]' - build the graph for FILE.
- `\\[universal-argument]' -N build the graph for FILE limiting nodes to N steps."
(interactive "P")
(let ((file (or file (buffer-file-name))))
(unless file
(user-error "Cannot build graph for nil file. Is current buffer visiting a file?"))
(unless (org-roam--org-roam-file-p file)
(user-error "\"%s\" is not an org-roam file" file))
(pcase arg
('nil (org-roam-graph--open (org-roam-graph--build node-query)))
('(4) (org-roam-graph--open (org-roam-graph--build-connected-component file)))
((pred integerp) (let ((graph (org-roam-graph--build-connected-component (buffer-file-name) (abs arg))))
(when (>= arg 0)
(org-roam-graph--open graph))))
('(16) (org-roam-graph--build node-query))
('- (org-roam-graph--build-connected-component file))
(_ (user-error "Unrecognized ARG: %s" arg)))))
(provide 'org-roam-graph)
;;; org-roam-graph.el ends here

48
org-roam-macs.el Normal file
View File

@ -0,0 +1,48 @@
;;; org-roam-macs.el --- Roam Research replica with Org-mode -*- coding: utf-8; lexical-binding: t -*-
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/jethrokuan/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 1.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (s "1.12.0") (org "9.3") (emacsql "3.0.0") (emacsql-sqlite "1.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 library implements macros used throughout org-roam
;;
;;
;;; Code:
;;;; Library Requires
(defmacro org-roam--with-temp-buffer (&rest body)
"Execute BODY within a temp buffer.
Like `with-temp-buffer', but propagates `org-roam-directory'."
(declare (indent 0) (debug t))
(let ((current-org-roam-directory (make-symbol "current-org-roam-directory")))
`(let ((,current-org-roam-directory org-roam-directory))
(with-temp-buffer
(let ((org-roam-directory ,current-org-roam-directory))
,@body)))))
(provide 'org-roam-macs)
;;; org-roam-macs.el ends here

View File

@ -4,8 +4,8 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/jethrokuan/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 1.0.0-rc1
;; Package-Requires: ((emacs "26.1") (org "9.0"))
;; Version: 1.1.0
;; Package-Requires: ((emacs "26.1") (org "9.3"))
;; This file is NOT part of GNU Emacs.
@ -35,23 +35,10 @@
;; 2. "roam-ref": This protocol creates or opens a note with the given REF
;;
;;; Code:
(require 'org-protocol)
(require 'org-roam)
(declare-function org-roam-find-ref "org-roam" (&optional info))
(declare-function org-roam--capture-get-point "org-roam" ())
(defvar org-roam-ref-capture-templates
'(("r" "ref" plain (function org-roam--capture-get-point)
""
:file-name "${slug}"
:head "#+TITLE: ${title}
#+ROAM_KEY: ${ref}\n"
:unnarrowed t))
"The Org-roam templates used during a capture from the roam-ref protocol.
Details on how to specify for the template is given in `org-roam-capture-templates'.")
;;;; Functions
(defun org-roam-protocol-open-ref (info)
"Process an org-protocol://roam-ref?ref= style url with INFO.
@ -67,15 +54,15 @@ It opens or creates a note with the given ref.
(val (cdr k.v)))
(cons key (org-link-decode val)))) alist)))
(unless (assoc 'ref decoded-alist)
(error "No ref key provided."))
(error "No ref key provided"))
(when-let ((title (cdr (assoc 'title decoded-alist))))
(push (cons 'slug (org-roam--title-to-slug title)) decoded-alist))
(let* ((org-roam-capture-templates org-roam-ref-capture-templates)
(org-roam--capture-context 'ref)
(org-roam--capture-info decoded-alist)
(let* ((org-roam-capture-templates org-roam-capture-ref-templates)
(org-roam-capture--context 'ref)
(org-roam-capture--info decoded-alist)
(template (cdr (assoc 'template decoded-alist))))
(raise-frame)
(org-roam-capture nil template)
(org-roam--capture nil template)
(message "Item captured.")))
nil)

File diff suppressed because it is too large Load Diff

View File

@ -31,273 +31,280 @@
(require 'org-roam)
(require 'dash)
(defun abs-path (file-path)
(defun org-roam-test-abs-path (file-path)
"Get absolute FILE-PATH from `org-roam-directory'."
(file-truename (expand-file-name file-path org-roam-directory)))
(defun org-roam--test-find-new-file (path)
(let ((path (abs-path path)))
(defun org-roam-test-find-new-file (path)
"PATH."
(let ((path (org-roam-test-abs-path path)))
(make-directory (file-name-directory path) t)
(find-file path)))
(defvar org-roam--tests-directory (file-truename (concat default-directory "tests/roam-files"))
(defvar org-roam-test-directory (file-truename (concat default-directory "tests/roam-files"))
"Directory containing org-roam test org files.")
(defun org-roam--test-init ()
(org-roam--db-close)
(let ((original-dir org-roam--tests-directory)
(defun org-roam-test-init ()
"."
(org-roam-db--close)
(let ((original-dir org-roam-test-directory)
(new-dir (expand-file-name (make-temp-name "org-roam") temporary-file-directory)))
(copy-directory original-dir new-dir)
(setq org-roam-directory new-dir)
(org-roam-mode +1)))
;;; Tests
(describe "org-roam-build-cache"
(it "initializes correctly"
(org-roam--test-init)
(org-roam-build-cache)
(describe "org-roam-db-build-cache"
(it "initializes correctly"
(org-roam-test-init)
(org-roam-db-build-cache)
;; Cache
(expect (caar (org-roam-sql [:select (funcall count) :from files])) :to-be 8)
(expect (caar (org-roam-sql [:select (funcall count) :from file-links])) :to-be 5)
(expect (caar (org-roam-sql [:select (funcall count) :from titles])) :to-be 8)
(expect (caar (org-roam-sql [:select (funcall count) :from titles
:where titles :is-null])) :to-be 2)
(expect (caar (org-roam-sql [:select (funcall count) :from refs])) :to-be 1)
;; Cache
(expect (caar (org-roam-db-query [:select (funcall count) :from files])) :to-be 8)
(expect (caar (org-roam-db-query [:select (funcall count) :from links])) :to-be 5)
(expect (caar (org-roam-db-query [:select (funcall count) :from titles])) :to-be 8)
(expect (caar (org-roam-db-query [:select (funcall count) :from titles
:where titles :is-null])) :to-be 2)
(expect (caar (org-roam-db-query [:select (funcall count) :from refs])) :to-be 1)
;; TODO Test files
;; TODO Test files
;; Links -- File-from
(expect (caar (org-roam-sql [:select (funcall count) :from file-links
:where (= file-from $s1)]
(abs-path "foo.org"))) :to-be 1)
(expect (caar (org-roam-sql [:select (funcall count) :from file-links
:where (= file-from $s1)]
(abs-path "nested/bar.org"))) :to-be 2)
;; Links
(expect (caar (org-roam-db-query [:select (funcall count) :from links
:where (= from $s1)]
(org-roam-test-abs-path "foo.org"))) :to-be 1)
(expect (caar (org-roam-db-query [:select (funcall count) :from links
:where (= from $s1)]
(org-roam-test-abs-path "nested/bar.org"))) :to-be 2)
;; Links -- File-to
(expect (caar (org-roam-sql [:select (funcall count) :from file-links
:where (= file-to $s1)]
(abs-path "nested/foo.org"))) :to-be 1)
(expect (caar (org-roam-sql [:select (funcall count) :from file-links
:where (= file-to $s1)]
(abs-path "nested/bar.org"))) :to-be 1)
(expect (caar (org-roam-sql [:select (funcall count) :from file-links
:where (= file-to $s1)]
(abs-path "unlinked.org"))) :to-be 0)
;; TODO Test titles
(expect (org-roam-sql [:select * :from titles])
:to-have-same-items-as
(list (list (abs-path "alias.org")
(list "t1" "a1" "a 2"))
(list (abs-path "bar.org")
(list "Bar"))
(list (abs-path "foo.org")
(list "Foo"))
(list (abs-path "nested/bar.org")
(list "Nested Bar"))
(list (abs-path "nested/foo.org")
(list "Nested Foo"))
(list (abs-path "no-title.org") nil)
(list (abs-path "web_ref.org") nil)
(list (abs-path "unlinked.org")
(list "Unlinked"))))
;; Links -- File-to
(expect (caar (org-roam-db-query [:select (funcall count) :from links
:where (= to $s1)]
(org-roam-test-abs-path "nested/foo.org"))) :to-be 1)
(expect (caar (org-roam-db-query [:select (funcall count) :from links
:where (= to $s1)]
(org-roam-test-abs-path "nested/bar.org"))) :to-be 1)
(expect (caar (org-roam-db-query [:select (funcall count) :from links
:where (= to $s1)]
(org-roam-test-abs-path "unlinked.org"))) :to-be 0)
;; TODO Test titles
(expect (org-roam-db-query [:select * :from titles])
:to-have-same-items-as
(list (list (org-roam-test-abs-path "alias.org")
(list "t1" "a1" "a 2"))
(list (org-roam-test-abs-path "bar.org")
(list "Bar"))
(list (org-roam-test-abs-path "foo.org")
(list "Foo"))
(list (org-roam-test-abs-path "nested/bar.org")
(list "Nested Bar"))
(list (org-roam-test-abs-path "nested/foo.org")
(list "Nested Foo"))
(list (org-roam-test-abs-path "no-title.org") nil)
(list (org-roam-test-abs-path "web_ref.org") nil)
(list (org-roam-test-abs-path "unlinked.org")
(list "Unlinked"))))
(expect (org-roam-sql [:select * :from refs])
:to-have-same-items-as
(list (list "https://google.com/" (abs-path "web_ref.org"))))
(expect (org-roam-db-query [:select * :from refs])
:to-have-same-items-as
(list (list "https://google.com/" (org-roam-test-abs-path "web_ref.org"))))
;; Expect rebuilds to be really quick (nothing changed)
(expect (org-roam-build-cache)
:to-equal
(list :files 0 :links 0 :titles 0 :refs 0 :deleted 0))))
;; Expect rebuilds to be really quick (nothing changed)
(expect (org-roam-db-build-cache)
:to-equal
(list :files 0 :links 0 :titles 0 :refs 0 :deleted 0))))
(describe "org-roam-insert"
(before-each
(org-roam--test-init)
(org-roam--db-clear)
(org-roam-build-cache))
(before-each
(org-roam-test-init)
(org-roam-db--clear)
(org-roam-db-build-cache))
(it "temp1 -> foo"
(let ((buf (org-roam--test-find-new-file "temp1.org")))
(with-current-buffer buf
(with-simulated-input
"Foo RET"
(org-roam-insert nil))))
(expect (buffer-string) :to-match (regexp-quote "file:foo.org")))
(it "temp1 -> foo"
(let ((buf (org-roam-test-find-new-file "temp1.org")))
(with-current-buffer buf
(with-simulated-input
"Foo RET"
(org-roam-insert nil))))
(expect (buffer-string) :to-match (regexp-quote "file:foo.org")))
(it "temp2 -> nested/foo"
(let ((buf (org-roam--test-find-new-file "temp2.org")))
(with-current-buffer buf
(with-simulated-input
"Nested SPC Foo RET"
(org-roam-insert nil))))
(expect (buffer-string) :to-match (regexp-quote "file:nested/foo.org")))
(it "temp2 -> nested/foo"
(let ((buf (org-roam-test-find-new-file "temp2.org")))
(with-current-buffer buf
(with-simulated-input
"Nested SPC Foo RET"
(org-roam-insert nil))))
(expect (buffer-string) :to-match (regexp-quote "file:nested/foo.org")))
(it "nested/temp3 -> foo"
(let ((buf (org-roam--test-find-new-file "nested/temp3.org")))
(with-current-buffer buf
(with-simulated-input
"Foo RET"
(org-roam-insert nil))))
(expect (buffer-string) :to-match (regexp-quote "file:../foo.org")))
(it "nested/temp3 -> foo"
(let ((buf (org-roam-test-find-new-file "nested/temp3.org")))
(with-current-buffer buf
(with-simulated-input
"Foo RET"
(org-roam-insert nil))))
(expect (buffer-string) :to-match (regexp-quote "file:../foo.org")))
(it "a/b/temp4 -> nested/foo"
(let ((buf (org-roam--test-find-new-file "a/b/temp4.org")))
(with-current-buffer buf
(with-simulated-input
"Nested SPC Foo RET"
(org-roam-insert nil))))
(expect (buffer-string) :to-match (regexp-quote "file:../../nested/foo.org"))))
(it "a/b/temp4 -> nested/foo"
(let ((buf (org-roam-test-find-new-file "a/b/temp4.org")))
(with-current-buffer buf
(with-simulated-input
"Nested SPC Foo RET"
(org-roam-insert nil))))
(expect (buffer-string) :to-match (regexp-quote "file:../../nested/foo.org"))))
(describe "rename file updates cache"
(before-each
(org-roam--test-init)
(org-roam--db-clear)
(org-roam-build-cache))
(before-each
(org-roam-test-init)
(org-roam-db--clear)
(org-roam-db-build-cache))
(it "foo -> new_foo"
(rename-file (abs-path "foo.org")
(abs-path "new_foo.org"))
;; Cache should be cleared of old file
(expect (caar (org-roam-sql [:select (funcall count)
:from titles
:where (= file $s1)]
(abs-path "foo.org"))) :to-be 0)
(expect (caar (org-roam-sql [:select (funcall count)
:from refs
:where (= file $s1)]
(abs-path "foo.org"))) :to-be 0)
(expect (caar (org-roam-sql [:select (funcall count)
:from file-links
:where (= file-from $s1)]
(abs-path "foo.org"))) :to-be 0)
(it "foo -> new_foo"
(rename-file (org-roam-test-abs-path "foo.org")
(org-roam-test-abs-path "new_foo.org"))
;; Cache should be cleared of old file
(expect (caar (org-roam-db-query [:select (funcall count)
:from titles
:where (= file $s1)]
(org-roam-test-abs-path "foo.org"))) :to-be 0)
(expect (caar (org-roam-db-query [:select (funcall count)
:from refs
:where (= file $s1)]
(org-roam-test-abs-path "foo.org"))) :to-be 0)
(expect (caar (org-roam-db-query [:select (funcall count)
:from links
:where (= from $s1)]
(org-roam-test-abs-path "foo.org"))) :to-be 0)
;; Cache should be updated
(expect (org-roam-sql [:select [file-to]
:from file-links
:where (= file-from $s1)]
(abs-path "new_foo.org"))
:to-have-same-items-as
(list (list (abs-path "bar.org"))))
(expect (org-roam-sql [:select [file-from]
:from file-links
:where (= file-to $s1)]
(abs-path "new_foo.org"))
:to-have-same-items-as
(list (list (abs-path "nested/bar.org"))))
;; Cache should be updated
(expect (org-roam-db-query [:select [to]
:from links
:where (= from $s1)]
(org-roam-test-abs-path "new_foo.org"))
:to-have-same-items-as
(list (list (org-roam-test-abs-path "bar.org"))))
(expect (org-roam-db-query [:select [from]
:from links
:where (= to $s1)]
(org-roam-test-abs-path "new_foo.org"))
:to-have-same-items-as
(list (list (org-roam-test-abs-path "nested/bar.org"))))
;; Links are updated
(expect (with-temp-buffer
(insert-file-contents (abs-path "nested/bar.org"))
(buffer-string))
:to-match
(regexp-quote "[[file:../new_foo.org][Foo]]")))
;; Links are updated
(expect (with-temp-buffer
(insert-file-contents (org-roam-test-abs-path "nested/bar.org"))
(buffer-string))
:to-match
(regexp-quote "[[file:../new_foo.org][Foo]]")))
(it "foo -> foo with spaces"
(rename-file (abs-path "foo.org")
(abs-path "foo with spaces.org"))
;; Cache should be cleared of old file
(expect (caar (org-roam-sql [:select (funcall count)
:from titles
:where (= file $s1)]
(abs-path "foo.org"))) :to-be 0)
(expect (caar (org-roam-sql [:select (funcall count)
:from refs
:where (= file $s1)]
(abs-path "foo.org"))) :to-be 0)
(expect (caar (org-roam-sql [:select (funcall count)
:from file-links
:where (= file-from $s1)]
(abs-path "foo.org"))) :to-be 0)
(it "foo -> foo with spaces"
(rename-file (org-roam-test-abs-path "foo.org")
(org-roam-test-abs-path "foo with spaces.org"))
;; Cache should be cleared of old file
(expect (caar (org-roam-db-query [:select (funcall count)
:from titles
:where (= file $s1)]
(org-roam-test-abs-path "foo.org"))) :to-be 0)
(expect (caar (org-roam-db-query [:select (funcall count)
:from refs
:where (= file $s1)]
(org-roam-test-abs-path "foo.org"))) :to-be 0)
(expect (caar (org-roam-db-query [:select (funcall count)
:from links
:where (= from $s1)]
(org-roam-test-abs-path "foo.org"))) :to-be 0)
;; Cache should be updated
(expect (org-roam-sql [:select [file-to]
:from file-links
:where (= file-from $s1)]
(abs-path "foo with spaces.org"))
:to-have-same-items-as
(list (list (abs-path "bar.org"))))
(expect (org-roam-sql [:select [file-from]
:from file-links
:where (= file-to $s1)]
(abs-path "foo with spaces.org"))
:to-have-same-items-as
(list (list (abs-path "nested/bar.org"))))
;; Cache should be updated
(expect (org-roam-db-query [:select [to]
:from links
:where (= from $s1)]
(org-roam-test-abs-path "foo with spaces.org"))
:to-have-same-items-as
(list (list (org-roam-test-abs-path "bar.org"))))
(expect (org-roam-db-query [:select [from]
:from links
:where (= to $s1)]
(org-roam-test-abs-path "foo with spaces.org"))
:to-have-same-items-as
(list (list (org-roam-test-abs-path "nested/bar.org"))))
;; Links are updated
(expect (with-temp-buffer
(insert-file-contents (abs-path "nested/bar.org"))
(buffer-string))
:to-match
(regexp-quote "[[file:../foo with spaces.org][Foo]]")))
;; Links are updated
(expect (with-temp-buffer
(insert-file-contents (org-roam-test-abs-path "nested/bar.org"))
(buffer-string))
:to-match
(regexp-quote "[[file:../foo with spaces.org][Foo]]")))
(it "no-title -> meaningful-title"
(rename-file (abs-path "no-title.org")
(abs-path "meaningful-title.org"))
;; File has no forward links
(expect (caar (org-roam-sql [:select (funcall count)
:from file-links
:where (= file-from $s1)]
(abs-path "no-title.org"))) :to-be 0)
(expect (caar (org-roam-sql [:select (funcall count)
:from file-links
:where (= file-from $s1)]
(abs-path "meaningful-title.org"))) :to-be 1)
(it "no-title -> meaningful-title"
(rename-file (org-roam-test-abs-path "no-title.org")
(org-roam-test-abs-path "meaningful-title.org"))
;; File has no forward links
(expect (caar (org-roam-db-query [:select (funcall count)
:from links
:where (= from $s1)]
(org-roam-test-abs-path "no-title.org"))) :to-be 0)
(expect (caar (org-roam-db-query [:select (funcall count)
:from links
:where (= from $s1)]
(org-roam-test-abs-path "meaningful-title.org"))) :to-be 1)
;; Links are updated with the appropriate name
(expect (with-temp-buffer
(insert-file-contents (abs-path "meaningful-title.org"))
(buffer-string))
:to-match
(regexp-quote "[[file:meaningful-title.org][meaningful-title]]")))
;; Links are updated with the appropriate name
(expect (with-temp-buffer
(insert-file-contents (org-roam-test-abs-path "meaningful-title.org"))
(buffer-string))
:to-match
(regexp-quote "[[file:meaningful-title.org][meaningful-title]]")))
(it "web_ref -> hello"
(expect (org-roam-sql
[:select [file] :from refs
:where (= ref $s1)]
"https://google.com/")
:to-equal
(list (list (abs-path "web_ref.org"))))
(rename-file (abs-path "web_ref.org")
(abs-path "hello.org"))
(expect (org-roam-sql
[:select [file] :from refs
:where (= ref $s1)]
"https://google.com/")
:to-equal (list (list (abs-path "hello.org"))))
(expect (caar (org-roam-sql
[:select [ref] :from refs
:where (= file $s1)]
(abs-path "web_ref.org")))
:to-equal nil)))
(it "web_ref -> hello"
(expect (org-roam-db-query
[:select [file] :from refs
:where (= ref $s1)]
"https://google.com/")
:to-equal
(list (list (org-roam-test-abs-path "web_ref.org"))))
(rename-file (org-roam-test-abs-path "web_ref.org")
(org-roam-test-abs-path "hello.org"))
(expect (org-roam-db-query
[:select [file] :from refs
:where (= ref $s1)]
"https://google.com/")
:to-equal (list (list (org-roam-test-abs-path "hello.org"))))
(expect (caar (org-roam-db-query
[:select [ref] :from refs
:where (= file $s1)]
(org-roam-test-abs-path "web_ref.org")))
:to-equal nil)))
(describe "delete file updates cache"
(before-each
(org-roam--test-init)
(org-roam--db-clear)
(org-roam-build-cache)
(sleep-for 1))
(before-each
(org-roam-test-init)
(org-roam-db--clear)
(org-roam-db-build-cache)
(sleep-for 1))
(it "delete foo"
(delete-file (abs-path "foo.org"))
(expect (caar (org-roam-sql [:select (funcall count)
:from titles
:where (= file $s1)]
(abs-path "foo.org"))) :to-be 0)
(expect (caar (org-roam-sql [:select (funcall count)
:from refs
:where (= file $s1)]
(abs-path "foo.org"))) :to-be 0)
(expect (caar (org-roam-sql [:select (funcall count)
:from file-links
:where (= file-from $s1)]
(abs-path "foo.org"))) :to-be 0))
(it "delete foo"
(delete-file (org-roam-test-abs-path "foo.org"))
(expect (caar (org-roam-db-query [:select (funcall count)
:from titles
:where (= file $s1)]
(org-roam-test-abs-path "foo.org"))) :to-be 0)
(expect (caar (org-roam-db-query [:select (funcall count)
:from refs
:where (= file $s1)]
(org-roam-test-abs-path "foo.org"))) :to-be 0)
(expect (caar (org-roam-db-query [:select (funcall count)
:from links
:where (= from $s1)]
(org-roam-test-abs-path "foo.org"))) :to-be 0))
(it "delete web_ref"
(expect (org-roam-sql [:select * :from refs])
:to-have-same-items-as
(list (list "https://google.com/" (abs-path "web_ref.org"))))
(delete-file (abs-path "web_ref.org"))
(expect (org-roam-sql [:select * :from refs])
:to-have-same-items-as
(list))))
(it "delete web_ref"
(expect (org-roam-db-query [:select * :from refs])
:to-have-same-items-as
(list (list "https://google.com/" (org-roam-test-abs-path "web_ref.org"))))
(delete-file (org-roam-test-abs-path "web_ref.org"))
(expect (org-roam-db-query [:select * :from refs])
:to-have-same-items-as
(list))))
(provide 'test-org-roam)
;;; test-org-roam.el ends here