What is Kakoune?
Kakoune (/kə'kuːn/) describes itself as a code
editor heavily inspired by Vim
, and like the venerable vi(1) and its
successor, its internal model interprets the user’s keystrokes like
utterances of a sort-of text-editing language
, but with a certain
linguistic twist (more on that later). Available—for reasons that will
later become clear—only on Unix-like systems, it was written in C++ by
Maxime Coste, has a clean code
base and runs like the wind in a
terminal. It is released under the Unlicense, which is compatible with
the GPL.
Skip ahead to Using Kakoune if you just want to get stuck in right way.
As a long time Vim user, Kakoune quickly piqued my interest and before
long I was convinced that it was the editor for me, and not just because
it’s incredibly obscure. Its grammatical reshuffle and wise design
principles put it above the rest for me, and I’m starting to think it’s
more than just a comfy nook in which to hide from the large and looming
cold hand of Emacs, the curious GNUisance (sorry) that swings
periodically over my shoulder whispering we have Org mode! And Lisp!
Maybe next year, Emacs. I really want to like you.
But that’s an essay for another day.
Here I endeavour to introduce the reader to Kakoune and present my thoughts on its merits and misfits in the context of a terminal-based, keyboard-driven workflow. I make frequent comparisons to Vim, and the reader would benefit from some experience with a modal editor such thereas. That said, those uninitiated in modal editors might find that Kakoune’s forgiving mechanics place it among the easier to learn.
Do we really need another Vim clone?
This is neither a fork nor clone.
In an effort to provide incremental results and interactivity (words
whose meaning became clear once I met the s key), the
selection-oriented code editor
takes a bold step away from some of
the Vim interactions familiar to many of us, while remaining competitive
keystroke-for-keystroke, millisecond-for-precious-millisecond.
Its author cites the Unix philosophy as one of Kakoune’s virtues, and certainly I would agree that it trumps Vim in adherence thereto (examples of this to come); and that is not to say it lacks enough features. Indeed it has built-in wrappers around Git, grep, make, and man, works with ctags, conforming linters and other things.
Screencast: browsing man pages in Kakoune
Vim is difficult to extend, not least because of the idiosyncratic
train wreck of a language that is VimL (or Vim Script, or
whatever). Conversely, Kakoune stands by its decision not to complicate
its language with flow control and whatnot, and instead relies on
languages we already know through its %sh{…}
blocks. And although
Kakoune is very usable out-of-the-box, one look at the plugins
page is enough to make any purist
cave.
%sh{…}
block; in fact—that’s how some of the
more complex plugins are built.
So what’s the twist?
Whereas vi’s keystroke language follows verb-object order, Kakoune inverts that by following object-verb order. In real terms, that means you make a selection (object) before deciding what to do (verb) with it. The object might be a character, word, sentence, paragraph, parenthetical, regular expression, you name it; the verb might be delete, yank (copy), change, indent, or even transformative operations like lint, format, uppercase, etc. In Kakoune, it is with this reversed grammar, this postfix notation, that you interactively sweep up a group or groups of characters before acting on them. That way if your object isn’t quite right, you can immediately correct it without having to undo and redo your verb.
I like to think Kakoune’s keystrokes as a text editing language
model,
in comparison to that of vi, is what linguists would call an
anastrophe—specifically an
object-verb inversion.
To English speakers, it might seem unnatural to place the verb last, but about 45% of documented natural languages have subject-object-verb order, including Latin, Ancient Greek, Japanese and Korean.
Isn’t that just Vim’s visual mode?
Well, yes, but Vim’s visual mode is a malformed afterthought in comparison, and you have to hit v every time you want to use it. Kakoune is visual mode done right, but not just that; it permits—nay thrives on—multiple selections (thousands if you wish but typically just a few) and provides some really neat tools to narrow them down incrementally, as we’ll see later.
This paradigm shift necessitated a revised set of key mappings, which Kakoune implements rather well if you don’t mind using Alt. Holding Shift means causes the usual motion keys to extend the selection, so unlike in Vim, traversing whitespace-separated words means holding Alt instead. And what about text objects? How do you select in and around words, parenthetical pairs, paragraphs, and so on? In Vim you begin by hitting v to enter visual mode followed by a or i. In Kakoune, however, normal mode is visual mode so instead Alt + a and Alt + i are used to avoid conflict with the normal meanings of a and i (append and insert).
English | Vim | Kakoune |
---|---|---|
Delete word | dw |
wd |
Delete up to whitespace | dW |
<a-w>d |
Delete inner word | diw |
<a-i>wd |
Delete back four words | d4b |
BBBBd or4Bd |
Change to end of word | ce |
ec |
Yank a sentence | yas |
<a-a>sy |
Change to next occurrence of ‘x’ | ctx |
txc |
Select to next occurrence of ‘x’ | vtx |
tx |
Indent three lines down | 3>> |
xXX> |
Unindent within braces | <i} |
<a-i>}< |
Admittedly, from the table above, my new favourite editor looks to be more complicated than Vim. Perhaps that’s true in some sense, but Kakoune’s strengths lie in its forgiving interactivity and incremental results, which are best experienced first hand.
Using Kakoune
At this point, I encourage the reader to play around with Kakoune. Have fun with it! Install it with your package manager or build it from source. Skim over the manual page for kak(1) and open a file in the terminal like so
kak example.cc
Make sure your terminal emulator supports alt key combinations and isn’t overriding them.
Have a look through :doc faq
, :doc keys
(then :doc keymap
for the
cheat sheet), and :doc commands
, experimenting as you go. That said,
the built-in help system is verbose and won’t exactly hold your hand.
The Kakoune wiki is more
navigable, and this
walkthrough
is particularly helpful for learning the basics. You can edit files and
manipulate buffers with the following commands
:edit <filename>
:buffer <name>
:buffer-next
and:buffer-previous
Use :delete-buffer
to delete a buffer. Write to disk with :w
and
quit with :q
. As you enter commands, you’ll see an ASCII art Clippy
show up in a box with the relevant documentation. Commands are
self-documenting, and many have a -docstring
argument in their
definition which enriches these info boxes.
Depending on your terminal colours, things might be unreadable. If so,
or otherwise, pick a colour scheme using the :colorscheme <name>
command. Try not to spend too many of your precious Earth seconds
fussing over which is best, as I did.
Kakoune shares a good deal of elementary keys with Vim, which eases the learning curve for veterans thereof. Of the lowercase letters, only s, z, x, v and m have completely new jobs. Hitting the a key, i or o or their shifted equivalents will enter insert mode in much the same way as in vi; Shift + Q and q handle macros; press u to undo (some will rejoice it’s Shift + U, not Ctrl + r, to redo); I could go on. As you’d expect, many motion keys accept counts, as in 4 w to traverse four words.
Motions
Get the hang of using motions—h, j, k, l, w, e, b, f and t for starters—and their majuscule equivalents; hold shift to extend the selection you already have; hit ; to reset the selection range back to the cursor itself. Then of course r, d and c are your destructive verbs, while ~, `, < and > are transformative; i, a, o and Shift + O respect the selection range (try it to see what I mean), as do y (yank/copy) and p (paste). Try combining some of these with Alt and see what happens. Try Alt + i or Alt + a and read the info box to see what you can do with them; same goes for [ and ], and their shifted equivalents { and } which, predictably, extend the selection.
Press g and you’ll see the ‘goto’ menu, which shows you the handful of keys that could complete the key-stroke sequence. Familiarise yourself with some of these.
Go to … |
Vim | Kakoune |
---|---|---|
Top of buffer | g, g | g, g or g, k |
End of line | $ | g, l |
Beginning of line | 0 | g, h |
First non-blank character | ^ | g, i |
Bottom of buffer | G | g, j |
End of buffer | G, $ | g, e |
Top of window | H | g, t |
Bottom of window | L | g, b |
Centre of window | M | g, c |
Last (alternate) buffer | Ctrl + ^ | g, a |
Path under cursor / in selection | g, f | g, f |
Same goes for v and the ‘view’ menu, which is for adjusting your viewport into the buffer.
View … |
Vim | Kakoune |
---|---|---|
Centre cursor vertically | z, z | v, v or v, c |
Centre cursor horizontally | Nope(*) | v, m |
Cursor on top | z, t | v, t |
Cursor on bottom | z, b | v, b |
Scroll left | z, h | v, h |
Scroll down | Ctrl + e | v, j |
Scroll up | Ctrl + y | v, k |
Scroll right | z, l | v, l |
set
sidescrolloff=999
.
Multiple selections
Pressing x selects a whole line, x again the next instead; or hold shift and see that X sweeps up multiple lines. Here’s where things get cool: sweep up a few lines with X or Alt + i, p and then press Alt + s. That splits the selection linewise into multiple selections. Another way to accrue selections is using Shift + C or Alt + Shift + C. Play around with these yourself. If things get out of hand you can hit Space to reset to one selection.
Aligning columns interactively
This is one case where multiple selections are your best friend. You just make your selections and hit & to align them vertically.
Screencast: aligning columns interactively
Narrowing
Still think multiple selections are a gimmick? So did I. Until I tried some of the narrowing mechanisms. What do I mean by that? Well, let’s say you want to replace all occurrences of ‘sir’ with ‘mate’ inside a particular paragraph. With your cursor situated somewhere within it, you’d press Alt + i, p to select the whole paragraph, then (and this is the good bit)
s, s, i, r, Enter
to select each occurrence of ‘sir’. Now you have multiple selections. Finally you’d type
c, m, a, t, e, Esc
to change each into ‘mate’.
Screencast: Incremental search and replace
To achieve the same in Vim you’d need to specify the line range of the
paragraph in an ex command (perhaps with the help of visual mode,
i.e. v, i, p), and provide the ‘g’ flag.
In Kakoune, everything is achieved with the keyboard-based text-editing
language
and as a result is more interactive in that it provides
incremental results so that you can make corrections on the fly.
You can enter a regular expression (see :doc regex
) into the
s command, but often simple key-stroke-based interactions
thereafter can achieve the same effect while being easier to come up
with and adjust as you go. As a contrived example, imagine trying to
replace the word that comes immediately after every occurrence of a
pattern.
A commonly used technique is to press % which selects the entire buffer. Then you can hit s to select occurrences of some pattern throughout the file. The information in the bottom right keeps count of how many selections you have.
The %, Alt + s combo is useful for operating linewise on entire files. For example,
%, Alt + s, Alt + k, i, n, c, l, u, d, e, Enter
will select all lines that contain the word ‘include’; or using Alt + Shift + K we can do
%, Alt + s, Alt + Shift + K, :, $, Return
to select all lines that don’t end with a colon. We could then do
Alt + k, ^, d, e, f, Enter
to narrow down further to only those that begin with ‘def’. Follow that up with an S key like so:
S, \, ., Enter
to split each selection at every period. As you can see, the narrowing tools are immensely powerful and the possibilities endless. And if you’re still not satisfied, there’s the $ key which filters your selections by piping each one through any program you like and keeping only those for which the program exists successfully—meaning you could always write a little shell script to be the predicate of that filter.
Changes through external programs
Don’t get too excited about $ before you’ve met |. This key is your program-wielding text-processing glue. The idea is that you make your selection(s) in Kakoune, type something of the form
|program args ...<ret>
and watch the magic happen. For each selection, Kakoune feeds it as standard input to the program, and replaces it with the standard output.
<ret>
refers to the Enter or Return key. See
:doc mapping
for more key names like this.
Word count and formatting
Starting with a simple example, you could select the entire buffer with %, then run it through wc(1) to get a word count of your prose:
%|wc -w<ret>
Or pipe it first through the appropriate pandoc(1) command to convert it to plain text, thereby eliding markup from your word count:
%|pandoc -t plain|wc -w<ret>
Or you could select a paragraph and pipe that through to fmt(1) or par(1), which are programs that nicely reflow paragraphs of text from standard input. This is why Kakoune seems to lack important features such as text reflowing; instead it makes it easy to delegate this sort of processing to other programs, thereby adhering a little closer to the Unix philosophy.
Evaluating code within the buffer
If your buffer contained a Python expression, say
factorial = lambda n: 1 if n<1 else n*factorial(n-1)
print(factorial(13) + factorial(16))
then you could select those lines and pipe it into python(1) by typing
|python<ret>
, leaving you with 20929016908800
as the
selection.
Screencast: Piping the selection through Python
The ! key does the same but without piping anything
through to the program: it simply copies the output of the program
into the buffer. For instance, !ls<ret>
will add a list of the
contents of the current directory before the selection. !cat example.sh<ret>
will add the lines of the file example.sh
before
the selection.
Inserting Emoji
Use Shift + | to conveniently pipe words like ‘smile’ 😄 and ‘house’ 🏠 to a program that converts stdin to emoji, like this one liner:
#!/bin/sh
xargs -r printf ':%s:' | pandoc -f gfm -t plain
The -r
option is a GNU extension.
Maybe Pandoc is overkill here, but you get the point.
Using the system clipboard
Piping to and from xsel(1) or xclip(1) is your interface to the X clipboard. Now you can copy those snippets from Stack Overflow and feed your cargo cult programming habit.
Primary selection | Clipboard | |
---|---|---|
Copy | $xsel -i |
$xsel -bi |
Cut | |xsel -i |
|xsel -bi |
Paste | !xsel |
!xsel -b |
User configuration
Mapping keys
Of course, you can create key mappings for these things to your heart’s
content. Nice thing about Kakoune is it has a proper way of keeping
user-specific mappings separate from global mappings, thanks to the
scope parameter of :map
. By default , is the prefix to all
user mappings.
As an example, here is a mapping I use all the time:
map global user m ': format;w;make<ret>ga: echo Making<ret>' -docstring 'Format and write the file, then call *make*(1)'
It’s scoped globally because I want this to work everywhere. Now I just hit ,, m to
- fix my sloppy formatting (
: format
)- the space after the colon prevents this command from being put into Kakoune’s prompt history
- write the file (
;w
)- the semicolon separates Kakoune commands
- run make(1)
;make<ret>
calls Kakoune’s:make
wrapper, which opens a new bufferga
goes back to the buffer I was working on: echo Making<ret>
is just for visual feedback.
Have a look at :doc mapping
for the full story. Note that :map
is
one of those commands that can take a -docstring
argument, which
becomes part of the self-documenting hints that you see throughout the
UI.
Classic line-editing shortcuts like Ctrl + w
and Ctrl + u that predate even Unix are missing
from Kakoune’s insert mode; those shortcuts do not fit the paradigm
that Kakoune implements
says the :doc faq
, but for me this is
one case where practicality beats purity.
See the kakoune-readline plugin.
Persistent configuration
Let’s say you’ve mapped a few keys and set a few options. How do you make them persistent between kak(1) sessions?
Create the file $HOME/.config/kak/kakrc
and place your mapping and
options in there. This is the analogue to one’s $HOME/.vimrc
.
When you start kak(1), before sourcing your kakrc
it first sources all
*.kak
files within your $HOME/.config/kak/autoload/
directory. That
means you can put anything—even Git repositories in there
(i.e. plugins)—and all non-Kakoune files don’t cause Kakoune any
grief.
See kak(1) (man kak
) for details on how exactly
Kakoune’s run-time files are sourced.
Once your autoload
directory exists, however, Kakoune decides not to
source the system run-time files under /usr/share/kak/autoload/
, so
you’ll want to link that system directory symbolically into yours:
mkdir -p $HOME/.config/kak/autoload/
ln -s /usr/share/kak/autoload/ $HOME/.config/kak/autoload/
Formatting the entire buffer
The :format
command is like doing %, | and
specifying some format-fixing program—maybe fmt(1), par(1)
or something else. You just need to set the formatcmd
option.
set-option window formatcmd par
The window
argument specifies the scope of this particular
assignment. See :doc options set-option
and :doc scope
for more
explanation.
Also look at autowrap_fmtcmd
and autowrap-enable
which wrap lines
for you while typing, so it doesn’t feel like you’ve reverted to using
Notepad.
Lightweight markup
If you’re writing in a lightweight markup language, be it Markdown,
ReStructuredText, AsciiDoc, or what have you, it’s nice to have a
program go through your writing and fix little formatting mistakes here
and there, remove trailing spaces and unnecessary line breaks and so
forth. Kakoune’s :format
command lets you do this really smoothly
without leaving the editor. Just set formatcmd
to some command that
calls your style linter with any appropriate arguments.
Pandoc can neatly reformat your lazy keyboard-mash markup by telling it that the input and output are of the same kind. ReStructuredText for example,
set-option buffer formatcmd 'pandoc -f rst -t rst --reference-links'
where passing --reference-links
is optional of course, but means you
can write an inline link and have it converted automatically to a
reference at the bottom of the file, which takes care of the otherwise
laborious task of managing references, their names and order by hand.
This could become slow for particularly large documents; here I’m using Pandoc to reformat some 600 lines of text and it takes a fraction of a second.
SCSS
In this
screencast
you can see me fixing a poorly written stylesheet using prettier(1)
with the following formatcmd
:
set-option window formatcmd 'prettier --parser=scss'
Hooks
You can use hooks to trigger a command when some event happens, such as
opening a new file, resizing the window, pressing a key in insert mode,
or the user being idle for some length of time. These also have an
associated scope. Read :doc hooks
to see how they work.
Filetype-specific run commands
Now, what if you want to set an option differently depending on the kind of file you’re editing? You can do that using the WinSetOption hook:
hook <scope> WinSetOption 'filetype=<filetype>' <command>
This hook is triggered whenever the filetype option is set to
<filetype>
. The command can be any list of commands. So to set a few
options that would be something like this:
hook global WinSetOption filetype=(css|scss) %{
set-option buffer indentwidth 2
set-option buffer tabstop 2
set-option buffer scrolloff 5,0
}
This can get repetitive for lots of different filetypes, so we can
factor this out using the function filetype-hook
as defined below:
define-command filetype-hook -params 2 %{
hook global WinSetOption 'filetype=(%arg{1})' %arg{2}
}
filetype-hook css|scss %{
set-option window indentwidth 2
set-option window tabstop 2
set-option window scrolloff 5,0
set-option window formatcmd 'prettier --parser=scss'
}
filetype-hook ruby|python %{
set-option window indentwidth 4
set-option window tabstop 4
set-option window matching_pairs ( ) [ ] { }
}
Should you use Kakoune?
There’s loads more to Kakoune, not least of which are its
plugins. But the potential for it to
be configured exactly how you like is huge, and it’s very easy to do so.
I haven’t even talked about evaluate-commands
and %sh{…}
blocks
here.
Kakoune is so smooth in the way it uses existing programs; take the clipboard for example: why should Kakoune bother with implementing a feature specific to and dependent on X, when it can very easily be done in run-time configuration by piping to and from a program such as xsel? This is a taste of the Unix philosophy, and it’s what makes Kakoune so wonderfully extensible.
But due to the difference in key mappings, existing Vim users will
become frustrated in the transition, and Vim veterans will be leaving
their beloved configuration behind, putting them back to square one. I
can see many Vim users dismissing Kakoune as an interesting idea, but
not worth the effort to learn. I mean, even its
creator describes it as an experiment for a
better code editor
.
I have found that learning to use Kakoune’s key stroke language has messed with my muscle memory somewhat when it comes to Vim and crucially Readline, although not as much as I’d anticipated. Still, I now use Emacs bindings in Readline, because they differ enough that I don’t get confused.
GNU Readline is the line-editing library used by countless terminal-based programs.
Update, August 2020: After much experience with all four,
my muscle memory can switch smoothly between Emacs, Readline, vi and
Kakoune. But
This write-up has been mostly positive, but my experience with Kakoune has not been without issue:
- I’m having to use Alt all the time now, which can be a bit fiddly to say the least.
- There’s just no way to have the cursor turn into a pipe shape while in insert mode, which is a shame because many people rely on that to indicate whether they’re in insert mode.
- Insert mode auto wrapping, which uses fold(1), will occasionally create a new line in the middle of a word I’m writing.
- Having lots of plugins and a lengthy
kakrc
can increase startup time, but this true of many if not all text editors.
Further reading
- kakoune.org – Official site
- README.asciidoc
- the Kakoune wiki
- TRAMPOLINE – walkthrough of Kakoune’s basic editing primatives.
- Kakoune Community Hub where you can find a discussion of this article.
- Why Kakoune — The quest for a better code editor – Maxime Coste
- Kakoune – Bri Hefele