How Hyperbole Works

Home About Codeberg

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 .hypb. 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: <( Link Name )>. If the explicit link markup delimiters are matched when the action key is typed, then the Hyperbole looks-up Link Name in the .hypb flat-file database, and execute the associated action.

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.