Hi, my name is Eduardo Ochs.
I'm this person here,
and the title of this talk is on "Why
Most of the Best Features in eev Look
Like Five Minute Hacks."
This is a presentation at the EmacsConf 2020
happening on November 28 and 29, 2020.
So this is part one of the presentation.
Here I'm going to explain
some ideas that are prerequisites for
understanding the rest of the presentation.
The three main keys of eev are
M-e, M-k, and M-j. I'm going to start by
explaining M-e and M-k.
M-e is used to follow hyperlinks.
Technically, it is essentially
just a C-e to move to
the end of the line,
and then a C-x C-e to execute this,
the sexp before point at the end of the line.
And the thing is that Emacs comes with
many functions that can be
used as sexp hyperlinks.
We can consider that they point to somewhere.
I'm going to refer to that as
the target of the hyperlink.
If we execute this
sexp hyperlinks, we coul go to that target.
For example, this one
is a hyperlink that points to a buffer
with the manpage for cat.
And usually, but not always, after
following the hyperlink, we can go back
by just killing the current buffer
that the hyperlink created:
the target of the hyperlink.
But this example here is badly behaved.
If we execute it, it creates a new frame,
and to go back to the previous situation,
we have to either click here or type C-x 5 0.
So here are some examples of
sexp hyperlinks using
standard Emacs functions.
This third one is badly behaved
in a different way.
If executed, the target is created
in the same window as we are now,
but it also shows a lot of garbage
here in the echo area,
so the current frame becomes a bit messy.
And well, one of the first things
that I did when I was creating eev
many many years ago was that I created
variants of all these functions
that were better behaved.
They were better behaved in two senses.
The obvious one was that
they all created the target
in the same window as before,
so I could go back by just typing M-k
which has essentially just killed this buffer.
I also implemented something extra that
are the postback lists.
For example, these extra arguments here are a postback list.
These extra arguments specify
position and the target buffer.
In this example, this postback list means:
starting from the beginning of the buffer,
search for the first occurrence of this string after that,
after the beginning of the buffer,
and then search for the first occurrence
of this string after that.
eev also defines some hyperlinks
that do not create new buffers.
Here is the first example.
If I execute this one,
this one is a hyperlink
to the result
of running this show comment date,
but instead of showing the result
in the new buffer,
the result is shown here.
So, if I execute this hyperlink,
the result of date, the output of date,
is shown in the echo area.
And if executed again,
it shows the result again,
and the result
changes every second.
So this is a variant of find-sh.
find-sh0 is the variant that
just shows the output in the echo area,
and find-sh shows the output in
a new buffer.
Here is an example of a hyperlink
that calls an external program.
If I execute this,
it calls Google Chrome to open
a certain URL.
Here it is. Let's go back to Emacs.
If I execute this hyperlink here,
it invokes my favorite PDF viewer
which is xpdf. It makes xpdf
open this PDF page. It is PDF
in this page, and these other arguments
are ignored. Let me show how it works.
Here it is. This is an excerpt from a book.
So page 3 in the pdf corresponds to
page 113 in the book.
This variant here of the hyperlink above,
it opens the PDF in a different way.
It runs a program called pdftotext on
this PDF here,
and Emacs takes the output of
running pdftotext on this pdf here
and displays it in a buffer.
Now this postback list
is interpreted in a different way.
This thing is interpreted
as a number of a page,
and Emacs goes to page three
by counting form feeds in
the converted version of the PDF
and then it searches for this string.
and in this three... So let's execute this
to see what happens. Here it is.
I opened the same page as before.
It starts with lecture one.
So the other hyperlink searched for this
string and for this string here.
This thing here is a hyperlink to video,
and when I execute it,
it's going to open this video here
at this timestamp. Let's see.
1, 2, 3. 1, 2, 3. That's the way to do it.
And also some hyperlinks
that I defined,
they don't work like
usual hyperlinks. They work more
like browser buttons,
these buttons that appear in web pages,
in the sense that these buttons usually
don't open a new page. They usually
just do something to change the current page.
If I execute this, the action
of this function eek is to...
It interprets this string as a series of keys
and it acts as if the user had typed all these keys.
So if executed, I get a hello
in the next line.
If executed again, I get another hello.
Another hello. hello. hello. etc. etc.
Let me undo this mess. Oops.
And here is another kind of button
that defines a new function. If I execute
this sexp here, at this moment, though it's
not defined.
And if I execute this, Emacs is going to
show me a message saying
symbol as function cell is not defined,
something like this.
But if I execute the defun,
the action of this function o here
is to run this, which opens a certain directory.
Let me go back. Here is another
button that defines
several functions at the same time.
If I execute this,
note that the the result of
executing this expression
is the name of one of the functions
that it defined.
That is this one here. Let me explain
these examples. One of the functions
that this thing here defined
is called find-orggitfile, where
this orggit in the middle of its name
is exactly this first argument to code-c-d.
The action of running find-orggitfile
on a string like this is that
find-orggitfile takes the string
and prepends this string to it,
this one here which is the second
argument to code-c-d,
and then it executes find-fline
on the result, which is this one.
find-fline is my variant of find-file
that supports both spec lists.
This function here that I'm
referring to as a button,
it also defines a function called
find-orggitnode here, where the orggit
is the same string as here.
This function opens a node
of an info manual. This one,
this text here opens this node
in the Org manual.
It is equivalent to this text here.
So in the passage from this line
to this line, we prepended
to the node name the name of the manual here.
find-node is my variant
of this standard Emacs function here,
but find-node also supports
postback lists.
eev also defines some functions that
define shorter hyperlinks to PDFs
and videos.
Remember that this thing here
is a shorter hyperlink
to a file. This thing here
is a shorter hyperlink to a node
in an Emacs menu in an info manual.
If we run this thing here, this code-pdf-page,
this acts like a button that defines a
certain function
and this string, this other sexp here,
defines another function.
The first one defines
the function find-fongspivak-page,
and the second one defines the function find-fongspivak-text.
When we run the file,
when we run find-fongspivak-page,
it opens this PDF here.
The name is quite long.
This example opens this PDF at page 8
and searches for the string contents.
In this case, it just ignores this string.
Here it only considers
the number of the page. Let's try.
Here it is, the contents of a book
that is freely available. Here is another page of the book.
And if we execute this hyperlink here,
find-fongspivak-text, it converts the
PDF to text
and it searches for page eight in it,
and then for the string,
this string here in page eight.
It takes a few seconds.
Here it is. So this is the
ASCII version of this contents page here.
Note that this block here
is a kind of an index to that book.
I have the full index somewhere,
but it's very long,
so I just copied a few lines here.
So this is a link to s
section one, chapter one. This is the
section 1.1, section 1.1.1, and so on.
Here is a link to the index.
Here is a part of my index
of positions in the video that we just saw
that I think that are especially relevant.
So this hyperlink is a kind of a button
that defines this function here,
find-punchandjudyvideo. Into the video.
We can also use this for
video tutorials. For example,
this is a very good tutorial on Magit.
If we execute this,
then these functions are going to be
defined, and these functions open
this tutorial on Magit.
These are some of the positions in the
tutorial that I found especially relevant.
This is a very dense tutorial.
I had to take notes of everything,
and I had to watch everything
several times.
For example, this is a link
to the position in the tutorial
that explains how in Spacemacs,
Magit interprets SPC g s as magit-status.
Let's see. "...beginners. SPC g s to initiate
Magit's git status.
You can also do..." That's it.
Here are some examples that I
took from somewhere else.
The video tutorials from
Rainer Koenig about Org Mode.
Now let me show how the functions
that define these shorter hyperlinks
are implemented.
The standard ways in Emacs
to define functions that define other functions
would be with macros.
Let's see an example. This is a standard
function that defines new functions.
If we execute it,
its result is the last function that it
defined, which is ee-glyph,
which is here.
It's implemented as a macro. We can
look at the result of macro-expand, which is going to
show us the result of this,
of the expansion of this.
Instead of expanding and executing,
it just expands and shows us the result.
Here the result is a bit messy.
It's too big for humans to understand,
but we can run this or this text here.
That takes that result and pretty-prints it.
So this is the pretty-printed version
of this macro here.
We can see that it defines
several functions here.
For example, this one.
And this, just as a curiosity, is a link
to the definition of cl-defstruct.
Note that the code is huge.
Well, it's very well-commented,
but it has lots of special cases.
It supports lots of constructions,
and so it's huge.
It's very difficult to understand.
I mean, I found it very difficult to understand.
Here's a link to document the
documentation of cl-defstruct
here in the manual for cl,
which is a kind of support
for some features of Common Lisp in Emacs.
So let's compare this standard way of
defining functions that define new functions,
which is with macros, with this.
I'm going to use a slogan repeatedly.
The slogan is: "I am a very bad programmer."
I'm a very bad programmer.
So, when I was trying to create functions
that would define new functions,
I found it easier to generally generate
this code as text,
and then run read and eval in it.
The code-c-d that we saw in the previous section,
we can see the code that it produces
by making a copy of this line
and prepending this string here
to the name of the function.
So, instead of running code-c-d,
we run find-code-cd,
and it creates a new temporary buffer
with the code that
code-c-d would execute.
So it's a series of the defuns and a few setqs and so on.
And this thing is implemented mostly as a template.
There's an inner function called
ee-code-c-d-base that receives just
these two arguments, and it says...
Essentially, it just runs the function
ee-template0 on the string here, and
the things between curly braces are
substituted by the values
of these arguments here.
There's one part of the tutorial here
that explains all these things,
except for the rationale for some
design decisions,
and those design decisions are one of
the many motivations for this talk.
I'm only going to explain these
things in detail at the end,
which is kind of...
So in the beginning, I said
that the three main keys of eev
are M-e, M-k and M-j.
Let's see now what M-j does.
I need to start with some motivation.
The motivation is that we
can define commands with very short
names. Actually, I became kind of
addicted to that.
This is an example of defun that
defines a comment with a very short name.
Its name is just one letter, "e."
and I can invoke... You invoke it
with M-x e.
If I type M-x p,
now it opens a LaTeX file
that I'm working on.
I create most of my LaTeX files
using template-based functions like
the implementation of code-c-d above.
These template-based functions
create files with extension .tex
that start with a series of defuns
in comments. For example,
let's look at this example here.
If I execute find-latex-links
with this argument,
it's going to do several things
for creating a file called /tmp/foo.tex,
and the header of that file
is going to be this,
which starts with three
defuns with functions with very short
names and comments.
Let's compare with the situation here.
In my file, 2020favorite-conventions.tex,
I have this header here in which I
define six functions with very short names.
And in this case here, that is even
explained in the tutorial.
These... We have mnemonics for
these short names here. c is compile,
d is display. I mean, display the PDF.
e is added in the sense of
make Emacs visit that file.
Now I can explain what is M-j itself.
We just saw commands with very short names.
The idea behind M-j is that
we can define commands with
very short numbers.
Let me explain this.
The short explanation for what M-j does
is that it jumps to set certain
predefined places.
In particular, a M-j without a numeric argument
takes us to a buffer
with the basic help
and a list of the current jump targets.
This is something that is a bit
simpler to understand.
If we type M-5 M-j,
then M-j runs this sexp here
that is associated to
the argument 5. I say that the target
for the argument 5 is this one,
and if the argument is true, then the
target associated to the true
is this sexp here that opens...
This one opens the main tutorial for eev,
and this one opens another tutorial.
This is a link to one of the tutorials
of eev to the part that explains M-j.
I've copied the the main part
of the text here.
The header that M-j shows...
Let me show it very quickly here.
Here is their head and here is the rest.
The header is very beginner friendly,
and if you're a beginner
who only knows how to use M-e to
execute and...
This should be okay.
M-k to go back.
Then you can and should use that header--
I mean, this header here--
as your main starting point.
Every time that you feel lost,
you can type M-j to go back to that header,
and you can use its links to navigate to the documentation
for Emacs and eev. Let me explain that.
This header here has several elisp hyperlinks.
One here, one here, one here, one here, and so on.
These ones are links to the
to the intros, which are the tutorials.
find-eev-quick-intro is the main tutorial,
and find-emacs-keys-intro is a kind of tutorial that is
an index of the main keys.
After that, we have an explanation of
what some numeric prefixes do.
So if we type M-1 M-j, the effect of that
is exactly the same as executing this.
We can execute this with M-e also.
M-2 M-j runs this sexp and
I can also execute it with M-e.
Here it is. It's this intro, this sandbox tutorial.
Here is another sandbox tutorial.
Let me go back. Then the
documentation says that header,
the header that is beginner-friendly
is followed by a section that is very
beginner-unfriendly
that contains a series of defuns like these ones.
Here, the last line of the header is this comment here.
Then we have several defuns like this.
Let me explain how these things work.
Technically, what happens
when we type M-j without any arguments
is that it runs eejump with argument nil,
and then this runs 5 eejumps.
When I run M-j with a numeric argument,
for example, with argument 5, it runs a jump 5.
eejump-5 concatenates this 5 one
to make a name of a function,
this function here.
and it executes this function eejump-5.
You jump -5, and eejump-5
executes find-eev-quick-intro.
If I execute just M-j,
the section that shows
the current jump targets
has a line for eejump-5. This is...
That is exactly the thing that I was explaining before.
So we can use M-j to navigate
the tutorials. We can copy the links.
Sorry. We can copy links to the
tutorials to our notes.
Oh, sorry, this has some typos.
For example, if I execute this,
I go to a section of this tutorial here
that explains the main keys of eev.
These things are hyperlinks.
I can mark a hyperlink like this.
it is just plain text.
I can copy it to my notes.
The idea is that every time
that I find something that is interesting,
I can create a hyperlink to it.
I can put these links in my notes
so I can navigate back
to all the interesting positions
very quickly.
Okay, next feature. If we type M-J (uppercase), then
this is a function that transforms
the current line in a certain way.
Let me give an example. Let me isolate this.
Let me duplicate this line to make clear what happens.
If I type M-J (uppercase) here,
this line here becomes the defun for eejump-6,
and the target of this eejump
is exactly this sexp here.
Let me undo this mess.
If the first word in the line
is not a number... For example,
here, let me do the same thing:
duplicate the line and type M-J,
then M-J (uppercase) converts that to
a defun that defines a function with a very short name.
This function with a very short name
opens this file here in the directory
with the copy of the git repository
for Org Mode.
Let me undo the mess again.
Oops. That's it.
M-J (uppercase) is a particular case of something that
I use a lot in eev.
eev has lots of commands that-- sorry, key sequences
that are like M- uppercase letter,
and almost all of them operate
on the current line and
transform the current line
in a certain way.
For example, this is a filename.
If I type M-F (uppercase) here,
it becomes a link to that file.
This is the name of a man page.
If I type M-M (uppercase) here,
it converts that to the link
to a manpage. This is a shell command.
If I type M-S (uppercase) here,
it converts that to a link to a
to find-sh (shell).
Until a few years ago, these functions
with M- uppercase letter were half
of my main ways of creating sexp hyperlinks
with a few key strokes.
In the beginning, of course, I had to create my
sexp pipelines by typing each character.
But after some time, I decided that
I needed something more efficient.
So this is the end of part one of the presentation.
So this is part two of the presentation,
and the main theme here
is the standard describe-key
function that comes with Emacs.
My variant of it... The thing is that
the standard describe-key in Emacs
is user-friendly, but it is
hacker-unfriendly. Well, I felt so.
When I tried to complement it
by writing a hacker-friendly version of it
that produced the sexp hyperlinks that I needed,
I got something that I found really lovely.
Several of the main
design decisions of eev can be seen there.
When I showed my variants to
other people, they hated it.
They felt that it was
totally against their notions of
user-friendliness.
Okay. So let's see.
The standard describe-key,
if I run this hyperlink here, I get this.
The result of running
describe-key on the key down...
This is a big buffer
with some things in italics.
Some hyperlinks here.
These hyperlinks are standard
in the sense that
the targets are not visible,
and they are implemented using
buttons in Emacs Lisp.
This section of the Emacs Lisp manual
describes how buttons work.
The source code is quite difficult.
I mean, when I was starting to
to try to decipher this
when I was a beginner
using Emacs 19.34, I felt that this
describe-key was
very difficult to understand.
I felt that the the designers,
the people who wrote it, were sacrificing
too much of the hacker-friendliness
that I was expecting from it
to make it beginner-friendly.
Let me explain. What are the problems
with the standard describe-key?
If we think that hyperlinks
are things like this
with the target and the text, then in the
button hyperlinks of describe-key,
these three bad things happen.
First, it is hard to extract the target from the hyperlink.
Second, it is hard to recreate
a list of code that would go to that target.
Third, it is hard to copy the full
hyperlink, including the targets to other buffers.
I only knew how to copy the text
when I was trying to decipher
what describe-key was doing.
I created lots of hyperlinks like this
to inspect the text properties and things like that.
For example, in the description
of the key down here,
we have a button that points to simple.el.
The text of that button is simple.el.
This hyperlink goes to the
to the middle of this button hyperlink here.
This hyperlink here
goes to the middle of the button of this button hyperlink,
and then inspects its text properties,
and then goes to this section here of the description.
So this is a high-level description
of the text properties.
I mean, the text properties that make it a button.
This is a lower-level description of these text properties.
The button that points to
forward-line--sorry, the button
whose text is forward-line, this one is
slightly different--
this hyperlink here goes to the middle of that button.
This hyperlink goes to the middle of that button,
inspects its text properties,
and goes to the section
of this button of this help buffer here
that describes the button
and the lower-level view of the text properties.
So I started with things like this
to understand what these buttons were doing
and I was able to figure out
how these things are implemented
in describe-key, and then
similar help functions in Emacs.
I discovered that one of the
main lower-level functions
that Emacs used for this
is a function called find-function-noselect.
If I run find-function-noselect on next line,
it returns a pair:
a cons made of a buffer and a position.
So I created functions that would
follow this. That would open that
buffer in that position
and then this is a postback list.
So we could go to these positions and
then search for this string, and another
string, and another string, and so on.
So this goes to the definition of find-efunction
and then to a string after it.
I use these things to implement
my own functions that pointed to the
same targets as the button hyperlinks
and describe-key.
Again, let me show the comparison.
This is the standard describe-key here,
and this is my variant.
It creates a buffer with links,
with the list of hyperlinks about this key.
We get this. So, each one of these
functions is either a blank line
or an elisp hyperlink.
Here is a slight variant of the function find-ekey-links above.
In this variant, the argument is a string that has to be processed by
read-kbd-macro to convert it to the
lower-level format.
Note that these functions here that I wrote,
they display temporary buffers
with no help at all.
To be honest, there's a link to
a tutorial here,
but this is a recent edition
so let's ignore this.
They display temporary buffers
with no help at all,
just lots of hyperlinks.
And these hyperlinks can be...
They are very hacker-friendly in the sense that
they can be followed with M-e.
They can be copied to other
buffers because they are plain text,
because they are just sexp.
And they can be inspected in the sense that...
For example, here,
we have a hyperlink to a function that we...
It may be difficult to figure out what
this function does,
but we can go to that position,
and then type C-h f to see the
description of this function.
And here is a hyperlink that does that
in my syntax, say.
This list of hyperlinks were
generated by this code here that just
used a back quote to generate
lists of sexps.
I felt that this function here
that just generated this list
was very easy to understand and to modify,
so this was hacker-friendly in the way that I wanted.
So I started using this,
and this idea of using buffers
with sexp hyperlinks and no help
violated all the notions of user-friendliness
that I knew, so I was
exploring something new
at that time. This is the end of part two.
Part three of this presentation is
about the killer features of eev,
or why everybody should use eev
or at least have eev installed
even if they think that eev is too weird.
So this is a very quick listing.
eev has elisp hyperlinks which are super nice.
It comes with lots of tutorials.
The main one here explains all the main features.
There's also a tutorial that's
an index of all the other tutorials here.
Many, many, many tutorials.
If we forget everything, we can just type M-j.
Remember that this part here is beginner-friendly,
and the rest is beginner-unfriendly.
There's a tutorial on Emacs Lisp here.
It mainly explains how to understand
Elisp code, which is much easier than...
It's much easier to understand Elisp code
than to understand how to program in Elisp.
Most people are only going to need this.
eev is very easy to install.
It's in ELPA, so we just need to do
this thing here, and it's very non-invasive.
Years ago, several years ago,
it was a very invasive package,
but then I changed everything.
Now, if we toggle eev-mode on and off,
what's going to happen is just that
the eev-keymap becomes activated or deactivated.
When we install eev--
I mean when we require eev,
the only things that happens globally are these things here:
several functions and variables become defined.
All of them have standard prefixes, except for one.
Three characters are changed in the
standard display table
to make them appear as colored glyphs:
the red star, the open double angle brackets,
and the closed double angle brackets.
Two environment variables are set.
This is a trivial technicality.
We just run a defadvice around one function that is used by "man."
Also, eev has a very high discoverability factor.
There's a way to create, a very easy way
to create a hyperlink to here.
I do not have time to show this now,
but for example, if I'm here in a tutorial,
and I think that this section is something interesting
and I want to create a hyperlink to it,
I just have to type a certain key sequence here,
and here I got a hyperlink
that I can copy to my notes,
and this hyperlink goes to that section.
We have hyperlinks that point to specific positions
in PDF documents and in video files.
Here, this one opens a PDF and displays it.
This one opens a PDF and converts it to text.
and this one opens the video in a certain position.
We also have a way to control
shell-like programs.
In my presentation of the last year,
I spent one third of the presentation explaining this,
and I think that I gave a very good demonstration there.
The demonstration is here.
We can go to the web page,
go to this section of the web page,
and start by this point.
And here we have an explanation and so on. Whatever.
I've already mentioned this before.
eev comes with a very nice Elisp tutorial.
So that's it. This is the end of part three.
So this is the last part of my presentation,
and it's about the title of the presentation.
I called the presentation, "Why
Most of the Best Features in eev Look
Like Five-Minute Hacks." I've already
run out of time, so I have to skip this
first part here in which I describe how
I was exposed to several different notions of user-friendliness,
and how the one that really blew my mind
was the one in a certain Forth environment.
Let me make the long, long story
very, very short.
In all this process, I switched from
the belief that the user was always someone else,
someone external, and that I always
had to write my programs for
this external user. I switched
from that to the belief
that I am the user.
I can play with the interface that I want.
I can write programs
that only I am going to understand.
I can experiment with hundreds of interfaces,
select the best ones,
document them, and then share them
with other people
who are also experimenting with interfaces
in their own ways.
So eev has lots of things that are user-friendly
in these unusual ways that I've explained before.
If we consider that
this notion of user-friendliness is valid,
then these things that eev implements,
they are user-friendly and hacker-friendly
at the same time.
Let me show one example.
This is one that really took me only five minutes to implement.
At one point a few months ago,
I discovered that Sacha Chua's weekly posts about Emacs News
were also being posted to a
mailing list that is stored at lists.gnu.org,
and it's called emacs-tangents.
I found a way to create
the links to the posts in both places,
but I had to use a template for that.
So what we are seeing here now
is a template with the default values.
So this means that we have not set the year correctly.
We have not set the month correctly,
or the day correctly,
but if we run this sexp here...
Let me do something else before...
If we run this sexp here,
we change some of these entries
in the template, and we get these links here.
They all work. For example,
this one opens the blog post in Sacha Chua's site,
and this one opens it in the mailing list.
Sometimes I want the Org source of that,
and the easiest way to get the Org source
is to look at this link here that has an attachment.
If I take this link here,
and I take this stem that points to the attachment, and I put it here,
and I generate this page again
with all this data, then I get a script here
that downloads...
Let me switch to a smaller font.
It downloads this attachment
and it renames that attachment to something:
./emacs-news -- sorry, something's...
-emacs-news-something
something emacs-news.org here.
The file is already here,
already with the right name.
So I can open it with just this hyperlink.
Let me go to the big font again.
And now I have the Org source for that hyperlink--
Sorry, for that blog post.
And so this one-line thing here
is, in a sense,
a hyperlink to this blog post in all its formats.
If I execute this, I get links to
all the places where it is posted,
and I get a script to download the local copy
of the Org source of it. And that's it.
Well, I'm already out of time,
so let me finish here.
Thanks. Bye.