Compare commits

..

2 Commits

Author SHA1 Message Date
Jethro Kuan
4ae5c99942 regenerate texi 2021-12-23 17:00:38 +08:00
Jethro Kuan
71cc275c3e docs: Correct how to install gcc on Windows
PATH needs to be manually set on Windows. Previously, it was explicitly
mentioned that it was unnecessary. More recent experience is that it's necessary.
2021-12-23 16:59:28 +08:00
22 changed files with 326 additions and 994 deletions

View File

@@ -4,9 +4,6 @@
(elisp-lint-ignored-validators . ("byte-compile" "package-lint")) (elisp-lint-ignored-validators . ("byte-compile" "package-lint"))
(elisp-lint-indent-specs . ((describe . 1) (elisp-lint-indent-specs . ((describe . 1)
(it . 1) (it . 1)
(thread-first . 0)
(cl-flet . 1)
(cl-flet* . 1)
(org-element-map . defun) (org-element-map . defun)
(org-roam-dolist-with-progress . 2) (org-roam-dolist-with-progress . 2)
(org-roam-with-temp-buffer . 1) (org-roam-with-temp-buffer . 1)

View File

@@ -46,7 +46,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install Eldev - name: Install Eldev
run: curl -fsSL https://raw.github.com/org-roam/org-roam/master/github-eldev | sh run: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/github-eldev | sh
- name: Install dependencies - name: Install dependencies
run: make prepare run: make prepare

View File

@@ -1,45 +1,8 @@
# Changelog # Changelog
## 2.2.1
### Breaking
- [#2054](https://github.com/org-roam/org-roam/pull/2054) node: simplify default `org-roam-node-display-template`.
This was done so completions work fine by default on all completion systems. To restore the tabular vertical completion interface, set this in your configuration:
```emacs-lisp
(setq org-roam-node-display-template
(concat "${title:*} "
(propertize "${tags:10}" 'face 'org-tag)))
```
## TBD
### Added ### Added
- [#2042](https://github.com/org-roam/org-roam/pull/2042) db: add `org-roam-db-extra-links-elements` and `org-roam-db-extra-links-exclude-keys` for fine-grained control over additional link parsing - [#1806](https://github.com/org-roam/org-roam/pull/1806) db: support caching and usage of Org 9.5's in-built citations
- [#2049](https://github.com/org-roam/org-roam/pull/2049) capture: allow ID to be used as part of `org-roam-capture-templates`
- [#2050](https://github.com/org-roam/org-roam/pull/2050) core: add `FILTER-FN` to `org-roam-node-random`
- [#2065](https://github.com/org-roam/org-roam/pull/2065) dailies: add `keys` argument to the remaining dailies functions `org-roam-dailies-goto-yesterday`/`-today`/`-tomorrow`/`-date` and `org-roam-dailies-capture-yesterday`/`-tomorrow`/`-date` to give the abilty to get into a capture buffer bypassing the selection screen in all dailies commands. Extension of #2055
- [#2079](https://github.com/org-roam/org-roam/pull/2079) capture: ensure that `:ref` info captured in all cases.
- [#2121](https://github.com/org-roam/org-roam/pull/2121) buffer: add unique option to `org-roam-backlinks-section`
### Removed
### Fixed
- [#2086](https://github.com/org-roam/org-roam/pull/2086) capture: correctly update org-id-locations on capture
- [#2082](https://github.com/org-roam/org-roam/pull/2082) buffer: don't destroy window if `org-roam-node-toggle` reuses window
- [#2080](https://github.com/org-roam/org-roam/pull/2080) dailies: prevent multiple "dailies/" subdir expansions
- [#2055](https://github.com/org-roam/org-roam/pull/2055) dailies: removed stray f require, which was causing require and compilation errors
- [#2117](https://github.com/org-roam/org-roam/pull/2117) capture: preserve trailing whitespace content in capture templates
### Changed
- [#2060](https://github.com/org-roam/org-roam/pull/2060) node: added double acute accent normalization for Unicode characters in titles
- [#2040](https://github.com/org-roam/org-roam/pull/2040) completions: fix completions display-width for Helm users
- [#2025](https://github.com/org-roam/org-roam/pull/2025) chore: removed the dependencies on f.el and s.el
- [#2109](https://github.com/org-roam/org-roam/pull/2109) capture: `org-roam-node-insert` places cursor after inserted link where appropriate
- [#2123](https://github.com/org-roam/org-roam/pull/2123), [#2124](https://github.com/org-roam/org-roam/pull/2124) buffer: `org-roam-mode-section-functions` renamed to `org-roam-mode-sections`, supports passing args into the section-rendering function
## 2.2.0
### Added
- [#1806](https://github.com/org-roam/org-roam/pull/1806), [#2017](https://github.com/org-roam/org-roam/pull/2017) db: support caching and usage of Org 9.5's in-built citations
- [#1963](https://github.com/org-roam/org-roam/pull/1963) db: cache file title into files table
- [#1977](https://github.com/org-roam/org-roam/pull/1977) db: support Org-ref v3 citations
- [#1907](https://github.com/org-roam/org-roam/pull/1907), [#2009](https://github.com/org-roam/org-roam/pull/2009), [#2018](https://github.com/org-roam/org-roam/pull/2018) db: support sqlite3
- [#2028](https://github.com/org-roam/org-roam/pull/2028) dailies: add `keys` argument to `org-roam-dailies-capture-today` and `org-roam-dailies--capture` functions to give the abilty to get into a capture buffer bypassing the selection screen
### Removed ### Removed
### Changed ### Changed
@@ -47,22 +10,12 @@
- [#1809](https://github.com/org-roam/org-roam/pull/1809) capture: the mandatory `:if-new` property of each capture template is now renamed to `:target` - [#1809](https://github.com/org-roam/org-roam/pull/1809) capture: the mandatory `:if-new` property of each capture template is now renamed to `:target`
- [#1829](https://github.com/org-roam/org-roam/pull/1829) perf: file sql updates are now wrapped in a transaction - [#1829](https://github.com/org-roam/org-roam/pull/1829) perf: file sql updates are now wrapped in a transaction
- [#1877](https://github.com/org-roam/org-roam/pull/1877) dailies: stop asking for time, only date - [#1877](https://github.com/org-roam/org-roam/pull/1877) dailies: stop asking for time, only date
- [#1949](https://github.com/org-roam/org-roam/pull/1949) db: check for property drawers are now case-insensitive
### Fixed ### Fixed
- [#1798](https://github.com/org-roam/org-roam/pull/1798) org-roam-node-at-point: do not skip invisible headings - [#1798](https://github.com/org-roam/org-roam/pull/1798) org-roam-node-at-point: do not skip invisible headings
- [#1807](https://github.com/org-roam/org-roam/pull/1807) capture: always trigger `:if-new` template for existing nodes - [#1807](https://github.com/org-roam/org-roam/pull/1807) capture: always trigger `:if-new` template for existing nodes
- [#1813](https://github.com/org-roam/org-roam/pull/1813) db: prevent empty ROAM_ALIASES from crashing db updates - [#1813](https://github.com/org-roam/org-roam/pull/1813) db: prevent empty ROAM_ALIASES from crashing db updates
- [#1816](https://github.com/org-roam/org-roam/pull/1816) db: prevent invalid ROAM_REFS from crashing db updates - [#1816](https://github.com/org-roam/org-roam/pull/1816) db: prevent invalid ROAM_REFS from crashing db updates
- [#1893](https://github.com/org-roam/org-roam/pull/1893), [#1896](https://github.com/org-roam/org-roam/pull/1896), [#1901](https://github.com/org-roam/org-roam/pull/1901), [#1895](https://github.com/org-roam/org-roam/pull/1895), [#1904](https://github.com/org-roam/org-roam/pull/1904) completions: various mini-buffer related completion fixes
- [#1931](https://github.com/org-roam/org-roam/pull/1931) utils: org-roam-set-keyword now skips over all drawers
- [#1947](https://github.com/org-roam/org-roam/pull/1947) db: links in ROAM_REFS are no longer considered as links
- [#1948](https://github.com/org-roam/org-roam/pull/1948) completions: fix same-line completions
- [#1953](https://github.com/org-roam/org-roam/pull/1953) db: refresh CATEGORY before writing to db
- [#1946](https://github.com/org-roam/org-roam/pull/1946), [#1946](https://github.com/org-roam/org-roam/pull/1946), [#1958](https://github.com/org-roam/org-roam/pull/1958) various performance improvements
- [#1980](https://github.com/org-roam/org-roam/pull/1980) utils: fix org-roam-with-file changing the minor-mode
- [#2016](https://github.com/org-roam/org-roam/pull/2016) db: fix node caching being affected by agenda variables
- [#2033](https://github.com/org-roam/org-roam/pull/2023) db: respect local variables during db parsing
## 2.1.0 ## 2.1.0
### Added ### Added

View File

@@ -47,6 +47,30 @@ Stable](https://stable.melpa.org/) using `package.el`:
``` ```
M-x package-install RET org-roam RET M-x package-install RET org-roam RET
``` ```
Here's a very basic sample for configuration of `org-roam` using `use-package`:
```emacs-lisp
(use-package org-roam
:ensure t
:custom
(org-roam-directory (file-truename "/path/to/org-files/"))
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n g" . org-roam-graph)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
;; Dailies
("C-c n j" . org-roam-dailies-capture-today))
:config
(org-roam-db-autosync-mode)
;; If using org-roam-protocol
(require 'org-roam-protocol))
```
Note that the `file-truename` function is only necessary when you use symbolic
link to `org-roam-directory`. Org-roam won't automatically resolve symbolic link
to the directory.
</details> </details>
### Using `straight.el` ### Using `straight.el`
@@ -174,33 +198,6 @@ Org-roam also comes with `.texi` files to integrate with Emacs' built-in Info
system. Read the manual to find more details for how to install them manually. system. Read the manual to find more details for how to install them manually.
</details> </details>
## Configuration
Here's a very basic sample for configuration of `org-roam` using `use-package`:
```emacs-lisp
(use-package org-roam
:ensure t
:custom
(org-roam-directory (file-truename "/path/to/org-files/"))
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n g" . org-roam-graph)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
;; Dailies
("C-c n j" . org-roam-dailies-capture-today))
:config
;; If you're using a vertical completion framework, you might want a more informative completion interface
(setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
(org-roam-db-autosync-mode)
;; If using org-roam-protocol
(require 'org-roam-protocol))
```
Note that the `file-truename` function is only necessary when you use symbolic
link to `org-roam-directory`. Org-roam won't automatically resolve symbolic link
to the directory.
## Getting Started ## Getting Started
[David Wilson](https://github.com/daviwil) of [System [David Wilson](https://github.com/daviwil) of [System
@@ -228,7 +225,7 @@ it has not already been addressed on [GitHub][issues] or on
- [Jethro Kuan](https://braindump.jethro.dev/) - [Jethro Kuan](https://braindump.jethro.dev/)
([Source](https://github.com/jethrokuan/braindump/tree/master/org)) ([Source](https://github.com/jethrokuan/braindump/tree/master/org))
- [Alexey Shmalko](https://www.alexeyshmalko.com/) - [Alexey Shmalko](https://braindump.rasen.dev/)
- [Sidharth Arya](https://sidhartharya.github.io/braindump/index.html) - [Sidharth Arya](https://sidhartharya.github.io/braindump/index.html)
## Contributing ## Contributing

View File

@@ -1,20 +1,20 @@
#+title: Org-roam User Manual #+title: Org-roam User Manual
#+author: Jethro Kuan #+author: Jethro Kuan
#+email: jethrokuan95@gmail.com #+email: jethrokuan95@gmail.com
#+date: 2020-2022 #+date: 2020-2021
#+language: en #+language: en
#+texinfo_deffn: t #+texinfo_deffn: t
#+texinfo_dir_category: Emacs #+texinfo_dir_category: Emacs
#+texinfo_dir_title: Org-roam: (org-roam). #+texinfo_dir_title: Org-roam: (org-roam).
#+texinfo_dir_desc: Roam Research for Emacs. #+texinfo_dir_desc: Roam Research for Emacs.
#+subtitle: for version 2.2.1 #+subtitle: for version 2.1.0
#+options: H:4 num:3 toc:nil creator:t ':t #+options: H:4 num:3 toc:nil creator:t ':t
#+property: header-args :eval never #+property: header-args :eval never
#+texinfo: @noindent #+texinfo: @noindent
This manual is for Org-roam version 2.2.1. This manual is for Org-roam version 2.1.0.
#+BEGIN_QUOTE #+BEGIN_QUOTE
Copyright (C) 2020-2021 Jethro Kuan <jethrokuan95@gmail.com> Copyright (C) 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
@@ -369,12 +369,7 @@ For this tutorial, create an empty directory, and set ~org-roam-directory~:
#+END_SRC #+END_SRC
The ~file-truename~ function is only necessary when you use symbolic links The ~file-truename~ function is only necessary when you use symbolic links
inside ~org-roam-directory~: Org-roam does not resolve symbolic links. One can inside ~org-roam-directory~: Org-roam does not resolve symbolic links.
however instruct Emacs to always resolve symlinks, at a performance cost:
#+begin_src emacs-lisp
(setq find-file-visit-truename t)
#+end_src
Next, we setup Org-roam to run functions on file changes to maintain cache Next, we setup Org-roam to run functions on file changes to maintain cache
consistency. This is achieved by running ~M-x org-roam-db-autosync-mode~. To consistency. This is achieved by running ~M-x org-roam-db-autosync-mode~. To
@@ -418,59 +413,8 @@ brought through the node creation process.
One can also conveniently insert links via the completion-at-point functions One can also conveniently insert links via the completion-at-point functions
Org-roam provides (see [[*Completion][Completion]]). Org-roam provides (see [[*Completion][Completion]]).
** Customizing Node Completions
Node selection is achieved via the ~completing-read~ interface, typically
through `org-roam-node-read`. The presentation of these nodes are governed by
~org-roam-node-display-template~.
- Variable: org-roam-node-display-template
Configures display formatting for Org-roam node.
Patterns of form "${field-name:length}" are interpolated based
on the current node.
Each "field-name" is replaced with the return value of each
corresponding accessor function for org-roam-node, e.g.
"${title}" will be interpolated by the result of
org-roam-node-title. You can also define custom accessors using
cl-defmethod. For example, you can define:
(cl-defmethod org-roam-node-my-title ((node org-roam-node))
(concat "My " (org-roam-node-title node)))
and then reference it here or in the capture templates as
"${my-title}".
"length" is an optional specifier and declares how many
characters can be used to display the value of the corresponding
field. If it's not specified, the field will be inserted as is,
i.e. it won't be aligned nor trimmed. If it's an integer, the
field will be aligned accordingly and all the exceeding
characters will be trimmed out. If it's "*", the field will use
as many characters as possible and will be aligned accordingly.
A closure can also be assigned to this variable in which case the
closure is evaluated and the return value is used as the
template. The closure must evaluate to a valid template string.
If you're using a vertical completion framework, such as Ivy and Selectrum,
Org-roam supports the generation of an aligned, tabular completion interface.
For example, to include a column for tags up to 10 character widths wide, one
can set ~org-roam-node-display-template~ as such:
#+begin_src emacs-lisp
(setq org-roam-node-display-template
(concat "${title:*} "
(propertize "${tags:10}" 'face 'org-tag)))
#+end_src
* Customizing Node Caching * Customizing Node Caching
** How to cache ** How to cache
:PROPERTIES:
:ID: 280bfca8-83f3-4371-bc3a-25478d25129c
:END:
Org-roam uses a sqlite database to perform caching, but there are multiple Emacs Org-roam uses a sqlite database to perform caching, but there are multiple Emacs
libraries that can be used. The default used by Org-roam is ~emacs-sqlite~. libraries that can be used. The default used by Org-roam is ~emacs-sqlite~.
@@ -541,35 +485,6 @@ all headlines with the ~ATTACH~ tag from the Org-roam database, one can set:
(not (member "ATTACH" (org-get-tags))))) (not (member "ATTACH" (org-get-tags)))))
#+end_src #+end_src
Org-roam relied on the obtained Org AST for the buffer to parse links. However,
links appearing in some places (e.g. within property drawers) are not considered
by the Org AST to be links. Therefore, Org-roam takes special care of
additionally trying to process these links. Use
~org-roam-db-extra-links-elements~ to specify which additional Org AST element
types to consider.
- Variable: org-roam-db-extra-links-elements
The list of Org element types to include for parsing by Org-roam.
By default, when parsing Org's AST, links within keywords and
property drawers are not parsed as links. Sometimes however, it
is desirable to parse and cache these links (e.g. hiding links in
a property drawer).
Additionally, one may want to ignore certain keys from being excluded within
property drawers. For example, we would not want ~ROAM_REFS~ links to be
self-referential. Hence, to exclude specific keys, we use
~org-roam-db-extra-links-exclude-keys~.
- Variable: org-roam-db-extra-links-exclude-keys
Keys to ignore when mapping over links.
The car of the association list is the Org element type (e.g. keyword). The
cdr is a list of case-insensitive strings to exclude from being treated as
links.
** When to cache ** When to cache
By default, Org-roam is eager in caching: each time an Org-roam file is modified By default, Org-roam is eager in caching: each time an Org-roam file is modified
@@ -636,10 +551,10 @@ There are currently 3 provided widget types:
- Unlinked references :: View nodes that contain text that match the nodes - Unlinked references :: View nodes that contain text that match the nodes
title/alias but are not linked title/alias but are not linked
To configure what sections are displayed in the buffer, set ~org-roam-mode-sections. To configure what sections are displayed in the buffer, set ~org-roam-mode-section-functions~.
#+begin_src emacs-lisp #+begin_src emacs-lisp
(setq org-roam-mode-sections (setq org-roam-mode-section-functions
(list #'org-roam-backlinks-section (list #'org-roam-backlinks-section
#'org-roam-reflinks-section #'org-roam-reflinks-section
;; #'org-roam-unlinked-references-section ;; #'org-roam-unlinked-references-section
@@ -648,16 +563,6 @@ To configure what sections are displayed in the buffer, set ~org-roam-mode-secti
Note that computing unlinked references may be slow, and has not been added in by default. Note that computing unlinked references may be slow, and has not been added in by default.
For each section function, you can pass args along to modify its behaviour. For
example, if you want to render unique sources for backlinks (and also keep
rendering reference links), set ~org-roam-mode-sections~ as follows:
#+begin_src emacs-lisp
(setq org-roam-mode-sections
'((org-roam-backlinks-section :unique t)
org-roam-reflinks-section))
#+end_src
** Configuring the Org-roam buffer display ** Configuring the Org-roam buffer display
Org-roam does not control how the pop-up buffer is displayed: this is left to Org-roam does not control how the pop-up buffer is displayed: this is left to
@@ -806,16 +711,6 @@ citation key:
:END: :END:
#+end_src #+end_src
or
#+begin_src org
,* Probabilistic Robotics
:PROPERTIES:
:ID: 51b7b82c-bbb4-4822-875a-ed548cffda10
:ROAM_REFS: [cite:@thrun2005probabilistic]
:END:
#+end_src
for ~org-cite~, or: for ~org-cite~, or:
#+begin_src org #+begin_src org
@@ -912,16 +807,7 @@ file:
#+END_SRC #+END_SRC
We also need to set up ~org-protocol~: the instructions for setting up We also need to set up ~org-protocol~: the instructions for setting up
~org-protocol~ are reproduced here. ~org-protocol~ are reproduced below.
On a high-level, external calls are passed to Emacs via ~emacsclient~.
~org-protocol~ intercepts these and runs custom actions based on the protocols
registered. Hence, to use ~org-protocol~, once must:
1. launch the ~emacsclient~ process
2. Register ~org-protocol://~ as a valid scheme-handler
The instructions for the latter for each operating system is detailed below.
*** Linux *** Linux
For Linux users, create a desktop application in For Linux users, create a desktop application in
@@ -1465,9 +1351,6 @@ documents (PDF, EPUB etc.) within Org-mode.
** Bibliography ** Bibliography
Org 9.5 added native citation and bibliography functionality, called "org-cite",
which org-roam supports.
[[https://github.com/org-roam/org-roam-bibtex][org-roam-bibtex]] offers tight integration between [[https://github.com/jkitchin/org-ref][org-ref]], [[https://github.com/tmalsburg/helm-bibtex][helm-bibtex]] and [[https://github.com/org-roam/org-roam-bibtex][org-roam-bibtex]] offers tight integration between [[https://github.com/jkitchin/org-ref][org-ref]], [[https://github.com/tmalsburg/helm-bibtex][helm-bibtex]] and
~org-roam~. This helps you manage your bibliographic notes under ~org-roam~. ~org-roam~. This helps you manage your bibliographic notes under ~org-roam~.
@@ -1640,20 +1523,6 @@ to the publishing directory. Example code follows:
(kill-buffer (file-name-nondirectory svg)) (kill-buffer (file-name-nondirectory svg))
(setq my-publish-time 0))))) (setq my-publish-time 0)))))
#+end_src #+end_src
** I'm seeing this "Selecting deleted buffer" error. What do I do?
The "selecting deleted buffer" error usually occurs when you don't have a
working ~emacsql-sqlite~ executable. Org-roam relies on this executable to
function properly, and doesn't catch this error. This issue is most commonly
seen on Windows setups. You can browse through the various GitHub issues posted
about this [[https://github.com/org-roam/org-roam/issues?q=is%3Aissue+selecting+deleted][here]].
To fix this, you can try the following:
1. If on Windows, try replacing your system binary with [[https://github.com/nobiot/emacsql-sqlite.exe][this one]] that has been proven
to work
2. Use the ~emacsql-sqlite3~ option rather than compiling your own emacsql
binary (see [[id:280bfca8-83f3-4371-bc3a-25478d25129c][How to cache]]).
* Developer's Guide to Org-roam * Developer's Guide to Org-roam
** Org-roam's Design Principle ** Org-roam's Design Principle

View File

@@ -31,7 +31,7 @@ General Public License for more details.
@finalout @finalout
@titlepage @titlepage
@title Org-roam User Manual @title Org-roam User Manual
@subtitle for version 2.2.1 @subtitle for version 2.1.0
@author Jethro Kuan @author Jethro Kuan
@page @page
@vskip 0pt plus 1filll @vskip 0pt plus 1filll
@@ -44,7 +44,7 @@ General Public License for more details.
@noindent @noindent
This manual is for Org-roam version 2.2.1. This manual is for Org-roam version 2.1.0.
@quotation @quotation
Copyright (C) 2020-2021 Jethro Kuan <jethrokuan95@@gmail.com> Copyright (C) 2020-2021 Jethro Kuan <jethrokuan95@@gmail.com>
@@ -110,7 +110,6 @@ Getting Started
* Links between Nodes:: * Links between Nodes::
* Setting up Org-roam:: * Setting up Org-roam::
* Creating and Linking Nodes:: * Creating and Linking Nodes::
* Customizing Node Completions::
Customizing Node Caching Customizing Node Caching
@@ -195,7 +194,6 @@ FAQ
* How do I migrate from Roam Research?:: * How do I migrate from Roam Research?::
* How to migrate from Org-roam v1?:: * How to migrate from Org-roam v1?::
* How do I publish my notes with an Internet-friendly graph?:: * How do I publish my notes with an Internet-friendly graph?::
* I'm seeing this ``Selecting deleted buffer'' error. What do I do?: I'm seeing this ``Selecting deleted buffer'' error What do I do?.
How do I publish my notes with an Internet-friendly graph? How do I publish my notes with an Internet-friendly graph?
@@ -588,7 +586,6 @@ your Emacs configuration folder like this:
* Links between Nodes:: * Links between Nodes::
* Setting up Org-roam:: * Setting up Org-roam::
* Creating and Linking Nodes:: * Creating and Linking Nodes::
* Customizing Node Completions::
@end menu @end menu
@node The Org-roam Node @node The Org-roam Node
@@ -655,12 +652,7 @@ For this tutorial, create an empty directory, and set @code{org-roam-directory}:
@end lisp @end lisp
The @code{file-truename} function is only necessary when you use symbolic links The @code{file-truename} function is only necessary when you use symbolic links
inside @code{org-roam-directory}: Org-roam does not resolve symbolic links. One can inside @code{org-roam-directory}: Org-roam does not resolve symbolic links.
however instruct Emacs to always resolve symlinks, at a performance cost:
@lisp
(setq find-file-visit-truename t)
@end lisp
Next, we setup Org-roam to run functions on file changes to maintain cache Next, we setup Org-roam to run functions on file changes to maintain cache
consistency. This is achieved by running @code{M-x org-roam-db-autosync-mode}. To consistency. This is achieved by running @code{M-x org-roam-db-autosync-mode}. To
@@ -712,56 +704,6 @@ brought through the node creation process.
One can also conveniently insert links via the completion-at-point functions One can also conveniently insert links via the completion-at-point functions
Org-roam provides (see @ref{Completion}). Org-roam provides (see @ref{Completion}).
@node Customizing Node Completions
@section Customizing Node Completions
Node selection is achieved via the @code{completing-read} interface, typically
through `org-roam-node-read`. The presentation of these nodes are governed by
@code{org-roam-node-display-template}.
@defvar org-roam-node-display-template
Configures display formatting for Org-roam node.
Patterns of form ``$@{field-name:length@}'' are interpolated based
on the current node.
Each ``field-name'' is replaced with the return value of each
corresponding accessor function for org-roam-node, e.g.
``$@{title@}'' will be interpolated by the result of
org-roam-node-title. You can also define custom accessors using
cl-defmethod. For example, you can define:
(cl-defmethod org-roam-node-my-title ((node org-roam-node))
(concat ``My '' (org-roam-node-title node)))
and then reference it here or in the capture templates as
``$@{my-title@}''.
``length'' is an optional specifier and declares how many
characters can be used to display the value of the corresponding
field. If it's not specified, the field will be inserted as is,
i.e. it won't be aligned nor trimmed. If it's an integer, the
field will be aligned accordingly and all the exceeding
characters will be trimmed out. If it's ``*'', the field will use
as many characters as possible and will be aligned accordingly.
A closure can also be assigned to this variable in which case the
closure is evaluated and the return value is used as the
template. The closure must evaluate to a valid template string.
@end defvar
If you're using a vertical completion framework, such as Ivy and Selectrum,
Org-roam supports the generation of an aligned, tabular completion interface.
For example, to include a column for tags up to 10 character widths wide, one
can set @code{org-roam-node-display-template} as such:
@lisp
(setq org-roam-node-display-template
(concat "$@{title:*@} "
(propertize "$@{tags:10@}" 'face 'org-tag)))
@end lisp
@node Customizing Node Caching @node Customizing Node Caching
@chapter Customizing Node Caching @chapter Customizing Node Caching
@@ -844,37 +786,6 @@ all headlines with the @code{ATTACH} tag from the Org-roam database, one can set
(not (member "ATTACH" (org-get-tags))))) (not (member "ATTACH" (org-get-tags)))))
@end example @end example
Org-roam relied on the obtained Org AST for the buffer to parse links. However,
links appearing in some places (e.g. within property drawers) are not considered
by the Org AST to be links. Therefore, Org-roam takes special care of
additionally trying to process these links. Use
@code{org-roam-db-extra-links-elements} to specify which additional Org AST element
types to consider.
@defvar org-roam-db-extra-links-elements
The list of Org element types to include for parsing by Org-roam.
By default, when parsing Org's AST, links within keywords and
property drawers are not parsed as links. Sometimes however, it
is desirable to parse and cache these links (e.g. hiding links in
a property drawer).
@end defvar
Additionally, one may want to ignore certain keys from being excluded within
property drawers. For example, we would not want @code{ROAM_REFS} links to be
self-referential. Hence, to exclude specific keys, we use
@code{org-roam-db-extra-links-exclude-keys}.
@defvar org-roam-db-extra-links-exclude-keys
Keys to ignore when mapping over links.
The car of the association list is the Org element type (e.g. keyword). The
cdr is a list of case-insensitive strings to exclude from being treated as
links.
@end defvar
@node When to cache @node When to cache
@section When to cache @section When to cache
@@ -976,10 +887,10 @@ There are currently 3 provided widget types:
title/alias but are not linked title/alias but are not linked
@end itemize @end itemize
To configure what sections are displayed in the buffer, set ~org-roam-mode-sections. To configure what sections are displayed in the buffer, set @code{org-roam-mode-section-functions}.
@lisp @lisp
(setq org-roam-mode-sections (setq org-roam-mode-section-functions
(list #'org-roam-backlinks-section (list #'org-roam-backlinks-section
#'org-roam-reflinks-section #'org-roam-reflinks-section
;; #'org-roam-unlinked-references-section ;; #'org-roam-unlinked-references-section
@@ -988,16 +899,6 @@ To configure what sections are displayed in the buffer, set ~org-roam-mode-secti
Note that computing unlinked references may be slow, and has not been added in by default. Note that computing unlinked references may be slow, and has not been added in by default.
For each section function, you can pass args along to modify its behaviour. For
example, if you want to render unique sources for backlinks (and also keep
rendering reference links), set @code{org-roam-mode-sections} as follows:
@lisp
(setq org-roam-mode-sections
'((org-roam-backlinks-section :unique t)
org-roam-reflinks-section))
@end lisp
@node Configuring the Org-roam buffer display @node Configuring the Org-roam buffer display
@section Configuring the Org-roam buffer display @section Configuring the Org-roam buffer display
@@ -1165,7 +1066,7 @@ Remove a ref from the node at point.
Since version 9.5, Org has first-class support for citations. Org-roam supports Since version 9.5, Org has first-class support for citations. Org-roam supports
the caching of both these in-built citations (of form @code{[cite:@@key]}) and @uref{https://github.com/jkitchin/org-ref, org-ref} the caching of both these in-built citations (of form @code{[cite:@@key]}) and @uref{https://github.com/jkitchin/org-ref, org-ref}
citations (of form cite:key). citations (of form @uref{key}).
Org-roam attempts to load both the @code{org-ref} and @code{org-cite} package when Org-roam attempts to load both the @code{org-ref} and @code{org-cite} package when
indexing files, so no further setup from the user is required for citation indexing files, so no further setup from the user is required for citation
@@ -1190,16 +1091,6 @@ citation key:
:END: :END:
@end example @end example
or
@example
* Probabilistic Robotics
:PROPERTIES:
:ID: 51b7b82c-bbb4-4822-875a-ed548cffda10
:ROAM_REFS: [cite:@@thrun2005probabilistic]
:END:
@end example
for @code{org-cite}, or: for @code{org-cite}, or:
@example @example
@@ -1319,21 +1210,7 @@ file:
@end lisp @end lisp
We also need to set up @code{org-protocol}: the instructions for setting up We also need to set up @code{org-protocol}: the instructions for setting up
@code{org-protocol} are reproduced here. @code{org-protocol} are reproduced below.
On a high-level, external calls are passed to Emacs via @code{emacsclient}.
@code{org-protocol} intercepts these and runs custom actions based on the protocols
registered. Hence, to use @code{org-protocol}, once must:
@itemize
@item
launch the @code{emacsclient} process
@item
Register @code{org-protocol://} as a valid scheme-handler
@end itemize
The instructions for the latter for each operating system is detailed below.
@menu @menu
* Linux:: * Linux::
@@ -2019,9 +1896,6 @@ documents (PDF, EPUB etc.) within Org-mode.
@node Bibliography @node Bibliography
@section Bibliography @section Bibliography
Org 9.5 added native citation and bibliography functionality, called ``org-cite'',
which org-roam supports.
@uref{https://github.com/org-roam/org-roam-bibtex, org-roam-bibtex} offers tight integration between @uref{https://github.com/jkitchin/org-ref, org-ref}, @uref{https://github.com/tmalsburg/helm-bibtex, helm-bibtex} and @uref{https://github.com/org-roam/org-roam-bibtex, org-roam-bibtex} offers tight integration between @uref{https://github.com/jkitchin/org-ref, org-ref}, @uref{https://github.com/tmalsburg/helm-bibtex, helm-bibtex} and
@code{org-roam}. This helps you manage your bibliographic notes under @code{org-roam}. @code{org-roam}. This helps you manage your bibliographic notes under @code{org-roam}.
@@ -2048,7 +1922,6 @@ Org-mode, and sync your cards to Anki via @uref{https://github.com/FooSoft/anki-
* How do I migrate from Roam Research?:: * How do I migrate from Roam Research?::
* How to migrate from Org-roam v1?:: * How to migrate from Org-roam v1?::
* How do I publish my notes with an Internet-friendly graph?:: * How do I publish my notes with an Internet-friendly graph?::
* I'm seeing this ``Selecting deleted buffer'' error. What do I do?: I'm seeing this ``Selecting deleted buffer'' error What do I do?.
@end menu @end menu
@node How do I have more than one Org-roam directory? @node How do I have more than one Org-roam directory?
@@ -2259,27 +2132,6 @@ to the publishing directory. Example code follows:
(setq my-publish-time 0))))) (setq my-publish-time 0)))))
@end lisp @end lisp
@node I'm seeing this ``Selecting deleted buffer'' error What do I do?
@section I'm seeing this ``Selecting deleted buffer'' error. What do I do?
The ``selecting deleted buffer'' error usually occurs when you don't have a
working @code{emacsql-sqlite} executable. Org-roam relies on this executable to
function properly, and doesn't catch this error. This issue is most commonly
seen on Windows setups. You can browse through the various GitHub issues posted
about this @uref{https://github.com/org-roam/org-roam/issues?q=is%3Aissue+selecting+deleted, here}.
To fix this, you can try the following:
@itemize
@item
If on Windows, try replacing your system binary with @uref{https://github.com/nobiot/emacsql-sqlite.exe, this one} that has been proven
to work
@item
Use the @code{emacsql-sqlite3} option rather than compiling your own emacsql
binary (see @ref{How to cache}).
@end itemize
@node Developer's Guide to Org-roam @node Developer's Guide to Org-roam
@chapter Developer's Guide to Org-roam @chapter Developer's Guide to Org-roam

View File

@@ -7,8 +7,8 @@
;; Leo Vivier <leo.vivier+dev@gmail.com> ;; Leo Vivier <leo.vivier+dev@gmail.com>
;; URL: https://github.com/org-roam/org-roam ;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience ;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1 ;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org-roam "2.1")) ;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org-roam "2.1"))
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.
@@ -34,9 +34,10 @@
;; each file named after certain date and stored in `org-roam-dailies-directory'. ;; each file named after certain date and stored in `org-roam-dailies-directory'.
;; ;;
;; One can use dailies for various purposes, e.g. journaling, fleeting notes, ;; One can use dailies for various purposes, e.g. journaling, fleeting notes,
;; scratch notes or whatever else you can think of. ;; scratch notes and whatever else you can came up with.
;; ;;
;;; Code: ;;; Code:
(require 'f)
(require 'dash) (require 'dash)
(require 'org-roam) (require 'org-roam)
@@ -129,103 +130,79 @@ See `org-roam-capture-templates' for the template documentation."
;;; Commands ;;; Commands
;;;; Today ;;;; Today
;;;###autoload ;;;###autoload
(defun org-roam-dailies-capture-today (&optional goto keys) (defun org-roam-dailies-capture-today (&optional goto)
"Create an entry in the daily-note for today. "Create an entry in the daily-note for today.
When GOTO is non-nil, go the note without creating an entry. When GOTO is non-nil, go the note without creating an entry."
ELisp programs can set KEYS to a string associated with a template.
In this case, interactive selection will be bypassed."
(interactive "P") (interactive "P")
(org-roam-dailies--capture (current-time) goto keys)) (org-roam-dailies--capture (current-time) goto))
;;;###autoload ;;;###autoload
(defun org-roam-dailies-goto-today (&optional keys) (defun org-roam-dailies-goto-today ()
"Find the daily-note for today, creating it if necessary. "Find the daily-note for today, creating it if necessary."
ELisp programs can set KEYS to a string associated with a template.
In this case, interactive selection will be bypassed."
(interactive) (interactive)
(org-roam-dailies-capture-today t keys)) (org-roam-dailies-capture-today t))
;;;; Tomorrow ;;;; Tomorrow
;;;###autoload ;;;###autoload
(defun org-roam-dailies-capture-tomorrow (n &optional goto keys) (defun org-roam-dailies-capture-tomorrow (n &optional goto)
"Create an entry in the daily-note for tomorrow. "Create an entry in the daily-note for tomorrow.
With numeric argument N, use the daily-note N days in the future. With numeric argument N, use the daily-note N days in the future.
With a `C-u' prefix or when GOTO is non-nil, go the note without With a `C-u' prefix or when GOTO is non-nil, go the note without
creating an entry. creating an entry."
ELisp programs can set KEYS to a string associated with a template.
In this case, interactive selection will be bypassed."
(interactive "p") (interactive "p")
(org-roam-dailies--capture (time-add (* n 86400) (current-time)) goto keys)) (org-roam-dailies--capture (time-add (* n 86400) (current-time)) goto))
;;;###autoload ;;;###autoload
(defun org-roam-dailies-goto-tomorrow (n &optional keys) (defun org-roam-dailies-goto-tomorrow (n)
"Find the daily-note for tomorrow, creating it if necessary. "Find the daily-note for tomorrow, creating it if necessary.
With numeric argument N, use the daily-note N days in the With numeric argument N, use the daily-note N days in the
future. future."
ELisp programs can set KEYS to a string associated with a template.
In this case, interactive selection will be bypassed."
(interactive "p") (interactive "p")
(org-roam-dailies-capture-tomorrow n t keys)) (org-roam-dailies-capture-tomorrow n t))
;;;; Yesterday ;;;; Yesterday
;;;###autoload ;;;###autoload
(defun org-roam-dailies-capture-yesterday (n &optional goto keys) (defun org-roam-dailies-capture-yesterday (n &optional goto)
"Create an entry in the daily-note for yesteday. "Create an entry in the daily-note for yesteday.
With numeric argument N, use the daily-note N days in the past. With numeric argument N, use the daily-note N days in the past.
When GOTO is non-nil, go the note without creating an entry. When GOTO is non-nil, go the note without creating an entry."
ELisp programs can set KEYS to a string associated with a template.
In this case, interactive selection will be bypassed."
(interactive "p") (interactive "p")
(org-roam-dailies-capture-tomorrow (- n) goto keys)) (org-roam-dailies-capture-tomorrow (- n) goto))
;;;###autoload ;;;###autoload
(defun org-roam-dailies-goto-yesterday (n &optional keys) (defun org-roam-dailies-goto-yesterday (n)
"Find the daily-note for yesterday, creating it if necessary. "Find the daily-note for yesterday, creating it if necessary.
With numeric argument N, use the daily-note N days in the With numeric argument N, use the daily-note N days in the
future. future."
ELisp programs can set KEYS to a string associated with a template.
In this case, interactive selection will be bypassed."
(interactive "p") (interactive "p")
(org-roam-dailies-capture-tomorrow (- n) t keys)) (org-roam-dailies-capture-tomorrow (- n) t))
;;;; Date ;;;; Date
;;;###autoload ;;;###autoload
(defun org-roam-dailies-capture-date (&optional goto prefer-future keys) (defun org-roam-dailies-capture-date (&optional goto prefer-future)
"Create an entry in the daily-note for a date using the calendar. "Create an entry in the daily-note for a date using the calendar.
Prefer past dates, unless PREFER-FUTURE is non-nil. Prefer past dates, unless PREFER-FUTURE is non-nil.
With a `C-u' prefix or when GOTO is non-nil, go the note without With a `C-u' prefix or when GOTO is non-nil, go the note without
creating an entry. creating an entry."
ELisp programs can set KEYS to a string associated with a template.
In this case, interactive selection will be bypassed."
(interactive "P") (interactive "P")
(let ((time (let ((org-read-date-prefer-future prefer-future)) (let ((time (let ((org-read-date-prefer-future prefer-future))
(org-read-date nil t nil (if goto (org-read-date nil t nil (if goto
"Find daily-note: " "Find daily-note: "
"Capture to daily-note: "))))) "Capture to daily-note: ")))))
(org-roam-dailies--capture time goto keys))) (org-roam-dailies--capture time goto)))
;;;###autoload ;;;###autoload
(defun org-roam-dailies-goto-date (&optional prefer-future keys) (defun org-roam-dailies-goto-date (&optional prefer-future)
"Find the daily-note for a date using the calendar, creating it if necessary. "Find the daily-note for a date using the calendar, creating it if necessary.
Prefer past dates, unless PREFER-FUTURE is non-nil. Prefer past dates, unless PREFER-FUTURE is non-nil."
ELisp programs can set KEYS to a string associated with a template.
In this case, interactive selection will be bypassed."
(interactive) (interactive)
(org-roam-dailies-capture-date t prefer-future keys)) (org-roam-dailies-capture-date t prefer-future))
;;;; Navigation ;;;; Navigation
(defun org-roam-dailies-goto-next-note (&optional n) (defun org-roam-dailies-goto-next-note (&optional n)
@@ -289,7 +266,7 @@ If FILE is not specified, use the current buffer's file-path."
(save-match-data (save-match-data
(and (and
(org-roam-file-p path) (org-roam-file-p path)
(org-roam-descendant-of-p path directory))))) (f-descendant-of-p path directory)))))
;;;###autoload ;;;###autoload
(defun org-roam-dailies-find-directory () (defun org-roam-dailies-find-directory ()
@@ -323,16 +300,11 @@ Return (MONTH DAY YEAR) or nil if not an Org time-string."
;;; Capture implementation ;;; Capture implementation
(add-to-list 'org-roam-capture--template-keywords :override-default-time) (add-to-list 'org-roam-capture--template-keywords :override-default-time)
(defun org-roam-dailies--capture (time &optional goto keys) (defun org-roam-dailies--capture (time &optional goto)
"Capture an entry in a daily-note for TIME, creating it if necessary. "Capture an entry in a daily-note for TIME, creating it if necessary.
When GOTO is non-nil, go the note without creating an entry. When GOTO is non-nil, go the note without creating an entry."
(let ((org-roam-directory (expand-file-name org-roam-dailies-directory org-roam-directory)))
ELisp programs can set KEYS to a string associated with a template.
In this case, interactive selection will be bypassed."
(let ((org-roam-directory (expand-file-name org-roam-dailies-directory org-roam-directory))
(org-roam-dailies-directory "./"))
(org-roam-capture- :goto (when goto '(4)) (org-roam-capture- :goto (when goto '(4))
:keys keys
:node (org-roam-node-create) :node (org-roam-node-create)
:templates org-roam-dailies-capture-templates :templates org-roam-dailies-capture-templates
:props (list :override-default-time time))) :props (list :override-default-time time)))

View File

@@ -5,7 +5,7 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com> ;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam ;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience ;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1 ;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1")) ;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1"))
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.
@@ -266,7 +266,7 @@ Handles both Org-roam nodes, and string nodes (e.g. urls)."
(org-roam-quote-string (org-roam-quote-string
(pcase org-roam-graph-shorten-titles (pcase org-roam-graph-shorten-titles
(`truncate (truncate-string-to-width title org-roam-graph-max-title-length nil nil "...")) (`truncate (truncate-string-to-width title org-roam-graph-max-title-length nil nil "..."))
(`wrap (org-roam-word-wrap org-roam-graph-max-title-length title)) (`wrap (s-word-wrap org-roam-graph-max-title-length title))
(_ title))))) (_ title)))))
(setq node-id (org-roam-node-id node) (setq node-id (org-roam-node-id node)
node-properties `(("label" . ,shortened-title) node-properties `(("label" . ,shortened-title)

View File

@@ -5,7 +5,7 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com> ;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam ;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience ;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1 ;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1")) ;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1"))
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.

View File

@@ -4,7 +4,7 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com> ;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam ;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience ;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1 ;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1")) ;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1"))
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.
@@ -169,6 +169,25 @@ org-protocol://roam-node?node=uuid"
(push '("org-roam-node" :protocol "roam-node" :function org-roam-protocol-open-node) (push '("org-roam-node" :protocol "roam-node" :function org-roam-protocol-open-node)
org-protocol-protocol-alist) org-protocol-protocol-alist)
;;; Capture implementation
(add-hook 'org-roam-capture-preface-hook #'org-roam-protocol--try-capture-to-ref-h)
(defun org-roam-protocol--try-capture-to-ref-h ()
"Try to capture to an existing node that match the ref."
(when-let ((node (and (plist-get org-roam-capture--info :ref)
(org-roam-node-from-ref
(plist-get org-roam-capture--info :ref)))))
(set-buffer (org-capture-target-buffer (org-roam-node-file node)))
(goto-char (org-roam-node-point node))
(widen)
(org-roam-node-id node)))
(add-hook 'org-roam-capture-new-node-hook #'org-roam-protocol--insert-captured-ref-h)
(defun org-roam-protocol--insert-captured-ref-h ()
"Insert the ref if any."
(when-let ((ref (plist-get org-roam-capture--info :ref)))
(org-roam-ref-add ref)))
(provide 'org-roam-protocol) (provide 'org-roam-protocol)
;;; org-roam-protocol.el ends here ;;; org-roam-protocol.el ends here

View File

@@ -1,11 +0,0 @@
#! /bin/sh
set -e
ELDEV_BIN_DIR=~/.local/bin
# `$GITHUB_PATH' is a magic file which contents is translated to environment variable `$PATH'.
echo "$ELDEV_BIN_DIR" >> $GITHUB_PATH
mkdir -p $ELDEV_BIN_DIR
curl -fsSL https://raw.githubusercontent.com/doublep/eldev/f111d19cda305e5e8fcb70a5675b87173041cb68/bin/eldev > $ELDEV_BIN_DIR/eldev
chmod a+x $ELDEV_BIN_DIR/eldev

View File

@@ -5,8 +5,8 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com> ;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam ;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience ;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1 ;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0")) ;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.
@@ -407,8 +407,6 @@ TEMPLATES is a list of org-roam templates."
(mapcar (lambda (template) (mapcar (lambda (template)
(org-roam-capture--convert-template template props)) (org-roam-capture--convert-template template props))
(or templates org-roam-capture-templates))) (or templates org-roam-capture-templates)))
(_ (setf (org-roam-node-id node) (or (org-roam-node-id node)
(org-id-new))))
(org-roam-capture--node node) (org-roam-capture--node node)
(org-roam-capture--info info)) (org-roam-capture--info info))
(when (and (not keys) (when (and (not keys)
@@ -505,7 +503,7 @@ Return the ID of the location."
(set-buffer (org-capture-target-buffer path)) (set-buffer (org-capture-target-buffer path))
(when new-file-p (when new-file-p
(org-roam-capture--put :new-file path) (org-roam-capture--put :new-file path)
(insert (org-roam-capture--fill-template head 'ensure-newline))) (insert (org-roam-capture--fill-template head t)))
(widen) (widen)
(setq p (goto-char (point-min)))) (setq p (goto-char (point-min))))
(`(file+head+olp ,path ,head ,olp) (`(file+head+olp ,path ,head ,olp)
@@ -515,7 +513,7 @@ Return the ID of the location."
(widen) (widen)
(when new-file-p (when new-file-p
(org-roam-capture--put :new-file path) (org-roam-capture--put :new-file path)
(insert (org-roam-capture--fill-template head 'ensure-newline))) (insert (org-roam-capture--fill-template head t)))
(setq p (point-min)) (setq p (point-min))
(let ((m (org-roam-capture-find-or-create-olp olp))) (let ((m (org-roam-capture-find-or-create-olp olp)))
(goto-char m))) (goto-char m)))
@@ -574,11 +572,11 @@ Return the ID of the location."
;; caller. ;; caller.
(save-excursion (save-excursion
(goto-char p) (goto-char p)
(if-let ((id (org-entry-get p "ID"))) (when-let* ((node org-roam-capture--node)
(setf (org-roam-node-id org-roam-capture--node) id) (id (org-roam-node-id node)))
(org-entry-put p "ID" (org-roam-node-id org-roam-capture--node))) (org-entry-put p "ID" id))
(prog1 (prog1
(org-id-get) (org-id-get-create)
(run-hooks 'org-roam-capture-new-node-hook))))) (run-hooks 'org-roam-capture-new-node-hook)))))
(defun org-roam-capture--get-target () (defun org-roam-capture--get-target ()
@@ -591,9 +589,8 @@ Return the ID of the location."
PATH is a string that can optionally contain templated text in PATH is a string that can optionally contain templated text in
it." it."
(or (org-roam-node-file org-roam-capture--node) (or (org-roam-node-file org-roam-capture--node)
(thread-first (thread-first path
path (org-roam-capture--fill-template t)
(org-roam-capture--fill-template)
(string-trim) (string-trim)
(expand-file-name org-roam-directory)))) (expand-file-name org-roam-directory))))
@@ -618,7 +615,7 @@ you can catch it with `condition-case'."
(org-with-wide-buffer (org-with-wide-buffer
(goto-char start) (goto-char start)
(dolist (heading olp) (dolist (heading olp)
(setq heading (org-roam-capture--fill-template heading)) (setq heading (org-roam-capture--fill-template heading t))
(let ((re (format org-complex-heading-regexp-format (let ((re (format org-complex-heading-regexp-format
(regexp-quote heading))) (regexp-quote heading)))
(cnt 0)) (cnt 0))
@@ -680,24 +677,6 @@ the current value of `point'."
(goto-char (org-entry-end-position)))))))) (goto-char (org-entry-end-position))))))))
(point)) (point))
;;; Capture implementation
(add-hook 'org-roam-capture-preface-hook #'org-roam-capture--try-capture-to-ref-h)
(defun org-roam-capture--try-capture-to-ref-h ()
"Try to capture to an existing node that match the ref."
(when-let ((node (and (plist-get org-roam-capture--info :ref)
(org-roam-node-from-ref
(plist-get org-roam-capture--info :ref)))))
(set-buffer (org-capture-target-buffer (org-roam-node-file node)))
(goto-char (org-roam-node-point node))
(widen)
(org-roam-node-id node)))
(add-hook 'org-roam-capture-new-node-hook #'org-roam-capture--insert-captured-ref-h)
(defun org-roam-capture--insert-captured-ref-h ()
"Insert the ref if any."
(when-let ((ref (plist-get org-roam-capture--info :ref)))
(org-roam-ref-add ref)))
;;;; Finalizers ;;;; Finalizers
(add-hook 'org-capture-prepare-finalize-hook #'org-roam-capture--install-finalize-h) (add-hook 'org-capture-prepare-finalize-hook #'org-roam-capture--install-finalize-h)
(defun org-roam-capture--install-finalize-h () (defun org-roam-capture--install-finalize-h ()
@@ -710,14 +689,11 @@ the current value of `point'."
(when-let ((region (org-roam-capture--get :region))) (when-let ((region (org-roam-capture--get :region)))
(org-roam-unshield-region (car region) (cdr region))) (org-roam-unshield-region (car region) (cdr region)))
(if org-note-abort (if org-note-abort
(when-let ((new-file (org-roam-capture--get :new-file)) (when-let ((new-file (org-roam-capture--get :new-file)))
(_ (yes-or-no-p "Delete file for aborted capture?"))) (org-roam-message "Deleting file for aborted capture %s" new-file)
(when (find-buffer-visiting new-file) (when (find-buffer-visiting new-file)
(kill-buffer (find-buffer-visiting new-file))) (kill-buffer (find-buffer-visiting new-file)))
(delete-file new-file)) (delete-file new-file))
(when-let* ((buffer (plist-get org-capture-plist :buffer))
(file (buffer-file-name buffer)))
(org-id-add-location (org-roam-capture--get :id) file))
(when-let* ((finalize (org-roam-capture--get :finalize)) (when-let* ((finalize (org-roam-capture--get :finalize))
(org-roam-finalize-fn (intern (concat "org-roam-capture--finalize-" (org-roam-finalize-fn (intern (concat "org-roam-capture--finalize-"
(symbol-name finalize))))) (symbol-name finalize)))))
@@ -744,53 +720,48 @@ This function is to be called in the Org-capture finalization process."
(delete-region (car region) (cdr region)) (delete-region (car region) (cdr region))
(set-marker (car region) nil) (set-marker (car region) nil)
(set-marker (cdr region) nil)) (set-marker (cdr region) nil))
(let* ((id (org-roam-capture--get :id)) (org-with-point-at mkr
(description (org-roam-capture--get :link-description)) (insert (org-link-make-string (concat "id:" (org-roam-capture--get :id))
(link (org-link-make-string (concat "id:" id) (org-roam-capture--get :link-description)))))))
description)))
(if (eq (point) (marker-position mkr))
(insert link)
(org-with-point-at mkr
(insert link)))
(run-hook-with-args 'org-roam-post-node-insert-hook
id
description)))))
;;;; Processing of the capture templates ;;;; Processing of the capture templates
(defun org-roam-capture--fill-template (template &optional ensure-newline) (defun org-roam-capture--fill-template (template &optional org-capture-p newline)
"Expand TEMPLATE and return it. "Expand TEMPLATE and return it.
It expands ${var} occurrences in TEMPLATE, and then runs It expands ${var} occurrences in TEMPLATE. When ORG-CAPTURE-P,
org-capture's template expansion. also run Org-capture's template expansion.
When ENSURE-NEWLINE, always ensure there's a newline behind." If NEWLINE, ensure that the template returned ends with a newline."
(let ((template-whitespace-content (org-roam-whitespace-content template))) (setq template (org-roam-format-template
template
(lambda (key default-val)
(let ((fn (intern key))
(node-fn (intern (concat "org-roam-node-" key)))
(ksym (intern (concat ":" key))))
(cond
((fboundp fn)
(funcall fn org-roam-capture--node))
((fboundp node-fn)
(funcall node-fn org-roam-capture--node))
((plist-get org-roam-capture--info ksym)
(plist-get org-roam-capture--info ksym))
(t (let ((r (read-from-minibuffer (format "%s: " key) default-val)))
(plist-put org-roam-capture--info ksym r)
r)))))))
;; WARNING:
;; `org-capture-fill-template' fills the template, but post-processes whitespace such that the resultant
;; template does not start with any whitespace, and only ends with a single newline
;;
;; In most cases where we rely on `org-capture-fill-template' to populate non-org-capture-related templates,
;; (e.g. in OLPs), we strip the final newline, obtaining a template that seems to be string-trimmed.
;;
;; This means that if the original passed template has newlines, and ORG-CAPTURE-P is true, then the extra
;; whitespace specified in the template will be ignored.
(when org-capture-p
(setq template (setq template
(org-roam-format-template (replace-regexp-in-string "\n$" "" (org-capture-fill-template template))))
template (when (and newline
(lambda (key default-val) (not (string-suffix-p "\n" template)))
(let ((fn (intern key)) (setq template (concat template "\n")))
(node-fn (intern (concat "org-roam-node-" key))) template)
(ksym (intern (concat ":" key))))
(cond
((fboundp fn)
(funcall fn org-roam-capture--node))
((fboundp node-fn)
(funcall node-fn org-roam-capture--node))
((plist-get org-roam-capture--info ksym)
(plist-get org-roam-capture--info ksym))
(t (let ((r (read-from-minibuffer (format "%s: " key) default-val)))
(plist-put org-roam-capture--info ksym r)
r)))))))
;; WARNING:
;; `org-capture-fill-template' fills the template, but post-processes whitespace such that the resultant
;; template does not start with any whitespace, and only ends with a single newline
;;
;; Instead, we restore the whitespace in the original template.
(setq template (replace-regexp-in-string "\n$" "" (org-capture-fill-template template)))
(when (and ensure-newline
(string-equal template-whitespace-content ""))
(setq template-whitespace-content "\n"))
(setq template (concat template template-whitespace-content))
template))
(defun org-roam-capture--convert-template (template &optional props) (defun org-roam-capture--convert-template (template &optional props)
"Convert TEMPLATE from Org-roam syntax to `org-capture-templates' syntax. "Convert TEMPLATE from Org-roam syntax to `org-capture-templates' syntax.

View File

@@ -5,7 +5,7 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com> ;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam ;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience ;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1 ;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1")) ;; Package-Requires: ((emacs "26.1"))
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.
@@ -229,10 +229,6 @@ nodes." org-id-locations-file)
'org-roam-remove-property 'org-roam-remove-property
'org-roam-property-remove "org-roam 2.1") 'org-roam-property-remove "org-roam 2.1")
(define-obsolete-variable-alias
'org-roam-mode-section-functions
'org-roam-mode-sections "org-roam 2.2.0")
;;; Obsolete functions ;;; Obsolete functions
(make-obsolete 'org-roam-get-keyword 'org-collect-keywords "org-roam 2.0") (make-obsolete 'org-roam-get-keyword 'org-collect-keywords "org-roam 2.0")

View File

@@ -5,8 +5,8 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com> ;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam ;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience ;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1 ;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0")) ;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.
@@ -54,7 +54,7 @@ a compiler. See https://nullprogram.com/blog/2014/02/06/."
(const sqlite3) (const sqlite3)
(symbol :tag "other"))) (symbol :tag "other")))
(defcustom org-roam-db-location (locate-user-emacs-file "org-roam.db") (defcustom org-roam-db-location (expand-file-name "org-roam.db" user-emacs-directory)
"The path to file where the Org-roam database is stored. "The path to file where the Org-roam database is stored.
It is the user's responsibility to set this correctly, especially It is the user's responsibility to set this correctly, especially
@@ -98,35 +98,15 @@ slow."
:type 'boolean :type 'boolean
:group 'org-roam) :group 'org-roam)
(defcustom org-roam-db-extra-links-elements '(node-property keyword)
"The list of Org element types to include for parsing by Org-roam.
By default, when parsing Org's AST, links within keywords and
property drawers are not parsed as links. Sometimes however, it
is desirable to parse and cache these links (e.g. hiding links in
a property drawer)."
:package-version '(org-roam . "2.2.0")
:group 'org-roam
:type '(set (const :tag "keywords" keyword)
(const :tag "property drawers" node-property)))
(defcustom org-roam-db-extra-links-exclude-keys '((node-property . ("ROAM_REFS"))
(keyword . ("transclude")))
"Keys to ignore when mapping over links.
The car of the association list is the Org element type (e.g.
keyword). The cdr is a list of case-insensitive strings to
exclude from being treated as links.
For example, we use this to prevent self-referential links in
ROAM_REFS."
:package-version '(org-roam . "2.2.0")
:group 'org-roam
:type '(alist))
;;; Variables ;;; Variables
(defconst org-roam-db-version 18) (defconst org-roam-db-version 18)
;; TODO Rename this
(defconst org-roam--sqlite-available-p
(with-demoted-errors "Org-roam initialization: %S"
(emacsql-sqlite-ensure-binary)
t))
(defvar org-roam-db--connection (make-hash-table :test #'equal) (defvar org-roam-db--connection (make-hash-table :test #'equal)
"Database connection to Org-roam database.") "Database connection to Org-roam database.")
@@ -165,7 +145,6 @@ Performs a database upgrade when required."
(let ((init-db (not (file-exists-p org-roam-db-location)))) (let ((init-db (not (file-exists-p org-roam-db-location))))
(make-directory (file-name-directory org-roam-db-location) t) (make-directory (file-name-directory org-roam-db-location) t)
(let ((conn (funcall (org-roam-db--conn-fn) org-roam-db-location))) (let ((conn (funcall (org-roam-db--conn-fn) org-roam-db-location)))
(emacsql conn [:pragma (= foreign_keys ON)])
(when-let ((process (emacsql-process conn))) (when-let ((process (emacsql-process conn)))
(set-process-query-on-exit-flag process nil)) (set-process-query-on-exit-flag process nil))
(puthash (expand-file-name (file-name-as-directory org-roam-directory)) (puthash (expand-file-name (file-name-as-directory org-roam-directory))
@@ -264,6 +243,7 @@ The query is expected to be able to fail, in this situation, run HANDLER."
(defun org-roam-db--init (db) (defun org-roam-db--init (db)
"Initialize database DB with the correct schema and user version." "Initialize database DB with the correct schema and user version."
(emacsql db [:pragma (= foreign_keys ON)])
(emacsql-with-transaction db (emacsql-with-transaction db
(pcase-dolist (`(,table ,schema) org-roam-db--table-schemata) (pcase-dolist (`(,table ,schema) org-roam-db--table-schemata)
(emacsql db [:create-table $i1 $S2] table schema)) (emacsql db [:create-table $i1 $S2] table schema))
@@ -379,12 +359,15 @@ If UPDATE-P is non-nil, first remove the file in the database."
;; Links correctly recognized by Org Mode ;; Links correctly recognized by Org Mode
((eq type 'link) ((eq type 'link)
(setq link element)) (setq link element))
;; Prevent self-referencing links in ROAM_REFS
((and (eq type 'node-property)
(org-roam-string-equal (org-element-property :key element) "ROAM_REFS"))
nil)
;; Links in property drawers and lines starting with #+. Recall that, as for Org Mode v9.4.4, the ;; Links in property drawers and lines starting with #+. Recall that, as for Org Mode v9.4.4, the
;; org-element-type of links within properties drawers is "node-property" and for lines starting with ;; org-element-type of links within properties drawers is "node-property" and for lines starting with
;; #+ is "keyword". ;; #+ is "keyword".
((and (member type org-roam-db-extra-links-elements) ((and (or (eq type 'node-property)
(not (member-ignore-case (org-element-property :key element) (eq type 'keyword))
(cdr (assoc type org-roam-db-extra-links-exclude-keys))))
(setq bounds (org-in-regexp org-link-any-re)) (setq bounds (org-in-regexp org-link-any-re))
(setq link (buffer-substring-no-properties (setq link (buffer-substring-no-properties
(car bounds) (car bounds)
@@ -499,24 +482,9 @@ INFO is the org-element parsed buffer."
(let (rows) (let (rows)
(dolist (ref refs) (dolist (ref refs)
(save-match-data (save-match-data
(cond (;; @citeKey (cond ((string-prefix-p "@" ref)
(string-prefix-p "@" ref)
(push (vector node-id (substring ref 1) "cite") rows)) (push (vector node-id (substring ref 1) "cite") rows))
(;; [cite:@citeKey] ((string-match org-link-plain-re ref)
(string-prefix-p "[cite:" ref)
(condition-case nil
(let ((cite-obj (org-cite-parse-objects ref)))
(org-element-map cite-obj 'citation-reference
(lambda (cite)
(let ((key (org-element-property :key cite)))
(push (vector node-id key "cite") rows)))))
(error
(lwarn '(org-roam) :warning
"%s:%s\tInvalid cite %s, skipping..." (buffer-file-name) (point) ref))))
(;; https://google.com, cite:citeKey
;; Note: we use string-match here because it matches any link: e.g. [[cite:abc][abc]]
;; But this form of matching is loose, and can accept invalid links e.g. [[cite:abc]
(string-match org-link-plain-re ref)
(let ((link-type (match-string 1 ref)) (let ((link-type (match-string 1 ref))
(path (match-string 2 ref))) (path (match-string 2 ref)))
(if (and (boundp 'org-ref-cite-types) (if (and (boundp 'org-ref-cite-types)

View File

@@ -1,117 +0,0 @@
;;; org-roam-id.el --- ID-related utilities for Org-roam -*- lexical-binding: t; -*-
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com>
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (magit-section "3.0.0"))
;; This file is NOT part of GNU Emacs.
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;;
;; This module provides ID-related facilities using the Org-roam database.
;;
;;; Code:
(require 'org-id)
(defun org-roam-id-at-point ()
"Return the ID at point, if any.
Recursively traverses up the headline tree to find the
first encapsulating ID."
(org-with-wide-buffer
(org-back-to-heading-or-point-min t)
(while (and (not (org-roam-db-node-p))
(not (bobp)))
(org-roam-up-heading-or-point-min))
(when (org-roam-db-node-p)
(org-id-get))))
(defun org-roam-id-find (id &optional markerp)
"Return the location of the entry with the id ID using the Org-roam db.
The return value is a cons cell (file-name . position), or nil
if there is no entry with that ID.
With optional argument MARKERP, return the position as a new marker."
(cond
((symbolp id) (setq id (symbol-name id)))
((numberp id) (setq id (number-to-string id))))
(let ((node (org-roam-populate (org-roam-node-create :id id))))
(when-let ((file (org-roam-node-file node)))
(if markerp
(unwind-protect
(let ((buffer (or (find-buffer-visiting file)
(find-file-noselect file))))
(with-current-buffer buffer
(move-marker (make-marker) (org-roam-node-point node) buffer))))
(cons (org-roam-node-file node)
(org-roam-node-point node))))))
(defun org-roam-id-open (id _)
"Go to the entry with id ID.
Like `org-id-open', but additionally uses the Org-roam database."
(org-mark-ring-push)
(let ((m (or (org-roam-id-find id 'marker)
(org-id-find id 'marker)))
cmd)
(unless m
(error "Cannot find entry with ID \"%s\"" id))
;; Use a buffer-switching command in analogy to finding files
(setq cmd
(or
(cdr
(assq
(cdr (assq 'file org-link-frame-setup))
'((find-file . switch-to-buffer)
(find-file-other-window . switch-to-buffer-other-window)
(find-file-other-frame . switch-to-buffer-other-frame))))
'switch-to-buffer-other-window))
(if (not (equal (current-buffer) (marker-buffer m)))
(funcall cmd (marker-buffer m)))
(goto-char m)
(move-marker m nil)
(org-show-context)))
(org-link-set-parameters "id" :follow #'org-roam-id-open)
;;;###autoload
(defun org-roam-update-org-id-locations (&rest directories)
"Scan Org-roam files to update `org-id' related state.
This is like `org-id-update-id-locations', but will automatically
use the currently bound `org-directory' and `org-roam-directory'
along with DIRECTORIES (if any), where the lookup for files in
these directories will be always recursive.
Note: Org-roam doesn't have hard dependency on
`org-id-locations-file' to lookup IDs for nodes that are stored
in the database, but it still tries to properly integrates with
`org-id'. This allows the user to cross-reference IDs outside of
the current `org-roam-directory', and also link with \"id:\"
links to headings/files within the current `org-roam-directory'
that are excluded from identification in Org-roam as
`org-roam-node's, e.g. with \"ROAM_EXCLUDE\" property."
(interactive)
(cl-loop for dir in (cons org-roam-directory directories)
for org-roam-directory = dir
nconc (org-roam-list-files) into files
finally (org-id-update-id-locations files org-roam-verbose)))
(provide 'org-roam-id)
;;; org-roam-id.el ends here

View File

@@ -5,8 +5,8 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com> ;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam ;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience ;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1 ;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0")) ;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.

View File

@@ -1,12 +1,12 @@
;;; org-roam-mode.el --- Major mode for special Org-roam buffers -*- lexical-binding: t -*- ;;; org-roam-mode.el --- Major mode for special Org-roam buffers -*- lexical-binding: t -*-
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com> ;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
;; Author: Jethro Kuan <jethrokuan95@gmail.com> ;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam ;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience ;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1 ;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0")) ;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.
@@ -39,28 +39,14 @@
(defvar org-ref-buffer-hacked) (defvar org-ref-buffer-hacked)
;;; Options ;;; Options
(defcustom org-roam-mode-sections (list #'org-roam-backlinks-section (defcustom org-roam-mode-section-functions (list #'org-roam-backlinks-section
#'org-roam-reflinks-section) #'org-roam-reflinks-section)
"A list of sections for the `org-roam-mode' based buffers. "Functions that insert sections in the `org-roam-mode' based buffers.
Each section is a function that is passed the an `org-roam-node' Each function is called with one argument, which is an
for which the section will be constructed for as the first `org-roam-node' for which the buffer will be constructed for.
argument. Normally this node is `org-roam-buffer-current-node'. Normally this node is `org-roam-buffer-current-node'."
The function may also accept other optional arguments. Each item
in the list is either:
1. A function, which is called only with the `org-roam-node' as the argument
2. A list, containing the function and the optional arguments.
For example, one can add
(org-roam-backlinks-section :unique t)
to the list to pass :unique t to the section-rendering function."
:group 'org-roam :group 'org-roam
:type `(repeat (choice (symbol :tag "Function") :type 'hook)
(list :tag "Function with arguments"
(symbol :tag "Function")
(repeat :tag "Arguments" :inline t (sexp :tag "Arg"))))))
(defcustom org-roam-buffer-postrender-functions (list) (defcustom org-roam-buffer-postrender-functions (list)
"Functions to run after the Org-roam buffer is rendered. "Functions to run after the Org-roam buffer is rendered.
@@ -182,7 +168,7 @@ This mode is used by special Org-roam buffers, such as persistent
`org-roam-buffer' and dedicated Org-roam buffers `org-roam-buffer' and dedicated Org-roam buffers
\(`org-roam-buffer-display-dedicated'), which render the \(`org-roam-buffer-display-dedicated'), which render the
information in a section-like manner (see information in a section-like manner (see
`org-roam-mode-sections'), with which the user can `org-roam-mode-section-functions'), with which the user can
interact with." interact with."
:group 'org-roam :group 'org-roam
(face-remap-add-relative 'header-line 'org-roam-header-line)) (face-remap-add-relative 'header-line 'org-roam-header-line))
@@ -242,14 +228,7 @@ buffer."
(org-roam-node-title org-roam-buffer-current-node)) (org-roam-node-title org-roam-buffer-current-node))
(magit-insert-section (org-roam) (magit-insert-section (org-roam)
(magit-insert-heading) (magit-insert-heading)
(dolist (section org-roam-mode-sections) (run-hook-with-args 'org-roam-mode-section-functions org-roam-buffer-current-node))
(pcase section
((pred functionp)
(funcall section org-roam-buffer-current-node))
(`(,fn . ,args)
(apply fn (cons org-roam-buffer-current-node args)))
(_
(user-error "Invalid `org-roam-mode-sections' specification")))))
(run-hooks 'org-roam-buffer-postrender-functions) (run-hooks 'org-roam-buffer-postrender-functions)
(goto-char 0))) (goto-char 0)))
@@ -310,7 +289,7 @@ To toggle its display use `org-roam-buffer-toggle' command.")
(pcase (org-roam-buffer--visibility) (pcase (org-roam-buffer--visibility)
('visible ('visible
(progn (progn
(quit-window nil (get-buffer-window org-roam-buffer)) (delete-window (get-buffer-window org-roam-buffer))
(remove-hook 'post-command-hook #'org-roam-buffer--redisplay-h))) (remove-hook 'post-command-hook #'org-roam-buffer--redisplay-h)))
((or 'exists 'none) ((or 'exists 'none)
(progn (progn
@@ -480,23 +459,14 @@ headline, up to the next headline."
(org-roam-populate (org-roam-backlink-target-node backlink))) (org-roam-populate (org-roam-backlink-target-node backlink)))
backlink) backlink)
(cl-defun org-roam-backlinks-get (node &key unique) (defun org-roam-backlinks-get (node)
"Return the backlinks for NODE. "Return the backlinks for NODE."
(let ((backlinks (org-roam-db-query
When UNIQUE is nil, show all positions where references are found. [:select [source dest pos properties]
When UNIQUE is t, limit to unique sources." :from links
(let* ((sql (if unique :where (= dest $s1)
[:select :distinct [source dest pos properties] :and (= type "id")]
:from links (org-roam-node-id node))))
:where (= dest $s1)
:and (= type "id")
:group :by source
:having (funcall min pos)]
[:select [source dest pos properties]
:from links
:where (= dest $s1)
:and (= type "id")]))
(backlinks (org-roam-db-query sql (org-roam-node-id node))))
(cl-loop for backlink in backlinks (cl-loop for backlink in backlinks
collect (pcase-let ((`(,source-id ,dest-id ,pos ,properties) backlink)) collect (pcase-let ((`(,source-id ,dest-id ,pos ,properties) backlink))
(org-roam-populate (org-roam-populate
@@ -512,12 +482,9 @@ Sorts by title."
(string< (org-roam-node-title (org-roam-backlink-source-node a)) (string< (org-roam-node-title (org-roam-backlink-source-node a))
(org-roam-node-title (org-roam-backlink-source-node b)))) (org-roam-node-title (org-roam-backlink-source-node b))))
(cl-defun org-roam-backlinks-section (node &key (unique nil)) (defun org-roam-backlinks-section (node)
"The backlinks section for NODE. "The backlinks section for NODE."
(when-let ((backlinks (seq-sort #'org-roam-backlinks-sort (org-roam-backlinks-get node))))
When UNIQUE is nil, show all positions where references are found.
When UNIQUE is t, limit to unique sources."
(when-let ((backlinks (seq-sort #'org-roam-backlinks-sort (org-roam-backlinks-get node :unique unique))))
(magit-insert-section (org-roam-backlinks) (magit-insert-section (org-roam-backlinks)
(magit-insert-heading "Backlinks:") (magit-insert-heading "Backlinks:")
(dolist (backlink backlinks) (dolist (backlink backlinks)
@@ -676,7 +643,7 @@ References from FILE are excluded."
col (string-to-number (match-string 3 line)) col (string-to-number (match-string 3 line))
match (match-string 4 line)) match (match-string 4 line))
(when (and match (when (and match
(not (file-equal-p (org-roam-node-file node) f)) (not (f-equal-p (org-roam-node-file node) f))
(member (downcase match) (mapcar #'downcase titles))) (member (downcase match) (mapcar #'downcase titles)))
(magit-insert-section section (org-roam-grep-section) (magit-insert-section section (org-roam-grep-section)
(oset section file f) (oset section file f)

View File

@@ -5,7 +5,7 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com> ;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam ;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience ;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1 ;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (magit-section "3.0.0")) ;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (magit-section "3.0.0"))
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.
@@ -36,7 +36,8 @@
;;; Options ;;; Options
;;;; Completing-read ;;;; Completing-read
(defcustom org-roam-node-display-template "${title}" (defcustom org-roam-node-display-template
(concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag))
"Configures display formatting for Org-roam node. "Configures display formatting for Org-roam node.
Patterns of form \"${field-name:length}\" are interpolated based Patterns of form \"${field-name:length}\" are interpolated based
on the current node. on the current node.
@@ -131,8 +132,7 @@ It takes a single argument REF, which is a propertized string."
:type 'boolean) :type 'boolean)
(defcustom org-roam-extract-new-file-path "%<%Y%m%d%H%M%S>-${slug}.org" (defcustom org-roam-extract-new-file-path "%<%Y%m%d%H%M%S>-${slug}.org"
"The file path template to use when a node is extracted to its own file. "The file path to use when a node is extracted to its own file."
This path is relative to `org-roam-directory'."
:group 'org-roam :group 'org-roam
:type 'string) :type 'string)
@@ -175,7 +175,6 @@ This path is relative to `org-roam-directory'."
776 ; U+0308 COMBINING DIAERESIS 776 ; U+0308 COMBINING DIAERESIS
777 ; U+0309 COMBINING HOOK ABOVE 777 ; U+0309 COMBINING HOOK ABOVE
778 ; U+030A COMBINING RING ABOVE 778 ; U+030A COMBINING RING ABOVE
779 ; U+030B COMBINING DOUBLE ACUTE ACCENT
780 ; U+030C COMBINING CARON 780 ; U+030C COMBINING CARON
795 ; U+031B COMBINING HORN 795 ; U+031B COMBINING HORN
803 ; U+0323 COMBINING DOT BELOW 803 ; U+0323 COMBINING DOT BELOW
@@ -187,12 +186,14 @@ This path is relative to `org-roam-directory'."
816 ; U+0330 COMBINING TILDE BELOW 816 ; U+0330 COMBINING TILDE BELOW
817 ; U+0331 COMBINING MACRON BELOW 817 ; U+0331 COMBINING MACRON BELOW
))) )))
(cl-flet* ((nonspacing-mark-p (char) (memq char slug-trim-chars)) (cl-flet* ((nonspacing-mark-p (char)
(strip-nonspacing-marks (s) (string-glyph-compose (memq char slug-trim-chars))
(apply #'string (strip-nonspacing-marks (s)
(seq-remove #'nonspacing-mark-p (string-glyph-compose
(string-glyph-decompose s))))) (apply #'string (seq-remove #'nonspacing-mark-p
(cl-replace (title pair) (replace-regexp-in-string (car pair) (cdr pair) title))) (string-glyph-decompose s)))))
(cl-replace (title pair)
(replace-regexp-in-string (car pair) (cdr pair) title)))
(let* ((pairs `(("[^[:alnum:][:digit:]]" . "_") ;; convert anything not alphanumeric (let* ((pairs `(("[^[:alnum:][:digit:]]" . "_") ;; convert anything not alphanumeric
("__*" . "_") ;; remove sequential underscores ("__*" . "_") ;; remove sequential underscores
("^_" . "") ;; remove starting underscore ("^_" . "") ;; remove starting underscore
@@ -425,41 +426,19 @@ GROUP BY id")))
all-titles))))) all-titles)))))
;;;; Finders ;;;; Finders
(defun org-roam-node-marker (node) (defun org-roam-node-find-noselect (node &optional force)
"Get the marker for NODE." "Navigate to the point for NODE, and return the buffer.
(unwind-protect If NODE is already visited, this won't automatically move the
(let* ((file (org-roam-node-file node)) point to the beginning of the NODE, unless FORCE is non-nil."
(buffer (or (find-buffer-visiting file) (unless (org-roam-node-file node)
(find-file-noselect file)))) (user-error "Node does not have corresponding file"))
(with-current-buffer buffer (let ((buf (find-file-noselect (org-roam-node-file node))))
(move-marker (make-marker) (org-roam-node-point node) buffer))))) (with-current-buffer buf
(when (or force
(defun org-roam-node-open (node &optional cmd force) (not (equal (org-roam-node-id node)
"Go to the node NODE. (org-roam-id-at-point))))
CMD is the command used to display the buffer. If not provided, (goto-char (org-roam-node-point node))))
`org-link-frame-setup' is respected. Assumes that the node is buf))
fully populated, with file and point. If NODE is already visited,
this won't automatically move the point to the beginning of the
NODE, unless FORCE is non-nil."
(interactive (list (org-roam-node-at-point) current-prefix-arg))
(org-mark-ring-push)
(let ((m (org-roam-node-marker node))
(cmd (or cmd
(cdr
(assq
(cdr (assq 'file org-link-frame-setup))
'((find-file . switch-to-buffer)
(find-file-other-window . switch-to-buffer-other-window)
(find-file-other-frame . switch-to-buffer-other-frame))))
'switch-to-buffer-other-window)))
(if (not (equal (current-buffer) (marker-buffer m)))
(funcall cmd (marker-buffer m)))
(when (or force
(not (equal (org-roam-node-id node)
(org-roam-id-at-point))))
(goto-char m))
(move-marker m nil))
(org-show-context))
(defun org-roam-node-visit (node &optional other-window force) (defun org-roam-node-visit (node &optional other-window force)
"From the current buffer, visit NODE. Return the visited buffer. "From the current buffer, visit NODE. Return the visited buffer.
@@ -471,10 +450,13 @@ If NODE is already visited, this won't automatically move the
point to the beginning of the NODE, unless FORCE is non-nil. In point to the beginning of the NODE, unless FORCE is non-nil. In
interactive calls FORCE always set to t." interactive calls FORCE always set to t."
(interactive (list (org-roam-node-at-point t) current-prefix-arg t)) (interactive (list (org-roam-node-at-point t) current-prefix-arg t))
(org-roam-node-open node (if other-window (let ((buf (org-roam-node-find-noselect node force))
(display-buffer-fn (if other-window
#'switch-to-buffer-other-window #'switch-to-buffer-other-window
#'pop-to-buffer-same-window) #'pop-to-buffer-same-window)))
force)) (funcall display-buffer-fn buf)
(when (org-invisible-p) (org-show-context))
buf))
;;;###autoload ;;;###autoload
(cl-defun org-roam-node-find (&optional other-window initial-input filter-fn &key templates) (cl-defun org-roam-node-find (&optional other-window initial-input filter-fn &key templates)
@@ -495,16 +477,16 @@ The TEMPLATES, if provided, override the list of capture templates (see
:props '(:finalize find-file))))) :props '(:finalize find-file)))))
;;;###autoload ;;;###autoload
(defun org-roam-node-random (&optional other-window filter-fn) (defun org-roam-node-random (&optional other-window)
"Find and open a random Org-roam node. "Find and open a random Org-roam node.
With prefix argument OTHER-WINDOW, visit the node in another With prefix argument OTHER-WINDOW, visit the node in another
window instead. window instead."
FILTER-FN is a function to filter out nodes: it takes an `org-roam-node',
and when nil is returned the node will be filtered out."
(interactive current-prefix-arg) (interactive current-prefix-arg)
(org-roam-node-visit (let ((random-row (seq-random-elt (org-roam-db-query [:select [id file pos] :from nodes]))))
(cdr (seq-random-elt (org-roam-node-read--completions filter-fn))) (org-roam-node-visit (org-roam-node-create :id (nth 0 random-row)
other-window)) :file (nth 1 random-row)
:point (nth 2 random-row))
other-window)))
;;;; Completing-read interface ;;;; Completing-read interface
(defun org-roam-node-read (&optional initial-input filter-fn sort-fn require-match prompt) (defun org-roam-node-read (&optional initial-input filter-fn sort-fn require-match prompt)
@@ -516,7 +498,17 @@ SORT-FN is a function to sort nodes. See `org-roam-node-read-sort-by-file-mtime'
for an example sort function. for an example sort function.
If REQUIRE-MATCH, the minibuffer prompt will require a match. If REQUIRE-MATCH, the minibuffer prompt will require a match.
PROMPT is a string to show at the beginning of the mini-buffer, defaulting to \"Node: \"" PROMPT is a string to show at the beginning of the mini-buffer, defaulting to \"Node: \""
(let* ((nodes (org-roam-node-read--completions filter-fn sort-fn)) (let* ((nodes (org-roam-node-read--completions))
(nodes (if filter-fn
(cl-remove-if-not
(lambda (n) (funcall filter-fn (cdr n)))
nodes)
nodes))
(sort-fn (or sort-fn
(when org-roam-node-default-sort
(intern (concat "org-roam-node-read-sort-by-"
(symbol-name org-roam-node-default-sort))))))
(_ (when sort-fn (setq nodes (seq-sort sort-fn nodes))))
(prompt (or prompt "Node: ")) (prompt (or prompt "Node: "))
(node (completing-read (node (completing-read
prompt prompt
@@ -537,31 +529,15 @@ PROMPT is a string to show at the beginning of the mini-buffer, defaulting to \"
(or (cdr (assoc node nodes)) (or (cdr (assoc node nodes))
(org-roam-node-create :title node)))) (org-roam-node-create :title node))))
(defun org-roam-node-read--completions (&optional filter-fn sort-fn) (defun org-roam-node-read--completions ()
"Return an alist for node completion. "Return an alist for node completion.
The car is the displayed title or alias for the node, and the cdr The car is the displayed title or alias for the node, and the cdr
is the `org-roam-node'. is the `org-roam-node'.
FILTER-FN is a function to filter out nodes: it takes an `org-roam-node',
and when nil is returned the node will be filtered out.
SORT-FN is a function to sort nodes. See `org-roam-node-read-sort-by-file-mtime'
for an example sort function.
The displayed title is formatted according to `org-roam-node-display-template'." The displayed title is formatted according to `org-roam-node-display-template'."
(let* ((template (org-roam-node--process-display-format org-roam-node-display-template)) (let ((template (org-roam-node--process-display-format org-roam-node-display-template))
(nodes (org-roam-node-list)) (nodes (org-roam-node-list)))
(nodes (mapcar (lambda (node) (mapcar (lambda (node)
(org-roam-node-read--to-candidate node template)) nodes)) (org-roam-node-read--to-candidate node template)) nodes)))
(nodes (if filter-fn
(cl-remove-if-not
(lambda (n) (funcall filter-fn (cdr n)))
nodes)
nodes))
(sort-fn (or sort-fn
(when org-roam-node-default-sort
(intern (concat "org-roam-node-read-sort-by-"
(symbol-name org-roam-node-default-sort))))))
(nodes (if sort-fn (seq-sort sort-fn nodes)
nodes)))
nodes))
(defun org-roam-node-read--to-candidate (node template) (defun org-roam-node-read--to-candidate (node template)
"Return a minibuffer completion candidate given NODE. "Return a minibuffer completion candidate given NODE.
@@ -569,8 +545,7 @@ TEMPLATE is the processed template used to format the entry."
(let ((candidate-main (org-roam-node--format-entry (let ((candidate-main (org-roam-node--format-entry
template template
node node
(1- (if (bufferp (current-buffer)) (1- (frame-width)))))
(window-width) (frame-width))))))
(cons (propertize candidate-main 'node node) node))) (cons (propertize candidate-main 'node node) node)))
(defun org-roam-node--format-entry (template node &optional width) (defun org-roam-node--format-entry (template node &optional width)
@@ -688,13 +663,9 @@ The INFO, if provided, is passed to the underlying `org-roam-capture-'."
(delete-region beg end) (delete-region beg end)
(set-marker beg nil) (set-marker beg nil)
(set-marker end nil)) (set-marker end nil))
(let ((id (org-roam-node-id node))) (insert (org-link-make-string
(insert (org-link-make-string (concat "id:" (org-roam-node-id node))
(concat "id:" id) description)))
description))
(run-hook-with-args 'org-roam-post-node-insert-hook
id
description)))
(org-roam-capture- (org-roam-capture-
:node node :node node
:info info :info info
@@ -702,10 +673,31 @@ The INFO, if provided, is passed to the underlying `org-roam-capture-'."
:props (append :props (append
(when (and beg end) (when (and beg end)
(list :region (cons beg end))) (list :region (cons beg end)))
(list :link-description description (list :insert-at (point-marker)
:link-description description
:finalize 'insert-link)))))) :finalize 'insert-link))))))
(deactivate-mark))) (deactivate-mark)))
(add-hook 'org-roam-find-file-hook #'org-roam-open-id-with-org-roam-db-h)
(defun org-roam-open-id-with-org-roam-db-h ()
"Try to open \"id:\" links at point by querying them to the database."
(add-hook 'org-open-at-point-functions #'org-roam-open-id-at-point nil t))
(defun org-roam-open-id-at-point ()
"Navigate to \"id:\" link at point using the Org-roam database."
(when (org-in-regexp org-link-any-re)
(let ((link (match-string 2))
id)
(when (string-prefix-p "id:" link)
(setq id (substring-no-properties link 3))
(let ((node (org-roam-populate (org-roam-node-create :id id))))
(cond
((org-roam-node-file node)
(org-mark-ring-push)
(org-roam-node-visit node nil 'force)
t)
(t nil)))))))
;;;;; [roam:] link ;;;;; [roam:] link
(org-link-set-parameters "roam" :follow #'org-roam-link-follow-link) (org-link-set-parameters "roam" :follow #'org-roam-link-follow-link)
(defun org-roam-link-follow-link (title-or-alias) (defun org-roam-link-follow-link (title-or-alias)
@@ -819,8 +811,7 @@ Any tags declared on #+FILETAGS: are transferred to tags on the new top heading.
Any top level properties drawers are incorporated into the new heading." Any top level properties drawers are incorporated into the new heading."
(interactive) (interactive)
(org-with-point-at 1 (org-with-point-at 1
(org-map-region #'org-do-demote (org-map-entries 'org-do-demote)
(point-min) (point-max))
(insert "* " (insert "* "
(org-roam--get-keyword "title") (org-roam--get-keyword "title")
"\n") "\n")
@@ -835,11 +826,9 @@ Converts a file containing a headline node at the top to a file
node." node."
(interactive) (interactive)
(org-with-point-at 1 (org-with-point-at 1
(org-map-region (org-map-entries (lambda ()
(lambda () (when (> (org-outline-level) 1)
(when (> (org-outline-level) 1) (org-do-promote))))
(org-do-promote)))
(point-min) (point-max))
(let ((title (nth 4 (org-heading-components))) (let ((title (nth 4 (org-heading-components)))
(tags (nth 5 (org-heading-components)))) (tags (nth 5 (org-heading-components))))
(beginning-of-line) (beginning-of-line)
@@ -931,11 +920,8 @@ If region is active, then use it instead of the node at point."
(t (let ((r (read-from-minibuffer (format "%s: " key) default-val))) (t (let ((r (read-from-minibuffer (format "%s: " key) default-val)))
(plist-put template-info ksym r) (plist-put template-info ksym r)
r))))))) r)))))))
(file-path (file-path (read-file-name "Extract node to: "
(expand-file-name (file-name-as-directory org-roam-directory) template nil template)))
(read-file-name "Extract node to: "
(file-name-as-directory org-roam-directory) template nil template)
org-roam-directory)))
(when (file-exists-p file-path) (when (file-exists-p file-path)
(user-error "%s exists. Aborting" file-path)) (user-error "%s exists. Aborting" file-path))
(org-cut-subtree) (org-cut-subtree)
@@ -945,6 +931,42 @@ If region is active, then use it instead of the node at point."
(org-roam-promote-entire-buffer) (org-roam-promote-entire-buffer)
(save-buffer))))) (save-buffer)))))
;;; IDs
;;;; Getters
(defun org-roam-id-at-point ()
"Return the ID at point, if any.
Recursively traverses up the headline tree to find the
first encapsulating ID."
(org-with-wide-buffer
(org-back-to-heading-or-point-min t)
(while (and (not (org-roam-db-node-p))
(not (bobp)))
(org-roam-up-heading-or-point-min))
(when (org-roam-db-node-p)
(org-id-get))))
;;;###autoload
(defun org-roam-update-org-id-locations (&rest directories)
"Scan Org-roam files to update `org-id' related state.
This is like `org-id-update-id-locations', but will automatically
use the currently bound `org-directory' and `org-roam-directory'
along with DIRECTORIES (if any), where the lookup for files in
these directories will be always recursive.
Note: Org-roam doesn't have hard dependency on
`org-id-locations-file' to lookup IDs for nodes that are stored
in the database, but it still tries to properly integrates with
`org-id'. This allows the user to cross-reference IDs outside of
the current `org-roam-directory', and also link with \"id:\"
links to headings/files within the current `org-roam-directory'
that are excluded from identification in Org-roam as
`org-roam-node's, e.g. with \"ROAM_EXCLUDE\" property."
(interactive)
(cl-loop for dir in (cons org-roam-directory directories)
for org-roam-directory = dir
nconc (org-roam-list-files) into files
finally (org-id-update-id-locations files org-roam-verbose)))
;;; Refs ;;; Refs
;;;; Completing-read interface ;;;; Completing-read interface
(defun org-roam-ref-read (&optional initial-input filter-fn) (defun org-roam-ref-read (&optional initial-input filter-fn)

View File

@@ -1,11 +1,11 @@
;;; org-roam-utils.el --- Utilities for Org-roam -*- lexical-binding: t; -*- ;;; org-roam-utils.el --- Utilities for Org-roam -*- lexical-binding: t; -*-
;; Copyright © 2020-2022 Jethro Kuan <jethrokuan95@gmail.com> ;; Copyright © 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>
;; Author: Jethro Kuan <jethrokuan95@gmail.com> ;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam ;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience ;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1 ;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4")) ;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4"))
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.
@@ -52,16 +52,6 @@
(org-roam-replace-string "\\" "\\\\") (org-roam-replace-string "\\" "\\\\")
(org-roam-replace-string "\"" "\\\""))) (org-roam-replace-string "\"" "\\\"")))
(defun org-roam-word-wrap (len s)
"If S is longer than LEN, wrap the words with newlines."
(declare (side-effect-free t))
(save-match-data
(with-temp-buffer
(insert s)
(let ((fill-column len))
(fill-region (point-min) (point-max)))
(buffer-substring (point-min) (point-max)))))
(defun org-roam-string-equal (s1 s2) (defun org-roam-string-equal (s1 s2)
"Return t if S1 and S2 are equal. "Return t if S1 and S2 are equal.
Like `string-equal', but case-insensitive." Like `string-equal', but case-insensitive."
@@ -69,15 +59,6 @@ Like `string-equal', but case-insensitive."
(or (string-equal s1 s2) (or (string-equal s1 s2)
(string-equal (downcase s1) (downcase s2))))) (string-equal (downcase s1) (downcase s2)))))
(defun org-roam-whitespace-content (s)
"Return the whitespace content at the end of S."
(with-temp-buffer
(let ((c 0))
(insert s)
(skip-chars-backward " \t\n")
(buffer-substring-no-properties
(point) (point-max)))))
(defun org-roam-strip-comments (s) (defun org-roam-strip-comments (s)
"Strip Org comments from string S." "Strip Org comments from string S."
(with-temp-buffer (with-temp-buffer
@@ -118,12 +99,6 @@ SPEC is a list, as per `dolist'."
`(dolist ,spec ,@body))) `(dolist ,spec ,@body)))
;;; File utilities ;;; File utilities
(defun org-roam-descendant-of-p (a b)
"Return t if A is descendant of B."
(unless (equal (file-truename a) (file-truename b))
(string-prefix-p (replace-regexp-in-string "^\\([A-Za-z]\\):" 'downcase (expand-file-name b) t t)
(replace-regexp-in-string "^\\([A-Za-z]\\):" 'downcase (expand-file-name a) t t))))
(defmacro org-roam-with-file (file keep-buf-p &rest body) (defmacro org-roam-with-file (file keep-buf-p &rest body)
"Execute BODY within FILE. "Execute BODY within FILE.
If FILE is nil, execute BODY in the current buffer. If FILE is nil, execute BODY in the current buffer.
@@ -144,8 +119,7 @@ Kills the buffer if KEEP-BUF-P is nil, and FILE is not yet visited."
(delay-mode-hooks (delay-mode-hooks
(let ((org-inhibit-startup t) (let ((org-inhibit-startup t)
(org-agenda-files nil)) (org-agenda-files nil))
(org-mode) (org-mode))))
(hack-local-variables))))
(setq res (progn ,@body)) (setq res (progn ,@body))
(unless (and new-buf (not ,keep-buf-p)) (unless (and new-buf (not ,keep-buf-p))
(save-buffer))) (save-buffer)))

View File

@@ -5,8 +5,8 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com> ;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam ;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience ;; Keywords: org-mode, roam, convenience
;; Version: 2.2.1 ;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0")) ;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "3.0.0"))
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.
@@ -71,6 +71,7 @@
;; majority of them can be found at https://github.com/org-roam and MELPA. ;; majority of them can be found at https://github.com/org-roam and MELPA.
;; ;;
;;; Code: ;;; Code:
(require 'f)
(require 'dash) (require 'dash)
(require 'rx) (require 'rx)
@@ -122,12 +123,6 @@ All Org files, at any level of nesting, are considered part of the Org-roam."
:group 'org-roam :group 'org-roam
:type 'hook) :type 'hook)
(defcustom org-roam-post-node-insert-hook nil
"Hook run when an Org-roam node is inserted as an Org link.
Each function takes two arguments: the id of the node, and the link description."
:group 'org-roam
:type 'hook)
(defcustom org-roam-file-extensions '("org") (defcustom org-roam-file-extensions '("org")
"List of file extensions to be included by Org-Roam. "List of file extensions to be included by Org-Roam.
While a file extension different from \".org\" may be used, the While a file extension different from \".org\" may be used, the
@@ -200,7 +195,7 @@ FILE is an Org-roam file if:
(member ext org-roam-file-extensions) (member ext org-roam-file-extensions)
(not (and org-roam-file-exclude-regexp (not (and org-roam-file-exclude-regexp
(string-match-p org-roam-file-exclude-regexp path))) (string-match-p org-roam-file-exclude-regexp path)))
(org-roam-descendant-of-p path (expand-file-name org-roam-directory)))))) (f-descendant-of-p path (expand-file-name org-roam-directory))))))
(defun org-roam-list-files () (defun org-roam-list-files ()
"Return a list of all Org-roam files under `org-roam-directory'. "Return a list of all Org-roam files under `org-roam-directory'.
@@ -265,8 +260,7 @@ If no files are found, an empty list is returned."
(shell-command-to-string it) (shell-command-to-string it)
(ansi-color-filter-apply it) (ansi-color-filter-apply it)
(split-string it "\n") (split-string it "\n")
(seq-filter (lambda (s) (seq-filter #'s-present? it)))
(not (or (null s) (string= "" s)))) it)))
(defun org-roam--list-files-search-globs (exts) (defun org-roam--list-files-search-globs (exts)
"Given EXTS, return a list of search globs. "Given EXTS, return a list of search globs.
@@ -285,8 +279,8 @@ E.g. (\".org\") => (\"*.org\" \"*.org.gpg\")"
(defun org-roam--list-files-fd (executable dir) (defun org-roam--list-files-fd (executable dir)
"Return all Org-roam files under DIR, using \"fd\", provided as EXECUTABLE." "Return all Org-roam files under DIR, using \"fd\", provided as EXECUTABLE."
(let* ((globs (org-roam--list-files-search-globs org-roam-file-extensions)) (let* ((globs (org-roam--list-files-search-globs org-roam-file-extensions))
(extensions (string-join (mapcar (lambda (glob) (concat "-e " (substring glob 2 -1))) globs) " ")) (extensions (string-join (mapcar (lambda (glob) (substring glob 2 -1)) globs) " -e "))
(command (string-join `(,executable "-L" "--type file" ,extensions "." ,dir) " "))) (command (string-join `(,executable "-L" ,dir "--type file" ,extensions) " ")))
(org-roam--shell-command-files command))) (org-roam--shell-command-files command)))
(defalias 'org-roam--list-files-fdfind #'org-roam--list-files-fd) (defalias 'org-roam--list-files-fdfind #'org-roam--list-files-fd)
@@ -319,7 +313,6 @@ E.g. (\".org\") => (\"*.org\" \"*.org.gpg\")"
(require 'org-roam-utils) (require 'org-roam-utils)
(require 'org-roam-db) (require 'org-roam-db)
(require 'org-roam-node) (require 'org-roam-node)
(require 'org-roam-id)
(require 'org-roam-capture) (require 'org-roam-capture)
(require 'org-roam-mode) (require 'org-roam-mode)
(require 'org-roam-migrate)) (require 'org-roam-migrate))

View File

@@ -1,51 +0,0 @@
;;; test-org-roam-capture.el --- Tests for Org-roam -*- lexical-binding: t; -*-
;; Copyright (C) 2020 Jethro Kuan
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; Package-Requires: ((buttercup))
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
(require 'buttercup)
(require 'org-roam)
(describe "org-roam-capture--fill-template"
(it "fills template without newline"
(expect
(org-roam-capture--fill-template "foo")
:to-equal "foo"))
(it "fills template ensuring newline"
(expect
(org-roam-capture--fill-template "foo" 'ensure-newline)
:to-equal "foo\n"))
(it "fills template with newline"
(expect
(org-roam-capture--fill-template "foo\n")
:to-equal "foo\n"))
(it "fills template with two newlines"
(expect
(org-roam-capture--fill-template "foo\n\n")
:to-equal "foo\n\n")
(expect
(org-roam-capture--fill-template "foo\n\t\n")
:to-equal "foo\n\t\n")))
(provide 'test-org-roam-capture)

View File

@@ -1,39 +0,0 @@
;;; test-org-roam-utils.el --- Tests for Org-roam -*- lexical-binding: t; -*-
;; Copyright (C) 2020 Jethro Kuan
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; Package-Requires: ((buttercup))
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
(require 'buttercup)
(require 'org-roam)
(describe "org-roam-whitespace-content"
(it "extracts whitespace correctly"
(expect
(org-roam-whitespace-content "foo")
:to-equal "")
(expect
(org-roam-whitespace-content "foo\n")
:to-equal "\n")
(expect
(org-roam-whitespace-content "foo\n\t\n")
:to-equal "\n\t\n")))
(provide 'test-org-roam-utils)