The Problem
The reason is probably that the found object is the first in list
, in which case (delete item list)
returns (cdr list)
instead of modifying its structure to preserve identity.
The important point here is that delete
cannot guarantee that
(eq x (delete item x))
==> t
e.g. when item
is the only element of x
, delete
will return nil
which cannot be eq
to the original cons
.
The Solution
The solution is to return the new value of list from remove-lambda-helper
by replacing
(dolist (item list) ...)
with
(dolist (item list list) ...)
and use it in remove-hook-name-lambda
like in 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)))))
The Final Remark
Adding lambdas to hooks is not a very good idea, especially if you want to remove them later. Note that your lambda removal test will fail if you happen to compile your code.
Lambdas also accumulate in the hook if you modify them, e.g., if you have
(add-hook 'my-hook (lambda () ...))
and then you modify the lambda
and evaluate the add-hook
form again, you will end up with two lambdas in the hook.
The much better solution is to use defun
to define the functions:
(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))))
PS
Responding to the concern you expressed in a comment, special characters in symbols are okay as long as you quote them when dealing with the reader; since you are not going to do that - you will be only using add-project-specifics
and remove-project-specifics
- you should be fine with interning them.
The Best Solution to Your Actual Problem
Use Per-Directory Local Variables in .dir-locals.el
.