From f07ed4336cacf762987e79dbac4087dd36b44118 Mon Sep 17 00:00:00 2001 From: Tibo De Peuter Date: Sat, 11 Jul 2026 20:26:10 +0200 Subject: [PATCH] feat(notetaking): add custom views --- notetaking/flake.nix | 9 ++-- notetaking/init.el | 52 +++++++++++++++++++--- notetaking/modules/my-org.el | 86 +++++++++++++++++++++++++++++++++--- 3 files changed, 133 insertions(+), 14 deletions(-) diff --git a/notetaking/flake.nix b/notetaking/flake.nix index 9705ed2..c8cfa9e 100644 --- a/notetaking/flake.nix +++ b/notetaking/flake.nix @@ -21,12 +21,13 @@ ]; emacsDependencies = with pkgs; [ - hunspell - hunspellDicts.nl_NL - hunspellDicts.en_GB-large ghostscript graphviz + hunspell + hunspellDicts.en_GB-large + hunspellDicts.nl_NL imagemagickBig + pandoc poppler-utils ripgrep @@ -60,6 +61,7 @@ epkgs.unicode-fonts pkgs.shellcheck + epkgs.guess-language ]; }) @@ -72,7 +74,6 @@ #}) pkgs.ankiAddons.anki-connect - pkgs.pandoc ]) ] ++ emacsDependencies; }; diff --git a/notetaking/init.el b/notetaking/init.el index cca0d16..c9b3c33 100644 --- a/notetaking/init.el +++ b/notetaking/init.el @@ -138,9 +138,54 @@ (auto-dark-mode) ) -;; TODO org-roam stores everything with a prefix. Is there a way to disable that or not? +(defvar my/pre-zen-menu-bar nil "Store menu bar state before zen mode.") +(defvar my/pre-zen-tool-bar nil "Store tool bar state before zen mode.") +(defvar my/pre-zen-scroll-bar nil "Store scroll bar state before zen mode.") +(defvar my/pre-zen-line-numbers nil "Stores line number state before zen mode.") + +(define-minor-mode my/zen-mode + "A complete full-screen, distraction-free environment." + :init-value nil + :global t + (if my/zen-mode + (progn ;; ON + (setq my/pre-zen-menu-bar (bound-and-true-p menu-bar-mode)) + (setq my/pre-zen-tool-bar (bound-and-true-p tool-bar-mode)) + (setq my/pre-zen-scroll-bar (bound-and-true-p scroll-bar-mode)) + (setq my/pre-zen-line-numbers (bound-and-true-p global-display-line-numbers-mode)) + + (olivetti-mode 1) + (menu-bar-mode -1) + (tool-bar-mode -1) + (scroll-bar-mode -1) + (display-line-numbers-mode -1) + (set-frame-parameter nil 'fullscreen 'maximized)) + (progn ;; OFF + (olivetti-mode -1) + (menu-bar-mode (if my/pre-zen-menu-bar 1 -1)) + (tool-bar-mode (if my/pre-zen-tool-bar 1 -1)) + (scroll-bar-mode (if my/pre-zen-scroll-bar 1 -1)) + (display-line-numbers-mode (if my/pre-zen-line-numbers 1 -1)) + (set-frame-parameter nil 'fullscreen nil)) + )) + +(define-minor-mode my/presentation-mode + "A clean, scaled-up environment." + :init-value nil + :global t + (if my/presentation-mode + (progn ;; ON + (my/zen-mode 1) ;; Inherit zen mode + (face-remap-set-base 'default :height 180)) ;; Scale font to 18pt + (progn ;; OFF + (my/zen-mode -1) + (face-remap-set-base 'default)) + )) + +(global-set-key (kbd "") 'my/zen-mode) +(global-set-key (kbd "") 'my/presentation-mode) + ;; TODO Put exports in their own directory? (now filename-prefix.pdf) -;; TODO Put dailies in "journals" instead of "daily" ;; TODO I store my lecture PDFs in ~/Nextcloud/Documents/UGent//theory/*.pdf, is there some way to make a shortcut for this (related to Fuzzy finding files etc.). Maybe consider integrating with Zotero and storing PDFs there? ;; Additional package to explore @@ -151,9 +196,6 @@ ;; TODO (add-hook 'text-mode-hook 'auto-fill-mode) ;; Do I want this? -;; TODO Automatically save buffer when going to other file -- maybe interactively? -;; TODO Spellchecking (UK & Dutch) - ;; TODO Finally, compare experience to organice https://organice.200ok.ch/ ;; TODO org-compile-file: File "/tmp/nix-shell.UEk6Ye/orgtexcJso3E.dvi" wasn’t produced Please adjust ‘dvipng’ part of ‘org-preview-latex-process-alist’. diff --git a/notetaking/modules/my-org.el b/notetaking/modules/my-org.el index 4786547..f7db757 100644 --- a/notetaking/modules/my-org.el +++ b/notetaking/modules/my-org.el @@ -21,12 +21,16 @@ (add-hook 'org-mode-hook 'visual-line-mode) ;; Make text wrap in org mode (add-hook 'org-mode-hook (lambda () (display-line-numbers-mode -1))) ;; Hide line numbers in org mode :custom - (org-hide-emphasis-markers t) ;; Required for org-appear to work + ;(org-hide-emphasis-markers t) ;; Required for org-appear to work (org-pretty-entities t) (org-image-actual-width nil) ;; Allow resizing images (org-link-window-setup 'current-window) ;; Force links to open in the current window (org-startup-folded 'showall) ;; https://orgmode.org/manual/Initial-visibility.html (org-html-with-latex 'lualatex-svg) ;; Tell HTML export to use SVG image pipeline + :bind + (:map org-mode-map + ("M-s r" . (lambda () (interactive) (consult-ripgrep my-org-roam-base-dir))) ;; Search in whole roam directory + ) :config (setq org-latex-compiler "lualatex") @@ -65,9 +69,9 @@ (org-roam-dailies-directory "dailies/") (org-roam-completion-everywhere t) :bind ( - ("C-c r f" . org-roam-node-find) ;; TODO This is case sensitive, make it insensitive - ("C-c r j" . org-roam-dailies-capture-today) + ("C-c r f" . org-roam-node-find) ("C-c r t" . org-roam-dailies-goto-today) + ("C-c r j" . my/org-roam-journal-stream) ) :init (setq org-roam-mode-sections ;; https://www.orgroam.com/manual.html#Configuring-what-is-displayed-in-the-buffer-1 @@ -84,8 +88,9 @@ '(("d" "default" plan "%?" :target (file+head "notes/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") - :unnarrowed t)) - ) + :unnarrowed t))) + (setq org-roam-node-display-template + (concat "${title:*} " (propertize "${tags:20}" 'face 'org-tag))) (add-to-list 'display-buffer-alist '("\\*org-roam\\*" @@ -97,6 +102,41 @@ ) ;; Open backlinks on the right. ) +(defun my/org-roam-dailies-prune () + "Scan org-roam dailies and prune empty entries." + (let* ((daily-dir (expand-file-name "dailies" my-org-roam-base-dir)) + (files (directory-files daily-dir t "^[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.*\\.org$")) + (empty-files '())) + (dolist (file files) + (when (file-exists-p file) + (with-temp-buffer + (insert-file-contents file) + (let* ((content (buffer-string)) + (no-title (replace-regexp-in-string "^#\\+title:.*$" "" content)) + (no-properties (replace-regexp-in-string "^:PROPERTIES:\n\\(.*\n\\)*?:END:\n" "" no-title)) + (clean (replace-regexp-in-string "[ \t\n\r]+" "" no-properties))) + (when (string-empty-p clean) + (push file empty-files)))))) + (if empty-files + (let ((buf (get-buffer-create "*Empty Journals to Prune*"))) + (with-current-buffer buf + (erase-buffer) + (insert "The following journal files appear to be empty:\n\n") + (dolist (f empty-files) + (insert (format "- %s\n" (file-name-nondirectory f))))) + (display-buffer buf '((display-buffer-in-direction) (direction . bottom))) + + (let ((proceed (yes-or-no-p (format "Found %d empty journal files. Delete them? " (length empty-files))))) + (when proceed + (dolist (f empty-files) + (delete-file f)) + (message "Empties pruned.")) + (kill-buffer buf) + t)) ;; Return t to allow exit + t))) ;; Return t to allow exit if no empties found + +(add-hook 'kill-emacs-query-functions #'my/org-roam-dailies-prune) + (use-package org-download :ensure t :after org @@ -127,6 +167,42 @@ ) ) +(defun my/org-roam-journal-stream () + "Create a virtual buffer showing journal entries." + (interactive) + (let* ((buf (get-buffer-create "*Journal-Stream*")) + (daily-dir (expand-file-name "dailies" my-org-roam-base-dir)) + (files (reverse (sort (directory-files daily-dir t "^[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.*\\.org$") 'string<))) + ) + (with-current-buffer buf + (setq default-directory daily-dir) + (read-only-mode -1) + (erase-buffer) + (insert "#+title: Journal Timeline\n#+options: toc:nil num:nil\n\n") + (if (null files) + (insert "* No journal entries found.\n") + (dolist (file files) + (let ((date-str (file-name-base file))) + (insert (format "* %s\n" date-str)) + (let ((content (with-temp-buffer + (insert-file-contents file) + (goto-char (point-min)) + (when (re-search-forward "^:PROPERTIES:\n\\(.*\n\\)*?:END:\n" nil t) + (replace-match "")) + (goto-char (point-min)) + (when (re-search-forward "^#\\+title:.*\n" nil t) + (replace-match "")) + (goto-char (point-min)) + (while (re-search-forward "^\\*" nil t) + (replace-match "**")) + (buffer-string)))) + (insert content) + (insert "\n\n"))))) + (org-mode) + (read-only-mode 1) + (org-overview)) + (switch-to-buffer buf))) + ;; Integrations (use-package org-anki ;; https://github.com/eyeinsky/org-anki