mirror of
https://github.com/org-roam/org-roam
synced 2025-08-03 12:27:23 -05:00
Compare commits
46 Commits
Author | SHA1 | Date | |
---|---|---|---|
cb029c4ce8 | |||
571f65cebd | |||
316ad40b2c | |||
b78b545d31 | |||
8523fb43b4 | |||
dd4b1a97a1 | |||
3a8908f72a | |||
ddaf855b5d | |||
f458c6caf6 | |||
0346d3b16c | |||
63754d1ccd | |||
05ada41710 | |||
bdc13cd6bf | |||
2522b9d2fa | |||
edbe34a1d9 | |||
570467b34b | |||
e84ab1de9a | |||
996923f9d9 | |||
4a5531cde3 | |||
2d206134fd | |||
883eed0a5e | |||
659babf922 | |||
424de1f0cb | |||
618b7f6124 | |||
ce305af319 | |||
58590a0e9d | |||
9ae03532da | |||
159b64b538 | |||
8ec3b441d1 | |||
f048a6b866 | |||
9aba7ee094 | |||
ba91fc41a7 | |||
5eb1a87123 | |||
914bbe3b53 | |||
01130b49e1 | |||
684ab67952 | |||
60eeb3985a | |||
a6cdc77980 | |||
9cd12a4f11 | |||
e00538f909 | |||
270995b2d4 | |||
1cfd71f5a8 | |||
ede33d7411 | |||
7817116403 | |||
efd2072070 | |||
791c059200 |
34
.github/CONTRIBUTING.md
vendored
Normal file
34
.github/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
# Contributing
|
||||
|
||||
If you discover issues, have ideas for improvements or new features, please
|
||||
report them to the [issue tracker][1] of the repository or submit a pull
|
||||
request. Please, try to follow these guidelines when you do so.
|
||||
|
||||
## Issue reporting
|
||||
|
||||
* Check that the issue has not already been reported.
|
||||
* Check that the issue has not already been fixed in the latest code
|
||||
(a.k.a. `develop`).
|
||||
* Be clear, concise and precise in your description of the problem.
|
||||
* Open an issue with a descriptive title and a summary in grammatically correct,
|
||||
complete sentences.
|
||||
* Include any relevant code to the issue summary.
|
||||
* If you're reporting performance issues it'd be nice if you added some profiling data (Emacs has a built-in profiler).
|
||||
|
||||
## Pull requests
|
||||
|
||||
* Read [how to properly contribute to open source projects on Github][2].
|
||||
* Use a topic branch to easily amend a pull request later, if necessary.
|
||||
* Write [good commit messages][3].
|
||||
* Mention related tickets in the commit messages (e.g. `[Fix #N] Add missing autoload cookies`)
|
||||
* Update the [changelog][5].
|
||||
* Use the same coding conventions as the rest of the project.
|
||||
* Verify your Emacs Lisp code with `checkdoc` (<kbd>C-c ? d</kbd>).
|
||||
* Open a [pull request][4] that relates to *only* one subject with a clear title
|
||||
and description in grammatically correct, complete sentences.
|
||||
|
||||
[1]: https://github.com/jethrokuan/org-roam/issues
|
||||
[2]: http://gun.io/blog/how-to-github-fork-branch-and-pull-request
|
||||
[3]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
||||
[4]: https://help.github.com/articles/using-pull-requests
|
||||
[5]: https://github.com/jethrokuan/org-roam/blob/master/CHANGELOG.md
|
30
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
30
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Something's not working.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: 'jethrokuan'
|
||||
---
|
||||
|
||||
### Description
|
||||
|
||||
#### Steps to Reproduce
|
||||
<!--
|
||||
Example:
|
||||
|
||||
1. Load Emacs
|
||||
2. Run `org-roam--build-cache-async`
|
||||
3. Run `org-roam-find-file`
|
||||
...
|
||||
-->
|
||||
|
||||
|
||||
#### Expected Results
|
||||
<!-- Example: File A is there -->
|
||||
|
||||
#### Actual Results
|
||||
<!-- Example: File A is missing -->
|
||||
|
||||
### Versions
|
||||
- Emacs (`C-h v emacs-version`): vX.X.X
|
||||
- Org-roam commit: https://github.com/jethrokuan/org-roam/commit/commithashhere
|
16
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
16
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Create a feature request to improve Org-roam
|
||||
title: ''
|
||||
labels: 'enhancement'
|
||||
assignees: 'jethrokuan'
|
||||
---
|
||||
|
||||
### Brief Abstract
|
||||
|
||||
### Long Description
|
||||
|
||||
### Proposed Implementation (if any)
|
||||
|
||||
### Please check the following:
|
||||
- [ ] No similar feature requests
|
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1 @@
|
||||
###### Motivation for this change
|
69
.github/workflows/test.yml
vendored
Normal file
69
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
# * test.yml --- Test Emacs packages using makem.sh on GitHub Actions
|
||||
|
||||
# https://github.com/alphapapa/makem.sh
|
||||
|
||||
# Based on Steve Purcell's examples at
|
||||
# <https://github.com/purcell/setup-emacs/blob/master/.github/workflows/test.yml>,
|
||||
# <https://github.com/purcell/package-lint/blob/master/.github/workflows/test.yml>.
|
||||
|
||||
# * License:
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# * Code:
|
||||
|
||||
name: "CI"
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
emacs_version:
|
||||
- 26.3
|
||||
- snapshot
|
||||
steps:
|
||||
- uses: purcell/setup-emacs@master
|
||||
with:
|
||||
version: ${{ matrix.emacs_version }}
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Initialize sandbox
|
||||
run: |
|
||||
SANDBOX_DIR=$(mktemp -d) || exit 1
|
||||
echo ::set-env name=SANDBOX_DIR::$SANDBOX_DIR
|
||||
./makem.sh -vv --sandbox $SANDBOX_DIR --install-deps --install-linters
|
||||
|
||||
# The "all" rule is not used, because it treats compilation warnings
|
||||
# as failures, so linting and testing are run as separate steps.
|
||||
|
||||
- name: Lint
|
||||
continue-on-error: true
|
||||
run: ./makem.sh -vv --sandbox $SANDBOX_DIR lint
|
||||
|
||||
- name: Test
|
||||
if: always() # Run test even if linting fails.
|
||||
run: ./makem.sh -vv --sandbox $SANDBOX_DIR test
|
||||
|
||||
# Local Variables:
|
||||
# eval: (outline-minor-mode)
|
||||
# End:
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/.sandbox/
|
||||
**/*.elc
|
93
CHANGELOG.md
Normal file
93
CHANGELOG.md
Normal file
@ -0,0 +1,93 @@
|
||||
# Changelog
|
||||
|
||||
## 0.1.2 (2020-02-21)
|
||||
|
||||
### Breaking Changes
|
||||
* [#143][gh-143] `org-roam-mode` is now a global mode. The installation instructions have changed accordingly.
|
||||
* [#103][gh-103] Change `org-roam-file-format` to a function: `org-roam-file-name-function` to allow more flexible file name customizaton. Also changes `org-roam-use-timestamp-as-filename` to `org-roam-filename-noconfirm` to better describe what it does.
|
||||
|
||||
### New Features
|
||||
* [#145][gh-145] `org-roam-show-graph`: Fallback to Emacs SVG viewer
|
||||
* [#141][gh-141] add variable `org-roam-new-file-directory` for new Org-roam files
|
||||
* [#138][gh-138] add `org-roam-switch-to-buffer`
|
||||
* [#124][gh-124], [#141][gh-141] Maintain cache consistency on file rename and delete
|
||||
* [#87][gh-87], [#90][gh-90] Support encrypted Org files
|
||||
* [#110][gh-110] Add prefix to `org-roam-insert`, for inserting titles down-cased
|
||||
* [#99][gh-99] Add keybinding so that `<return>` or `mouse-1` in the backlinks buffer visits the source file of the backlink at point
|
||||
|
||||
### Changes
|
||||
|
||||
* [#108][gh-108] Locally overwrite the link following behaviour in the org-roam-buffer to open files in the same window `org-roam` was called from
|
||||
|
||||
### Bugfixes
|
||||
* [#86][gh-86] Fix `org-roam--parse-content` incorrect `:to` computation for nested files
|
||||
* [#98][gh-98] Fix `org-roam--find-file` picking up temporary files
|
||||
* [#136][gh-136] Misc bugfixes
|
||||
|
||||
### Internal
|
||||
* [#122][gh-122], [#128][gh-128] Improve performance of post-command-hook
|
||||
* [#92][gh-92], [#105][gh-105] Add tests for core functionality
|
||||
|
||||
### New Contributors
|
||||
* [@frigge](https://github.com/frigge)
|
||||
* [@juergenhoetzel](https://github.com/juergenhoetzel)
|
||||
* [@chip2n](https://github.com/chip2n)
|
||||
* [@l3kn](https://github.com/l3kn)
|
||||
* [@jdormit](https://github.com/jdormit)
|
||||
* [@herbertjones](https://github.com/herbertjones)
|
||||
* [@CeleritasCelery](https://github.com/CeleritasCelery)
|
||||
* [@daniel-koudouna](https://github.com/daniel-koudouna)
|
||||
|
||||
## 0.1.1 (2020-02-15)
|
||||
|
||||
Mostly a documentation/cleanup release.
|
||||
|
||||
### New Features
|
||||
* [#62][gh-62] Add the options `org-roam-use-timestamps-as-filename` and `org-roam-file-format`, more in documentation.
|
||||
|
||||
### Breaking Changes
|
||||
* [#62][gh-62] The ID (file-name) workflow is no longer first-class, but a fallback when titles don't exist.
|
||||
|
||||
### Changes
|
||||
* [#66][gh-66], [#68][gh-68]: Improved the quality of the package in preparation of submission to MELPA
|
||||
* [#73][gh-73]: Added CI to the project via Github Issues (Thanks [@alphapapa](https://github.com/alphapapa/) for scripts and setup)
|
||||
* [#69][gh-69], [#72][gh-72], [#75][gh-75]: Major cleanup and de-duplication of code
|
||||
|
||||
### Bugfixes
|
||||
* [#67][gh-67]: Fixed `org-roam--make-file` not creating files with extensions
|
||||
* [#71][gh-71], [#78][gh-78]: Fixed `org-roam-insert` not inserting correct paths
|
||||
* [#82][gh-82]: Fixed nested Org-roam files not being detected as part of Org-roam
|
||||
|
||||
[gh-62]: https://github.com/jethrokuan/org-roam/pull/66
|
||||
[gh-66]: https://github.com/jethrokuan/org-roam/pull/66
|
||||
[gh-67]: https://github.com/jethrokuan/org-roam/pull/67
|
||||
[gh-68]: https://github.com/jethrokuan/org-roam/pull/68
|
||||
[gh-69]: https://github.com/jethrokuan/org-roam/pull/69
|
||||
[gh-71]: https://github.com/jethrokuan/org-roam/pull/71
|
||||
[gh-72]: https://github.com/jethrokuan/org-roam/pull/72
|
||||
[gh-73]: https://github.com/jethrokuan/org-roam/pull/73
|
||||
[gh-75]: https://github.com/jethrokuan/org-roam/pull/75
|
||||
[gh-78]: https://github.com/jethrokuan/org-roam/pull/78
|
||||
[gh-82]: https://github.com/jethrokuan/org-roam/pull/82
|
||||
[gh-86]: https://github.com/jethrokuan/org-roam/pull/86
|
||||
[gh-87]: https://github.com/jethrokuan/org-roam/pull/87
|
||||
[gh-90]: https://github.com/jethrokuan/org-roam/pull/90
|
||||
[gh-92]: https://github.com/jethrokuan/org-roam/pull/92
|
||||
[gh-98]: https://github.com/jethrokuan/org-roam/pull/98
|
||||
[gh-99]: https://github.com/jethrokuan/org-roam/pull/99
|
||||
[gh-103]: https://github.com/jethrokuan/org-roam/pull/103
|
||||
[gh-105]: https://github.com/jethrokuan/org-roam/pull/105
|
||||
[gh-108]: https://github.com/jethrokuan/org-roam/pull/108
|
||||
[gh-110]: https://github.com/jethrokuan/org-roam/pull/110
|
||||
[gh-122]: https://github.com/jethrokuan/org-roam/pull/122
|
||||
[gh-124]: https://github.com/jethrokuan/org-roam/pull/124
|
||||
[gh-128]: https://github.com/jethrokuan/org-roam/pull/128
|
||||
[gh-136]: https://github.com/jethrokuan/org-roam/pull/136
|
||||
[gh-138]: https://github.com/jethrokuan/org-roam/pull/138
|
||||
[gh-141]: https://github.com/jethrokuan/org-roam/pull/141
|
||||
[gh-142]: https://github.com/jethrokuan/org-roam/pull/142
|
||||
[gh-143]: https://github.com/jethrokuan/org-roam/pull/143
|
||||
|
||||
# Local Variables:
|
||||
# eval: (auto-fill-mode -1)
|
||||
# End:
|
56
Makefile
Normal file
56
Makefile
Normal file
@ -0,0 +1,56 @@
|
||||
# * makem.sh/Makefile --- Script to aid building and testing Emacs Lisp packages
|
||||
|
||||
# This Makefile is from the makem.sh repo: <https://github.com/alphapapa/makem.sh>.
|
||||
|
||||
# * Arguments
|
||||
|
||||
# For consistency, we use only var=val options, not hyphen-prefixed options.
|
||||
|
||||
# NOTE: I don't like duplicating the arguments here and in makem.sh,
|
||||
# but I haven't been able to find a way to pass arguments which
|
||||
# conflict with Make's own arguments through Make to the script.
|
||||
# Using -- doesn't seem to do it.
|
||||
|
||||
ifdef install-deps
|
||||
INSTALL_DEPS = "--install-deps"
|
||||
endif
|
||||
ifdef install-linters
|
||||
INSTALL_LINTERS = "--install-linters"
|
||||
endif
|
||||
|
||||
ifdef sandbox
|
||||
ifeq ($(sandbox), t)
|
||||
SANDBOX = --sandbox
|
||||
else
|
||||
SANDBOX = --sandbox $(sandbox)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef debug
|
||||
DEBUG = "--debug"
|
||||
endif
|
||||
|
||||
# ** Verbosity
|
||||
|
||||
# Since the "-v" in "make -v" gets intercepted by Make itself, we have
|
||||
# to use a variable.
|
||||
|
||||
verbose = $(v)
|
||||
|
||||
ifneq (,$(findstring vv,$(verbose)))
|
||||
VERBOSE = "-vv"
|
||||
else ifneq (,$(findstring v,$(verbose)))
|
||||
VERBOSE = "-v"
|
||||
endif
|
||||
|
||||
# * Rules
|
||||
|
||||
# TODO: Handle cases in which "test" or "tests" are called and a
|
||||
# directory by that name exists, which can confuse Make.
|
||||
|
||||
%:
|
||||
@./makem.sh $(DEBUG) $(VERBOSE) $(SANDBOX) $(INSTALL_DEPS) $(INSTALL_LINTERS) $(@)
|
||||
|
||||
.DEFAULT: init
|
||||
init:
|
||||
@./makem.sh $(DEBUG) $(VERBOSE) $(SANDBOX) $(INSTALL_DEPS) $(INSTALL_LINTERS)
|
62
README.md
62
README.md
@ -1,28 +1,26 @@
|
||||
[![License GPL 3][badge-license]](http://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
[](https://org-roam.readthedocs.io/en/latest/?badge=latest)
|
||||
[](https://img.shields.io/github/v/release/jethrokuan/org-roam)
|
||||
|
||||
## Synopsis
|
||||
|
||||
Org-roam is a rudimentary [Roam][roamresearch] replica built around
|
||||
the all-powerful [Org-mode][org].
|
||||
|
||||
Like Roam, Org-roam offers a powerful and effortless non-hierarchical
|
||||
note-taking approach. With Org-roam, notes flow naturally, making
|
||||
note-taking fun and easy.
|
||||
note-taking fun and easy. Org-roam *enables* a note-taking workflow that
|
||||
is not fluid with vanilla Org-mode (more in [this blog
|
||||
post](https://blog.jethro.dev/posts/how_to_take_smart_notes_org/)).
|
||||
|
||||
|
||||
The goal of the project is to implement core features of Roam around
|
||||
Org-mode, and eventually introduce features enabled by the Emacs
|
||||
ecosystem.
|
||||
ecosystem.
|
||||
|
||||
For more documentation, see [the documentation page](https://org-roam.readthedocs.io/en/latest/).
|
||||
|
||||
## Understanding Roam
|
||||
|
||||
To understand more about Roam, I recommend the following links:
|
||||
|
||||
- [Building a second brain in
|
||||
Roam](https://reddit.com/r/RoamResearch/comments/eho7de/building_a_second_brain_in_roamand_why_you_might)
|
||||
- [Roam: Why I Love It and How I Use
|
||||
It](https://www.nateliason.com/blog/roam)
|
||||
|
||||
## Project Status
|
||||
Visit [the documentation
|
||||
page](https://org-roam.readthedocs.io/en/latest/) for a tutorial and
|
||||
more links.
|
||||
|
||||
As of February 2020, it is in a very early stage of development.
|
||||
|
||||
@ -37,16 +35,50 @@ used to navigate to the respective files.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
|
||||
The recommended method is using use-package and straight, or a similar package manager.
|
||||
|
||||
```emacs-lisp
|
||||
(use-package org-roam
|
||||
:after org
|
||||
:hook
|
||||
(after-init . org-roam-mode)
|
||||
:straight (:host github :repo "jethrokuan/org-roam" :branch "develop")
|
||||
:custom
|
||||
(org-roam-directory "/path/to/org-files/")
|
||||
:bind (:map org-roam-mode-map
|
||||
(("C-c n l" . org-roam)
|
||||
("C-c n f" . org-roam-find-file)
|
||||
("C-c n g" . org-roam-show-graph))
|
||||
:map org-mode-map
|
||||
(("C-c n i" . org-roam-insert))))
|
||||
```
|
||||
|
||||
For more detailed installation instructions (including instructions for
|
||||
Spacemacs users), please see [the installation
|
||||
documentation](https://org-roam.readthedocs.io/en/develop/installation/).
|
||||
|
||||
## Knowledge Bases using Org-Roam
|
||||
|
||||
- [Jethro Kuan](https://braindump.jethro.dev/)
|
||||
([Source](https://github.com/jethrokuan/braindump/tree/master/org))
|
||||
|
||||
## Changelog
|
||||
|
||||
A changelog is being maintained [here](CHANGELOG.md)
|
||||
|
||||
## Contributing
|
||||
|
||||
To report bugs and suggest new feature use the issue tracker. If you
|
||||
have some code which you would like to be merged, then open a pull
|
||||
request. Please also see CONTRIBUTING.md.
|
||||
request. Please also see [CONTRIBUTING.md](.github/CONTRIBUTING.md).
|
||||
|
||||
## License
|
||||
|
||||
Copyright © Jethro Kuan and contributors. Distributed under the GNU
|
||||
General Public License, Version 3
|
||||
|
||||
[roamresearch]: https://www.roamresearch.com/
|
||||
[org]: https://orgmode.org/
|
||||
[badge-license]: https://img.shields.io/badge/license-GPL_3-green.svg
|
||||
|
121
doc/configuration.md
Normal file
121
doc/configuration.md
Normal file
@ -0,0 +1,121 @@
|
||||
To ensure that Org-roam remains manageable, the number of
|
||||
configuration options is deliberately kept small. However, we have
|
||||
attempted to accommodate as many usage styles as possible.
|
||||
|
||||
In this section, we'll go over the main customization options
|
||||
available to Org-Roam. This section is *crucial*. We need to exploit
|
||||
the flexibility of Emacs, and mould our tools exactly to our liking.
|
||||
|
||||
All of Org-roam's customization options can be viewed via `M-x
|
||||
customize-group org-roam`.
|
||||
|
||||
## Setting the Org-roam Directory
|
||||
|
||||
Perhaps the single most important variable to set is
|
||||
`org-roam-directory`. Set `org-roam-directory` to the folder
|
||||
containing all your Org files:
|
||||
|
||||
```emacs-lisp
|
||||
(setq org-roam-directory "/path/to/org/")
|
||||
```
|
||||
|
||||
Every Org file, at any level of nesting, within `/path/to/org/` is
|
||||
considered part of the Org-roam ecosystem.
|
||||
|
||||
## Org-roam Buffer
|
||||
|
||||
The Org-roam buffer defaults to popping up from the right. You may
|
||||
choose to set it to pop up from the left with `(setq
|
||||
org-roam-buffer-position 'left)`.
|
||||
|
||||
The Org-roam buffer name can also be renamed: e.g. `(setq
|
||||
org-roam-buffer "*my-buffer-name*")`.
|
||||
|
||||
The Org-roam buffer width is adjustable via `org-roam-buffer-width`.
|
||||
The value of `org-roam-buffer-width` set as a percentage of the total
|
||||
frame width. For example:
|
||||
|
||||
```emacs-lisp
|
||||
(setq org-roam-buffer-width 0.4)
|
||||
```
|
||||
|
||||
Will result in the Org-roam buffer taking up 40% of the screen width.
|
||||
I have found this to be a good number.
|
||||
|
||||
## Org-roam Links
|
||||
|
||||
By default, links are inserted with the title as the link description.
|
||||
This can make them hard to distinguish from external links. If you
|
||||
wish, you may choose add special indicators for Org-roam links by
|
||||
tweaking `org-roam-link-title-format`, for example:
|
||||
|
||||
```emacs-lisp
|
||||
(setq org-roam-link-title-format "R:%s")
|
||||
```
|
||||
|
||||
## Org-roam Files
|
||||
|
||||
These customization options revolve around the Org files created and
|
||||
managed by Org-roam.
|
||||
|
||||
### Automatically Creating Files Using Timestamp
|
||||
|
||||
A common hassle is ensuring that files are uniquely named within the
|
||||
Org-roam directory. Org-roam's default workflow utilizes the title of
|
||||
Org files in all of its main commands (`org-roam-insert`,
|
||||
`org-roam-find-file`). Hence, having any unique file name is a decent
|
||||
option, and the default workflow uses the timestamp as the filename.
|
||||
|
||||
The format of the filename is controlled by the function
|
||||
`org-roam-file-name-function`, which defaults to a format like
|
||||
`YYYYMMDDHHMMSS_title_here.org`. You may choose to define your own
|
||||
function to change this.
|
||||
|
||||
If you wish to be prompted to change the file name on creation, set
|
||||
`org-roam-filename-noconfirm` to `nil`:
|
||||
|
||||
```emacs-lisp
|
||||
(setq org-roam-filename-noconfirm nil)
|
||||
```
|
||||
|
||||
It is then the user's responsibility to ensure that the file names are
|
||||
unique.
|
||||
|
||||
### Autopopulating Titles
|
||||
|
||||
The default workflow uses the title of the Org file in several
|
||||
commands. The title is specified via the `#+TITLE:` attribute,
|
||||
typically near the top of the file. The option
|
||||
`org-roam-autopopulate-title` defaults to `t`. When true, the title
|
||||
attribute is automatically inserted into the files created via
|
||||
Org-roam commands. Setting it to `nil` will disable this behaviour.
|
||||
|
||||
### Encryption
|
||||
|
||||
Encryption (via GPG) can be enabled for all new files by setting
|
||||
`org-roam-encrypt-files` to `t`. When enabled, new files are created
|
||||
with the .org.gpg extension and decryption are handled automatically
|
||||
by EasyPG. Note that this causes Emacs to ask for password when the
|
||||
cache is built (if you have an encrypted file in `org-roam-directory`)
|
||||
as well as each time a new file is created. It might be a good idea to
|
||||
cache the password in order to make this more managable.
|
||||
|
||||
## Org-roam Graph Viewer
|
||||
|
||||
Org-roam generates an SVG image using
|
||||
[Graphviz](https://graphviz.org/). To setup graph navigation, see the
|
||||
[Graph Setup](graph_setup.md) page.
|
||||
|
||||
Org-roam tries its best to locate the Graphviz executable from your
|
||||
PATH, but if it fails to do so, you may set it manually:
|
||||
|
||||
```
|
||||
(setq org-roam-graphviz-executable "/path/to/dot")
|
||||
```
|
||||
|
||||
Org-roam also attempts to use Firefox (located on PATH) to view the
|
||||
SVG, you may choose to set it to any compatible program:
|
||||
|
||||
```
|
||||
(setq org-roam-graph-viewer "/path/to/image-viewer")
|
||||
```
|
109
doc/ecosystem.md
109
doc/ecosystem.md
@ -1,12 +1,11 @@
|
||||
## Ecosystem
|
||||
|
||||
A number of packages work well combined with Org-Roam:
|
||||
|
||||
### Deft
|
||||
[Deft](https://jblevins.org/projects/deft/) provides a nice
|
||||
interface for browsing and filtering org-roam notes.
|
||||
## Deft
|
||||
|
||||
```
|
||||
[Deft][deft] provides a nice interface for browsing and filtering
|
||||
org-roam notes.
|
||||
|
||||
```emacs-lisp
|
||||
(use-package deft
|
||||
:after org
|
||||
:bind
|
||||
@ -15,17 +14,51 @@ interface for browsing and filtering org-roam notes.
|
||||
(deft-recursive t)
|
||||
(deft-use-filter-string-for-filename t)
|
||||
(deft-default-extension "org")
|
||||
(deft-directory "/path/to/org-roam-files/")
|
||||
(deft-use-filename-as-title t))
|
||||
(deft-directory "/path/to/org-roam-files/"))
|
||||
```
|
||||
|
||||
### Org-journal
|
||||
If the title of the Org file is not the first line, you might not get
|
||||
nice titles. You may choose to patch this to use `org-roam`'s
|
||||
functionality. Here I'm using [el-patch](https://github.com/raxod502/el-patch):
|
||||
|
||||
```emacs-lisp
|
||||
(use-package el-patch
|
||||
:straight (:host github
|
||||
:repo "raxod502/el-patch"
|
||||
:branch "develop"))
|
||||
|
||||
(eval-when-compile
|
||||
(require 'el-patch))
|
||||
|
||||
(use-package deft
|
||||
;; same as above...
|
||||
:config/el-patch
|
||||
(defun deft-parse-title (file contents)
|
||||
"Parse the given FILE and CONTENTS and determine the title.
|
||||
If `deft-use-filename-as-title' is nil, the title is taken to
|
||||
be the first non-empty line of the FILE. Else the base name of the FILE is
|
||||
used as title."
|
||||
(el-patch-swap (if deft-use-filename-as-title
|
||||
(deft-base-filename file)
|
||||
(let ((begin (string-match "^.+$" contents)))
|
||||
(if begin
|
||||
(funcall deft-parse-title-function
|
||||
(substring contents begin (match-end 0))))))
|
||||
(org-roam--get-title-or-slug file))))
|
||||
```
|
||||
|
||||
The Deft interface can slow down quickly when the number of files get
|
||||
huge. [Notdeft][notdeft] is a fork of Deft that uses an external
|
||||
search engine and indexer.
|
||||
|
||||
## Org-journal
|
||||
|
||||
[Org-journal](https://github.com/bastibe/org-journal) is a more
|
||||
powerful alternative to the simple function `org-roam-today`. It
|
||||
provides better journaling capabilities, and a nice calendar interface
|
||||
to see all dated entries.
|
||||
|
||||
```
|
||||
```emacs-lisp
|
||||
(use-package org-journal
|
||||
:bind
|
||||
("C-c n j" . org-journal-new-entry)
|
||||
@ -35,3 +68,59 @@ to see all dated entries.
|
||||
(org-journal-dir "/path/to/org-roam-files/")
|
||||
(org-journal-date-format "%A, %d %B %Y"))
|
||||
```
|
||||
|
||||
## Note-taking Add-ons
|
||||
|
||||
These are some plugins that make note-taking in Org-mode more
|
||||
enjoyable.
|
||||
|
||||
### Org-download
|
||||
|
||||
[Org-download][org-download] lets you screenshot and yank images from
|
||||
the web into your notes:
|
||||
|
||||

|
||||
|
||||
```emacs-lisp
|
||||
(use-package org-download
|
||||
:after org
|
||||
:bind
|
||||
(:map org-mode-map
|
||||
(("s-Y" . org-download-screenshot)
|
||||
("s-y" . org-download-yank))))
|
||||
```
|
||||
|
||||
### mathpix.el
|
||||
|
||||
[mathpix.el][mathpix-el] uses [Mathpix's](https://mathpix.com/) API to convert clips into
|
||||
latex equations:
|
||||
|
||||

|
||||
|
||||
```emacs-lisp
|
||||
(use-package mathpix.el
|
||||
:straight (:host github :repo "jethrokuan/mathpix.el")
|
||||
:custom ((mathpix-app-id "app-id")
|
||||
(mathpix-app-key "app-key"))
|
||||
:bind
|
||||
("C-x m" . mathpix-screenshot))
|
||||
```
|
||||
|
||||
### Org-noter / Interleave
|
||||
|
||||
[Org-noter][org-noter] and [Interleave][interleave] are both projects
|
||||
that allow synchronised annotation of documents (PDF, EPUB etc.)
|
||||
within Org-mode.
|
||||
|
||||
### Org-ref
|
||||
|
||||
[Org-ref][org-ref] does citation and bibliography management in
|
||||
Org-mode, and a great tool for scientific notes.
|
||||
|
||||
[deft]: https://jblevins.org/projects/deft/
|
||||
[notdeft]: https://github.com/hasu/notdeft
|
||||
[org-download]: https://github.com/abo-abo/org-download
|
||||
[mathpix-el]: https://github.com/jethrokuan/mathpix.el
|
||||
[org-noter]: https://github.com/weirdNox/org-noter
|
||||
[interleave]: https://github.com/rudolfochrist/interleave
|
||||
[org-ref]: https://github.com/jkitchin/org-ref
|
||||
|
78
doc/graph_setup.md
Normal file
78
doc/graph_setup.md
Normal file
@ -0,0 +1,78 @@
|
||||
The setup is similar to that of org-protocol. Here `roam://` links are
|
||||
defined, and need to be associated with an application.
|
||||
|
||||
The gist of the setup is setting up a Bash script to trim off the
|
||||
`roam://` prefix from the link, causing the desktop application to
|
||||
call `emacsclient path/to/org-roam-file.org`.
|
||||
|
||||
## Linux
|
||||
|
||||
Create a desktop application. I place mine in
|
||||
`~/.local/share/applications/roam.desktop`:
|
||||
|
||||
```
|
||||
[Desktop Entry]
|
||||
Name=Org-Roam Client
|
||||
Exec=/home/jethro/.local/bin/launch_emacs %u
|
||||
Icon=emacs-icon
|
||||
Type=Application
|
||||
Terminal=false
|
||||
MimeType=x-scheme-handler/roam
|
||||
```
|
||||
|
||||
Note the `Exec` key is set to a bash script poorly named
|
||||
`launch_emacs`. You can set it to whatever you want.
|
||||
|
||||
Create the corresponding bash script, and make it executable. Here's
|
||||
how it looks like:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
emacsclient "${1#*:}"
|
||||
```
|
||||
|
||||
Finally, associate `roam://` links with the desktop application by
|
||||
running in your shell:
|
||||
|
||||
```bash
|
||||
xdg-mime default roam.desktop x-scheme-handler/roam
|
||||
```
|
||||
|
||||
## Mac OS
|
||||
|
||||
One solution to this, recommended in [Issue
|
||||
#115](https://github.com/jethrokuan/org-roam/issues/115), is to use
|
||||
[Platypus](https://github.com/sveinbjornt/Platypus). Here are the
|
||||
instructions for setting up with Platypus and Chrome:
|
||||
|
||||
1. Create an executable `launch-emacs.sh` script:
|
||||
|
||||
```sh
|
||||
#!/usr/bin/env bash
|
||||
/usr/local/bin/emacsclient --no-wait "${1#*:}"
|
||||
```
|
||||
|
||||
2. Install and launch Platypus (with [Homebrew](https://brew.sh/)):
|
||||
|
||||
```sh
|
||||
brew cask install playtpus
|
||||
```
|
||||
|
||||
3. Playtpus settings:
|
||||
|
||||
- App Name: `OrgRoam`
|
||||
- Script Type: `env` and `/usr/bin/env`
|
||||
- Script Path: `/path/to/your/launch-emacs.sh`
|
||||
- Tick Accept dropped items and click Settings
|
||||
- Tick Accept dropped files
|
||||
- Tick Register as URI scheme handler
|
||||
- Add `roam` as a protocol
|
||||
- Create the app
|
||||
|
||||
To disable the "confirm" prompt in Chrome, you can also make Chrome
|
||||
show a checkbox to tick, so that the `OrgRoam` app will be used
|
||||
without confirmation. To do this, run in a shell:
|
||||
|
||||
```sh
|
||||
defaults write com.google.Chrome ExternalProtocolDialogShowAlwaysOpenCheckbox -bool true
|
||||
```
|
BIN
doc/images/mathpix.gif
Normal file
BIN
doc/images/mathpix.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 781 KiB |
BIN
doc/images/org-download.gif
Normal file
BIN
doc/images/org-download.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 MiB |
BIN
doc/images/org-roam-find-file.gif
Normal file
BIN
doc/images/org-roam-find-file.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 578 KiB |
BIN
doc/images/org-roam-insert-filetag.gif
Normal file
BIN
doc/images/org-roam-insert-filetag.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 774 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.2 MiB |
@ -6,17 +6,17 @@ The recommended method is using [use-package][use-package] and
|
||||
```
|
||||
(use-package org-roam
|
||||
:after org
|
||||
:hook (org-mode . org-roam-mode)
|
||||
:straight (:host github :repo "jethrokuan/org-roam")
|
||||
:hook
|
||||
(after-init . org-roam-mode)
|
||||
:straight (:host github :repo "jethrokuan/org-roam" :branch "develop")
|
||||
:custom
|
||||
(org-roam-directory "/path/to/org-files/")
|
||||
(org-roam-link-representation 'title) ;; or keep it as 'id
|
||||
:bind
|
||||
("C-c n l" . org-roam)
|
||||
("C-c n t" . org-roam-today)
|
||||
("C-c n f" . org-roam-find-file)
|
||||
("C-c n i" . org-roam-insert)
|
||||
("C-c n g" . org-roam-show-graph))
|
||||
:bind (:map org-roam-mode-map
|
||||
(("C-c n l" . org-roam)
|
||||
("C-c n f" . org-roam-find-file)
|
||||
("C-c n g" . org-roam-show-graph))
|
||||
:map org-mode-map
|
||||
(("C-c n i" . org-roam-insert))))
|
||||
```
|
||||
|
||||
If not using package.el, you can also clone it into your Emacs
|
||||
@ -26,10 +26,68 @@ directory and add it to your load path:
|
||||
git clone https://github.com/jethrokuan/org-roam/ ~/.emacs.d/elisp/org-roam
|
||||
```
|
||||
|
||||
```
|
||||
(use-package org-roam
|
||||
:after org
|
||||
:load-path "elisp/"
|
||||
:hook
|
||||
(after-init . org-roam-mode)
|
||||
:straight (:host github :repo "jethrokuan/org-roam" :branch "develop")
|
||||
:custom
|
||||
(org-roam-directory "/path/to/org-files/")
|
||||
:bind (:map org-roam-mode-map
|
||||
(("C-c n l" . org-roam)
|
||||
("C-c n f" . org-roam-find-file)
|
||||
("C-c n g" . org-roam-show-graph))
|
||||
:map org-mode-map
|
||||
(("C-c n i" . org-roam-insert))))
|
||||
```
|
||||
|
||||
Or without use-package:
|
||||
|
||||
```
|
||||
(add-to-list 'load-path "./elisp")
|
||||
(require 'org-roam)
|
||||
```
|
||||
|
||||
There are a number of important configuration options, that greatly
|
||||
affect the Roam workflow. Do look through them at the
|
||||
[Configuration](configuration.md) page.
|
||||
|
||||
[use-package]: https://github.com/jwiegley/use-package
|
||||
[straight]: https://github.com/raxod502/straight.el
|
||||
|
||||
## Spacemacs
|
||||
If you are using Spacemacs, you can easily install org-roam by creating a simple layer that wraps org-roam. Paste the following into a new file `/.emacs.d/private/org-roam/packages.el`.
|
||||
```
|
||||
(defconst org-roam-packages
|
||||
'((org-roam :location
|
||||
(recipe :fetcher github :repo "jethrokuan/org-roam" :branch "develop"))))
|
||||
|
||||
(defun org-roam/init-org-roam ()
|
||||
(use-package org-roam
|
||||
:after org
|
||||
:hook
|
||||
(after-init . org-roam-mode)
|
||||
:custom
|
||||
(org-roam-directory "/path/to/org-files/")
|
||||
:init
|
||||
(progn
|
||||
(spacemacs/declare-prefix "ar" "org-roam")
|
||||
(spacemacs/set-leader-keys
|
||||
"arl" 'org-roam
|
||||
"art" 'org-roam-today
|
||||
"arf" 'org-roam-find-file
|
||||
"arg" 'org-roam-show-graph)
|
||||
|
||||
(spacemacs/declare-prefix-for-mode 'org-mode "mr" "org-roam")
|
||||
(spacemacs/set-leader-keys-for-major-mode 'org-mode
|
||||
"rl" 'org-roam
|
||||
"rt" 'org-roam-today
|
||||
"rb" 'org-roam-switch-to-buffer
|
||||
"rf" 'org-roam-find-file
|
||||
"ri" 'org-roam-insert
|
||||
"rg" 'org-roam-show-graph))))
|
||||
```
|
||||
|
||||
Next, append `org-roam` to the `dotspacemacs-configuration-layers` list in your `.spacemacs` configuration file. Reload (`SPC f e R`) or restart Emacs to load `org-roam`. It's functions are available under the prefix `SPC a r` and `, r` when visiting an org-mode buffer.
|
||||
|
20
doc/notetaking_workflow.md
Normal file
20
doc/notetaking_workflow.md
Normal file
@ -0,0 +1,20 @@
|
||||
## Recommended Books
|
||||
- [How to Take Smart Notes][1]
|
||||
|
||||
## Articles
|
||||
- [How to Take Smart Notes in Org-mode - Jethro Kuan][7]
|
||||
- [The Zettelkasten Method - LessWrong 2.0][3]
|
||||
- [Building a second brain in Roam][4]
|
||||
- [Roam: Why I Love It and How I Use It][5]
|
||||
- [Adam Keesling's Twitter Thread][6]
|
||||
|
||||
## What to Do With Your Notes
|
||||
- [How to Use Roam to Outline a New Article in Under 20 Minutes][2]
|
||||
|
||||
[1]: https://www.goodreads.com/book/show/34507927-how-to-take-smart-notes?ac=1&from_search=true&qid=6L8iEE1FIA&rank=1
|
||||
[2]: https://www.youtube.com/watch?v=RvWic15iXjk
|
||||
[3]: https://www.lesswrong.com/posts/NfdHG6oHBJ8Qxc26s/the-zettelkasten-method-1
|
||||
[4]: https://reddit.com/r/RoamResearch/comments/eho7de/building_a_second_brain_in_roamand_why_you_might
|
||||
[5]: https://www.nateliason.com/blog/roam
|
||||
[6]: https://twitter.com/adam_keesling/status/1196864424725774336?s=20
|
||||
[7]: https://blog.jethro.dev/posts/how_to_take_smart_notes_org/
|
73
doc/tour.md
73
doc/tour.md
@ -1,20 +1,69 @@
|
||||
### A Tour of Org-Roam
|
||||
Org-roam was built to support a workflow that was not possible with
|
||||
vanilla Org-mode. This flow is modelled after the [Zettelkasten
|
||||
method][zettelkasten], and many of [Roam Research][roam]'s workflows.
|
||||
Understanding this flow is crucial! Org-roam doesn't auto-magically
|
||||
make your note-taking better -- it's changing the note-taking workflow
|
||||
that does.
|
||||
|
||||
All of this starts from the note. A note is just a simple `.org` file
|
||||
in the directory. Any org file in the directory is considered part of
|
||||
the org-roam ecosystem. Notes are quickly linked together (and created
|
||||
if necessary) using `org-roam-insert`.
|
||||
To understand more the methods and madness, the [Note-Taking
|
||||
Workflow][appendix:ntw] page contains a page of useful references.
|
||||
I've also written [a post][jethro-blog-post] about how I use Org-roam.
|
||||
|
||||

|
||||
Without further ado, let's begin!
|
||||
|
||||
Org-roam tracks all of these file links, and builds a cache
|
||||
asynchronously in the background. This cache is used to populate the
|
||||
backlinks buffer, which shows files that link to the current file, as
|
||||
well as some preview contents:
|
||||
## Building the Cache
|
||||
|
||||
Assuming you've set `org-roam-directory` appropriately, running `M-x
|
||||
org-roam--build-cache-async` should build up the caches that will
|
||||
allow you to begin using Org-roam. I do this on startup:
|
||||
|
||||
```emacs-lisp
|
||||
(add-hook 'after-init-hook 'org-roam--build-cache-async)
|
||||
```
|
||||
|
||||
## Finding a Note
|
||||
|
||||
`org-roam-find-file` shows you the list of notes you currently have in
|
||||
Org-roam. Selecting the title will bring you to the corresponding
|
||||
note. Entering a title of a note that does not yet exist will create a
|
||||
new note with that title.
|
||||
|
||||

|
||||
|
||||
## Inserting Links
|
||||
|
||||
Within your Org-roam notes, you are encouraged to liberally insert
|
||||
links to existing (or new) Org-roam notes with `org-roam-insert`.
|
||||
Entering a non-existent title will also create a new note with that
|
||||
title.
|
||||
|
||||

|
||||
|
||||
It is crucial for good usage of Org-roam to insert links liberally,
|
||||
where you want them the notes to resurface!
|
||||
|
||||
## The Org-roam Buffer
|
||||
|
||||
All of Org-roam's operations are designed such that the built cache is
|
||||
a consistent view of the inter-connectivity between your notes. The
|
||||
Org-roam buffer shows backlinks: i.e. the files that link to the
|
||||
currently viewed file, along with some surrounding context. The
|
||||
Org-roam buffer will always show the backlinks for the current
|
||||
Org-roam file in view.
|
||||
|
||||

|
||||
|
||||
These file links also form a graph. The generated graph is navigable
|
||||
in Emacs.
|
||||
## Exporting the Graph
|
||||
|
||||
It's also possible to export the links as a graph, using graphviz. The
|
||||
generated graph is navigable in Emacs, but requires some additional
|
||||
setup, which I describe in the [Graph Appendix][appendix:graph-setup]
|
||||
page.
|
||||
|
||||

|
||||
|
||||
[zettelkasten]: https://zettelkasten.de/
|
||||
[appendix:ntw]: notetaking_workflow.md
|
||||
[appendix:graph-setup]: graph_setup.md
|
||||
[roam]: https://www.roamresearch.com/
|
||||
[jethro-blog-post]: https://blog.jethro.dev/posts/how_to_take_smart_notes_org/
|
||||
|
@ -7,8 +7,11 @@ nav:
|
||||
- Home: index.md
|
||||
- A Tour of Org-Roam: tour.md
|
||||
- Installation: installation.md
|
||||
- Configuration: configuration.md
|
||||
- Ecosystem: ecosystem.md
|
||||
- Similar Packages: comparison.md
|
||||
- "Appendix: Note-taking Workflow": notetaking_workflow.md
|
||||
- "Appendix: Graph Setup": graph_setup.md
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
- pymdownx.betterem:
|
||||
|
169
org-roam-utils.el
Normal file
169
org-roam-utils.el
Normal file
@ -0,0 +1,169 @@
|
||||
;;; org-roam-utils.el --- Roam Research replica with Org-mode -*- coding: utf-8; lexical-binding: t -*-
|
||||
|
||||
;; Copyright © 2020 Jethro Kuan <jethrokuan95@gmail.com>
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; URL: https://github.com/jethrokuan/org-roam
|
||||
;; Keywords: org-mode, roam, convenience
|
||||
;; Version: 0.1.2
|
||||
;; Package-Requires: ((emacs "26.1"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 3, or (at your option)
|
||||
;; any later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs; see the file COPYING. If not, write to the
|
||||
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
;; Boston, MA 02110-1301, USA.
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; This library is an attempt at injecting Roam functionality into Org-mode.
|
||||
;; This is achieved primarily through building caches for forward links,
|
||||
;; backward links, and file titles.
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(require 'org)
|
||||
(require 'org-element)
|
||||
(require 'subr-x)
|
||||
(require 'cl-lib)
|
||||
|
||||
(defun org-roam--file-name-extension (filename)
|
||||
"Return file name extension for FILENAME.
|
||||
|
||||
Like file-name-extension, but does not strip version number."
|
||||
(save-match-data
|
||||
(let ((file (file-name-nondirectory filename)))
|
||||
(if (and (string-match "\\.[^.]*\\'" file)
|
||||
(not (eq 0 (match-beginning 0))))
|
||||
(substring file (+ (match-beginning 0) 1))))))
|
||||
|
||||
(defun org-roam--org-file-p (path)
|
||||
"Check if PATH is pointing to an org file."
|
||||
(let ((ext (org-roam--file-name-extension path)))
|
||||
(or (string= ext "org")
|
||||
(and
|
||||
(string= ext "gpg")
|
||||
(string= (org-roam--file-name-extension (file-name-sans-extension path)) "org")))))
|
||||
|
||||
(defun org-roam--find-files (dir)
|
||||
"Return all `org-roam' files in `DIR'."
|
||||
(if (file-exists-p dir)
|
||||
(let ((files (directory-files dir t "." t))
|
||||
(dir-ignore-regexp (concat "\\(?:"
|
||||
"\\."
|
||||
"\\|\\.\\."
|
||||
"\\)$"))
|
||||
result)
|
||||
(dolist (file files)
|
||||
(cond
|
||||
((file-directory-p file)
|
||||
(when (not (string-match dir-ignore-regexp file))
|
||||
(setq result (append (org-roam--find-files file) result))))
|
||||
((and (file-readable-p file)
|
||||
(org-roam--org-file-p file))
|
||||
(setq result (cons (file-truename file) result)))))
|
||||
result)))
|
||||
|
||||
(defun org-roam--parse-content (&optional file-path)
|
||||
"Parse the current buffer, and return a list of items for processing."
|
||||
(org-element-map (org-element-parse-buffer) 'link
|
||||
(lambda (link)
|
||||
(let ((type (org-element-property :type link))
|
||||
(path (org-element-property :path link))
|
||||
(start (org-element-property :begin link)))
|
||||
(when (and (string= type "file")
|
||||
(org-roam--org-file-p path))
|
||||
(goto-char start)
|
||||
(let* ((element (org-element-at-point))
|
||||
(begin (or (org-element-property :content-begin element)
|
||||
(org-element-property :begin element)))
|
||||
(content (or (org-element-property :raw-value element)
|
||||
(buffer-substring
|
||||
begin
|
||||
(or (org-element-property :content-end element)
|
||||
(org-element-property :end element)))))
|
||||
(content (string-trim content))
|
||||
(file-path (or file-path
|
||||
(file-truename (buffer-file-name (current-buffer))))))
|
||||
(list :from file-path
|
||||
:to (file-truename (expand-file-name path (file-name-directory file-path)))
|
||||
:properties (list :content content :point begin))))))))
|
||||
|
||||
(cl-defun org-roam--insert-item (item &key forward backward)
|
||||
"Insert ITEM into FORWARD and BACKWARD cache.
|
||||
|
||||
ITEM is of the form: (:from from-path :to to-path :properties (:content preview-content :point point))."
|
||||
(pcase-let ((`(:from ,p-from :to ,p-to :properties ,props) item))
|
||||
;; Build forward-links
|
||||
(let ((links (gethash p-from forward)))
|
||||
(if links
|
||||
(puthash p-from
|
||||
(if (member p-to links)
|
||||
links
|
||||
(cons p-to links)) forward)
|
||||
(puthash p-from (list p-to) forward)))
|
||||
;; Build backward-links
|
||||
(let ((contents-hash (gethash p-to backward)))
|
||||
(if contents-hash
|
||||
(if-let ((contents-list (gethash p-from contents-hash)))
|
||||
(let ((updated (cons props contents-list)))
|
||||
(puthash p-from updated contents-hash)
|
||||
(puthash p-to contents-hash backward))
|
||||
(progn
|
||||
(puthash p-from (list props) contents-hash)
|
||||
(puthash p-to contents-hash backward)))
|
||||
(let ((contents-hash (make-hash-table :test #'equal)))
|
||||
(puthash p-from (list props) contents-hash)
|
||||
(puthash p-to contents-hash backward))))))
|
||||
|
||||
(defun org-roam--extract-title ()
|
||||
"Extract the title from `BUFFER'."
|
||||
(org-element-map
|
||||
(org-element-parse-buffer)
|
||||
'keyword
|
||||
(lambda (kw)
|
||||
(when (string= (org-element-property :key kw) "TITLE")
|
||||
(org-element-property :value kw)))
|
||||
:first-match t))
|
||||
|
||||
(defun org-roam--build-cache (dir)
|
||||
"Build the org-roam caches in DIR."
|
||||
(let ((backward-links (make-hash-table :test #'equal))
|
||||
(forward-links (make-hash-table :test #'equal))
|
||||
(file-titles (make-hash-table :test #'equal)))
|
||||
(let* ((org-roam-files (org-roam--find-files dir))
|
||||
(file-items (mapcar (lambda (file)
|
||||
(with-temp-buffer
|
||||
(insert-file-contents file)
|
||||
(org-roam--parse-content file))) org-roam-files)))
|
||||
(dolist (items file-items)
|
||||
(dolist (item items)
|
||||
(org-roam--insert-item
|
||||
item
|
||||
:forward forward-links
|
||||
:backward backward-links)))
|
||||
(dolist (file org-roam-files)
|
||||
(with-temp-buffer
|
||||
(insert-file-contents file)
|
||||
(when-let ((title (org-roam--extract-title)))
|
||||
(puthash file title file-titles)))
|
||||
org-roam-files))
|
||||
(list
|
||||
:forward forward-links
|
||||
:backward backward-links
|
||||
:titles file-titles)))
|
||||
|
||||
(provide 'org-roam-utils)
|
||||
|
||||
;;; org-roam-utils.el ends here
|
829
org-roam.el
829
org-roam.el
File diff suppressed because it is too large
Load Diff
10
shell.nix
10
shell.nix
@ -1,10 +0,0 @@
|
||||
let
|
||||
pkgs = import <nixpkgs> {};
|
||||
in
|
||||
pkgs.mkShell {
|
||||
name = "docs";
|
||||
buildInput = with pkgs; [
|
||||
mkdocs
|
||||
python3Packages.alabaster
|
||||
];
|
||||
}
|
7
tests/roam-files/f1.org
Normal file
7
tests/roam-files/f1.org
Normal file
@ -0,0 +1,7 @@
|
||||
#+TITLE: File 1
|
||||
|
||||
link to [[file:nested/f1.org][Nested File 1]]
|
||||
link to [[file:f2.org][File 2]]
|
||||
|
||||
Arbitrary [[https://google.com][HTML]] link
|
||||
Arbitrary text
|
3
tests/roam-files/f2.org
Normal file
3
tests/roam-files/f2.org
Normal file
@ -0,0 +1,3 @@
|
||||
#+TITLE: File 2
|
||||
|
||||
This file has no links.
|
5
tests/roam-files/f3.org
Normal file
5
tests/roam-files/f3.org
Normal file
@ -0,0 +1,5 @@
|
||||
#+TITLE: File 3
|
||||
|
||||
This file has a link to an file with no title.
|
||||
|
||||
[[file:no-title.org][no-title]]
|
4
tests/roam-files/nested/f1.org
Normal file
4
tests/roam-files/nested/f1.org
Normal file
@ -0,0 +1,4 @@
|
||||
#+TITLE: Nested File 1
|
||||
|
||||
Link to [[file:f2.org][Nested File 2]]
|
||||
Link to [[file:../f1.org][File 1]]
|
3
tests/roam-files/nested/f2.org
Normal file
3
tests/roam-files/nested/f2.org
Normal file
@ -0,0 +1,3 @@
|
||||
#+TITLE: Nested File 2
|
||||
|
||||
Link to [[file:f1.org][Nested File 1]]
|
1
tests/roam-files/no-title.org
Normal file
1
tests/roam-files/no-title.org
Normal file
@ -0,0 +1 @@
|
||||
no title in this file :O
|
230
tests/test-org-roam.el
Normal file
230
tests/test-org-roam.el
Normal file
@ -0,0 +1,230 @@
|
||||
;;; test-org-roam.el --- Tests for org-roam -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2020 Jethro Kuan
|
||||
|
||||
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
|
||||
;; Package-Requires: ((buttercup) (with-simulated-input))
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;;
|
||||
|
||||
;;; Code:
|
||||
|
||||
;;;; Requirements
|
||||
|
||||
(require 'buttercup)
|
||||
(require 'with-simulated-input)
|
||||
(require 'org-roam)
|
||||
(require 'dash)
|
||||
|
||||
(defun abs-path (file-path)
|
||||
(file-truename (expand-file-name file-path org-roam-directory)))
|
||||
|
||||
(defun org-roam--test-find-new-file (path)
|
||||
(let ((path (abs-path path)))
|
||||
(make-directory (file-name-directory path) t)
|
||||
(find-file path)))
|
||||
|
||||
(defvar org-roam--tests-directory (file-truename (concat default-directory "tests/roam-files"))
|
||||
"Directory containing org-roam test org files.")
|
||||
|
||||
(defun org-roam--test-init ()
|
||||
(let ((original-dir org-roam--tests-directory)
|
||||
(new-dir (expand-file-name (make-temp-name "org-roam") temporary-file-directory)))
|
||||
(copy-directory original-dir new-dir)
|
||||
(setq org-roam-directory new-dir))
|
||||
(org-roam-mode +1))
|
||||
|
||||
(defun org-roam--test-build-cache ()
|
||||
"Builds the caches synchronously."
|
||||
(let ((cache (org-roam--build-cache org-roam-directory)))
|
||||
(setq org-roam-forward-links-cache (plist-get cache :forward))
|
||||
(setq org-roam-backward-links-cache (plist-get cache :backward))
|
||||
(setq org-roam-titles-cache (plist-get cache :titles))
|
||||
(setq org-roam-cache-initialized t)))
|
||||
|
||||
;;; Tests
|
||||
(describe "org-roam--build-cache-async"
|
||||
(it "initializes correctly"
|
||||
(org-roam--test-init)
|
||||
(expect org-roam-cache-initialized :to-be nil)
|
||||
(expect (hash-table-count org-roam-forward-links-cache) :to-be 0)
|
||||
(expect (hash-table-count org-roam-backward-links-cache) :to-be 0)
|
||||
(expect (hash-table-count org-roam-titles-cache) :to-be 0)
|
||||
|
||||
(org-roam--build-cache-async)
|
||||
(sleep-for 3) ;; Because it's async
|
||||
|
||||
;; Caches should be populated
|
||||
(expect org-roam-cache-initialized :to-be t)
|
||||
(expect (hash-table-count org-roam-forward-links-cache) :to-be 4)
|
||||
(expect (hash-table-count org-roam-backward-links-cache) :to-be 5)
|
||||
(expect (hash-table-count org-roam-titles-cache) :to-be 5)
|
||||
|
||||
;; Forward cache
|
||||
(let ((f1 (gethash (abs-path "f1.org") org-roam-forward-links-cache))
|
||||
(f2 (gethash (abs-path "f2.org") org-roam-forward-links-cache))
|
||||
(nested-f1 (gethash (abs-path "nested/f1.org") org-roam-forward-links-cache))
|
||||
(nested-f2 (gethash (abs-path "nested/f2.org") org-roam-forward-links-cache))
|
||||
(expected-f1 (list (abs-path "nested/f1.org")
|
||||
(abs-path "f2.org")))
|
||||
(expected-nested-f1 (list (abs-path "nested/f2.org")
|
||||
(abs-path "f1.org")))
|
||||
(expected-nested-f2 (list (abs-path "nested/f1.org"))))
|
||||
|
||||
(expect f1 :to-have-same-items-as expected-f1)
|
||||
(expect f2 :to-be nil)
|
||||
(expect nested-f1 :to-have-same-items-as expected-nested-f1)
|
||||
(expect nested-f2 :to-have-same-items-as expected-nested-f2))
|
||||
|
||||
;; Backward cache
|
||||
(let ((f1 (hash-table-keys (gethash (abs-path "f1.org") org-roam-backward-links-cache)))
|
||||
(f2 (hash-table-keys (gethash (abs-path "f2.org") org-roam-backward-links-cache)))
|
||||
(nested-f1 (hash-table-keys(gethash (abs-path "nested/f1.org") org-roam-backward-links-cache)))
|
||||
(nested-f2 (hash-table-keys (gethash (abs-path "nested/f2.org") org-roam-backward-links-cache)))
|
||||
(expected-f1 (list (abs-path "nested/f1.org")))
|
||||
(expected-f2 (list (abs-path "f1.org")))
|
||||
(expected-nested-f1 (list (abs-path "nested/f2.org")
|
||||
(abs-path "f1.org")))
|
||||
(expected-nested-f2 (list (abs-path "nested/f1.org"))))
|
||||
(expect f1 :to-have-same-items-as expected-f1)
|
||||
(expect f2 :to-have-same-items-as expected-f2)
|
||||
(expect nested-f1 :to-have-same-items-as expected-nested-f1)
|
||||
(expect nested-f2 :to-have-same-items-as expected-nested-f2))
|
||||
|
||||
;; Titles Cache
|
||||
(expect (gethash (abs-path "f1.org") org-roam-titles-cache) :to-equal "File 1")
|
||||
(expect (gethash (abs-path "f2.org") org-roam-titles-cache) :to-equal "File 2")
|
||||
(expect (gethash (abs-path "nested/f1.org") org-roam-titles-cache) :to-equal "Nested File 1")
|
||||
(expect (gethash (abs-path "nested/f2.org") org-roam-titles-cache) :to-equal "Nested File 2")
|
||||
(expect (gethash (abs-path "no-title.org") org-roam-titles-cache) :to-be nil)))
|
||||
|
||||
(describe "org-roam-insert"
|
||||
(before-each
|
||||
(org-roam--test-init)
|
||||
(org-roam--clear-cache)
|
||||
(org-roam--test-build-cache))
|
||||
|
||||
(it "temp1 -> f1"
|
||||
(let ((buf (org-roam--test-find-new-file "temp1.org")))
|
||||
(with-current-buffer buf
|
||||
(with-simulated-input
|
||||
"File SPC 1 RET"
|
||||
(org-roam-insert nil))))
|
||||
(expect (buffer-string) :to-match (regexp-quote "file:f1.org")))
|
||||
|
||||
(it "temp2 -> nested/f1"
|
||||
(let ((buf (org-roam--test-find-new-file "temp2.org")))
|
||||
(with-current-buffer buf
|
||||
(with-simulated-input
|
||||
"Nested SPC File SPC 1 RET"
|
||||
(org-roam-insert nil))))
|
||||
(expect (buffer-string) :to-match (regexp-quote "file:nested/f1.org")))
|
||||
|
||||
(it "nested/temp3 -> f1"
|
||||
(let ((buf (org-roam--test-find-new-file "nested/temp3.org")))
|
||||
(with-current-buffer buf
|
||||
(with-simulated-input
|
||||
"File SPC 1 RET"
|
||||
(org-roam-insert nil))))
|
||||
(expect (buffer-string) :to-match (regexp-quote "file:../f1.org")))
|
||||
|
||||
(it "a/b/temp4 -> nested/f1"
|
||||
(let ((buf (org-roam--test-find-new-file "a/b/temp4.org")))
|
||||
(with-current-buffer buf
|
||||
(with-simulated-input
|
||||
"Nested SPC File SPC 1 RET"
|
||||
(org-roam-insert nil))))
|
||||
(expect (buffer-string) :to-match (regexp-quote "file:../../nested/f1.org"))))
|
||||
|
||||
(describe "rename file updates cache"
|
||||
(before-each
|
||||
(org-roam--test-init)
|
||||
(org-roam--clear-cache)
|
||||
(org-roam--test-build-cache))
|
||||
|
||||
(it "f1 -> new_f1"
|
||||
(rename-file (abs-path "f1.org")
|
||||
(abs-path "new_f1.org"))
|
||||
;; Cache should be cleared of old file
|
||||
(expect (gethash (abs-path "f1.org") org-roam-forward-links-cache) :to-be nil)
|
||||
(expect (->> org-roam-backward-links-cache
|
||||
(gethash (abs-path "nested/f1.org"))
|
||||
(hash-table-keys)
|
||||
(member (abs-path "f1.org"))) :to-be nil)
|
||||
|
||||
(expect (->> org-roam-forward-links-cache
|
||||
(gethash (abs-path "new_f1.org"))) :not :to-be nil)
|
||||
|
||||
(expect (->> org-roam-forward-links-cache
|
||||
(gethash (abs-path "new_f1.org"))
|
||||
(member (abs-path "nested/f1.org"))) :not :to-be nil)
|
||||
;; Links are updated
|
||||
(expect (with-temp-buffer
|
||||
(insert-file-contents (abs-path "nested/f1.org"))
|
||||
(buffer-string)) :to-match (regexp-quote "[[file:../new_f1.org][File 1]]")))
|
||||
|
||||
|
||||
(it "f1 -> f1 with spaces"
|
||||
(rename-file (abs-path "f1.org")
|
||||
(abs-path "f1 with spaces.org"))
|
||||
;; Cache should be cleared of old file
|
||||
(expect (gethash (abs-path "f1.org") org-roam-forward-links-cache) :to-be nil)
|
||||
(expect (->> org-roam-backward-links-cache
|
||||
(gethash (abs-path "nested/f1.org"))
|
||||
(hash-table-keys)
|
||||
(member (abs-path "f1.org"))) :to-be nil)
|
||||
;; Links are updated
|
||||
(expect (with-temp-buffer
|
||||
(insert-file-contents (abs-path "nested/f1.org"))
|
||||
(buffer-string)) :to-match (regexp-quote "[[file:../f1 with spaces.org][File 1]]")))
|
||||
|
||||
(it "no-title -> meaningful-title"
|
||||
(rename-file (abs-path "no-title.org")
|
||||
(abs-path "meaningful-title.org"))
|
||||
;; File has no forward links
|
||||
(expect (gethash (abs-path "no-title.org") org-roam-forward-links-cache) :to-be nil)
|
||||
(expect (gethash (abs-path "meaningful-title.org") org-roam-forward-links-cache) :to-be nil)
|
||||
|
||||
(expect (->> org-roam-forward-links-cache
|
||||
(gethash (abs-path "f3.org"))
|
||||
(member (abs-path "no-title.org"))) :to-be nil)
|
||||
|
||||
(expect (->> org-roam-forward-links-cache
|
||||
(gethash (abs-path "f3.org"))
|
||||
(member (abs-path "meaningful-title.org"))) :not :to-be nil)
|
||||
|
||||
;; Links are updated with the appropriate name
|
||||
(expect (with-temp-buffer
|
||||
(insert-file-contents (abs-path "f3.org"))
|
||||
(buffer-string)) :to-match (regexp-quote "[[file:meaningful-title.org][meaningful-title]]"))))
|
||||
|
||||
(describe "delete file updates cache"
|
||||
(before-each
|
||||
(org-roam--test-init)
|
||||
(org-roam--clear-cache)
|
||||
(org-roam--test-build-cache))
|
||||
(it "delete f1"
|
||||
(delete-file (abs-path "f1.org"))
|
||||
(expect (->> org-roam-forward-links-cache
|
||||
(gethash (abs-path "f1.org"))) :to-be nil)
|
||||
(expect (->> org-roam-backward-links-cache
|
||||
(gethash (abs-path "nested/f1.org"))
|
||||
(gethash (abs-path "f1.org"))) :to-be nil)
|
||||
(expect (->> org-roam-backward-links-cache
|
||||
(gethash (abs-path "nested/f1.org"))
|
||||
(gethash (abs-path "nested/f2.org"))) :not :to-be nil)))
|
Reference in New Issue
Block a user