Emacs and eev, or: How to Automate Almost EverythingEduardo Ochs
NOTE:
This document is unfinished and VERY obsolete!
Quick index:
1. Three kinds of interfacesInteractive programs in a Un*x system(1) can have basically three kinds of interfaces: they can be mouse-oriented, like most programs with graphical interfaces nowadays, in which commands are given by clicking with the mouse; they can be character-oriented, like most editors and mail readers, in which most commands are single keys or short sequences of keys; and they can be line-oriented, as, for example, shells are: in a shell commands are given by editing a full line and then typing “enter” to process that line. It is commonplace to classify computer users in a spectrum where the “users” are in one extreme and the “programmers” are in the other; the “users” tend to use only mouse-oriented and character-oriented programs, and the “programmers” only character-oriented and line-oriented programs. In this paper we will show a way to “automate” interactions with line-oriented programs, and, but not so well, to character-oriented programs; more precisely, it is a way to edit commands for these programs in a single central place --- Emacs --- and then send them to the programs; re-sending the same commands afterwards, with or without modifications, then becomes very easy. This way (“e-scripts”) can not be used to send commands to mouse-oriented programs --- at least not without introducing several new tricks. But “programmers” using Un*x systems usually see most mouse-oriented programs --- except for a few that are intrinsically mouse-oriented, like drawing programs --- as being just wrappers around line-oriented programs than perform the same tasks with different interfaces; and so, most mouse-oriented programs “do not matter”, and our method of automating interactions using e-scripts can be used to automate “almost everything”; hence the title of the paper. (1): Actually we are more interested in GNU systems than in “real” Unix systems; the reasons will become clear in the section nnn. By the way: the term “Unix” is Copyright (C) Bell Labs). 2. “Make each program do one thing well”One of the tenets of the Unix philosophy is that each program should do one thing, and do it well; this is a good design rule for Unix programs because the system makes it easy to invoke external programs to perform tasks, and to connect programs. Some of parts of a Unix system are more like “meta-programs” or
“sub-programs” than like self-contained programs that do some
clearly useful task by themselves. Shells, for example, are
meta-programs: their main function is to allow users to invoke “real
programs” and to connect these programs using pipes, redirections,
control structures (if, for, etc) and Unix “signals”. On the other
hand, libraries are sub-programs: for example, on GNU systems there's
a library called GNU readline that line-oriented programs can use to
get input; if a program, say, bc (a calculator) gets its input by
calling 3. Making programs receive commands[See also: code, miniature, INSTALL, eev-rctool ] Many line-oriented programs allow “scripting”, which means
executing commands from a file. For example, in most shells we can say
“ So, it is possible to prepare commands for a shell (or for
scriptable line-oriented programs; for arbitrary line-oriented
programs see the section nnn) in several ways: by typing them at the
shell's interface --- and if the shell uses readline its interface can
be reasonably friendly --- or, alternatively, by using a text editor
to edit a file, say,
~/.bashrc , ~/.zshrc ,
...) we can reduce “source ~/ee.sh ” to just “ee ”: e , e , enter --- three keystrokes.
We just saw how a shell --- or, by the way, any line-oriented
program in which we can define an `ee' function like we did for the
shell --- can receive commands prepared in an external editor and
stored in a certain file; let's refer to that file, 4. Sending commandsUpdate (2013feb11): see this instead: GNU Emacs, “the extensible, self-documenting text-editor” ([S79]), does at least two things very well: one is to edit text, and so it can be used to edit temporary scripts, and thus to send commands to shells and to line-oriented programs with `ee' functions; and the other one is to run Lisp. Lisp is a powerful programming language, and (at least in principle!) any action or series of actions can be expressed as a program in Lisp; the first thing that we want to do is a way to mark a region of a text and “send it as commands to a shell”, by saving it in a temporary script file. We implement that in two ways:
ee ' (the name stands for something like `emacs-execute') just
saves the currently-marked region of text to ~/ee.sh ; `eev '
(for something like `emacs-execute-verbose') does the same but adding
to the beginning of the temporary script a command to put the shell in
“verbose mode”, where each command is displayed before being
executed, and also adding at the end an command to leave verbose mode.
We can now use ` 5. HyperlinksUpdate (2013feb11): see this instead: When we are using a system like *NIX, in a part of the time we are using programs with which we are perfectly familiar, and in the rest of the time we are using things that we don't understand completely and that make us have to access the documentation from time to time. In a GNU system the documentation is all on-line, and the steps needed to access any piece of documentation can be automated. We can use Emacs Lisp “one-liners” to create “hyperlinks” to files:
These expressions, when executed --- which is done by placing the
cursor after them and then typing
The convention is that these “extended hyperlink functions” have
names like ` Here are the definitions of `find-node' and `find-fline':
Now consider what happens when we send to a shell a sequence of commands like this one:
the shell ignores the first line because of the ` Note: the actual definitions of ` (See also: the section about e-scripts). 6. Shorter HyperlinksUpdate (2013feb11): see this instead: The hyperlinks in lines
are equivalent to the ones labeled Eev defines a function called `
The arguments for ` 7. Keys for following hyperlinks and for going backUpdate (2013feb11): see this instead: (Rewrite this; mention M-k, M-K, `to' and the (disabled) stubs to implement a `back' command) It is so common to have Lisp hyperlinks that extend from some position in a line --- usually after a comment sign --- to the end of the line that eev implements a special key for executing these hyperlinks: the effect of typing M-e (when eev is installed and “eev mode” is on) is roughly the same of first going to the end of the line and then typing C-x C-e; that is, M-e does the same as the key sequence C-e C-x C-e(1). (There are many other kinds of hyperlinks. Examples?) (1) The main difference between 8. Dangerous hyperlinksNote that these “hyperlinks” can do very dangerous things. If we start to execute blindly every Lisp expression we see just because it can do something interesting or take us to an interesting place then we can end up running something like:
The modern approach to safety in hyperlinks --- the one found in
web browsers, for example --- is that following a hyperlink can
execute only a few kinds of actions, all known to be safe; the
“target” of a hyperlink is something of the form Eev's approach is the opposite of that. I wrote the first functions of eev in my first weeks after installing GNU/Linux in my home machine and starting using GNU Emacs, in 1994; before that I was using mostly Forth (on MS-DOS), and I hadn't had a lot of exposure to *nix systems by then --- in particular, I had tried to understand *nix's notions of user IDs and file ownerships and permissions, and I felt that they were a thick layer of complexity that I wasn't being able to get through. Forth's attitude is more like ``the user knows what he's doing''; the system is kept very simple, so that understanding all the consequences of an action is not very hard. If the user wants to change a byte in a critical memory position and crash the machine he can do that, and partly because of that simplicity bringing the machine up again didn't use to take more than one minute (in the good old days, of course). Forth people developed good backup strategies to cope with the insecurities, and --- as strange as that might sound nowadays, where all machines are connected and multi-user and crackers abound --- using the system in the Forth way was productive and fun. *NIX systems are not like Forth, but when I started using them I
was accustomed to this idea of achieving simplicity through the lack
of safeguards, and eev reflects that. The only thing that keeps eev's
hyperlinks reasonably safe is transparency: the code that a
hyperlink executes is so visible that it is hard to mistake a
dangerous Lisp expression for a “real” hyperlink. Also, all the safe
hyperlink functions implemented by eev start with `
wget --help ”, puts the output of that in an Emacs
buffer and then jumps to the first occurrence of the string “recursive download ” there; other `find-xxxsh ' functions are
variations on that that execute some extra shell commands before
executing the first argument --- typically either switching to another
directory or loading an initialization file, like ~/.bashrc or
~/.zshrc . The `find-xxxsh0 ' functions are similar to their
`find-xxxsh ' counterparts, but instead of creating a buffer with
their output they just show it at Emacs's echo area and they use only
the first argument and ignore the others (the pos-spec).
9. Generating Hyperlinks[See also: code] Do we need to remember the names of all hyperlinks functions, like
Eev implements several functions that create temporary buffers
containing hyperlinks, that can then be cut and pasted to other
buffers. For example, `
The first line of that buffer is a hyperlink to that
dynamically-generated page of hyperlinks. Its function --- `
The argument to `eek' is a string describing a sequence of keys in
a certain verbose format, and the effect of running, say, ((M-h is a prefix; ((Exceptions: M-h M-c, M-h M-2, M-h M-y. Show examples of how to edit hyperlinks with M-h M-2 and M-h M-y.)) ((Mention hyperlinks about a key sequence? ((Mention hyperlinks about a Debian package? 10. Returning from Hyperlinks((Mention M-k to kill the current buffer, and how Emacs asks for confirmation when it's a file and it's modified)) ((Mention M-K for burying the current buffer)) ((Mention what to do in the cases where a hyperlink points to the current buffer (section 16); there used to be an “ee-back” function bound to M-B, but to reactivate it I would have to add back some ugly code to `to'... (by the way, that included Rubikitch's contributions))) ((Web browsers have a way to “return” from hyperlinks: the “back” button... In eev we have many kinds of hyperlinks, including some that are unsafe and irreversible, but we have a few kinds of “back”s that work... 1) if the hyperlink opened a new file or buffer, then to kill the file or buffer, use M-k (an eev binding for kill-this-buffer); note that it asks for a confirmation when the buffer is associated to a file and it has been modified --- or we can use bury-buffer; M-K is an eev binding for bury-buffer. ((explain how emacs keeps a list of buffers?)) Note: if the buffer contains, say, a manpage, or an html page rendered by w3m, which take a significant time to generate, then M-K is better is than M-k. 2) if the hyperlink was a `to' then it jumped to another position in the same file... it is possible to keep a list of previous positions in a buffer and to create an `ee-back' function (suggestion: bind it to M-B) but I haver never been satisfied with the implementations that I did so we're only keeping a hook in `to' for a function that saves the current position before the jump)) ((dto recommended winner-undo)) 11. Local copies of files from the internetUpdate (2013feb11): see this instead: [See also: code, code, eev-rctool, m.list, gmane] Emacs knows how to fetch files from the internet, but for most
purposes it is better to use local copies. Suppose that the
environment variable
emacs-paper.html inside ~/snarf/http/ . The two last lines are hyperlinks to the local copy;
`find-w3m ' opens it “as HTML”, using a web browser called w3m
that can be run either in standalone mode or inside Emacs; `find-w3m ' uses w3m's Emacs interface, and it accepts extra arguments,
which are treated as a pos-spec-list.
Instead of running the `
~/.psne.log ). It is more convenient to have a `psne ' that
changes the current directory of the shell than one that doesn't, and
for that it must be defined as a shell function.
Eev comes with an installer script, called
((See: http://lists.gnu.org/archive/html/eev/2005-06/msg00000.html)) 12. Glyphs[See also: code, code, miniature flipbook] Emacs allows redefining how characters are displayed, and one of
the modules of eev --- eev-glyphs --- uses that to make some
characters stand out. Character 15, for example, is displayed on the
screen by default as ' Eev changes the appearance of char 15 to make it be displayed as a
red star. Here is how: Emacs has some structures called “faces” that
store font and color information, and `
For this article, as red doesn't print well in black and white, we used this instead:
* ' (note that this is outside of the ascii range), using the default
face, i.e., the default font and color.
Eev also sets a few other glyphs with non-standard faces. The most
important of those are `
« ' and `» ' only
have character codes 171 and 187 in a few cases, mainly in the
`raw-text' encoding and in “unibyte” buffers; in most other
encodings they have other char codes, usually above 255, and when they
have these other codes Emacs considers that they are other characters
for which no special glyphs were set and shows them in the default
face. This visual distinction between the below-255 `« ' and ` ' and the other `« ' and `» 's is deliberate --- it helps
preventing some subtle bugs involving the anchor functions of section
\ref{anchors}.
(3). Determined by the “face” escape-glyph-face, introduced in GNU Emacs in late 2004. 13. Compose Pairs[See also: code] To insert a ` Eev-compose defines a few variables that hold tables of “compose
pairs”, which map pairs of characters that are easy to type into
other, weirder characters; for example, `eev-composes-otheriso' says
that the pair " The variable ` 14. Delimited regionsUpdate (2013feb11): see this instead: [See also: code, miniature, shot, anim] Sometimes it happens that we need to run a certain (long) series of commands over and over again, maybe with some changes from one run to the next; then having to mark the block all the time becomes a hassle. One alternative to that is using a variaton on ` The original definition of eev-bounded was something like this:
ee-search-backwards ' searches for the first
occurrence of the string "\n#*\n " (newline, hash sign, control-O,
newline) before the cursor and returns the position after the "\n#*\n ", without moving the cursor; the call to ee-search-forward does something similar with a forward search. As
the arguments to `eev ' indicate the extremities of the region to
be saved into the temporary script, this saves the region between the
first "\n#*\n " backwards from the cursor to the first "\n#*\n " after the cursor.
The actual definition of `
Eev binds the key F3 to the function ` All these defaults values come from a single list, which is stored
in the variable `
Note that in Emacs Lisp (and in most other Lisps) each symbol has a
value as a variable that is independent from its “value as a
function”: actually a symbol is a structure containg a name, a
“value cell”, a “function cell” and a few other fields. Our
definition of ` Eev has an auxiliary function for defining these “bounded functions”; running
setq ' and the `defun '
above.
As for the meaning of the entries of the list ` Eev also implements other of these “bounded” functions. For
example, running `
ee-delimiter-percent ' holds the string "\n%*\n "; comments in LaTeX start with percent signs, not hash signs,
and it is convenient to use delimiters that are treated as comments.
((The block below ... tricky ... blah. How to typeset `
...for example eelatex, that saves the region (plus certain standard header and footer lines) to a “temporary LaTeX file” and saves into the temporary script file the commands to make `ee' run LaTeX on that and display the result. The block below is an example of (...) ...The block below shows a typical application of
((Comment about the size: the above code is “too small for being a script”, and the hyperlinks are important)) gdb (here-documents, gcc, ee-once) (alternative: here-documents, gcc, gdb, screenshot(s) for gdb) 15. Communication channelsUpdate (2013feb11): see this instead: [See also: code, code, miniature, anim] The way that we saw to send commands to a shell is in two steps:
first we use
The screenshot at Figure 3 shows this at work. The user has started
with the cursor at the second line from the top of the screen in the
Emacs window and then has typed F9 several times. Eev binds F9 to a
command that operates on the current line and then moves down to the
next line; if the current line starts with ` The first F9 executed ` The next two ` The next line had just ` In the following lines there is a small shell program that outputs
“ There are also ways to send whole blocks of lines at once through communication channels; see Section \ref{bigmodular}. 15.1. The Implementation of Communication Channels[See also: code, code, miniature, anim] [2007: There's a much better explanation, with nice ascii diagrams, at channels.anim; it should be merged here.] Communication channels are implemented using an auxiliary script
called `eegchannel', which is written in Expect ([L90] and [L95]). If we start an xterm in the default way it starts a shell (say,
Eegchannel passes characters back and forth between the xterm and the shell without changing them in any way; it mostly tries to pretend that it is not there and that the xterm is communicating directly with the shell. However, when eegchannel receives a certain signal it sends to the shell a certain sequence of characters that were not sent by the xterm; it “fakes a sequence of keystrokes”. Let's see a concrete example. Suppose than Emacs was running with
process id (“pid”) 1000, and running
and xterm invoked eegchannel with “
in a shell sends the string “ 16. AnchorsUpdate (2013feb11): see this instead: [See also: code] The function `
What `to' does is simply to wrap its argument inside ` The function `
does roughly the same as:
Actually ` 17. E-scriptsThe best short definition for eev that I've found involves some
cheating, as it is a circular definition: “eev is a library that adds
support for e-scripts to Emacs” --- and e-scripts are files that
contain chunks meant to be processed by eev's functions. Almost any
file can contain parts “meant for eev”: for example, a
in a Lua script, and the script will be at the same time a Lua script and an e-script. When I started using GNU and Emacs the notion of an e-script was something quite precise to me: I was keeping notes on what I was learning and on all that I was trying to do, and I was keeping those notes in a format that was partly English (or Portuguese), partly executable things --- not all of them finished, or working --- after all, it was much more practical to write
than to write
because if I had the second form in my notes I would have to translate that from English into machine commands every time... So, those files where I was keeping my notes contained “executable notes”, or were “scripts for Emacs”, and I was quite sure that everyone else around were also keeping notes in executable formats, possibly using other editors and environments (vi, maybe?) and that if I showed these people my notes and they were about some task that they were also struggling with then they would also show me their notes... I ended up making a system that uploaded regularly all my e-scripts (no matter how messy they were) to my home page, and writing a text --- “The Eev Manifesto” ([O99]) --- about sharing these executable notes. Actually trying to define an e-script as being “a file containing executable parts, that are picked up and executed interactively” makes the concept of an e-script very loose. Note that we can execute the Lua parts in the code above by
running the Lua interpreter on it, we can execute the elisp
one-liner with A piece of code containing instructions in English on how to use it is also an e-script, in a sense; but to execute these instructions we need to invoke an external entity --- a human, usually ourselves --- to interpret them. This is much more flexible, but also much more error-prone and slow, than just pressing a simple sequence of keys like M-e, or F9, or F3, alt-tab, e, e, enter. 18. Splitting eev.elWhen I first submittted eev for inclusion in GNU Emacs, in 1999, the people at the FSF requested some changes. One of them was to split eev.el --- the code at that point was all in a single Emacs Lisp file, called eev.el --- into several separate source files according to functionality; at least the code for saving temporary scripts and the code for hyperlinks should be kept separate. It turned out that that was the wrong way of splitting eev. The frontier between what is a hyperlink and what is a block of commands is blurry:
The two ` So, what happens is that often a new kind of hyperlink will begin
its life as a series of shell commands (another example: using ` There's a much better way to split conceptually what eev does, though. Most functions in eev take a region of text (for example Emacs's own “selected region”, or the extent of Lisp expression coming before the cursor) and “execute” that in some way; the kinds of regions are
Actions (can be composed): * Saving a region or a string into a file * Sending a signal to a process * Executing as Lisp * Executing immediately in a shell * Start a debugger ((Emacs terminology: commands)) 19. Steps[See also: code, miniature, flipbook] ((Simple examples)) ((writing demos)) ((hyperlinks for which no short form is known)) ((producing animations and screenshots)) 20. Sending lines to processes running in Emacs buffersUpdate (oct/2011): PLEASE IGNORE THIS! This part of eev has been completely rewritten - see:
(These sections - 20 to 24 - are very new (handwritten in 2007jul12, typed a few days later). They are early drafts, full of errors, describing some code that does not yet exist (ee-tbr), etc. Also, I don't know Rubikitch's real name, so I used a random Japanese name...) Emacs can run external programs interactively inside buffers; in the screenshot in Figure 5 there's a shell running in the buffer "*shell*" in the lower window. Technically, what is going on is much more complex than what we described in the previous section. The shell runs in a pseudo-terminal (pty), but ptys are usually associated to rectangular grids of characters with a definite width and height, while in an Emacs buffer the width of each line, and the total number of lines,are only limited by memory constraints. Many interactive programs expect their input to come through their more-or-less minimalistic line editors, that may try to send to the terminal commands like "clear the screen" or "go to column x at line y"; how should these things be handled in a shell buffer? Also, the user can move freely in a shell buffer, and edit its contents as text, but the "Return" key becomes special: when it is hit in a shell buffer Emacs takes the current line - except maybe some initial characters that are seen as a prompt - and sends that to the shell process, as if the user had typed exactly that; so, Emacs takes over the line editor of the shell process completely. The translation between character sequences going through the pty and buffer-editing functions is very tricky, full of non-obvious design choices, and even though it has been around for more than 20 years it still has some (inevitable) quirks. I almost never used shell buffers, so I found the following idea, by OGAMI Itto, very surprising when he sent it to the eev mailing list in 2005.
The current window, above in Figure 5, is editing an e-script, and the other window shows a shell buffer - that we will refer to as the "target buffer". When the user types a certain key - by default F8 - the current line is sent to the target buffer, and the point is moved down to the next line; pressing F8 n times in sequence sendsn lines, one by one. One detail: "sending a line" means inserting its contents - except the newline - at the current position in the target buffer, and then running there the action associated to the "Return" key. "Return" is almost always a special key, bound to different actions in different major modes, so just inserting a newline would not work - that would not simulate what happens when a user types "Return". Note that, in a sense, the action of F8 is much more complex than that of F9, described in the last section; but user might perceive F8 as being much simpler, as there are no external programs involved (Expect, eegchannel, xterm), and no setup hassles - all the machinery to make Emacs buffers invoke external processes in buffers pretending to be terminals ("comint mode") comes built-in with Emacs since the early 1980s. Ogami's idea also included three "bonus features": window setup, reconstruction of the target buffer, and star-escapes. In the default Emacs setting some commands - M-x shell between them - might split the current Emacs frame in two windows; none of eev's hyperlink functions do that, and I have always felt that it is more natural to use eev with a setting (pop-up-windows set to nil) that disables window splittings except when explicitly requested by the user. Anyway: M-x shell ensures that a "*shell*" buffer is visible in a window, and that a shell process is running in it; this setup code for F8,
splits the window (if the frame has just one window), and runs `(shell)' in the other window - with the right defaults - to force that window to display a shell buffer with a live shell process running in it; it also sets a variable, `eepitch-target-buffer', to that buffer, so that the next `F8's will have a definite buffer to send lines too - as target buffers need not necessarily be shell buffers. As for the star-escapes, it's the same idea as with F9: when a line
starts with a red star glyph, running F8 on it executes everything on
it - after the red star - as Lisp, and if there are no errors the
point is moved down. So lines starting with a red star can be used to
set up an eepitch target, to switch to another target, or to do
special actions - like killing a certain target so that it will be
reconstructed anew by the next F8. Note that once that we recognize
that a region of an e-script is to be used by eepitch there is only
one key to be used to "run" each of its lines, both the ones with red
stars and the ones without: F8. However, as with F9, the user must
know what to expect after each step. A badly-written e-script for
eepitch may try, for example, to "cd" into a directory that does not
exist, and if the next line is, say, " 21. Using eepitch to control unprepared shells
As we have seen in section 4, M-x eev sends the region to a "prepared shell"; if the shell has the right settings for the environment variables $EEVTMPDIR and $EE, and if it has the shell function `ee', then running `ee' in the shell "sources" the temporary script - corresponding to the regin - in verbose mode. Well, if Emacs loads eev.el and the environment variables $EEVDIR, $EEVTMPDIR and $EE are not set, then they are set, respectively, to the directory where eev.el was read from, to the subdirectory of it given by $EEVDIR/tmp, and to the file $EEVTMPDIR/ee.sh. Processes started from Emacs inherit these environment variables, so a shell buffer created by running F8 on these two lines,
will be running a prepared shell. Such buffers can be used to let users understand better how prepared shells work, and decide if they want to patch their initialization files for the shell (see eev-rctool) so that their shells will be "prepared" by default. (Note: I haven't yet played much with this idea - discuss running eev-rctool on such shells (and a function that creates a buffer with an e-script for that), and loading psne.sh from an unprepared shell). 22. Controlling debuggers with eepitch[See also: .emacs, m.list, gmane]
On *NIX it is common to keep debuggers separated into two parts: a back-end, with a simple textual interface, and a front-end, that controls the back-end via its textual interface but presents a better interface, showing source files and breakpoints in a nice way, etc. The GNU Debugger, GDB, is a back-end, and it can be used to debug and single-step several compiled languages; the "Grand Unified Debugger" mode of Emacs, a.k.a. GUD, is a front-end for GDB and other back-ends. Usually, GUD splits an Emacs frame into two windows, one for interaction with GDB (or other back-end, but let's say just "GDB" for simplicity), and another one for displaying the source file where the execution is. Some of the output of GDB - lines meaning, e.g., "we're at the source file foo.c, at line 25" - are filtered by GUD and are not shown in the GUD buffer; and the user can press special key sequences on source files that generate commands to GDB - like, "set a breakpoint on this line". In order to control GDB with eepitch we need a window setting with three windows, like in the screenshot in Figure 6.
The way to set up that does not integrate very well with the "standard" eepitch at this moment, but that should come with time. 23. E-scripting GDB with eepitch
We can use elisp hyperlinks to point to specific lines in source files - and we can combine these hyperlinks with the code to set up breakpoints, in two ways.
The first line above contains an elisp hyperlink to a line in the source of Lua. Actually, it points to the code for an opcode in Lua's virtual machine that most people find rather mysterious. As the line starts with `*;', an F8 on it executes a Lisp comment - i.e., does nothing - and moves down; only a `M-e' (or a `C-e C-x C-e') on that line would follow the hyperlink. The second line, when executed with F8, would go to that line in the source, then run `(ee-tbr)' there; ee-tbr invokes gud-tbr to set a temporary breakpoint on that source line (i.e., one that is disabled when the execution stops there for the first time), and then buries the buffer - the one with "lmv.c" - like a `M-K' would do; the effect is that the buffer in that window - the top-left window in a situation like in Figure 6 - does not change, it will still show the e-script. A variation on this is to wrap the hyperlink in an ee-tbr:
When ee-tbr is called with an argument it evaluated the argument inside a save-excursion, and sets a breakpoint there; the effect is almost the same as the previous case, but this does not change the order of the buffers in the buffer list. 24. Two little languages for debuggingE-scripts for eepitch and GDB can be used to bring programs to a certain point (and to inspect their data structures there; we will have more to say about this in the next section). In a sense, as in {Bentley}, these e-scripts are written in a language that describes states of running programs - and they can be executed step by step. These e-scripts, being executable, can be used in e-mails to communicate particular states of programs - say, where a certain bug occurs. Unfortunately, they are too fragile and may cease working after minimal changes in the program, and they are almost impossible to read... However, the screenshot in Figure 5 suggests another language for communicating controlling programs with GDB: the contents of the "*gud*" buffer. After removing some excess verbosity by hand we get something that is readable enough if included in e-mails - and to extract the original commands from that we just have to discard the lines that don't start with "(gdb)", then remove the "(gdb)" prompts. As for the hyperlinks with `(ee-tbr)', they may need to be copied to the GUD buffer, and not filtered out; we still need to experiment with different ways to do that to be able to choose one. 25. Inspecting data in running programsAlmost anyone who has learned a bit of Lisp should be familiar with this kind of box diagrams. After running
the value of y can be represented by:
This representation is verynice - it omits lots of details that are usually irrelevant, like the address in the memory of each cons, and the exact names of each struct in C and their fields. But sometimes we need to understand the implementation in C, and a more complete diagram would be convenient. At least, we would like to know how to get, in the C source of Emacs, from the address of the leftmost cons in the top line to the rightmost "ab" in the bottom line - but how do we express following the "cdr" arrows, the "car" arrows, and extracting the contents of a string object in elisp, One solution is to use GDB, and e-scripts for it:
A "complete diagram" corresponding to the one above, whatever the format that we choose to draw it, should include some information explaining that "cdr" arrows correspond to "->cdr", "car" arrows correspond to ..., and each string object corresponds to another kind of box different from the cons boxes; to get to the C string stored in an elisp string object we should examine its "foo" field, i.e., do a "->foo". Obviously, this same idea applies also to other programs with complex data structures - and for some programs we may even have fancier ways to explore their data structures; for example, in a graphic toolkit it might be possible to change the background of a button to orange from GDB. 26. Big Modular E-scriptsA shell can be run in two modes: either interactively, by expecting lines from the user and executing them as soon as they are received\footnote{except for multi-line commands.}, or by scripts: in the later case the shell already has access to the commands, and executes them in sequence as fast as possible, with no pause between one command and the next. When we are sending lines to a shell with F9 we are telling it not only what to execute but also when to execute it; this is somewhat similar to running a program step-by-step inside a debugger --- but note that most shells provide no single-stepping facilities. We will start with a toy example --- actually the example from Section \ref{anchors} with five new lines added at the end --- and then in the next section we will see a real-world example that uses these ideas.
((Somewhere between a script and direct user interaction)) ((No loops, no conditionals)) ((Several xterms)) 27. Internet Skills for Disconnected PeopleSuppose that we have a person P who has learned how to use a computer and now wants to learn how the internet works. That person P knows a bit of programming and can use Emacs, and sure she can use e-mail clients and web browsers by clicking around with the mouse, but she has grown tired of just using those things as black boxes; now she wants to experiment with setting up HTTP and mail servers, to understand how data packets are driven around, how firewalls can block some connections, such things. The problem is that P has never had access to any machine besides her own, which is connected to the internet only through a modem; and also, she doesn't have any friends who are computer technicians or sysadmins, because from the little contact that she's had with these people she's got the impression that they live lifes that are almost as grey as the ones of factory workers, and she's afraid of them. To add up to all that, P has some hippie job that makes her happy but poor, so she's not going to buy a second computer, and the books she can borrow, for example, Richard Stevens' series on TCP/IP programming, just don't cut. One of eev's intents isto make life easier for autodidacts. Can it be used to rescue people in positions like P's(4)? It was thinking on that that I created a side-project to eev called “Internet Skills for Disconnected People”: it consists of e-scripts about running a second machine, called the “guest”, emulated inside the “host”, and making the two talk to each other via standard internet protocols, via emulated ethernet cards. Those e-scripts make heavy use of the concepts in the last section ((...))
(4). by the way, I created P inspired on myself; my hippie job is being a mathematician. 28. Availability and ResourcesEev can be downloaded from the author's homepage, http://angg.twu.net/. That page also contains lots of examples, some animations showing some of eev's features at work, a mailing list, etc. Eev is in the middle of the process of becoming a standard part of GNU Emacs; I expect it to be integrated just after the release of GNU Emacs 22.1 in mid-2007. Eev's copyright has already been transferred to the FSF; it is distributed under the GPL license. AcknowledgmentsI would like to thank David O'Toole, Diogo Leal and Leslie Watter for our countless hours of discussions about eev; many of the recent features of eev --- almost half of this article --- were conceived at our talks. ((Thank also the people at #emacs, for help with the code and for small revision tips)) References[L90] - Libes, D. - Expect: Curing Those Uncontrollable Fits of Interaction. 1990. Available online from http://expect.nist.gov/. [L95] - Libes, D. - Exploring Expect. O'Reilly, 1995. [O99] - Ochs, E. - The Eev Manifesto (http://angg.twu.net/eev-manifesto.html). [S79] - Stallman, R. - EMACS: The Extensible, Customizable Display Editor. (http://www.gnu.org/software/emacs/emacs-paper.html) |