branch: externals/denote-sequence
commit c64e9468d83860fda3ddaecb9afa86b127d5e70b
Author: Protesilaos Stavrou <[email protected]>
Commit: Protesilaos Stavrou <[email protected]>

    Continue implementing the alphanumeric-delimited scheme
---
 denote-sequence.el            | 52 +++++++++++++++++++++++++++++++++++--------
 tests/denote-sequence-test.el | 28 +++++++++++++++++++++++
 2 files changed, 71 insertions(+), 9 deletions(-)

diff --git a/denote-sequence.el b/denote-sequence.el
index d2a1e27987..0c43db312d 100644
--- a/denote-sequence.el
+++ b/denote-sequence.el
@@ -63,9 +63,14 @@
   :link '(url-link :tag "Denote homepage" 
"https://protesilaos.com/emacs/denote";)
   :link '(url-link :tag "Denote Sequence homepage" 
"https://protesilaos.com/emacs/denote-sequence";))
 
+;; TODO 2026-03-24: The `alphanumeric-delimited' is not supporting partial 
sequences.
+;; This will probably be a problem for `denote-sequence-convert'.
 (defcustom denote-sequence-scheme 'numeric
   "Sequencing scheme to establish file hierarchies.
-The value is the symbol `numeric' or `alphanumeric'.
+The value is a symbol among `numeric', `alphanumeric', and
+`alphanumeric-delimited'.  Users can change the applicable scheme for
+one file or those marked in Dired by calling the command
+`denote-sequence-convert'.
 
 Numeric sequences (the default) are the easier to understand but also
 are the longest.  Each level of depth in the hierarchy is delimited by
@@ -79,10 +84,17 @@ that 1a2 refers to the second child of the first child of 
parent 1.
 Because they alternate between numbers and letters, they do not use the
 equals sign.  When a number cannot be represented by a single letter,
 two or more are used instead, such as the number 51 corresponding to
-zx (z is 26 and x is 25)."
+zx (z is 26 and x is 25).
+
+Alphanumeric delimited sequences combine elements of the aforementioned.
+Levels of depth are expressed as alternating numbers and letters, like
+with the `alphanumeric' scheme, while they also get the = as a separator
+as a visual aid for long sequences.  The sepator is inserted after the
+first level of depth and then after every third level, like 1=a2b=a1c."
   :group 'denote-sequence
   :type '(choice (const :tag "Numeric like 1=1=2" numeric)
-                 (const :tag "Alphanumeric like 1a2" alphanumeric)))
+                 (const :tag "Alphanumeric like 1a2" alphanumeric)
+                 (const :tag "Alphanumeric delimited like 1=a2b=a1c" 
alphanumeric-delimited)))
 
 (defconst denote-sequence-numeric-regexp "=?[0-9]+"
   "Pattern of a numeric sequence.")
@@ -189,6 +201,10 @@ Refer to the `denote-sequence-scheme' for the details."
     sequence)
    (t
     (when (and (string-match-p "=" sequence)
+               ;; TODO 2026-03-24: Probably this should not be here
+               ;; due to how we end up with this check.  See, for
+               ;; example, `denote-sequence-p' which already checks
+               ;; for the numeric before it reaches this one.
                (not (denote-sequence-numeric-p sequence)))
       (let ((strings (denote-sequence--alphanumeric-delimited-split sequence)))
         (when (and (denote-sequence--alphanumeric-delimited-check-alternation 
strings)
@@ -200,13 +216,15 @@ Refer to the `denote-sequence-scheme' for the details."
 Also see `denote-sequence-alphanumeric-p' and `denote-sequence-numeric-p'."
   (pcase denote-sequence-scheme
     ('numeric (denote-sequence-numeric-p sequence))
-    ('alphanumeric (denote-sequence-alphanumeric-p sequence))))
+    ('alphanumeric (denote-sequence-alphanumeric-p sequence))
+    ('alphanumeric-delimited (denote-sequence-alphanumeric-delimited-p 
sequence))))
 
 (defun denote-sequence-p (sequence)
   "Return SEQUENCE string is of a supported scheme.
 Also see `denote-sequence-numeric-p' and `denote-sequence-alphanumeric-p'."
   (when (or (denote-sequence-numeric-p sequence)
-            (denote-sequence-alphanumeric-p sequence))
+            (denote-sequence-alphanumeric-p sequence)
+            (denote-sequence-alphanumeric-delimited-p sequence))
     sequence))
 
 (defun denote-sequence-with-error-p (sequence)
@@ -236,6 +254,8 @@ of numbers or letters.
 
 Produce an error if the sequencing scheme cannot be established."
   (cond
+   ((and (not partial) (string-match-p "\\`[0-9]+\\'" sequence))
+    (cons sequence denote-sequence-scheme))
    ((and (not partial)
          (not (string-match-p "[[:alpha:]]" sequence))
          (eq denote-sequence-scheme 'numeric))
@@ -246,13 +266,24 @@ Produce an error if the sequencing scheme cannot be 
established."
    ((or (and partial (denote-sequence--numeric-partial-p sequence))
         (denote-sequence-numeric-p sequence))
     (cons sequence 'numeric))
+   ;; TODO 2026-03-24: Implement the 
`denote-sequence--alphanumeric-delimited-partial-p'.
+   ;; FIXME 2026-03-24: What are we even doing with those "partial" checks?
+   ((or ;; (and partial (denote-sequence--alphanumeric-delimited-partial-p 
sequence))
+        (denote-sequence-alphanumeric-delimited-p sequence))
+    (cons sequence 'alphanumeric-delimited))
    (t (error "The sequence `%s' does not pass `denote-sequence-and-scheme-p'" 
sequence))))
 
+;; FIXME 2026-03-24: This is technically incorrect because it assumes
+;; homogeneity of sequencing schemes.  But we never enforce as much.
 (defun denote-sequence--scheme-of-strings (strings)
   "Return the sequencing scheme of STRINGS, per `denote-sequence-scheme'."
-  (if (seq-find (lambda (string) (string-match-p "[[:alpha:]]" string)) 
strings)
-      'alphanumeric
-    'numeric))
+  (cond
+   ((seq-every-p #'denote-sequence-numeric-p strings)
+    'numeric)
+   ((seq-every-p #'denote-sequence-alphanumeric-p strings)
+    'alphanumeric)
+   ((seq-every-p #'denote-sequence-alphanumeric-delimited-p strings)
+    'alphanumeric-delimited)))
 
 (defun denote-sequence-file-p (file)
   "Return the sequence if Denote signature of FILE is a sequence.
@@ -275,7 +306,9 @@ SEQUENCE conforms with `denote-sequence-p'.  If PARTIAL is 
non-nil, it
 has the same meaning as in `denote-sequence-and-scheme-p'."
   (pcase-let* ((`(,sequence . ,scheme) (denote-sequence-and-scheme-p sequence 
partial)))
     (pcase scheme
-      ('numeric
+      ;; TODO 2026-03-24: The `alphanumeric-delimited' needs to handle
+      ;; partial sequences.
+      ((or 'numeric 'alphanumeric-delimited)
        (split-string sequence "=" t))
       ('alphanumeric
        (let ((strings nil)
@@ -358,6 +391,7 @@ has the same meaning as in `denote-sequence-and-scheme-p'."
                              parts)))
       (denote-sequence-join converted-parts 'alphanumeric))))
 
+;; TODO 2026-03-24: Add support for the `alphanumeric-delimited'.
 (defun denote-sequence-make-conversion (string &optional string-is-sequence)
   "Convert STRING to its counterpart sequencing scheme.
 If STRING-IS-SEQUENCE then assume STRING to be a complete sequence, in
diff --git a/tests/denote-sequence-test.el b/tests/denote-sequence-test.el
index c2d73520e0..f0cecd6ce2 100644
--- a/tests/denote-sequence-test.el
+++ b/tests/denote-sequence-test.el
@@ -95,6 +95,34 @@ levels of depth between delimiters."
   (should (string= (denote-sequence-alphanumeric-delimited-p "1=a1b") "1=a1b"))
   (should (string= (denote-sequence-alphanumeric-delimited-p "1=a1b=2a1") 
"1=a1b=2a1")))
 
+(ert-deftest dst-denote-sequence-and-scheme-p ()
+  "Test that `denote-sequence-and-scheme-p' covers all cases."
+  (should-error (denote-sequence-and-scheme-p "a"))
+  (should
+   (equal
+    (denote-sequence-and-scheme-p "1=1")
+    (cons "1=1" 'numeric)))
+  (should
+   (equal
+    (denote-sequence-and-scheme-p "1a")
+    (cons "1a" 'alphanumeric)))
+  (should
+   (equal
+    (denote-sequence-and-scheme-p "1=a")
+    (cons "1=a" 'alphanumeric-delimited)))
+  (should
+   (let ((denote-sequence-scheme 'numeric))
+     (equal (denote-sequence-and-scheme-p "1")
+            (cons "1" 'numeric))))
+  (should
+   (let ((denote-sequence-scheme 'alphanumeric))
+     (equal (denote-sequence-and-scheme-p "1")
+            (cons "1" 'alphanumeric))))
+  (should
+   (let ((denote-sequence-scheme 'alphanumeric-delimited))
+     (equal (denote-sequence-and-scheme-p "1")
+            (cons "1" 'alphanumeric-delimited)))))
+
 (ert-deftest dst-denote-sequence--get-new-exhaustive ()
   "Test if we get the correct parent, child, sibling, or relatives of a 
sequence.
 Use the function `denote-sequence-get-new' for child and sibling with

Reply via email to