From e6d6ec2a85167842e71b8182266624a03f620ce7 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Mon, 7 Oct 2024 16:31:33 +0200 Subject: [PATCH] Add tree-sitter --- packages/common/kak-tree-sitter.nix | 2 + packages/common/nki-kakoune/default.nix | 7 +- packages/common/nki-kakoune/kakrc | 3 - packages/common/nki-kakoune/rc.nix | 11 +- .../nki-kakoune/tree-sitter/default.nix | 171 ++++++++++++++++++ .../nki-kakoune/tree-sitter/grammars.nix | 119 ++++++++++++ packages/common/nki-kakoune/utils.nix | 10 +- 7 files changed, 314 insertions(+), 9 deletions(-) create mode 100644 packages/common/nki-kakoune/tree-sitter/default.nix create mode 100644 packages/common/nki-kakoune/tree-sitter/grammars.nix diff --git a/packages/common/kak-tree-sitter.nix b/packages/common/kak-tree-sitter.nix index 3e0c6a9..9819e3a 100644 --- a/packages/common/kak-tree-sitter.nix +++ b/packages/common/kak-tree-sitter.nix @@ -35,6 +35,8 @@ let self.runtime_dir.join("sources").join(url_dir) '') ]; + + meta.mainProgram = "kak-tree-sitter"; }; in kak-tree-sitter diff --git a/packages/common/nki-kakoune/default.nix b/packages/common/nki-kakoune/default.nix index bb65355..0d48b06 100644 --- a/packages/common/nki-kakoune/default.nix +++ b/packages/common/nki-kakoune/default.nix @@ -1,13 +1,18 @@ { callPackage, kakoune, kakoune-unwrapped, ... }: let lsp = callPackage ./lsp.nix { }; + tree-sitter = callPackage ./tree-sitter { }; + rc = (callPackage ./rc.nix { + prependRc = tree-sitter.rc; + }); in (kakoune.override { plugins = callPackage ./plugins.nix { } ++ callPackage ./themes.nix { } ++ [ (callPackage ./kaktex { }) - (callPackage ./rc.nix { }) + rc + tree-sitter.plugin lsp.plugin ]; }).overrideAttrs (attrs: { diff --git a/packages/common/nki-kakoune/kakrc b/packages/common/nki-kakoune/kakrc index aafa044..dc06ca3 100644 --- a/packages/common/nki-kakoune/kakrc +++ b/packages/common/nki-kakoune/kakrc @@ -1,6 +1,3 @@ -# Enable kak-tree-sitter -eval %sh{test -z "$WE_STARTED_KAK" && kak-tree-sitter --kakoune -d --server --init $kak_session} -map global normal ": enter-user-mode tree-sitter" # ## Set some color overrides # set global kts_yellow "rgb:e2b75e" # set global kts_teal "rgb:008080" diff --git a/packages/common/nki-kakoune/rc.nix b/packages/common/nki-kakoune/rc.nix index fa4c94d..ac579c9 100644 --- a/packages/common/nki-kakoune/rc.nix +++ b/packages/common/nki-kakoune/rc.nix @@ -1,4 +1,11 @@ -{ lib, fish, writeScript, writeTextDir, ... }: +{ lib +, fish +, writeScript +, writeTextDir +, prependRc ? "" +, appendRc ? "" +, ... +}: let source-pwd = writeScript "source-pwd" '' @@ -8,7 +15,9 @@ let ''; in writeTextDir "share/kak/kakrc.local" '' + ${prependRc} ${builtins.readFile ./kakrc} + ${appendRc} # Source any settings in the current working directory, # recursive upwards diff --git a/packages/common/nki-kakoune/tree-sitter/default.nix b/packages/common/nki-kakoune/tree-sitter/default.nix new file mode 100644 index 0000000..ce16343 --- /dev/null +++ b/packages/common/nki-kakoune/tree-sitter/default.nix @@ -0,0 +1,171 @@ +{ lib +, callPackage +, formats +, runCommandLocal +, kak-tree-sitter +, ... +}: +let + utils = callPackage ../utils.nix { }; + grammars = (callPackage ./grammars.nix { }).grammars; + # Highlighter groups to add to the `highlighterGroups`. Maps from group names to face names. + highlighterGroups = { + attribute = "@attribute"; + comment = "@comment"; + conceal = "%opt{mauve}+i"; + constant = "%opt{peach}"; + constant_builtin_boolean = "%opt{sky}"; + constant_character = "%opt{yellow}"; + constant_macro = "%opt{mauve}"; + constant_numeric = "%opt{peach}"; + constructor = "%opt{sapphire}"; + diff_plus = "%opt{green}"; + diff_minus = "%opt{red}"; + diff_delta = "%opt{blue}"; + diff_delta_moved = "%opt{mauve}"; + error = "%opt{red}+b"; + function = "@function"; + function_builtin = "@builtin"; + function_macro = "+i@ts_function"; + hint = "%opt{blue}+b"; + info = "%opt{green}+b"; + keyword = "keyword"; + keyword_conditional = "+i@ts_keyword"; + keyword_control_conditional = "+i@ts_keyword"; + keyword_control_directive = "+i@ts_keyword"; + keyword_control_import = "+i@ts_keyword"; + keyword_directive = "+i@ts_keyword"; + label = "%opt{sapphire}+i"; + markup_bold = "%opt{peach}+b"; + markup_heading = "%opt{red}"; + markup_heading_1 = "%opt{red}"; + markup_heading_2 = "%opt{mauve}"; + markup_heading_3 = "%opt{green}"; + markup_heading_4 = "%opt{yellow}"; + markup_heading_5 = "%opt{pink}"; + markup_heading_6 = "%opt{teal}"; + markup_heading_marker = "%opt{peach}+b"; + markup_italic = "%opt{pink}+i"; + markup_list_checked = "%opt{green}"; + markup_list_numbered = "%opt{blue}+i"; + markup_list_unchecked = "%opt{teal}"; + markup_list_unnumbered = "%opt{mauve}"; + markup_link_label = "%opt{blue}"; + markup_link_url = "%opt{teal}+u"; + markup_link_uri = "%opt{teal}+u"; + markup_link_text = "%opt{blue}"; + markup_quote = "%opt{crust}"; + markup_raw = "%opt{sky}"; + markup_raw_block = "%opt{sky}"; + markup_raw_inline = "%opt{green}"; + markup_strikethrough = "%opt{crust}+s"; + namespace = "@module"; + operator = "@operator"; + property = "%opt{sky}"; + punctuation = "%opt{overlay2}"; + punctuation_special = "%opt{sky}"; + special = "%opt{blue}"; + spell = "%opt{mauve}"; + string = "%opt{green}"; + string_regex = "%opt{peach}"; + string_regexp = "%opt{peach}"; + string_escape = "%opt{mauve}"; + string_special = "%opt{blue}"; + string_special_path = "%opt{green}"; + string_special_symbol = "%opt{mauve}"; + string_symbol = "%opt{red}"; + tag = "%opt{teal}"; + tag_error = "%opt{red}"; + text_title = "%opt{mauve}"; + type = "@type"; + type_enum_variant = "+i@ts_type"; + variable = "@variable"; + variable_builtin = "@builtin"; + variable_other_member = "%opt{teal}"; + variable_parameter = "+i@variable"; + warning = "%opt{peach}+b"; + }; + + # Highlighter groups to be aliased by other groups + aliases = { + comment_block = "comment"; + comment_line = "comment"; + constant_character_escape = "constant_character"; + constant_numeric_float = "constant_numeric"; + constant_numeric_integer = "constant_numeric"; + function_method = "function"; + function_special = "function"; + keyword_control = "keyword"; + keyword_control_repeat = "keyword"; + keyword_control_return = "keyword"; + keyword_control_except = "keyword"; + keyword_control_exception = "keyword"; + keyword_function = "keyword"; + keyword_operator = "keyword"; + keyword_special = "keyword"; + keyword_storage = "keyword"; + keyword_storage_modifier = "keyword"; + keyword_storage_modifier_mut = "keyword"; + keyword_storage_modifier_ref = "keyword"; + keyword_storage_type = "keyword"; + punctuation_bracket = "punctuation"; + punctuation_delimiter = "punctuation"; + text = "string"; + type_builtin = "type"; + + # Scala stuff + method = "function"; + module = "namespace"; + function_call = "function"; + method_call = "method"; + + boolean = "constant_builtin_boolean"; + number = "constant_numeric"; + float = "constant_numeric_float"; + + type_qualifier = "keyword_special"; + storageclass = "keyword_storage_modifier"; + conditional = "keyword_conditional"; + include = "keyword_control_import"; + }; + + configDir = + let + toScm = name: lib.concatStringsSep "." (lib.splitString "_" name); + + toml = formats.toml { }; + file = + toml.generate "config.toml" { + highlight.groups = builtins.map toScm (builtins.attrNames highlighterGroups ++ builtins.attrNames aliases); + features = { + highlighting = true; + text_objects = true; + }; + language = grammars; + }; + in + runCommandLocal "kak-tree-sitter-config" { } '' + mkdir -p $out/kak-tree-sitter + ln -s ${file} $out/kak-tree-sitter/config.toml + ''; + + extraFaces = + let + toTs = name: "ts_${lib.concatStringsSep "_" (lib.splitString "." name)}"; + + definedFaces = lib.mapAttrs' (name: value: { inherit value; name = toTs name; }) highlighterGroups; + aliasFaces = lib.mapAttrs' (name: value: { name = toTs name; value = "@${toTs value}"; }) aliases; + faces = lib.recursiveUpdate definedFaces aliasFaces; + in + faces; +in +{ + rc = '' + # Enable kak-tree-sitter + eval %sh{env XDG_CONFIG_DIR=${configDir} ${lib.getExe' kak-tree-sitter "kak-tree-sitter"} --kakoune -d --server --init $kak_session} + map global normal ": enter-user-mode tree-sitter" + ''; + + plugin = utils.mkFacesScript "kak-tree-sitter" extraFaces; +} + diff --git a/packages/common/nki-kakoune/tree-sitter/grammars.nix b/packages/common/nki-kakoune/tree-sitter/grammars.nix new file mode 100644 index 0000000..426edb3 --- /dev/null +++ b/packages/common/nki-kakoune/tree-sitter/grammars.nix @@ -0,0 +1,119 @@ +{ lib, stdenv, fetchFromGitHub, runCommandLocal, ... }: +let + mkGrammarPackage = + { name + , src + , grammarPath ? "src" + , grammarCompileArgs ? [ "-O3" "-c" "-fpic" "../parser.c" "../scanner.c" "-I" ".." ] + , grammarLinkArgs ? [ "-shared" "-fpic" "parser.o" "scanner.o" ] + , ... + }: stdenv.mkDerivation { + inherit src; + name = "kak-tree-sitter-grammar-${name}"; + version = "latest"; + buildPhase = '' + mkdir ${grammarPath}/build + cd ${grammarPath}/build + $CC ${lib.concatStringsSep " " grammarCompileArgs} + $CC ${lib.concatStringsSep " " grammarLinkArgs} -o ${name}.so + ''; + installPhase = '' + mkdir $out + cp ${name}.so $out + ''; + }; + mkGrammar = + args @ { name + , src + , grammarPath ? "src" + , grammarCompileArgs ? [ "-O3" "-c" "-fpic" "../parser.c" "../scanner.c" "-I" ".." ] + , grammarLinkArgs ? [ "-shared" "-fpic" "parser.o" "scanner.o" ] + , querySrc ? src + , queryPath ? "runtime/queries/${name}" + , + }: { + grammar.source.local.path = "${mkGrammarPackage args}"; + queries.source.local.path = querySrc; + queries.path = queryPath; + }; + + tree-sitter-go = fetchFromGitHub { + owner = "tree-sitter"; + repo = "tree-sitter-go"; + rev = "v0.20.0"; + hash = "sha256-G7d8CHCyKDAb9j6ijRfHk/HlgPqSI+uvkuRIRRvjkHI="; + }; +in +{ + grammars = builtins.mapAttrs (name: value: mkGrammar ({ inherit name; } // value)) { + scala = { + src = fetchFromGitHub { + owner = "tree-sitter"; + repo = "tree-sitter-scala"; + rev = "70afdd5632d57dd63a960972ab25945e353a52f6"; + hash = "sha256-bi0Lqo/Zs2Uaz1efuKAARpEDg5Hm59oUe7eSXgL1Wow="; + }; + queryPath = "queries/scala"; + }; + haskell = { + src = fetchFromGitHub { + owner = "tree-sitter"; + repo = "tree-sitter-haskell"; + rev = "ba0bfb0e5d8e9e31c160d287878c6f26add3ec08"; + hash = "sha256-ZSOF0CLOn82GwU3xgvFefmh/AD2j5zz8I0t5YPwfan0="; + }; + grammarCompileArgs = [ "-O3" "-c" "-fpic" "../parser.c" "../scanner.c" "../unicode.h" "-I" ".." ]; + queryPath = "queries"; + }; + yaml = { + src = fetchFromGitHub { + owner = "ikatyang"; + repo = "tree-sitter-yaml"; + rev = "0e36bed171768908f331ff7dff9d956bae016efb"; + hash = "sha256-bpiT3FraOZhJaoiFWAoVJX1O+plnIi8aXOW2LwyU23M="; + }; + grammarCompileArgs = [ "-c" "-fpic" "../scanner.cc" "../parser.c" "-I" ".." ]; + grammarLinkArgs = [ "-lstdc++" "-shared" "-fpic" "scanner.o" "parser.o" ]; + querySrc = fetchFromGitHub { + owner = "helix-editor"; + repo = "helix"; + rev = "dbd248fdfa680373d94fbc10094a160aafa0f7a7"; + hash = "sha256-wk8qVUDFXhAOi1Ibc6iBMzDCXb6t+YiWZcTd0IJybqc="; + }; + }; + templ = rec { + src = fetchFromGitHub { + owner = "vrischmann"; + repo = "tree-sitter-templ"; + rev = "044ad200092170727650fa6d368df66a8da98f9d"; + hash = "sha256-hJuB3h5pp+LLfP0/7bAYH0uLVo+OQk5jpzJb3J9BNkY="; + }; + querySrc = runCommandLocal "templ-tree-sitter-queries" { } '' + mkdir -p $out/queries + # copy most stuff from tree-sitter-templ + install -m644 ${src}/queries/templ/* $out/queries + # override inherited files + cat ${tree-sitter-go}/queries/highlights.scm ${src}/queries/templ/highlights.scm > $out/queries/highlights.scm + ''; + queryPath = "queries"; + }; + go = { + src = tree-sitter-go; + grammarCompileArgs = [ "-O3" "-c" "-fpic" "../parser.c" "-I" ".." ]; + grammarLinkArgs = [ "-shared" "-fpic" "parser.o" ]; + queryPath = "queries"; + }; + hylo = { + src = fetchFromGitHub { + owner = "natsukagami"; + repo = "tree-sitter-hylo"; + rev = "494cbdff0d13cbc67348316af2efa0286dbddf6f"; + hash = "sha256-R5UeoglCTl0do3VDJ/liCTeqbxU9slvmVKNRA/el2VY="; + }; + grammarCompileArgs = [ "-O3" "-c" "-fpic" "../parser.c" "-I" ".." ]; + grammarLinkArgs = [ "-shared" "-fpic" "parser.o" ]; + queryPath = "queries"; + }; + }; +} + diff --git a/packages/common/nki-kakoune/utils.nix b/packages/common/nki-kakoune/utils.nix index 47e7c75..4183aa6 100644 --- a/packages/common/nki-kakoune/utils.nix +++ b/packages/common/nki-kakoune/utils.nix @@ -1,5 +1,7 @@ -{ lib, writeFile, ... }: { - mkFacesScript = name: faces: writeFile "${name}-faces.kak" ( - lib.concatStringsSep "\n" (builtins.attrValues (builtins.mapAttrs (name: face: "face global ${name} \"${face}\"") faces)) - ); +{ lib, writeTextDir, ... }: { + mkFacesScript = name: faces: writeTextDir "share/kak/autoload/${name}/faces.kak" '' + hook global KakBegin .* { + ${lib.concatStringsSep "\n" (builtins.attrValues (builtins.mapAttrs (name: face: " face global ${name} \"${face}\"") faces))} + } + ''; }