denote lazy loading

This commit is contained in:
Levi Neely 2024-09-15 20:19:59 +02:00
parent 3c81cb004a
commit 4ca76053d2
3 changed files with 169 additions and 160 deletions

View File

@ -9,85 +9,87 @@
(require 'module-denote) (require 'module-denote)
(defvar my/denote-metadata-index-file (concat denote-directory "../denote-metadata.org") (with-eval-after-load 'denote
"Path to the metadata index file.")
(defun my/extract-date-from-filename (file) (defvar my/denote-metadata-index-file (concat denote-directory "../denote-metadata.org")
"Extract date from FILE name. Assumes first 8 characters are YYYYMMDD." "Path to the metadata index file.")
(substring (file-name-nondirectory file) 0 8))
(defun my/format-date (date-string) (defun my/extract-date-from-filename (file)
"Format DATE-STRING (YYYYMMDD) as YYYY-MM-DD." "Extract date from FILE name. Assumes first 8 characters are YYYYMMDD."
(format "%s-%s-%s" (substring (file-name-nondirectory file) 0 8))
(substring date-string 0 4)
(substring date-string 4 6)
(substring date-string 6 8)))
(defun my/extract-summary (file) (defun my/format-date (date-string)
"Extract summary from FILE." "Format DATE-STRING (YYYYMMDD) as YYYY-MM-DD."
(with-temp-buffer (format "%s-%s-%s"
(insert-file-contents file) (substring date-string 0 4)
(goto-char (point-min)) (substring date-string 4 6)
(when (re-search-forward "^\\* Summary$" nil t) (substring date-string 6 8)))
(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 () (defun my/extract-summary (file)
"Update the metadata index for Denote notes in Org format." "Extract summary from FILE."
(interactive) (with-temp-buffer
(with-temp-file my/denote-metadata-index-file (insert-file-contents file)
(insert "#+TITLE: Denote Metadata Index\n") (goto-char (point-min))
(insert "#+AUTHOR: Your Name\n") (when (re-search-forward "^\\* Summary$" nil t)
(insert "#+DATE: " (format-time-string "%Y-%m-%d") "\n\n") (forward-line)
(dolist (file (directory-files-recursively denote-directory "\\.org$")) (let ((start (point)))
(let ((file-contents (with-temp-buffer (if (re-search-forward "^\\*" nil t)
(insert-file-contents file) (string-trim (buffer-substring-no-properties start (line-beginning-position)))
(buffer-string)))) (string-trim (buffer-substring-no-properties start (point-max))))))))
(with-temp-buffer
(insert file-contents) (defun my/update-denote-metadata-index ()
(goto-char (point-min)) "Update the metadata index for Denote notes in Org format."
(when (re-search-forward "^#\\+title: \\(.+\\)$" nil t) (interactive)
(let* ((title (string-trim (match-string 1))) (with-temp-file my/denote-metadata-index-file
(keywords (denote-extract-keywords-from-path file)) (insert "#+TITLE: Denote Metadata Index\n")
(date-string (my/extract-date-from-filename file)) (insert "#+AUTHOR: Your Name\n")
(formatted-date (my/format-date date-string)) (insert "#+DATE: " (format-time-string "%Y-%m-%d") "\n\n")
(is-journal (and (listp keywords) (member "journal" keywords))) (dolist (file (directory-files-recursively denote-directory "\\.org$"))
(summary (if is-journal (let ((file-contents (with-temp-buffer
(format "Journal entry for [%s]" formatted-date) (insert-file-contents file)
(my/extract-summary file)))) (buffer-string))))
(with-current-buffer (find-file-noselect my/denote-metadata-index-file) (with-temp-buffer
(goto-char (point-max)) (insert file-contents)
(insert (format "* [[file:%s][%s]]\n" file title)) (goto-char (point-min))
(insert " :PROPERTIES:\n") (when (re-search-forward "^#\\+title: \\(.+\\)$" nil t)
(insert (format " :KEYWORDS: %s\n" keywords)) (let* ((title (string-trim (match-string 1)))
(insert (format " :DATE: [%s]\n" formatted-date)) (keywords (denote-extract-keywords-from-path file))
(insert " :END:\n\n") (date-string (my/extract-date-from-filename file))
(insert (if summary (formatted-date (my/format-date date-string))
summary (is-journal (and (listp keywords) (member "journal" keywords)))
"No summary provided.")) (summary (if is-journal
(unless (string-suffix-p "\n\n" (or summary "")) (format "Journal entry for [%s]" formatted-date)
(insert "\n\n")))))))))) (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"))))))))))
(defun my/search-denote-notes () (defun my/search-denote-notes ()
"Use consult-ripgrep to search only the Denote metadata index file." "Use consult-ripgrep to search only the Denote metadata index file."
(interactive) (interactive)
(let* ((index-file my/denote-metadata-index-file) (let* ((index-file my/denote-metadata-index-file)
(default-directory (file-name-directory index-file)) (default-directory (file-name-directory index-file))
(file-name (file-name-nondirectory index-file)) (file-name (file-name-nondirectory index-file))
(consult-ripgrep-args (consult-ripgrep-args
(concat "rg --null --ignore-case --type org --line-buffered --color=never " (concat "rg --null --ignore-case --type org --line-buffered --color=never "
"--max-columns=500 --no-heading --line-number " "--max-columns=500 --no-heading --line-number "
"--max-depth 0 " "--max-depth 0 "
(shell-quote-argument file-name)))) (shell-quote-argument file-name))))
(if (file-exists-p index-file) (if (file-exists-p index-file)
(consult-ripgrep default-directory) (consult-ripgrep default-directory)
(message "Metadata index file not found: %s" index-file)))) (message "Metadata index file not found: %s" index-file))))
(global-set-key (kbd "C-x n /") #'my/search-denote-notes) (global-set-key (kbd "C-x n /") #'my/search-denote-notes))
(provide 'module-denote-index) (provide 'module-denote-index)

View File

@ -10,69 +10,73 @@
(require 'module-denote-index) (require 'module-denote-index)
(require 'module-alioth) ;; depends on alioth for some functions (require 'module-alioth) ;; depends on alioth for some functions
(defvar my/denote-local-notes-directory "~/notes/") (autoload 'my/denote-create-note "denote" nil t)
(defvar my/denote-remote-notes-directory "~/alioth/notes/")
(setq denote-directory my/denote-local-notes-directory) (with-eval-after-load 'denote
(defvar my/denote-local-notes-directory "~/notes/")
(defvar my/denote-remote-notes-directory "~/alioth/notes/")
(defun my/denote-open-or-create () (setq denote-directory my/denote-local-notes-directory)
"Ensure alioth is mounted before creating or opening a note."
(interactive)
(ensure-alioth-mounted)
(let ((target (denote-file-prompt nil nil :no-require-match)))
(if (and target (file-exists-p target))
(find-file target)
(denote--command-with-features (denote-command-prompt) :use-file-prompt-as-def-title nil nil nil))))
(defun my/denote-echo-current-directory () (defun my/denote-open-or-create ()
"Echo the current value of denote-directory." "Ensure alioth is mounted before creating or opening a note."
(declare (interactive-only t)) (interactive)
(interactive) (ensure-alioth-mounted)
(message "Current Denote directory: %s" denote-directory)) (let ((target (denote-file-prompt nil nil :no-require-match)))
(if (and target (file-exists-p target))
(find-file target)
(denote--command-with-features (denote-command-prompt) :use-file-prompt-as-def-title nil nil nil))))
(defun my/denote-directory-segment () (defun my/denote-echo-current-directory ()
"Return the current Denote directory for the mode line." "Echo the current value of denote-directory."
(when (bound-and-true-p denote-directory) (declare (interactive-only t))
(format " Denote:%s " (file-name-nondirectory (directory-file-name denote-directory))))) (interactive)
(message "Current Denote directory: %s" denote-directory))
(defun my/denote-switch-directory () (defun my/denote-directory-segment ()
"Switch current denote working directory." "Return the current Denote directory for the mode line."
(interactive) (when (bound-and-true-p denote-directory)
(let ((new-dir (if (string= denote-directory my/denote-local-notes-directory) (format " Denote:%s " (file-name-nondirectory (directory-file-name denote-directory)))))
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) (defun my/denote-switch-directory ()
"Temporarily use both directories for a given ORIG-FUN and ARGS." "Switch current denote working directory."
(let ((original-dir denote-directory) (interactive)
(result nil)) (let ((new-dir (if (string= denote-directory my/denote-local-notes-directory)
(setq denote-directory my/denote-local-notes-directory) my/denote-remote-notes-directory
(setq result (apply orig-fun args)) my/denote-local-notes-directory)))
(setq denote-directory my/denote-remote-notes-directory) (setq denote-directory new-dir)
(setq result (append result (apply orig-fun args))) (setq my/denote-metadata-index-file (concat denote-directory "../denote-metadata.org"))
(setq denote-directory original-dir) (message "Denote directory switched to %s" new-dir)))
result))
(defun my/denote-create-note () (defun my/denote-use-both-directories (orig-fun &rest args)
"Create a note in directory of choice." "Temporarily use both directories for a given ORIG-FUN and ARGS."
(interactive) (let ((original-dir denote-directory)
(let* ((dirs (list my/denote-local-notes-directory my/denote-remote-notes-directory)) (result nil))
(chosen-dir (completing-read "Choose directory: " dirs))) (setq denote-directory my/denote-local-notes-directory)
(let ((denote-directory chosen-dir)) (setq result (apply orig-fun args))
(call-interactively #'denote)))) (setq denote-directory my/denote-remote-notes-directory)
(setq result (append result (apply orig-fun args)))
(setq denote-directory original-dir)
result))
(advice-add 'denote-directory-files (defun my/denote-create-note ()
:around #'my/denote-use-both-directories) "Create a note in directory of choice."
(advice-add 'denote-directory-subdirectories (interactive)
:around #'my/denote-use-both-directories) (let* ((dirs (list my/denote-local-notes-directory my/denote-remote-notes-directory))
(chosen-dir (completing-read "Choose directory: " dirs)))
(let ((denote-directory chosen-dir))
(call-interactively #'denote))))
(global-set-key (kbd "C-x n f") #'my/denote-open-or-create) (advice-add 'denote-directory-files
(global-set-key (kbd "C-x n n") #'my/denote-create-note) :around #'my/denote-use-both-directories)
(global-set-key (kbd "C-x n d s") #'my/denote-switch-directory) (advice-add 'denote-directory-subdirectories
(global-set-key (kbd "C-x n d d") #'my/denote-echo-current-directory) :around #'my/denote-use-both-directories)
(global-set-key (kbd "C-x n f") #'my/denote-open-or-create)
(global-set-key (kbd "C-x n n") #'my/denote-create-note)
(global-set-key (kbd "C-x n d s") #'my/denote-switch-directory)
(global-set-key (kbd "C-x n d d") #'my/denote-echo-current-directory))
(provide 'module-denote-multidir) (provide 'module-denote-multidir)

View File

@ -11,42 +11,45 @@
(pkg/require 'denote) (pkg/require 'denote)
(denote-rename-buffer-mode 1) (with-eval-after-load 'denote
(setq denote-save-buffers nil (denote-rename-buffer-mode 1)
denote-known-keywords '("emacs" "golang" "dev")
denote-infer-keywords t
denote-sort-keywords t
denote-file-type nil
denote-history-completion-in-prompts nil
denote-prompts '(title keywords)
denote-excluded-directories-regexp nil
denote-excluded-keywords-regexp nil
denote-rename-confirmations '(rewrite-front-matter modify-file-name)
denote-date-prompt-use-org-read-date t
denote-date-format nil
denote-backlinks-show-context t)
(global-unset-key (kbd "C-x n")) (setq denote-save-buffers nil
(global-set-key (kbd "C-x n c") #'denote-region) denote-known-keywords '("emacs" "golang" "dev")
(global-set-key (kbd "C-x n !") #'denote-date) denote-infer-keywords t
(global-set-key (kbd "C-x n z") #'denote-signature) denote-sort-keywords t
(global-set-key (kbd "C-x n s") #'denote-subdirectory) denote-file-type nil
(global-set-key (kbd "C-x n S-n") #'denote-type) denote-history-completion-in-prompts nil
(global-set-key (kbd "C-x n t") #'denote-template) denote-prompts '(title keywords)
(global-set-key (kbd "C-x n l l") #'denote-link) denote-excluded-directories-regexp nil
(global-set-key (kbd "C-x n l a") #'denote-add-links) denote-excluded-keywords-regexp nil
(global-set-key (kbd "C-x n l f") #'denote-find-link) denote-rename-confirmations '(rewrite-front-matter modify-file-name)
(global-set-key (kbd "C-x n b l") #'denote-backlinks) denote-date-prompt-use-org-read-date t
(global-set-key (kbd "C-x n b f") #'denote-find-backlink) denote-date-format nil
(global-set-key (kbd "C-x n r r") #'denote-rename-file) denote-backlinks-show-context t)
(global-set-key (kbd "C-x n r f") #'denote-rename-file-using-front-matter)
(let ((map dired-mode-map)) (global-unset-key (kbd "C-x n"))
(define-key map (kbd "C-x n d") #'denote-dired-mode) (global-set-key (kbd "C-x n n") #'denote)
(define-key map (kbd "C-x n i") #'denote-link-dired-marked-notes) (global-set-key (kbd "C-x n c") #'denote-region)
(define-key map (kbd "C-x n k") #'denote-dired-rename-marked-files-with-keywords) (global-set-key (kbd "C-x n !") #'denote-date)
(define-key map (kbd "C-x n r r") #'denote-dired-rename-files) (global-set-key (kbd "C-x n z") #'denote-signature)
(define-key map (kbd "C-x n r f") #'denote-dired-rename-marked-files-using-front-matter)) (global-set-key (kbd "C-x n s") #'denote-subdirectory)
(global-set-key (kbd "C-x n S-n") #'denote-type)
(global-set-key (kbd "C-x n t") #'denote-template)
(global-set-key (kbd "C-x n l l") #'denote-link)
(global-set-key (kbd "C-x n l a") #'denote-add-links)
(global-set-key (kbd "C-x n l f") #'denote-find-link)
(global-set-key (kbd "C-x n b l") #'denote-backlinks)
(global-set-key (kbd "C-x n b f") #'denote-find-backlink)
(global-set-key (kbd "C-x n r r") #'denote-rename-file)
(global-set-key (kbd "C-x n r f") #'denote-rename-file-using-front-matter)
(let ((map dired-mode-map))
(define-key map (kbd "C-x n d") #'denote-dired-mode)
(define-key map (kbd "C-x n i") #'denote-link-dired-marked-notes)
(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)))
(provide 'module-denote) (provide 'module-denote)