This is a card in Dave's Virtual Box of Cards.

'ratlink' a fuzzy search link-maker for this site

Created: 2023-01-20

I’ve made working on this website pretty painless. But linking between pages was always a bit annoying.

Now I can just type ,rl (stands for "rat link") in Vim and get a fuzzy-finder for all of the pages in my website. Choosing one creates the link. It can also embed images (by file name) with ,ri ("rat image").

See also:

This tiny bit of Vim script in my .vimrc launches the linker. I really don’t enjoy writing Vim script, but a little goes a long way:

function! Ratlink(type)
    let l:from_path = expand('%:p') " get whole dir path to current file
    " ratlink is my Bash shell script to make relative path to other page/file
    let l:link_path = system('ratlink ' . a:type . " " . l:from_path)
    " v:shell_error is exit code after system() call - my ratlink script
    " returns a 1 when the fuzzy find has been canceled with Esc
    if v:shell_error > 0
        redraw!
        return
    endif
    execute "normal! a" . l:link_path . "\<Esc>"
    redraw!
endfunction
nnoremap <leader>rl :call Ratlink('link')<cr>
nnoremap <leader>ri :call Ratlink('image')<cr>

The bulk of the functionality is in a Bash script where I’m more likely to maintain it:

#!/bin/bash

# This can be invoked from the command line, but it was written to be
# called from a Vim function to link my wiki (and especially website)
# pages together.

# First param: 'link' or 'image'
kind="$1"

# Second param: The absolute file path FROM WHICH we will be generating a link.
# This will be used to create a relative link.
from="$2"
from_path=${from%/*}           # strip from last / to end

ext="\.adoc|\.html"

if [[ $kind == 'image' ]]
then
    ext="\.jpg|\.png|\.svg"
fi

# ag is The Silver Searcher (and -g searches for file names) by Geoff Greer
# zf is a fuzzy finder written in Zig by Nathan Craddock
match=$(ag -g "($ext)\$" /home/dave/wiki/ratf/src/ | zf)

# You can cancel the fuzzy find with Esc, which will return a blank match
if [[ -z $match ]]
then
    # I check the exit status in Vim, non-zero statuses do nothing
    echo "No file to link selected. Bye!"
    exit 1
fi

# Make relative path from input path/file to chosen path.
# or https://stackoverflow.com/a/53191456/695615
path=$(realpath --relative-to="$from_path" $match)

# Remove any .adoc extensions, or entire index.adoc!
# Will only apply to .adoc files Links
path=${path%index.adoc}
path=${path%.adoc}

if [[ $kind == 'link' ]]
then
    name=${path##*/}          # strip from last / to beginning
    name=${name%.adoc}   # strip page extension
    printf "link:$path[$name]"
else
    printf "image::$path[]"
fi

The best part is that I get to use two of my favorite tools in this script:

(See the comments in the Bash script above for detail.)

Now I’ll test the ability to embed images in pages with a few keystrokes:

rat logo
rat logo green

Nice!