Short hyperlinks to Python docs
Eduardo Ochs
The following image shows where the talk is in the schedule for Sun 2022-12-04. Solid lines show talks with Q&A via BigBlueButton. Dashed lines show talks with Q&A via IRC or Etherpad.
Format: 15-min talk followed by IRC Q&A (#emacsconf-dev)
Etherpad: https://pad.emacsconf.org/2022-python
Discuss on IRC: #emacsconf-dev
Status: Q&A finished, IRC and pad will be archived on this page
Description
If we have a local copy of the Python docs installed then it is easy to define the three hyperlink functions in the Python program below,
# (find-pydoc "tutorial/classes")
# (find-pydocw "tutorial/classes")
# (find-pydocr "tutorial/classes")
class MyVector:
def __init__(v, x, y):
v.x = x
v.y = y
such that each one expands its argument in the right way, and the
first one opens the local URL
<file:///usr/share/doc/python3.9-doc/html/tutorial/classes.html> in
the browser, the
second one opens https://docs.python.org/3/tutorial/classes.html, and
the third one opens the RST source of those HTML pages in Emacs: the
file /<rstsourcedir>/tutorial/classes.rst.txt
.
The docs for Python are designed to be navigated in a browser. Suppose that we start on the page classes.html above, follow a couple of hyperlinks, and then we find this other page that, ahem, is very interesting and important and we need to have hyperlinks to:
https://docs.python.org/3/reference/datamodel.html#object.__init__
The most obvious way to create elisp hyperlinks to that page is to
copy its URL to Emacs, edit it by hand to produce a (find-pydoc ...)
hyperlink, duplicate that hyperlink twice, and add a "w
" and a "r
"
into the right places… but this is not very practical.
In this presentation I will show a practical way to handle that. It is
a new module of eev –
eev-rstdoc.el
– that performs both the
expansions needed by find-pydoc{,w,r}
and the "shrinkings" that
convert URLs and filenames to short hyperlinks. Eev-rstdoc.el comes
with three "families" of hyperlinks, expansions, and shrinkings: one
for Python docs, one for SymPy, and one for MatPlotLib. It is easy to
add new families, and the parameters for expansion and shrinking in
each family are easy to configure.
For more info see this page. For a translation of the Python tutorial to a format that has only executable examples and elisp hyperlinks, see this.
Transcript
Hi! My name is Eduardo Ochs. I'm the author
of an Emacs package called eev...
and eev is about taking executable notes
of everything that you do, and this
presentation is about how I use this...
how I finally found a way to take
executable notes of what the python docs
say.
Let me explain that in another way. I've
try to Learn Python many times, but
hm, my brain is wired in a weird way, so
it didn't work... and finally a few
months ago I found a way of studying
Python that finally clicked for me.
The idea is that... well, it's here in
the title - is a way to create short
hyperlinks to the
documentation of python.
Here's an example.
This file contains some some chunks
of code from the Python tutorial and
some links to the places in which
I found these chunks of code.
for example, if I run this link here
it opens a certain page of the Python
tutorial in my browser - note that it
opens the local copy of the
documentation -
and if I
run this link here it opens the source
in .rst
of the same page. So the first link opens
the HTML and this one opens the
RST. This is useful because in the
beginning
I was copying these chunks of code in
the obvious way - I would simply
visit the the documentation in HTML and
I would mark
a chunk... a snippet of code here and I
would copy it to my notes.
And then after a while I
realized that it was much easier to
simply go to the RST sources and to copy
the chunks of code from there... and
note that these links look quite similar.
There's one difference here, that is
this r
that is prepended to the name
of the function... the r
means
"open the RST"...
and if I use the suffix w
it means
use the documentation on the web instead
of using the local copy.
So this one
opens a local copy
and this one
takes a while
and opens the
the page of the documentation in the
site of Python blah blah...
and this thing here is
executable in the usual eev sense, that
we ca... if we type f8 several times here
the f8s on the lines that start
with red stars create a target buffer
here... and in this case it creates a
target buffer running Python, and if I
type f8 on these other lines these are
the lines are sent
to that REPL.
But anyway, let me go back.
Most of the things that I'm going to
present here are in the tutorial of this...
package...
we can go to the source code
here in the eev directory - it's a file
called eev-rstdoc.el but the best
docs are in the tutorial, here...
and the tutorial also has some
executable
chunks... some snippets of python
code that are executable, but they
don't have those nice colors... so
apologies for that.
We need to run this thing here to make
everything work.
This thing will define some functions
with funny names that I will
explain later.
Let me explain something new.
let's compare all these
links here. They take this argument
here and they expand the the argument in
a certain way. For example this string is
expanded to this long URL here... note that
it got a prefix here,
that's quite long... it got the .html here,
and then the hash and the anchor here...
and each one of the functions in the
pydoc family expands this
argument in a different way.
The one that that opens the doc in the
web uses another prefix -
this one - and the one that opens the rst
file ignores the part after the hash
for technical reasons... I was never
able to to find a good way to convert
this hash into a string to search for,
so to make something that goes to
the right section in the link to the rst
doc I have to convert by hand, and by
trial and error, this thing here into a
pointer to that section, like
this one...
in which the "_numeric-types:"
is here.
So all these links here are based on
expansion, and this is easy to
understand...
but suppose that I want to
create a link like this, or suppose that
I'm browsing the docs here
and I just I follow some some links...
let me do something random here...
suppose that I decide that this
section is very interesting. How can I
create a link to that? I can
use this pilcrow symbol and the
"Copy link address",
and copy the link to
my notes...
and then the Python family...
well, we saw the the functions in the
Python family have a certain way - have
several ways of expanding these
short arguments... and they also have a
certain way of
shortening URLs like this one. If I type
M-x pdk
the message is this one.
pdk
is a mnemonic for
"Python doc kill", and this
"kill" means "copy to the kill ring"
so if I type M-x pdk
here it
considers that this thing is a link
to the python Docs, and it
shortens this link in a certain way, and
it kills a short link.
I can insert the short link with C-y
(yank)
and then I can test this link to be sure
that it points to where I want, and
then I can delete this thing, and ta-da,
now I have a short link, and of course I
can modify this link by adding a suffix
here...
and in this case here
I will have to change the identifier
to something else...
but I'm not going to do that now.
This module of eev comes with three
families predefined. One is a family that
points to the the documentation of
Python itself, another one points the
documentation of SymPy, that is a program
for symbolic computation, like for doing
mathematics equations...
and the other one points to the
documentation of MatPlotLib.
How do these families work?
Each family has to be defined in two
parts.
Remember that
eev has lots of functions
like this one... this one
is the most basic, and it is explained
here, in this section of the main
tutorial. This section explains that
a sexp like this one produces lots of
functions - produces a family of
functions - and it does that by producing
a certain chunk of code and then
executing this chunk of code... and if we
add a certain prefix here... find-
and we
execute this we can... instead of executing
that chunk of code we can see what is
that chunk of code. In the case of code-c-d
it is this. It is a setq
, several
defun
s, and some comments here, with
links to the documentation.
In the case of rstdoc it's the same.
We have this function here that defines
the function in the python family...
and we can run this to understand what
this code-rstdoc
does.
It creates this temporary buffer here...
with lots of defun
s, a code-c-d
here,
and lots of comments here... and the
comments include some tests. For example
we can use these functions here to test
how the expansion works.
And
note that in this buffer here we don't
have the paths that that this family
uses. We don't have for example
the URL that points to the site of
Python, to the directory that contains
the reference manual, or whatever... all
these things are in another part of the
definition of that family - that is a
variable.
If we execute this we go to the
source code of eev-rstdoc,
to the parts in which
this variable is defined...
and
for each family we have a variable like
this,
whose value is a property
list with several fields...
these first fields are very easy to
understand - they are used in the
expansion... this one too. And these
two fields are used in the shrinking -
in the shortening - and
this field here
tells what is the name of the
killing function
so the fields of this thing here are
used
to generate...
some fields are used to generate the
code that appears here, and some fields
are simply
read by functions like this one, that
consults the variable.
Now the natural question is: how can we
define new families? Or: how can we change
a family like this one to point to
another version of Python?
There are some template-based functions
for doing that. They are explained in
this section of the tutorial...
where is that?...
oh God, it's far away...
here.
Suppose that we have a package foo, that
we want to create a family that points
to the docs
of that package foo... so, we
can execute this thing here, and it
generates this
this thing from a template.
If we just want to modify a current
definition we can run something like
this - note that the family :py
already exists, and instead of using
placeholders in some of these
URLs it will use the current values of
the fields...
so we can also use this modify
existing families.
Well these are the technical details.
Now the natural question is: why do I
want this? This doesn't
any sense to me! Why should I
try this?
And the best answer: is for most people
this way of using
executable notes do not make any sense
at all at first sight...
so what I'm trying to do is: I'm trying
to write to these tutorials with
many examples that are very easy to run,
and that examine data structures,
and functions, and test things,
and so on... so my main argument
for convincing people to
test this is: this is trivial to test -
simply install eev and run this thing
here, and run the examples, and probably
you're going to find that this
tutorial is fun to follow.
So that's it! =)
Captioner: eduardo
Questions or comments? Please e-mail emacsconf-org-private@gnu.org