GnoponEmacs
Components
Package Management
(defvar straight-install-script-path
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el")
(setq straight-repository-branch "develop")
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously straight-install-script-path
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
(straight-use-package 'use-package)
User Experience
User Configuration
(setq user-mail-address "emsenn@emsenn.net")
(setq ring-bell-function 'ignore)
(setq make-backup-files nil)
(setq inhibit-startup-message t)
(setq inhibit-startup-screen t)
(setq initial-scratch-message
";; LANDBACK")
(menu-bar-mode -1)
(tool-bar-mode -1)
(show-paren-mode 1)
(setq line-number-mode t)
(setq column-number-mode t)
(setq-default truncate-lines t)
(setq-default line-spacing 1)
(setq sentence-end-double-space nil)
(global-visual-line-mode t)
(setq echo-keystrokes 0.1)
(setq fill-column 68)
(setq mouse-wheel-scroll-amount '(1 ((shift) .1)))
Mixed Pitch Mode
(use-package mixed-pitch
:straight t
:hook
(text-mode . mixed-pitch-mode))
Modus Theme
(use-package modus-themes
:straight t
:config
(load-theme 'modus-vivendi t))
Olivetti
(use-package olivetti
:straight t
:hook
(text-mode . olivetti-mode))
(require 'ucs-normalize)
Recordkeeping
Beancount
(straight-use-package
'(beancount :type git :host github
:repo "beancount/beancount-mode"))
YASnippet
(use-package
yasnippet :straight t
:hook ((text-mode
prog-mode
conf-mode
snippet-mode)
. yas-minor-mode-on)
:custom (yas-snippet-dirs '("~/ems/org/met/yas-snippets")))
Org-mode
Org-mode Configuration
(use-package
org :straight t
:custom
(org-directory "~/ems/org")
(org-startup-folded 'fold)
(org-hide-block-startup 'hideblocks)
(org-catch-invisible-edits 'show-and-error)
(org-agenda-custom-commands
'(("A" "Agenda and TODO"
((agenda "" )
(alltodo "" )))))
(org-agenda-todo-ignore-scheduled 'all)
(org-agenda-files (list "~/ems/org"))
(org-export-with-section-numbers nil)
(org-export-with-smart-quotes nil)
(org-export-with-toc nil)
(org-html-htmlize-output-type 'nil)
(org-html-validation-link nil)
(org-log-done 'time)
(org-log-into-drawer 'LOGBOOK)
(org-image-actual-width '(400))
(org-cite-global-bibliography '("~/ems/bibliography.bib"))
(org-export-global-macros
'(
("nl" . "(eval \"\\n\")")
))
:bind (
("C-c l" . org-store-link)
("C-c a" . org-agenda)
("C-c c" . org-capture)
("C-c t" . org-toggle-link-display)
("C-c C-q" . counsel-org-tag)
)
:defines gpe/emsenn-net-head
:config
;; from https://www.john2x.com/blog/blogging-with-orgmode.html
(defun gpe/org-publish-format-sitemap (title sitemap)
(let ((posts (cdr sitemap)))
(concat
(format "#+title: %s\n" title)
"#+options: timestamp:nil date:nil\n"
(format "#+date: %s\n" (format-time-string "[%Y-%m-%d %a %H:%M:%S]" (current-time)))
(org-list-to-org (cons (car sitemap) posts)))))
(setq gpe/emsenn-net-head
(with-temp-buffer
(insert "<style>\n")
(insert-file-contents "~/ems/org/src/emsenn-net/main.css")
(goto-char (point-max)) ;; move to end before appending
(insert "\n</style>")
(buffer-string)))
(setq gpe/emsenn-net-preamble
(with-temp-buffer
(insert-file-contents "~/ems/org/src/emsenn-net/preamble.html")
(buffer-string)))
(org-babel-do-load-languages 'org-babel-load-languages
'(
(shell . t)
)))
Org-roam
(use-package
org-roam :straight t
:after org
:config
(defvar gpe/org-roam-public-node-files '())
(defun gpe/insert-backlinks (backend)
"Insert backlinks at the end of the buffer before Org export.
BACKEND is the export backend symbol, e.g., 'html or 'latex."
(when (org-export-derived-backend-p backend 'html)
(let ((node (org-roam-node-at-point)))
(when node
(save-excursion
(goto-char (point-max))
(insert "\n* Backlinks\n")
(dolist (ref (org-roam-backlinks-get node))
(let* ((source (org-roam-backlink-source-node ref))
(props (org-roam-node-properties source))
(is-public (string= (cdr (assoc "PUBLIC" props)) "true")))
(when is-public
(insert (format "- [[id:%s][%s]]\n"
(org-roam-node-id source)
(org-roam-node-title source)))))))))))
(defun gpe/org-roam-public-node-files ()
"Return a list of Org-roam files where PUBLIC property is true"
(mapcar #'car
(org-roam-db-query
[:select [file]
:from nodes
:where (like properties '"%public%true%")])))
(defun gpe/org-roam-open-random-node ()
"Open a random Org-roam node from the database."
(interactive)
(let* ((nodes (org-roam-node-list))
(count (length nodes)))
(if (zerop count)
(message "No Org-roam nodes found.")
(let* ((random-index (random count))
(node (nth random-index nodes)))
(org-roam-node-visit node)))))
(defun gpe/apply-capture-properties ()
(let ((properties '(:author :form)))
(dolist (property properties)
(let ((value (plist-get org-capture-current-plist property)))
(when value
(org-set-property (substring (symbol-name property) 1) value))))))
(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)))))
:hook
((org-export-before-processing . gpe/insert-backlinks)
(org-capture-mode . gpe/apply-capture-properties))
:custom
(org-roam-directory (file-truename "~/ems/org"))
(org-roam-dailies-directory ".")
(org-roam-db-extra-links-exclude-keys '((node-property "ROAM_REFS")))
(org-roam-capture-templates
(let ((files (directory-files "~/ems/org/src/gpe/org-roam-capture-templates/" t "\\.el$")))
(mapcar (lambda (file)
(with-temp-buffer
(insert-file-contents file)
(read (buffer-string))))
files)))
(org-publish-project-alist
`(
("emsenn-net" :components ("emsenn-net-all"))
("emsenn-net-all"
:base-directory "~/ems/org"
:exclude ".*\\.org$"
:include ,(gpe/org-roam-public-node-files)
:publishing-function org-html-publish-to-html
:preparation-function gpe/org-publish-prepare-backlinks
:html-doctype "html5"
:html-html5-fancy t
:html-container "section"
:headline-levels 6
:recursive t
:html-divs ((preamble "section" "preamble")
(content "main" "content")
(postamble "section" "postamble"))
:html-head-include-scripts nil
:html-head-include-default-style nil
:html-head ,gpe/emsenn-net-head
:html-format-drawer-function gpe/org-html-format-drawer
:exclude "\\`per/\\|README.org\\|DRAFT\\|PRIVATE"
:with-footnotes t
:with-date nil
:with-timestamps nil
:with-author nil
:publishing-directory "~/ems/pub/emsenn-net"
:makeindex t
:html-preamble ,gpe/emsenn-net-preamble
)
))
:bind (
("C-c n i" . org-roam-node-insert)
("C-c n f" . org-roam-node-find)
("C-c n c" . org-roam-node-capture)
("C-c n d" . org-roam-dailies-capture-today)
("C-c n D" . org-roam-dailies-capture-yesterday)
)
)
Org-transclusion
(use-package
org-transclusion :straight t
:custom
(org-transclusion-exclude-elements '(keyword property-drawer))
:bind (
("C-c n t" . org-transclusion-mode)
("C-c n T" . org-transclusion-add)
))
Publishing
HTMLize
(use-package htmlize :straight t)
Interfaces
Magit
(use-package magit :straight t)
Org-Roam UI
(use-package org-roam-ui
:straight t)
Learning
Org-drill
;;; Org-drill
(use-package
org-drill :straight t
:custom
(org-drill-scope 'agenda))
Supplements
Full Source
(defvar straight-install-script-path
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el")
(setq straight-repository-branch "develop")
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously straight-install-script-path
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
(straight-use-package 'use-package)
(setq user-mail-address "emsenn@emsenn.net")
(setq ring-bell-function 'ignore)
(setq make-backup-files nil)
(setq inhibit-startup-message t)
(setq inhibit-startup-screen t)
(setq initial-scratch-message
";; LANDBACK")
(menu-bar-mode -1)
(tool-bar-mode -1)
(show-paren-mode 1)
(setq line-number-mode t)
(setq column-number-mode t)
(setq-default truncate-lines t)
(setq-default line-spacing 1)
(setq sentence-end-double-space nil)
(global-visual-line-mode t)
(setq echo-keystrokes 0.1)
(setq fill-column 68)
(setq mouse-wheel-scroll-amount '(1 ((shift) .1)))
(use-package mixed-pitch
:straight t
:hook
(text-mode . mixed-pitch-mode))
(use-package modus-themes
:straight t
:config
(load-theme 'modus-vivendi t))
(use-package olivetti
:straight t
:hook
(text-mode . olivetti-mode))
(require 'ucs-normalize)
(straight-use-package
'(beancount :type git :host github
:repo "beancount/beancount-mode"))
(use-package
yasnippet :straight t
:hook ((text-mode
prog-mode
conf-mode
snippet-mode)
. yas-minor-mode-on)
:custom (yas-snippet-dirs '("~/ems/org/met/yas-snippets")))
(use-package
org :straight t
:custom
(org-directory "~/ems/org")
(org-startup-folded 'fold)
(org-hide-block-startup 'hideblocks)
(org-catch-invisible-edits 'show-and-error)
(org-agenda-custom-commands
'(("A" "Agenda and TODO"
((agenda "" )
(alltodo "" )))))
(org-agenda-todo-ignore-scheduled 'all)
(org-agenda-files (list "~/ems/org"))
(org-export-with-section-numbers nil)
(org-export-with-smart-quotes nil)
(org-export-with-toc nil)
(org-html-htmlize-output-type 'nil)
(org-html-validation-link nil)
(org-log-done 'time)
(org-log-into-drawer 'LOGBOOK)
(org-image-actual-width '(400))
(org-cite-global-bibliography '("~/ems/bibliography.bib"))
(org-export-global-macros
'(
("nl" . "(eval \"\\n\")")
))
:bind (
("C-c l" . org-store-link)
("C-c a" . org-agenda)
("C-c c" . org-capture)
("C-c t" . org-toggle-link-display)
("C-c C-q" . counsel-org-tag)
)
:defines gpe/emsenn-net-head
:config
;; from https://www.john2x.com/blog/blogging-with-orgmode.html
(defun gpe/org-publish-format-sitemap (title sitemap)
(let ((posts (cdr sitemap)))
(concat
(format "#+title: %s\n" title)
"#+options: timestamp:nil date:nil\n"
(format "#+date: %s\n" (format-time-string "[%Y-%m-%d %a %H:%M:%S]" (current-time)))
(org-list-to-org (cons (car sitemap) posts)))))
(setq gpe/emsenn-net-head
(with-temp-buffer
(insert "<style>\n")
(insert-file-contents "~/ems/org/src/emsenn-net/main.css")
(goto-char (point-max)) ;; move to end before appending
(insert "\n</style>")
(buffer-string)))
(setq gpe/emsenn-net-preamble
(with-temp-buffer
(insert-file-contents "~/ems/org/src/emsenn-net/preamble.html")
(buffer-string)))
(org-babel-do-load-languages 'org-babel-load-languages
'(
(shell . t)
)))
(use-package
org-roam :straight t
:after org
:config
(defvar gpe/org-roam-public-node-files '())
(defun gpe/insert-backlinks (backend)
"Insert backlinks at the end of the buffer before Org export.
BACKEND is the export backend symbol, e.g., 'html or 'latex."
(when (org-export-derived-backend-p backend 'html)
(let ((node (org-roam-node-at-point)))
(when node
(save-excursion
(goto-char (point-max))
(insert "\n* Backlinks\n")
(dolist (ref (org-roam-backlinks-get node))
(let* ((source (org-roam-backlink-source-node ref))
(props (org-roam-node-properties source))
(is-public (string= (cdr (assoc "PUBLIC" props)) "true")))
(when is-public
(insert (format "- [[id:%s][%s]]\n"
(org-roam-node-id source)
(org-roam-node-title source)))))))))))
(defun gpe/org-roam-public-node-files ()
"Return a list of Org-roam files where PUBLIC property is true"
(mapcar #'car
(org-roam-db-query
[:select [file]
:from nodes
:where (like properties '"%public%true%")])))
(defun gpe/org-roam-open-random-node ()
"Open a random Org-roam node from the database."
(interactive)
(let* ((nodes (org-roam-node-list))
(count (length nodes)))
(if (zerop count)
(message "No Org-roam nodes found.")
(let* ((random-index (random count))
(node (nth random-index nodes)))
(org-roam-node-visit node)))))
(defun gpe/apply-capture-properties ()
(let ((properties '(:author :form)))
(dolist (property properties)
(let ((value (plist-get org-capture-current-plist property)))
(when value
(org-set-property (substring (symbol-name property) 1) value))))))
(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)))))
:hook
((org-export-before-processing . gpe/insert-backlinks)
(org-capture-mode . gpe/apply-capture-properties))
:custom
(org-roam-directory (file-truename "~/ems/org"))
(org-roam-dailies-directory ".")
(org-roam-db-extra-links-exclude-keys '((node-property "ROAM_REFS")))
(org-roam-capture-templates
(let ((files (directory-files "~/ems/org/src/gpe/org-roam-capture-templates/" t "\\.el$")))
(mapcar (lambda (file)
(with-temp-buffer
(insert-file-contents file)
(read (buffer-string))))
files)))
(org-publish-project-alist
`(
("emsenn-net" :components ("emsenn-net-all"))
("emsenn-net-all"
:base-directory "~/ems/org"
:exclude ".*\\.org$"
:include ,(gpe/org-roam-public-node-files)
:publishing-function org-html-publish-to-html
:preparation-function gpe/org-publish-prepare-backlinks
:html-doctype "html5"
:html-html5-fancy t
:html-container "section"
:headline-levels 6
:recursive t
:html-divs ((preamble "section" "preamble")
(content "main" "content")
(postamble "section" "postamble"))
:html-head-include-scripts nil
:html-head-include-default-style nil
:html-head ,gpe/emsenn-net-head
:html-format-drawer-function gpe/org-html-format-drawer
:exclude "\\`per/\\|README.org\\|DRAFT\\|PRIVATE"
:with-footnotes t
:with-date nil
:with-timestamps nil
:with-author nil
:publishing-directory "~/ems/pub/emsenn-net"
:makeindex t
:html-preamble ,gpe/emsenn-net-preamble
)
))
:bind (
("C-c n i" . org-roam-node-insert)
("C-c n f" . org-roam-node-find)
("C-c n c" . org-roam-node-capture)
("C-c n d" . org-roam-dailies-capture-today)
("C-c n D" . org-roam-dailies-capture-yesterday)
)
)
(use-package
org-transclusion :straight t
:custom
(org-transclusion-exclude-elements '(keyword property-drawer))
:bind (
("C-c n t" . org-transclusion-mode)
("C-c n T" . org-transclusion-add)
))
(use-package htmlize :straight t)
(use-package magit :straight t)
(use-package org-roam-ui
:straight t)
;;; Org-drill
(use-package
org-drill :straight t
:custom
(org-drill-scope 'agenda))
Old Source
This source block is a functioning verison of GnoponEmacs, captured
. I'm keeping it here to make sure I don't lose any necessary chunks as I refactor the chunks into the GnoponEmacs Org-mode file.;;; GnoponEmacs
;;; Package Management
(defvar straight-install-script-path
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el")
(setq straight-repository-branch "develop")
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously straight-install-script-path
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
(straight-use-package 'use-package)
;;; User Configuration
(setq user-mail-address "emsenn@emsenn.net")
(setq ring-bell-function 'ignore)
;;; User Experience
(setq inhibit-startup-message t)
(setq inhibit-startup-screen t)
(setq initial-scratch-message
";; LANDBACK")
(menu-bar-mode -1)
(tool-bar-mode -1)
(show-paren-mode 1)
(setq line-number-mode t)
(setq column-number-mode t)
(setq-default truncate-lines t)
(setq-default line-spacing 1)
(setq sentence-end-double-space nil)
(global-visual-line-mode t)
(setq echo-keystrokes 0.1)
(setq fill-column 68)
(setq mouse-wheel-scroll-amount '(1 ((shift) .1)))
(use-package mixed-pitch
:straight t
:hook
(text-mode . mixed-pitch-mode))
(use-package modus-themes
:straight t
:config
(load-theme 'modus-vivendi t))
(use-package olivetti
:straight t
:hook
(text-mode . olivetti-mode))
(require 'ucs-normalize)
;;; Beancount
(straight-use-package
'(beancount :type git :host github
:repo "beancount/beancount-mode"))
;;; Emacs Behaviors
(setq make-backup-files nil)
;;; HTMLize
(use-package htmlize :straight t)
;;; Magit
(use-package magit :straight t)
;;; YASnippet
(use-package
yasnippet :straight t
:hook ((text-mode
prog-mode
conf-mode
snippet-mode)
. yas-minor-mode-on)
:custom (yas-snippet-dirs '("~/ems/org/met/yas-snippets")))
;;; Org-mode
(use-package
org :straight t
:custom
(org-directory "~/ems/org")
(org-startup-folded 'fold)
(org-hide-block-startup 'hideblocks)
(org-catch-invisible-edits 'show-and-error)
(org-agenda-custom-commands
'(("A" "Agenda and TODO"
((agenda "" )
(alltodo "" )))))
(org-agenda-todo-ignore-scheduled 'all)
(org-agenda-files (list "~/ems/org"))
(org-export-with-section-numbers nil)
(org-export-with-smart-quotes nil)
(org-export-with-toc nil)
(org-html-htmlize-output-type 'nil)
(org-html-validation-link nil)
(org-log-done 'time)
(org-log-into-drawer 'LOGBOOK)
(org-image-actual-width '(400))
(org-cite-global-bibliography '("~/ems/bibliography.bib"))
(org-export-global-macros
'(
("nl" . "(eval \"\\n\")")
))
:bind (
("C-c l" . org-store-link)
("C-c a" . org-agenda)
("C-c c" . org-capture)
("C-c t" . org-toggle-link-display)
("C-c C-q" . counsel-org-tag)
)
:defines gpe/emsenn-net-head
:config
;; from https://www.john2x.com/blog/blogging-with-orgmode.html
(defun gpe/org-publish-format-sitemap (title sitemap)
(let ((posts (cdr sitemap)))
(concat
(format "#+title: %s\n" title)
"#+options: timestamp:nil date:nil\n"
(format "#+date: %s\n" (format-time-string "[%Y-%m-%d %a %H:%M:%S]" (current-time)))
(org-list-to-org (cons (car sitemap) posts)))))
(setq gpe/emsenn-net-head
(with-temp-buffer
(insert "<style>\n")
(insert-file-contents "~/ems/org/src/emsenn-net/main.css")
(goto-char (point-max)) ;; move to end before appending
(insert "\n</style>")
(buffer-string)))
(setq gpe/emsenn-net-preamble
(with-temp-buffer
(insert-file-contents "~/ems/org/src/emsenn-net/preamble.html")
(buffer-string)))
(org-babel-do-load-languages 'org-babel-load-languages
'(
(shell . t)
)))
(use-package
org-roam :straight t
:after org
:config
(defvar gpe/org-roam-public-node-files '())
(defun gpe/insert-backlinks (backend)
"Insert backlinks at the end of the buffer before Org export.
BACKEND is the export backend symbol, e.g., 'html or 'latex."
(when (org-export-derived-backend-p backend 'html)
(let ((node (org-roam-node-at-point)))
(when node
(save-excursion
(goto-char (point-max))
(insert "\n* Backlinks\n")
(dolist (ref (org-roam-backlinks-get node))
(let* ((source (org-roam-backlink-source-node ref))
(props (org-roam-node-properties source))
(is-public (string= (cdr (assoc "PUBLIC" props)) "true")))
(when is-public
(insert (format "- [[id:%s][%s]]\n"
(org-roam-node-id source)
(org-roam-node-title source)))))))))))
(defun gpe/org-roam-public-node-files ()
"Return a list of Org-roam files where PUBLIC property is true"
(mapcar #'car
(org-roam-db-query
[:select [file]
:from nodes
:where (like properties '"%public%true%")])))
(defun gpe/org-roam-open-random-node ()
"Open a random Org-roam node from the database."
(interactive)
(let* ((nodes (org-roam-node-list))
(count (length nodes)))
(if (zerop count)
(message "No Org-roam nodes found.")
(let* ((random-index (random count))
(node (nth random-index nodes)))
(org-roam-node-visit node)))))
(defun gpe/apply-capture-properties ()
(let ((properties '(:author :form)))
(dolist (property properties)
(let ((value (plist-get org-capture-current-plist property)))
(when value
(org-set-property (substring (symbol-name property) 1) value))))))
(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)))))
:hook
((org-export-before-processing . gpe/insert-backlinks)
(org-capture-mode . gpe/apply-capture-properties))
:custom
(org-roam-directory (file-truename "~/ems/org"))
(org-roam-dailies-directory ".")
(org-roam-db-extra-links-exclude-keys '((node-property "ROAM_REFS")))
(org-roam-capture-templates
(let ((files (directory-files "~/ems/org/src/gpe/org-roam-capture-templates/" t "\\.el$")))
(mapcar (lambda (file)
(with-temp-buffer
(insert-file-contents file)
(read (buffer-string))))
files)))
(org-roam-title-to-slug-function
(org-publish-project-alist
`(
("emsenn-net" :components ("emsenn-net-all"))
("emsenn-net-all"
:base-directory "~/ems/org"
:exclude ".*\\.org$"
:include ,(gpe/org-roam-public-node-files)
:publishing-function org-html-publish-to-html
:preparation-function gpe/org-publish-prepare-backlinks
:html-doctype "html5"
:html-html5-fancy t
:html-container "section"
:headline-levels 6
:recursive t
:html-divs ((preamble "section" "preamble")
(content "main" "content")
(postamble "section" "postamble"))
:html-head-include-scripts nil
:html-head-include-default-style nil
:html-head ,gpe/emsenn-net-head
:html-format-drawer-function gpe/org-html-format-drawer
:exclude "\\`per/\\|README.org\\|DRAFT\\|PRIVATE"
:with-footnotes t
:with-date nil
:with-timestamps nil
:with-author nil
:publishing-directory "~/ems/pub/emsenn-net"
:makeindex t
:html-preamble ,gpe/emsenn-net-preamble
)
))
:bind (
("C-c n i" . org-roam-node-insert)
("C-c n f" . org-roam-node-find)
("C-c n c" . org-roam-node-capture)
("C-c n d" . org-roam-dailies-capture-today)
("C-c n D" . org-roam-dailies-capture-yesterday)
)
)
;;; Org-roam-UI
(use-package org-roam-ui
:straight t)
;;; Org-drill
(use-package
org-drill :straight t
:custom
(org-drill-scope 'agenda))
;;; Org-transclusion
(use-package
org-transclusion :straight t
:custom
(org-transclusion-exclude-elements '(keyword property-drawer))
:bind (
("C-c n t" . org-transclusion-mode)
("C-c n T" . org-transclusion-add)
))