In emacs there is a feature called compilation mode. Was watching an emacs configuration video from Tsoding where he talks about it. The gist is that instead of hooking features directly to your editor, you reuse the cli version of the tool and use the output. It immediately made me think about the fifo.md I’ve been using to keep track of scripts running.
Compilation mode
Most modern editors (including TUI editors) have integrations with LSPs, unit test runners or linting tools. In my time with neovim I’ve spend more than a handful of hours getting Jest to work correctly for example. LSP integration was less of a pain in the current days, but it’s not an out of the box experience. Paid editors like IntelliJ IDEA come working with most out of the box.
But even in the best case, when a new tool or language comes out it does not immediately come with an LSP most of the time. Elm in the beginning did not have an LSP, wgsl currently. But most tools do come with a CLI tool to run.
Compilation mode is using the CLI output directly in an editor buffer. No integration like running it in the background and underline a wrongly spelled variable. You won’t get the line where a test failed marked in your editor. However; you get experience working with the actual compiler that will most likely run in CI anyway. Configuring the output to bind key mappings to jump to files takes 5 minutes.
Navigating the output of a CLI command is also more convenient in a kakoune buffer. You can select the failed assertion of a unit test conveniently.
Creating a fifo from kakoune
I’ve extracted the function that cargo.kak uses to create a temporary fifo and close it when the buffer is detached. I use that function now for all my external commands.
define-command run-in-fifo -params 2 %{
evaluate-commands %{
write-all
}
set-option global last_command %arg{1}
set-option global last_command_type %arg{2}
evaluate-commands %sh{
output=$(mktemp -d "${TMPDIR:-/tmp}"/kak-fifo.XXXXXXXX)/fifo
mkfifo ${output}
( eval $1 > ${output} 2>&1 ) > /dev/null 2>&1 < /dev/null &
printf %s\\n "
evaluate-commands -try-client '$kak_opt_toolsclient' %{
write-all
edit! -fifo ${output} -scroll *compilation*
set-option buffer filetype $2
hook -once buffer BufCloseFifo .* %{
nop %sh{ rm -r $(dirname ${output}) }
evaluate-commands -try-client '$kak_client' %{
echo -- Completed $*
}
}
}
"
}
}
It allows you to run a command, pipe the output to a fifo buffer, open that buffer in kakoune, and give it a filetype. The filetype is used by hooks to add custom commands to the buffer that uses the structured format the command outputs to allow you to for example jump to errors.
Unit tests, linting and compilers
I now use this way of working to run my unit tests for a frontend project. Run :run-in-fifo ‘npx jest’ jest I’ve added a jest.kak to my kakoune config where I add hooks and keybindings for specific jest output.
You can also use it for eslint or the typescript compiler. Same way of working and it works for everything that is able to run from the command line and has a structured output.
Grep
You can extend it to use grep from kakoune:
:run-in-fifo 'grep -n test *.md' grep
And all you need is to create a few hooks to directly jump to files from your grep results.
ls
Kakoune doesn’t come with a file tree or netrw type solution. I’ve used kaktree for the time being and while it works it requires a perl script to function. Meaning it’s quite complicated for someone like me to extend it, and adds complexity by introducing yet another concept.
I’ve run into someone on discord who shared a very elegant solution using fifo buffers and the same minimal hooks and file type trick.
Like the ls
in compilation mode.
It’s only a 100 lines of code, and gives you a way to browse your files from your editor.
Repeat last task
Another convenient thing is when you are running a thing, can be unit tests/compiler/or even running a task with npm or cargo example. You can keep the last ran command in a variable and assign a key mapping to rerun the last one.