>>>>> 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))))