我将以下数据结构作为ELisp变量(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")))
我可以使用cddadr
将我需要的列表部分隔离开来,
但我需要在此列表中添加一个元素:
((("---" 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")))
我尝试了add-to-list
,但显然我需要cddadr
部分的符号名称(我可以在技术上优化到cadr
)add-to-list
工作
我如何实现我需要的结果?
最佳尝试:
(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))))))
答案 0 :(得分:1)
我认为你的方法中缺少list
:
(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)))))))
在您的版本中,相关列表的结构会发生变化。在修改之前,它是一个conses列表。修改后,它是一个混合列表。大多数条目是conses但最后一个car是一个字符串,最后一个cdr也是一个字符串。
除setcdr
和last
之外,您可以使用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)))))))
接下来是一项测试。为了与原始发布中的所需结果进行比较,我将"\\\\end[ \n]*{[ \n]*%s"
替换为"end%s"
,将"[ \n]*}"
替换为""
中的LaTeX-ispell-skip-environment
。在progn
结束时,(LaTeX-ispell-skip-environment "env3")
的结果将使用equal
针对所需结果进行测试。测试返回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")))))
答案 1 :(得分:1)
为了更笼统地回答标题中的问题,这里有一个函数,它在列表的第 n 个位置插入一个元素:
(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)))