mirror of
https://github.com/org-roam/org-roam
synced 2025-08-31 14:43:32 -05:00
Compare commits
14 Commits
filenotify
...
feat/unify
Author | SHA1 | Date | |
---|---|---|---|
|
b6a898d6d6 | ||
|
e9ae19c01c | ||
|
d25d477b4f | ||
|
04b7780ff9 | ||
|
858f531d96 | ||
|
f819720c51 | ||
|
887c49c89c | ||
|
d4cbb1d499 | ||
|
f29a770af3 | ||
|
4a7ecfbed8 | ||
|
df65654b2f | ||
|
b627298171 | ||
|
b8a66deae9 | ||
|
aafc8606bb |
44
CHANGELOG.md
44
CHANGELOG.md
@@ -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
174
README.md
@@ -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
|
||||
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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'.")
|
||||
|
@@ -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)
|
||||
|
@@ -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.
|
||||
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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))
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
116
org-roam-node.el
116
org-roam-node.el
@@ -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))
|
||||
|
@@ -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."
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user