Next: Specifics of the Event Gathering Mechanism, Previous: Introduction to Events, Up: Events and the Event Loop [Contents][Index]
The command loop is the top-level loop that the editor is always
running. It loops endlessly, calling next-event
to retrieve an
event and dispatch-event
to execute it. dispatch-event
does
the appropriate thing with non-user events (process, timeout,
magic, eval, mouse motion); this involves calling a Lisp handler
function, redrawing a newly-exposed part of a frame, reading
subprocess output, etc. For user events, dispatch-event
looks up the event in relevant keymaps or menubars; when a
full key sequence or menubar selection is reached, the appropriate
function is executed. dispatch-event
may have to keep state
across calls; this is done in the “command-builder” structure
associated with each console (remember, there’s usually only
one console), and the engine that looks up keystrokes and
constructs full key sequences is called the command builder.
This is documented elsewhere.
The guts of the command loop are in command_loop_1()
. This
function doesn’t catch errors, though—that’s the job of
command_loop_2()
, which is a condition-case (i.e. error-trapping)
wrapper around command_loop_1()
. command_loop_1()
never
returns, but may get thrown out of.
When an error occurs, cmd_error()
is called, which usually
invokes the Lisp error handler in command-error
; however, a
default error handler is provided if command-error
is nil
(e.g. during startup). The purpose of the error handler is simply to
display the error message and do associated cleanup; it does not need to
throw anywhere. When the error handler finishes, the condition-case in
command_loop_2()
will finish and command_loop_2()
will
reinvoke command_loop_1()
.
command_loop_2()
is invoked from three places: from
initial_command_loop()
(called from main()
at the end of
internal initialization), from the Lisp function recursive-edit
,
and from call_command_loop()
.
call_command_loop()
is called when a macro is started and when
the minibuffer is entered; normal termination of the macro or minibuffer
causes a throw out of the recursive command loop. (To
execute-kbd-macro
for macros and exit
for minibuffers.
Note also that the low-level minibuffer-entering function,
read-minibuffer-internal
, provides its own error handling and
does not need command_loop_2()
’s error encapsulation; so it tells
call_command_loop()
to invoke command_loop_1()
directly.)
Note that both read-minibuffer-internal and recursive-edit set up a
catch for exit
; this is why abort-recursive-edit
, which
throws to this catch, exits out of either one.
initial_command_loop()
, called from main()
, sets up a
catch for top-level
when invoking command_loop_2()
,
allowing functions to throw all the way to the top level if they really
need to. Before invoking command_loop_2()
,
initial_command_loop()
calls top_level_1()
, which handles
all of the startup stuff (creating the initial frame, handling the
command-line options, loading the user’s .emacs file, etc.). The
function that actually does this is in Lisp and is pointed to by the
variable top-level
; normally this function is
normal-top-level
. top_level_1()
is just an error-handling
wrapper similar to command_loop_2()
. Note also that
initial_command_loop()
sets up a catch for top-level
when
invoking top_level_1()
, just like when it invokes
command_loop_2()
.
Next: Specifics of the Event Gathering Mechanism, Previous: Introduction to Events, Up: Events and the Event Loop [Contents][Index]