Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Kakoune, a Punk Rock Text Editor

I've been using Kakoune as my primary text editor for a few years. After using Vim for over a decade, I wanted to try some of the features listed on Kakoune's home page, like multiple selections and the object-verb editing language — and yeah, those are great. However, those aren't what's kept me using Kakoune. Instead, there's something about the overall design and values that I find satisfying.

I had a hard time explaining exactly what it was I liked about Kakoune, until one day I described it to someone as "very punk rock". I didn't have a specific analogy in mind, and I really only had a vague pop-culture idea of what punk was about, but it seemed worth digging into more deeply.

DISCLAIMER: I haven't actually talked about Kakoune with anyone who identifies as part of the punk community, or talked about punk rock with mawww or anybody else who's worked on Kakoune. Any misunderstandings or misrepresentations are entirely mine.

What is punk?

Wikipedia has a bunch of pages about the punk subculture, so here's some choice quotes from the introduction:

It is largely characterised by anti-establishment views, the promotion of individual freedom, DIY ethics, and is centred on a loud, aggressive genre of rock music called punk rock.

The punk ethos is primarily made up of beliefs such as non-conformity, anti-authoritarianism, anti-corporatism, a do-it-yourself ethic, anti-consumerist, anti-corporate greed, direct action and not "selling out".

[...]

Punk aesthetics determine the type of art punks enjoy, which typically has underground, minimalist, iconoclastic and satirical sensibilities.

That's a very intellectual summary, but I don't know how to convey a more emotional understanding in just a few words. Before going any further, I recommend watching the classic interview with Iggy Pop where he talks about hating the term punk rock, and his motivations. Beyond that, hit play on Never Mind The Bollocks... or The Clash and let's go.

The Licence

Before we even get into the design or implementation of Kakoune, I want to talk about the licence.

Most open-source licences work within copyright law to grant users permissions that copyright normally restricts. Kakoune's "licence" is different, though — it uses the Unlicence. Rather than working within copyright law, the Unlicence states that the software is in the public domain, i.e. that copyright law does not apply.

Can you just straight-up declare that a particular law doesn't apply to you? The exact answer to that question doesn't really matter: the legal profession is all about limiting legal risk, so any uncertainty makes this a terrible idea from a legal standpoint. Using the BSD or ISC licences would have the same practical effect, and put you on much firmer legal ground, so that's the path every lawyer would prefer. For example, Google's guidelines on using "public domain" code say:

Public domain is a complex topic that requires legal analysis on a case by case basis.

[...]

It is non-trivial to place software in the public domain. While an explicit disclaimer of copyright protection is required, that is not necessarily sufficient.

...and their rules for what projects Googlers can contribute patches to specifically forbids the Unlicence.

Meanwhile, the Unlicence website says things like:

Why Use the Unlicense?

Because you have more important things to do than enriching lawyers or imposing petty restrictions on users of your code.

While there may be ways to make the Unlicence more palatable to Google's lawyers, I get the impression that the creators of the Unlicence are perfectly happy the way it is now.

Going back to Wikipedia's list of punk values, we see things like "non-conformity", "anti-corporate greed", and "not selling out". I think the Unlicence is very punk-rock. It might not swear as much as the WTFPL, but it's setting out to offend lawyers, not 1970s tabloid readers.

Using Kakoune

Some popular text editors provide a polished, platform-native user-interface. Others build their interface on a web-browser rendering engine, giving them a completely custom interface that's highly portable. Kakoune does neither of these things, it only runs inside a terminal emulator.

In some ways this is incredibly limiting — everything is aligned to a character grid, you can't display any symbols or decorations that aren't text, and a terminal's keyboard handling is much more primitive than that of graphical toolkits. On the other hand, the terminal is vastly, vastly simpler than other output methods, and it's pretty easy to make something that looks about as good as any other terminal application. Today in October 2020, Kakoune uses the ncurses library for managing terminal output, but there's a branch in development that drops the external dependency and does all the terminal management manually — for a net decrease of 13 lines of code.

I think Kakoune's terminal-based interface is a lot like the traditional punk aesthetic of ripped clothes repaired with safety pins, or slogans hastily painted onto jackets. It's cheap to buy a new shirt from a store, it's easy to learn to sew enough to patch a hole, but literally anyone can slash a shirt and safety pin it together in under thirty seconds. In the same way, every platform has robust native widgets and lots of people know HTML and CSS, but literally anyone can add colours and formatting to a terminal-based "hello world" app in under thirty seconds. "Direct action" and "do-it-yourself ethic" are on Wikipedia's list of punk values, and it's hard to name a computer interface more egalitarian than the humble terminal.

I also want to point out another detail you'll quickly encounter when using Kakoune. As you can see in the screenshots on the website, Kakoune frequently displays help-text for the next key press or the syntax for its built-in command line. By default, Kakoune displays the image of a helpful paperclip next to such messages, satirising the less-than-helpful Microsoft Office Assistant. Sure enough, "satirical sensibilities" are on Wikipedia's list of punk values too.

Scripting

No tool can completely cover every possible use, especially in a field as broad as text editing. Like many other editors, Kakoune can be extended with user-created scripts. However, Kakoune's scripting has some interesting twists of its own.

Let's say we're auditing an online payment system, and want to check that it doesn't log customers' credit-card numbers. Let's also assume this code-base consistently uses the abbreviation "ccn" for "credit-card number", so we want to find locations where the word "ccn" appears inside a call to the logging function. To do this interactively, a user might type something like:

%slog\(<ret>m<a-k>\bccn\b<ret>

...where <ret> means the Return key, and <a-k> means Alt+K. This basically means "find all the calls to the logging function, select the arguments, then focus on argument lists that include the word 'ccn'". That's not a 100% bullet-proof validation, but it's a quick way to find the most glaring problems.

Doing that interactively is reasonable on a single file, but our code-base probably contains many, many files. We ought to script this functionality so we can quickly repeat it on many files. In Kakoune's scripting language, the easiest way to perform these actions on demand is:

execute-keys %slog\(<ret>m<a-k>\bccn\b<ret>

Yes, that's just the keys you'd type interactively, used almost verbatim as a parameter to the execute-keys command. Sometimes, people familiar with more sophisticated text editors or general-purpose programming languages find this to be unreadably grotesque, and they ask if there's a way they can script Kakoune more like this:

select-buffer
find-all 'log\('
extend-selection-to-matching-bracket
for-each-selection {
    if not find-any '\bccn\b' {
        drop-selection
    }
}

This is definitely more readable for somebody new to Kakoune, especially somebody with programming experience. However, there's a cost to this scheme most people don't think about: while it's a lot easier to look at this code and guess what it does, it's much harder to look at the keys you'd press interactively and guess what the equivalent script would be.

Now, there's a school of thought that says that code is read more often than it's written, so easy-to-read is more important than easy-to-write. That school of thought comes from computing's military and commercial origins, where non-technical users would ask programmers to solve a problem for them, and then the programmers would have to keep the solution working forever. On the other hand, the punk do-it-yourself safety-pins-and-painted-slogans ethos says that users shouldn't need a pack of programmers, writing scripts should be easy for everybody. It doesn't matter if it's hard to maintain an old script if writing a new one is fast and cheap. And therefore, Kakoune's scripting system optimises for writing, not reading.

There's also another reason the "readable" script above can't be written today: Kakoune's "scripting" does not support loops or if-statements. It's not really a scripting language in the traditional sense, it's pretty much straight-line imperative instructions.

(I'm not going to claim that Kakoune's scripting language is Turing-incomplete. I suspect it's intended to be incomplete, but Turing-completeness can be tricky, so who knows, really.)

If you want to do any kind of processing, you need to shell out to an external program — and I mean "shell out" literally. Kakoune has a special syntax for marking a block of text as a POSIX shell-script, and replacing the block with the output of that shell-script. Let's say you want to make Kakoune display an info box (the one with a picture of Clippy) if current line begins with the word "Dear". The core decision-making part of the code might wind up looking like this:

evaluate-commands %sh{
    if [ "Dear " = "$kak_selection" ]; then
        echo 'info "It looks like you'"'"'re writing a letter"'
    fi
}

If you're like most software engineers, you probably had a pretty violent reaction to the above example. Having to launch an external process just for a conditional? Having to dynamically generate and evaluate code instead of just writing it? Having to deal with multiple layers of quoting? And all this in POSIX shell, widely regarded as one of the ugliest and most treacherous languages in common use? Surely this is a terrible idea!

And yet, there are some distinct advantages. Some people know C, some people know JavaScript, but everybody has to know at least a little bit of shell to get by. Some languages are designed to be embedded into a host application, some languages are designed to stand alone, but every language can take command-line arguments and print to standard output. Even if other languages are better at expressing logic, or at processing data, integrating different programs requires plumbing them together, and shell is great at that. So even if POSIX shell itself is one of the worst languages, for integration purposes it is every language.

It's still pretty ugly, of course, and some might consider it downright offensive, but punk has never shied away from offending mainstream tastes — in fact, quite the opposite. Not that Kakoune was designed primarily to offend, but it was definitely designed, and if the end result causes an uproar in the tabloids, they're more than welcome to spend column-inches talking about it.

Plugins

Kakoune does not support plugins, in the sense that the word "plugin" (or any variation) does not appear anywhere in the editor's source-code. Instead, at startup Kakoune just loads all the *.kak files it can find in ~/.config/kak/autoload/.

As a result, there's a really smooth gradient of modularity from sticking something in your kakrc, to splitting it into a separate file in your autoload directory, to giving a copy to your friend to stick in their autoload directory. At no point do you have to write a metadata file, conform to a directory structure, or sign up for a developer account. It's all just a natural progression from scratching your own itch to helping others. You can go further and add a README or put your plugin in a Git repository to help people keep it up-to-date, set things up so it gets listed on the official website, but that's entirely optional — you can do it if you want or don't if you don't.

I've already mentioned the punk values of "direct action" and "do-it-yourself", but I think this is an excellent demonstration of those ideas. Kakoune's whole scripting system is designed to make it as quick and painless as possible to go from doing a thing manually to automating it and sharing that automation with others.

But is it any good?

I confess, I'm not really a fan of punk rock myself. The music is very loud, and aggressive, and I just don't have that inner reserve of frustration and anger that the Sex Pistols tapped into in 1977. However, I respect the time and effort that goes into creating punk rock (or any other creative outlet), I have sympathy for ideas like anti-consumerism and non-conformity, and I absolutely love punk's radical accessibility, encouraging and empowering everybody to express themselves.

In the same way, although Kakoune has design limitations that annoy me, and there's occasional bugs or things that are confusingly documented, I love Kakoune's radical accessibility. I'd rather use rough, unpolished software with that philosophy than beautiful, powerful software that only provided the functionality the creators thought I should have. More to the point, I'd rather be part of the team working in and around the software I use than part of the politely-applauding audience.

But that's just me. That's who I am, and the kinds of things I value. Other people value different things, and would probably hate using Kakoune. That's OK, the world's big enough for multiple viewpoints.

But if you do like punk rock, I recommend trying Kakoune as your text editor.

Thanks

Thanks to cjv, avalenn, and the rest of the folks in #kakoune on irc.freenode.org for reviewing drafts of this essay.

@lenormf

This comment has been minimized.

Copy link

@lenormf lenormf commented Oct 8, 2020

Yes, that's just the keys you'd type interactively

The creator of the project got inspired by sed's language:

I think I see sed as a pretty good text editing language, and I liked the idea that commands are single char
I mean, even if sed is not interactive, part of its appeal is how concise you can express you text modifications with its language, if you had to use command names, it would lose much of this appeal

Refer to the following discussion below to get some context surrounding the quote above.

Discussion from #kakoune @ FreeNode
nick log
bitonic and i'm still short of a case where the new behavior is more convenient. i don't think consistency should be the primary goal for an editor, since the vast majority of the case you're editing by muscle memory, not by first principles
bitonic so i'd favor the latter
ironzorg inconsistency makes scripting harder
bitonic ironzorg: well, i think here the disagreement goes down to the fact that i would not have the same api for editing and for scripting, since they have very different concerns
bitonic for a programming API consistency and predictability are important
bitonic and so is readability and maintanability -- concerns which just do not exist when you edit
bitonic so i think having one api for everything the original sin -- but then again, it's not my editor :)
mawww Well, as always, its a tradeoff
mawww I like the idea that the editing language is both usable for interactive and non-interactive uses
bitonic mawww: i'd basically go more emacs style in that regard, where key bindings and commands are separated
mawww Yep, not going this way was an early design choice for Kakoune
ironzorg so get rid of primitives entirely and rely on 10 keys long shortcuts ?
bitonic ironzorg: have the key bindings to be shortcuts for commands
bitonic mawww: i'm curious, have you written down the motivation for that anywhere?
mawww nope
bitonic it's quite clear that you wanted to avoid that, i'm curious on why
ironzorg modal editors don't work that way
bitonic ironzorg: vim can be scripted in many languages
bitonic it started out this way and then inevitably evolved towards having a proper programming language to configure it
ironzorg mappings are still primitive that were not replaced by commands
bitonic i understand, but in practice people script it with a very different language than what people edit it with
mawww I think one of my main concern was that once you have bindings to commands, the default set of bindings is not really special anymore, so if you want to explain how to do a complex operation, you need to use the command names
mawww Like, how to replace all instances of foo with bar in the current curly braces block ?
mawww { sfoo cbar
bitonic mawww: you could have exactly the same UI as kakoune with a proper language for scripting
bitonic e.g. nothing prevents you from having a really rich ui of key shortcuts
bitonic anyway as i said it's your editor, not mine! and i really like it anyway
bitonic anyway, thanks for the discussion / explanation, ttys!
ironzorg it would be a fun experiment as a fork
ironzorg soft bindings from a language to kakoune's primitives
mawww I think I see sed as a pretty good text editing language, and I liked the idea that commands are single char
mawww I mean, even if sed is not interactive, part of its appeal is how concise you can express you text modifications with its language, if you had to use command names, it would lose much of this appeal
mawww But I must confess that I sometimes wonder about introducing a command layer
mawww And then I thing "dont be silly, you knew what you were doing back then" :D
Screwtape That's interesting. I came to Kakoune from vis, which does have a text-editing language (specifically sam's), and Kakoune's deliberate choice not to have a language was novel.
ironzorg it was the right call
mawww Screwtape: isnt sam's editing language the same as kakoune, one char commands ?
mawww I think Kakoune in a way is a more interactive, less pure sam, we support structural regex for example, by chaining s commands
mawww and we have much more commands than sam has
ironzorg also vis uses Lua as far as I know, so kakoune hits two birds with one stone
Screwtape sam's editing language is very similar to sed, where each command takes addresses like "line 5" or "the previous match for this regex" or "the current selection, expanded to the following newline".
Screwtape It's pretty cool in a minimalist way, but I've adapted to Kakoune's more interactive UI more rapidly.
Screwtape Part of it is that Kakoune has a bunch of keys to do all the different things, while sam has very flexible syntax, so it's easier to find the right keystroke in keys.asciidoc than to engineer a sam expression from first principles.
Screwtape Yeah, Kakoune's configuration syntax was very impressive. It's a little bit like TCL, I guess, or like shell, where everything is expanding string substitutions.. but vastly more sensible and coherent than Bourne shell syntax.
@sucrecacao

This comment has been minimized.

Copy link

@sucrecacao sucrecacao commented Oct 10, 2020

I totally fololw bitonic's point of view on this discussion
.
I really don't like the idea that the editing language is both usable for interactive and scripting use.

Maybe kakoune default keybinding are better than vim, but they are not perfect. Maybe they are perfect for mawww but they can not fits every user. Therefore, remapping kakoune default keybinding is very likely to happen.

For my part, I didn't like a lot of kakoune's default mapping, more over I don't use a qwerty keyboard. So I had to remap almost 30% of kakoune mapping.

Now, editing my kakrc is way more harder than it should be, because I have to check kakoune default binding every-time and translate when I write a script. Imagine writing and reading code in a language where every command is just a random letter.

This design is holding back from doing new remapping, because I know it's going to make my kakrc editing harder. It's also holding me back from switching to ergonomic keyboard layout like colemak because I know it's going to create a big mess.

It also make project similar to https://github.com/pacha/vem/ impossible to do with kakoune.

I think it's sad that such "punk" and unix editor like kakoune is holding me back from remapping the default keybinding and changing my keyboard layout. It in contradiction with it's initial philosophy .

I'm in favor of changing this design, if anyone wants to start a fork on this I'll join instantly.

@Screwtapello

This comment has been minimized.

Copy link
Owner Author

@Screwtapello Screwtapello commented Oct 11, 2020

It's OK that one tool isn't equally useful for everybody. Kakoune doesn't work that well on non-POSIX operating systems, and it doesn't work very well for people whose writing systems aren't well supported in most terminals. It probably also doesn't work very well for people whose keyboard layouts don't overlap very much with ASCII (I use Dvorak and it's fine, so I don't think QWERTY is necessary, but ASCII probably is).

If you're willing to use a Kakoune variant that's incompatible with regular Kakoune, why not start by customising the default mappings in the source code? It's pretty straightforward, even if you don't know much about C++, and that way execute-keys will be consistent with your interactive usage.

That said, I'd definitely love to see a bunch of Kakoune-inspired editors written by different people, optimised for different use-cases, just like there's a bunch of different Vi- and Vim-inspired editors and plugins around.

@sucrecacao

This comment has been minimized.

Copy link

@sucrecacao sucrecacao commented Oct 11, 2020

Thanks Screwtapello for the link and tips, I'll give it a try :)
Is this Hashmap used both for keypress event and execute-keys parsing ? Like what would happen if I rename the key i to <insert> ?

@Screwtapello

This comment has been minimized.

Copy link
Owner Author

@Screwtapello Screwtapello commented Oct 12, 2020

Yes, it's a map of keys to actions. The keys are used interactively, and the key-names are used for execute-keys parsing. I'm not sure what would happen if you tried to rename i to <insert>, since that's not a single key. Well, there is Key::Insert, but that's the key next to Home and Delete, not what you're talking about.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.