gpt4 book ai didi

emacs - 从 Emacs 中的钩子(Hook)中删除特定 lambda 的函数

转载 作者:行者123 更新时间:2023-12-01 09:26:31 25 4
gpt4 key购买 nike

我找到了这个宏,为特定项目路径运行代码:

(defmacro project-specifics (name &rest body)
`(progn
(add-hook 'find-file-hook
(lambda ()
(when (string-match-p ,name (buffer-file-name))
,@body)))
(add-hook 'dired-after-readin-hook
(lambda ()
(when (string-match-p ,name (dired-current-directory))
,@body)))))

我用它:

(project-specifics "projects/test"
(message "z"))

我致力于修改以从钩子(Hook)中删除 prevoius lambda,到目前为止我有辅助函数

(defun remove-lambda-helper (list matcher)
(dolist (item list)
(if (and (listp item) (eq (car item) 'lambda))
(when (funcall matcher item)
(message "found")
(setq list (delete item list))))))

(defun remove-hook-name-lambda (name hook)
(remove-lambda-helper hook
(lambda (body)
(equal (cadr (cadr (caddr body))) name))))

但是当我打电话时:

(remove-hook-name-lambda "projects/test" find-file-hook)

found 显示在 *Messages* 缓冲区中,但 lambda 未被删除。这里有什么问题吗?

最佳答案

问题

原因可能是找到的对象是list中的第一个,此时(delete item list)返回 (cdr 列表) 而不是修改其结构以保留身份。

这里的重点是delete不能保证

(eq x (delete item x))
==> t

例如当itemx的唯一元素时,delete会返回nil,不能是eq 到原始的 cons

解决方案

解决方案是通过替换

remove-lambda-helper 返回列表的新值
(dolist (item list) ...)

(dolist (item list list) ...)

并在 remove-hook-name-lambda 中使用它,就像在 add-to-list 中一样:

(defun remove-hook-name-lambda (name hook-name)
(set hook-name
(remove-lambda-helper (symbol-value hook)
(lambda (body)
(equal (cadr (cadr (caddr body))) name)))))

最后的话

将 lambda 添加到 hooks 不是一个好主意,尤其是当你想稍后删除它们时。请注意,如果您碰巧编译了代码,您的 lambda 删除测试将会失败。

如果您修改了 Lambda,它们也会在钩子(Hook)中累积,例如,如果您有

(add-hook 'my-hook (lambda () ...))

然后您修改 lambda 并再次计算 add-hook 表单,您最终会在钩子(Hook)中有两个 lambda。

更好的解决方案是使用defun 来定义函数:

(defmacro add-project-specifics (name &rest body)
(let ((ffh (intern (concat name "-find-file-hook")))
(darh (intern (concat name "-dired-after-readin-hook"))))
`(progn
(defun ,ffh ()
(when (string-match-p ,name (buffer-file-name))
,@body))
(add-hook 'find-file-hook ',ffh)
(defun ,darh ()
(when (string-match-p ,name (dired-current-directory))
,@body))
(add-hook 'dired-after-readin-hook ',darh))))

(defmacro remove-project-specifics (name)
(let ((ffh (intern (concat name "-find-file-hook")))
(darh (intern (concat name "-dired-after-readin-hook"))))
`(progn
(remove-hook 'find-file-hook ',ffh)
(unintern ',ffh nil)
(remove-hook 'dired-after-readin-hook ',darh)
(unintern ',darh nil))))

附言

针对您在评论中表达的担忧,符号中的特殊字符是可以的,只要您在与读者打交道时引用它们即可;因为您不打算这样做 - 您将只使用 add-project-specificsremove-project-specifics - 实习他们应该没问题。

您实际问题的最佳解决方案

使用Per-Directory Local Variables.dir-locals.el 中。

关于emacs - 从 Emacs 中的钩子(Hook)中删除特定 lambda 的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22671045/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com