mirror of
https://github.com/org-roam/org-roam
synced 2025-08-21 13:53:31 -05:00
124 lines
5.2 KiB
Markdown
124 lines
5.2 KiB
Markdown
Rather than creating blank files on `org-roam-insert` and
|
|
`org-roam-find-file`, it is may be desirable to prefill the file with
|
|
content. This may include:
|
|
|
|
- Time of creation
|
|
- File it was created from
|
|
- Clipboard content
|
|
- Any other data you may want to input manually
|
|
|
|
This requires a complex template insertion system, but fortunately,
|
|
Org ships with a powerful one: `org-capture`. However, org-capture was
|
|
not designed for such use. Org-roam abuses `org-capture` to some
|
|
extent, extending its syntax. To first understand how org-roam's
|
|
templating system works, it may be useful to look into org-capture.
|
|
|
|
Org-roam's templates can be customized by modifying the variable
|
|
`org-roam-capture-templates`.
|
|
|
|
## Org-roam Templates
|
|
|
|
The org-roam capture template extends org-capture's template with 2
|
|
additional properties:
|
|
|
|
1. `:file-name`: This is the file name template used when a new note
|
|
is created. Notes can be placed in sub-directories by prepending them to
|
|
the filename (`sub/file-name`)
|
|
2. `:head`: This is the template that is inserted on initial note
|
|
creation.
|
|
|
|
### Org-roam Template Expansion
|
|
|
|
Org-roam's template definitions also extend org-capture's template
|
|
syntax, to allow prefilling of strings. In many scenarios,
|
|
`org-roam-capture--capture` is passed a mapping between variables and strings.
|
|
For example, during `org-roam-insert`, a title is prompted for. If the
|
|
title doesn't already exist, we would like to create a new file,
|
|
without prompting for the title again.
|
|
|
|
Variables passed are expanded with the `${var}` syntax. For example,
|
|
during `org-roam-insert`, `${title}` is prefilled for expansion. Any
|
|
variables that do not contain strings, are prompted for values using
|
|
`completing-read`.
|
|
|
|
After doing this expansion, the org-capture's template expansion
|
|
system is used to fill up the rest of the template. You may read up
|
|
more on this on [org-capture's documentation
|
|
page](https://orgmode.org/manual/Template-expansion.html#Template-expansion).
|
|
|
|
For example, take the template: `"%<%Y%m%d%H%M%S>-${title}"`, with the title
|
|
`"Foo"`. The template is first expanded into `%<%Y%m%d%H%M%S>-Foo`. Then
|
|
org-capture expands `%<%Y%m%d%H%M%S>` with timestamp: e.g.
|
|
`20200213032037-Foo`.
|
|
|
|
All of the flexibility afforded by emacs and org-mode are
|
|
available. For example, if you want to encode a UTC timestamp in the
|
|
filename, you can take advantage of org-mode's `%(EXP)` template
|
|
expansion to call `format-time-string` directly to provide its third
|
|
argument to specify UTC.
|
|
|
|
``` emacs-lisp
|
|
("d" "default" plain (function org-roam--capture-get-point)
|
|
"%?"
|
|
:file-name "%(format-time-string \"%Y-%m-%d--%H-%M-%SZ--${slug}\" (current-time) t)"
|
|
:head "#+TITLE: ${title}\n"
|
|
:unnarrowed t)
|
|
```
|
|
|
|
Similarly, if you want to change how titles are transformed into
|
|
slugs, you can override `org-roam--title-to-slug`. For example, to use
|
|
hyphens instead of underscores:
|
|
|
|
|
|
``` emacs-lisp
|
|
(defun org-roam--title-to-slug (title)
|
|
"Convert TITLE to a filename-suitable slug. Uses hyphens rather than underscores."
|
|
(cl-flet* ((nonspacing-mark-p (char)
|
|
(eq 'Mn (get-char-code-property char 'general-category)))
|
|
(strip-nonspacing-marks (s)
|
|
(apply #'string (seq-remove #'nonspacing-mark-p
|
|
(ucs-normalize-NFD-string s))))
|
|
(cl-replace (title pair)
|
|
(replace-regexp-in-string (car pair) (cdr pair) title)))
|
|
(let* ((pairs `(("[^[:alnum:][:digit:]]" . "-") ;; convert anything not alphanumeric
|
|
("--*" . "-") ;; remove sequential underscores
|
|
("^-" . "") ;; remove starting underscore
|
|
("-$" . ""))) ;; remove ending underscore
|
|
(slug (-reduce-from #'cl-replace (strip-nonspacing-marks title) pairs)))
|
|
(s-downcase slug))))
|
|
```
|
|
|
|
This templating system is used throughout org-roam templates.
|
|
|
|
### Template examples
|
|
|
|
Here I walkthrough the default template, reproduced below.
|
|
|
|
```
|
|
("d" "default" plain (function org-roam--capture-get-point)
|
|
"%?"
|
|
:file-name "%<%Y%m%d%H%M%S>-${slug}"
|
|
:head "#+TITLE: ${title}\n"
|
|
:unnarrowed t)
|
|
```
|
|
|
|
1. The template has short key `"d"`. If you have only one template,
|
|
org-roam automatically chooses this template for you.
|
|
2. The template is given a description of `"default"`.
|
|
3. `plain` text is inserted. Other options include Org headings via
|
|
`entry`.
|
|
4. `(function org-roam--capture-get-point)` should not be changed.
|
|
5. `"%?"` is the template inserted on each call to `org-roam-capture--capture`.
|
|
This template means don't insert any content, but place the cursor
|
|
here.
|
|
6. `:file-name` is the file-name template for a new note, if it
|
|
doesn't yet exist. This creates a file at path that looks like
|
|
`/path/to/org-roam-directory/20200213032037-foo.org`.
|
|
7. `:head` contains the initial template to be inserted (once only),
|
|
at the beginning of the file. Here, the title global attribute is
|
|
inserted.
|
|
8. `:unnarrowed t` tells org-capture to show the contents for the
|
|
whole file, rather than narrowing to just the entry.
|
|
|
|
Other options you may want to learn about include `:immediate-finish`.
|