Org-roam

概要

Org-roamはRoam Research1の非公式なEmacs版。 org-modeをベースに、目的ファイルへのアクセスしやすさ、リンク、グラフ化の機能を強化する。 文書のトップページInsomniaのグラフは、org-roamが生成するsqliteレコードを加工して作成している。

GitHubリポジトリ
https://github.com/org-roam/org-roam
公式サイト
https://www.orgroam.com/
マニュアル
https://www.orgroam.com/manual.html

Memo

db関連がおかしくなったとき

dbへ書き込みできませんエラーが出たとき。

  • (org-roam-db-location) でDBが保存されているパスを調べる。
  • .dbファイルを削除。
  • (org-roam-db-clear-all) でキャッシュ削除。
  • (org-roam-db-sync) によってdbファイルを再作成。

Selecting deleted buffer が出るとき。

  • ライブラリをすべて削除してインストールし直す
  • emacsql-sqliteを保存しているディレクトリに行く。sqliteディレクトリ下でmakeしなおす
    • make clean && make emacsql-sqlite

バックエンドの違いを吸収する関数

いわゆるコネクターパターン。接続に使用する関数を返す関数。

(defun org-roam-db–conn-fn () “Return the function for creating the database connection.” (cl-case org-roam-database-connector (sqlite (progn (require ’emacsql-sqlite) #’emacsql-sqlite)) (libsqlite3 (progn (require ’emacsql-libsqlite3) #’emacsql-libsqlite3)) (sqlite3 (progn (require ’emacsql-sqlite3) #’emacsql-sqlite3))))

Tasks

References

Org-roam User Manual

マニュアル。

Org mode 教室 その9: org-roam でアイデアをひねり出す

具体的なワークフローがわかりやすい。

https://blog.jethro.dev/posts/introducing_org_roam/

作者サイトのマニュアル。

Archives

CLOSE CI, sqliteを入れて試してみる

  • search emacsql

Default install sqlite on ubuntu, so does not matter.

DONE 基本的キーバインド

  • find(C-c n f)
  • バックリンク(C-c n l)
  • Roamリンク挿入(C-c n i)補完を有効にすることであまり使わなくなる。

DONE idリンクをpublishできない問題

roamのidがhtmlに変換できないよう。

Unable to resolve link

になる。

(setq org-hugo-base-dir ".")
(setq org-export-with-broken-links t)

するとできるが、idリンクを辿れない。 ほかのサイトではidがあってもできてるように見える。 https://hugocisneros.com/blog/my-org-roam-notes-workflow/ orgのバージョンを最新にしたが変わらず。

公式で言及。 https://github.com/org-roam/org-roam/wiki/Hitchhiker's-Rough-Guide-to-Org-roam-V2#export

(setq org-id-link-to-org-use-id t)
(setq org-id-extra-files (org-roam--list-files org-roam-directory))

↓で設定していた。これを設定すると成功した。 https://hugocisneros.com/org-config/#configuration

https://gist.github.com/hugcis/1f2d2ad4b98b07ee543f10232ba1b025

(require 'find-lisp)
(defun hugcis/publish-note (file)
  "Publish a note in FILE."
  (interactive)
  (with-current-buffer (find-file-noselect file)
    (projectile-mode -1)
    (setq org-hugo-section "notes"
          org-hugo-base-dir "."
          citeproc-org-org-bib-header "* Bibliography\n<ol class=\"biblio-list\">"
          citeproc-org-org-bib-footer "</ol>")
    (let ((org-id-extra-files (find-lisp-find-files org-roam-directory "\.org$")))
        (org-hugo-export-wim-to-md))))
find . -name '*.org' | emacs --batch -l ./publish.el --funcall kd/publish

DONE 初期設定

⚠バージョンが上がって設定が変わった。この内容は古い。 roamのデフォルトディレクトリを作成して、そこでファイルが作成されたり、検索対象になる。

(require 'org-roam)
(add-hook 'after-init-hook 'org-roam-mode)
(make-directory "~/roam" t)
(setq org-roam-directory "~/roam")
(setq org-roam-completion-everywhere t)
(define-key org-mode-map (kbd "C-M-i") 'completion-at-point)

リンク補完が有効になります。非常に便利。

(define-key org-roam-mode-map (kbd "C-c n l") 'org-roam)
(define-key org-roam-mode-map (kbd "C-c n f") 'org-roam-find-file)
(define-key org-roam-mode-map (kbd "C-c n g") 'org-roam-graph)
(define-key org-mode-map (kbd "C-c n i") 'org-roam-insert)
(define-key org-mode-map (kbd "C-c n I") 'org-roam-insert-immediate)

DONE 外部リンクをグラフに表示したくない

org-roam-graph でファイルリンクだけのつながりを表示したい。 v1ではファイルリンクだけで、外部リンクは出てなくてわかりやすかった。

org-roam-uiを使ってみた。めちゃかっこいい。

org-roam-graph-link-hidden-types でhttp, httpsを指定すると消せた。 これでCIでも出力できるはず。

(setq org-roam-graph-link-hidden-types '("https" "http" "file"))

DONE d3でのグラフ出力

  1. org-roam-db-syncでdbファイルを生成する
  2. dbファイルをグラフとしてjsonに変換する
  3. JavaScriptのd3ライブラリでjsonを読み込む
  4. ブラウザ描画

CLOSE Selecting deleted bufferエラー

新しく構築した環境にて、 (org-roam-db-sync) をやると Selecting deleted buffer がエラーが出る。 依存しているemacs-sqlite関係でなにかおかしくなっているよう。同じくemacs-sqliteに依存しているmagit-forgeも動かない。

メインマシン、GitHub Actions環境ではうまくいっているので、sqlite関係か、.emacs.dで何か起きている。 うまくいくようになった。関連ライブラリが修正されたよう。

DONE dbを使って何をしているのか   DontKnow

デフォルトではsqliteを利用しているのは知っているが、実際何をしているのだろうか。結論: ファイルの変更をdbに同期し、再利用しやすいようにしている。

まずorg-roam-db.elを見てみる。

;;; Database API ;;;; Clearing (defun org-roam-db-clear-all () “Clears all entries in the Org-roam cache.” (interactive) (when (file-exists-p org-roam-db-location) (dolist (table (mapcar #’car org-roam-db–table-schemata)) (org-roam-db-query `[:delete :from ,table]))))

(defun org-roam-db-clear-file (&optional file)

(defun org-roam-db-insert-file () “Update the files table for the current buffer. If UPDATE-P is non-nil, first remove the file in the database.” (let* ((file (buffer-file-name)) (file-title (org-roam-db–file-title)) (attr (file-attributes file)) (atime (file-attribute-access-time attr)) (mtime (file-attribute-modification-time attr)) (hash (org-roam-db–file-hash))) (org-roam-db-query [:insert :into files :values $v1] (list (vector file file-title hash atime mtime)))))

(defun org-roam-db-get-scheduled-time ()

org-roam-db-insert-fileが呼ばれることによって、orgファイルの追加をdbと同期する。こういった感じで1ファイルの追加、削除、変更に対応する同期関数がある。

↑のみでは1ファイルのみなので、org-roamファイル全体に大して同期をかける関数がある。org-roam-db-sync。変更のタイプを判定して、各関数で処理し、orgファイルとdbの内容を同期する。なるほど。

(defun org-roam-db-sync (&optional force) “Synchronize the cache state with the current Org files on-disk. If FORCE, force a rebuild of the cache from scratch.” (interactive “P”) (org-roam-db–close) ;; Force a reconnect (when force (delete-file org-roam-db-location)) (org-roam-db) ;; To initialize the database, no-op if already initialized (org-roam-require ’(org-ref oc)) (let* ((gc-cons-threshold org-roam-db-gc-threshold) (org-agenda-files nil) (org-roam-files (org-roam-list-files)) (current-files (org-roam-db–get-current-files)) (modified-files nil)) (dolist (file org-roam-files) (let ((contents-hash (org-roam-db–file-hash file))) (unless (string= (gethash file current-files) contents-hash) (push file modified-files))) (remhash file current-files)) (emacsql-with-transaction (org-roam-db) (org-roam-dolist-with-progress (file (hash-table-keys current-files)) “Clearing removed files…” (org-roam-db-clear-file file)) (org-roam-dolist-with-progress (file modified-files) “Processing modified files…” (condition-case err (org-roam-db-update-file file ’no-require) (error (org-roam-db-clear-file file) (lwarn ’org-roam :error “Failed to process %s with error %s, skipping…” file (error-message-string err))))))))

;;;###autoload

直にdbに追加する関数を呼ぶことはなく、ファイルの変更をもとに同期関数経由でdbに追加されるようだ。ファイルの方が先に存在していて、後でdbと同期する。

;;;###autoload (cl-defun org-roam-node-find (&optional other-window initial-input filter-fn &key templates) “Find and open an Org-roam node by its title or alias. INITIAL-INPUT is the initial input for the prompt. FILTER-FN is a function to filter out nodes: it takes an `org-roam-node’, and when nil is returned the node will be filtered out. If OTHER-WINDOW, visit the NODE in another window. The TEMPLATES, if provided, override the list of capture templates (see `org-roam-capture-’.)” (interactive current-prefix-arg) (let ((node (org-roam-node-read initial-input filter-fn))) (if (org-roam-node-file node) (org-roam-node-visit node other-window) (org-roam-capture- :node node :templates templates :props ’(:finalize find-file)))))

  • ファイルがあれば、visitを呼び出す
  • ファイルがなければ、作成するためにcaptureを呼び出す。dbと関係することは同期時にやるので、ここでは一切考えなくてよく、責務分離できている

dbへの同期をみた。利用はどうしているのだろうか。

探す系は、org-roam-node.elに含まれている。

;;;###autoload (cl-defun org-roam-node-find (&optional other-window initial-input filter-fn &key templates) “Find and open an Org-roam node by its title or alias. INITIAL-INPUT is the initial input for the prompt. FILTER-FN is a function to filter out nodes: it takes an `org-roam-node’, and when nil is returned the node will be filtered out. If OTHER-WINDOW, visit the NODE in another window. The TEMPLATES, if provided, override the list of capture templates (see `org-roam-capture-’.)” (interactive current-prefix-arg) (let ((node (org-roam-node-read initial-input filter-fn))) (if (org-roam-node-file node) (org-roam-node-visit node other-window) (org-roam-capture- :node node :templates templates :props ’(:finalize find-file)))))

  • nodeが存在していればファイルを開く。そうでなければorg-roam-captureでテンプレート画面を開く
  • 開くときもdbに接続して情報を取ってくるはずだが、コードのどの箇所かわからなかった

DONE メモのとり方について再考

  • denoteとroamの使い分けが微妙
  • 1つの見出しが1つのファイルに属するとは限らない
  • 文章としてあまり読みやすいものではない

脚注

Footnotes:

1

https://roamresearch.com/ Webでのアウトラインツール。