Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
The is the `doc/tutorial.e' file of GNU eev.
This file is in the Public Domain.
Author and version (of these headers): Eduardo Ochs, 2005jan06
Note: this file is old, and it was never a good tutorial!
Try the README instead: <http://angg.twu.net/eev-current/README.html>.



# «.lisp_hiperlinks»	(to "lisp_hiperlinks")
# «.code-c-d»		(to "code-c-d")
# «.eev»		(to "eev")
# «.delimited_blocks»	(to "delimited_blocks")
# «.eeg»		(to "eeg")
# «.anchors»		(to "anchors")
# «.debian»		(to "debian")
# «.mkto_dff_inn»	(to "mkto_dff_inn")
# «.variables»		(to "variables")
# «.glyphs»		(to "glyphs")
# «.eegud»		(to "eegud")
# «.installing»		(to "installing")
# «.demos_eeg4»		(to "demos_eeg4")
# «.links»		(to "links")




  Emacs and eev.el, or: how to automate almost everything
  =======================================================

Part 1: Emacs, Lisp and hyperlinks
----------------------------------

# «lisp_hiperlinks»  (to ".lisp_hiperlinks")

People usually tend to think that Emacs is a text editor. This is not
exactly true, and it would be more correct to say that it a Lisp
environment that is used most of the time as a text editor.

# (find-elnode "Command Loop")

Each key that you type is interpreted by Emacs either as a complete
command or as the prefix of a longer command, composed of several
keys; for example, C-a (that is, "control-a") generally corresponds to
the function `beginning-of-line', that moves the cursor (called the
"point") to the beginning of the current line; C-x is a prefix, and
C-x C-e is a complete command -- `eval-last-sexp', that evaluates the
Lisp expression that is just before point. Another stranger example is
M-x ("M-x"; in most configurations this is the same as "alt-x"), that
lets us execute commands by name -- M-x eval-last-sexp is the same as
C-x C-e.

# (find-enode "Keys")
# (find-enode "Moving Point" "`beginning-of-line'")
# (find-enode "User Input" "Meta")
# (find-enode "User Input" "<ALT> which is really a <META> key")
# (find-enode "M-x")
# (find-enode "Completion")
# (find-enode "Minibuffer")
# (find-enode "Key Help")

Let's suppose that you are editing the text version of this tutorial.
If you place the point just after the "(+ 1 2)" below and type C-x C-e
you'll se a "3" in the last line of the screen (that line is called
the "minibuffer" or the "echo area"); what happened is that you
executed the Lisp expression "(+ 1 2)", which didn't have any very
interesting consequence, and the expression returned the value 3 - the
sum of 1 and 2.

    (+ 1 2)

# (find-elnode "Lists as Boxes")
# (find-elinode "Run a Program")
# (find-enode "Lisp Eval")
# (find-elnode "Functions for Key Lookup" "Function: key-binding")
# (key-binding "\C-x\C-e")

If you evaluate one of the expressions below (also with C-x C-e,
obviously) Emacs will open the file /etc/inittab, in the first case,
and the "file" ~/ -- your home directory -- in the latter; as ~/ is a
directory and not a normal file Emacs will show the contents of
directory in a certain way and enter "Dired mode", a mode in which
certain keys will be interpreted specially -- for example "q" will
leave Dired mode and <enter> will open the file or directory that is
being shown in the current line.

    (find-file "/etc/inittab")
    (find-file "~/")

As the function `find-file' is bound to the key sequence C-x C-f it
would be equivalent to type C-x C-f /etc/inittab or C-x C-f ~/.

# (where-is 'find-file)
# (find-enode "Dired")
# (find-enode "Visiting" "`find-file'")

If you are running an Emacs in which the eev.el library was loaded
then several other functions similar to `find-file' will be available,
and you can use those functions to create hyperlinks in plain text
files; the functions `find-enode', `find-elnode' and `find-elinode',
that have already appeared above without any explanation, are links to
pages (in "info" format) of the Emacs Manual, of the Emacs Lisp
Reference Manual, and of a manual called "Introduction to Emacs Lisp",
respectively.

Calls to these `find-xxx' functions may have an extra parameter
besides the name of the file or the page; that parameter is
interpreted as a string to search for, and the cursor will be placed
just after the first occurence of that string in the text. Note that
that feature doesn't work in the HTMLized version of these pages; the
link takes your browser to the right page, but doesn't make it search
for a string automatically.

# (find-eev "eev-links.el" "find-")
# (find-eev "eev-links.el" "find-" "defun ee-goto-rest")

The `find-fline' function, that is defined in eev.el, is a version of
`find-file' that accepts that extra parameter indicating a position.
It has that weird name because when I started to code those functions,
back in 1995, the extra parameter was always a number, that was
interpreted as a line number. Nowadays those numeric parameters are
still accepted, but they aren't very convenient to use -- if the file
is changed then the paragraph that you are looking for will probably
start at a different line number, but if you search for the right
string or keyword you will still get there.

# «code-c-d»  (to ".code-c-d")

The eev library also defines several other kinds of hyperlinks: to
files, to tags, to HTML documents, to manpages, and some other weirder
ones. Some of the ways to link to manpages and HTML pages will require
tricks from the next section, as they will involve interacting with a
shell.

The main tool for generating new hyperlink functions is the `code-c-d'
function: a call to `code-c-d' like the one below

  (code-c-d "grub" "/usr/src/grub-0.5.95/" "grub")

defines `find-grubfile', `find-grubnode', `find-grubw3',
`find-grubtag' and some other less interesting functions... if you
know Lisp and you want the technical details, when the `code-c-d' line
above is executed Emacs generates the code belows (as a big string)
and evaluates it:

  (setq ee-grubdir "/usr/src/grub-0.5.95/")
  (setq ee-grubtagsfile "/usr/src/grub-0.5.95/TAGS")
  (defun ee-grubfile (str)
    (concat (substitute-in-file-name ee-grubdir) str))
  (defun ee-use-grub-tags ()
    (setq tags-file-name ee-grubtagsfile))
  (defun find-grubfile (str &rest pos-spec-list)
    (ee-use-grub-tags)
    (apply 'find-fline-nosubst (ee-grubfile str) pos-spec-list))
  (defun find-grubtag (str)
    (ee-use-grub-tags) (find-tag str))
  (defun find-grubw3 (furl &rest pos-spec-list)
    (apply 'find-w3 (ee-grubfile furl) pos-spec-list))
  (setq ee-temp-code "grub" ee-temp-infofile "grub")

  (defun find-grubnode (nodename &rest pos-spec-list)
    (find-node2 "grub" nodename pos-spec-list  "grub")))

A detail: the last `defun' wouldn't be generated if we hadn't passed
the third parameter ("grub") to `code-c-d'.

# (find-eev "eev-links.el" "code-c-d")
# (find-elinode "defun")

# (find-eev "eev-links.el" "code-c-d" "defun icode-c-d")
# (icode-c-d "grub" "/usr/src/grub-0.5.95/" "grub")




Part 2: Interpreting a block of text as a series of shell commands
------------------------------------------------------------------

# «eev»  (to ".eev")

Consider the block below:

rm -Rv /tmp/c/
mkdir  /tmp/c/
cd     /tmp/c/
cat > demo.c <<'---'
#include <stdio.h>
main() {
  int sum, i;
  for(sum=0, i=0; i<10; ++i)
    sum += i;
  printf("Sum: %d\n", sum);
}
---
gcc -E demo.c > demo.i 
gcc -S demo.c
gcc -S demo.c -g -o demog.s
gcc -c demo.c
gcc -c demo.c -g -o demog.o
gcc    demo.c -o demo -v	2>&1 | tee ogv
gcc    demo.c -o demog -g -v	2>&1 | tee ogvg
diff ogv ogvg
./demo

It is a series of shell commands (for bash or zsh); it will create a
directory "/tmp/c/" and file called "demo.c" inside it, and then call
gcc in several ways to compile demo.c into something executable and
into several less well-known intermediate forms.

There are several ways to execute a block like that. You could go to a
shell and paste its text there using the mouse, or you could simply
type everything by hand there; or you could save the block to a file
(called "/tmp/xxx", say) using the emacs command `write-region', and
the got to a shell and type "bash /tmp/xxx" or ". /tmp/xxx"...

# (find-enode "M-x")
# (find-enode "Misc File Ops")
# (find-node "(bash)Redirections" "<<")

Eev.el implements two other ways to execute that. The first way -- the
second will be described in the next section -- is to mark the block
and type `M-x eev'; that will save the block in a temporary file
("~/tmp/ee.sh" by default) and then if you type "ee" in a shell
(provided that you have configured that shell correctly, as described
in appendix xxx) then the shell will execute the commands in sequence
in "verbose mode", which means that every command will be displayed
before being run, and that all commands that change the shell state --
like "cd" and "set" -- will work as expected; if we typed the five
lines below

tac <<'---'
  first
  second
---
cd /tmp/

by hand in a shell we would see something like:

/home/edrx(edrx)# tac <<'---'
>   first
>   second
> ---
  second
  first
/home/edrx(edrx)# cd /tmp/
/tmp(edrx)#

and with `M-x eev' and "ee" what we see is:

/home/edrx(edrx)# ee
tac <<'---'
  first
  second
---
  second
  first
cd /tmp/
/tmp(edrx)#

that is close enough; for a way to simulate perfectly what happens
when things are typed by hand see the section [eeg and Expect], below.

[Add note about the behaviour of bash and tcsh on here-documents in
verbose mode; zsh is the only shell that behaves as it should in
that.]

Note (or remember!) that lines beginning with "#" are treated by the
shell as comments, which means that they are not executed, no matter
whet they contain; so we can put Emacs Lisp hyperlinks in comments in
blocks of shell commands and the shell will ignore them... and we will
still be able to follow the hyperlinks when we edit the file in Emacs.

Suppose that we have some file with notes, each one containing a mix
of text, links and blocks of shell code; the links point to all
documentation that we found relevant while we were writing the notes,
and also to other places in other files with notes...

[I need to translate the rest of this paragraph...]

Imagine que temos alguns arquivos de anotações, cada um contendo uma
mistura de texto, links e blocos de código shell; os links apontam
para pontos relevantes em outros dos nossos arquivos de anotações, e
também para outros lugares com documentação importante, e para alguns
scripts que nós escrevemos; esses scripts provavelmente começaram como
blocos de código shell nos arquivos de anotações, e quando nós os
transformamos em scripts nós resolvemos manter os links que eles
continham, já que não havia motivo para tirá-los... bom, com isso o
Emacs acaba virando um ambiente fantástico: cada coisa que escrevemos
aponta para outros lugares relacionados, e seguir os links é facílimo,
e quando os seguimos continuamos dentro do Emacs, de onde os links
continuam funcionando... tudo fica muito próximo e muito acessível.
Para um exemplo realista de quão linkadas as coisas podem ficar, veja
<http://angg.twu.net/>.




Part 3: Delimited blocks
------------------------

# «delimited_blocks»  (to ".delimited_blocks")

If you are running an Emacs in which eev.el was "completely installed"
(i.e., with `ee-invade-global-keymap'; see the appendix) then the F3
key will be bound to an Emacs command called `ee-bounded', that by
default runs `eev-bounded', that, by its turn, act as a sort of `eev'
that finds the limits of the block by itself, searching for certain
delimiters, instead of requiring us to mark the block explicitly. The
default delimiters are "\n#-\n", that is, a line that contain just a
"#-", but I prefer to use "\n#*\n"; the "*" is a char 15, that can be
typed with `C-q C-o' and that will appear as a red star if you are
using GNU Emacs and have installed the package for "glyphs" that comes
with eev.el. The section [variables] explains how to change the
default globally or for some specific files.

# (find-enode "Inserting Text" "* `C-q'")
# (find-eev "eev.el" "eev")
# (find-eev "eev.el" "bounded")

Example:

#*
# (eev-bounded)
# (eev-bounded 'once)
tac <<'---'
  one
  two
---
#*
rev <<'---'
  one
  two
---
#*

Note that it is possible to execute the block above all at once (i.e.,
ignoring the middle "#*") by marking it in the usual way and typing
`M-x eev'; the shell will consider the line with "#*" as a comment and
will ignore it.

`eev' is not the only command that has a version supporting
delimiters; eeg and eelatex (two commands that we haven't seen yet)
also have. Example: if you run `M-x eelatex-bounded' from inside the
block below then Emacs will save a temporary script that when executed
with "ee" in a shell will interpret the saved block as a LaTeX text.
Note that it will use "%*" as delimiters instead of "#*", because
comments in TeX and LaTeX begin with "%". The delimiter string used
for `eelatex-bounded' can also be controlled with the tricks of the
section [variables].

%*
% (eelatex-bounded)
% (eelatex-bounded 'once)
A text in \LaTeX

%*

If you are not in the mood to type `M-x eelatex-bounded' you can
execute one of the lines of the block that call `eelatex-bounded'...
the eexxx-bounded commands admit an optional parameter, that if
present will mean that the function is to be run "only once", that is,
it should not become the new default action for F3. It is possible to
call these functions in "once" mode using M-x: for example, with `M-1
M-x eelatex-bounded'.

# (find-enode "Completion")
# (find-enode "Arguments")




Part 4: The generic interface: eeg
----------------------------------

# «eeg»  (to ".eeg")

If you know enough about *NIX and shells you should be able to control
most interactive programs using pipes. For example:

#*
# (eev-bounded)
echo 1+2 | bc
bc <<'---'
2+3
3+4
---
#*

But many interactive programs will behave differently when they notice
that they are receiving their input from a file or a pipe, and
sometimes you may want to get on your screen exactly what you would
you'd get in interactive mode -- by piping input with "<<'xxx'" and
"xxx" you see all the input first, then all the output -- and, of
course, you'd like to get that without having to type everything
manually.

There is a "generic interface" for eev that handles those cases. It is
composed of a program called "eeg", written in Expect, and two Emacs
commands, `M-x eeg' and `M-x eeg-bounded'; `M-x eeg' works like `M-x
eev', but it saves the block in another temporary file, by default
"~/bin/ee.generic"; if everything was installed correctly then the
shell variable $EEG will contain the name of that file, and so in

#*
cat > $EEG <<'---'
2+3
3+4
quit
---
eeg bc
#*

the "cat" will work as if we had marked the three lines between the
"---"s manually in Emacs and typed `M-x eeg'.

The trick is that when we call bc "through eeg", as in the line "eeg
bc", bc will run normally, in interactive mode, will almost all keys
of the user being sent directly to it, as usual; but there's one key
that is "translated" in a special way: each time the user types `M-l'
eeg will execute an "action" from its list of actions; eeg prepares
this list of actions by reading $EEG, and the first will correspond to
sending "2+3", followed by an <enter> to bc, the second will be "3+4"
plus <enter>, the third "quit" <enter>, and all others will be null.
So, if we execute the block above with `ee' in a shell and we type
`M-l asfdg <enter> M-l M-l', we will see something like

/home/edrx(edrx)# ee
cat > $EEG <<'---'
2+3
3+4
quit
---
eeg bc
bc 1.05
Copyright 1991, 1992, 1993, 1994, 1997, 1998 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
2+3
5
asdfg
0
3+4
7
quit
/home/edrx(edrx)#

Expect is able to control any program that interacts with the world
via terminals, that is, via stdin, stdout, stderr and /dev/tty; that
includes even "essentially interactive programs" like ssh, telnet,
adduser, emacs and vi, and only excludes the programs that can only be
run through X. The idea is that "everything" (if we are willing to
pretend that programs that only have graphical interfaces "do not
matter" or "do not exist"!) can be controlled by Expect and eeg.

For some programs it may be more convenient to use a variation of eeg
that is not restricted to sending a whole line (terminated by a CR) at
each M-l. Actually this variation -- called eeg4 -- is exactly the
same program as eeg, but when invoked with a different name it runs
with different defaults. At this moment it isn't very well-documented,
so here is a link to its source code:

# (find-eev "eev/eeg4")





Part 5: anchors and local links
--------------------------------

# «anchors»  (to ".anchors")

Sometimes we may want to create "local links" that point to other
positions in the current file; this can be done using the "to"
function. A call like `(to "tag")' (like the one above) will jump to
the first occurrence of the string "«tag»" in the current file; this
string, "«tag»", is obtained from the parameter, "tag", by surrounding
"tag" with the default "anchor delimiters" -- more technically, this
is done in the Lisp code by running `(format ee-anchor-format "tag")',
where the default value for `ee-anchor-format' is "<<%s>>"; this
default can be changed for a specific file by using "file-local
variables", as described in section 7, below. For example, in this
file ee-anchor-format was set to "«%s»".

# (find-eev "eev-links.el" "to_and_back")
# (find-eev "eev.el" "ee-invade-global-")
# (find-eev "eev-vars.el" "variables")

There are several ways to type the "«»" characters. The most standard
(though not very convenient) way is to enter them using their octal
codes, by typing C-q 2 5 3 RET and C-q 2 7 3 RET.

# (find-enode "Inserting Text" "sequence of octal digits")

The function `to' is a particular case of a function that looks for a
certain "anchor" in a certain file (...)

# (find-eev "eev-links.el" "find-anchor")






Part 6: links to information about packages in a Debian system
--------------------------------------------------------------

# «debian»  (to ".debian")
# (find-eev "eev-links.el" "find-Package")
# (find-eev "eev-mklinks.el" "dff")




Part 7: tricks for creating links more quickly
-----------------------------------------------

# «mkto_dff_inn»  (to ".mkto_dff_inn")
# (find-eev "eev-mklinks.el" "inn")
# (find-eev "eev-mklinks.el" "dff")

(Explain also the trick for recording macros)
# (find-es "emacs" "saving_emacs_macros")



Part 8: variables
-----------------

# «variables»  (to ".variables")
# (find-enode "Variables")
# (find-elinode "Variables")
# (find-elnode "Variables")
# (find-eev "eev-vars.el")



Part 9: glyphs
--------------

# «glyphs»  (to ".glyphs")
# (find-eev "glyphs.el")
# (find-angg "vtutil/mathchars.lua")




Part 10: eev and GUD (Emacs's Grand Unified Debugger)
-----------------------------------------------------

# «eegud»  (to ".eegud")

[Show how we made gdb support an `ee' command; explain eegdb,
eegdb-bounded, eegud-gdb, eegud-keys-mode; give a simple example with
just one here-doc'ed C file, and a not-so-simple one with two C files
and dynamic linking (dlopen). Change eegud to make it use
gdb-mode-hook, and fix its behaviour when we try to kill the gdb
window when it's the only one in the screen.]

# (find-eev "eev-gud.el")
# (find-eev "rcfiles/.gdbinit")

# (find-eev "eev-vars.el" "variables")
# (find-eev "rcfiles/.bashrc")
# (find-eev "rcfiles/.cshrc")
# (find-eev "rcfiles/.zshrc")

# (find-enode "Debuggers")
# (find-enode "Starting GUD")
# (find-enode "Commands of GUD")
# (find-enode "GUD Customization")

# (find-es "anatocc" "dlopen")
# (find-es "anatocc" "dlopen-gdb")
# (find-es "lua5" "argpatch-gdb")

# (find-angg ".gdbinit")







Appendix 1: installing eev in a Debian system
---------------------------------------------

# «installing»  (to ".installing")
# (find-eev "INSTALL")



Appendix 2: creating demos with eeg4
------------------------------------

# «demos_eeg4»  (to ".demos_eeg4")
# (find-eev "eeg4")

# (find-eev "demo/")
# (find-eev "demo/dlopen.e")
# (find-eev "demo/dlopen.eeg4")
# (find-eev "demo/emacs0.eeg4")





Appendix 3: the basic kinds of links defined by eev
---------------------------------------------------

# «links»  (to ".links")
# (find-eev "e/links.e")
#*
cd ~/eev/
grep defun eev-ALL.el | tee ~/o
#*

(find-node "(elisp)Top" "Evaluation")
(find-fline "/etc/fstab")
(find-fline-nosubst "/tmp/~foo")
(find-w3 "/var/www/")

(icode-c-d "CODE" "DIR/" "INFO")

(find-devreftxt "")
(find-pl5pod "syn" "Loop Control")


Links that use anchors:
  (find-anchor "~/eev/e/debian.e" "_partition")
  (find-Package   "/var/lib/dpkg/status" "emacsen-common")
  (find-status    "emacsen-common")
  (find-available "emacsen-common")
  (find-es   "anatocc"  "cdecl")
  (find-angg ".zshrc"   "ee"
  (find-eev  "Makefile" "install")

Links to the source code of Emacs functions and variables:
  (find-efunction 'eev)
  (find-evariable 'ee-file)

Links to the output of programs:
  (find-progoutput "wget --help" "--continue")

Links to manpages (eeman is a hybrid between link and e-script):
  (eeman       "1 man" "System calls")
  (find-man.el "1 man" "System calls")
  (find-man    "1 man" "System calls")

Links to pages of .ps and .dvi files (possibly compressed):
  (find-dvipage 
  (find-zdvipage (fname n)
  (find-pspage (fname n)

;; code-ps
;; code-dvi
;; code-zdvi









# (find-es "anatocc" "cdecl")

find-status
find-vldifile xxx.list

# (find-es "anatocc" "cdecl")
".e"s

# (find-es "anatocc" "dlopen")

alias in .bashrc



;; (describe-function 'find-fline)
;; (describe-function 'find-node)
;; (describe-function 'ee-goto-position)
;; (describe-function 'eev)
;; (describe-function 'eeman)
;; (describe-function 'eecd)
;; (describe-function 'eeg)
;; (describe-function 'eev-bounded)
;; (describe-function 'eelatex)
;; (describe-function 'eelatex-bounded)
;; (describe-function 'eeg-bounded)
;; (describe-function 'end-of-line-then-eval-last-sexp)
;; (describe-function 'ee-bounded)
;; (describe-function 'code-c-d)
;; (describe-function 'inn)
;; (describe-function 'dff)











Apêndice I: Instalando o eev.el num sistema Debian
--------------------------------------------------

# (find-es "escripts")
# (find-es "escripts" "copy_of_edrxs_home_LR")
# (find-eev "README")


Apêndice __: Rodando um demo em eeg2








#  Local Variables:
#  coding:               raw-text-unix
#  ee-delimiter-hash:    "\n#*\n"
#  ee-delimiter-percent: "\n%*\n"
#  ee-anchor-format:     "«%s»"
#  End: