emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/denote 4041e437b2 214/355: Add PROTOTYPE of front matte


From: ELPA Syncer
Subject: [elpa] externals/denote 4041e437b2 214/355: Add PROTOTYPE of front matter rewrite post-rename
Date: Sun, 26 Jun 2022 23:58:26 -0400 (EDT)

branch: externals/denote
commit 4041e437b2c4f03302276bb71d41a5c91b4aefe5
Author: Protesilaos Stavrou <info@protesilaos.com>
Commit: Protesilaos Stavrou <info@protesilaos.com>

    Add PROTOTYPE of front matter rewrite post-rename
---
 denote-dired.el | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 103 insertions(+), 8 deletions(-)

diff --git a/denote-dired.el b/denote-dired.el
index 346b513b90..9619a49bce 100644
--- a/denote-dired.el
+++ b/denote-dired.el
@@ -62,7 +62,7 @@
 
 ;;; Code:
 
-(require 'denote)
+(require 'denote-retrieve)
 (require 'dired)
 
 (defgroup denote-dired ()
@@ -101,6 +101,26 @@ old name followed by the new one."
    ((denote-dired--file-attributes-time file))
    (t (format-time-string denote--id-format))))
 
+(defcustom denote-dired-post-rename-functions
+  (list #'denote-dired-rewrite-front-matter)
+  "List of functions called after `denote-dired-rename-file'.
+The function must accept three arguments: FILE, TITLE, and
+KEYWORDS.  The first is the full path to the file provided as a
+string, the second is the human-readable file name (not what
+Denote sluggifies) also as a string, and the third are the
+keywords.  If there is only one keyword, it is a string, else a
+list of strings.
+
+DEVELOPMENT NOTE: the `denote-dired-rewrite-front-matter' needs
+to be tested thoroughly.  It rewrites file contents so we have to
+be sure it does the right thing.  To avoid any trouble, it always
+asks for confirmation before performing the replacement.  This
+confirmation ignores `denote-dired-rename-expert' for the time
+being, though we might want to lift that restriction once
+everything works as intended."
+  :type 'hook
+  :group 'denote-dired)
+
 ;;;###autoload
 (defun denote-dired-rename-file (file title keywords)
   "Rename FILE to include TITLE and KEYWORDS.
@@ -143,13 +163,88 @@ attachments that the user adds to their notes."
                     keywords
                     (denote--sluggify title)
                     extension)))
-    (when (y-or-n-p
-           (format "Rename %s to %s?"
-                   (propertize old-name 'face 'error)
-                   (propertize (file-name-nondirectory new-name) 'face 
'success)))
-      (rename-file old-name new-name nil)
-      (when (eq major-mode 'dired-mode)
-        (revert-buffer)))))
+    (unless (string= old-name (file-name-nondirectory new-name))
+      (when (y-or-n-p
+             (format "Rename %s to %s?"
+                     (propertize old-name 'face 'error)
+                     (propertize (file-name-nondirectory new-name) 'face 
'success)))
+        (rename-file old-name new-name nil)
+        (when (derived-mode-p 'dired-mode)
+          (revert-buffer))
+        (run-hook-with-args 'denote-dired-post-rename-functions new-name title 
keywords)))))
+
+(defun denote-dired--file-meta-header (title date keywords id filetype)
+  "Front matter for renamed notes.
+
+TITLE, DATE, KEYWORDS, FILENAME, ID, and FILETYPE are all strings
+ which are provided by `denote-dired-rewrite-front-matter'."
+  (let ((kw-space (denote--file-meta-keywords keywords))
+        (kw-toml (denote--file-meta-keywords keywords 'toml)))
+    (pcase filetype
+      ('markdown-toml (format denote-toml-front-matter title date kw-toml id))
+      ('markdown-yaml (format denote-yaml-front-matter title date kw-space id))
+      ('text (format denote-text-front-matter title date kw-space id 
denote-text-front-matter-delimiter))
+      (_ (format denote-org-front-matter title date kw-space id)))))
+
+(defun denote-dired--filetype-heuristics (file)
+  "Return likely file type of FILE.
+The return value is for `denote--file-meta-header'."
+  (pcase (file-name-extension file)
+    ("md" (if (string-match-p "title\\s-*=" (denote-retrieve--value-title file 
0))
+              'markdown-toml
+            'markdown-yaml))
+    ("txt" 'text)
+    (_ 'org)))
+
+(defun denote-dired--front-matter-search-delimiter (filetype)
+  "Return likely front matter delimiter search for FILETYPE."
+  (pcase filetype
+    ('markdown-toml (re-search-forward "^\\+\\+\\+$" nil t 2))
+    ('markdown-yaml (re-search-forward "^---$" nil t 2))
+    ;; 2 at most, as the user might prepend it to the block as well.
+    ;; Though this might give us false positives, it ultimately is the
+    ;; user's fault.
+    ('text (or (re-search-forward denote-text-front-matter-delimiter nil t 2)
+               (re-search-forward denote-text-front-matter-delimiter nil t 1)
+               (re-search-forward "^[\s\t]*$" nil t 1)))
+    ;; Org does not have a real delimiter.  This is the trickiest one.
+    (_ (re-search-forward "^[\s\t]*$" nil t 1))))
+
+(defun denote-dired-rewrite-front-matter (file title keywords)
+  "Rewrite front matter of note after `denote-dired-rename-file'.
+The FILE, TITLE, and KEYWORDS are passed from the renaming
+ command and are used to construct a new front matter block."
+  (when (and (file-regular-p file)
+             (file-writable-p file)
+             ;; Heuristic to check if this is one of our notes
+             (string= default-directory (abbreviate-file-name 
(denote-directory))))
+    (let* ((id (denote-retrieve--filename-identifier file))
+           (date (denote-retrieve--value-date file))
+           (filetype (denote-dired--filetype-heuristics file))
+           (new-front-matter (denote--file-meta-header title date keywords id 
filetype))
+           old-front-matter
+           front-matter-delimiter)
+      (with-current-buffer (find-file-noselect file)
+        (save-excursion
+          (goto-char (point-min))
+          (setq old-front-matter
+                (buffer-substring-no-properties
+                 (point)
+                 (progn
+                   (setq front-matter-delimiter 
(denote-dired--front-matter-search-delimiter filetype))
+                   (point)))))
+        (when (and old-front-matter
+                   (y-or-n-p
+                    (format "%s\n%s\nReplace front matter?"
+                            (propertize old-front-matter 'face 'error)
+                            (propertize new-front-matter 'face 'success))))
+          (delete-region (point-min) front-matter-delimiter)
+          (goto-char (point-min))
+          (insert new-front-matter)
+          ;; FIXME 2022-06-16: Instead of `delete-blank-lines', we
+          ;; should check if we added any new lines and delete only
+          ;; those.
+          (delete-blank-lines))))))
 
 ;;;; Extra fontification
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]