branch: externals/denote
commit c73c4cf143852f0fc51ba8bb7824858ac9afe42b
Merge: 9a82b7d313 33ca6c25e3
Author: Protesilaos Stavrou <i...@protesilaos.com>
Commit: GitHub <nore...@github.com>

    Merge pull request #360 from 
jeanphilippegg/denote-file-name-components-order
    
    Add `denote-file-name-components-order` to allow reordering
---
 denote.el | 90 ++++++++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 63 insertions(+), 27 deletions(-)

diff --git a/denote.el b/denote.el
index cec061818e..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,35 +851,34 @@ 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.
-Hyphens, underscores and equal signs are replaced with a single
-one in str, if necessary according to COMPONENT."
-  ;; -- are allowed in titles
-  (if (eq component 'title)
-      (replace-regexp-in-string
-       "_\\{2,\\}" "_"
-       (replace-regexp-in-string
-        "=\\{2,\\}" "=" str))
-    (replace-regexp-in-string
-     "-\\{2,\\}" "-"
-     (replace-regexp-in-string
-      "_\\{2,\\}" "_"
+Hyphens, underscores, equal signs and at signs are replaced with
+a single one in str, if necessary according to COMPONENT."
+  (let ((str (replace-regexp-in-string
+              "_\\{2,\\}" "_"
+              (replace-regexp-in-string
+               "=\\{2,\\}" "="
+               (replace-regexp-in-string
+                "@\\{2,\\}" "@" str)))))
+    ;; -- are allowed in titles
+    (if (eq component 'title)
+        str
       (replace-regexp-in-string
-       "=\\{2,\\}" "=" str)))))
+       "-\\{2,\\}" "-" str))))
 
 (defun denote-sluggify (component str)
   "Make STR an appropriate slug for file name 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
@@ -1642,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.
@@ -1856,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