Reputation: 3658
I have the following data structure as an ELisp variable (ispell-tex-skip-alists
):
((("---" ispell-tex-arg-end 2)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end)
("---" . "---"))
(("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end 2)
("env1" . "endenv1")
("env2" . "endenv2")))
I can isolate the part of the list I need with with cddadr
,
but I need to add an element to this list:
((("---" ispell-tex-arg-end 2)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end)
("---" . "---"))
(("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end 2)
("env1" . "endenv1")
("env2" . "endenv2")
("env3" . "endenv3")))
I have tried add-to-list
, but obviously I need a symbol name for the cddadr
part of the list (which I could technically optimize to cadr
) for add-to-list
to work.
How might I achieve the result I need?
Best attempt:
(defun LaTeX-ispell-skip-environment (env &optional star)
(let ((start (concat "%s" (if star "\\*?")))
(end (concat "\\\\end[ \n]*{[ \n]*%s" (if star "\\*?") "[ \n]*}")))
(let ((env-list (cddadr ispell-tex-skip-alists)))
(setcdr (last env-list)
(cons (format start env)
(format end env))))))
Upvotes: 2
Views: 1428
Reputation: 25187
To answer the question stated in the title more generically, here is a function which inserts an element in the n-th position of a list:
(defun insert-into-list (list el n)
"Insert into list LIST an element EL at index N.
If N is 0, EL is inserted before the first element.
The resulting list is returned. As the list contents is mutated
in-place, the old list reference does not remain valid."
(let* ((padded-list (cons nil list))
(c (nthcdr n padded-list)))
(setcdr c (cons el (cdr c)))
(cdr padded-list)))
Upvotes: 5
Reputation: 5198
I assume you are missing a list
in your approach:
(defun LaTeX-ispell-skip-environment (env &optional star)
(let ((start (concat "%s" (if star "\\*?")))
(end (concat "\\\\end[ \n]*{[ \n]*%s" (if star "\\*?") "[ \n]*}")))
(let ((env-list (cddadr ispell-tex-skip-alists)))
(setcdr (last env-list)
(list
(cons (format start env)
(format end env)))))))
In your version the structure of the relevant list changes. Before the modification it is a list of conses. After the modification it is a mixed list. Most of the entries are conses but the last car is a string and the last cdr is also a string.
Alternatively to setcdr
and last
, you could use nconc
:
(defun LaTeX-ispell-skip-environment (env &optional star)
(let ((start (concat "%s" (if star "\\*?")))
(end (concat "\\\\end[ \n]*{[ \n]*%s" (if star "\\*?") "[ \n]*}")))
(let ((env-list (cddadr ispell-tex-skip-alists)))
(nconc env-list
(list
(cons (format start env)
(format end env)))))))
There follows a test. To make comparison with the wanted result from the original posting possible I replaced "\\\\end[ \n]*{[ \n]*%s"
by "end%s"
and "[ \n]*}"
by ""
in LaTeX-ispell-skip-environment
. At the end of the progn
the result of (LaTeX-ispell-skip-environment "env3")
is tested with equal
against the wanted result. The test returns t
.
(progn
(defun LaTeX-ispell-skip-environment (env &optional star)
(let ((start (concat "%s" (if star "\\*?")))
(end (concat "end%s" (if star "\\*?") "")))
(let ((env-list (cddadr ispell-tex-skip-alists)))
(setcdr (last env-list)
(list
(cons (format start env)
(format end env)))))))
(setq ispell-tex-skip-alists
'((("---" ispell-tex-arg-end 2)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end)
("---" . "---"))
(("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end 2)
("env1" . "endenv1")
("env2" . "endenv2"))))
(LaTeX-ispell-skip-environment "env3")
(equal ispell-tex-skip-alists
'((("---" ispell-tex-arg-end 2)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end)
("---" . "---"))
(("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end 2)
("env1" . "endenv1")
("env2" . "endenv2")
("env3" . "endenv3")))))
Upvotes: 1