Commit f6d62986 authored by Stefan Monnier's avatar Stefan Monnier

Don't reset post-command-hook to nil upon error.

* src/eval.c (enum run_hooks_condition): Remove.
(funcall_nil, funcall_not): New functions.
(run_hook_with_args): Call each function through a `funcall' argument.
Remove `cond' argument, now redundant.
(Frun_hooks, Frun_hook_with_args, Frun_hook_with_args_until_success)
(Frun_hook_with_args_until_failure): Adjust accordingly.
(run_hook_wrapped_funcall, Frun_hook_wrapped): New functions.
* src/keyboard.c (safe_run_hook_funcall): New function.
(safe_run_hooks_1, safe_run_hooks_error, safe_run_hooks): On error,
don't set the hook to nil, but remove the offending function instead.
(Qcommand_hook_internal): Remove, unused.
(syms_of_keyboard): Don't initialize Qcommand_hook_internal nor define
Vcommand_hook_internal.
* doc/lispref/commands.texi (Command Overview): post-command-hook is not reset
to nil any more.
parent 947b6566
2011-03-28 Stefan Monnier <monnier@iro.umontreal.ca>
* commands.texi (Command Overview): post-command-hook is not reset to
nil any more.
2011-03-19 Stefan Monnier <monnier@iro.umontreal.ca>
* strings.texi (String Conversion): Don't mention
......
......@@ -91,8 +91,9 @@ and also when the command loop is first entered. At that time,
Quitting is suppressed while running @code{pre-command-hook} and
@code{post-command-hook}. If an error happens while executing one of
these hooks, it terminates execution of the hook, and clears the hook
variable to @code{nil} so as to prevent an infinite loop of errors.
these hooks, it does not terminate execution of the hook; instead
the error is silenced and the function in which the error occurred
is removed from the hook.
A request coming into the Emacs server (@pxref{Emacs Server,,,
emacs, The GNU Emacs Manual}) runs these two hooks just as a keyboard
......
......@@ -748,6 +748,11 @@ sc.el, x-menu.el, rnews.el, rnewspost.el
* Lisp changes in Emacs 24.1
** pre/post-command-hook are not reset to nil upon error.
Instead, the offending function is removed.
** New low-level function run-hook-wrapped.
** byte-compile-disable-print-circle is obsolete.
** deferred-action-list and deferred-action-function are obsolete.
** Removed the stack-trace-on-error variable.
......
2011-03-28 Stefan Monnier <monnier@iro.umontreal.ca>
* keyboard.c (safe_run_hook_funcall): New function.
(safe_run_hooks_1, safe_run_hooks_error, safe_run_hooks): On error,
don't set the hook to nil, but remove the offending function instead.
(Qcommand_hook_internal): Remove, unused.
(syms_of_keyboard): Don't initialize Qcommand_hook_internal nor define
Vcommand_hook_internal.
* eval.c (enum run_hooks_condition): Remove.
(funcall_nil, funcall_not): New functions.
(run_hook_with_args): Call each function through a `funcall' argument.
Remove `cond' argument, now redundant.
(Frun_hooks, Frun_hook_with_args, Frun_hook_with_args_until_success)
(Frun_hook_with_args_until_failure): Adjust accordingly.
(run_hook_wrapped_funcall, Frun_hook_wrapped): New functions.
2011-03-28 Juanma Barranquero <lekktu@gmail.com>
* dispextern.h (string_buffer_position): Remove declaration.
This diff is collapsed.
......@@ -254,7 +254,6 @@ Lisp_Object Qecho_area_clear_hook;
/* Hooks to run before and after each command. */
Lisp_Object Qpre_command_hook;
Lisp_Object Qpost_command_hook;
Lisp_Object Qcommand_hook_internal;
Lisp_Object Qdeferred_action_function;
......@@ -1815,20 +1814,63 @@ adjust_point_for_property (EMACS_INT last_pt, int modified)
static Lisp_Object
safe_run_hooks_1 (void)
{
return Frun_hooks (1, &Vinhibit_quit);
eassert (CONSP (Vinhibit_quit));
return call0 (XCDR (Vinhibit_quit));
}
/* Subroutine for safe_run_hooks: handle an error by clearing out the hook. */
/* Subroutine for safe_run_hooks: handle an error by clearing out the function
from the hook. */
static Lisp_Object
safe_run_hooks_error (Lisp_Object data)
safe_run_hooks_error (Lisp_Object error_data)
{
Lisp_Object hook
= CONSP (Vinhibit_quit) ? XCAR (Vinhibit_quit) : Vinhibit_quit;
Lisp_Object fun = CONSP (Vinhibit_quit) ? XCDR (Vinhibit_quit) : Qnil;
Lisp_Object args[4];
args[0] = build_string ("Error in %s (%s): %s");
args[1] = hook;
args[2] = fun;
args[3] = error_data;
Fmessage (4, args);
if (SYMBOLP (hook))
{
Lisp_Object val;
int found = 0;
Lisp_Object newval = Qnil;
for (val = find_symbol_value (hook); CONSP (val); val = XCDR (val))
if (EQ (fun, XCAR (val)))
found = 1;
else
newval = Fcons (XCAR (val), newval);
if (found)
return Fset (hook, Fnreverse (newval));
/* Not found in the local part of the hook. Let's look at the global
part. */
newval = Qnil;
for (val = (NILP (Fdefault_boundp (hook)) ? Qnil
: Fdefault_value (hook));
CONSP (val); val = XCDR (val))
if (EQ (fun, XCAR (val)))
found = 1;
else
newval = Fcons (XCAR (val), newval);
if (found)
return Fset_default (hook, Fnreverse (newval));
}
return Qnil;
}
static Lisp_Object
safe_run_hook_funcall (int nargs, Lisp_Object *args)
{
Lisp_Object args[3];
args[0] = build_string ("Error in %s: %s");
args[1] = Vinhibit_quit;
args[2] = data;
Fmessage (3, args);
return Fset (Vinhibit_quit, Qnil);
eassert (nargs == 1);
if (CONSP (Vinhibit_quit))
XSETCDR (Vinhibit_quit, args[0]);
else
Vinhibit_quit = Fcons (Vinhibit_quit, args[0]);
return internal_condition_case (safe_run_hooks_1, Qt, safe_run_hooks_error);
}
/* If we get an error while running the hook, cause the hook variable
......@@ -1838,10 +1880,13 @@ safe_run_hooks_error (Lisp_Object data)
void
safe_run_hooks (Lisp_Object hook)
{
/* FIXME: our `internal_condition_case' does not provide any way to pass data
to its body or to its handlers other than via globals such as
dynamically-bound variables ;-) */
int count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, hook);
internal_condition_case (safe_run_hooks_1, Qt, safe_run_hooks_error);
run_hook_with_args (1, &hook, safe_run_hook_funcall);
unbind_to (count, Qnil);
}
......@@ -11438,9 +11483,6 @@ syms_of_keyboard (void)
Qdeferred_action_function = intern_c_string ("deferred-action-function");
staticpro (&Qdeferred_action_function);
Qcommand_hook_internal = intern_c_string ("command-hook-internal");
staticpro (&Qcommand_hook_internal);
Qfunction_key = intern_c_string ("function-key");
staticpro (&Qfunction_key);
Qmouse_click = intern_c_string ("mouse-click");
......@@ -11908,22 +11950,18 @@ Buffer modification stores t in this variable. */);
Qdeactivate_mark = intern_c_string ("deactivate-mark");
staticpro (&Qdeactivate_mark);
DEFVAR_LISP ("command-hook-internal", Vcommand_hook_internal,
doc: /* Temporary storage of `pre-command-hook' or `post-command-hook'. */);
Vcommand_hook_internal = Qnil;
DEFVAR_LISP ("pre-command-hook", Vpre_command_hook,
doc: /* Normal hook run before each command is executed.
If an unhandled error happens in running this hook,
the hook value is set to nil, since otherwise the error
might happen repeatedly and make Emacs nonfunctional. */);
the function in which the error occurred is unconditionally removed, since
otherwise the error might happen repeatedly and make Emacs nonfunctional. */);
Vpre_command_hook = Qnil;
DEFVAR_LISP ("post-command-hook", Vpost_command_hook,
doc: /* Normal hook run after each command is executed.
If an unhandled error happens in running this hook,
the hook value is set to nil, since otherwise the error
might happen repeatedly and make Emacs nonfunctional. */);
the function in which the error occurred is unconditionally removed, since
otherwise the error might happen repeatedly and make Emacs nonfunctional. */);
Vpost_command_hook = Qnil;
#if 0
......
......@@ -2278,7 +2278,7 @@ void staticpro (Lisp_Object *);
struct window;
struct frame;
/* Defined in data.c */
/* Defined in data.c. */
extern Lisp_Object Qnil, Qt, Qquote, Qlambda, Qsubr, Qunbound;
extern Lisp_Object Qerror_conditions, Qerror_message, Qtop_level;
extern Lisp_Object Qerror, Qquit, Qwrong_type_argument, Qargs_out_of_range;
......@@ -2812,7 +2812,7 @@ extern void init_obarray (void);
extern void init_lread (void);
extern void syms_of_lread (void);
/* Defined in eval.c */
/* Defined in eval.c. */
extern Lisp_Object Qautoload, Qexit, Qinteractive, Qcommandp, Qdefun, Qmacro;
extern Lisp_Object Qinhibit_quit;
extern Lisp_Object Vautoload_queue;
......@@ -2830,6 +2830,9 @@ EXFUN (Frun_hooks, MANY);
EXFUN (Frun_hook_with_args, MANY);
EXFUN (Frun_hook_with_args_until_failure, MANY);
extern void run_hook_with_args_2 (Lisp_Object, Lisp_Object, Lisp_Object);
extern Lisp_Object run_hook_with_args (int nargs, Lisp_Object *args,
Lisp_Object (*funcall)
(int nargs, Lisp_Object *args));
EXFUN (Fprogn, UNEVALLED);
EXFUN (Finteractive_p, 0);
EXFUN (Fthrow, 2) NO_RETURN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment