(feat): move fuzzy links to roam: links (#1105)

This commit is contained in:
Jethro Kuan
2020-09-23 17:58:18 +08:00
committed by GitHub
parent da6af3a468
commit ae32c465de
8 changed files with 539 additions and 384 deletions

View File

@ -23,7 +23,7 @@ Org-roam also now does not resolve symlinks. This significantly speeds up cache
- [#974](https://github.com/org-roam/org-roam/pull/974) Protect region targeted by `org-roam-insert` - [#974](https://github.com/org-roam/org-roam/pull/974) Protect region targeted by `org-roam-insert`
- [#994](https://github.com/org-roam/org-roam/pull/994) Simplify org-roam-store-link - [#994](https://github.com/org-roam/org-roam/pull/994) Simplify org-roam-store-link
- [#1062](https://github.com/org-roam/org-roam/pull/1062) Variable `org-roam-completions-everywhere` allows for completions everywhere from word at point - [#1062](https://github.com/org-roam/org-roam/pull/1062) Variable `org-roam-completions-everywhere` allows for completions everywhere from word at point
- [#910](https://github.com/org-roam/org-roam/pull/910) Support fuzzy links of the form [[Title]], [[*Headline]] and [[Title*Headline]] - [#910](https://github.com/org-roam/org-roam/pull/910), [#1105](https://github.com/org-roam/org-roam/pull/1105) Support fuzzy links of the form [[roam:Title]], [[roam:*Headline]] and [[roam:Title*Headline]]
### Bugfixes ### Bugfixes

View File

@ -544,10 +544,46 @@ The Org-roam buffer displays backlinks for the currently active Org-roam note.
The ~no-delete-window~ parameter for the org-roam buffer. Setting it to ~'t~ prevents the window from being deleted when calling ~delete-other-windows~. The ~no-delete-window~ parameter for the org-roam buffer. Setting it to ~'t~ prevents the window from being deleted when calling ~delete-other-windows~.
** Org-roam Links ** Org-roam Files
Org-roam links are regular ~file:~ links in Org-mode. By default, links are Org-roam files are created and prefilled using Org-roam's templating
inserted with the title as the link description with ~org-roam-insert~. system. The templating system is customizable (see [[*The Templating System][The Templating System]]).
* Inserting Links
The preferred mode of linking is via ~file~ links to files, and ~id~ links for
headlines. This maintains the strongest compatibility with Org-mode, ensuring
that the links still function without Org-roam, and work well exporting to other
backends.
~file~ links can be inserted via ~org-roam-insert~. Links to headlines can be
inserted by navigating to the desired headline and calling ~org-store-link~.
This will create an ID for the headline if it does not already exist, and
populate the Org-roam database. The link can then be inserted via
~org-insert-link~.
An alternative mode of insertion is using Org-roam's ~roam~ links. Org-roam
registers this link type, and interprets the path as follows:
- ~[[roam:title]]~ :: links to an Org-roam file with title or alias "title"
- ~[[roam:*headline]]~ :: links to the headline "headline" in the current Org-roam file
- ~[[roam:title*headline]]~ :: links to the headline "headline" in the Org-roam file with title or alias "title"
~roam~ links support auto-completion via ~completion-at-point~: simply call
~completion-at-point~ within a roam link. Users of ~company-mode~ may want to
prepend ~company-capf~ to the beginning of variable ~company-backends~.
To easily insert ~roam~ links, one may wish to use a package like [[https://github.com/emacsorphanage/key-chord/][key-chord]]. In the following example, typing "[[" will insert a stub ~roam~ link:
#+BEGIN_SRC emacs-lisp
(key-chord-define org-mode-map "[[" #'my/insert-roam-link)
(defun my/insert-roam-link ()
"Inserts an Org-roam link."
(interactive)
(insert "[[roam:]]")
(backward-char 2))
#+END_SRC
- User Option: org-roam-link-title-format - User Option: org-roam-link-title-format
@ -557,10 +593,18 @@ inserted with the title as the link description with ~org-roam-insert~.
If your version of Org is at least ~9.2~, consider styling the link differently, If your version of Org is at least ~9.2~, consider styling the link differently,
by customizing the ~org-roam-link~, and ~org-roam-link-current~ faces. by customizing the ~org-roam-link~, and ~org-roam-link-current~ faces.
** Org-roam Files - User Option: org-roam-completion-ignore-case
Org-roam files are created and prefilled using Org-roam's templating When non-nil, the ~roam~ link completions are ignore case. For example,
system. The templating system is customizable (see [[*The Templating System][The Templating System]]). calling ~completion-at-point~ within ~[[roam:fo]]~ will present a completion
for a file with title "Foo". Defaults to ~t~.
- User Option: org-roam-link-auto-replace
When non-nil, ~roam~ links will be replaced with ~file~ or ~id~ links when
they are navigated to, and on file save, when a match is found. This is
desirable to maintain compatibility with vanilla Org, but resolved links are
harder to edit. Defaults to ~t~.
* Navigating Around * Navigating Around

View File

@ -72,6 +72,7 @@ General Public License for more details.
* Anatomy of an Org-roam File:: * Anatomy of an Org-roam File::
* The Templating System:: * The Templating System::
* Concepts and Configuration:: * Concepts and Configuration::
* Inserting Links::
* Navigating Around:: * Navigating Around::
* Encryption:: * Encryption::
* Graphing:: * Graphing::
@ -108,7 +109,6 @@ Concepts and Configuration
* Directories and Files:: * Directories and Files::
* The Org-roam Buffer:: * The Org-roam Buffer::
* Org-roam Links::
* Org-roam Files:: * Org-roam Files::
Navigating Around Navigating Around
@ -294,9 +294,9 @@ To use Melpa:
@end itemize @end itemize
@lisp @lisp
(require 'package) (require 'package)
(add-to-list 'package-archives (add-to-list 'package-archives
'("melpa" . "http://melpa.org/packages/") t) '("melpa" . "http://melpa.org/packages/") t)
@end lisp @end lisp
@itemize @itemize
@ -305,9 +305,9 @@ To use Melpa-Stable:
@end itemize @end itemize
@lisp @lisp
(require 'package) (require 'package)
(add-to-list 'package-archives (add-to-list 'package-archives
'("melpa-stable" . "http://stable.melpa.org/packages/") t) '("melpa-stable" . "http://stable.melpa.org/packages/") t)
@end lisp @end lisp
Org-roam also depends on a recent version of Org, which can be obtained in Org's Org-roam also depends on a recent version of Org, which can be obtained in Org's
@ -321,14 +321,14 @@ Once you have added your preferred archive, you need to update the
local package list using: local package list using:
@example @example
M-x package-refresh-contents RET M-x package-refresh-contents RET
@end example @end example
Once you have done that, you can install Org-roam and its dependencies Once you have done that, you can install Org-roam and its dependencies
using: using:
@example @example
M-x package-install RET org-roam RET M-x package-install RET org-roam RET
@end example @end example
Now see @ref{Post-Installation Tasks}. Now see @ref{Post-Installation Tasks}.
@ -340,7 +340,7 @@ Users of Debian 11 or later or Ubuntu 20.10 or later can simply install Org-roam
using Apt: using Apt:
@example @example
apt-get install elpa-org-roam apt-get install elpa-org-roam
@end example @end example
Org-roam will then be autoloaded into Emacs. Org-roam will then be autoloaded into Emacs.
@ -356,7 +356,7 @@ Org-roam uses @code{emacsql-sqlite3}, which requires @code{sqlite3} to be locate
operating system. You can verify that this is the case by executing: operating system. You can verify that this is the case by executing:
@lisp @lisp
(executable-find "sqlite3") (executable-find "sqlite3")
@end lisp @end lisp
If you have @code{sqlite3} installed, and @code{executable-find} still reports @code{nil}, then If you have @code{sqlite3} installed, and @code{executable-find} still reports @code{nil}, then
@ -365,7 +365,7 @@ variable @code{exec-path}. You may rectify this by manually adding the path with
your Emacs configuration: your Emacs configuration:
@lisp @lisp
(add-to-list 'exec-path "path/to/sqlite3") (add-to-list 'exec-path "path/to/sqlite3")
@end lisp @end lisp
@node Getting Started @node Getting Started
@ -478,10 +478,10 @@ The aliases are space-delimited, and can be multi-worded using quotes
Take for example the following org file: Take for example the following org file:
@example @example
#+title: World War 2 #+title: World War 2
#+roam_alias: "WWII" "World War II" #+roam_alias: "WWII" "World War II"
* Headline * Headline
@end example @end example
@multitable {aaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaa} @multitable {aaaaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaa}
@ -552,8 +552,8 @@ Refs are unique identifiers for files. Each note can only have 1 ref.
For example, a note for a website may contain a ref: For example, a note for a website may contain a ref:
@example @example
#+title: Google #+title: Google
#+roam_key: https://www.google.com/ #+roam_key: https://www.google.com/
@end example @end example
These keys come in useful for when taking website notes, using the These keys come in useful for when taking website notes, using the
@ -563,8 +563,8 @@ Alternatively, add a ref for notes for a specific paper, using its
@uref{https://github.com/jkitchin/org-ref, org-ref} citation key: @uref{https://github.com/jkitchin/org-ref, org-ref} citation key:
@example @example
#+title: Neural Ordinary Differential Equations #+title: Neural Ordinary Differential Equations
#+roam_key: cite:chen18_neural_ordin_differ_equat #+roam_key: cite:chen18_neural_ordin_differ_equat
@end example @end example
The backlinks buffer will show any cites of this key: e.g. The backlinks buffer will show any cites of this key: e.g.
@ -617,11 +617,11 @@ To demonstrate the additions made to org-capture templates. Here, we walkthrough
the default template, reproduced below. the default template, reproduced below.
@lisp @lisp
("d" "default" plain (function org-roam--capture-get-point) ("d" "default" plain (function org-roam--capture-get-point)
"%?" "%?"
:file-name "%<%Y%m%d%H%M%S>-$@{slug@}" :file-name "%<%Y%m%d%H%M%S>-$@{slug@}"
:head "#+title: $@{title@}\n" :head "#+title: $@{title@}\n"
:unnarrowed t) :unnarrowed t)
@end lisp @end lisp
@enumerate @enumerate
@ -687,11 +687,11 @@ advantage of org-mode's @code{%(EXP)} template expansion to call @code{format-ti
directly to provide its third argument to specify UTC@. directly to provide its third argument to specify UTC@.
@lisp @lisp
("d" "default" plain (function org-roam--capture-get-point) ("d" "default" plain (function org-roam--capture-get-point)
"%?" "%?"
:file-name "%(format-time-string \"%Y-%m-%d--%H-%M-%SZ--$@{slug@}\" (current-time) t)" :file-name "%(format-time-string \"%Y-%m-%d--%H-%M-%SZ--$@{slug@}\" (current-time) t)"
:head "#+title: $@{title@}\n" :head "#+title: $@{title@}\n"
:unnarrowed t) :unnarrowed t)
@end lisp @end lisp
@node Concepts and Configuration @node Concepts and Configuration
@ -707,7 +707,6 @@ All of Org-roam's customization options can be viewed via
@menu @menu
* Directories and Files:: * Directories and Files::
* The Org-roam Buffer:: * The Org-roam Buffer::
* Org-roam Links::
* Org-roam Files:: * Org-roam Files::
@end menu @end menu
@ -773,11 +772,53 @@ User Option: org-roam-buffer-no-delete-other-windows
The @code{no-delete-window} parameter for the org-roam buffer. Setting it to @code{'t} prevents the window from being deleted when calling @code{delete-other-windows}. The @code{no-delete-window} parameter for the org-roam buffer. Setting it to @code{'t} prevents the window from being deleted when calling @code{delete-other-windows}.
@end itemize @end itemize
@node Org-roam Links @node Org-roam Files
@section Org-roam Links @section Org-roam Files
Org-roam links are regular @code{file:} links in Org-mode. By default, links are Org-roam files are created and prefilled using Org-roam's templating
inserted with the title as the link description with @code{org-roam-insert}. system. The templating system is customizable (see @ref{The Templating System}).
@node Inserting Links
@chapter Inserting Links
The preferred mode of linking is via @code{file} links to files, and @code{id} links for
headlines. This maintains the strongest compatibility with Org-mode, ensuring
that the links still function without Org-roam, and work well exporting to other
backends.
@code{file} links can be inserted via @code{org-roam-insert}. Links to headlines can be
inserted by navigating to the desired headline and calling @code{org-store-link}.
This will create an ID for the headline if it does not already exist, and
populate the Org-roam database. The link can then be inserted via
@code{org-insert-link}.
An alternative mode of insertion is using Org-roam's @code{roam} links. Org-roam
registers this link type, and interprets the path as follows:
@table @asis
@item @code{[[roam:title]]}
links to an Org-roam file with title or alias ``title''
@item @code{[[roam:*headline]]}
links to the headline ``headline'' in the current Org-roam file
@item @code{[[roam:title*headline]]}
links to the headline ``headline'' in the Org-roam file with title or alias ``title''
@end table
@code{roam} links support auto-completion via @code{completion-at-point}: simply call
@code{completion-at-point} within a roam link. Users of @code{company-mode} may want to
prepend @code{company-capf} to the beginning of variable @code{company-backends}.
To easily insert @code{roam} links, one may wish to use a package like @uref{https://github.com/emacsorphanage/key-chord/, key-chord}. In the following example, typing ``[['' will insert a stub @code{roam} link:
@lisp
(key-chord-define org-mode-map "[[" #'my/insert-roam-link)
(defun my/insert-roam-link ()
"Inserts an Org-roam link."
(interactive)
(insert "[[roam:]]")
(backward-char 2))
@end lisp
@itemize @itemize
@item @item
@ -788,14 +829,23 @@ special indicators for Org-roam links. Defaults to @code{"%s"}.
If your version of Org is at least @code{9.2}, consider styling the link differently, If your version of Org is at least @code{9.2}, consider styling the link differently,
by customizing the @code{org-roam-link}, and @code{org-roam-link-current} faces. by customizing the @code{org-roam-link}, and @code{org-roam-link-current} faces.
@item
User Option: org-roam-completion-ignore-case
When non-nil, the @code{roam} link completions are ignore case. For example,
calling @code{completion-at-point} within @code{[[roam:fo]]} will present a completion
for a file with title ``Foo''. Defaults to @code{t}.
@item
User Option: org-roam-link-auto-replace
When non-nil, @code{roam} links will be replaced with @code{file} or @code{id} links when
they are navigated to, and on file save, when a match is found. This is
desirable to maintain compatibility with vanilla Org, but resolved links are
harder to edit. Defaults to @code{t}.
@end itemize @end itemize
@node Org-roam Files
@section Org-roam Files
Org-roam files are created and prefilled using Org-roam's templating
system. The templating system is customizable (see @ref{The Templating System}).
@node Navigating Around @node Navigating Around
@chapter Navigating Around @chapter Navigating Around
@ -906,10 +956,10 @@ a function accepting a single argument: the graph file path.
If you are using WSL2 and would like to open the graph in Windows, you can use the second option to set the browser and network file path: If you are using WSL2 and would like to open the graph in Windows, you can use the second option to set the browser and network file path:
@lisp @lisp
(setq org-roam-graph-viewer (setq org-roam-graph-viewer
(lambda (file) (lambda (file)
(let ((org-roam-graph-viewer "/mnt/c/Program Files/Mozilla Firefox/firefox.exe")) (let ((org-roam-graph-viewer "/mnt/c/Program Files/Mozilla Firefox/firefox.exe"))
(org-roam-graph--open (concat "file://///wsl$/Ubuntu" file))))) (org-roam-graph--open (concat "file://///wsl$/Ubuntu" file)))))
@end lisp @end lisp
@end itemize @end itemize
@ -968,7 +1018,7 @@ are excluded.
@end itemize @end itemize
@example @example
(setq org-roam-graph-exclude-matcher '("private" "dailies")) (setq org-roam-graph-exclude-matcher '("private" "dailies"))
@end example @end example
This setting excludes all files whose path contain ``private'' or ``dailies''. This setting excludes all files whose path contain ``private'' or ``dailies''.
@ -981,7 +1031,7 @@ its interactive commands. The default setting uses Emacs' standard
@code{completing-read} mechanism. @code{completing-read} mechanism.
@lisp @lisp
(setq org-roam-completion-system 'default) (setq org-roam-completion-system 'default)
@end lisp @end lisp
If you have installed Helm or Ivy, and have their modes enabled, under the If you have installed Helm or Ivy, and have their modes enabled, under the
@ -991,7 +1041,7 @@ In the rare scenario where you use Ivy globally, but prefer @uref{https://emacs-
commands, set: commands, set:
@lisp @lisp
(setq org-roam-completion-system 'helm) (setq org-roam-completion-system 'helm)
@end lisp @end lisp
Other options include @code{'ido}, and @code{'ivy}. Other options include @code{'ido}, and @code{'ivy}.
@ -1184,7 +1234,7 @@ or as a keybinding in @code{qutebrowser} in , using the @code{config.py} file (s
@uref{https://github.com/qutebrowser/qutebrowser/blob/master/doc/help/configuring.asciidoc, Configuring qutebrowser}): @uref{https://github.com/qutebrowser/qutebrowser/blob/master/doc/help/configuring.asciidoc, Configuring qutebrowser}):
@example @example
config.bind("<Ctrl-r>", "open javascript:location.href='org-protocol://roam-ref?template=r&ref='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)") config.bind("<Ctrl-r>", "open javascript:location.href='org-protocol://roam-ref?template=r&ref='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)")
@end example @end example
where @code{template} is the template key for a template in where @code{template} is the template key for a template in
@ -1255,7 +1305,7 @@ operations. To reduce the number of garbage collection processes, one may set
@code{org-roam-db-gc-threshold} to a high value (such as @code{most-positive-fixnum}): @code{org-roam-db-gc-threshold} to a high value (such as @code{most-positive-fixnum}):
@lisp @lisp
(setq org-roam-db-gc-threshold most-positive-fixnum) (setq org-roam-db-gc-threshold most-positive-fixnum)
@end lisp @end lisp
@node Appendix @node Appendix
@ -1319,9 +1369,9 @@ operations. To reduce the number of garbage collection processes, one may set
@code{winner-mode} can be used as a simple version of browser history for Org-roam. Each click through org-roam links (from both Org files and the backlinks buffer) causes changes in window configuration, which can be undone and redone using @code{winner-mode}. To use @code{winner-mode}, simply enable it, and bind the appropriate interactive functions: @code{winner-mode} can be used as a simple version of browser history for Org-roam. Each click through org-roam links (from both Org files and the backlinks buffer) causes changes in window configuration, which can be undone and redone using @code{winner-mode}. To use @code{winner-mode}, simply enable it, and bind the appropriate interactive functions:
@lisp @lisp
(winner-mode +1) (winner-mode +1)
(define-key winner-mode-map (kbd "<M-left>") #'winner-undo) (define-key winner-mode-map (kbd "<M-left>") #'winner-undo)
(define-key winner-mode-map (kbd "<M-right>") #'winner-redo) (define-key winner-mode-map (kbd "<M-right>") #'winner-redo)
@end lisp @end lisp
@ -1343,15 +1393,15 @@ versions of a tracked Org-roam note.
@uref{https://jblevins.org/projects/deft/, Deft} provides a nice interface for browsing and filtering org-roam notes. @uref{https://jblevins.org/projects/deft/, Deft} provides a nice interface for browsing and filtering org-roam notes.
@lisp @lisp
(use-package deft (use-package deft
:after org :after org
:bind :bind
("C-c n d" . deft) ("C-c n d" . deft)
:custom :custom
(deft-recursive t) (deft-recursive t)
(deft-use-filter-string-for-filename t) (deft-use-filter-string-for-filename t)
(deft-default-extension "org") (deft-default-extension "org")
(deft-directory "/path/to/org-roam-files/")) (deft-directory "/path/to/org-roam-files/"))
@end lisp @end lisp
If the title of the Org file is not the first line, you might not get If the title of the Org file is not the first line, you might not get
@ -1360,29 +1410,29 @@ functionality. Here I'm using
@uref{https://github.com/raxod502/el-patch, el-patch}: @uref{https://github.com/raxod502/el-patch, el-patch}:
@lisp @lisp
(use-package el-patch (use-package el-patch
:straight (:host github :straight (:host github
:repo "raxod502/el-patch" :repo "raxod502/el-patch"
:branch "develop")) :branch "develop"))
(eval-when-compile (eval-when-compile
(require 'el-patch)) (require 'el-patch))
(use-package deft (use-package deft
;; same as above... ;; same as above...
:config/el-patch :config/el-patch
(defun deft-parse-title (file contents) (defun deft-parse-title (file contents)
"Parse the given FILE and CONTENTS and determine the title. "Parse the given FILE and CONTENTS and determine the title.
If `deft-use-filename-as-title' is nil, the title is taken to If `deft-use-filename-as-title' is nil, the title is taken to
be the first non-empty line of the FILE. Else the base name of the FILE is be the first non-empty line of the FILE. Else the base name of the FILE is
used as title." used as title."
(el-patch-swap (if deft-use-filename-as-title (el-patch-swap (if deft-use-filename-as-title
(deft-base-filename file) (deft-base-filename file)
(let ((begin (string-match "^.+$" contents))) (let ((begin (string-match "^.+$" contents)))
(if begin (if begin
(funcall deft-parse-title-function (funcall deft-parse-title-function
(substring contents begin (match-end 0)))))) (substring contents begin (match-end 0))))))
(org-roam--get-title-or-slug file)))) (org-roam--get-title-or-slug file))))
@end lisp @end lisp
The Deft interface can slow down quickly when the number of files get The Deft interface can slow down quickly when the number of files get
@ -1398,14 +1448,14 @@ provides better journaling capabilities, and a nice calendar interface
to see all dated entries. to see all dated entries.
@lisp @lisp
(use-package org-journal (use-package org-journal
:bind :bind
("C-c n j" . org-journal-new-entry) ("C-c n j" . org-journal-new-entry)
:custom :custom
(org-journal-date-prefix "#+title: ") (org-journal-date-prefix "#+title: ")
(org-journal-file-format "%Y-%m-%d.org") (org-journal-file-format "%Y-%m-%d.org")
(org-journal-dir "/path/to/org-roam-files/") (org-journal-dir "/path/to/org-roam-files/")
(org-journal-date-format "%A, %d %B %Y")) (org-journal-date-format "%A, %d %B %Y"))
@end lisp @end lisp
@node Note-taking Add-ons @node Note-taking Add-ons
@ -1432,12 +1482,12 @@ These are some plugins that make note-taking in Org-mode more enjoyable.
@end float @end float
@lisp @lisp
(use-package org-download (use-package org-download
:after org :after org
:bind :bind
(:map org-mode-map (:map org-mode-map
(("s-Y" . org-download-screenshot) (("s-Y" . org-download-screenshot)
("s-y" . org-download-yank)))) ("s-y" . org-download-yank))))
@end lisp @end lisp
@node mathpixel @node mathpixel
@ -1451,12 +1501,12 @@ These are some plugins that make note-taking in Org-mode more enjoyable.
@end float @end float
@lisp @lisp
(use-package mathpix.el (use-package mathpix.el
:straight (:host github :repo "jethrokuan/mathpix.el") :straight (:host github :repo "jethrokuan/mathpix.el")
:custom ((mathpix-app-id "app-id") :custom ((mathpix-app-id "app-id")
(mathpix-app-key "app-key")) (mathpix-app-key "app-key"))
:bind :bind
("C-x m" . mathpix-screenshot)) ("C-x m" . mathpix-screenshot))
@end lisp @end lisp
@node Org-noter / Interleave @node Org-noter / Interleave
@ -1503,8 +1553,8 @@ variable using directory-local variables. This is what @code{.dir-locals.el} may
contain: contain:
@lisp @lisp
((nil . ((org-roam-directory . ".") ((nil . ((org-roam-directory . ".")
(org-roam-db-location . "./org-roam.db")))) (org-roam-db-location . "./org-roam.db"))))
@end lisp @end lisp
All files within that directory will be treated as their own separate All files within that directory will be treated as their own separate

View File

@ -47,6 +47,11 @@
(function :tag "Custom function")) (function :tag "Custom function"))
:group 'org-roam) :group 'org-roam)
(defcustom org-roam-completion-ignore-case t
"Whether to ignore case in Org-roam `completion-at-point' completions."
:group 'org-roam
:type 'boolean)
(defun org-roam-completion--helm-candidate-transformer (candidates _source) (defun org-roam-completion--helm-candidate-transformer (candidates _source)
"Transforms CANDIDATES for Helm-based completing read. "Transforms CANDIDATES for Helm-based completing read.
SOURCE is not used." SOURCE is not used."

274
org-roam-link.el Normal file
View File

@ -0,0 +1,274 @@
;;; org-roam-link.el --- Custom links for Org-roam -*- coding: utf-8; lexical-binding: t; -*-
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
;; Alan Carroll
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 1.2.1
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (s "1.12.0") (org "9.3") (emacsql "3.0.0") (emacsql-sqlite3 "1.0.2"))
;; 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 adds the custom `roam:' link to Org-roam. `roam:' links allow linking to
;; Org-roam files via their titles and headlines.
;;
;;; Code:
;;;; Dependencies
(require 'ol)
(require 'org-roam-compat)
(defvar org-roam-completion-ignore-case)
(declare-function org-roam--find-file "org-roam")
(declare-function org-roam-find-file "org-roam")
(defcustom org-roam-link-auto-replace t
"When non-nil, replace Org-roam's roam links with file or id links whenever possible."
:group 'org-roam
:type 'boolean)
;;; the roam: link
(org-link-set-parameters "roam"
:follow #'org-roam-link-follow-link)
(defun org-roam-link-follow-link (path)
"Navigates to location specified by PATH."
(pcase-let ((`(,link-type ,loc ,desc ,mkr) (org-roam-link--get-location path)))
(when (and org-roam-link-auto-replace loc desc)
(org-roam-link--replace-link link-type loc desc))
(pcase link-type
("file"
(if loc
(org-roam--find-file loc)
(org-roam-find-file desc nil nil t)))
("id"
(org-goto-marker-or-bmk mkr)))))
;;; Retrieval Functions
(defun org-roam-link--get-titles ()
"Return all titles within Org-roam."
(mapcar #'car (org-roam-db-query [:select [titles:title] :from titles])))
(defun org-roam-link--get-headlines (&optional file with-marker use-stack)
"Return all outline headings for the current buffer.
If FILE, return outline headings for passed FILE instead.
If WITH-MARKER, return a cons cell of (headline . marker).
If USE-STACK, include the parent paths as well."
(let* ((buf (or (and file
(or (find-buffer-visiting file)
(find-file-noselect file)))
(current-buffer)))
(outline-level-fn outline-level)
(path-separator "/")
(stack-level 0)
stack cands name level marker)
(with-current-buffer buf
(save-excursion
(goto-char (point-min))
(while (re-search-forward org-complex-heading-regexp nil t)
(save-excursion
(setq name (substring-no-properties (or (match-string 4) "")))
(setq marker (point-marker))
(when use-stack
(goto-char (match-beginning 0))
(setq level (funcall outline-level-fn))
;; Update stack. The empty entry guards against incorrect
;; headline hierarchies, e.g. a level 3 headline
;; immediately following a level 1 entry.
(while (<= level stack-level)
(pop stack)
(cl-decf stack-level))
(while (> level stack-level)
(push name stack)
(cl-incf stack-level))
(setq name (mapconcat #'identity
(reverse stack)
path-separator)))
(push (if with-marker
(cons name marker)
name) cands)))))
(nreverse cands)))
(defun org-roam-link--get-file-from-title (title &optional no-interactive)
"Return the file path corresponding to TITLE.
When NO-INTERACTIVE, return nil if there are multiple options."
(let ((files (mapcar #'car (org-roam-db-query [:select [titles:file] :from titles
:where (= titles:title $v1)]
(vector title)))))
(pcase files
('nil nil)
(`(,file) file)
(_
(unless no-interactive
(completing-read "Select file: " files))))))
(defun org-roam-link--get-id-from-headline (headline &optional file)
"Return (marker . id) correspondng to HEADLINE.
If FILE, get headline from FILE instead.
If there is no corresponding headline, return nil."
(save-excursion
(with-current-buffer (or (and file
(or (find-buffer-visiting file)
(find-file-noselect file)))
(current-buffer))
(let ((headlines (org-roam-link--get-headlines file 'with-markers)))
(when-let ((marker (cdr (assoc-string headline headlines))))
(goto-char marker)
(cons marker
(when org-roam-link-auto-replace
(org-id-get-create))))))))
;;; Path-related functions
(defun org-roam-link--split-path (path)
"Splits PATH into title and headline.
Return a list of the form (type title has-headline-p headline star-idx).
type is one of `title', `headline', `title+headline'.
title is the title component of the path.
headline is the headline component of the path.
star-idx is the index of the asterisk, if any."
(save-match-data
(let* ((star-index (string-match-p "\\*" path))
(title (substring-no-properties path 0 star-index))
(headline (if star-index
(substring-no-properties path (+ 1 star-index))
""))
(type (cond ((not star-index)
'title)
((= 0 star-index)
'headline)
(t 'title+headline))))
(list type title headline star-index))))
(defun org-roam-link--get-location (link)
"Return the location of Org-roam fuzzy LINK.
The location is returned as a list containing (link-type loc desc marker).
nil is returned if there is no matching location.
link-type is either \"file\" or \"id\".
loc is the target location: e.g. a file path, or an id.
marker is a marker to the headline, if applicable."
(let (mkr link-type desc loc)
(pcase-let ((`(,type ,title ,headline _) (org-roam-link--split-path link)))
(pcase type
('title+headline
(let ((file (org-roam-link--get-file-from-title title)))
(if (not file)
(org-roam-message "Cannot find matching file")
(setq mkr (org-roam-link--get-id-from-headline headline file))
(pcase mkr
(`(,marker . ,target-id)
(setq mkr marker
loc target-id
link-type "id"
desc headline))
(_ (org-roam-message "cannot find matching id"))))))
('title
(setq loc (org-roam-link--get-file-from-title title)
desc title
link-type "file")
(when loc (setq loc (file-relative-name loc))))
('headline
(setq mkr (org-roam-link--get-id-from-headline headline))
(pcase mkr
(`(,marker . ,target-id)
(setq mkr marker
loc target-id
desc headline
link-type "id"))
(_ (org-roam-message "Cannot find matching headline")))))
(list link-type loc desc mkr))))
;;; Conversion Functions
(defun org-roam-link--replace-link (link-type loc &optional desc)
"Replace link at point with a vanilla Org link.
LINK-TYPE is the Org link type, typically \"file\" or \"id\".
LOC is path for the Org link.
DESC is the link description."
(save-excursion
(save-match-data
(unless (org-in-regexp org-link-bracket-re 1)
(user-error "No link at point"))
(replace-match "")
(insert (org-roam-link-make-string (concat link-type ":" loc) desc)))))
(defun org-roam-link-replace-all ()
"Replace all roam links in the current buffer."
(interactive)
(save-excursion
(goto-char (point-min))
(while (re-search-forward org-link-bracket-re nil t)
(let ((context (org-element-context)))
(pcase (org-element-lineage context '(link) t)
(`nil nil)
(link
(when (string-equal "roam" (org-element-property :type link))
(pcase-let ((`(,link-type ,loc ,desc _) (org-roam-link--get-location (org-element-property :path link))))
(when (and link-type loc)
(org-roam-link--replace-link link-type loc desc))))))))))
(defun org-roam-link--replace-link-on-save ()
"Hook to replace all roam links on save."
(when org-roam-link-auto-replace
(org-roam-link-replace-all)))
;;; Completion
(defun org-roam-link-complete-at-point ()
"Do appropriate completion for the link at point."
(let ((end (point))
(start (point))
(exit-fn (lambda (&rest _) nil))
collection)
(when (org-in-regexp org-link-bracket-re 1)
(setq start (+ (match-beginning 1) (length "roam:"))
end (match-end 1))
(let ((context (org-element-context)))
(pcase (org-element-lineage context '(link) t)
(`nil nil)
(link (when (string-equal "roam" (org-element-property :type link))
(pcase-let ((`(,type ,title _ ,star-idx)
(org-roam-link--split-path (org-element-property :path link))))
(pcase type
('title+headline
(when-let ((file (org-roam-link--get-file-from-title title t)))
(setq collection (apply-partially #'org-roam-link--get-headlines file))
(setq start (+ start star-idx 1))))
('title
(setq collection #'org-roam-link--get-titles))
('headline
(setq collection #'org-roam-link--get-headlines)
(setq start (+ start star-idx 1))))))))))
(when collection
(let ((prefix (buffer-substring-no-properties start end)))
(list start end
(if (functionp collection)
(completion-table-case-fold
(completion-table-dynamic
(lambda (_)
(cl-remove-if (apply-partially #'string= prefix)
(funcall collection))))
(not org-roam-completion-ignore-case))
collection)
:exit-function exit-fn)))))
(provide 'org-roam-link)
;;; org-roam-link.el ends here

View File

@ -74,19 +74,6 @@ If FILE, set `org-roam-temp-file-name' to file and insert its contents."
(s-replace "\\" "\\\\") (s-replace "\\" "\\\\")
(s-replace "\"" "\\\""))) (s-replace "\"" "\\\"")))
;;; Link Utilities
(defun org-roam-replace-fuzzy-link (new-loc &optional desc)
"Replace the current fuzzy link (e.g. [[Foo]]) with a NEW-LOC.
If DESC, also replace the desc"
(save-match-data
(unless (org-in-regexp org-link-bracket-re 1)
(user-error "No link at point"))
(let ((desc (or desc (match-string-no-properties 1)))
(remove (list (match-beginning 0) (match-end 0))))
(apply #'delete-region remove)
(insert (org-roam-link-make-string new-loc desc)))
(sit-for 0)))
;;; Shielding regions ;;; Shielding regions
(defun org-roam-shield-region (beg end) (defun org-roam-shield-region (beg end)
"Shield REGION against modifications. "Shield REGION against modifications.

View File

@ -63,6 +63,7 @@
(require 'org-roam-db) (require 'org-roam-db)
(require 'org-roam-doctor) (require 'org-roam-doctor)
(require 'org-roam-graph) (require 'org-roam-graph)
(require 'org-roam-link)
;;;; Declarations ;;;; Declarations
;; From org-ref-core.el ;; From org-ref-core.el
@ -277,6 +278,9 @@ The currently supported symbols are:
:type 'boolean :type 'boolean
:group 'org-roam) :group 'org-roam)
(defvar org-roam-completion-functions nil
"List of functions to be used with `completion-at-point' for Org-roam.")
;;;; Dynamic variables ;;;; Dynamic variables
(defvar org-roam-last-window nil (defvar org-roam-last-window nil
"Last window `org-roam' was called from.") "Last window `org-roam' was called from.")
@ -633,6 +637,7 @@ it as FILE-PATH."
(setq type "cite") (setq type "cite")
(org-ref-split-and-strip-string path)) (org-ref-split-and-strip-string path))
("fuzzy" (list path)) ("fuzzy" (list path))
("roam" (list path))
(_ (if (or (file-remote-p path) (_ (if (or (file-remote-p path)
(org-roam--url-p path)) (org-roam--url-p path))
(list path) (list path)
@ -1152,15 +1157,14 @@ This function hooks into `org-open-at-point' via
:group 'org-roam :group 'org-roam
:type 'boolean) :type 'boolean)
(defun org-roam-complete-at-point () ;;;; Tags completion
"Do appropriate completion for the thing at point." (defun org-roam-complete-tags-at-point ()
"`completion-at-point' function for Org-roam tags."
(let ((end (point)) (let ((end (point))
(start (point)) (start (point))
(exit-fn (lambda (&rest _) nil)) (exit-fn (lambda (&rest _) nil))
collection) collection)
(cond (when (looking-back "^#\\+roam_tags:.*" (line-beginning-position))
(;; completing roam_tags
(looking-back "^#\\+roam_tags:.*" (line-beginning-position))
(when (looking-at "\\>") (when (looking-at "\\>")
(setq start (save-excursion (skip-syntax-backward "w") (setq start (save-excursion (skip-syntax-backward "w")
(point)) (point))
@ -1169,263 +1173,55 @@ This function hooks into `org-open-at-point' via
exit-fn (lambda (str _status) exit-fn (lambda (str _status)
(delete-char (- (length str))) (delete-char (- (length str)))
(insert "\"" str "\"")))) (insert "\"" str "\""))))
(;; Completions for fuzzy links (when collection
org-roam-enable-fuzzy-links (let ((prefix (buffer-substring-no-properties start end)))
(cond (list start end
(;; In a fuzzy link (if (functionp collection)
(and (org-roam--fuzzy-link-p)) (completion-table-case-fold
(org-in-regexp org-link-any-re 1) ; org-roam--fuzzy-link-p guarantees this is true (completion-table-dynamic
(setq start (match-beginning 2) (lambda (_)
end (match-end 2)) (cl-remove-if (apply-partially #'string= prefix)
(pcase-let ((`(,type ,title _ ,star-idx) (funcall collection))))
(org-roam--split-fuzzy-link (match-string-no-properties 2)))) (not org-roam-completion-ignore-case))
(pcase type collection)
('title+headline :exit-function exit-fn)))))
(when-let ((file (org-roam--get-file-from-title title t)))
(setq collection (apply-partially #'org-roam--get-headlines file)) (defun org-roam--get-titles ()
(setq start (+ start star-idx 1)))) "Return all titles within Org-roam."
('title (mapcar #'car (org-roam-db-query [:select [titles:title] :from titles])))
(setq collection #'org-roam--get-titles))
('headline (defun org-roam-complete-everywhere ()
(setq collection #'org-roam--get-headlines) "`completion-at-point' function for word at point.
(setq start (+ start star-idx 1)))))) This is active when `org-roam-completion-everywhere' is non-nil."
(;; At a plain "[[|]]" (let ((end (point))
(org-in-regexp (rx "[[]]")) (start (point))
(setq start (+ (match-beginning 0) 2) (exit-fn (lambda (&rest _) nil))
end (+ (match-beginning 0) 2) collection)
collection #'org-roam--get-titles)))) (when (and org-roam-completion-everywhere
(;; Completions everywhere (thing-at-point 'word))
(and org-roam-completion-everywhere
(thing-at-point 'word))
(let ((bounds (bounds-of-thing-at-point 'word))) (let ((bounds (bounds-of-thing-at-point 'word)))
(setq start (car bounds) (setq start (car bounds)
end (cdr bounds) end (cdr bounds)
collection #'org-roam--get-titles collection #'org-roam--get-titles
exit-fn (lambda (str _status) exit-fn (lambda (str _status)
(delete-char (- (length str))) (delete-char (- (length str)))
(insert "[[" str "]]")))))) (insert "[[" str "]]")))))
(when collection (when collection
(let ((prefix (buffer-substring-no-properties start end))) (let ((prefix (buffer-substring-no-properties start end)))
(list start end (list start end
(if (functionp collection) (if (functionp collection)
(completion-table-dynamic (completion-table-case-fold
(lambda (_) (completion-table-dynamic
(cl-remove-if (apply-partially #'string= prefix) (lambda (_)
(funcall collection)))) (cl-remove-if (apply-partially #'string= prefix)
(funcall collection))))
(not org-roam-completion-ignore-case))
collection) collection)
:exit-function exit-fn))))) :exit-function exit-fn)))))
;;; Fuzzy Links (add-to-list 'org-roam-completion-functions #'org-roam-complete-tags-at-point)
(defcustom org-roam-enable-fuzzy-links t (add-to-list 'org-roam-completion-functions #'org-roam-complete-everywhere)
"When non-nil, replace Org's [[fuzzy link]] behaviour with Org-roam's. (add-to-list 'org-roam-completion-functions #'org-roam-link-complete-at-point)
Org-roam emulates Roam Research, treating [[Foo]] links as links
to files titled Foo. In addition to this behaviour, [[Foo*Bar]]
links to the headline Bar within the file titled Foo."
:group 'org-roam
:type 'boolean)
(defcustom org-roam-auto-replace-fuzzy-links t
"When non-nil, replace Org-roam's fuzzy links with file or id links whenever possible."
:group 'org-roam
:type 'boolean)
(defun org-roam--fuzzy-link-p (&optional point-or-marker)
"Return t if the link at point is a fuzzy link.
If POINT-OR-MARKER, then check the link at POINT-OR-MARKER.
Some [[foo]] links are not fuzzy links: they could have a
type (e.g. file, https) or be a custom id link (e.g. #foo)."
(save-excursion
(save-match-data
(goto-char (or point-or-marker (point)))
(when (org-in-regexp org-link-any-re 1)
(let ((context (org-element-context)))
(pcase (org-element-lineage context '(link) t)
(`nil nil)
(link (string-equal "fuzzy" (org-element-property :type link)))))))))
(defun org-roam--split-fuzzy-link (link)
"Splits LINK into title and headline.
Return a list of the form (type title has-headline-p headline star-idx).
type is one of `title', `headline', `title+headline'.
title is the title component of the link.
headline is the headline component of the link.
star-idx is the index of the asterisk, if any."
(save-match-data
(let* ((star-index (string-match-p "\\*" link))
(title (substring-no-properties link 0 star-index))
(headline (if star-index
(substring-no-properties link (+ 1 star-index))
""))
(type (cond ((not star-index)
'title)
((= 0 star-index)
'headline)
(t 'title+headline))))
(list type title headline star-index))))
(defun org-roam--get-titles ()
"Return all titles within Org-roam."
(mapcar #'car (org-roam-db-query [:select [titles:title] :from titles])))
(defun org-roam--get-headlines (&optional file with-marker use-stack)
"Return all outline headings for the current buffer.
If FILE, return outline headings for passed FILE instead.
If WITH-MARKER, return a cons cell of (headline . marker).
If USE-STACK, include the parent paths as well."
(let* ((buf (or (and file
(or (find-buffer-visiting file)
(find-file-noselect file)))
(current-buffer)))
(outline-level-fn outline-level)
(path-separator "/")
(stack-level 0)
stack cands name level marker)
(with-current-buffer buf
(save-excursion
(goto-char (point-min))
(while (re-search-forward org-complex-heading-regexp nil t)
(save-excursion
(setq name (substring-no-properties (or (match-string 4) "")))
(setq marker (point-marker))
(when use-stack
(goto-char (match-beginning 0))
(setq level (funcall outline-level-fn))
;; Update stack. The empty entry guards against incorrect
;; headline hierarchies, e.g. a level 3 headline
;; immediately following a level 1 entry.
(while (<= level stack-level)
(pop stack)
(cl-decf stack-level))
(while (> level stack-level)
(push name stack)
(cl-incf stack-level))
(setq name (mapconcat #'identity
(reverse stack)
path-separator)))
(push (if with-marker
(cons name marker)
name) cands)))))
(nreverse cands)))
(defun org-roam--get-file-from-title (title &optional no-interactive)
"Return the file path corresponding to TITLE.
When NO-INTERACTIVE, return nil if there are multiple options."
(let ((files (mapcar #'car (org-roam-db-query [:select [titles:file] :from titles
:where (= titles:title $v1)]
(vector title)))))
(pcase files
('nil nil)
(`(,file) file)
(_
(unless no-interactive
(completing-read "Select file: " files))))))
(defun org-roam--get-id-from-headline (headline &optional file)
"Return (marker . id) correspondng to HEADLINE.
If FILE, get headline from FILE instead.
If there is no corresponding headline, return nil."
(save-excursion
(with-current-buffer (or (and file
(or (find-buffer-visiting file)
(find-file-noselect file)))
(current-buffer))
(let ((headlines (org-roam--get-headlines file 'with-markers)))
(when-let ((marker (cdr (assoc-string headline headlines))))
(goto-char marker)
(cons marker
(when org-roam-auto-replace-fuzzy-links
(org-id-get-create))))))))
(defun org-roam--get-fuzzy-link-location (link)
"Return the location of Org-roam fuzzy LINK.
The location is returned as a list containing (link-type loc desc marker).
nil is returned if there is no matching location.
link-type is either \"file\" or \"id\".
loc is the target location: e.g. a file path, or an id.
marker is a marker to the headline, if applicable."
(let (mkr link-type desc loc)
(pcase-let ((`(,type ,title ,headline _) (org-roam--split-fuzzy-link link)))
(pcase type
('title+headline
(let ((file (org-roam--get-file-from-title title)))
(if (not file)
(org-roam-message "Cannot find matching file")
(setq mkr (org-roam--get-id-from-headline headline file))
(pcase mkr
(`(,marker . ,target-id)
(setq mkr marker
loc target-id
link-type "id"
desc headline))
(_ (org-roam-message "cannot find matching id"))))))
('title
(setq loc (org-roam--get-file-from-title title)
desc title
link-type "file")
(when loc (setq loc (file-relative-name loc))))
('headline
(setq mkr (org-roam--get-id-from-headline headline))
(pcase mkr
(`(,marker . ,target-id)
(setq mkr marker
loc target-id
desc headline
link-type "id"))
(_ (org-roam-message "Cannot find matching headline")))))
(list link-type loc desc mkr))))
(defun org-roam--open-fuzzy-link (link)
"Open a Org fuzzy LINK.
To be added to `org-open-link-functions'. This function always
resolves, completely replacing Org's original fuzzy link opening behaviour.
Three types of fuzzy links are supported:
[[Title]]
Opens a file with the corresponding title.
[[*Headline]]
Creates or gets an ID for the corresponding headline from current file.
[[Title*Headline]]
Creates or gets an ID for the corresponding headline from file with corresponding title."
(when (and org-roam-enable-fuzzy-links
(bound-and-true-p org-roam-mode)
(org-roam--org-roam-file-p))
(when-let ((location (org-roam--get-fuzzy-link-location link)))
(pcase-let ((`(,link-type ,loc ,desc ,mkr) location))
(when (and org-roam-auto-replace-fuzzy-links
loc desc)
(org-roam-replace-fuzzy-link (concat link-type ":" loc) desc))
(pcase link-type
("file"
(if loc
(org-roam--find-file loc)
(org-roam-find-file desc nil nil t)))
("id"
(org-goto-marker-or-bmk mkr)))))
t))
(defun org-roam-replace-all-fuzzy-links ()
"Replace all fuzzy links in current buffer."
(interactive)
(save-excursion
(goto-char (point-min))
(while (re-search-forward org-link-any-re nil t)
(when (org-roam--fuzzy-link-p)
(when-let ((location (org-roam--get-fuzzy-link-location (match-string-no-properties 2))))
(pcase-let ((`(,link-type ,loc ,desc _) location))
(when (and link-type loc)
(org-roam-replace-fuzzy-link (concat link-type ":" loc) desc))))))))
(defun org-roam--replace-fuzzy-link-on-save ()
"Hook to replace all fuzzy links on save."
(when (and org-roam-enable-fuzzy-links
org-roam-auto-replace-fuzzy-links)
(org-roam-replace-all-fuzzy-links)))
;;; Org-roam-mode ;;; Org-roam-mode
;;;; Function Faces ;;;; Function Faces
@ -1525,9 +1321,10 @@ during the next idle slot."
(run-hooks 'org-roam-file-setup-hook) ; Run user hooks (run-hooks 'org-roam-file-setup-hook) ; Run user hooks
(org-roam--setup-title-auto-update) (org-roam--setup-title-auto-update)
(add-hook 'post-command-hook #'org-roam-buffer--update-maybe nil t) (add-hook 'post-command-hook #'org-roam-buffer--update-maybe nil t)
(add-hook 'before-save-hook #'org-roam--replace-fuzzy-link-on-save nil t) (add-hook 'before-save-hook #'org-roam-link--replace-link-on-save nil t)
(add-hook 'after-save-hook #'org-roam--queue-file-for-update nil t) (add-hook 'after-save-hook #'org-roam--queue-file-for-update nil t)
(add-hook 'completion-at-point-functions #'org-roam-complete-at-point nil t) (dolist (fn org-roam-completion-functions)
(add-hook 'completion-at-point-functions fn nil t))
(org-roam-buffer--update-maybe :redisplay t))) (org-roam-buffer--update-maybe :redisplay t)))
(defun org-roam--delete-file-advice (file &optional _trash) (defun org-roam--delete-file-advice (file &optional _trash)
@ -1725,7 +1522,6 @@ M-x info for more information at Org-roam > Installation > Post-Installation Tas
(add-hook 'find-file-hook #'org-roam--find-file-hook-function) (add-hook 'find-file-hook #'org-roam--find-file-hook-function)
(add-hook 'kill-emacs-hook #'org-roam-db--close-all) (add-hook 'kill-emacs-hook #'org-roam-db--close-all)
(add-hook 'org-open-at-point-functions #'org-roam-open-id-at-point) (add-hook 'org-open-at-point-functions #'org-roam-open-id-at-point)
(add-hook 'org-open-link-functions #'org-roam--open-fuzzy-link)
(unless org-roam--file-update-timer (unless org-roam--file-update-timer
(setq org-roam--file-update-timer (run-with-idle-timer org-roam-update-db-idle-seconds t #'org-roam--process-update-queue))) (setq org-roam--file-update-timer (run-with-idle-timer org-roam-update-db-idle-seconds t #'org-roam--process-update-queue)))
(advice-add 'rename-file :after #'org-roam--rename-file-advice) (advice-add 'rename-file :after #'org-roam--rename-file-advice)
@ -1740,7 +1536,6 @@ M-x info for more information at Org-roam > Installation > Post-Installation Tas
(remove-hook 'find-file-hook #'org-roam--find-file-hook-function) (remove-hook 'find-file-hook #'org-roam--find-file-hook-function)
(remove-hook 'kill-emacs-hook #'org-roam-db--close-all) (remove-hook 'kill-emacs-hook #'org-roam-db--close-all)
(remove-hook 'org-open-at-point-functions #'org-roam-open-id-at-point) (remove-hook 'org-open-at-point-functions #'org-roam-open-id-at-point)
(remove-hook 'org-open-link-functions #'org-roam--open-fuzzy-link)
(when org-roam--file-update-timer (when org-roam--file-update-timer
(cancel-timer org-roam--file-update-timer)) (cancel-timer org-roam--file-update-timer))
(advice-remove 'rename-file #'org-roam--rename-file-advice) (advice-remove 'rename-file #'org-roam--rename-file-advice)
@ -1753,7 +1548,7 @@ M-x info for more information at Org-roam > Installation > Post-Installation Tas
(dolist (buf (org-roam--get-roam-buffers)) (dolist (buf (org-roam--get-roam-buffers))
(with-current-buffer buf (with-current-buffer buf
(remove-hook 'post-command-hook #'org-roam-buffer--update-maybe t) (remove-hook 'post-command-hook #'org-roam-buffer--update-maybe t)
(remove-hook 'before-save-hook #'org-roam--replace-fuzzy-link-on-save t) (remove-hook 'before-save-hook #'org-roam-link--replace-link-on-save t)
(remove-hook 'after-save-hook #'org-roam--queue-file-for-update t)))))) (remove-hook 'after-save-hook #'org-roam--queue-file-for-update t))))))
;;; Interactive Commands ;;; Interactive Commands

View File

@ -259,25 +259,25 @@
`(["e84d0630-efad-4017-9059-5ef917908823" ,(test-org-roam--abs-path "headlines/headline.org")] `(["e84d0630-efad-4017-9059-5ef917908823" ,(test-org-roam--abs-path "headlines/headline.org")]
["801b58eb-97e2-435f-a33e-ff59a2f0c213" ,(test-org-roam--abs-path "headlines/headline.org")]))))) ["801b58eb-97e2-435f-a33e-ff59a2f0c213" ,(test-org-roam--abs-path "headlines/headline.org")])))))
(describe "Test fuzzy links" (describe "Test roam links"
(it "" (it ""
(expect (org-roam--split-fuzzy-link "") (expect (org-roam-link--split-path "")
:to-equal :to-equal
'(title "" "" nil))) '(title "" "" nil)))
(it "title" (it "title"
(expect (org-roam--split-fuzzy-link "title") (expect (org-roam-link--split-path "title")
:to-equal :to-equal
'(title "title" "" nil))) '(title "title" "" nil)))
(it "title*" (it "title*"
(expect (org-roam--split-fuzzy-link "title*") (expect (org-roam-link--split-path "title*")
:to-equal :to-equal
'(title+headline "title" "" 5))) '(title+headline "title" "" 5)))
(it "title*headline" (it "title*headline"
(expect (org-roam--split-fuzzy-link "title*headline") (expect (org-roam-link--split-path "title*headline")
:to-equal :to-equal
'(title+headline "title" "headline" 5))) '(title+headline "title" "headline" 5)))
(it "*headline" (it "*headline"
(expect (org-roam--split-fuzzy-link "*headline") (expect (org-roam-link--split-path "*headline")
:to-equal :to-equal
'(headline "" "headline" 0)))) '(headline "" "headline" 0))))