Structural selections for Kakoune
Branch: master
Clone or download
Type Name Latest commit message Commit time
Failed to load latest commit information.
rc unify the closest node and node of kind selection commands; better docs Jan 2, 2019
.gitignore PoC Dec 26, 2018
.gitmodules feature gate languages Dec 28, 2018
Cargo.lock avoid premature optimization Dec 31, 2018
Cargo.toml avoid premature optimization Dec 31, 2018
README.asciidoc fix installation instruction; close #6 Jan 12, 2019
UNLICENSE PoC Dec 26, 2018
rustfmt.toml PoC Dec 26, 2018


Structural selections for Kakoune

kak-tree is a plugin for Kakoune which enables selection of syntax tree nodes. Parsing is performed with tree-sitter.

Status: proof of concept, interface and overall development direction could change drastically based on feedback.


Replace "rust javascript" with a list of languages you need. Or use all to build all supported languages. Note that all build takes a long time, and resulting binary is quite fat which could have a negative impact on responsiveness.

git clone --recurse-submodules
cargo install --path . --force --features "rust javascript"
cp rc/tree.kak ~/.config/kak/autoload/

Look at Cargo.toml for a full list of supported languages.

It is possible to check programmaticaly if kak-tree was built with support for a given filetype:

kak-tree --do-you-understand rust

If language is supported then exit code is 0 otherwise it’s non-zero (1 at the moment, but it is not guaranteed in future).


Tree-sitter parsers produce very detailed syntax tree, many elements of which are not interesting for day-to-day selection purposes. kak-tree introduces the concept of a visible node. Node is visible when:

  1. Node is named in the tree-sitter grammar for the given language (as opposed to anonymous nodes, more).

  2. Either there is no white/blacklist for the given filetype or node kind is whitelisted or not blacklisted. See Configuration for details about white/blacklisting.

Most of the kak-tree commands operate on visible nodes and skip not visible ones.

tree-select-parent-node [<KIND>]

Select the closest visible ancestor or ancestor of KIND when provided.

tree-select-next-node [<KIND>]

Select the closest visible next sibling or next sibling of KIND when provided.

tree-select-previous-node [<KIND>]

Select the closest visible previous sibling or previous sibling of KIND when provided.

tree-select-children [<KIND>]

Select all immediate visible children or all descendants matching KIND when provided.

tree-select-first-child [<KIND>]

Select the first immediate visible children or the first descendant matching KIND when provided.


Show info box with a syntax tree of the main selection parent.


kak-tree supports configuration via a configuration file. As for now there is no default path to load the configuration file, and it must be given using CLI option --config or -c for short:

set global tree_cmd 'kak-tree -c /path/to/kak-tree.toml'

Filetype configuration

Configuration for specific filetypes should be provided like this:

blacklist = ["identifier", "scoped_identifier", "string_literal"]
whitelist = ["function_item"]
group.identifier = ["identifier", "scoped_identifier"]
group.fn = ["function_item"]

group.fn = ["function", "arrow_function"]

Configuration under the [filetype.default] key will be used for all filetypes without configuration. Specific filetype configuration doesn’t extend default configuration but rather overwrites it.


If whitelist array is provided then kak-tree selection will skip nodes which kinds are not whitelisted. If blacklist array is provided then kak-tree selection will skip nodes which kinds are blacklisted.

whitelist takes precedence over blacklist. In the Rust example above kak-tree would expand selection up to the function definition, ignoring other node kinds.
tree-node-sexp command is useful for exploring node kinds which appear in the specific code.

Whitelisting or blacklisting node kinds could be tedious as tree-sitter parsers define many of them, but it also could be rewarding as you will be able to quickly modify selection in scopes which matter for you with fewer keystrokes.

Kind groups

Groups of node kinds serve a two-fold purpose:

  1. Groups allow matching functionally similar node kinds (i.e. identifier and scoped_identifier in Rust) by a single query.

  2. Groups allow matching functionally similar nodes across filetypes (i.e. function_item in Rust and function in JavaScript) as tree-sitter parsers don’t use uniform node kind names.

whitelist and blacklist options doesn’t expand groups yet.


For kak-tree see UNLICENSE file. For tree-sitter and its parsers look at their repositories.