How Hyperbole Works
This article is a follow-up to an article I wrote
called What does GNU
Hyperbole do?
which was an overview of the Hyperbole
user experience. This article goes more into the technical details
of how Hyperbole works.
Hyperbole, at its core, is an Emacs Lisp system for assigning
executable code to pieces of text. Hyperlinks are triggered when a
universal action key binding {
M-RET }
is typed, and this triggers a cascade of pattern
matching rules on the piece of text under the cursor. Therefore a
hyperlink can be executed anywhere, regardless of major or minor
mode. This allows information in Emacs to link to other pieces of
information without explicitly programming it to do so.
Comparing it to ordinary Emacs hyperlinks
In Emacs, most hyperlinks you use are generated by a
major
or minor mode program using text patterns like
regular
expressions (regexs
)
or syntax
tables. These patterns are applied to the entire
text of a buffer. Any portion of text that matches the pattern will
have a hyperlink target attached to it using a data structure called
the text
properties, which is the same data structure that stores the
syntax highlighting information (like the font and color) of that
piece of text. Any change made to the text buffer will automatically
re-scan the buffer to reapply the syntax highlighting, including
the hyperlinks. Therefore hyperlinks in Emacs are very ephemeral,
always being generated on the fly by the major or minor mode set for
the buffer. There are hundreds of these major and minor modes
provided in the default Emacs installation: the
find-grep
command, Org-Mode,
and Texinfo
manual mode are just three examples of this mechanism at
work.
Hyperbole takes a very different approach: the hyperlink
action, that is, the action to be executed when a hyperlink
is activated is programmed separately from the document text
and buffer. When you see a hyperlinked piece of text within
a text document, Hyperbole looks up the hyperlink action for that
piece of text
on-demand, based on context, whenever
the { M-RET }
key is
pressed. This means the hyperlink target is not required to be
encoded in the
text properties of a piece of text in order to create a
functioning hyperlink, and Hyperbole hyperlinks can exist
independent of the major or minor mode set for a buffer.
Hyperbole is not mutually exclusive with other Emacs hyperlinks
Hyperbole recognizes when there are hyperlink text properties assigned to a piece of text, so you can always use the default hyperlink action that is set by the current major mode. Consequently, Hyperbole extends the hyperlinks generated by any of the other Emacs major modes with intelligence that Emacs does not provide out of the box.
Where are hyperlink actions actually defined?
So Hyperbole lets you program actions to be triggered on certain pieces of text in a document, but does not store the code for these programmable actions into the text of the document itself. So then, where does the executable code for these actions actually exist? Hyperbole provides two different places to store it.
1. Implicit Hyperlinks
Implicit
links
let you you reuse executable code already
provided by the Hyperbole system. This is used for pieces of text
that already encode a hyperlink, such as URLs, file paths, or any
text with a text
properties hyperlink already set. URLs, for example, are
often written by people directly into the plain text of documents,
and a URL already encodes it's complete link target. There is
no need to associate executable Lisp code with a URL in order to
trigger it's action. Activating a URL with Hyperbole will
trigger an implicit link action, which simply reuses the
code that understands how to activate URLs.
When you activate an implicit link, a cascade of
pre-defined parsers is matched against the text under the
point/cursor. If, for example, the regex pattern that matches a URL
matches the text under the cursror, the ordinary
browse-url
command built-in to Emacs is triggered. Hyperbole provides rules for
matching many
other types of implicit link patterns apart from just URLs.
The implicit link matching rules can use the full power of Emacs
Lisp, so you can define more intelligent, context sensitive pattern
matching rules than what an ordinary regex can match. These rules
are applied on-demand, that is, when the { M-RET
}
action key is typed. So even if your implicit link matching
rules are a bit complex, it still feels like these links activate
instantly.
This may seem a bit too magical for comfort, but
fear not: you can always check which Hyperbole implicit link action
would be triggered by typing the { C-u M-RET }
keys.
Users of the
Embark package
will probably recognize that Hyperbole implicit links work a little
like the embark-act
command. The difference with Embark
is that Hyperbole will try to do the right thing without presenting
a contextual menu of actions to choose from, Hyperbole will execute
the first action for the pattern that matches the text. I have
heard people describe Embark as similar to what a right mouse click
does in a GUI. By that analogy, Hyperbole would then be similar to a
left mouse click.
2. Explicit Hyperlinks
Explicit
links store the hyperlink target in a flat-file
database in the same directory as the document, in a file
named
. There is a very simple markup
language that denotes text in a document to be a hyperlink. The
markup for a hyperlink looks like this: .hypb
<( Link Name )>
. If the explicit link
markup delimiters are matched when the action key is typed, then the
Hyperbole looks-up
in the Link
Name
flat-file
database, and execute the associated action..hypb
Notice that the markup for explicit links looks a bit like ASCII art. This helps to keep the document as human-readable as possible, even when reading the document in a place that does not have access to Hyperbole functionality.
Would you use a markup language for creating links that look like this? <( YES )> <( NO )>
As with implicit links, there are many pre-defined explicit link types that you can use. The usual target types (URLs, file paths) are provided, of course. But there are some other targets that one might find surprisingly useful, like target actions for running shell scripts, or changing the Emacs window layout.