jcu*_*bic 3 emacs hook lambda elisp
我找到了这个宏,用于运行特定项目路径的代码:
(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)))))
Run Code Online (Sandbox Code Playgroud)
我用它:
(project-specifics "projects/test"
(message "z"))
Run Code Online (Sandbox Code Playgroud)
我正在做一些修改工作,该工作将从钩子中删除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))))
Run Code Online (Sandbox Code Playgroud)
但是当我打电话时:
(remove-hook-name-lambda "projects/test" find-file-hook)
Run Code Online (Sandbox Code Playgroud)
发现的内容显示在*Messages*缓冲区中,但未删除lambda。怎么了
原因可能是找到的对象是in 中的第一个对象list,在这种情况下,(delete item list)返回(cdr list)而不是修改其结构以保留身份。
这里的重点是delete 不能保证
(eq x (delete item x))
==> t
Run Code Online (Sandbox Code Playgroud)
例如,当item是的唯一元素时x,delete将会返回原来nil不能返回eq的值cons。
解决方案是通过替换返回 list的新值remove-lambda-helper
(dolist (item list) ...)
Run Code Online (Sandbox Code Playgroud)
与
(dolist (item list list) ...)
Run Code Online (Sandbox Code Playgroud)
并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)))))
Run Code Online (Sandbox Code Playgroud)
在钩子上添加lambda不是一个好主意,尤其是如果您以后要删除它们时。请注意,如果您碰巧编译代码,则lambda删除测试将失败。
如果您修改Lambda,它们也会在钩子中累积,例如,如果您有
(add-hook 'my-hook (lambda () ...))
Run Code Online (Sandbox Code Playgroud)
然后修改lambda并add-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))))
Run Code Online (Sandbox Code Playgroud)
回应您在评论中表达的关注,只要您在与读者打交道时引用符号,就可以使用符号中的特殊字符;因为您不打算这样做-您只会使用add-project-specifics和remove-project-specifics-实习他们应该没问题。
使用每目录局部变量在.dir-locals.el。