ficd.sh/content/blog/kak/url-open.md

4.6 KiB

title date
Opening URLs In Kakoune 07 Jul 2025

One feature built into Helix is the ability to super-easily open URLs in your browser. All you need to do is move your cursor over a URL, and press gf. This is very helpful when reading documentation, emails, et cetera...

So, how can we do this in Kakoune?

[TOC]

Goal

Here's our target user experience:

  1. The user moves their cursor over a URL.
  2. The user presses a key.
  3. The URL is selected, validated, and opened.
  4. The user is notified of any errors or success.

Like any bit of custom functionality, the best way to go is to define a command. This gives us re-usability, and greater flexibility (since map only allows mapping to key sequences, not any arbitrary string of commands).

Selecting

First, we need to find the URL under the cursor. Of course, if there isn't one, we should fail at this step. The standard way to do this in Kakoune is by using a regular expression to filter the selection. If there's no matches at all, that's something we can try/catch.

We won't get far without a URL regex. When I'm including long regexes in #!kak execute-keys commands, I like saving them to a register, like so:

set-register b 'https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)'

Then, we just need to check if this regex exists around the user's cursor. Since URLs don't have spaces, we can select the surrounding WORD, and filter from there:

execute-keys -draft '<a-a><a-w>s<c-r>b<ret>"ay'

The above command selects the outer WORD, then runs the select command with our regex (stored in register b). Once the URL has been selected, it's copied to the a register. If there is no URL, the command fails.

Cleaning

It's usually better to allow regex to be a bit greedier, and then filter unwanted characters out of the result. In our case, some trailing punctuation is included in the capture -- we can use sed in a shell block to strip them.

clean_url="$(echo "$kak_reg_a" | sed 's/[][(){}.,;!?]*$//')"

Opening

Our next step is to figure out how we'd open a URL from the shell -- after all, anything we implement in Kakoune ends up running shell commands! If you have xdg-open available (part of the xdg-utils package on Arch Linux), this is simple:

xdg-open https://ficd.sh

XDG handles figuring out the correct application to forward the URL to. If your environment is set up properly, this is probably your default browser. If you don't have (or don't want to use) xdg-open, most browsers let you open URLs from the command line directly:

firefox https://ficd.sh

Depending on the browser -- if you already have an open session, the link will be opened as a new tab in an existing window. Nice!

Let's define an option which contains the shell command we'll use to open the link:

# %s gets replaced with the URL
declare-option str url_open_cmd 'xdg-open %s'

Then, in our shell block, we can substitute the cleaned URL into the %s format specifier, and evaluate the resulting string as a command:

if eval "$(printf "$kak_opt_url_open_cmd" "$clean_url")" >/dev/null 2>&1; then
    echo "info -title 'URL Opened' '$clean_url'"
else
    echo "fail 'url_open_cmd failed!'"
fi

Completed Plugin

That's it, that's all! We now have a command called url-open, which we can easily bind to something like gu:

map global goto u '<esc>: url-open<ret>'

Here's the complete plugin code:

declare-option -docstring %{
    Command for opening URLs.
} str url_open_cmd 'xdg-open %s'
define-command -docstring %{
    Open the URL the cursor is on with url_open_cmd.
} url-open %{
    evaluate-commands -save-regs 'ab' %{
        set-register b 'https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)'
        try %{
            try %{
                execute-keys -draft '<a-a><a-w>s<c-r>b<ret>"ay'
            } catch %{
                fail 'No URL found!'
            }
            evaluate-commands %sh{
                # strip trailing punctuation
                clean_url="$(echo "$kak_reg_a" | sed 's/[][(){}.,;!?]*$//')"
                if eval "$(printf "$kak_opt_url_open_cmd" "$clean_url")" >/dev/null 2>&1; then
                    echo "info -title 'URL Opened' '$clean_url'"
                else
                    echo "fail 'url_open_cmd failed!'"
                fi
            }
        } catch %{
            info -title 'URL Open' "Couldn't open URL: %val{error}"
        }
    }
}