;; -*- mode: emacs-lisp; buffer-read-only: t; -*-
;; be paranoid, only open org files in read-only mode.
;;
(defun myorg-open-read-only-mode ()
"Enable `read-only-mode' for Org mode files."
(when (and buffer-file-name
(string-match "\\.org\\'" buffer-file-name))
(read-only-mode 1)))
(add-hook 'org-mode-hook 'myorg-open-read-only-mode)
;;;; add inactive timestamp to every org-item
;; https://stackoverflow.com/a/52815573/5115219
;; https://emacs.stackexchange.com/a/45369/29404
(defun insert-created-date (&rest ignore)
"Insert inacative timestamp property,
but only in org-items, not in org-item-checkboxes."
(interactive)
(if (not (org-at-item-checkbox-p))
(progn
(insert (format-time-string
(concat "\n"
":properties:\n"
":created: "
"[%Y-%m-%d %a %H:%M]\n"
":end:"
)))
;; in org-capture, this folds the entry; when inserting a heading, this moves point back to the heading line
(org-back-to-heading)
;; when inserting a heading, this moves point to the end of the line
(move-end-of-line ()))))
;;;; add inactive timestamp to entries in org-mode
(advice-add 'org-insert-heading :after #'insert-created-date)
;; ----------------------------------------------------------------------
;;; org-roam
;; ----------------------------------------------------------------------
;;;; Filter nodes
;; https://www.reddit.com/r/emacs/comments/vb989o/orgroam_show_only_file_nodes_when_inserting_a_node/ic8bc7l/?context=3
;;;;; Define regexp for filtering daily journal files like `2022-05-22'
(setq my-date-regexp "^[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [A-Za-z]+")
;;;;; Define filter functions to be used in `org-roam-node-find' function.
(defun ugt-filter-org-roam-node-file-p (node)
"Filter nodes that represent files.
So exclude nodes that are outline items in org files.
Usage example:
(org-roam-node-read nil #'ugt-filter-org-roam-node-file-p)
"
(and
(= (org-roam-node-level node) 0)
(not (string-match my-date-regexp (org-roam-node-title node)))))
(defun ugt-filter-org-roam-node-exclude-dates (node)
"Exclude journal files like `2022-05-17' from nodes list."
(not (string-match my-date-regexp (org-roam-node-title node))))
(defun ugt-filter-org-roam-node-exclude-archived-and-journal-files (node)
"Exclude these files / nodes
- tagged `archive'
- in folder `archive'
- journal files."
(and
;; no journal files
(not (string-match my-date-regexp (org-roam-node-title node)))
;; not tagged `archive'
(not (member "archive" (org-roam-node-tags node)))
;; not in any folder named `archive'
(not (string-match-p "archive/" (org-roam-node-file node)))))
;;;;; Define custom `org-roam-node-find' functions with filters.
(defun ugt-org-roam-node-find nil
"Refined search for org-roam nodes.
Exclude elements tagged `archive'."
(interactive)
;; nb: can add initial search string like "^"
(org-roam-node-find :other-window nil #'ugt-filter-org-roam-node-exclude-archived-and-journal-files))
(defun ugt-org-roam-node-find-document-nodes nil
"Refined search for org-roam nodes.
Search for only document level nodes. Exclude dates."
(interactive)
;;(org-roam-node-find :other-window)
(org-roam-node-find :other-window nil #'ugt-filter-org-roam-node-file-p))
;;;; Custom `org-roam-dailies-goto-today' function
(defun ugt-org-roam-dailies-goto-today nil
"Open todays journal in other window."
(interactive)
(split-window-right)
(other-window 1)
(org-roam-dailies-goto-today))
(setq org-roam-node-display-template
(concat "${title:70}"(propertize "${tags:30}" 'face 'org-tag) "${file:48}"))
(setq org-roam-capture-templates '(
("d" "default (personal notes)"
plain "%?"
;; could use
;; (file (concat org-directory "/org-roam/personal/templates/personal.org"))
:if-new (file+head "personal/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+startup: showall\n\n")
:immediate-finish t
:empty-lines 1
:unnarrowed t)
("q" "FreeBSD"
plain "%?"
:if-new (file+head "personal/freebsd/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+filetags: FreeBSD\n#+startup: showall\n\n")
:immediate-finish t
:empty-lines 1
:unnarrowed t)
("l" "Japanese"
plain "%?"
:if-new (file+head "personal/japanese/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+filetags: Japanese\n#+startup: showall\n\n")
:immediate-finish t
:empty-lines 1
:unnarrowed t)
("z" "Blog Post"
plain "%?"
:if-new (file+head "~/omnia/weblog/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+filetags: blog_post\n#+startup: showall\n
#+AUTHOR: Alexandro Longo \n
#+HTML_HEAD_EXTRA: \n
#+OPTIONS: toc:nil \n
#+HTML_HEAD: \n
\n")
:immediate-finish t
:empty-lines 1
:unnarrowed t)
("c" "Math Ideas"
plain "%?"
:if-new (file+head "personal/math-ideas/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+filetags: mathematical_ideas\n#+startup: showall\n\n")
:immediate-finish t
:empty-lines 1
:unnarrowed t)
("t" "Proofs"
plain "%?"
:if-new (file+head "personal/math-ideas/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+filetags: mathematical_proofs\n#+startup: showall\n\n")
:immediate-finish t
:empty-lines 1
:unnarrowed t)
("x" "Real Analysis"
plain "%?"
:if-new (file+head "personal/math-ideas/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+filetags: real_analysis\n#+startup: showall\n\n")
:immediate-finish t
:empty-lines 1
:unnarrowed t)
("m" "mechanics"
plain "%?"
:if-new (file+head "personal/mechanics/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+filetags: mechanics\n#+startup: showall\n\n")
:immediate-finish t
:empty-lines 1
:unnarrowed t)
("s" "stoicism"
plain "%?"
:if-new (file+head "personal/stoicism/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+filetags: stoicism\n#+startup: showall\n\n")
:immediate-finish t
:empty-lines 1
:unnarrowed t)
("n" "My Readings"
plain "%?"
:if-new (file+head "my-readings/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+filetags: My_readings \n#+startup: content\n")
:empty-lines 1
:unnarrowed t)
("g" "Guix"
plain "%?"
:if-new (file+head "guix/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+filetags: Guix \n#+startup: content\n")
:empty-lines 1
:unnarrowed t)
("e" "Emacs related notes"
plain "%?"
:if-new (file+head "emacs/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+filetags: emacs\n#+startup: content\n")
:empty-lines 1
:unnarrowed t)
("w" "work notes"
plain "%?"
:if-new (file+head "work/${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d %a %R>\n#+updated: \n %R>\n#+filetags: work_notes\n\n")
:immediate-finish t
:empty-lines 1
:unnarrowed t))
time-stamp-start "#\\+updated: [\t]*")
(setq org-roam-dailies-capture-templates '(("d" "default" entry
"\n* %<%H:%M> %?\n:properties:\n:created: %U\n:end:\n"
:target (file+head "%<%Y-%m-%d>.org"
"#+title: %<%Y-%m-%d %a>\n#+startup: showall\n")
;;:unnarrowed t
;;:jump-to-captured t
:empty-lines 1
)))
;; Change file-name (slug) creation
;; Replace whitespace with dashes instead of underscores.
;; See
;; - https://github.com/org-roam/org-roam/issues/686
;; - https://github.com/org-roam/org-roam/pull/1544[[id:2022-06-12T213159.588064][test mest hest]]
(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
779 ; U+030B COMBINING DOUBLE ACUTE ACCENT
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) (string-glyph-compose
(apply #'string
(seq-remove #'nonspacing-mark-p
(string-glyph-decompose 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)))))
;; https://org-roam.discourse.group/t/v2-set-id-to-a-timestamp/1492/2
;; (setq org-roam-capture-templates
;; '(("p" "personal" plain
;; (function org-roam--capture-get-point) "%?"
;; :file-name "personal/%<%Y-%m-%dT%H%M%S>"
;; :head "---\ntitle: ${title}\nid: %<%Y-%m-%dT%H%M%S.%6N">\nmodified: <>\n---\n"
;; :unnarrowed t)))
(org-roam-db-autosync-mode)
;; If using org-roam-protocol
(require 'org-roam-protocol)
;;;; Go to item text after capture
(defun ugt-org-capture-after-finalize-hook nil
(org-capture-goto-last-stored)
(end-of-buffer)
(recenter-top-bottom '(4)) ;; center of window
)
(add-hook 'org-capture-after-finalize-hook #'ugt-org-capture-after-finalize-hook)
;;;; Hide drawers after creation
(defun my-org-capture-hook ()
(when (plist-member org-capture-plist :org-roam)
(org-cycle-hide-drawers 'overview)))
(add-hook 'org-capture-mode-hook #'my-org-capture-hook)
;;;; Hide drawers in all cases in org-roam.
(defun my-org-roam-hook () (org-cycle-hide-drawers 'overview))
(add-hook 'org-roam-mode-hook #'my-org-roam-hook)
;;;; Jump to the end of buffer when today's journal is opened
(defun ugt-org-roam-dailies-find-file-hook nil (end-of-buffer))
(add-hook 'org-roam-dailies-find-file-hook #'ugt-org-roam-dailies-find-file-hook)
;;;; add inactive timestamp to journal entries in org-roam
(add-hook 'org-roam-dailies-capture-today #'insert-created-date)