diff --git a/emacs/init.el b/emacs/init.el index e31fa32..8afe05e 100644 --- a/emacs/init.el +++ b/emacs/init.el @@ -332,6 +332,8 @@ my/denote-remote-notes-directory my/denote-local-notes-directory))) (setq denote-directory new-dir) + (setq my/denote-metadata-index-file (concat denote-directory "../denote-metadata.org")) + (message "Denote directory switched to %s" new-dir))) (defun my/denote-use-both-directories (orig-fun &rest args) @@ -356,12 +358,22 @@ (advice-add 'denote-directory-files :around #'my/denote-use-both-directories) (advice-add 'denote-directory-subdirectories :around #'my/denote-use-both-directories) - + (defun my/search-denote-notes () - "Use ripgrep to search denote notes." + "Use consult-ripgrep to search only the Denote metadata index file, without recursion." (interactive) - (let ((default-directory denote-directory)) - (consult-ripgrep))) + (let* ((index-file my/denote-metadata-index-file) + (default-directory (file-name-directory index-file)) + (file-name (file-name-nondirectory index-file)) + (consult-ripgrep-args + (concat "rg --null --ignore-case --type org --line-buffered --color=never " + "--max-columns=500 --no-heading --line-number " + "--max-depth 0 " + (shell-quote-argument file-name)))) + (if (file-exists-p index-file) + (consult-ripgrep default-directory) + (message "Metadata index file not found: %s" index-file)))) + (let ((map dired-mode-map)) (define-key map (kbd "C-x n d") #'denote-dired-mode) @@ -369,14 +381,6 @@ (define-key map (kbd "C-x n k") #'denote-dired-rename-marked-files-with-keywords) (define-key map (kbd "C-x n r r") #'denote-dired-rename-files) (define-key map (kbd "C-x n r f") #'denote-dired-rename-marked-files-using-front-matter)) - - ;; show current denote directory in modeline - (with-eval-after-load 'doom-modeline - (doom-modeline-def-segment denote-directory - (my-denote-directory-segment)) - (setq doom-modeline-format-left - (append doom-modeline-format-left - '(denote-directory)))) (setq denote-save-buffers nil denote-known-keywords '("emacs" "golang" "dev") @@ -904,6 +908,78 @@ nil (window-parameters (mode-line-format . none))))) +(use-package ement + :ensure t + :defer t + :config + (setq ement-save-sessions t) + (setq ement-room-list-auto-update t)) + +(require 'denote) + +;; automated denote metadata management +(defvar my/denote-metadata-index-file (concat denote-directory "../denote-metadata.org") + "Path to the metadata index file.") + +(defun my/extract-date-from-filename (file) + "Extract date from FILE name. Assumes first 8 characters are YYYYMMDD." + (substring (file-name-nondirectory file) 0 8)) + +(defun my/format-date (date-string) + "Format DATE-STRING (YYYYMMDD) as YYYY-MM-DD." + (format "%s-%s-%s" + (substring date-string 0 4) + (substring date-string 4 6) + (substring date-string 6 8))) + +(defun my/extract-summary (file) + "Extract summary from FILE." + (with-temp-buffer + (insert-file-contents file) + (goto-char (point-min)) + (when (re-search-forward "^\\* Summary$" nil t) + (forward-line) + (let ((start (point))) + (if (re-search-forward "^\\*" nil t) + (string-trim (buffer-substring-no-properties start (line-beginning-position))) + (string-trim (buffer-substring-no-properties start (point-max)))))))) + + +(defun my/update-denote-metadata-index () + "Update the metadata index for Denote notes in Org format." + (interactive) + (with-temp-file my/denote-metadata-index-file + (insert "#+TITLE: Denote Metadata Index\n") + (insert "#+AUTHOR: Your Name\n") + (insert "#+DATE: " (format-time-string "%Y-%m-%d") "\n\n") + (dolist (file (directory-files-recursively denote-directory "\\.org$")) + (let ((file-contents (with-temp-buffer + (insert-file-contents file) + (buffer-string)))) + (with-temp-buffer + (insert file-contents) + (goto-char (point-min)) + (when (re-search-forward "^#\\+title: \\(.+\\)$" nil t) + (let* ((title (string-trim (match-string 1))) + (keywords (denote-extract-keywords-from-path file)) + (date-string (my/extract-date-from-filename file)) + (formatted-date (my/format-date date-string)) + (is-journal (and (listp keywords) (member "journal" keywords))) + (summary (if is-journal + (format "Journal entry for [%s]" formatted-date) + (my/extract-summary file)))) + (with-current-buffer (find-file-noselect my/denote-metadata-index-file) + (goto-char (point-max)) + (insert (format "* [[file:%s][%s]]\n" file title)) + (insert " :PROPERTIES:\n") + (insert (format " :KEYWORDS: %s\n" keywords)) + (insert (format " :DATE: [%s]\n" formatted-date)) + (insert " :END:\n\n") + (insert (if summary + summary + "No summary provided.")) + (unless (string-suffix-p "\n\n" (or summary "")) + (insert "\n\n")))))))))) (provide 'init)