branch: externals/denote
commit 33ca6c25e30acbb72801ada43b0dbbec424ca943
Author: Jean-Philippe Gagné Guay <jeanphilippe...@gmail.com>
Commit: Jean-Philippe Gagné Guay <jeanphilippe...@gmail.com>

    Add denote-file-name-components-order to allow reordering
---
 denote.el | 69 +++++++++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 54 insertions(+), 15 deletions(-)

diff --git a/denote.el b/denote.el
index 3e25aa3924..e54bd4045a 100644
--- a/denote.el
+++ b/denote.el
@@ -303,6 +303,32 @@ Also see `denote-history-completion-in-prompts'."
                      (const :tag "Template" template)
                      (const :tag "Signature" signature))))
 
+(defvar denote-file-name-components-order '(identifier signature title 
keywords)
+  "Specify the order of the file name components of new notes.
+
+The value is a list of the following symbols:
+
+- `identifier': An identifier in a file name looks like
+  \"20240101T111111\" if it appears as the first component.
+  Else, it is prepended with \"@@\" if it appears anywhere else
+  in the file name.
+
+- `signature': A signature in a file name is an arbitrary string
+  that combines \"==\" with the signature of
+  `denote-signature-prompt'.
+
+- `title': A title in a file name is an arbitrary string that
+  combines \"--\" with the title of `denote-title-prompt'.
+
+- `keywords': Keywords in a file name are represented as a string
+  that combines \"__\" with the keywords of
+  `denote-keywords-prompt' separated with an underscore.
+
+All the symbols above must appear exactly once.  Any symbol
+missing will be added automatically.
+
+See also `denote-prompts'.")
+
 (defcustom denote-sort-keywords t
   "Whether to sort keywords in new files.
 
@@ -825,11 +851,11 @@ leading and trailing hyphen."
   (replace-regexp-in-string "\\." "" str))
 
 (defun denote--trim-right-token-characters (str component)
-  "Remove =, - and _ from the end of STR.
+  "Remove =, -, _ and @ from the end of STR.
 The removal is done only if necessary according to COMPONENT."
   (if (eq component 'title)
-      (string-trim-right str "[=_]+")
-    (string-trim-right str "[=_-]+")))
+      (string-trim-right str "[=@_]+")
+    (string-trim-right str "[=@_-]+")))
 
 (defun denote--replace-consecutive-token-characters (str component)
   "Replace consecutive characters with a single one in STR.
@@ -838,7 +864,9 @@ a single one in str, if necessary according to COMPONENT."
   (let ((str (replace-regexp-in-string
               "_\\{2,\\}" "_"
               (replace-regexp-in-string
-               "=\\{2,\\}" "=" str))))
+               "=\\{2,\\}" "="
+               (replace-regexp-in-string
+                "@\\{2,\\}" "@" str)))))
     ;; -- are allowed in titles
     (if (eq component 'title)
         str
@@ -850,7 +878,7 @@ a single one in str, if necessary according to COMPONENT."
 
 Apply the function specified in `denote-file-name-slug-function'
 to COMPONENT which is one of `title', `signature', `keyword'.  If
-the resulting string still contains consecutive -,_ or =, they
+the resulting string still contains consecutive -,_,= or @, they
 are replaced by a single occurence of the character, if necessary
 according to COMPONENT.  If COMPONENT is `keyword', remove
 underscores from STR as they are used as the keywords separator
@@ -1639,8 +1667,10 @@ contain the newline."
 To create a new one, refer to the function
 `denote-create-unique-file-identifier'."
   (let ((filename (file-name-nondirectory file)))
-    (if (string-match (concat "\\`" denote-id-regexp) filename)
-        (match-string-no-properties 0 filename))))
+    (cond ((string-match (concat "\\`" denote-id-regexp) filename)
+           (match-string-no-properties 0 filename))
+          ((string-match (concat "@@\\(?1:" denote-id-regexp "\\)") filename)
+           (match-string-no-properties 1 filename)))))
 
 ;; TODO 2023-12-08: Maybe we can only use
 ;; `denote-retrieve-filename-identifier' and remove this function.
@@ -1853,14 +1883,23 @@ which case it is not added to the base file name."
     (error "ID must not be an empty string"))
    ((not (string-match-p denote-id-regexp id))
     (error "ID `%s' does not match `denote-id-regexp'" id)))
-  (let ((file-name (concat dir-path id)))
-    (when (and signature (not (string-empty-p signature)))
-      (setq file-name (concat file-name "==" (denote-sluggify 'signature 
signature))))
-    (when (and title (not (string-empty-p title)))
-      (setq file-name (concat file-name "--" (denote-sluggify 'title title))))
-    (when keywords
-      (setq file-name (concat file-name "__" (denote-keywords-combine 
(denote-sluggify-keywords keywords)))))
-    (concat file-name extension)))
+  (let ((file-name "")
+        (components (seq-union denote-file-name-components-order
+                               '(identifier signature title keywords))))
+    (dolist (component components)
+      (cond ((and (eq component 'identifier) id (not (string-empty-p id)))
+             (setq file-name (concat file-name "@@" id)))
+            ((and (eq component 'title) title (not (string-empty-p title)))
+             (setq file-name (concat file-name "--" (denote-sluggify 'title 
title))))
+            ((and (eq component 'keywords) keywords)
+             (setq file-name (concat file-name "__" (denote-keywords-combine 
(denote-sluggify-keywords keywords)))))
+            ((and (eq component 'signature) signature (not (string-empty-p 
signature)))
+             (setq file-name (concat file-name "==" (denote-sluggify 
'signature signature))))))
+    (setq file-name (concat file-name extension))
+    ;; Do not prepend identifier with @@ if it is the first component.
+    (when (string-prefix-p "@@" file-name)
+      (setq file-name (substring file-name 2)))
+    (concat dir-path file-name)))
 
 (defun denote--format-front-matter-title (title file-type)
   "Format TITLE according to FILE-TYPE for the file's front matter."

Reply via email to