protesilaos / denote

Simple notes for Emacs with an efficient file-naming scheme
https://protesilaos.com/emacs/denote
GNU General Public License v3.0
545 stars 55 forks source link

Proposal: add frontmatter normalization functions #397

Closed ashton314 closed 4 months ago

ashton314 commented 4 months ago

Hi Prot, here's an idea I had, and I wanted to flesh it out here in an issue before working on it some more.

I have a bunch of files, but some of the frontmatter got made by a poorly-written script (i.e., a Perl script I wrote) so it doesn't look nice:

#+title: A senseless conversation
#+date: <2024-07-02 Tue>
#+identifier: 20240702T112233

or something like that. I'd like all the frontmatter to look like I had just made it with denote-add-front-matter. Here's a little bit of code I made to do this for org-mode files:

(defun aw/denote-normalize-org-frontmatter ()
  "Normalize the front-matter in an org-mode file."
  (interactive)
  (when-let* ((file (buffer-file-name))
              (denote-filename-is-note-p file)
              (type (denote-filetype-heuristics file))
              (title (denote-retrieve-title-value file type))
              (id (denote-retrieve-filename-identifier file)))
    (let ((kwds (denote-retrieve-keywords-value file type)))
      (delete-matching-lines "^#\\+title:.*$" (point-min) (point-max))
      (delete-matching-lines "^#\\+date:.*$" (point-min) (point-max))
      (delete-matching-lines "^#\\+identifier:.*$" (point-min) (point-max))
      (delete-matching-lines "^#\\+filetags:.*$" (point-min) (point-max))
      (denote--add-front-matter file title kwds id type)
      (delete-matching-lines "^$" (point) (- (point) 1)))))

How would you suggest adding such a thing to Denote? Would you want it? How would you want it to work?

Also, here's a sample transient function I made that I find helpful. I know this has been on your wishlist for some time, so maybe this can get thought-juices flowing in some people's brains :)

  (transient-define-prefix denote-transient ()
    "Denote dispatch"
    [["Note creation (d)"
      ("dd" "new note" denote)
      ("dj" "new or existing journal entry" denote-journal-extras-new-or-existing-entry)
      ("dc" "open or create" denote-open-or-create)
      ("dt" "new specifying date and time" denote-date)
      ("ds" "create in subdirectory " denote-subdirectory)]
     ["Reviewing (r)"
      ("rd" "notes this day" aw/notes-this-day)]]
    [["Bookkeeping (b)"
      ("br" "prompt and rename" denote-rename-file)
      ("bf" "rename with frontmatter" denote-rename-file-using-front-matter)
      ("ba" "add frontmatter" denote-add-front-matter)
      ("bk" "modify keywords" denote-rename-file-keywords)]
     ["Linking (l)"
      ("li" "insert link" denote-link)
      ("lb" "show backlinks" denote-backlinks)
      ("lg" "visit backlink" denote-find-backlink)
      ("lo" "org backlink block" denote-org-extras-dblock-insert-backlinks)]]
    [["Searching (s)"
      ("sd" "deft" deft)
      ("sn" "consult-notes" consult-notes)
      ("ss" "consult-notes search" consult-notes-search-in-all-notes)]])
protesilaos commented 4 months ago

From: Ashton Wiersdorf @.***> Date: Wed, 17 Jul 2024 22:44:54 -0700

[... 31 lines elided]

How would you suggest adding such a thing to Denote?

Maybe we can use the 'align-regexp' function?

I first created three notes. Then I manually modified their front matter to resemble what you showed me.

;; Create some files in the background.
(save-window-excursion
  (dotimes (n 3)
    (let ((denote-directory "/tmp/notes/")
          (denote-save-buffers t))
      (denote (format "Check front matter %s" n) '("denote" "testing")))))

Then I ran this:

;; Try to align the front matter
(let ((denote-directory "/tmp/notes/"))
  (dolist (file (denote-directory-files))
    (with-current-buffer (find-file-noselect file)
      (let ((beg (point-min))
            (end (save-excursion
                   (re-search-forward "^$")
                   (point))))
        (align-regexp beg end "\\(.*?:\\)\\(\s*\\)" 2 1 nil)))))

Of course, such code will need to be more sophisticated with the regexp it uses. This assumes the Org format.

Would you want it? How would you want it to work?

Nobody has asked for it before. I think we can have it in the manual for now and see how it goes.

Also, here's a sample transient function I made that I find helpful. I know this has been on your wishlist for some time, so maybe this can get thought-juices flowing in some people's brains :)

[... 27 lines elided]

I want to write a denote-transient.el at some point, but because we are not still supporting Emacs 28 I am delaying that plan. We will eventually make Emacs 29 the minimum requirement and then we can use the built-in transient.el.

-- Protesilaos Stavrou https://protesilaos.com

ashton314 commented 4 months ago

Maybe we can use the align-regexp function

That does have the virtue of being significantly simpler. I like it. The only thing it doesn't do is add missing lines. (E.g. if the #+identifier: … line is missing.) Maybe we run the regexp-align function, and then add missing lines if there are any?

Nobody has asked for it before. I think we can have it in the manual for now and see how it goes.

I like this idea. No commitment to the code base—just a potentially-useful feature for certain people.

transient… Emacs 29

Emacs 29 was such a good release. I understand not wanting to write that until it's built-in. Thank you for your thoughts and your work.

I'll go ahead and close this issue; I think this has been resolved well enough for now. Thanks again Prot!