trinket-blog/articles/Writing Your First Kakoune Config (kakrc).md

892 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

> **⚠️️ this guide is written as of Kakoune v2022.10.31, future versions may not be compatible with parts of this guide anymore ⚠️**
When I first started seriously learning to program, I used a mixture of text-editors and IDE's and really whatever I could get my hands on. I didn't quite know what I was doing.
## A rough timeline of me first using text editors
- I used [Atom](https://atom.io) *(rest in peace, you were loved by some)*.
- I saw someone using [Sublime Text](https://www.sublimetext.com/) and thought it looked very pretty.
- Sublime costs money. Never-mind I'm broke.
- What's this, [Brackets](https://brackets.io/) is *gorgeous* (this is something I maintain to this day. Brackets is the most beautiful text editor but no one knows it).
- Oh, Brackets is unmaintained and doesn't work with new frameworks very well :\[ `EDIT: It is now maintained again, go check it out`
- Maybe I want to be an iOS developer? omg it takes seven hours to install [Xcode](https://developer.apple.com/xcode/) (5 of those are just opening the app)
- Never-mind, [Swift](https://www.swift.org/) isn't fun anymore, and Xcode serves no other purpose to me.
- Woah, this guy in this one YouTube tutorial is using *the terminal* to edit. How is that even possible?
- Oh! It must be [Nano](https://www.nano-editor.org/). Team Nano!
- Wait.. this looks different and there's no syntax highlighting :\[
- Never-mind, not team Nano anymore.
- Ohhh it was [Vim](https://www.vim.org/). Let's open it up, can't be too hard to use right?
- *One vim-quitting-induced OS reinstall later*
- Ok, let's not do that.
- What's this hot new thing? [VSCode](https://code.visualstudio.com/)? I've used [Visual Studio](https://visualstudio.microsoft.com/) before, but idk what this is. Let's try it, why not.
And there I was, yet another VSCode dev.
To be clear, there's absolutely nothing wrong with this. The themes are great, the editor runs smoothly (for me), extensions do all the hard work, it's a mostly good experience.
But something in me yearned for more, I needed something new.
## To [Vim](https://www.vim.org/), [Neovim](https://neovim.io), etc.
A video by [ThePrimeagen](https://www.youtube.com/@ThePrimeagen) on YouTube was the final catalyst for me, watching him duck and weave through files, never touching the mouse and editing at the speed of thought was inspiring.
- I set out to learn Vim.
- I quickly switched to [Neovim](https://neovim.io/), but eventually gave up and returned to VSCode
I wasn't quite ready for the world of configuration and text file customization. My sudden introduction to it scared me away.
Eventually, I stumbled across [Helix](https://helix-editor.com/) configuring Helix is dead-simple. In fact, here's my Helix config right here:
```toml
theme = "everforest_dark"
[editor]
middle-click-paste = false
line-number = "relative"
auto-save = true
auto-format = false
bufferline = "always"
color-modes = true
shell = ["zsh", "-c"]
[editor.statusline]
mode.normal = "NORMAL"
mode.insert = "INSERT"
mode.select = "SELECT"
left = ["mode", "file-name", "version-control"]
center = ["spinner", "position-percentage", "file-encoding"]
right = ["diagnostics", "primary-selection-length", "position", "file-type"]
[editor.lsp]
auto-signature-help = false
display-signature-help-docs = false
# Remaps
[keys.normal]
A-F = ":fmt"
esc = ["collapse_selection", "keep_primary_selection", ":w"]
C-r = [":reload"]
"{" = "goto_prev_paragraph"
"}" = "goto_next_paragraph"
[keys.normal.space]
space = "goto_next_buffer"
m = "goto_previous_buffer"
q = ":buffer-close"
[keys.select]
"{" = "goto_prev_paragraph"
"}" = "goto_next_paragraph"
[keys.insert]
A-F = ":fmt"
esc = ["normal_mode", ":w"]
```
> Not very complicated, all things considered
I used Helix for a while, I really liked it a lot.
Eventually, I got good at the keybindings and was a whizz at getting through files just like I had dreamt of.
But the 'batteries included' nature of Helix eventually got to me. It did nearly everything I needed, but the lack of customization via plugins really killed it for me eventually.
Not to mention, the beta software state meant that Helix had a lot of little quirks and bugs that sometimes made using it a pain in the ass.
## To [Kakoune](https://kakoune.org/)
I knew [Kakoune](https://kakoune.org/) was the inspiring editor for Helix, and I really did love the keybindings for Helix, so I decided to give it a try.
Well, it was damn good!
Using Kakoune was a much smoother experience, Kakoune was obviously more mature, thought out, and performance-wise I could feel noticeable lag going back to Helix.
The only problem; configuration.
Eventually, I figured it out. I used a combination of other people's config files, trial and error, and reading some of the source code for Kakoune, but eventually I understood the configuration layout well enough to write a config file of my own that serves me well.
## Small disclaimer
This guide is for those who already know keybindings in Kakoune, and want a nice configuration file. I'm not going to be going over actually using the editor in detail.
## Writing a nice configuration file
Here's what Kakoune looks like by default
![default kakrc](https://i.imgur.com/DArA8Jy.png)
> pretty damn ugly if I do say so myself
Here's what my current config looks like
![default kakrc](https://i.imgur.com/h3wlERq.png)
> That's a marked improvement for me at least
## Step-by-step
### The basic-basics
When ran, `kak` will search for the autoload folder(s) and recursively load all `.kak` files in it. The `autoload` dir is usually `~/.config/kak/autoload/`. Then, `kak` will search for a `kakrc` file in your configuration folder (usually `~/.config/kak/kakrc`), and load it up.
Let's set that up
```bash
mkdir -p ~/.config/kak
kak ~/.config/kak/kakrc
```
> yes, we're using Kakoune to edit it's own config
### Tips
Kakoune has a lot of detailed documentation, it's just not very easy to read.
The `:doc` command gives instant access to every article, it's just not super easy to find what you're for. All the actual docs files can be found on GitHub [here](https://github.com/mawww/kakoune/tree/master/doc)
### Color scheme
Obviously, the most important thing about a text-editor is it's themes. Let's get something nice going for Kakoune.
In Kakoune, the `colorscheme` command set's the terminal. You can type `:colorscheme ` and `<tab>` around to find something you like.
`kakrc`
```vim
colorscheme gruvbox-dark
```
> that should make things nicer
You can reload your `kakrc` by running `:source kakrc`. When that doesn't work, just `:wq` and open it right back up, no biggie.
*How's the new color-scheme look?*
**Let's take a quick detour to talk about scopes**
### Scopes
> `global/`
First, `:doc scopes`
According to the docs, there's three options for scopes.
`global`, `buffer`, and `window`
##### Global
The `global` scope refers to every linked instance of `kak` currently running (you can spawn new 'linked' instances of Kakoune with the `:new` command). Changes you make to the `global` scope will be available everywhere. If you edit your `kakrc`, changes will only be available in new session from then on.
##### Buffer
A buffer is in most cases, just the raw file that is opened. Kakoune has a neat feature called `:new` that I won't get into, but it allows multiple instances of the same file to be edited at the same time which is wicked cool.
Objects in the `buffer` scope will affect every instance of that file open in `kak`
##### Window
The `window` scope is the logical subset of the `buffer` scope. Where the `window` scope affects all instances of `kak` with that buffer open, `window` refers to *this* instance of *this* buffer open.
Make sure you understand this to the best of your abilities, `scopes` are *very* handy in Kakoune
### Line numbers
Something very useful in any sort of text editor is line numbers, fortunately Kakoune offers line numbers as a builtin feature.
Kakoune offers most visual customization through the `add-highlighter`command, the docs are at `:doc highlighters`.
#### Syntax
`add-highlighter [-override] <path>/<name> <type> <parameters> ...`
In Kakoune, you can think of highlighters as literal unique objects in the editor, each highlighter is a unique instance with it's own unique scope.
Here's how to add line numbers to Kakoune
```vim
add-highlighter global/ number-lines
```
Let's go over that word-by-word
- `add-highlighter` - the root command to add 'highlighters' to the editor
- `global/` - the scope of this command
- `number-lines` - the builtin highlighter to apply to the Kakoune look
But wait, did you notice that `global` has a trailing `/`?
That's actually another very neat feature of Kakoune.
In `kak` each `highlighter` is it's own unique object with it's own ID. This means that the alternate command `remove-highlighter` exists, you'll see how useful this can be later in this article.
How to use `remove-highlighter` is an exercise left to the reader for now (`:doc` is your friend).
#### Great, but what about `/`?
In Kakoune, you can set the name of a `highlighter` , or just let `kak` pick one for you automagically.
Setting a custom name in Kakoune is what the `/` is for. For example, here's the equivalent command but with a custom name:
```vim
add-highlighter global/number-lines-highlighter number-lines
```
In this case, our highlighter will be named `number-lines-highlighter` and that allows us to refer to it in the future.
Unless you know you'll need to refer to a `highlighter`, I recommend letting Kakoune pick names for you since it will eliminate the risk of accidental name collision.
The trailing `/` is how you tell Kakoune to pick a name for you.
#### Getting gnarly
In Kakoune, some `highlighters` have optional arguments that can be passed to them.
The `:docs` will always explain this.
Here's the options for `number-lines`:
```text
-relative
show line numbers relative to the main cursor line
-hlcursor
highlight the cursor line with a separate face
-separator <separator text>
specify a string to separate the line numbers column from the rest of the buffer (default is '|')
-cursor-separator <separator text>
identical to -separator but applies only to the line of the cursor (default is the same value passed to -separator)
-min-digits <num>
always reserve room for at least num digits, so text doesnt jump around as lines are added or removed (default is 2)
```
Let's apply some of those;
```vim
add-highlighter global/ number-lines -hlcursor -relative -separator " " -cursor-separator " |"
```
Try adding each of those flags one at a time to see what happens. After that you can customize it to your liking.
#### Going deeper
To read a much more extensive and informative article on `highlighters`, see [here](https://zork.net/~st/jottings/Intro_to_Kakoune_highlighters.html)
### Matching braces
`kak` has another useful feature and that's to highlight matching brackets, braces, parentheses, quotes, etc.
The command is
```vim
add-highlighter global/ show-matching
```
Here's a before-and-after to illustrate what that does:
**Before**
![show-matching-before](https://i.imgur.com/oZotdaR.png)
**After**
![show-matching-before](https://i.imgur.com/5A6A4XY.png)
Notice how the other bracket was highlighted blue in the second photo.
This feature can be super useful in large codebases, or situations where there's nested blocks in your code.
### Pit Stop
Ok, here's our `kakrc` so far
```vim
# custom theme
colorscheme gruvbox-dark
## highlighting
# display line numbers
add-highlighter global/ number-lines -hlcursor -relative -separator " " -cursor-separator " |"
# show matching symbols
add-highlighter global/ show-matching
```
> pretty simple so far
### Set-option
`:doc options`
#### Syntax
`set-option [-add|-remove] <scope> <name> <values>...`
#### Tab-width
Most settings in `kak` can be accessed though the `set-options` command.
For example, I like my tabs to be 2 spaces wide, so I'm going to add that to my config like this:
```vim
#command #scope #name #value
set-option global tabstop 2
set-option global indentwidth 2
```
> Options don't get names in `kak`, that's why there's no `/` after the `global`scope.
#### Scroll-off
In Kakoune, you can specify a margin around the cursor. This is useful because it lets you see the text around a cursor even when editing text at the edges of the window.
```vim
# always keep eight lines and three columns displayed around the cursor
set-option global scrolloff 8,3
```
### Keybindings
`:doc mapping`
The `map` command is really quite simple. You tell it `key a`, and `keys b` and then whenever you type `key a`, Kakoune will just pretend you typed `keys b` instead. A bit like an alias.
#### Syntax
`map [switches] <scope> <mode> <key> <keys>`
Everything here should be straightforwards except possibly `<mode>`. I'm not going to get into `modes` here, since those are something you should already understand if you know `vim/kak` keybindings.
Here are the modes defined in `:doc mapping`
```text
insert
insert mode
normal
normal mode
prompt
prompts, such as when entering a command through :, or a regex through /
menu
mode entered when a menu is displayed with the 'menu' command
user
mode entered when the user prefix is hit (default: '<space>')
goto
mode entered when the goto key is hit (default: 'g')
view
mode entered when the view key is hit (default: 'v')
object
mode entered when an object selection is triggered (e.g. '<a-i>')
```
#### `normal` mode maps
##### `qwe`
Normally, to navigate word-by-word you'd use the `w`, `b`, and `e` keys to move around. However, I find it more convenient to remap the `b` to `q`. That way the keys are `qwe` and are next to each other on my keyboard.
Here's how to do that
```vim
# remap b to q
map global normal q b
# variations of b
map global normal Q B
map global normal <a-q> <a-b>
map global normal <a-Q> <a-B>
```
Kakoune doesn't have a `select` mode like Vim or Helix, so we only need to map from `normal` mode.
##### Clear selection on`<esc>`
In `kak`, pressing `<esc>` doesn't clear any highlighted text or collapse cursors which doesn't feel intuitive to me. Let's fix that;
```vim
# unselect on <esc>
map global normal <esc> ";,"
```
`;` un-highlights text, and `,` gets rid of multiple cursors.
##### Auto-comment lines
I like to map `<c-v>` (control+v) to the `:comment-line` command in Kakoune. This lets me toggle lines really quickly when debugging or refactoring code.
```vim
# comment lines
map global normal <c-v> ":comment-line<ret>"
```
> `<ret>` tells Kakoune to execute the commadn
Normally, I'd map `<c-c>` to this, but in Kakoune certain key-mappings don't work because of compatibility features (i think), and control+c is one of them. More info [here](https://github.com/mawww/kakoune/issues/797#issuecomment-649494417).
#### `user` mode maps
`user` mode is really neat, it allows you to setup a little menu of commands that you access by typing `<space>` and then the mapping.
##### Buffer control
Some utilities for navigating buffers
```vim
map -docstring "close current buffer" global user b ": db<ret>"
map -docstring "goto previous buffer" global user n ": bp<ret>"
map -docstring "goto next buffer" global user m ": bn<ret>"
```
> `-docstring` is just the help-text shown for the mapping in the menu
Now, by typing `<space>m`, `<space>n`, and `<space>b` I can go one buffer forwards, back, and close the current buffer respectively.
The more astute among you may have noticed that the commands in that mapping have a space separating the `:` colon and the actual command. In older versions Kakoune we did this when we didn't want the command saved in the history (access the history by typing `:` and pressing the up/down arrows). Current and future versions of Kakoune do this automatically, so we don't need to worry about the `<space>`.
##### Some more misc. mappings
```vim
# fancy insert newline
map -docstring "insert newline above" global user [ "O<esc>j"
map -docstring "insert newline below" global user ] "o<esc>k"
# spellcheck (requires aspell)
map -docstring "check document for spelling" global user w ": spell<ret>"
map -docstring "clear document spelling" global user q ": spell-clear<ret>"
```
##### And one more
```vim
# copy to system pboard [MAC ONLY]
map -docstring "copy to system pboard" global user y "<a-|> pbcopy<ret>"
```
- `<a-|>` - the *pipe-to* command
- `pbcopy` - a shell tool available on macs to manipulate the clipboard
#### Insert mode autosave
I like it when text-editors autosave. Neovim has this awesome autosave plugin that prints a little log message each time it saves and I want to implement something similar to that as a `map`.
First, the most basic
```vim
map -docstring "save current buffer" global user s ": w<ret>"
```
But there's no log :(
Also, later we're going to make this something that happens automatically when the user presses `<esc>` in `insert` mode.
So let's take a really quick detour to the `define-command` command, essentially functions in `kak`.
### Custom commands
`:doc commands declaring-new-commands`
```text
New commands can be defined using the define-command command:
define-command [<switches>] <command_name> <commands>
commands is a string containing the commands to execute, and switches can be any combination of the following parameters:
-params <num>
the command accepts a num parameter, which can be either a number, or of the form <min>..<max>, with both <min> and <max> omittable
-override
allow the new command to replace an existing one with the same name
-hidden
do not show the command in command name completions
-docstring
define the documentation string for the command
-menu
-file-completion
-client-completion
-buffer-completion
-command-completion
-shell-completion
-shell-script-completion
-shell-script-candidates
old-style command completion specification, function as-if the switch and its eventual parameter was passed to the complete-command command (See Configuring command completion)
The use of those switches is discouraged in favor of the complete-command command.
Using shell expansion allows defining complex commands or accessing Kakoune's state:
# create a directory for current buffer if it does not exist
define-command mkdir %{ nop %sh{ mkdir -p $(dirname $kak_buffile) } }
```
Overall, it's a lot like `map`. Define a command name, and then some other commands that will be ran.
#### Save-buffer
Here's my `save-buffer` command:
```vim
define-command save-buffer -docstring "save current buffer and show info" %{
write
info "file saved at %sh{date}"
}
```
- `write` - save the current buffer (the same thing as `:w`)
- `info - `info` logs a little snipped to the user, try `:info "hello, world!"` to see for yourself.
- `'file saved at %sh{date}'` - `kak` will first expand `%sh{date}` into the output of the `date` shell command, and then interpolate that with `file saved at ` before passing it to the `info` command.
The reason we don't need the `:` in the `%{}` block is that Kakoune treats the commands there as just that - commands.
The `map` command simulates those actual keypresses, so we need to tell the editor to go to `prompt` mode.
#### A more complicated example
```vim
# open tutor (needs curl)
define-command trampoline -docstring "open a tutorial" %{
evaluate-commands %sh{
tramp_file=$(mktemp -t "kakoune-trampoline.XXXXXXXX")
echo "edit -fifo $tramp_file *TRAMPOLINE*"
curl -s https://raw.githubusercontent.com/mawww/kakoune/master/contrib/TRAMPOLINE -o "$tramp_file"
}
}
```
> found on the [Kakoune forums](https://discuss.kakoune.com/)
Figuring out how this works is an exercise left to the reader.
### Plugins
The main reason I switched from Helix to Kakoune was plugins. Helix does not yet have support for plugins, where Kakoune has an incredible ecosystem. Albeit a much smaller one than Vim/Neovim, but personally, I think `kak` extensions are much easier to write,
In Kakoune, any `.kak` files in the `~/.config/kak/autoload` directory will be loaded, so one way to install extensions is to just clone git repos there.
**However**
Kakoune has an extremely well made package manager that I highly recommend.
It's called [plug.kak](https://github.com/andreyorst/plug.kak).
According to the site there's a few ways to install it, but here's how I like to do it:
```bash
mkdir -p $HOME/.config/kak/plugins
git clone https://github.com/andreyorst/plug.kak.git $HOME/.config/kak/plugins/plug.kak
```
Before we start using it, you should go read the `README` on the tool's [GitHub](https://github.com/andreyorst/plug.kak).
#### Initializing `plug.kak`
`plug.kak` has to be loaded by `plug.kak`! Kinda trippy I know.
Here's the line to do that:
```vim
source "%val{config}/plugins/plug.kak/rc/plug.kak"
plug "andreyorst/plug.kak" noload
```
This should go before your other plugins in your `kakrc`.
- `source` just tells `kak` where to find `plug.kak`
- `plug` is a special command that `plug.kak` provides that tells it to make that plugin available to Kakoune, among other things.
#### Loading plugins
Whenever you add a plugin, you need to reload your `kakrc`, then you can run the `:plug-install` command. Read the `plug.kak` [README](https://github.com/andreyorst/plug.kak) for a better explanation of all this.
#### Our first plugin - more themes
I like Gruvbox, I do, but I don't quite like running it 24/7, the colors hurt my eyes. Luckily, the amazing `anhsirk0` made a huge collection of amazing themes for Kakoune. Here's the repo for that [GitHub](https://github.com/anhsirk0/kakoune-themes).
Unfortunately, the structure of that repo makes it not work super well with `plug.kak`. Luckily, I made a fork of it that preserves all the themes and makes it work with `plug`. [Link here](https://github.com/secondary-smiles/kakoune-themes).
Now, let's get it 'installed'.
```vim
# themes
plug "secondary-smiles/kakoune-themes" theme config %{
colorscheme pastel
}
```
> Woah, there's a lot going on there.
- `plug "secondary-smiles/kakoune-themes"` - `plug.kak` will automagically search github for a plugin if you just provide a *username/repo* string.
- `theme` - this tells `plug.kak` that this extension is actually a pack of themes, or just one theme. It will treat the files differently because of that.
- `config` - this is some `Kakscript` that will be ran only once `plug.kak` has loaded this extension.
- `%{ colorscheme pastel }` - this will be run once `plug.kak` loads the extension, it works in a pair with the `config` keyword. (blocks in Kakoune are defined with `%[optional directive]{}`).
Well, try and reload your config now, see what you think!
Oh, we should probably remove that `colorscheme gruvbox-dark` from earlier too, we don't need two themes racing each-other to be dominant in the editor.
#### Auto-pairs
I might be the weird one out, but I really like auto-pairs when typing. That's where typing a matched character like `(`, `[`, `<`, etc. the editor automatically inserts the opposite character (`)`, `]`, `>`, etc.).
Luckily, a plugin exists for just that!
```vim
# autopairs
plug "alexherbo2/auto-pairs.kak" config %{
enable-auto-pairs
}
```
`enable-auto-pairs` is a command provided by `auto-pairs.kak`. You can, of course, disable it with `:disable-auto-pairs`.
#### Fuzzy-finder
Having a builtin file picker is really useful in any editor. [`fzf.kak`](https://github.com/andreyorst/fzf.kak) is a really superb implementation of this with a lot of customization abilities.
```vim
# fzf
plug "andreyorst/fzf.kak" config %{
require-module fzf
require-module fzf-grep
require-module fzf-file
} defer fzf %{
set-option global fzf_highlight_command "lat -r {}"
} defer fzf-file %{
set-option global fzf_file_command "fd . --no-ignore-vcs"
} defer fzf-grep %{
set-option global fzf_grep_command "fd"
}
```
If you read the `plug.kak` `README`, you'd already understand this.
Let's go over it anyways though.
`fzf.kak` provides several modules to further customize the plugin.
In the first `config` block, we `require` those modules so that they get loaded.
Then, we use the `defer <module-name>` block to run more commands only *after* that module is loaded by `plug.kak`. In this case, I'm using [`lat`](https://github.com/secondary-smiles/lat) (*shameless plug*) as my default file viewer, and [`fd`](https://github.com/sharkdp/fd) as my grepper.
I also like to set `<space>f` to enter fuzzy-finder mode:
```vim
map -docstring "open fzf" global user f ": fzf-mode<ret>"
```
#### Powerline
The default Kakoune status-bar leaves a lot to be desired. This plugin adds a lot more customizability.
Read the [README](https://github.com/andreyorst/powerline.kak) for more info on customization
```vim
plug "andreyorst/powerline.kak" defer kakoune-themes %{
powerline-theme pastel
} defer powerline %{
powerline-format global "git lsp bufname filetype mode_info lsp line_column position"
set-option global powerline_separator_thin ""
set-option global powerline_separator ""
} config %{
powerline-start
}
```
#### Enhanced selection
In Helix, pressing `x` will select the entire line. Subsequent `x`'s will keep expanding the selection line-by-line. In Kakoune, Subsequent `x`'s do nothing.
[byline.kak](https://github.com/evanrelf/byline.kak) does exactly that.
In fact, pressing `<shift>x` will shrink the selection by a line! Very useful.
```vim
plug "evanrelf/byline.kak" config %{
require-module "byline"
}
```
#### Luar
Some Kakoune plugins are written in Lua, this plugin will allow those ones to run. Adding this plugin is a nice future-proof against plugins randomly break because you forgot this one.
```vim
plug "gustavo-hms/luar" %{
require-module luar
}
```
#### LSP I
Kakoune has autocomplete out-of-the-box, but now that LSP's are standard, it makes a lot of sense to use them.
There's an extension for that!
```vim
plug "kak-lsp/kak-lsp" do %{
cargo install --locked --force --path .
# optional: if you want to use specific language servers
# mkdir -p ~/.config/kak-lsp
# cp -n kak-lsp.toml ~/.config/kak-lsp/
}
```
- The `do` directive tells `plug.kak` to run those shell commands only when first installing the plugin.
However, `kak-lsp` requires a bit more configuration to work properly.
First, read the `kak-lsp` [README](https://github.com/kak-lsp/kak-lsp) (always read the README for everything).
Before finishing `lsp`, let's learn about `hooks`;
### Hooks
`:doc hooks`
Hooks in `kak` are like Events in Javascript, or `autocmd` in Vim/Neovim.
Basically, you give Kakoune some commands to run, and a trigger. When `kak` detects that trigger happening, it'll run your commands.
#### Autosave
Let's finally finish that autosave feature we were working on.
Here's a simple hook to do that:
```vim
hook global ModeChange pop:insert:.* %{
save-buffer
}
```
- `ModeChange` - the hook for whenever the user goes from `user` to `insert` or any combination of other modes
- `ModeChange` accepts a string formatted as `[push|pop]:<old mode>:<new mode>`
- `pop:insert:.*` - this is the filter for the `ModeChange` hook, let's go over that
- `pop` - this is the *kind* of mode-change. The options here are `pop`, `push`, and `.*`.
- `pop` - refers to moving out of a mode and into the next one.
- `push` - *push*ing a command into a mode, for example, pressing `<alt>;` escapes `normal` mode for a single command.
- `.*` - wildcard for all
- `insert` - the **from** mode, or the mode that we're leaving.
- `.*` - the **to** mode, or the mode that we're going to. This is set to *any*, as we want to save anytime we exit `insert` mode
- `save-buffer` - our custom command to save the buffer and log the time.
#### Soft-wrap in markdown files
Another hook I have enabled is soft-wrapping text in `.md` files. I find that it makes it a lot easier to edit text (not code) when I can see everything at once and don't have to horizontally-scroll.
```vim
hook global WinSetOption filetype=markdown %{
add-highlighter -override global/markdown-wrap wrap -word
hook -once -always window WinSetOption filetype=.* %{
remove-highlighter global/markdown-wrap
}
}
```
> Yeah, you can nest `hooks` 😎
Figuring out what the nested `hook` does is an exercise left to the reader.
#### Lsp II
If you read the `kak-lsp` [README](https://github.com/kak-lsp/kak-lsp), then this part is going to make a lot of sense.
While it's possible to just blindly enable `kak-lsp` for everything, I prefer so set hooks for the specific filetypes that I want to be editing.
```vim
hook global WinSetOption filetype=(rust|javascript|typescript|c) %{
lsp-enable-window
lsp-inlay-diagnostics-enable global
}
## enable syntax highlighting for each lang
# c
hook global WinSetOption filetype=c %{
hook window -group semantic-tokens BufReload .* lsp-semantic-tokens
hook window -group semantic-tokens NormalIdle .* lsp-semantic-tokens
hook window -group semantic-tokens InsertIdle .* lsp-semantic-tokens
hook -once -always window WinSetOption filetype=.* %{
remove-hooks window semantic-tokens
}
}
# rust
hook global WinSetOption filetype=rust %{
hook window -group semantic-tokens BufReload .* lsp-semantic-tokens
hook window -group semantic-tokens NormalIdle .* lsp-semantic-tokens
hook window -group semantic-tokens InsertIdle .* lsp-semantic-tokens
hook -once -always window WinSetOption filetype=.* %{
remove-hooks window semantic-tokens
}
}
# typescript
hook global WinSetOption filetype=typescript %{
hook window -group semantic-tokens BufReload .* lsp-semantic-tokens
hook window -group semantic-tokens NormalIdle .* lsp-semantic-tokens
hook window -group semantic-tokens InsertIdle .* lsp-semantic-tokens
hook -once -always window WinSetOption filetype=.* %{
remove-hooks window semantic-tokens
}
}
# javascript
hook global WinSetOption filetype=javascript %{
hook window -group semantic-tokens BufReload .* lsp-semantic-tokens
hook window -group semantic-tokens NormalIdle .* lsp-semantic-tokens
hook window -group semantic-tokens InsertIdle .* lsp-semantic-tokens
hook -once -always window WinSetOption filetype=.* %{
remove-hooks window semantic-tokens
}
}
```
> If you read the comments, you'll also notice that we enabled better syntax highlighting for each of those filetypes as well.
I also like to set a mapping to `user` mode to let me access the `lsp` menu really quickly:
```vim
map -docstring "open lsp" global user l ": enter-user-mode lsp<ret>"
```
- Some extensions create their own special menus like the one that `<space>` creates. We access those with the `:enter-user-mode` command.
- Now, `<space>lf` will perform lsp-assisted formatting!
#### Tab completion
I don't like the `<c-n>`, `<c-p>` convention for selecting autocomplete items.
This is the recommended hook (according to the Kakoune wiki) for enabling `<tab>` and `<shift><tab>` selections.
```vim
# tabs for autocomplete
hook global InsertCompletionShow .* %{
try %{
# this command temporarily removes cursors preceded by whitespace;
# if there are no cursors left, it raises an error, does not
# continue to execute the mapping commands, and the error is eaten
# by the `try` command so no warning appears.
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 .* %{
unmap window insert <tab> <c-n>
unmap window insert <s-tab> <c-p>
}
}
}
```
#### LSP III
To learn more about creating custom completion tools in Kakoune see [here](https://zork.net/~st/jottings/Intro_to_Kakoune_completions.html).
### Goodbye clippy
You probably noticed that clippy appears a lot in Kakoune
```text
╭──╮
│ │
@ @ ╭
││ ││ │
││ ││ ╯
│╰─╯│
╰───╯
```
> this mf
Well, a not-so-secret easter egg in Kakoune is that it's possible to change the assistant!
Here's how to remove clippy altogether
```vim
set-option global ui_options terminal_assistant=none
```
> Available options are `clippy`, `dilbert`, `cat`, and `none`. Try setting each of those, something interesting might happen ;D
## Wrapping up
My current, mostly up-to-date `kakrc` can be found on my github [.dots](https://github.com/secondary-smiles/.dots/blob/main/pkg/kakoune/kakrc).
Kakoune is an incredible editor, I've really never had this much fun in a text editor, and for me it just feels so good using a [punk-rock editor](https://zork.net/~st/jottings/kakoune-a-punk-rock-text-editor.html).
This article isn't an introduction to terminal-editors, but if you're interested in the field, YouTube is a great starting place.
Also check out the [Kakoune Forums](https://discuss.kakoune.com/) for infinite `kak` tips and tricks.
Thanks for reading!