Next: , Previous: , Up: Events and the Event Loop   [Contents][Index]

13.2 Main Loop

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: , Previous: , Up: Events and the Event Loop   [Contents][Index]