Function: remove-hook

remove-hook is an interactive and byte-compiled function defined in subr.el.gz.

Signature

(remove-hook HOOK FUNCTION &optional LOCAL)

Documentation

Remove FUNCTION from HOOK's functions.

HOOK should be a symbol, and FUNCTION may be any valid function. Do nothing if HOOK does not currently contain FUNCTION. Compare functions with `equal`, which means that it can be slow if FUNCTION is not a symbol. See add-hook.

The optional third argument, LOCAL, if non-nil, says to modify the hook's buffer-local value rather than its default value.

Interactively, prompt for the various arguments (skipping local unless HOOK has both local and global functions). If multiple functions have the same representation under princ, the first one will be removed.

View in manual

Probably introduced at or before Emacs version 19.20.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/subr.el.gz
(defun remove-hook (hook function &optional local)
  "Remove FUNCTION from HOOK's functions.
HOOK should be a symbol, and FUNCTION may be any valid function.
Do nothing if HOOK does not currently contain FUNCTION.
Compare functions with `equal`, which means that it can be
slow if FUNCTION is not a symbol.  See `add-hook'.

The optional third argument, LOCAL, if non-nil, says to modify
the hook's buffer-local value rather than its default value.

Interactively, prompt for the various arguments (skipping local
unless HOOK has both local and global functions).  If multiple
functions have the same representation under `princ', the first
one will be removed."
  (interactive
   (let* ((default (and (symbolp (variable-at-point))
                        (symbol-name (variable-at-point))))
          (hook (intern (completing-read
                         (format-prompt "Hook variable" default)
                         obarray #'boundp t nil nil default)))
          (local
           (and
            (local-variable-p hook)
            (symbol-value hook)
            ;; No need to prompt if there's nothing global
            (or (not (default-value hook))
                (y-or-n-p (format "%s has a buffer-local binding, use that? "
                                  hook)))))
          (fn-alist (mapcar
                     (lambda (x) (cons (with-output-to-string (prin1 x)) x))
                     (if local (symbol-value hook) (default-value hook))))
          (function (alist-get (completing-read
                                (format "%s hook to remove: "
                                        (if local "Buffer-local" "Global"))
                                fn-alist
                                nil t nil 'set-variable-value-history)
                               fn-alist nil nil #'string=)))
     (list hook function local)))
  (or (boundp hook) (set hook nil))
  (or (default-boundp hook) (set-default hook nil))
  ;; Do nothing if LOCAL is t but this hook has no local binding.
  (unless (and local (not (local-variable-p hook)))
    ;; Detect the case where make-local-variable was used on a hook
    ;; and do what we used to do.
    (when (and (local-variable-p hook)
	       (not (and (consp (symbol-value hook))
			 (memq t (symbol-value hook)))))
      (setq local t))
    (let ((hook-value (if local (symbol-value hook) (default-value hook)))
          (old-fun nil))
      ;; Remove the function, for both the list and the non-list cases.
      (if (or (not (listp hook-value)) (eq (car hook-value) 'lambda))
	  (when (equal hook-value function)
	    (setq old-fun hook-value)
	    (setq hook-value nil))
	(when (setq old-fun (car (member function hook-value)))
	  (setq hook-value (remq old-fun hook-value))))
      (when old-fun
        ;; Remove auxiliary depth info to avoid leaks (bug#46414)
        ;; and to avoid the list growing too long.
        (let* ((depth-sym (get hook 'hook--depth-alist))
               (depth-alist (if depth-sym (if local (symbol-value depth-sym)
                                            (default-value depth-sym))))
               (di (assq old-fun depth-alist)))
          (when di
            (setf (if local (symbol-value depth-sym)
                    (default-value depth-sym))
                  (remq di depth-alist)))))
      ;; If the function is on the global hook, we need to shadow it locally
      ;;(when (and local (member function (default-value hook))
      ;;	       (not (member (cons 'not function) hook-value)))
      ;;  (push (cons 'not function) hook-value))
      ;; Set the actual variable
      (if (not local)
	  (set-default hook hook-value)
	(if (equal hook-value '(t))
	    (kill-local-variable hook)
	  (set hook hook-value))))))