My Kakoune Editor Configuration

A friendly explanation of how Kakoune is configured.

Image for post
Image for post

ost likely you read this because you have some idea of what the Kakoune editor already is. If you don’t you can think of Kakoune as Vim for dummies. Yes, I include myself in that category. I have what amounts to goldfish memory when it comes to remembering tons of commands in advance coding editors.

Read more: Kakoune, the Text Editor I Didn’t Know I Needed.

I quite like the whole concept of Vim, but I can never quite get used to it. Instead I prefer to use more GUI oriented editors such as TextMate and VSCode. However there are many cases where a more terminal oriented editor such as Vim and Emacs is preferable. Vim has been my goto editor in these cases. But if you like me are more of a casual user of Vim, I think you will find Kakoune a superior alternative. It operates in very similar fashion to Vim. But it is like a modern more user friendly version of Vim.

Here is a quick example to see the benefits. With Vim you would delete three words with the d3w command. The logic of Vim is: First you type what you want to do, which is d for delete. Next you type the part of the text to apply this to which is 3w, meaning tree words from the word you are currently at.

The problem with this approach is that it is never readily apparent what you are going to perform your operation on.

Kakoune make some minor changes to the Vim formula to make this more user friend. With Kakoune the command is 3Wd. When you first just type 3W you will see the following in your editor:

Image for post

Meaning you actually see what part of the text will get affected by the command you are about to press next. Please note that W means Shift-W. In Kakoune like in a regular GUI editor you typically use Shift key to expand a selection. Thus in Kakoune 3w will jump to the third word and highlight it, while 3W will highlight all three words. Alternatively you can can jump three words with www or highlight three words with WWW.

Anyway this was just quick into to Kakoune, next I will cover how you configure the operations of the editor by specifically looking at the configurations I use.

Read more: Most Useful Kakoune Editor Commands.

Configuring the Kakoune Editor

This is my Kakoune configuration file on macOS. The location of the configuration file will be similar on Linux:

$ cat ~/.config/kak/kakrc
hook global InsertCompletionShow .* %{
try %{
execute-keys -draft 'h<a-K>\h<ret>'
map window insert <tab> <c-n>
map window insert <s-tab> <c-p>
hook -once -always window InsertCompletionHide .* %{
map window insert <tab> <tab>
map window insert <s-tab> <s-tab>
}
}
}

set global indentwidth 4
set global tabstop 4
# add-highlighter global/ number-lines

Normally there will be no file at .config/kak/kakrc in your home directory, so you will have to create it.

This particular configuration file is set to do a couple of different things. The part that starts with hook reconfigures how I do word completions in Kakoune. When you type in Kakoune it typically gives you completion suggestions.

Image for post

Normally Kakoune is setup so you cycle through these with Ctrl-N. That is not something obvious or natural for me. I greatly prefer to use tab for this purpose. That is what this hook is for. It replaces Ctrl-N and Ctrl-P used for cycling forwards or backwards in completions with Tab and Shift-Tab. Note that in Kakoune we use much shorter abbreviations for hotkeys. This Ctrl-N is written <c-n> e.g.

How to Discover Functionality in Kakoune

You may wonder how you figure out how to write a configuration like this. Of course you can Google, but it useful to understand how to modify this code to suit your needs. All the stuff you can write into the .config/kak/kakrc file you could also write while in the editor. Just like Vim, you can hit Esc and the : to get into a sort of command mode. Kakoune is very helpful when you do this because it shows a live help in a yellow box, giving you advice and suggestions. For instance when I type :hook I get this advice:

Image for post

You can see that I began typing the second argument which specifies scope for this command. Kakoune is helpful in giving me completions for possible scopes. Thus if I want to add line numbers to the current window I am working on I can simple write:

:add-highlighter window/ number-lines

As you type that out you will be given completions and explanations which help doing it. Sure it may be awkward to write this every time, but you can simple begin to write :add-high and use the up and down arrow keys to complete based on your previous history. This whatever commands you have used in the past which started with :add-high can be quickly cycled through.

Don’t want to use line numbers? Easy we can remove them with:

:remove-highlighter window/number-lines

This works in a practical fashion because when you have just written window/ I will get completions based on the highlighters I have previously installed.

Okay, I know I have been talking about highlighters as if it is obvious what I mean by that. This is a rather broad concept in Kakoune, that we will get into shortly.

Kakoune Concepts

To better understand how to configure and modify Kakoune, it helps to understand the key concepts that exists in Kakoune. To summarize these are:

  • Scopes — Which says gives a context for where a command applies. Does a command apply to all of Kakoune, a particular buffer or window? Note windows in Kakoune means a view of a buffer. A buffer is an instance of an open file.
  • Hooks — Hooks are actions you want to perform in response to certain events.
  • Highlighters — Manipulate how text is shown. These are cumulative. You can add multiple highlighters which all modify how your text is shown.
  • Commands — The stuff you actually do, such as performing highlighting, switch buffer, open file etc.

Scopes

When you open a file in Vim, Emacs or Kakoune you create a buffer. Or at least that is the terminology most of these editors use. You could also create a new buffer not associated with any existing files. In Kakoune a buffer could have multiple views. These are called windows. Thus you can modify the same buffer using two different windows which use different configurations. The normal scopes are:

  • window — Means applying a command to the current window being shown.
  • buffer — Apply to current buffer. That means all windows viewing this same buffer will be subject to the same command.
  • global — Applies to all open windows

Let us look at an example:

:add-highlighter window/ number-lines

This toggles line numbering for current window. To toggle for all windows you would write this instead:

:add-highlighter global/ number-lines

Hooks

Hooks are actions to perform in response to different events. A simple way to find out what events exists is to use the completion. Here you can see that I have tabbed through the list of possible completions to WinCreate. This is the event broadcast when a new window is created, e.g. because you just opened a file.

Image for post

To learn what the various events are actually for you can show the documentation for hooks. It lists all the different events. Just type:

:doc hooks

This creates a new buffer containing documentation. How do you close this buffer? There are lots of buffer commands that start with buffer and which has short-cuts so either of these will work:

:delete-buffer
:db

When a new file is opened, you might want to look at the type and decide on particular highlighters to toggle on. Guess what this hook does:

hook global WinCreate .*\.java %{ add-highlighter number-lines }

It helps to understand this by looking at the general format of the hook command:

hook <scope> <event> <filter> <command>

The .*\.java part is the filter. It is a regular expression which matches Java source code files.

What needs a bit more explanation is the fact that the command part is given as the somewhat cryptic looking:

%{ add-highlighter number-lines }

It is not readily apparent where the command is enclosed with the %{ } symbols. Before covering that lets just cover commands.

Commands

In addition to commands such as :doc and :buffer-delete Kakoune also has the ability to use the command you use while editing your text. You can use this is hooks. Here is an example:

:execute-keys xyo<esc>p

This looks really cryptic, but is really just a sequence of keystrokes you would use interactively. It is as if you used:

  1. x to highlight current line.
  2. Then you used y to yank (copy) current selection.
  3. o to insert a new line below.
  4. Get back to command mode by hitting the escape key. Special keys are written with <>. Thus escape is <esc>.
  5. Paste what was previously yanked with p.

Command Parsing and Expansion

Kakoune commands don’t work the way a normal programming language works where we have nested expressions which get evaluated in order and substituted. Rather the way to think about this is in terms of text substitution.

The command echo in Kakoune, will just show what you wrote like echo in the shell. Thus if I write the command:

:echo Hello World!!!

It will produce the Hello World!!! text string at the bottom of the text editor. The following line will just show the word data.

:echo date

But here is the interesting part. You can specify different ways of causing text to be expanded. Think of the Unix shell. If you write *.java on the shell prompt, that will expand to a list of every file ending with .java. That is what you Unix command sees. It never sees the *.java text. We got the same kind of thing happening in Kakoune.

If you write this, then the text string will expand to the output from a shell command before being past to echo.

:echo %sh{date}

When you run this I will get the output you see at the bottom of editor. You we get the current date Fri Feb 12 17:55:25 CET 2021 which is when I wrote that example.

Image for post

Kakoune has many different types of expansions. You can read about them by typing:

:doc expansions

I will not cover all of them here. Just the basics to understand my basic Kakoune configuration. With the %{} things are just substituted as they are. We can use that to provide text that runs over multiple lines like this example:

hook global InsertCompletionShow .* %{
try %{
execute-keys -draft 'h<a-K>\h<ret>'
map window insert <tab> <c-n>
map window insert <s-tab> <c-p>
hook -once -always window InsertCompletionHide .* %{
map window insert <tab> <tab>
map window insert <s-tab> <s-tab>
}
}
}

This means we can store a text representing a bunch of commands with the hook, to be run later. As this example shows you can nest expansions. Hence you could put something which expands to something else with a shell command when the hook is run.

InsertCompletionShow Hook Breakdown

So let us look at what is actually going on in the hook in I use in my Kakoune config file. The InsertCompletionShow is triggered when Kakoune shows a completion window. It happens as you are writing and it sees a possible match for something else in the current window.

Let us look at the first part:

hook global InsertCompletionShow .*

This says the hook applies to all windows (global) and to the InsertCompletionShow event for any file .*. Next comes the command, which has to be given as one text string. To bundle multiple commands into one text string we use the %{}. That is sort of a way of quoting everything. Similar to how you use "hello world" to quote a text string in the shell to avoid having the space being interpreted as separating two arguments.

Next we got this part:

execute-keys -draft 'h<a-K>\h<ret>'

This runs 'h<a-K>\h<ret>' key combinations in a separate buffer (the -draft option). h moves one character back. <a-K> Means to hold down Alt-Shift-K. <ret> is simply the return key.

Lets move to the next part:

map window insert <tab> <c-n>

This replaces one key stroke with a series of other key strokes. First we got to give context. window say this should happen in the current window. insert says we should do it while in insertion mode. That means when you are typing character into the window. The next part says that whenever you hit <tab> in insertion mode, this should be replaced by <c-n> which means Ctrl-N.

However we don’t want tab to work this way all the time while being in insertion mode. Hence as soon as the completion window is closed, we want to go back to normal:

hook -once -always window InsertCompletionHide .* %{
map window insert <tab> <tab>
map window insert <s-tab> <s-tab>
}

This tells Kakoune to map Tab to Tab and Shift-Tab to Shift-Tab. That means Tab is no longer translating to Ctrl-N.

Further Exploration

I hope this helps grokking Kakoune configuration. All of this is covered in the doc system built into Kakoune. But it can be hard to know where to get started.

While this may seem a bit complex, Kakoune doesn’t go much deeper. There is no built in script language like in Vim or Emacs. Instead the simple mechanism shown is intended to allow you to interface with other scripts or Unix commands.

Geek dad, living in Oslo, Norway with passion for UX, Julia programming, science, teaching, reading and writing.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store