Find empty notes and put them in a Dired buffer
[ This feature is based on the command denote-sort-dired (Sort files by component). ]
Users may have a workflow where they use the commands denote-link-or-create or denote-link-after-creating (and related) to produce new notes that they plan to elaborate on later (Link to an existing note or create a new one).
To help users find those empty notes, we document the following commands:
my-denote-sort-dired-empty-filesmy-denote-sort-dired-without-empty-filesmy-denote-sort-dired-all-empty-filesmy-denote-sort-dired-without-all-empty-files
emacs-lisp
(defun my-denote--note-has-no-contents-p (file)
"Return non-nil if FILE is an empty note.
This means that FILE conforms with `denote-file-is-note-p' and either
has no contents or has only the front matter."
(and (denote-file-is-note-p file)
(or (denote--file-with-temp-buffer file
(re-search-forward "^$" nil t)
(if (re-search-forward "[^\s\t\n\r]+" nil t)
nil
t))
;; This must come later because here we consider a file
;; "empty" even if it only has front matter.
(denote--file-empty-p file))))
(defun my-denote-sort-dired-empty-files (files-matching-regexp sort-by-component reverse exclude-regexp)
"Like `denote-sort-dired' but only cover empty files.
Empty files are those that satisfy `my-denote--note-has-no-contents-p'."
(interactive (append (list (denote-files-matching-regexp-prompt)) (denote-sort-dired--prompts)))
(pcase-let* ((`(,component . ,reverse-sort) (denote-sort-dired--get-sort-parameters sort-by-component reverse))
(relative-p (denote-has-single-denote-directory-p))
(files-fn `(lambda ()
(let* ((files (denote-sort-get-directory-files ,files-matching-regexp ',component ,reverse-sort))
(empty-files (seq-filter #'my-denote--note-has-no-contents-p files)))
(if relative-p
(mapcar #'file-relative-name empty-files)
empty-files)))))
(if-let* ((directory (if relative-p ; see comment in `denote-file-prompt'
(car (denote-directories))
(denote-directories-get-common-root)))
(files (funcall files-fn))
(buffer-name (funcall denote-sort-dired-buffer-name-function (format "%s (EMPTY)" files-matching-regexp) sort-by-component reverse-sort exclude-regexp)))
(denote-sort-dired--prepare-buffer directory files-fn buffer-name)
(message "No matching files for: %s" files-matching-regexp))))
(defun my-denote-sort-dired-without-empty-files (files-matching-regexp sort-by-component reverse exclude-regexp)
"Like `denote-sort-dired' but omit empty files.
Empty files are those that satisfy `my-denote--note-has-no-contents-p'."
(interactive (append (list (denote-files-matching-regexp-prompt)) (denote-sort-dired--prompts)))
(pcase-let* ((`(,component . ,reverse-sort) (denote-sort-dired--get-sort-parameters sort-by-component reverse))
(relative-p (denote-has-single-denote-directory-p))
(files-fn `(lambda ()
(let* ((files (denote-sort-get-directory-files ,files-matching-regexp ',component ,reverse-sort))
(empty-files (seq-remove #'my-denote--note-has-no-contents-p files)))
(if relative-p
(mapcar #'file-relative-name empty-files)
empty-files)))))
(if-let* ((directory (if relative-p ; see comment in `denote-file-prompt'
(car (denote-directories))
(denote-directories-get-common-root)))
(files (funcall files-fn))
(buffer-name (funcall denote-sort-dired-buffer-name-function (format "%s (OMIT EMPTY)" files-matching-regexp) sort-by-component reverse-sort exclude-regexp)))
(denote-sort-dired--prepare-buffer directory files-fn buffer-name)
(message "No matching files for: %s" files-matching-regexp))))
(defun my-denote-sort-dired-all-empty-files ()
"List all empty files in a Dired buffer.
This is the same as calling `my-denote-sort-dired' with a
FILES-MATCHING-REGEXP of \".*\"."
(declare (interactive-only t))
(interactive)
(pcase-let ((`(,sort-by ,reverse ,exclude-rx) (denote-sort-dired--prompts)))
(my-denote-sort-dired-empty-files ".*" sort-by reverse exclude-rx)))
(defun my-denote-sort-dired-without-all-empty-files ()
"List all empty files in a Dired buffer.
This is the same as calling `my-denote-sort-dired' with a
FILES-MATCHING-REGEXP of \".*\"."
(declare (interactive-only t))
(interactive)
(pcase-let ((`(,sort-by ,reverse ,exclude-rx) (denote-sort-dired--prompts)))
(my-denote-sort-dired-without-empty-files ".*" sort-by reverse exclude-rx)))[ In the above snippet, I am purposefully duplicating code to make it easier for users to pick the ones they need. ]