Hi! My name is Eduardo Ochs, and this is a
quite technical talk about eev, so I'm
going to suppose that everyone knows
what is the Emacs and what is eev.
The title of this talk is:
"Some template-based functions of eev
that are not 5-minute hacks"
and the reason for this title is that
when I gave a presentation at the
EmacsConf 2020 I give this title to it:
"On why most of the best features in eev
look like 5-minute hacks",
and the last section of that
presentation was about one specific
feature that I really implemented in
just five minutes.
We can play the video here by
executing this link here...
here: Part 4
and I explained a certain notion of
user-friendliness, and then i explained
the function called
`find-emacs-tangents-links'
in this passage...
but let's see it in a more technical way.
if we execute (find-emacs-tangents-links)
we get a buffer like this, in which this
part here is generated by a template,
and if I change these things here
by something else, for example by YEAR
in uppercase letters, and i run this line
again, then the all the buffer is going
to be generated again with these values
for the the things in curly braces, so
if I execute this I get this...
taaa - this became YEAR.
The implementation of this is very
simple, it is just a function, here...
with the template here...
and the interesting thing is that...
the thing that allowed me to write this
thing in just five minutes is that
I have a function that generates
skeletons for functions like this.
If I run this hyperlink here -
and note that in the code of
`find-emacs-tangents-links',
in these comments here, I have a link
to this skeleton...
if I run this skeleton here
I get a buffer that has
this header, this `defun' here,
the optional arguments, and then this
field here, that is blank... in this field
is a list of of temporary variables that
I set in a `let*'.
For example, let me change this to FOO
and BAR in uppercase letters.
If I execute this again I get
this other skeleton here, in which now I
this `let*' here, that sets FOO and
BAR to default values,
and then the indentation changes a bit.
If I delete these things and I generate
the buffer again...
look at this part here, the `let*' is
going to disappear, and this thing is
going to to move a bit to the left,
and one of these parentheses
is going to disappear.
That's it. So,
to write this function
`find-emacs-tangents-links'
I essentially started with a skeleton
like this,
I had a draft of this thing that I put
in the template,
and I just moved this thing to the
template and
put backslashes in the right places, so
that this thing is
going to be just a big string, because...
no, let's look at the source code.
If I don't have a backslash here then
this thing becomes a big mess and
some things that should be strings
are not going to be strings, and, well,
whatever...
So, this is how I wrote this function and
most of my template-based
hyperlink functions.
This one is called
`find-find-links-links-new' because it is
a successor of a previous version that
was called just `find-find-links-links',
that was my function that produced the
buffer that would create a skeleton for a
function called `find-something-links'
but this one was a bit messy, and
the new one is quite clean.
So I like it very much and I hate the
old one, but I still have the code
of it somewhere, and I think that I
still have some
functions that depend on it.
Now let's see one function that uses a
template...
its code is quite short, but I
that that's a very interesting idea.
In one of the sections of one of the
tutorials of eev...
the one that has number eight here in
the index of the tutorials;
it is called find-psne-intro, and
psne is a contraction of something
that was already a contraction...
this is explained there, but it's not
important now...
and the thing is that psne
is a way to download local copies of
files from the internet...
and it has this example here, where
if we execute these...
let me change to a smaller font...
if we execute this thing here we create
a temporary buffer, here,
that runs a shell, and we set the
target of eepitch to
this shell here... and now in the
lines that do not start with a
red star...
if I type an f8 here then that line is
going to be sent to the target buffer
as if the user was typing that line...
and in this case, these four lines...
they create a directory corresponding to
to the remote location of this
URL here,
it changes - it "cd"s to that directory -
and it "wget"s that file...
and it also saves the URL
to a certain log file.
So this is the general idea
And then this tutorial explains how i
use something
similar to this, but much more
complicated to download local copies of
files from the internet.
Let me switch to a bigger font again...
and the new way is by just using
`M-x brep'... and the "br"
in the beginning is the prefix that
indicates that we're going to do a
variant of `browse-url', and this "ep"
means that we are going to run
a version in Emacs of something that
I used to call "psne" 20 years ago.
If we run this hyperlink here
we get a temporary
buffer like this...
so it has some variants of how to
download this,
in which this thing here is changed...
and we have code to download a
local copy of this URL here...
and we have these links here
that will let us check the local copy.
so we get this -
the contents don't matter to us now...
and my favorite way of running this
is by typing `M-x brep',
which calls `find-psne-links'
on this URL here.
So it's a variant of `browse-url'
in which instead of browsing the url we
are generating a temporary buffer with it,
and this temporary buffer
allows us to,
to change the URL if we need to...
let me confirm here - and then we get this
this buffer here, and usually I just go
to this block, and I execute this
without even thinking.
So, the rest of this tutorial explains
the details, but let me go back...
The third template-based function
that I want to show is the function that
defines this `brep', because...
well, let me show this in practice.
The `brep' is defined
by this sexp here,
that uses a template... and this is a
variant of `code-c-d' that defines
this function... it generates a
lot of elisp code as text, and then it
`read's and `eval's it,
and it generates in this case
just one function that is
based on this function here,
`find-psne-links', that operates on urls,
and it defines this function here, `brep'.
And the nice thing is that we can
just add this prefix here, "find-",
to the line above, to check the code
that this thing generates...
So instead of executing this
code we are going to just generate
the code and show it as Emacs Lisp,
which means: with nice colors...
So this is the definition of `brep', and
the docstring of it is just "Apply
`find-psne-links' on URL",
and it runs blah blah blah, the details
don't matter...
and the general idea behind this
`code-something' functions and their
variants that start with `find-'
is explained in my presentation in
the EmacsConf 2020, in this position
here... let me just show it...
...that we saw in the
previous section...
we can see the 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-c-d',
and it creates a new temporary buffer
with the code that `code-c-d' would
execute...
ok, let me go back.
This is explained in the... even in the
main tutorial, because `code-c-d'
is very important and the variants of
`code-c-d' are very are, so there's a
section called "Shorter hyperlinks"
here, a subsection that is just about
`code-c-d'...
and this explanation here -
very brief but it sort of works -
of how `code-c-d' works... it produces
a big string using a template...
and an explanation of this idea of
prepending a "find-" to the `code-c-d'
to understand the code that the thing
generates...
And several of my functions that
are related to `code-c-d' accept extra
arguments,
and this tutorial has even a section
about these extra arguments,
using `code-c-d', that is the main
function that users are going to
to use... and it has some examples.
If we run just this
we generate this code here,
that starts with comments, and then it
has several definitions here: it defines
a variable,
and it defines several functions...
one of the reasons for using text
instead of using macros,
by the way, is that by generating
text I can add comments,
and these comments here have even
elisp hyperlinks to the documentation.
Ok, so this is the code generated by
just `find-code-c-d' without extra
arguments...
and we if we add an extra argument here
the output becomes a little bigger...
this section appears, and this section
defines a function that opens a node
in a certain info manual...
and then this thing explains a bit of
the innards, and a bit of the other
extra arguments that we can use...
So this was a very quick
introduction to this `code-c-d'
and its related functions...
and again: when I defined `brep'
I used one of these `code-something'
functions, `code-brurl', and we can
inspect its code by running
this `find-code-brurl'.
So: (code-brurl 'find-psne-links ...)
executes this thing here.
Ok, next section:
4. `find-esetkey-links'.
Sometimes... one of the things that
beginners often want to do
is to define new key bindings,
and I realized that I could use
the ideas of eev to provide a
different way of doing that.
If we just run (find-esetkey-links) -
or with `M-x' or with this sexp here, -
sorry, if we run with `M-x' we get
a prompt here that tells us to to give a
key and then a command... let me try
M-f5
and then the command is going to be
`next-line'. We get a buffer here that
has a big header with lots of help...
for example, this line here
shows the section of Emacs manual
that explains how to change key bindings
interactively...
it's not trivial to to save these key
bindings to your .emacs after defining
them interactively...
and these links go to the documentation
of these functions here...
and this has some calls to these
functions that
it seems that the Emacs suggests
people to use interactively...
but here we generate sexps
for them, both for setting the key
and for unsetting the key, and we can
save these the settings in our notes,
or even in our ~/.emacs file.
For example, I have these keybindings
here. I use the super key for several
toggles... here in my keyboard the
super key is the Windows key.
So if i use super-t I toggle the
`tool-bar-mode', which is this thing here...
so let's do that several times...
if I use super-m I toggle the
`menu-bar-mode'... I can have both at the
same time, I can toggle them
very quickly, whatever... but I usually
don't like them.
and I realized that one thing that
I do very often especially when I'm
recording videos with a big font is
that I toggle line wrap...
and I have a function, that i've defined
ages ago, that is called just `wrap'...
I used to call it with just `M-x wrap'.
Its definition is here. It's in my
~/.emacs, that is a total mess...
and I realized that I could use
this `define-key' here to define
super-w to wrap, and in this case here,
for reasons that I'm not going to
explain now, instead of setting this in
the global keymap I'm setting this
in the eev keymap... and if I go
here there's even a link to describe
what are the current
bindings in the eev keymap...
so we get them here,
and we get the `wrap' here.
So... in the emacs-devel mailing list
people are always discussing how to
make these things more user-friendly
without ever using Lisp, because
"USERS SHOULD NOT BE FORCED
TO SEE LISP", and I'm taking
exactly the opposite - I'm
doing everything with the Lisp
very evident, with no hidden text,
and whatevers...
and this is an experiment to see
if users like this thing... this is
very recent, I haven't
tested this in
guinea pig users yet, so I didn't get
any feedback yet...
but i think that this can be a good way
to teach users how to
to bind keys, especially because
if they type something wrong they can
see what they have
typed wrong, and they can see the sexps
that corresponds to doing that, they can
change the sexps, and so on...
Ok, this was was the fourth thing that
I wanted to show.
And the fifth thing that I want to show
now is how I download
videos from Youtube.
And this is really far from
a 5-minute hack, because this
one does a lot of magic.
And the idea, as always,
is that if we twist the notion of
"user" in exactly the right way
then user-friendly and hacker-friendly
become very similar to one another.
So this is _my_ user-friendly way to
download videos from Youtube that is
user-friendly to _me_, and maybe
to other people... but whatever.
The documentation about this
`find-youtubedl-links' is in this
section here
of the tutorial about how to use
audio and video files in eev...
in this section here...
and the idea is that
links to Youtube can have
several formats. The long format is this
one, but there's also a couple of
shorthands to this... and
they always contain an id
that is always 11 characters long.
It only uses certain characters,
and I don't remember exactly why, but
I decided to call it the "hash" instead
of the "id", so in the code i refer to
this thing as the "hash" of the
video everywhere.
And so... here the documentation says
how to download the video if you have
youtube-dl installed, and due to this
option here the video is going to be
downloaded with both its title and its
identifier in the local file name.
And my favorite way of downloading a
local copy is... with this function,
`find-youtubedl-links'...
it's code is here, it's not
very ugly, but the thing is that
it uses lots of internal functions
and variables to discover what
is the local file
corresponding to the video.
Let me show a demo - here. I'm going to
use a temporary directory for the
video just to not have so much clutter
in the screen...
let me switch to a smaller font again...
ok, let me recreate this directory.
By the way, i never type
these things by hand
what I do is that I just put
the name of the directory in a line
by itself,
and I type meta-uppercase-r.
And I get this.
But let's go back to the demo. I'm going
to set my favorite directories for videos
to this directory here, that is
a temporary directory that is not
the one that i tend to use... and
let me show how to download a certain
video.
So: the hash of the video is here...
I just have to place the coursor on the
hash and type `M-x find-youtubedl-links'...
and this function discovers
what is the hash around point,
let me type an Enter here...
and it produces this temporary
buffer here...
oops, sorry...
here we have two different functions
that regenerate this buffer in
slightly different ways...
and I'm going to run this script here.
Note that it has several variants that
run youtube-dl with slightly different
arguments... I'm going to to use the
default one.
It takes a while...
it downloads the video - it's quite short,
it's just 10 megabytes -
and now I have a video with that name -
I mean, with this hash in its name.
If I visit the directory where I'm
downloading the videos I'm going to see
that there's a video with this
string in its name, so if execute this
this sexp opens that directory and
uh searches for the first occurrence of
this string, which is exactly in the line
where my video is. It is here -
so my magic functions have to discover
the rest of this file name just
by this string here...
and if I run this sexp here,
that has nil in the place of the title,
then `find-youtubedl-links' is going to
try to guess the title of the video
from just this thing and the directory.
Let me try... TA-DA! It found
the right title, here we have a sexp
that concatenates the directory, the
title, and the hash, and the extension...
the magic functions also discover the
extension...
and if I change this {stem} here
I get short links to this video.
So if I execute this I get a short
link to this video... let's use the usual
trick...
if I run this `find-code-video'
here I will get the code that
`code-video' is going to run...
let me copy this to my notes...
these hashes look ugly. So, if I execute
this... note that now I have very long
lines, so I can type super-w, and ta-da,
it toggles line wrapping...
ok, so if I run this thing here...
I get a buffer that shows the
code that defines this function here -
`find-preadingvideo' - "The problem
with reading (something)".
If I just execute this line here it
defines `find-preadingvideo',
and if I execute this I open this...
"In the rest of the significant portion
of the play..."
in the beginning
but suppose that i've downloaded this
video because I discovered that it has a
sentence... a part that is very
important... so i took down notes of
where it starts and what is the sentence,
so I can just make a copy of this
that points to the right position...
"...of the play where Jocasta
the queen has no lines, and because we're
reading the play - most of us now read
the play very few of us will have the
opportunity - although i urge you to take
it if it comes - to see the play
enacted... there are some movie versions,
and occasionally..."
well, whatever.
These are things that I have just put
here because initially I thought
about presenting this in a
in a different order... so: this is how
I download videos from youtube,
in a way that is only user-friendly
if I define "users"
in exactly the right way, in which
the main user in the universe is me.
And the last template-based function
that I wanted to present is
`find-here-links'. This is one that
deserves another presentation, I'm
to record a video about it, but let me
present it very quickly. This is one
of the main functions of eev -
I use it hundreds of times a day
because the central idea of eev is that
we can keep executable logs of what
we do, and these executable logs
usually are made
half of hyperlinks to interesting things
and half of executable code, like
shell command, or things like that...
so this tutorial explained these ideas,
and then the technical details...
for example, if i run `find-here-links'
here... note that it is bound to
`M-h M-h', and...
when I type `M-h M-h'
it generates a a temporary buffer
with links to "here"...
here is a header with help, and here
is the link that I want: a link to
the tutorial in which i was...
And I want to show something that is
not very well documented yet,
that is a different way to create
links to video files, audio files, PDF
files, and so on...
it is explained in this section of
the tutorial but
i don't think that i've revised it
enough times yet, so it may not be
very readable...
and the idea is that if you type
`M-h M-e' then this runs
`find-extra-file-links', and
this is an experimental feature whose
behavior may change soon...
but here is how it works now.
Here is an example in Lisp. If we
execute this we get a temporary buffer
with several kinds of hyperlinks,
including `code-c-d', `code-video',
etc, pointing to this file here...
so: this block here supposes that
this file is a PDF file, this one
supposes that it is a video file,
and I can use this {stem} here
to generate functions that have this
string, "MYFOO", in their names...
let me show a more realistic
example of how to use this,
which is... let's go to the directory
where I've downloaded this video file:
here. If I type `M-h M-e' here I get
a buffer that lets me define several
kinds of links to this file...
this file is a video file,
and let me use this string to identify
it...
uh =(
sorry, I played this as an audio,
and there's no very easy way to to stop
it...
so, if I run this... now I've defined
these short links here...
`find-preadvideo'... and if i
execute this...
ok, sorry for the mess! And
these were the things that I wanted to
show in this presentation, and that's it.
Bye! =P