>>>>> Tassilo Horn <[email protected]> writes:
> While you are at it, could you please add some TeX-add-to-alist tests to
> our suite.  Looking at your relevant diff hunk it is obvious that this
> function isn't trivial and some tests are justified.

OK, the attached revised patch includes a new test.

>> and `TeX-add-to-alist' runs without error for me, even without the
>> patch.

> Not for me.  Just eval in *scratch* which has lexical-binding at least
> in my emacs master checkout:
> (let ((alist nil))
>   (TeX-add-to-alist 'alist '((a 1)))
>   alist) ;; <== C-j here

Well, that wouldn't work even after my patch is applied. Here the symbol
`alist' is lexically scoped variable and the `symbol-value' causes
error, before `add-to-list' does.

When the first argument of `TeX-add-to-alist' is dynamic scope variable,
it runs without error in e.g. `LaTeX-arg-usepackage-insert', without my
patch.

(`TeX-add-to-alist' is used only for building
LaTeX-provided-{class,package}-options, thus I suppose it's enough that
`TeX-add-to-alist' allows only dynamic scope variable as its first
argument.)

Regards,
Ikumi Keita

diff --git a/tests/tex/utility.el b/tests/tex/utility.el
index 92442ba5..6078150d 100644
--- a/tests/tex/utility.el
+++ b/tests/tex/utility.el
@@ -1,6 +1,6 @@
 ;;; utility.el --- tests for AUCTeX utility functions
 
-;; Copyright (C) 2017 Free Software Foundation, Inc.
+;; Copyright (C) 2017, 2021 Free Software Foundation, Inc.
 
 ;; This file is part of AUCTeX.
 
@@ -28,4 +28,44 @@
   (should (TeX-delete-duplicate-strings '("nil")))
   (should (TeX-delete-dups-by-car '(("nil" . 1)))))
 
+(ert-deftest TeX-adding-to-alist ()
+  "Check whether `TeX-add-to-alist' works as expected."
+  ;; `TeX-add-to-alist' needs dynamically scope variable as its
+  ;; first argument, so it isn't allowed to enable lexical binding on
+  ;; this file.
+  ;; N.B. Even
+  ;; (unwind-protect
+  ;;   (progn
+  ;;      (defvar dummy-alist nil)
+  ;;      ...)
+  ;;   (makunbound 'dummy-alist))
+  ;; leaves the symbol `dummy-alist' as special variable, at least in
+  ;; emacs 27.1, contradicting to the instruction in
+  ;; (info "(ert)Tests and Their Environment"):
+  ;; ,----
+  ;; |   ...and if it has to make any changes to Emacs’s state or state
+  ;; |   external to Emacs (such as the file system), it should undo these
+  ;; |   changes before it returns, regardless of whether it passed or
+  ;; |   failed.
+  ;; `----
+  (let ((dummy-alist nil))
+    (TeX-add-to-alist 'dummy-alist '((a 1)))
+    (should (equal dummy-alist '((a 1))))
+
+    (TeX-add-to-alist 'dummy-alist '((b 2)))
+    (should (equal dummy-alist '((a 1) (b 2))))
+
+    (TeX-add-to-alist 'dummy-alist '((a 3)))
+    (should (equal dummy-alist '((b 2) (a 1 3))))
+
+    ;; Adding the same value again should not create duplicated
+    ;; elements.
+    (TeX-add-to-alist 'dummy-alist '((a 1)))
+    (should (equal dummy-alist '((b 2) (a 1 3))))
+
+    ;; A value which is the same as the key should be included in the
+    ;; result.
+    (TeX-add-to-alist 'dummy-alist '((a a)))
+    (should (equal dummy-alist '((b 2) (a 1 3 a))))))
+
 ;;; utility.el ends here
diff --git a/tex.el b/tex.el
index 8469dd05..915702f4 100644
--- a/tex.el
+++ b/tex.el
@@ -1365,7 +1365,7 @@ restarting Emacs."
                      ,(let (list)
                         ;; Build the list of available predicates.
                         (mapc (lambda (spec)
-                                (add-to-list 'list `(const ,(car spec))))
+                                (cl-pushnew `(const ,(car spec)) list :test #'equal))
                               (append TeX-view-predicate-list
                                       TeX-view-predicate-list-builtin))
                         ;; Sort the list alphabetically.
@@ -1421,7 +1421,7 @@ are evaluated positively is chosen."
                 ;; Offer list of defined predicates.
                 ,(let (list)
                    (mapc (lambda (spec)
-                           (add-to-list 'list `(const ,(car spec))))
+                           (cl-pushnew `(const ,(car spec)) list :test #'equal))
                          (append TeX-view-predicate-list
                                  TeX-view-predicate-list-builtin))
                    (setq list (sort list
@@ -1437,8 +1437,8 @@ are evaluated positively is chosen."
                 (group (choice :tag "Viewer"
                                ,@(let (list)
                                    (mapc (lambda (spec)
-                                           (add-to-list 'list
-                                                        `(const ,(car spec))))
+                                           (cl-pushnew `(const ,(car spec))
+                                                       list :test #'equal))
                                          (append TeX-view-program-list
                                                  TeX-view-program-list-builtin))
                                    (sort list
@@ -4713,9 +4713,11 @@ element to ALIST-VAR."
             (set alist-var (delete old-element (symbol-value alist-var)))
             ;; Append to `old-element' the values of the current element of
             ;; NEW-ALIST.
-            (mapc (lambda (elt) (add-to-list 'old-element elt t))
+            (mapc (lambda (elt)
+                    (unless (member elt (cdr old-element))
+                      (setq old-element (append old-element (list elt)))))
                   (cdr new-element))
-            (set alist-var (add-to-list alist-var old-element t)))
+            (add-to-list alist-var old-element t))
         (add-to-list alist-var new-element t)))
     ;; Next element of NEW-ALIST.
     (setq new-alist (cdr new-alist))))

Reply via email to