mirror of
https://github.com/mawww/kakoune.git
synced 2024-11-22 13:28:32 +03:00
Merge why-kakoune asciidoc source git history into the website git repo
This commit is contained in:
commit
63d00dda6e
2
why-kakoune/Makefile
Normal file
2
why-kakoune/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
why-kakoune.html: why-kakoune.asciidoc
|
||||
asciidoctor $<
|
362
why-kakoune/why-kakoune.asciidoc
Normal file
362
why-kakoune/why-kakoune.asciidoc
Normal file
@ -0,0 +1,362 @@
|
||||
Why Kakoune -- The quest for a better code editor
|
||||
=================================================
|
||||
Maxime Coste <mawww@kakoune.org>
|
||||
|
||||
image::kakoune_logo.svg[align="center", link="http://kakoune.org"]
|
||||
|
||||
Why invest time into text editing
|
||||
---------------------------------
|
||||
|
||||
While discussing with fellow developers, I was asked the following question
|
||||
a few times: We spend most of our time as developers thinking, not editing
|
||||
code; so, why invest time into mastering a complicated code editor, and why
|
||||
lose some cognitive resources on thinking about text editing instead of
|
||||
about the real programming problem?
|
||||
|
||||
I think this point of view is misguided, for a few reasons:
|
||||
|
||||
* Despite their name, code editors are not only about editing, but also about
|
||||
code navigation. Programming is a hard task partly due to the huge amount of
|
||||
context we have to keep in mind, and being able to quickly navigate code helps
|
||||
us refresh that context, by looking at definitions, implementations, and comments.
|
||||
|
||||
* Although code editing itself is not the most important part of programming,
|
||||
it still takes non-negligible time to perform, and can be optimized by using
|
||||
better tools.
|
||||
|
||||
* Finally, a programming career spans a few decades, so investing a few weeks
|
||||
to improving our editing and navigating speed is definitely worth it.
|
||||
|
||||
Why a modal text editor
|
||||
-----------------------
|
||||
|
||||
What is modal text editing
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now that we have established that investing time into mastering text editing
|
||||
is worth it, let's focus on why I think modal text editors are the way to go.
|
||||
|
||||
A modal text editor can be, as its name implies, in different modes. Depending
|
||||
on the current mode, keys have different effects: in *insert* mode most keys
|
||||
insert their character in the buffer, as in non-modal editors, but in *normal*
|
||||
(default) mode, keys have a different effect. For example, `w` can move the
|
||||
cursor to the next word, `y` can yank (copy) the current selection, `p` can
|
||||
paste, `u` can undo, `g` followed by `f` can open the filename under the cursor...
|
||||
|
||||
Some commands from *normal* mode would change the mode, for example `i` would
|
||||
enter *insert* mode, from which the `<esc>` key would return to *normal* mode.
|
||||
|
||||
The first thing to realize is that non-modal text editors are extremely biased
|
||||
towards insertion. They make insertion easy (by making the default behaviour of
|
||||
most keys to insert a character into the buffer) at the expense of making most
|
||||
other operations suboptimal, by requiring hard to reach keys or modifiers (or,
|
||||
even worse, moving your hand all the way to your mouse).
|
||||
|
||||
Insertion is a key part of text editing, and is worth optimizing, which is
|
||||
the whole point of completion systems. But it is only a small part of text
|
||||
editing, we spend a huge amount of our editing time navigating, moving code
|
||||
around, copying, pasting and reformating.
|
||||
|
||||
A modal text editor makes all these operations much more accessible, and easier
|
||||
to express. But they are not only about having convenient shortcuts.
|
||||
|
||||
Modal editing as a text editing language
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Many vi users have an epiphany when they realize that vi does not just
|
||||
provide a set of modes making various text editing shortcuts easier to type,
|
||||
but actually provides a text editing language.
|
||||
|
||||
Commands are composable in order to express complex changes, `dw` in vi is
|
||||
not just a shortcut to delete a word, it is the combination of a *verb*: `d`
|
||||
for delete, with an *object* `w` for word. There are more complex objects like
|
||||
`ib` (inside block) refers to the content of the parenthesis surrounding
|
||||
the cursor, so `yib` would yank (copy) the text inside the surround
|
||||
parenthesis.
|
||||
|
||||
This language allows the programmer to express their intent much more closely
|
||||
than in other editors; most editors can express "delete the word after the
|
||||
next parenthesis", but more often than not, expressing that intent is more
|
||||
cumbersome than simply doing an ad-hoc edit. Text editing as a language
|
||||
changes that, by making clearly expressing your intent the fastest and easiest
|
||||
way to do your edit.
|
||||
|
||||
This is a desirable property because a lot of text editing operations are
|
||||
repetitive, but only on structurally similar text: the subject text are
|
||||
different, but they follow the same structure. Being able to express the
|
||||
text editing at the structural level allows for reusable commands, and makes
|
||||
the computer do the repetitive job.
|
||||
|
||||
Another often overlooked property of using a text editing language is that
|
||||
it's fun. Programmers are problem solvers, we enjoy solving problems, and
|
||||
we enjoy even more solving them with a clean and efficient solution. This
|
||||
kind of text editor transform a dull and repetitive edition task into an
|
||||
interesting puzzle to solve, and that is an engaging thing.
|
||||
|
||||
Think about it this way: Yes, programming is about thinking, concentrating
|
||||
on a design problem, or on a bug, understanding what needs to be done,
|
||||
designing a solution, and then writing it. More often that not, once you get
|
||||
to the writing phase, most of the thinking, problem solving, part is done,
|
||||
now the remaining task is just editing the code. Modal editors make this
|
||||
phase both faster, and more fun.
|
||||
|
||||
Why Kakoune
|
||||
-----------
|
||||
|
||||
Up to now, I have used vi as an example for modal text editor, mostly because
|
||||
I expect most programmers have at least heard of it. However, I dont believe
|
||||
vi and clones are the best modal text editor out there.
|
||||
|
||||
I have been working, for the last 5 years, on a new modal editor called
|
||||
Kakoune. It first started as a reimplementation of Vim (the most popular vi
|
||||
clone) whose source code is quite dated. But, I soon realized that we could
|
||||
improve a lot on vi editing model.
|
||||
|
||||
Improving on the editing model
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
vi basic grammar is *verb* followed by *object*; it's nice because it matches
|
||||
well with the order we use in English, "delete word". On the other hand,
|
||||
it does not match well with the nature of what we express: There is only
|
||||
a handfull of *verbs* in text editing (**d**elete, **y**ank, **p**aste,
|
||||
**i**nsert...), and they don't compose, contrarily to *objects* which can be
|
||||
arbitrarily complex, and difficult to express. That means that errors are
|
||||
not handled well. If you express your object wrongly with a delete verb,
|
||||
the wrong text will get deleted, you will need to undo, and try again.
|
||||
|
||||
Kakoune's grammar is *object* followed by *verb*, combined with instantaneous
|
||||
feedback, that means you always see the current object (In Kakoune we call
|
||||
that the selection) before you apply your change, which allows you to correct
|
||||
errors on the go.
|
||||
|
||||
Kakoune tries hard to fix one of the big problems with the vi model: its
|
||||
lack of interactivity. Because of the *verb* followed by *object* grammar,
|
||||
vi changes are made in the dark, we dont see their effect until the whole
|
||||
editing *sentence* is finished. `5dw` will delete to next five words, if
|
||||
you then realize that was one word too many, you need to undo, go back to
|
||||
your initial position, and try again with `4dw`. In Kakoune, you would do
|
||||
`5W`, see immediately that one more word than expected was selected, type
|
||||
`BH` to remove that word from the selection, then `d` to delete. At each
|
||||
step you get visual feedback, and have the opportunity to correct it.
|
||||
|
||||
At the lower level, the problem is that vi treats moving around and selecting
|
||||
an object as two different things. Kakoune unifies that, moving *is* selecting.
|
||||
`w` does not just go to the next word, it selects from current position to
|
||||
the next word. By convention, capital commands tend to expand the selection,
|
||||
so `W` would expand the current selection to the next word.
|
||||
|
||||
Multiple selections
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Another particular feature of Kakoune is its support for, and emphasis
|
||||
towards the use of multiple selections. Multiple selections in Kakoune
|
||||
are not just one additional feature, it is the central way of interacting
|
||||
with your text. For example there is no such thing as a "global replace" in
|
||||
Kakoune. What you would do is select the whole buffer with the `%` command,
|
||||
then select all matches for a regex in the current selections (that is the
|
||||
whole buffer here) with the `s` command, which prompts for a regex. You would
|
||||
end up with one selection for each match of your regex and use the insert
|
||||
mode to do your change. Globally replacing foo with bar would be done with
|
||||
`%sfoo<ret>cbar<esc>` which is just the combination of basic building blocks.
|
||||
|
||||
.Global replace
|
||||
video::video/global-replace.webm[align="center", options="autoplay,loop"]
|
||||
|
||||
Multiple selections provides us with a very powerfull to express structural
|
||||
selection: we can subselect matches inside the current selections, keep
|
||||
selections containing/not containing a match, split selections on a regex,
|
||||
swap selections contents...
|
||||
|
||||
For example, convert from `snake_case_style` to `camelCaseStyle` can be done
|
||||
by selecting the word (with `w` for example) then subselecting underscores
|
||||
in the word with `s_<ret>`, deleting these with `d`, then upper casing the
|
||||
selected characters with `~`. The inverse operation could be done by selecting
|
||||
the word, then subselecting the upper case characters with `s[A-Z]<ret>`
|
||||
lower casing them with ` and then inserting an underscode before them with
|
||||
`i_<esc>` This operation could be put in a macro, and would be reusable
|
||||
easily to convert any identifier.
|
||||
|
||||
.Camel case to snake case
|
||||
video::video/camel.webm[align="center", options="autoplay,loop"]
|
||||
|
||||
Another example would be parameter swapping, if you had `func(arg2, arg1);`
|
||||
you could select the contents of the parenthesis with `<a-i>(`, split the
|
||||
selection on comma with `S, <ret>`, and swap selection contents with `<a-)>`.
|
||||
|
||||
.Swapping arguments
|
||||
video::video/args-swap.webm[align="center", options="autoplay,loop"]
|
||||
|
||||
It is as well easy to use multiple selections for alignment, as the `&`
|
||||
command will align all selection cursors by inserting blanks before
|
||||
selection start
|
||||
|
||||
.Aligning variables
|
||||
video::video/align.webm[align="center", options="autoplay,loop"]
|
||||
|
||||
Or to use multiple selections as a way to gather some text from different
|
||||
places and regroup it in another place, thanks to a special form of pasting
|
||||
`<a-p>` that will paste every yanked selections instead of the first one.
|
||||
|
||||
.Regrouping manager objects together
|
||||
video::video/regroup.webm[align="center", options="autoplay,loop"]
|
||||
|
||||
Interactive, predictible and fast
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A design goal of Kakoune is to beat vim at its own game, while providing a
|
||||
cleaner editing model. The combination of multiple selections and cleaned up
|
||||
grammar shows thats its possible to have text edition that is interactive,
|
||||
predictible, and fast at the same time.
|
||||
|
||||
Interactivity comes by providing feedback on every commands, the inverted
|
||||
*object* then *verb* grammar makes that possible, every selection modification
|
||||
has direct visual feedback, regex based selections incrementally show what
|
||||
will get selected, including when the regular expression is invalid, and even
|
||||
yanking some text displays a message notifying how many selections were yanked.
|
||||
|
||||
Predictibilty comes from the simple effect of most commands. Each command is
|
||||
conceptually simple, doing one single thing. `d` deletes whatever is selected,
|
||||
nothing more. `%` selects the whole buffer, `s` prompts for a regex and
|
||||
selects matches in the previous selection. It is the combination of these
|
||||
building blocks that allows for complex, but predictible, actions on the text.
|
||||
|
||||
Being fast, as in less keystrokes, is provided by carefully designing the set
|
||||
of editing commands so that they interact well together, and by sometimes
|
||||
sacrificing beauty for useability. For example, `<a-s>` is equivalent to
|
||||
`S^<ret>`, they both split on new lines, but this is a so common use case that
|
||||
it deserves to have its own key. As shown in http://github.com/mawww/golf,
|
||||
Kakoune manages to beat Vim at the keystroke count game in most cases,
|
||||
using much more idiomatic commands.
|
||||
|
||||
|
||||
Discoverability
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Keyboard oriented programs tend to be at a disadvantage compared to GUI
|
||||
applications because they are less discoverable; there is no menu bar on
|
||||
which to click to see the available options, no tooltip appearing when you
|
||||
hover above a button explaining what it does.
|
||||
|
||||
Kakoune solves this problem through the use of two mechanisms: extensive
|
||||
completion support, and auto-information display.
|
||||
|
||||
When a command is written in a prompt, Kakoune will automatically open a menu
|
||||
providing you with the available completions for the current parameter. It
|
||||
will know if the parameter is supposed to be a word against a fixed set
|
||||
of word, the name of a buffer, a filename, etc... Actually, as soon as `:`
|
||||
is typed, entering command prompt mode, the list of existing commands will
|
||||
be displayed in the completion menu.
|
||||
|
||||
Additionally, Kakoune will display an information box, describing what the
|
||||
command does, what optional switches it can take, what they do...
|
||||
|
||||
.Command discoverability
|
||||
video::video/discoverability.webm[align="center", options="autoplay,loop"]
|
||||
|
||||
That information box gets displayed in other cases, for example if the `g`
|
||||
key is hit, which then waits for another key (`g` is the *goto* commands
|
||||
prefix), an information box will display all the recognized keys, informing
|
||||
the user that Kakoune is waiting on a keystroke, and listing the available
|
||||
options.
|
||||
|
||||
To go even further in discoverability, the auto information system can
|
||||
be set to display an information box after each normal mode keystroke,
|
||||
explaining what the key pressed just did.
|
||||
|
||||
Extensive completion support
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Keyboard oriented programs are much easier to work with when they provide
|
||||
extensive completion support. For a long time, completion has been prefix
|
||||
based, and that has been working very well.
|
||||
|
||||
More recently, we started to see more and more programs using the so called
|
||||
fuzzy completion. Fuzzy completion tends to be subsequence based, instead
|
||||
of prefix based, which means the typed query needs to be a subsequence of
|
||||
a candidate to be considered matching, instead of a prefix. That will generate
|
||||
more candidates (all prefix matches are also subsequence matches), so it
|
||||
needs a good ranking algorithm to sort the matches and put the best ones first.
|
||||
|
||||
Kakoune embraces fuzzy matching for its completion support, which kicks in both
|
||||
during insert mode, and prompt mode.
|
||||
|
||||
.Word completion support
|
||||
video::video/completion.webm[align="center", options="autoplay,loop"]
|
||||
|
||||
Insert mode completion provides completion suggestions while inserting in the
|
||||
buffer, it can complete words from the buffer, or from all buffers, lines,
|
||||
filenames, or get completion candidates from an external source, making it
|
||||
possible to implement intelligent code completion.
|
||||
|
||||
.Language specific completion support
|
||||
video::video/cpp-completion.webm[align="center", options="autoplay,loop"]
|
||||
|
||||
Prompt completion is displayed whenever we enter command mode, and provides
|
||||
completion candidates that are adapted to the command being entered, and to
|
||||
the current argument being edited.
|
||||
|
||||
A better unix citizen
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Easily making programs cooperate with each others is one of the main strength
|
||||
of the Unix environment. Kakoune is designed to integrate nicely with a POSIX
|
||||
system: various text editing commands give direct access to the power of POSIX
|
||||
tools, like `|`, which prompts for a shell command and pipe selections through
|
||||
it, replacing their contents with the command output, or `$` that prompts for
|
||||
a command, and keeps selections for which the command returned success.
|
||||
|
||||
.Using external commands as filters
|
||||
video::video/filters.webm[align="center", options="autoplay,loop"]
|
||||
|
||||
This is only the tip of the iceberg. Kakoune is very easily controllable from
|
||||
the shell, just pipe whatever commands you like to `kak -p <session>`, and the
|
||||
target Kakoune session will execute these.
|
||||
|
||||
Kakoune command line also supports shell expansion, similar to what `$(...)`
|
||||
does in a shell. If you type `echo %sh{ echo hello }` in the command prompt,
|
||||
"hello" will get displayed in the status line. Various values from Kakoune
|
||||
can be accessed in these expand through environment variables, which, along
|
||||
with shell scripting forms the basis of Kakoune extension model.
|
||||
|
||||
.Interaction with external shell
|
||||
video::video/external.webm[align="center", options="autoplay,loop"]
|
||||
|
||||
This model, although a bit less familiar than integrating a scripting language,
|
||||
is conceptually very simple, relatively simple implementation-wise, and is
|
||||
expressive enough to implement a custom code completer, linters, formatters...
|
||||
|
||||
Moreover, combined with support for `fifo` buffers, that read data from a
|
||||
named `fifo`, Kakoune ends up with an extension model that easily support
|
||||
asynchronous tasks, by forking a shell in the background to do long lived
|
||||
work (`grep` or `make` for example) while displaying the result as they
|
||||
come through the `fifo`.
|
||||
|
||||
Kakoune also tries to limit its scope to code editing: in particular, it does
|
||||
not try to manage windows, and lets the system's window manager, or terminal
|
||||
multiplexer (such as tmux), handle that responsiblity. This is achieved through
|
||||
a client/server design: An editing session runs on a server process, and
|
||||
multiple clients can connect to that session to display different buffers.
|
||||
|
||||
.Asynchronous make and multiple clients in tmux
|
||||
video::video/async.webm[align="center", options="autoplay,loop"]
|
||||
|
||||
Final Thoughts
|
||||
--------------
|
||||
|
||||
Kakoune provides an efficient code editing environment, both very predictible,
|
||||
hence scriptable, and very interactive. Its learning curve is considerably
|
||||
easier than Vim thanks to a more consistent design associated with strong
|
||||
discoverability, while still being faster (as in less keystrokes) in most
|
||||
use cases.
|
||||
|
||||
Although easier to learn than Vim, the learning curve is still quite steep,
|
||||
however we have established that investing time into optimizing the text
|
||||
editing workflow is worth it for programmers. Moreover, Kakoune simply makes
|
||||
code editing a fun and rewarding experience.
|
||||
|
||||
Kakoune is still evolving, getting better as we get more users, and gathering
|
||||
more use cases to cater for. It's already a very good code editor, and we need
|
||||
you to use it so that it can be made even better.
|
||||
|
||||
Kakoune is available at http://github.com/mawww/kakoune and has a website at
|
||||
http://kakoune.org
|
Loading…
Reference in New Issue
Block a user