unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* remove-hook.
@ 2003-10-07 13:25 Lute Kamstra
  2003-10-07 13:40 ` remove-hook Luc Teirlinck
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Lute Kamstra @ 2003-10-07 13:25 UTC (permalink / raw)


The last sentence of remove-hook's docstring puzzles me:

,----[ C-h f remove-hook RET ]
| remove-hook is a compiled Lisp function in `subr'.
| (remove-hook HOOK FUNCTION &optional LOCAL)
| 
| Remove from the value of HOOK the function FUNCTION.
| HOOK should be a symbol, and FUNCTION may be any valid function.  If
| FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the
| list of hooks to run in HOOK, then nothing is done.  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.
| This makes the hook buffer-local if needed.
`----

When does remove-hook need to make a hook buffer-local to remove a
function from it?

  Lute.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: remove-hook.
  2003-10-07 13:25 remove-hook Lute Kamstra
@ 2003-10-07 13:40 ` Luc Teirlinck
  2003-10-07 13:42 ` remove-hook Stefan Monnier
  2003-10-08  4:52 ` remove-hook Richard Stallman
  2 siblings, 0 replies; 12+ messages in thread
From: Luc Teirlinck @ 2003-10-07 13:40 UTC (permalink / raw)
  Cc: emacs-devel

Lute Kamstra wrote:

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

   When does remove-hook need to make a hook buffer-local to remove a
   function from it?

When one only wants the function removed in the current buffer.  (As
the next to last sentence says.)

Sincerely,

Luc.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: remove-hook.
  2003-10-07 13:25 remove-hook Lute Kamstra
  2003-10-07 13:40 ` remove-hook Luc Teirlinck
@ 2003-10-07 13:42 ` Stefan Monnier
  2003-10-07 14:00   ` remove-hook Lute Kamstra
  2003-10-08  4:52 ` remove-hook Richard Stallman
  2 siblings, 1 reply; 12+ messages in thread
From: Stefan Monnier @ 2003-10-07 13:42 UTC (permalink / raw)
  Cc: emacs-devel

> When does remove-hook need to make a hook buffer-local to remove a
> function from it?

(add-hook 'foo-hook 'bar)
(remove-hook 'foo-hook 'bar 'local)


        Stefan


PS: Admittedly, this doesn't work in Emacs-CVS because the only way this
    can work is if we can put "negative" entries on the local side of
    a hook to disable an element on the global side.  I have code to make
    it work, but last time this came up RMS said it was overkill.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: remove-hook.
  2003-10-07 13:42 ` remove-hook Stefan Monnier
@ 2003-10-07 14:00   ` Lute Kamstra
  2003-10-07 14:59     ` remove-hook Stefan Monnier
  2003-10-08  4:52     ` remove-hook Richard Stallman
  0 siblings, 2 replies; 12+ messages in thread
From: Lute Kamstra @ 2003-10-07 14:00 UTC (permalink / raw)
  Cc: emacs-devel

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

>> When does remove-hook need to make a hook buffer-local to remove a
>> function from it?
>
> (add-hook 'foo-hook 'bar)
> (remove-hook 'foo-hook 'bar 'local)
>
>
> PS: Admittedly, this doesn't work in Emacs-CVS because the only way this
>     can work is if we can put "negative" entries on the local side of
>     a hook to disable an element on the global side.  

If it doesn't work, the docstring is confusing.

>     I have code to make it work, 

I'm curious... can I have a peek?

>     but last time this came up RMS said it was overkill.

I tend to agree that such a system would get rather complicated.  It
also seems necessary to keep remove-hook efficient: when I
instrumented it, I noticed that it was called twice every keystroke.


  Lute.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: remove-hook.
  2003-10-07 14:00   ` remove-hook Lute Kamstra
@ 2003-10-07 14:59     ` Stefan Monnier
  2003-10-07 15:13       ` remove-hook Lute Kamstra
  2003-10-08  4:52     ` remove-hook Richard Stallman
  1 sibling, 1 reply; 12+ messages in thread
From: Stefan Monnier @ 2003-10-07 14:59 UTC (permalink / raw)
  Cc: emacs-devel

>> PS: Admittedly, this doesn't work in Emacs-CVS because the only way this
>> can work is if we can put "negative" entries on the local side of
>> a hook to disable an element on the global side.  

> If it doesn't work, the docstring is confusing.

The docstring is still correct: if you pass the LOCAL flag and the hook has
no local side yet, `remove-hook' will create the local side of the hook.
It is a necessary first step for remove-hook to work.  Admittedly, it's
currently a useless step because the necessary second step doesn't
work anyway.

>> I have code to make it work, 
> I'm curious... can I have a peek?

Can't extract it right now, but it's pretty simple:
If there's no local `bar' element to remove, `remove-hook' adds a (not bar)
element.  When `run-hooks' sees such a (not bar) entry, it doesn't run
anything, but stuffs `bar' in a list of hooks to inhibit when processing
the global side of the hook.

> I tend to agree that such a system would get rather complicated.  It
> also seems necessary to keep remove-hook efficient: when I
> instrumented it, I noticed that it was called twice every keystroke.

I don't see how that calls for efficiency.  It's still tiny compared
to the time it takes for your keystroke to pass through the layers
and processing necessary for Emacs to get the event (and you can
add the time for Emacs to update its display, ...).


        Stefan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: remove-hook.
  2003-10-07 14:59     ` remove-hook Stefan Monnier
@ 2003-10-07 15:13       ` Lute Kamstra
  2003-10-07 15:24         ` remove-hook Stefan Monnier
  2003-10-07 22:04         ` remove-hook Luc Teirlinck
  0 siblings, 2 replies; 12+ messages in thread
From: Lute Kamstra @ 2003-10-07 15:13 UTC (permalink / raw)
  Cc: emacs-devel

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

>>> PS: Admittedly, this doesn't work in Emacs-CVS because the only way this
>>> can work is if we can put "negative" entries on the local side of
>>> a hook to disable an element on the global side.  
>
>> If it doesn't work, the docstring is confusing.
>
> The docstring is still correct: if you pass the LOCAL flag and the hook has
> no local side yet, `remove-hook' will create the local side of the hook.
> It is a necessary first step for remove-hook to work.  Admittedly, it's
> currently a useless step because the necessary second step doesn't
> work anyway.

The docstring is not really correct as remove-hook also removes the
buffer-local binding again:

      ...
      (if (equal hook-value '(t))
	  (kill-local-variable hook)
        ...


>>> I have code to make it work, 
>> I'm curious... can I have a peek?
>
> Can't extract it right now, but it's pretty simple: 
> If there's no local `bar' element to remove, `remove-hook' adds a
> (not bar) element.  When `run-hooks' sees such a (not bar) entry, it
> doesn't run anything, but stuffs `bar' in a list of hooks to inhibit
> when processing the global side of the hook.

And you still have the mechanism where t in the buffer-local value of
a hook is substituted by the functions in the global value?

>> I tend to agree that such a system would get rather complicated.
>> It also seems necessary to keep remove-hook efficient: when I
>> instrumented it, I noticed that it was called twice every
>> keystroke.
>
> I don't see how that calls for efficiency.  It's still tiny compared
> to the time it takes for your keystroke to pass through the layers
> and processing necessary for Emacs to get the event (and you can add
> the time for Emacs to update its display, ...).

I probably haven't developed a good intuition for these kind of speed
things yet.  :-(

  Lute.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: remove-hook.
  2003-10-07 15:13       ` remove-hook Lute Kamstra
@ 2003-10-07 15:24         ` Stefan Monnier
  2003-10-07 22:04         ` remove-hook Luc Teirlinck
  1 sibling, 0 replies; 12+ messages in thread
From: Stefan Monnier @ 2003-10-07 15:24 UTC (permalink / raw)
  Cc: emacs-devel

> And you still have the mechanism where t in the buffer-local value of
> a hook is substituted by the functions in the global value?

Sure.  Think of it as:

  (defun run-hook (h)
    (let ((inhibit nil)
          (funs (symbol-value h)))
      (while funs
        (let ((fun (pop funs)))
          (cond
           ((eq 'not (car-safe fun)) (push fun inhibit))
           ((member fun inhibit) nil)
           ((eq t fun) (setq funs (append (default-value h) funs)))
           (t (funcall fun)))))))


-- Stefan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: remove-hook.
  2003-10-07 15:13       ` remove-hook Lute Kamstra
  2003-10-07 15:24         ` remove-hook Stefan Monnier
@ 2003-10-07 22:04         ` Luc Teirlinck
  1 sibling, 0 replies; 12+ messages in thread
From: Luc Teirlinck @ 2003-10-07 22:04 UTC (permalink / raw)
  Cc: monnier, emacs-devel

Lute Kamstra wrote:

   If it doesn't work, the docstring is confusing.

I responded too quickly this morning.  I now remember the issues
involved and I now agree that the documentation string of
`remove-hook' is misleading.  It clearly suggests that one can use
`remove-hook' to buffer-locally remove FUNCTION from the
default-value, whereas one can not.  (Or at least not in one step,
although one could play tricks and remove the added `t' later, but I
do not believe one is really "supposed" to do that.)

Sincerely,

Luc.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: remove-hook.
  2003-10-07 13:25 remove-hook Lute Kamstra
  2003-10-07 13:40 ` remove-hook Luc Teirlinck
  2003-10-07 13:42 ` remove-hook Stefan Monnier
@ 2003-10-08  4:52 ` Richard Stallman
  2 siblings, 0 replies; 12+ messages in thread
From: Richard Stallman @ 2003-10-08  4:52 UTC (permalink / raw)
  Cc: emacs-devel

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

    When does remove-hook need to make a hook buffer-local to remove a
    function from it?

I am not sure any more why it does that, or whether it is
really necessary, but that is indeed what the code does.
Perhaps the reason is to prevent it from removing a global
hook when lOCAL is non-nil.

It also deletes buffer-local values when there is no more
need for them.

Anyway, this seems like a cleaner definition overall.
But does it work right?



(defun remove-hook (hook function &optional local)
  "Remove from the value of HOOK the function FUNCTION.
HOOK should be a symbol, and FUNCTION may be any valid function.  If
FUNCTION isn't the value of HOOK, or, if FUNCTION doesn't appear in the
list of hooks to run in HOOK, then nothing is done.  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."
  (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))))
      ;; Remove the function, for both the list and the non-list cases.
      (if (or (not (listp hook-value)) (eq (car hook-value) 'lambda))
	  (if (equal hook-value function) (setq hook-value nil))
	(setq hook-value (delete function (copy-sequence hook-value))))
      ;; 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))))))

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: remove-hook.
  2003-10-07 14:00   ` remove-hook Lute Kamstra
  2003-10-07 14:59     ` remove-hook Stefan Monnier
@ 2003-10-08  4:52     ` Richard Stallman
  2003-10-10 14:25       ` remove-hook Lute Kamstra
  1 sibling, 1 reply; 12+ messages in thread
From: Richard Stallman @ 2003-10-08  4:52 UTC (permalink / raw)
  Cc: monnier, emacs-devel

    It
    also seems necessary to keep remove-hook efficient: when I
    instrumented it, I noticed that it was called twice every keystroke.

That really surprises me.  Who is calling it, and why?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: remove-hook.
  2003-10-08  4:52     ` remove-hook Richard Stallman
@ 2003-10-10 14:25       ` Lute Kamstra
  2003-10-11 17:12         ` remove-hook Richard Stallman
  0 siblings, 1 reply; 12+ messages in thread
From: Lute Kamstra @ 2003-10-10 14:25 UTC (permalink / raw)
  Cc: monnier, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     It also seems necessary to keep remove-hook efficient: when I
>     instrumented it, I noticed that it was called twice every
>     keystroke.
>
> That really surprises me.  Who is calling it, and why?

I tried to figure this out, but it is rather annoying, to say the
least.  Once I instrument remove-hook, almost every key I press
triggers Edebug (one or more times).  Who is calling remove hook to do
what depends on which features are turned on.  I also get the
impression (not sure, though) that Edebug itself causes remove-hook to
be called.  The horror, the horror...

Before I went insane, I did manage to come up with a simple and,
hopefully, easy to reproduce example.  Start Emacs with "emacs -q
--no-site-file lisp/subr.el" and do "C-u C-M-x" on remove-hook.  Now
try moving around the buffer a bit.  Every keystroke will warp you
into Edebug due to a (remove-hook 'pre-command-hook
'blink-cursor-end).

If you want to go insane too, start Emacs with "emacs -q
--no-site-file lisp/subr.el", do "M-x global-font-lock-mode", and do
"C-u C-M-x" on remove-hook.  Now switch to the *scratch* buffer with
"C-x b RET" (this will invoke Edebug some 12 times, just `c' through
them) and then try to type something into the *scratch* buffer.  Every
insertion evokes Edebug 5 times.

Enjoy!

  Lute.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: remove-hook.
  2003-10-10 14:25       ` remove-hook Lute Kamstra
@ 2003-10-11 17:12         ` Richard Stallman
  0 siblings, 0 replies; 12+ messages in thread
From: Richard Stallman @ 2003-10-11 17:12 UTC (permalink / raw)
  Cc: monnier, emacs-devel

    I tried to figure this out, but it is rather annoying, to say the
    least.  Once I instrument remove-hook, almost every key I press
    triggers Edebug (one or more times).

A simpler and safer method is just to make remove-hook do (beep)
at the beginning.  Then you can put a breakpoint at Fbeep using gdb
and find out where it is called from.

However, when I put (beep) into remove-hook, ordinary editing doesn't
even beep.  So I guess remove-hook is not called for every key
in my environment.  Probably some mode you enabled is what does it.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2003-10-11 17:12 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-10-07 13:25 remove-hook Lute Kamstra
2003-10-07 13:40 ` remove-hook Luc Teirlinck
2003-10-07 13:42 ` remove-hook Stefan Monnier
2003-10-07 14:00   ` remove-hook Lute Kamstra
2003-10-07 14:59     ` remove-hook Stefan Monnier
2003-10-07 15:13       ` remove-hook Lute Kamstra
2003-10-07 15:24         ` remove-hook Stefan Monnier
2003-10-07 22:04         ` remove-hook Luc Teirlinck
2003-10-08  4:52     ` remove-hook Richard Stallman
2003-10-10 14:25       ` remove-hook Lute Kamstra
2003-10-11 17:12         ` remove-hook Richard Stallman
2003-10-08  4:52 ` remove-hook Richard Stallman

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).