embarking videos
Inspired by Prot's musings on completion, i've, ahem, embarked in a reconsideration of my completions setup (as you might have intuited from my recent experiments with the spotify API and consult). As it happens, i'm starting to feel quite at home with a combination of selectrum, prescient and consult, and the ideas to augment what i have with contextual actions using embark seem really natural to me.
The main premise of embark is pretty simple: one has categories of targets that can be acted upon (URLs, regions, files, buffers…), and, for each category, a collection of commands that take an instance of the target and do something with it (that is, a collection of actions on target instances). As you may imagine, user-defined categories and actions are a thing in embark.
A little application of those ideas immediately popped to my mind when i started reading about embark: streaming videos from video hosting platforms. For many reasons, i try to avoid switching my context to graphical browsers and prefer to play those kind of videos by passing their URLs to mpv, which in turn will use youtube-dl to stream the contents.
Now, it's very easy to recognise when a URL is a video URL, we just need to match it against an appropriate regular expression. For example:
(defvar jao-video-url-rx (format "^https?://\\(?:www\\.\\)?%s/.+" (regexp-opt '("youtu.be" "youtube.com" "blip.tv" "vimeo.com" "infoq.com") t)) "A regular expression matching URLs that point to video streams")
Given that regular expression, we can write a "video-url target"
finder function, using for instance the Emacs standard library
thing-at
:
(defun jao-video-finder () "Check whether we're looking at a video URL. Return (video-url . <URL>) if so." (when-let ((url (thing-at-point-url-at-point))) (when (string-match-p jao-video-url-rx url) (cons 'video-url url))))
Once we have a URL in our hands, playing it with mpv is very easy 1:
(defun jao-play-video-url (&optional url) (interactive "sURL: ") (let ((cmd (format "mpv %s" (shell-quote-argument url)))) (start-process-shell-command "mpv" nil cmd)))
Now, we can put both things together with embark and tell it, first,
that we have a new kind of target (video-url
), and, second, what
actions are associated to it (jao-play-video-url, among others).
The new target category definition is accomplished by adding its
finder function to embark-target-finders
alist:
(add-to-list 'embark-target-finders #'jao-video-finder)
Similarly, registering the possible actions for a target is done by
adding a keymap for it to embark-keymap-alist
. Embark provides the
utility macro embark-define-keymap
for easily defining new keymaps,
so, putting both things together we have:
(embark-define-keymap jao-video-url-map "Actions on URLs pointing to remote video streams." ("p" jao-play-video-url) ("b" browse-url) ("f" browse-url-firefox)) (add-to-list 'embark-keymap-alist '(video-url . jao-video-url-map))
Besides our default, jao-play-video-url
, i've thrown in for good
measure a couple other actions. Note that they don't need to be
specially defined, they're just stock Emacs commands taking one
argument; and also that jao-video-url-map
is just a run-of-the-mill
Emacs keymap. As such, it can also be used and modified via the
standard Emacs utilities: embark will just use the final
result 2.
With that in place, we're done3: one can invoke M-x embark-act
(most probably via a keyboard shortcut) when point is around (or right
before) a video stream URL, and then press, say, p
, to call mpv
on it.
You might be thinking that writing a single Emacs command doing the
same thing for us and binding it to a key is very easy too, so why
bother? Well, as a matter of fact, "writing a standard Emacs command
and binding it to a key" is exactly what we did, so, for starters,
making it all part of the embark system is not giving us much
additional trouble, if any (a couple of calls to add-to-list
, all in
all). In exchange, we reap the benefits of making our new action
interplay with the generic utilities and integrations provided by
embark (for instance, you'll see that a host of other generic actions
are available and readily accessible for free for our new video URL
target). This is, again, a good illustration of (and a homage to) the
modularity and orthogonality of a system composed of pieces such as
embark and friends.
Footnotes:
Note how we're defining jao-play-video-url
as an interactive
function, that is, as a command, so that it can be used as an action.
That's an illustration of a point highlighted several times by Prot in his talks: a key feature of these utilities is their smooth integration with existing Emacs vanilla APIs, in a modular way that confers them notable power. I cannot overemphasise how right on the money he is!
Well, this being Emacs, one is never done. We can build upon these ideas and add new tricks. For instance, i was musing about adding some kind of metadata to these video URLs, which would then be slurped by Marginalia and then be automatically available to all the other little elfs in this completion forest.