这是我的 org-roam 配置,不需要理解,只需要你安装好 org-roam 和 org-roam-ui,学会开头几行设置的几个快捷键就可以了。
我目前也就用了C-c n f
C-c n i
C-c n a
C-c n t
和 org-roam-ui-open 的 C-c G
五个快捷键。
新手最重要的是先用起来再去理解。安装好插件之后,先抄能把插件功能跑起来的那部分代码。不要把事情搞复杂,想着一次性配置完美。
我短短几个月重新写了两遍配置,理解代码真的很痛苦。
我的建议就是:先用起来,等功能不够了再改配置。
;; org-roam: basic config
;; {{{
(use-package org-roam
:ensure t
:defer t ;; autoload
:bind (
("C-c n a" . org-roam-alias-add)
("C-c n c" . org-roam-capture)
("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 j" . org-roam-dailies-capture-today) ;; Dailies
("C-c n l" . org-roam-buffer-toggle)
("C-c n t" . org-roam-tag-add)
)
:config
(setq org-roam-directory "~/org-roam")
(setq org-roam-db-location "~/org-roam/org-roam.db")
(setq org-roam-file-extensions '("org" "md")) ;; enable Org-roam for markdown
(require 'org-roam-protocol) ;; org-roam-protocol
(org-roam-db-autosync-mode 1) ;; if md-roam installed, move to md-roam config
)
;; }}}
;; org-roam: backlink count & node hierarchy
;; {{{
;; https://github.com/Jousimies/.emacs.d/blob/master/lisp/init-roam.el
(require 'org)
(require 'org-roam)
;;
(cl-defmethod org-roam-node-directories ((node org-roam-node))
(if-let ((dirs (file-name-directory (file-relative-name (org-roam-node-file node) org-roam-directory))))
(format "(%s)" (car (split-string dirs "/")))
""))
;;
(cl-defmethod org-roam-node-backlinkscount ((node org-roam-node))
(let* ((count (caar (org-roam-db-query
[:select (funcall count source)
:from links
:where (= dest $s1)
:and (= type "id")]
(org-roam-node-id node)))))
(format "[%d]" count)))
;;
(cl-defmethod org-roam-node-hierarchy ((node org-roam-node))
(let ((level (org-roam-node-level node)))
(concat
(when (> level 0) (concat (org-roam-node-file-title node) " > "))
(when (> level 1) (concat (string-join (org-roam-node-olp node) " > ") " > "))
(org-roam-node-title node))))
;;
(setq org-roam-node-display-template
"${title:50} ${hierarchy:*} ${backlinkscount:6} ${tags:50} ${directories:10}")
;;
;; (setq org-roam-node-display-template (concat
;; "${type:8} ${backlinkscount:3} ${hierarchy:*}"
;; (propertize "${tags:20}" 'face 'org-tag) " "))
;;
;; (setq org-roam-node-display-template "${hierarchy:*} ${tags:20}")
;;
;; (setq org-roam-node-display-template
;; (concat "${title:*} "
;; (propertize "${tags:10}" 'face 'org-tag)
;; ))
;; }}}
;; org-roam: completion
;; {{{
(setq org-roam-completion-everywhere t)
;;roam links support auto-completion via completion-at-point
;; call M-x completion-at-point within a roam link.
;; Where the | character represents the cursor:
;; [[|]] : completes for a file title
;; [[roam:]] : completes for a file title
;; [[*|]] : completes for a headline within this file
;; [[foo*|]] : completes a headline within the file with title “foo”
;; [[roam:foo*|]] completes a headline within the file with title “foo”
;; }}}
;; org-roam: slug (called by org-roam-capture-templates)
;; {{{
;; (cl-defmethod org-roam-node-slug ((node org-roam-node))
;; "Return the slug of NODE."
;; (let ((title (org-roam-node-title node))
;; (slug-trim-chars '(;; Combining Diacritical Marks https://www.unicode.org/charts/PDF/U0300.pdf
;; 768 ; U+0300 COMBINING GRAVE ACCENT
;; 769 ; U+0301 COMBINING ACUTE ACCENT
;; 770 ; U+0302 COMBINING CIRCUMFLEX ACCENT
;; 771 ; U+0303 COMBINING TILDE
;; 772 ; U+0304 COMBINING MACRON
;; 774 ; U+0306 COMBINING BREVE
;; 775 ; U+0307 COMBINING DOT ABOVE
;; 776 ; U+0308 COMBINING DIAERESIS
;; 777 ; U+0309 COMBINING HOOK ABOVE
;; 778 ; U+030A COMBINING RING ABOVE
;; 780 ; U+030C COMBINING CARON
;; 795 ; U+031B COMBINING HORN
;; 803 ; U+0323 COMBINING DOT BELOW
;; 804 ; U+0324 COMBINING DIAERESIS BELOW
;; 805 ; U+0325 COMBINING RING BELOW
;; 807 ; U+0327 COMBINING CEDILLA
;; 813 ; U+032D COMBINING CIRCUMFLEX ACCENT BELOW
;; 814 ; U+032E COMBINING BREVE BELOW
;; 816 ; U+0330 COMBINING TILDE BELOW
;; 817 ; U+0331 COMBINING MACRON BELOW
;; )))
;; (cl-flet* ((nonspacing-mark-p (char)
;; (memq char slug-trim-chars))
;; (strip-nonspacing-marks (s)
;; (ucs-normalize-NFC-string
;; (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)))
;; (downcase slug)))))
;; }}}
;; org-roam: filter tags
;; {{{
(defun my/org-roam-filter-by-tag (tag-name)
(lambda (node)
(member tag-name (org-roam-node-tags node))))
(defun my/org-roam-list-notes-by-tag (tag-name)
(mapcar #'org-roam-node-file
(seq-filter
(my/org-roam-filter-by-tag tag-name)
(org-roam-node-list))))
;; }}}
;; org-roam: search tag
;; {{{
(defun my/org-roam-node-find-by-tag ()
(interactive)
(let ((chosen-tag
(completing-read "filter by tag: "
(seq-uniq
(org-roam-db-query
[:select [tag]
:from tags ])))))
(org-roam-node-find
nil
nil
(lambda (node) (member chosen-tag (org-roam-node-tags node))))))
;; }}}
;; org-roam: template, id (uuid) timestamps and so on
;; {{{
(setq org-roam-capture-templates
'(
;; #+date: %<%Y-%m-%d-%H:%M:%S %Z>\n
;; #+date: %<%FT%T%z>\n
;; a: audio & music
;; b: book
("b" "图书" plain "%?"
:target (file+head "图书/${title}.org"
"#+title: ${title}\n#+date: %<%FT%T%z>\n#+category:\n#+filetags: \n")
:immediate-finish t
:unnarrowed t)
("bz" "Z综合性图书" plain "%?"
:target (file+head "图书/Z综合性图书/${title}.org"
"#+title: ${title}\n#+date: %<%FT%T%z>\n#+category:\n#+filetags: \n")
:immediate-finish t
:unnarrowed t)
;; c:
("d" "default" plain "%?"
:target (file+head "${slug}.org"
"#+title: ${title}\n#+date: %<%FT%T%z>\n#+category:\n#+filetags:\n")
:empty-lines 1
:immediate-finish t
:unnarrowed t)
("e" "Emacs" plain "%?"
:target (file+head "Emacs/${slug}.org"
"#+title: ${title}\n#+date: %<%FT%T%z>\n#+category:\n#+filetags: \n")
:immediate-finish t
:unnarrowed t)
;; f:
("f" "Emacs Function" plain "%?"
:target (file+head "Emacs/function/${slug}.org"
"#+title: ${title}\n#+date: %<%FT%T%z>\n#+category:\n#+filetags: \n")
:immediate-finish t
:unnarrowed t)
;; g:
;; h: human
;; i:
;; j:
;; k:
;; l:
;; m:
;; n:
;; o:
;; p: project
("p" "project" plain "%?"
:target (file+head "${slug}.org"
"#+title: ${title}\n#+date: %<%FT%T%z>\n")
:immediate-finish t
:unnarrowed t)
("P" "Emacs 包/插件" plain "%?"
:target (file+head "Emacs/package/${title}.org"
"#+title: ${title}\n#+date: %<%FT%T%z>\n#+filetags: :Emacs:\n")
:immediate-finish t
:unnarrowed t)
;; q:
("r" "reference" plain "%?"
:target (file+head "reference/${title}-%<%FT%T%z>.org"
"#+title: ${title}\n#+date: %<%FT%T%z>\n")
:unnarrowed t)
;; s:
("s" "软件" plain "%?"
:target (file+head "software/${slug}.org"
"#+title: ${title}\n#+date: %<%FT%T%z>\n")
:immediate-finish t
:unnarrowed t)
;; t: topic todo
("t" "主题" plain "%?"
:target (file+head "topics/${slug}.org"
"#+title: ${title}\n#+date: %<%FT%T%z>\n")
:immediate-finish t
:unnarrowed t)
;; u:
;; v:
("v" "Emacs 变量" plain "%?"
:target (file+head "Emacs/variable/${slug}.org"
"#+title: ${title}\n#+date: %<%FT%T%z>\n")
:immediate-finish t
:unnarrowed t)
;; w:
;; x:
;; y:
;; z:
))
;; }}}
;; org-roam: UI
;; {{{
;; (custom-set-faces
;; '((org-roam-link org-roam-link-current)
;; :foreground "#e24888" :underline t))
;;
;; (defface my-org-id-link '((t :inherit org-link :slant italic))
;; "Face for org-id links."
;; :group 'org-faces)
;; }}}
;; little hack
;; {{{
;; brew install --cask db-browser-for-sqlite
(defun my/org-roam-view-db ()
(interactive)
(cond
((eq system-type 'darwin)
(shell-command
;; net.sourceforge.sqlitebrowser
(format "open \"/Applications/DB Browser for SQLite.app\" --args --table nodes %s" org-roam-db-location)))
(t
(message "my/org-roam-view-db not yet working on this system-type"))))
;; }}}
;; org-roam-ui
;; {{{
(use-package org-roam-ui
:after org-roam
;; normally we'd recommend hooking orui after org-roam, but since org-roam does not have
;; a hookable mode anymore, you're advised to pick something yourself
;; if you don't care about startup time, use
;; :hook (after-init . org-roam-ui-mode)
:bind (("C-c G" . org-roam-ui-open)
)
:config
(setq org-roam-ui-sync-theme t
org-roam-ui-follow t
org-roam-ui-update-on-save t
org-roam-ui-open-on-start t)
)
;; }}}