branch: externals/auctex-label-numbers
commit a77c9ea1717a1cf20350672ae8d7afec7d97415e
Author: Paul Nelson <[email protected]>
Commit: Paul Nelson <[email protected]>

    Add option to customize the display prefix of external labels
    
    References resolved through distinct external documents were all
    displayed with the prefix "X", making them indistinguishable at a
    glance.  Name external documents A, B, ..., Z, AA, ... according to
    the order of their declarations, and let the user customize this.
    
    * auctex-label-numbers.el (auctex-label-numbers--ordinal-letters)
    (auctex-label-numbers-external-prefix-letter)
    (auctex-label-numbers-external-prefix-x): New functions.
    (auctex-label-numbers-external-prefix-function): New user option,
    defaulting to spreadsheet-style letters in declaration order.
    (auctex-label-numbers-label-to-number): Use it.
    * tests/auctex-label-numbers-tests.el
    (test-auctex-label-numbers-external-prefix-letter): New test.
---
 auctex-label-numbers.el             | 43 +++++++++++++++++++++++++++++++++++--
 tests/auctex-label-numbers-tests.el | 14 ++++++++++++
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/auctex-label-numbers.el b/auctex-label-numbers.el
index 7a6d5dac91c..81dc35586da 100644
--- a/auctex-label-numbers.el
+++ b/auctex-label-numbers.el
@@ -108,6 +108,39 @@ to find the corresponding aux files."
   "Regexp for \\externaldocument commands.
 Optional prefix is (match-string 1), filename is (match-string 2).")
 
+(defun auctex-label-numbers--ordinal-letters (ordinal)
+  "Return spreadsheet-style letters for ORDINAL: 1=A, ..., 26=Z, 27=AA."
+  (let ((result ""))
+    (while (> ordinal 0)
+      (setq ordinal (1- ordinal))
+      (setq result (concat (char-to-string (+ ?A (% ordinal 26))) result))
+      (setq ordinal (/ ordinal 26)))
+    result))
+
+(defun auctex-label-numbers-external-prefix-letter (ordinal _prefix _filename)
+  "Return letters A, B, ..., Z, AA, ... according to ORDINAL."
+  (auctex-label-numbers--ordinal-letters ordinal))
+
+(defun auctex-label-numbers-external-prefix-x (_ordinal _prefix _filename)
+  "Return the constant display prefix \"X\"."
+  "X")
+
+(defcustom auctex-label-numbers-external-prefix-function
+  #'auctex-label-numbers-external-prefix-letter
+  "Function computing the display prefix for external label numbers.
+Called with three arguments describing the \\externaldocument
+declaration through which a label was resolved: ORDINAL, the 1-based
+position of the declaration among those in the current document; PREFIX,
+the label prefix from the declaration's optional argument, or nil if
+there is none; and FILENAME, the declared file name.  The returned
+string is prepended to the label number in the folded display."
+  :type '(choice
+          (function-item :tag "Letters by declaration order (A, B, ...)"
+                         auctex-label-numbers-external-prefix-letter)
+          (function-item :tag "Constant \"X\""
+                         auctex-label-numbers-external-prefix-x)
+          (function :tag "Custom function")))
+
 (defun auctex-label-numbers--external-documents ()
   "Return the \\externaldocument declarations of the current buffer.
 The result is a list of (ORDINAL PREFIX FILENAME) lists, in buffer
@@ -131,7 +164,8 @@ nil for unprefixed declarations."
 If the buffer does not point to a file, or if the corresponding aux file
 does not exist, or if the label cannot be found, then return nil.
 Otherwise, return the label number as a string.  If the label is found
-in an external document, prefix the string with \"X\"."
+in an external document, prefix the string using
+`auctex-label-numbers-external-prefix-function'."
   (if auctex-label-numbers-label-to-number-function
       (funcall auctex-label-numbers-label-to-number-function label)
     (or
@@ -151,6 +185,7 @@ in an external document, prefix the string with \"X\"."
             found)
         (while (and (null found) declarations)
           (let* ((declaration (pop declarations))
+                 (ordinal (nth 0 declaration))
                  (prefix (nth 1 declaration))
                  (external (nth 2 declaration)))
             (when (or (null prefix) (string-prefix-p prefix label))
@@ -166,7 +201,11 @@ in an external document, prefix the string with \"X\"."
                 (when-let* ((_ aux-filename)
                             (number 
(auctex-label-numbers-label-to-number-helper
                                      bare-label aux-filename)))
-                  (setq found (concat "X" number)))))))
+                  (setq found
+                        (concat
+                         (funcall auctex-label-numbers-external-prefix-function
+                                  ordinal prefix external)
+                         number)))))))
         found)))))
 
 (defun auctex-label-numbers-preview-preprocessor (str)
diff --git a/tests/auctex-label-numbers-tests.el 
b/tests/auctex-label-numbers-tests.el
index d2bffb2cf42..8a23cd8c09c 100644
--- a/tests/auctex-label-numbers-tests.el
+++ b/tests/auctex-label-numbers-tests.el
@@ -114,5 +114,19 @@
                      (2 nil "beta")
                      (3 "C-" "gamma"))))))
 
+(ert-deftest test-auctex-label-numbers-external-prefix-letter ()
+  "Test spreadsheet-style external-document prefixes."
+  (dolist (case '((1 "A")
+                  (26 "Z")
+                  (27 "AA")
+                  (52 "AZ")
+                  (53 "BA")
+                  (702 "ZZ")
+                  (703 "AAA")))
+    (pcase-let ((`(,ordinal ,expected) case))
+      (should
+       (equal (auctex-label-numbers-external-prefix-letter ordinal nil nil)
+              expected)))))
+
 (provide 'auctex-label-numbers-tests)
 ;;; auctex-label-numbers-tests.el ends here

Reply via email to