From 8774f1afd63b11f56c1e02ae1cbb6baf069e813c Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Fri, 30 Jun 2023 13:38:46 +0200 Subject: [PATCH] Add tree-sitter kakoune module --- home/kakoune/kak.nix | 48 +++- home/kakoune/reload-faces.kak | 130 ---------- home/modules/programs/my-kakoune/default.nix | 21 +- .../programs/my-kakoune/tree-sitter.nix | 242 ++++++++++++++++++ 4 files changed, 307 insertions(+), 134 deletions(-) delete mode 100644 home/kakoune/reload-faces.kak create mode 100644 home/modules/programs/my-kakoune/tree-sitter.nix diff --git a/home/kakoune/kak.nix b/home/kakoune/kak.nix index d06a9ad..99d6405 100644 --- a/home/kakoune/kak.nix +++ b/home/kakoune/kak.nix @@ -96,10 +96,26 @@ in }; }; + programs.my-kakoune.tree-sitter.languages = { + scala = + let + src = pkgs.fetchFromGitHub { + owner = "tree-sitter"; + repo = "tree-sitter-scala"; + rev = "cda0de8a038b0e4ad79a97f7aa281250fcf88560"; + sha256 = "sha256-3R5aflBeTny56EL6sONWfMWpVnPb6VHL6IsisMdM5bk="; + leaveDotGit = true; + }; in + { + grammar.src = src; + queries.src = src; + queries.path = "queries/scala"; + }; + }; + programs.my-kakoune.package = kakounePkg; programs.my-kakoune.rc = - builtins.readFile ./kakrc + - builtins.readFile ./reload-faces.kak + '' + builtins.readFile ./kakrc + '' # Source any settings in the current working directory, # recursive upwards @@ -107,6 +123,34 @@ in ${pkgs.writeScript "source-pwd" (builtins.readFile ./source-pwd)} } ''; + + programs.my-kakoune.extraFaces = { + Default = "%opt{white},%opt{background}"; + BufferPadding = "%opt{background},%opt{background}"; + MenuForeground = "blue,white+bF"; + MenuBackground = "bright-blue,white+F"; + Information = "bright-blue,white"; + # Markdown help color scheme + InfoDefault = "Information"; + InfoBlock = "@block"; + InfoBlockQuote = "+i@block"; + InfoBullet = "@bullet"; + InfoHeader = "@header"; + InfoLink = "@link"; + InfoLinkMono = "+b@mono"; + InfoMono = "@mono"; + InfoRule = "+b@Information"; + InfoDiagnosticError = "@DiagnosticError"; + InfoDiagnosticHint = "@DiagnosticHint"; + InfoDiagnosticInformation = "@Information"; + InfoDiagnosticWarning = "@DiagnosticWarning"; + # Extra faces + macro = "+b@function"; + method = "+i@function"; + format_specifier = "+i@string"; + mutable_variable = "+u@variable"; + class = "+b@variable"; + }; programs.my-kakoune.autoload = [ # My own scripts { diff --git a/home/kakoune/reload-faces.kak b/home/kakoune/reload-faces.kak deleted file mode 100644 index 20a174c..0000000 --- a/home/kakoune/reload-faces.kak +++ /dev/null @@ -1,130 +0,0 @@ -# Reload all faces -# our faces -set-face global Default "%opt{white},%opt{background}" -set-face global BufferPadding "%opt{background},%opt{background}" -# face global Default rgb:121213,default -# face global BufferPadding rgb:A0A0A0,default -face global MenuForeground blue,white+bF -face global MenuBackground bright-blue,white+F -face global Information bright-blue,white -# Markdown help color scheme -face global InfoDefault Information -face global InfoBlock @block -face global InfoBlockQuote +i@block -face global InfoBullet @bullet -face global InfoHeader @header -face global InfoLink @link -face global InfoLinkMono +b@mono -face global InfoMono @mono -face global InfoRule +b@Information -face global InfoDiagnosticError @DiagnosticError -face global InfoDiagnosticHint @DiagnosticHint -face global InfoDiagnosticInformation @Information -face global InfoDiagnosticWarning @DiagnosticWarning -# Extra faces -face global macro +b@function -face global method +i@function -face global format_specifier +i@string -face global mutable_variable +u@variable -face global class +b@variable - -# tree-sitter -#set-face global ts_unknown red+ub -set-face global ts_attribute "@attribute" -set-face global ts_comment "@comment" -set-face global ts_comment_block "@ts_comment" -set-face global ts_comment_line "@ts_comment" -set-face global ts_conceal "%opt{mauve}+i" -set-face global ts_constant "%opt{peach}" -set-face global ts_constant_builtin_boolean "%opt{sky}" -set-face global ts_constant_character "%opt{yellow}" -set-face global ts_constant_character_escape "@ts_constant_character" -set-face global ts_constant_macro "%opt{mauve}" -set-face global ts_constant_numeric "%opt{peach}" -set-face global ts_constant_numeric_float "@ts_constant_numeric" -set-face global ts_constant_numeric_integer "@ts_constant_numeric" -set-face global ts_constructor "%opt{sapphire}" -set-face global ts_diff_plus "%opt{green}" -set-face global ts_diff_minus "%opt{red}" -set-face global ts_diff_delta "%opt{blue}" -set-face global ts_diff_delta_moved "%opt{mauve}" -set-face global ts_error "%opt{red}+b" -set-face global ts_function "@function" -set-face global ts_function_builtin "@builtin" -set-face global ts_function_macro "+i@ts_function" -set-face global ts_function_method "@ts_function" -set-face global ts_function_special "@ts_function" -set-face global ts_hint "%opt{blue}+b" -set-face global ts_info "%opt{green}+b" -set-face global ts_keyword "keyword" -set-face global ts_keyword_control "@ts_keyword" -set-face global ts_keyword_conditional "+i@ts_keyword" -set-face global ts_keyword_control_conditional "+i@ts_keyword" -set-face global ts_keyword_control_directive "+i@ts_keyword" -set-face global ts_keyword_control_import "+i@ts_keyword" -set-face global ts_keyword_control_repeat "@ts_keyword" -set-face global ts_keyword_control_return "@ts_keyword" -set-face global ts_keyword_control_except "@ts_keyword" -set-face global ts_keyword_control_exception "@ts_keyword" -set-face global ts_keyword_directive "+i@ts_keyword" -set-face global ts_keyword_function "@ts_keyword" -set-face global ts_keyword_operator "@ts_keyword" -set-face global ts_keyword_special "@ts_keyword" -set-face global ts_keyword_storage "@ts_keyword" -set-face global ts_keyword_storage_modifier "@ts_keyword" -set-face global ts_keyword_storage_modifier_mut "@ts_keyword" -set-face global ts_keyword_storage_modifier_ref "@ts_keyword" -set-face global ts_keyword_storage_type "@ts_keyword" -set-face global ts_label "%opt{sapphire}+i" -set-face global ts_markup_bold "%opt{peach}+b" -set-face global ts_markup_heading "%opt{red}" -set-face global ts_markup_heading_1 "%opt{red}" -set-face global ts_markup_heading_2 "%opt{mauve}" -set-face global ts_markup_heading_3 "%opt{green}" -set-face global ts_markup_heading_4 "%opt{yellow}" -set-face global ts_markup_heading_5 "%opt{pink}" -set-face global ts_markup_heading_6 "%opt{teal}" -set-face global ts_markup_heading_marker "%opt{peach}+b" -set-face global ts_markup_italic "%opt{pink}+i" -set-face global ts_markup_list_checked "%opt{green}" -set-face global ts_markup_list_numbered "%opt{blue}+i" -set-face global ts_markup_list_unchecked "%opt{teal}" -set-face global ts_markup_list_unnumbered "%opt{mauve}" -set-face global ts_markup_link_label "%opt{blue}" -set-face global ts_markup_link_url "%opt{teal}+u" -set-face global ts_markup_link_uri "%opt{teal}+u" -set-face global ts_markup_link_text "%opt{blue}" -set-face global ts_markup_quote "%opt{gray1}" -set-face global ts_markup_raw "%opt{sky}" -set-face global ts_markup_raw_block "%opt{sky}" -set-face global ts_markup_raw_inline "%opt{green}" -set-face global ts_markup_strikethrough "%opt{gray1}+s" -set-face global ts_namespace "@module" -set-face global ts_operator "@operator" -set-face global ts_property "%opt{sky}" -set-face global ts_punctuation "%opt{overlay2}" -set-face global ts_punctuation_bracket "@ts_punctuation" -set-face global ts_punctuation_delimiter "@ts_punctuation" -set-face global ts_punctuation_special "%opt{sky}" -set-face global ts_special "%opt{blue}" -set-face global ts_spell "%opt{mauve}" -set-face global ts_string "%opt{green}" -set-face global ts_string_regex "%opt{peach}" -set-face global ts_string_regexp "%opt{peach}" -set-face global ts_string_escape "%opt{mauve}" -set-face global ts_string_special "%opt{blue}" -set-face global ts_string_special_path "%opt{green}" -set-face global ts_string_special_symbol "%opt{mauve}" -set-face global ts_string_symbol "%opt{red}" -set-face global ts_tag "%opt{teal}" -set-face global ts_tag_error "%opt{red}" -set-face global ts_text "@ts_string" -set-face global ts_text_title "%opt{mauve}" -set-face global ts_type "%opt{yellow}" -set-face global ts_type_builtin "@ts_type" -set-face global ts_type_enum_variant "%opt{flamingo}" -set-face global ts_variable "@variable" -set-face global ts_variable_builtin "@builtin" -set-face global ts_variable_other_member "%opt{teal}" -set-face global ts_variable_parameter "%opt{maroon}+i" -set-face global ts_warning "%opt{peach}+b" diff --git a/home/modules/programs/my-kakoune/default.nix b/home/modules/programs/my-kakoune/default.nix index aa34efc..125484a 100644 --- a/home/modules/programs/my-kakoune/default.nix +++ b/home/modules/programs/my-kakoune/default.nix @@ -28,7 +28,7 @@ let }; in { - imports = [ ./kak-lsp.nix ./fish-session.nix ]; + imports = [ ./kak-lsp.nix ./fish-session.nix ./tree-sitter.nix ]; options.programs.my-kakoune = { enable = mkEnableOption "My version of the kakoune configuration"; @@ -52,6 +52,12 @@ in default = { }; description = "Themes to load"; }; + + extraFaces = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Extra faces to include"; + }; }; config = mkIf cfg.enable { @@ -89,10 +95,21 @@ in }) cfg.themes )); + + kakouneFaces = + let + txt = strings.concatStringsSep "\n" (builtins.attrValues (builtins.mapAttrs (name: face: "face global ${name} \"${face}\"") cfg.extraFaces)); + in + pkgs.writeText "faces.kak" txt; in { # kakrc - "kak/kakrc".text = cfg.rc; + "kak/kakrc".text = '' + ${cfg.rc} + + # Load faces + source ${kakouneFaces} + ''; } // (builtins.listToAttrs (lib.lists.flatten (map kakouneAutoload ([ # include the original autoload files diff --git a/home/modules/programs/my-kakoune/tree-sitter.nix b/home/modules/programs/my-kakoune/tree-sitter.nix new file mode 100644 index 0000000..2020327 --- /dev/null +++ b/home/modules/programs/my-kakoune/tree-sitter.nix @@ -0,0 +1,242 @@ +{ config, pkgs, lib, ... }: +with lib; +let + cfg = config.programs.my-kakoune.tree-sitter; + + languageModule = types.submodule { + options = { + grammar.src = mkOption { + type = types.package; + description = "The repo to be used"; + }; + grammar.path = mkOption { + type = types.str; + default = "src"; + }; + grammar.compile = { + command = mkOption { type = types.str; default = "${pkgs.gcc}/bin/gcc"; }; + args = mkOption { type = types.listOf types.str; default = [ "-c" "-fpic" "../parser.c" "../scanner.c" "-I" ".." ]; }; + flags = mkOption { type = types.listOf types.str; default = [ "-O3" ]; }; + }; + grammar.link = { + command = mkOption { type = types.str; default = "${pkgs.gcc}/bin/gcc"; }; + args = mkOption { type = types.listOf types.str; default = [ "-shared" "-fpic" "parser.o" "scanner.o" ]; }; + flags = mkOption { type = types.listOf types.str; default = [ "-O3" ]; }; + }; + queries.src = mkOption { + type = types.package; + description = "The repo to be used"; + }; + queries.path = mkOption { + type = types.nullOr types.str; + default = null; + }; + }; + }; +in +{ + options.programs.my-kakoune.tree-sitter = { + enable = mkOption { + type = types.bool; + default = true; + description = "Enable kak-tree-sitter"; + }; + package = mkPackageOption pkgs "kak-tree-sitter" { }; + + highlighterGroups = mkOption { + type = types.attrsOf types.str; + default = { + 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{gray1}"; + markup_raw = "%opt{sky}"; + markup_raw_block = "%opt{sky}"; + markup_raw_inline = "%opt{green}"; + markup_strikethrough = "%opt{gray1}+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 = "%opt{yellow}"; + type_enum_variant = "%opt{flamingo}"; + variable = "@variable"; + variable_builtin = "@builtin"; + variable_other_member = "%opt{teal}"; + variable_parameter = "%opt{maroon}+i"; + warning = "%opt{peach}+b"; + }; + }; + + extraHighlighterGroups = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Highlighter groups to add to the `highlighterGroups`. Maps from group names to face names."; + }; + + aliases = mkOption { + type = types.attrsOf types.str; + default = { + 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"; + }; + description = "Highlighter groups to be aliased by other groups"; + }; + + extraAliases = mkOption { + type = types.attrsOf types.str; + default = { }; + description = "Extra highlighter groups to be aliased by other groups"; + }; + + languages = mkOption { + type = types.attrsOf languageModule; + default = { }; + }; + }; + + config = + let + aliasedOnce = name: values: if asserts.assertMsg (builtins.length values 1) "face ${name} was aliased more than once: ${toString values}" then (builtins.head values) else [ ]; + + allGroups = attrsets.recursiveUpdate cfg.highlighterGroups cfg.extraHighlighterGroups; + + aliases = attrsets.recursiveUpdate cfg.aliases cfg.extraAliases; + + toTs = name: "ts_${strings.concatStringsSep "_" (strings.splitString "." name)}"; + toScm = name: strings.concatStringsSep "." (strings.splitString "_" name); + + definedFaces = attrsets.mapAttrs' (name: value: { inherit value; name = toTs name; }) allGroups; + aliasFaces = attrsets.mapAttrs' (name: value: { name = toTs name; value = "@${toTs value}"; }) aliases; + faces = attrsets.recursiveUpdate definedFaces aliasFaces; + + toml = pkgs.formats.toml { }; + + toLanguageConf = name: lang: with lang; { + grammar = { + inherit (grammar) path; + url = "${grammar.src}"; + compile = grammar.compile.command; + compile_args = grammar.compile.args; + compile_flags = grammar.compile.flags; + link = grammar.link.command; + link_args = grammar.link.args ++ [ "-o" "${name}.so" ]; + link_flags = grammar.link.flags; + }; + queries = { + url = "${queries.src}"; + path = if queries.path == null then "runtime/queries/${name}" else queries.path; + }; + }; + in + mkIf cfg.enable { + assertions = with lib.asserts; ([ ] + ++ attrsets.mapAttrsToList + (name: _: { + assertion = (! (builtins.hasAttr name allGroups)); + message = "${name} was both defined and aliased"; + }) + aliases + ); + home.packages = [ cfg.package ]; + + xdg.configFile."kak-tree-sitter/config.toml" = { + source = toml.generate "config.toml" { + highlight.groups = builtins.map toScm (builtins.attrNames allGroups ++ builtins.attrNames aliases); + + language = builtins.mapAttrs toLanguageConf cfg.languages; + }; + + onChange = + let + buildCmd = lang: "ktsctl -fci ${lang}"; + buildAll = strings.concatMapStringsSep "\n" buildCmd (builtins.attrNames cfg.languages); + in + '' + # Rebuild languages + ${buildAll} + ''; + }; + + programs.my-kakoune.extraFaces = faces; + }; + +} +