Skip to content

Instantly share code, notes, and snippets.

@lewalkingdad
Last active November 3, 2025 23:42
Show Gist options
  • Select an option

  • Save lewalkingdad/6fe0ef63418f1f87aa1d963c3778c707 to your computer and use it in GitHub Desktop.

Select an option

Save lewalkingdad/6fe0ef63418f1f87aa1d963c3778c707 to your computer and use it in GitHub Desktop.
Kakoune Tree Sitter Nix
{
config,
pkgs,
lib,
...
}:
let
groups = [
"variable"
"variable.builtin"
"variable.parameter"
"variable.parameter.builtin"
"variable.member"
"variable.other.member"
"variable.other.member.private"
"constant"
"constant.builtin"
"constant.builtin.boolean"
"constant.character"
"constant.character.escape"
"constant.macro"
"constant.numeric"
"constant.integer"
"constant.float"
"module"
"module.builtin"
"label"
"string"
"string.documentation"
"string.regexp"
"string.escape"
"string.special"
"string.special.symbol"
"string.special.url"
"string.special.path"
"character"
"character.special"
"boolean"
"number"
"number.float"
"type"
"type.builtin"
"type.definition"
"type.parameter"
"type.enum"
"type.enum.variant"
"attribute"
"attribute.builtin"
"property"
"function"
"function.builtin"
"function.call"
"function.macro"
"function.method"
"function.method.call"
"function.method.private"
"function.special"
"constructor"
"operator"
"keyword"
"keyword.coroutine"
"keyword.function"
"keyword.operator"
"keyword.import"
"keyword.type"
"keyword.modifier"
"keyword.repeat"
"keyword.return"
"keyword.debug"
"keyword.exception"
"keyword.conditional"
"keyword.conditional.ternary"
"keyword.directive"
"keyword.directive.define"
"keyword.storage"
"keyword.storage.type"
"keyword.storage.modifier"
"keyword.control.conditional"
"keyword.control.repeat"
"keyword.control.import"
"keyword.control.return"
"keyword.control.exception"
"punctuation.delimiter"
"punctuation.bracket"
"punctuation.special"
"comment"
"comment.line"
"comment.line.documentation"
"comment.block"
"comment.block.documentation"
"comment.unused"
"comment.documentation"
"comment.error"
"comment.warning"
"comment.todo"
"comment.note"
"markup"
"markup.strong"
"markup.bold"
"markup.italic"
"markup.strikethrough"
"markup.underline"
"markup.heading"
"markup.heading.marker"
"markup.heading.1"
"markup.heading.2"
"markup.heading.3"
"markup.heading.4"
"markup.heading.5"
"markup.heading.6"
"markup.quote"
"markup.math"
"markup.link"
"markup.link.label"
"markup.link.url"
"markup.link.text"
"markup.raw"
"markup.raw.block"
"markup.raw.inline"
"markup.list"
"markup.list.checked"
"markup.list.unchecked"
"markup.list.unnumbered"
"markup.list.numbered"
"diff"
"diff.plus"
"diff.plus.gutter"
"diff.minus"
"diff.minus.gutter"
"diff.delta"
"diff.delta.moved"
"diff.delta.conflict"
"diff.delta.gutter"
"tag"
"tag.builtin"
"tag.attribute"
"tag.delimiter"
"none"
"special"
"conceal"
"spell"
"nospell"
"embedded"
];
kts-master = pkgs.rustPlatform.buildRustPackage {
pname = "kak-tree-sitter-master";
version = "main-2025-10-26";
src = pkgs.fetchFromSourcehut {
owner = "~hadronized";
repo = "kak-tree-sitter";
rev = "cdcfb42da9affd9dd0db9e8df1173731c61e3d9f";
hash = "sha256-Q8R++fEJMZFftiI9zGjwF7X8mek2oc40Yl9WMUtQWEA=";
};
cargoHash = "sha256-lZNM5HqICP6JfaMiBjACcUNRTTTIRhq2ou8cOLU0yOU=";
};
only_file = (attrName: attrValue: attrValue == "regular");
get_include = (file_content: builtins.match "^.*inherits: (([a-z_-]+,?)+)+.*$" file_content);
has_include = file: null != get_include file.content;
map_queries =
lang_name:
let
lang_basepath = "${pkgs.helix}/lib/runtime/queries/";
query_files = lib.filterAttrs only_file (builtins.readDir "${lang_basepath}/${lang_name}");
in
pkgs.lib.mapAttrsToList (file: type: {
name = file;
content = builtins.readFile "${lang_basepath}/${lang_name}/${file}";
}) query_files;
needs_processing = (
lang_name:
let
lang_basepath = "${pkgs.helix}/lib/runtime/queries/";
in
if builtins.pathExists "${lang_basepath}/${lang_name}" then
builtins.any has_include (map_queries lang_name)
else
false
);
languagesConfig = builtins.fromTOML (builtins.readFile ./helix-languages.toml);
languages_to_process = builtins.filter (lang: needs_processing lang.name) languagesConfig.language;
processed_queries = builtins.map (
language:
let
queries_files = map_queries language.name;
in
rec {
lang = language;
destination = "${config.home.homeDirectory}/.config/kak-tree-sitter/runtime/queries/${lang.name}";
files = builtins.map (
file:
let
include_refs = pkgs.lib.splitString "," (builtins.head (get_include file.content));
includes = builtins.filter (include: null != include) (
builtins.map (
other_lang:
let
ref_path = "${pkgs.helix}/lib/runtime/queries/${other_lang}/${file.name}";
in
if builtins.pathExists ref_path then builtins.readFile ref_path else null
) include_refs
);
in
{
name = file.name;
content =
if has_include file then
builtins.concatStringsSep "\n" includes
else
builtins.readFile "${pkgs.helix}/lib/runtime/queries/${lang.name}/${file.name}";
}
) queries_files;
}
) languages_to_process;
standard_queries = builtins.map (lang: {
lang = lang;
destination = "${pkgs.helix}/lib/runtime/queries/${lang.name}";
}) (builtins.filter (lang: false == needs_processing lang.name) languagesConfig.language);
kakoune_queries = builtins.foldl' (
acc: query:
{
"${query.lang.name}".queries.source.local.path = query.destination;
}
// acc
) { } (standard_queries ++ processed_queries);
grammars = builtins.foldl' (
acc: lang:
{
"${lang.name}".source.local.path =
"${pkgs.helix}/lib/runtime/grammars/${lang.grammar or lang.name}.so";
}
// acc
) { } languagesConfig.language;
kts-config = {
highlight = { inherit groups; };
features = {
highlighting = true;
text_objects = true;
};
language = kakoune_queries;
grammar = grammars;
};
kts-config-toml = (pkgs.formats.toml { }).generate "kak-tree-sitter-config.toml" kts-config;
in
{
homeManagerModules.kakoune = {
home.packages = with pkgs; [
kakoune-lsp
kts-master
google-java-format
fzf
helix
fd
moreutils
nixfmt
usql
perl
bc
timewarrior
taskwarrior3
];
programs.kakoune = {
enable = true;
extraConfig = builtins.readFile ./kakrc;
plugins = with pkgs.kakounePlugins; [
rep
(pkgs.kakouneUtils.buildKakounePluginFrom2Nix {
pname = "kak-dap";
version = "2022-08-11";
src = pkgs.fetchgit {
url = "https://codeberg.org/jdugan6240/kak-dap";
rev = "355df2c627ceb124f4ff018c95762cf9c19068ae";
hash = "sha256-73DdcOduxMJ/KhEOQuJD3JgY52TYCQfdjiWeIwLxodE=";
};
})
];
};
xdg.configFile."kak/colors/catppuccin-mocha.kak".source = ./catppuccin-mocha.kak;
xdg.configFile."kak/plugins/password-store.kak".source = ./password-store.kak;
home.file =
(builtins.listToAttrs (
builtins.concatMap (
query:
builtins.map (file: {
name = ".config/kak-tree-sitter/runtime/queries/${query.lang.name}/${file.name}";
value = {
text = file.content;
};
}) query.files
) processed_queries
))
// {
".config/kak-tree-sitter/config.toml" = {
source = kts-config-toml;
};
};
};
}
@lewalkingdad
Copy link
Author

lewalkingdad commented Oct 30, 2025

From Discord chats: to get the best out of tree-sitter and kakoune we are better off using the main branch of kak-tree-sitter:

kts-master = pkgs.rustPlatform.buildRustPackage {
        pname = "kak-tree-sitter-master";
	version = "main-2025-10-26";
	src = pkgs.fetchFromSourcehut {
    	 owner = "~hadronized";
    	 repo = "kak-tree-sitter";
    	 rev = "cdcfb42da9affd9dd0db9e8df1173731c61e3d9f";
    	 hash = "sha256-Q8R++fEJMZFftiI9zGjwF7X8mek2oc40Yl9WMUtQWEA=";
	};

	cargoHash = "sha256-lZNM5HqICP6JfaMiBjACcUNRTTTIRhq2ou8cOLU0yOU=";
      };

I will need to also simplify the config.toml, known working config as a reference: https://gist.github.com/saifulapm/06749fc2f3c13c269b13a0600c11350a

Also I will have to change / edit queries, kts does not support includes, I won't be able to reuse as is the helix queries, I will have to parse them check for any includes, and if there is any I will have to concat the referenced file in the grammer calling the include instruction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment