Compare commits

...

14 Commits

Author SHA1 Message Date
Wetlize
b6a898d6d6 (feat!)capture: unify template variables
Instead of using various capture template variables, like
org-roam-dailies-capture-templates or org-roam-capture-ref-templates,
just use org-roam-capture-templates for everything.

From now on, each individual template will able to optionally specify a
more detailed context for which they're dedicated for, using :kind and
:action properties. Both of them accept either, a symbol or a list of
symbols.

If it's a list, then it can optionally start with :not symbol to
indicate inverse logic, otherwise it will act akin to memq. If it's a
symbol, then it will work akin to eq, but with support for special 'any
value, which indicates that it will work in any contexts; 'any can be
also used inside of the list based values.

Org-roam and the built-in extension will provide the following contexts:
- :action {capture,goto,any}
- :kind {normal,daily,protocol,any}
but third party extensions / users can easily extend them for their own
needs.

If :action isn't specified it will implicitly default to 'capture, while
:kind will default to 'normal contexts.

BREAKING CHANGE: org-roam-dailies-capture-templates and
org-roam-capture-ref-templates are now removed in the favor of unified
approach.
2021-08-25 00:36:17 +03:00
Jeremy Friesen
e9ae19c01c (chore): adding changelog entry (#1800)
Related to #1693 and #1681
2021-08-23 14:34:50 +08:00
Victor Deryagin
d25d477b4f (refactor): ensure dependencies are loaded for org-roam-utils.el (#1799)
If org-roam-utils.el is byte-compiled when org-macs is not loaded (`org-with-point-at` macro missing), error can appear about missing `org-with-point-at`.
2021-08-23 01:41:58 +03:00
Ilya Konovalov
04b7780ff9 fix: Do not skip invisible headings when getting node at point. (#1798) 2021-08-22 00:01:52 +08:00
Jethro Kuan
858f531d96 (feat)buffer: optimize reflinks fetch (#1795)
Use SQL join instead of iterating over each ref and running another sql query.
2021-08-21 16:18:41 +08:00
Jethro Kuan
f819720c51 v2.1.0 (#1792) 2021-08-21 02:57:40 +08:00
Wetlize
887c49c89c (docs)readme: update installation section (#1787) 2021-08-19 22:05:18 +08:00
Wetlize
d4cbb1d499 (feat): don't move the point when revisiting already visited nodes (#1788)
This is now the default behavior for `org-roam-find-noselect` and
`org-roam-node-visit`, unless FORCE parameter set to non-nil.

Co-authored-by: Duncan Burke <duncankburke@gmail.com>
2021-08-19 15:16:02 +03:00
Jethro Kuan
f29a770af3 (feat)org-roam-version: output commit hash when available (#1786)
Output the commit hash when it's available (e.g. when using straight to
install packages). This comes in handy during debugging during error
reporting.
2021-08-18 16:16:32 +08:00
Bram Schoenmakers
4a7ecfbed8 (fix): remove duplicate edges from graphs (#1768)
When a node links to the another node twice, two edges appear in the
graph. To keep the graph clean, remove all duplicate edges.
2021-08-18 15:50:57 +08:00
Jethro Kuan
df65654b2f (fix)completions: allow empty field-width (#1785)
This allows the empty field-width to be used, but using an empty
field-width will result in misalignment. This is useful for people who
use completion frameworks like Ido.
2021-08-18 14:03:16 +08:00
Wetlize
b627298171 (fix){preview,grep}-visit: always navigate to the source of the preview
Previously when the preview and buffer would be opened, it would just
display the buffer at the last visited position without performing any
repositiong.

To enforce the correct behavior, the point should be always moved after
the buffer is visited, and not before.
2021-08-18 00:39:42 +03:00
Jethro Kuan
b8a66deae9 (docs): link to org-roam-ui (#1782)
Closes #1780
2021-08-18 00:29:53 +08:00
Jethro Kuan
aafc8606bb (feat): add generalized template prefixes (#1723)
Adds org-roam-node-template-prefixes to split and prefix node properties
as a query language during completions, and allow 0-width template portions.
2021-08-17 23:40:56 +08:00
17 changed files with 502 additions and 288 deletions

View File

@@ -1,9 +1,46 @@
# Changelog
## 1.2.4 (TBD)
## TBD
### Added
### Removed
### Changed
- [#1795](https://github.com/org-roam/org-roam/pull/1795) buffer: optimized reflinks fetch
### Fixed
- [#1798](https://github.com/org-roam/org-roam/pull/1798) org-roam-node-at-point: do not skip invisible headings
## 2.1.0
### Added
- [#1693](https://github.com/org-roam/org-roam/pull/1693) added `filter-fn` and `templates` parameter to `org-roam-capture`, `org-roam-node-find`, and `org-roam-node-insert`
- [#1709](https://github.com/org-roam/org-roam/pull/1709) added ability to specify default value in org-roam capture templates
- [#1710](https://github.com/org-roam/org-roam/pull/1710) added `org-roam-extract-subtree`
- [#1720](https://github.com/org-roam/org-roam/pull/1720) added `org-roam-db-update-on-save`
- [#1758](https://github.com/org-roam/org-roam/pull/1758) added `org-roam-db-autosync-mode`, replacing `org-roam-setup` and `org-roam-teardown`
### Removed
- [#1716](https://github.com/org-roam/org-roam/pull/1716) helper function `org-roam-get-keyword` is now obsolete: prefer `org-collect-keywords`
### Changed
- [#1595](https://github.com/org-roam/org-roam/pull/1595), [#1724](https://github.com/org-roam/org-roam/pull/1724) Major refactoring and restructuring of the codebase
- [#1655](https://github.com/org-roam/org-roam/pull/1655) improved org-roam contents preview
- [#1741](https://github.com/org-roam/org-roam/pull/1741) expose `org-roam-capture-` keys in interactive commands
- [#1786](https://github.com/org-roam/org-roam/pull/1786) org-roam-version now outputs commit hash if found
- [#1788](https://github.com/org-roam/org-roam/pull/1788) the point is not moved if the node is already visited
### Fixed
- [#1608](https://github.com/org-roam/org-roam/pull/1608) migration: empty ROAM_REFS are now removed
- [#1609](https://github.com/org-roam/org-roam/pull/1609) migration: fixed file-link replacement
- [#1653](https://github.com/org-roam/org-roam/pull/1653) migration: fixed tags migration
- [#1694](https://github.com/org-roam/org-roam/pull/1694) core: nodes with no title are now skipped
- [#1637](https://github.com/org-roam/org-roam/pull/1637) core: fix org-ref multi-cite links not being split
- [#1651](https://github.com/org-roam/org-roam/pull/1651) core: fix org-roam-file-p crashing when there is no corresponding file
- [#1705](https://github.com/org-roam/org-roam/pull/1705) core: fix for add/remove of file-level tags
- [#1769](https://github.com/org-roam/org-roam/pull/1769) core: gracefully handle absence of `org-id-locations-file`
- [#1713](https://github.com/org-roam/org-roam/pull/1713) capture: check for file-existence before template insertion
- [#1725](https://github.com/org-roam/org-roam/pull/1725) db: always compute hash of encrypted file to prevent re-processing of encrypted files
## 2.0.0
### Added
- [#1396](https://github.com/org-roam/org-roam/pull/1396) add option to choose between prepending, appending, and omitting `roam_tags` in file completion
- [#1270](https://github.com/org-roam/org-roam/pull/1270) capture: create OLP if it does not exist. Removes need for OLP setup in `:head`.
- [#1353](https://github.com/org-roam/org-roam/pull/1353) support file-level property drawers
@@ -11,7 +48,7 @@
### Changed
- [#1352](https://github.com/org-roam/org-roam/pull/1352) prefer lower-case for roam_tag and roam_alias in interactive commands
- [#1513](https://github.com/org-roam/org-roam/pull/1513) replaced hardcoded "svg" with defcustom org-roam-graph-filetype
- [#1513](https://github.com/org-roam/org-roam/pull/1513) replaced hardcoded "svg" with defcustom org-roam-graph-filetype
- [#1540](https://github.com/org-roam/org-roam/pull/1540) allow `roam_tag` and `roam_alias` to be specified on multiple lines
### Fixed
@@ -28,7 +65,6 @@
- [#1403](https://github.com/org-roam/org-roam/issues/1403) fixed inconsistency between how we write and read props like alias and tags
- [#1409](https://github.com/org-roam/org-roam/issues/1398) prevent inclusion of non-org-roam files in `org-roam-dailies--list-files`
- [#1542](https://github.com/org-roam/org-roam/issues/1542) fix files not excluded when `org-roam-list-files-commands` is nil
- [#1705](https://github.com/org-roam/org-roam/pull/1705) fix for add/remove of file-level tags
## 1.2.3 (13-11-2020)

174
README.md
View File

@@ -33,38 +33,170 @@ solution for anyone already using Org-mode for their personal wiki.
## Installation
You can install `org-roam` using `package.el`:
Down below you will find basic installation instructions for how to quickly
install `org-roam` using various environments for various purposes. For more
detailed information, please read the [manual][docs].
### Using `package.el`
<details>
<summary>Toggle instuctions</summary>
You can install `org-roam` from [MELPA](https://melpa.org/) or [MELPA
Stable](https://stable.melpa.org/) using `package.el`:
```
M-x package-install RET org-roam RET
```
Here's a sample configuration with `use-package`:
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))
: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))
```
The `file-truename` function is only necessary when you use symbolic links
inside `org-roam-directory`: Org-roam does not resolve symbolic links.
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>
Org-roam requires sqlite to function. Org-roam optionally uses Graphviz for
graph-related functionality. It is recommended to install PCRE-enabled ripgrep
for better performance and extended functionality.
### Using `straight.el`
<details>
<summary>Toggle instuctions</summary>
Installation from MELPA or MELPA Stable using `straight.el`:
```emacs-lisp
(straight-use-package 'org-roam)
```
Or with `use-package`:
```emacs-lisp
(use-package org-roam
:straight t
...)
```
If you need to install the package directly from the source repository, instead
of from MELPA, the next sample shows how to do so:
```emacs-lisp
(use-package org-roam
:straight (:host github :repo "org-roam/org-roam"
:files (:defaults "extensions/*"))
...)
```
If you plan to use your own local fork for the development and contribution, the
next sample will get you there:
```emacs-lisp
(use-package org-roam
:straight (:local-repo "/path/to/org-roam-fork"
:files (:defaults "extensions/*")
:build (:not compile))
...)
```
</details>
### Using Doom Emacs
<details>
<summary>Toggle instuctions</summary>
Doom's `:lang org` module comes with support for `org-roam`, but it's not
enabled by default. To activate it pass `+roam2` flag to `org` module in your
`$DOOMDIR/init.el` (e.g. `(org +roam2)`), save the file and run `doom sync -u`
in your shell.
To provide better stability, Doom pins the package to a specific commit. If you
need to unpin it *(not recommended doing that, request Doom to bump the package
instead)* use the next in your `packages.el`:
```emacs-lisp
(unpin! org-roam)
```
If for some reasons you want to use a different recipe for `org-roam`, you can
use the next form in your `packages.el` to install the package from a recipe
repository (e.g. MELPA):
```emacs-lisp
(package! org-roam)
```
You can pass `:pin "commit hash"` to pin the package to a specific commit.
With the next sample you can install the package directly from the source
repository:
```emacs-lisp
(package! org-roam
:recipe (:host github :repo "org-roam/org-roam"
:files (:defaults "extensions/*")))
```
And if you plan to use your own local fork for the development or contribution,
the next sample will get you there:
```emacs-lisp
(package! org-roam
:recipe (:local-repo "/path/to/org-roam-fork"
:files (:defaults "extensions/*")
:build (:not compile)))
```
</details>
### Without a package manager
<details>
<summary>Toggle instructions</summary>
To install the package without using a package manager you have the next two
options:
1. Install the package by cloning it with `git` from the source repository.
2. Or install the package by downloading the latest [release
version](https://github.com/org-roam/org-roam/releases).
In both of the cases you will need to ensure that you have all the required
dependencies. These include:
- dash
- f
- s
- org (9.4 is the minimal required version!)
- emacsql
- emacsql-sqlite
- magit-section
- filenotify-recursive
After installing the package, you will need to properly setup `load-path` to the
package:
``` emacs-lisp
(add-to-list 'load-path "/path/to/org-roam/")
(add-to-list 'load-path "/path/to-org-roam/extensions/")
```
After which you should be able to resolve `(require 'org-roam)` call without any
problems.
Org-roam also comes with `.texi` files to integrate with Emacs' built-in Info
system. Read the manual to find more details for how to install them manually.
</details>
## Getting Started

View File

@@ -116,8 +116,8 @@
<div class="row">
<a
class="content footer-links"
href="https://github.com/org-roam/org-roam-server"
>org-roam-server</a
href="https://github.com/org-roam/org-roam-ui"
>org-roam-ui</a
>
</div>
</div>

View File

@@ -8,13 +8,13 @@
#+texinfo_dir_category: Emacs
#+texinfo_dir_title: Org-roam: (org-roam).
#+texinfo_dir_desc: Roam Research for Emacs.
#+subtitle: for version 2.0.0
#+subtitle: for version 2.1.0
#+options: H:4 num:3 toc:nil creator:t ':t
#+property: header-args :eval never
#+texinfo: @noindent
This manual is for Org-roam version 2.0.0.
This manual is for Org-roam version 2.1.0.
#+BEGIN_QUOTE
Copyright (C) 2020-2021 Jethro Kuan <jethrokuan95@gmail.com>

View File

@@ -31,7 +31,7 @@ General Public License for more details.
@finalout
@titlepage
@title Org-roam User Manual
@subtitle for version 2.0.0
@subtitle for version 2.1.0
@author Jethro Kuan
@page
@vskip 0pt plus 1filll
@@ -44,7 +44,7 @@ General Public License for more details.
@noindent
This manual is for Org-roam version 2.0.0.
This manual is for Org-roam version 2.1.0.
@quotation
Copyright (C) 2020-2021 Jethro Kuan <jethrokuan95@@gmail.com>

View File

@@ -7,8 +7,8 @@
;; Leo Vivier <leo.vivier+dev@gmail.com>
;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 2.0.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org-roam "2.0"))
;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org-roam "2.1"))
;; This file is NOT part of GNU Emacs.
@@ -36,6 +36,18 @@
;; One can use dailies for various purposes, e.g. journaling, fleeting notes,
;; scratch notes and whatever else you can came up with.
;;
;; To add new capture templates dedicated for dailies, specify ":kind daily" for
;; each of such template in `org-roam-capture-templates', e.g.
;;
;; (setq org-roam-capture-templates
;; '(("d" "daily" entry "* %?" :kind daily
;; :if-new (file+head "%<%Y-%m-%d>.org"
;; "#+title: %<%Y-%m-%d>\n"))))
;;
;; Note that in order for your daily files to properly integrate with the
;; calendar, each daily file should be named with a format understood by
;; `org-parse-time-string'.
;;
;;; Code:
(require 'f)
(require 'dash)
@@ -49,8 +61,9 @@
;;; Options
(defcustom org-roam-dailies-directory "daily/"
"Path to daily-notes.
This path is relative to `org-roam-directory'."
"Path to daily-notes. This path is relative to `org-roam-directory'.
Daily based capture templates will automatically start from this
path."
:group 'org-roam
:type 'string)
@@ -59,74 +72,6 @@ This path is relative to `org-roam-directory'."
:group 'org-roam
:type 'hook)
(defcustom org-roam-dailies-capture-templates
`(("d" "default" entry
"* %?"
:if-new (file+head "%<%Y-%m-%d>.org"
"#+title: %<%Y-%m-%d>\n")))
"Capture templates for daily-notes in Org-roam.
Note that for daily files to show up in the calendar, they have to be of format
\"org-time-string.org\".
See `org-roam-capture-templates' for the template documentation."
:group 'org-roam
:type '(repeat
(choice (list :tag "Multikey description"
(string :tag "Keys ")
(string :tag "Description"))
(list :tag "Template entry"
(string :tag "Keys ")
(string :tag "Description ")
(choice :tag "Capture Type " :value entry
(const :tag "Org entry" entry)
(const :tag "Plain list item" item)
(const :tag "Checkbox item" checkitem)
(const :tag "Plain text" plain)
(const :tag "Table line" table-line))
(choice :tag "Template "
(string)
(list :tag "File"
(const :format "" file)
(file :tag "Template file"))
(list :tag "Function"
(const :format "" function)
(function :tag "Template function")))
(plist :inline t
;; Give the most common options as checkboxes
:options (((const :format "%v " :if-new)
(choice :tag "Node location"
(list :tag "File"
(const :format "" file)
(string :tag " File"))
(list :tag "File & Head Content"
(const :format "" file+head)
(string :tag " File")
(string :tag " Head Content"))
(list :tag "File & Outline path"
(const :format "" file+olp)
(string :tag " File")
(list :tag "Outline path"
(repeat (string :tag "Headline"))))
(list :tag "File & Head Content & Outline path"
(const :format "" file+head+olp)
(string :tag " File")
(string :tag " Head Content")
(list :tag "Outline path"
(repeat (string :tag "Headline"))))))
((const :format "%v " :prepend) (const t))
((const :format "%v " :immediate-finish) (const t))
((const :format "%v " :jump-to-captured) (const t))
((const :format "%v " :empty-lines) (const 1))
((const :format "%v " :empty-lines-before) (const 1))
((const :format "%v " :empty-lines-after) (const 1))
((const :format "%v " :clock-in) (const t))
((const :format "%v " :clock-keep) (const t))
((const :format "%v " :clock-resume) (const t))
((const :format "%v " :time-prompt) (const t))
((const :format "%v " :tree-type) (const week))
((const :format "%v " :unnarrowed) (const t))
((const :format "%v " :table-line-pos) (string))
((const :format "%v " :kill-buffer) (const t))))))))
;;; Commands
;;;; Today
;;;###autoload
@@ -306,8 +251,8 @@ 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)))
(org-roam-capture- :goto (when goto '(4))
:node (org-roam-node-create)
:templates org-roam-dailies-capture-templates
:props (list :override-default-time time)))
:props (list :kind 'daily
:override-default-time time)))
(when goto (run-hooks 'org-roam-dailies-find-file-hook)))
(add-hook 'org-roam-capture-preface-hook #'org-roam-dailies--override-capture-time-h)
@@ -317,6 +262,12 @@ When GOTO is non-nil, go the note without creating an entry."
(when (org-roam-capture--get :override-default-time)
(org-capture-put :default-time (org-roam-capture--get :override-default-time)))))
(when (org-roam-capture--load-templates-p 'org-roam-dailies)
(push '("d" "daily" entry "* %?" :kind daily
:if-new (file+head "%<%Y-%m-%d>.org"
"#+title: %<%Y-%m-%d>\n"))
org-roam-capture-templates))
;;; Bindings
(defvar org-roam-dailies-map (make-sparse-keymap)
"Keymap for `org-roam-dailies'.")

View File

@@ -5,8 +5,8 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 2.0.0
;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.0"))
;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1"))
;; This file is NOT part of GNU Emacs.
@@ -207,7 +207,8 @@ WITH RECURSIVE
connected_component(source) AS
(SELECT dest FROM links_of WHERE source = $s1 UNION
SELECT dest FROM links_of JOIN connected_component USING(source))
SELECT source, dest, type FROM links WHERE source IN connected_component OR dest IN connected_component;"
SELECT DISTINCT source, dest, type FROM links
WHERE source IN connected_component OR dest IN connected_component;"
"
WITH RECURSIVE
links_of(source, dest) AS
@@ -224,7 +225,7 @@ WITH RECURSIVE
AND json_array_length(cc.trace) < $s2)),
nodes(source) as (SELECT DISTINCT source
FROM connected_component GROUP BY source ORDER BY min(json_array_length(trace)))
SELECT source, dest, type FROM links WHERE source IN nodes OR dest IN nodes;")))
SELECT DISTINCT source, dest, type FROM links WHERE source IN nodes OR dest IN nodes;")))
(org-roam-db-query query id distance)))
(defun org-roam-graph--dot-option (option &optional wrap-key wrap-val)

View File

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

View File

@@ -4,8 +4,8 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 2.0.0
;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.0"))
;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (org "9.4") (org-roam "2.1"))
;; This file is NOT part of GNU Emacs.
@@ -32,12 +32,21 @@
;; 1. "roam-node": This protocol simply opens the node given by the node ID
;; 2. "roam-ref": This protocol creates or opens the node with the given REF
;;
;; You can find detailed instructions on how to setup the protocol in the
;; documentation for Org-roam.
;; To add new capture templates dedicated for the protocol, specify ":kind
;; protocol" for each of such template in `org-roam-capture-templates', e.g.
;;
;; (setq org-roam-capture-templates
;; '(("r" "ref" plain "%?" :kind protocol
;; :if-new (file+head "${slug}.org"
;; "#+title: ${title}")
;; :unnarrowed t)))
;;
;; You can find a detailed instruction on how to setup the protocol in the
;; manual for Org-roam.
;;
;;; Code:
(require 'org-protocol)
(require 'ol) ;; for org-link-decode
(require 'ol) ; to use `org-link-decode'
(require 'org-roam)
;;; Options
@@ -46,73 +55,12 @@
:type 'boolean
:group 'org-roam)
(defcustom org-roam-capture-ref-templates
'(("r" "ref" plain "%?"
:if-new (file+head "${slug}.org"
"#+title: ${title}")
:unnarrowed t))
"The Org-roam templates used during a capture from the roam-ref protocol.
See `org-roam-capture-templates' for the template documentation."
:group 'org-roam
:type '(repeat
(choice (list :tag "Multikey description"
(string :tag "Keys ")
(string :tag "Description"))
(list :tag "Template entry"
(string :tag "Keys ")
(string :tag "Description ")
(choice :tag "Capture Type " :value entry
(const :tag "Org entry" entry)
(const :tag "Plain list item" item)
(const :tag "Checkbox item" checkitem)
(const :tag "Plain text" plain)
(const :tag "Table line" table-line))
(choice :tag "Template "
(string)
(list :tag "File"
(const :format "" file)
(file :tag "Template file"))
(list :tag "Function"
(const :format "" function)
(function :tag "Template function")))
(plist :inline t
;; Give the most common options as checkboxes
:options (((const :format "%v " :if-new)
(choice :tag "Node location"
(list :tag "File"
(const :format "" file)
(string :tag " File"))
(list :tag "File & Head Content"
(const :format "" file+head)
(string :tag " File")
(string :tag " Head Content"))
(list :tag "File & Outline path"
(const :format "" file+olp)
(string :tag " File")
(list :tag "Outline path"
(repeat (string :tag "Headline"))))
(list :tag "File & Head Content & Outline path"
(const :format "" file+head+olp)
(string :tag " File")
(string :tag " Head Content")
(list :tag "Outline path"
(repeat (string :tag "Headline"))))))
((const :format "%v " :prepend) (const t))
((const :format "%v " :immediate-finish) (const t))
((const :format "%v " :jump-to-captured) (const t))
((const :format "%v " :empty-lines) (const 1))
((const :format "%v " :empty-lines-before) (const 1))
((const :format "%v " :empty-lines-after) (const 1))
((const :format "%v " :clock-in) (const t))
((const :format "%v " :clock-keep) (const t))
((const :format "%v " :clock-resume) (const t))
((const :format "%v " :time-prompt) (const t))
((const :format "%v " :tree-type) (const week))
((const :format "%v " :unnarrowed) (const t))
((const :format "%v " :table-line-pos) (string))
((const :format "%v " :kill-buffer) (const t))))))))
;;; Protocols
(mapc (lambda (spec) (cl-pushnew spec org-protocol-protocol-alist :test #'equal))
'(("org-roam-ref" :protocol "roam-ref" :function org-roam-protocol-open-ref)
("org-roam-node" :protocol "roam-node" :function org-roam-protocol-open-node)))
;;; Handlers
;;;; roam-ref
(defun org-roam-protocol-open-ref (info)
"Process an org-protocol://roam-ref?ref= style url with INFO.
@@ -146,29 +94,9 @@ It opens or creates a note with the given ref.
:node (org-roam-node-create :title (plist-get info :title))
:info (list :ref (plist-get info :ref)
:body (plist-get info :body))
:templates org-roam-capture-ref-templates)
:props '(:kind protocol))
nil)
(defun org-roam-protocol-open-node (info)
"This handler simply opens the file with emacsclient.
INFO is a plist containing additional information passed by the protocol URL.
It should contain the FILE key, pointing to the path of the file to open.
Example protocol string:
org-protocol://roam-node?node=uuid"
(when-let ((node (plist-get info :node)))
(raise-frame)
(org-roam-node-visit (org-roam-populate (org-roam-node-create :id node))))
nil)
(push '("org-roam-ref" :protocol "roam-ref" :function org-roam-protocol-open-ref)
org-protocol-protocol-alist)
(push '("org-roam-node" :protocol "roam-node" :function org-roam-protocol-open-node)
org-protocol-protocol-alist)
;;; Capture implementation
(add-hook 'org-roam-capture-preface-hook #'org-roam-protocol--try-capture-to-ref-h)
(defun org-roam-protocol--try-capture-to-ref-h ()
"Try to capture to an existing node that match the ref."
@@ -186,6 +114,27 @@ org-protocol://roam-node?node=uuid"
(when-let ((ref (plist-get org-roam-capture--info :ref)))
(org-roam-ref-add ref)))
(when (org-roam-capture--load-templates-p 'org-roam-protocol)
(push '("r" "ref" plain "%?" :kind protocol
:if-new (file+head "${slug}.org"
"#+title: ${title}")
:unnarrowed t)
org-roam-capture-templates))
;;;; roam-node
(defun org-roam-protocol-open-node (info)
"This handler simply opens the file with emacsclient.
INFO is a plist containing additional information passed by the protocol URL.
It should contain the FILE key, pointing to the path of the file to open.
Example protocol string:
org-protocol://roam-node?node=uuid"
(when-let ((node (plist-get info :node)))
(raise-frame)
(org-roam-node-visit (org-roam-populate (org-roam-node-create :id node)) nil 'force))
nil)
(provide 'org-roam-protocol)

View File

@@ -5,7 +5,7 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 2.0.0
;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "2.90.1"))
;; This file is NOT part of GNU Emacs.
@@ -38,6 +38,33 @@
(defvar org-end-time-was-given)
;;; Options
(defcustom org-roam-capture-load-default-templates t
"Whether to include default Org-roam capture templates during the loading.
The value will also affect default templates provided by
Org-roam's extensions. It can be:
t
Include all the default capture templates provided by
Org-roam and its extensions.
nil
Don't include the default capture templates provided by
Org-roam and its extensions.
a list of symbols
Each symbol in the list corresponds to a `provide'd FEATURE,
for which the default capture templates will be automatically
included (if any). The list can start with a special value
`:not', in which case the logic will be inverted to
exclusion, e.g. (:not org-roam-dailies) won't include the
default templates provided by `org-roam-dailies', but will
include for other features."
:type '(choice
(const :tag "Yes" t)
(const :tag "No" nil)
(repeat :tag "List features" symbol))
:group 'org-roam)
(defcustom org-roam-capture-templates
'(("d" "default" plain "%?"
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
@@ -378,9 +405,18 @@ This variable is populated dynamically, and is only non-nil
during the Org-roam capture process.")
(defconst org-roam-capture--template-keywords (list :if-new :id :link-description :call-location
:region)
:region :kind :action)
"Keywords used in `org-roam-capture-templates' specific to Org-roam.")
(defun org-roam-capture--load-templates-p (feature)
"Return t if capture templates for FEATURE are allowed to be loaded.
See `org-roam-capture-load-default-templates' for more details."
(let ((user-value org-roam-capture-load-default-templates))
(pcase user-value
((pred consp) (org-roam--valid-option-p feature user-value))
((pred null) nil)
('t t))))
;;; Main entry point
;;;###autoload
(cl-defun org-roam-capture- (&key goto keys node info props templates)
@@ -390,11 +426,18 @@ INFO is a plist for filling up Org-roam's capture templates.
NODE is an `org-roam-node' construct containing information about the node.
PROPS is a plist containing additional Org-roam properties for each template.
TEMPLATES is a list of org-roam templates."
(let* ((props (plist-put props :call-location (point-marker)))
(let* ((props (thread-first props
(plist-put :call-location (point-marker))
(plist-put :action (or (plist-get props :action) (if goto 'goto 'capture)))
(plist-put :kind (or (plist-get props :kind) 'normal))))
(templates (org-roam-capture-get-templates
:action (plist-get props :action)
:kind (plist-get props :kind)
:templates (or templates org-roam-capture-templates)))
(org-capture-templates
(mapcar (lambda (template)
(org-roam-capture--convert-template template props))
(or templates org-roam-capture-templates)))
templates))
(org-roam-capture--node node)
(org-roam-capture--info info))
(when (and (not keys)
@@ -429,6 +472,27 @@ valid for the capture (i.e. initialization, and finalization of
the capture)."
(plist-get org-capture-plist :org-roam))
(cl-defun org-roam-capture-get-templates (&key (kind 'normal)
(action 'capture)
(templates org-roam-capture-templates))
"Return list of narrowed down capture TEMPLATES to a suitable KIND and ACTION."
(cl-loop for templ in templates
for templ-kind = (or (plist-get templ :kind) 'normal)
for templ-action = (or (plist-get templ :action) 'capture)
when (and (org-roam--valid-option-p kind templ-kind)
(org-roam--valid-option-p action templ-action))
if (org-roam-capture--dull-template-p templ) collect it
else collect templ))
(defun org-roam-capture--dull-template-p (template)
"Return prefix key declaration of TEMPLATE if it's a prefix key based one.
Unlike `org-capture', in Org-roam such templates can also
optionally specify dedicated `:kind' and `:action' values."
(cl-loop for property in (cddr template) by #'cddr
unless (memq property '(:kind :action))
return nil
finally return (cl-subseq template 0 2)))
(defun org-roam-capture--get (keyword)
"Get the value for KEYWORD from the `org-roam-capture-template'."
(plist-get (plist-get org-capture-plist :org-roam) keyword))

View File

@@ -5,7 +5,7 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 2.0.0
;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1"))
;; This file is NOT part of GNU Emacs.
@@ -202,6 +202,10 @@ nodes." org-id-locations-file)
;;; Obsolete functions
(make-obsolete 'org-roam-get-keyword 'org-collect-keywords "org-roam 2.0")
;;; Obsolete variables
(make-obsolete-variable 'org-roam-dailies-capture-templates 'org-roam-capture-templates "org-roam 2.1")
(make-obsolete-variable 'org-roam-capture-ref-templates 'org-roam-capture-templates "org-roam 2.1")
(provide 'org-roam-compat)
;;; org-roam-compat.el ends here

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 2.0.0
;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "2.90.1"))
;; This file is NOT part of GNU Emacs.
@@ -379,7 +379,8 @@ the same time:
The preview content comes from FILE, and the link as at POINT.")
(defun org-roam-preview-visit (file point &optional other-window)
"Visit FILE at POINT. With OTHER-WINDOW non-nil do so in another window.
"Visit FILE at POINT and return the visited buffer.
With OTHER-WINDOW non-nil do so in another window.
In interactive calls OTHER-WINDOW is set with
`universal-argument'."
(interactive (list (org-roam-buffer-file-at-point 'assert)
@@ -389,11 +390,12 @@ In interactive calls OTHER-WINDOW is set with
(display-buffer-fn (if other-window
#'switch-to-buffer-other-window
#'pop-to-buffer-same-window)))
(funcall display-buffer-fn buf)
(with-current-buffer buf
(widen)
(goto-char point))
(funcall display-buffer-fn buf)
(when (org-invisible-p) (org-show-context))))
(when (org-invisible-p) (org-show-context))
buf))
(defun org-roam-preview-get-contents (file point)
"Get preview content for FILE at POINT."
@@ -540,22 +542,20 @@ Sorts by title."
(defun org-roam-reflinks-get (node)
"Return the reflinks for NODE."
(let ((refs (org-roam-db-query [:select [ref] :from refs
:where (= node-id $s1)]
(let ((refs (org-roam-db-query [:select :distinct [refs:ref links:source links:pos links:properties]
:from refs
:left-join links
:where (= refs:node-id $s1)
:and (= links:dest refs:ref)]
(org-roam-node-id node)))
links)
(pcase-dolist (`(,ref) refs)
(pcase-dolist (`(,source-id ,pos ,properties) (org-roam-db-query
[:select [source pos properties]
:from links
:where (= dest $s1)]
ref))
(push (org-roam-populate
(org-roam-reflink-create
:source-node (org-roam-node-create :id source-id)
:ref ref
:point pos
:properties properties)) links)))
(pcase-dolist (`(,ref ,source-id ,pos ,properties) refs)
(push (org-roam-populate
(org-roam-reflink-create
:source-node (org-roam-node-create :id source-id)
:ref ref
:point pos
:properties properties)) links))
links))
(defun org-roam-reflinks-sort (a b)
@@ -593,7 +593,7 @@ Sorts by title."
"A `magit-section' used by `org-roam-mode' to contain grep output.")
(defun org-roam-grep-visit (file &optional other-window row col)
"Visits FILE. If ROW, move to the row, and if COL move to the COL.
"Visit FILE at row ROW (if any) and column COL (if any). Return the buffer.
With OTHER-WINDOW non-nil (in interactive calls set with
`universal-argument') display the buffer in another window
instead."
@@ -605,6 +605,7 @@ instead."
(display-buffer-fn (if other-window
#'switch-to-buffer-other-window
#'pop-to-buffer-same-window)))
(funcall display-buffer-fn buf)
(with-current-buffer buf
(widen)
(goto-char (point-min))
@@ -612,8 +613,8 @@ instead."
(forward-line (1- row)))
(when col
(forward-char (1- col))))
(funcall display-buffer-fn buf)
(when (org-invisible-p) (org-show-context))))
(when (org-invisible-p) (org-show-context))
buf))
;;;; Unlinked references
(defvar org-roam-unlinked-references-result-re

View File

@@ -5,7 +5,7 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 2.0.0
;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4") (magit-section "2.90.1"))
;; This file is NOT part of GNU Emacs.
@@ -76,6 +76,21 @@ It takes a single argument NODE, which is an `org-roam-node' construct."
(const :tag "file-atime" file-atime))
:group 'org-roam)
(defcustom org-roam-node-template-prefixes
'(("tags" . "#")
("todo" . "t:"))
"Prefixes for each of the node's properties.
This is used in conjunction with
`org-roam-node-display-template': in minibuffer completions the
node properties will be prefixed with strings in this variable,
acting as a query language of sorts.
For example, if a node has tags (\"foo\" \"bar\") and the alist
has the entry (\"tags\" . \"#\"), these will appear as
\"#foo #bar\"."
:group 'org-roam
:type '(alist))
(defcustom org-roam-ref-annotation-function #'org-roam-ref-read--annotation
"This function used to attach annotations for `org-roam-ref-read'.
It takes a single argument REF, which is a propertized string.")
@@ -165,7 +180,7 @@ populated."
(magit-section-up)
(org-roam-node-at-point)))
(t (org-with-wide-buffer
(org-back-to-heading-or-point-min)
(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))
@@ -354,23 +369,31 @@ GROUP BY id")))
all-titles)))))
;;;; Finders
(defun org-roam-node-find-noselect (node)
"Navigate to the point for NODE, and return the buffer."
(defun org-roam-node-find-noselect (node &optional force)
"Navigate to the point for NODE, and return the buffer.
If NODE is already visited, this won't automatically move the
point to the beginning of the NODE, unless FORCE is non-nil."
(unless (org-roam-node-file node)
(user-error "Node does not have corresponding file"))
(let ((buf (find-file-noselect (org-roam-node-file node))))
(with-current-buffer buf
(goto-char (org-roam-node-point node)))
(when (or force
(not (equal (org-roam-node-id node)
(org-roam-id-at-point))))
(goto-char (org-roam-node-point node))))
buf))
(defun org-roam-node-visit (node &optional other-window)
(defun org-roam-node-visit (node &optional other-window force)
"From the current buffer, visit NODE. Return the visited buffer.
Display the buffer in the selected window. With a prefix
argument OTHER-WINDOW display the buffer in another window
instead."
(interactive (list (org-roam-node-at-point t) current-prefix-arg))
(let ((buf (org-roam-node-find-noselect node))
instead.
If NODE is already visited, this won't automatically move the
point to the beginning of the NODE, unless FORCE is non-nil. In
interactive calls FORCE always set to t."
(interactive (list (org-roam-node-at-point t) current-prefix-arg t))
(let ((buf (org-roam-node-find-noselect node 'force))
(display-buffer-fn (if other-window
#'switch-to-buffer-other-window
#'pop-to-buffer-same-window)))
@@ -455,50 +478,51 @@ The displayed title is formatted according to `org-roam-node-display-template'."
(let ((candidate-main (org-roam-node-read--format-entry node (1- (frame-width)))))
(cons (propertize candidate-main 'node node) node)))
(defun org-roam-node-read--tags-to-str (tags)
"Convert list of TAGS into a string."
(mapconcat (lambda (s) (concat "#" s)) tags " "))
(defun org-roam-node-read--format-entry (node width)
"Formats NODE for display in the results list.
WIDTH is the width of the results list.
Uses `org-roam-node-display-template' to format the entry."
(let ((fmt (org-roam-node-read--process-display-format org-roam-node-display-template)))
(pcase-let ((`(,tmpl . ,tmpl-width)
(org-roam-node-read--process-display-format org-roam-node-display-template)))
(org-roam-format-template
(car fmt)
tmpl
(lambda (field _default-val)
(let* ((field (split-string field ":"))
(field-name (car field))
(field-width (cadr field))
(getter (intern (concat "org-roam-node-" field-name)))
(field-value (or (funcall getter node) "")))
(when (and (equal field-name "tags")
field-value)
(setq field-value (org-roam-node-read--tags-to-str field-value)))
(pcase-let* ((`(,field-name ,field-width) (split-string field ":"))
(getter (intern (concat "org-roam-node-" field-name)))
(field-value (funcall getter node)))
(when (and (equal field-name "file")
field-value)
(setq field-value (file-relative-name field-value org-roam-directory)))
(when (and (equal field-name "olp")
field-value)
(setq field-value (string-join field-value " > ")))
(if (not field-width)
field-value
(setq field-width (string-to-number field-width))
(let ((display-string (truncate-string-to-width
field-value
(if (> field-width 0)
field-width
(- width (cdr fmt)))
0 ?\s)))
;; Setting the display (which would be padded out to the field length) for an
;; empty string results in an empty string and misalignment for candidates that
;; don't have some field. This uses the actual display string, made of spaces
;; when the field-value is "" so that we actually take up space.
(if (not (equal field-value ""))
;; Remove properties from the full candidate string, otherwise the display
;; formatting with pre-prioritized field-values gets messed up.
(propertize (substring-no-properties field-value) 'display display-string)
display-string))))))))
(when (and field-value (not (listp field-value)))
(setq field-value (list field-value)))
(setq field-value (mapconcat
(lambda (v)
(concat (or (cdr (assoc field-name org-roam-node-template-prefixes))
"")
v))
field-value " "))
(setq field-width (cond
((not field-width)
field-width)
((string-equal field-width "*")
(- width tmpl-width))
((>= (string-to-number field-width) 0)
(string-to-number field-width))))
;; Setting the display (which would be padded out to the field length) for an
;; empty string results in an empty string and misalignment for candidates that
;; don't have some field. This uses the actual display string, made of spaces
;; when the field-value is "" so that we actually take up space.
(let ((display-string (if field-width
(truncate-string-to-width field-value field-width 0 ?\s)
field-value)))
(if (equal field-value "")
display-string
;; Remove properties from the full candidate string, otherwise the display
;; formatting with pre-prioritized field-values gets messed up.
(propertize (substring-no-properties field-value) 'display display-string))))))))
(defun org-roam-node-read--process-display-format (format)
"Pre-calculate minimal widths needed by the FORMAT string."
@@ -597,7 +621,7 @@ Assumes that the cursor was put where the link is."
(cond
((org-roam-node-file node)
(org-mark-ring-push)
(org-roam-node-visit node)
(org-roam-node-visit node nil 'force)
t)
(t nil))))))
@@ -611,7 +635,7 @@ Assumes that the cursor was put where the link is."
(when org-roam-link-auto-replace
(org-roam-link-replace-at-point))
(org-mark-ring-push)
(org-roam-node-visit node))
(org-roam-node-visit node nil 'force))
(org-roam-capture-
:node (org-roam-node-create :title title-or-alias)
:props '(:finalize find-file))))
@@ -803,7 +827,7 @@ If region is active, then use it instead of the node at point."
"Convert current subtree at point to a node, and extract it into a new file."
(interactive)
(save-excursion
(org-back-to-heading-or-point-min)
(org-back-to-heading-or-point-min t)
(when (bobp) (user-error "Already a top-level node"))
(org-id-get-create)
(save-buffer)
@@ -841,7 +865,7 @@ If region is active, then use it instead of the node at point."
Recursively traverses up the headline tree to find the
first encapsulating ID."
(org-with-wide-buffer
(org-back-to-heading-or-point-min)
(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))

View File

@@ -5,7 +5,7 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 2.0.0
;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.4"))
;; This file is NOT part of GNU Emacs.
@@ -32,6 +32,8 @@
;;
;;; Code:
(require 'org-roam)
;;; String utilities
;; TODO Refactor this.
(defun org-roam-replace-string (old new s)
@@ -103,6 +105,29 @@ If FILE, set `default-directory' to FILE's directory and insert its contents."
(setq-local default-directory (file-name-directory ,file)))
,@body)))))
;;; Processing options
(defun org-roam--valid-option-p (option choice)
"Return t if OPTION satisfies CHOICE, else nil.
OPTION is a symbol, while CHOICE is either, a symbol or a list of
symbols that can optionally start with `:not' keyword.
If CHOICE is a list that indicates negation, then the function
will return t if OPTION isn't in the list. Otherwise it will
return t is OPTION is present in the CHOICE.
When CHOICE is a symbol, it will behave like `eq', except of
special 'any value, in which case it will always return t,
independently OPTION's value.
CHOICE as a list can too contain 'any, in which case any OPTION
value will be considered as part of the CHOICE, with respect to
negation."
(let* ((choices (-list choice))
(intersection (-intersection (list option 'any) choices))
(negation (eq :not (car choices))))
(or (and intersection (not negation))
(and (not intersection) negation))))
;;; Formatting
(defun org-roam-format-template (template replacer)
"Format TEMPLATE with the function REPLACER.
@@ -288,18 +313,45 @@ If VAL is not specified, user is prompted to select a value."
"Return `org-roam' version.
Interactively, or when MESSAGE is non-nil, show in the echo area."
(interactive)
(let* ((version
(with-temp-buffer
(insert-file-contents-literally (locate-library "org-roam.el"))
(goto-char (point-min))
(save-match-data
(if (re-search-forward "\\(?:;; Version: \\([^z-a]*?$\\)\\)" nil nil)
(substring-no-properties (match-string 1))
"N/A")))))
(let* ((toplib (or load-file-name buffer-file-name))
gitdir topdir version)
(unless (and toplib (equal (file-name-nondirectory toplib) "org-roam-utils.el"))
(setq toplib (locate-library "org-roam-utils.el")))
(setq toplib (and toplib (org-roam--straight-chase-links toplib)))
(when toplib
(setq topdir (file-name-directory toplib)
gitdir (expand-file-name ".git" topdir)))
(when (file-exists-p gitdir)
(setq version
(let ((default-directory topdir))
(shell-command-to-string "git describe --tags --dirty --always"))))
(unless version
(setq version (with-temp-buffer
(insert-file-contents-literally (locate-library "org-roam.el"))
(goto-char (point-min))
(save-match-data
(if (re-search-forward "\\(?:;; Version: \\([^z-a]*?$\\)\\)" nil nil)
(substring-no-properties (match-string 1))
"N/A")))))
(if (or message (called-interactively-p 'interactive))
(message "%s" version)
version)))
(defun org-roam--straight-chase-links (filename)
"Chase links in FILENAME until a name that is not a link.
This is the same as `file-chase-links', except that it also
handles fake symlinks that are created by the package manager
straight.el on Windows.
See <https://github.com/raxod502/straight.el/issues/520>."
(when (and (bound-and-true-p straight-symlink-emulation-mode)
(fboundp 'straight-chase-emulated-symlink))
(when-let ((target (straight-chase-emulated-symlink filename)))
(unless (eq target 'broken)
(setq filename target))))
(file-chase-links filename))
;;;###autoload
(defun org-roam-diagnostics ()
"Collect and print info for `org-roam' issues."

View File

@@ -5,7 +5,7 @@
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; URL: https://github.com/org-roam/org-roam
;; Keywords: org-mode, roam, convenience
;; Version: 2.0.0
;; Version: 2.1.0
;; Package-Requires: ((emacs "26.1") (dash "2.13") (f "0.17.2") (org "9.4") (emacsql "3.0.0") (emacsql-sqlite "1.0.0") (magit-section "2.90.1"))
;; This file is NOT part of GNU Emacs.
@@ -94,7 +94,6 @@
(eval-when-compile
(require 'subr-x))
(require 'org-roam-utils)
(require 'org-roam-compat)
;;; Options
@@ -310,6 +309,7 @@ E.g. (\".org\") => (\"*.org\" \"*.org.gpg\")"
(provide 'org-roam)
(cl-eval-when (load eval)
(require 'org-roam-utils)
(require 'org-roam-db)
(require 'org-roam-node)
(require 'org-roam-capture)