diff --git a/colors.nix b/colors.nix index cf24d99..7b9792b 100644 --- a/colors.nix +++ b/colors.nix @@ -61,8 +61,8 @@ let inherit (builtins) mapAttrs map; in rec { }; green = { - bright = "29f26c"; normal = "8aff80"; + bright = "29f26c"; pastel = ""; }; @@ -79,7 +79,7 @@ let inherit (builtins) mapAttrs map; in rec { }; purple = { - normal = "bd78fa"; + normal = "b58aff"; bright = "c97ffa"; pastel = "d9b5ff"; }; @@ -91,7 +91,7 @@ let inherit (builtins) mapAttrs map; in rec { }; pink = { - normal = "f74ddb"; + normal = "ee8fff"; bright = "ff63e5"; pastel = "ff96e3"; }; diff --git a/modules/kak/colors.nix b/modules/kak/colors.nix index 75f1322..7ff85eb 100644 --- a/modules/kak/colors.nix +++ b/modules/kak/colors.nix @@ -17,5 +17,11 @@ pkgs.writeTextFile (rec { face global meta rgb:${green.bright} face global type rgb:${blue.bright} + face global LineNumbers rgb:${background.slight} + face global BufferPadding rgb:${background.slight} + face global LineNumberCursor rgb:${foreground.primary} + face global crosshairs_line "default,rgb:${background.normal}" + face global MenuForeground "default,rgb:${blue.normal}" + face global MenuBackground "default,rgb:313131" ''; }) diff --git a/modules/kak/default.nix b/modules/kak/default.nix index 3b4b1c8..18d54b1 100644 --- a/modules/kak/default.nix +++ b/modules/kak/default.nix @@ -140,14 +140,15 @@ in with lib; { kak.enable = (mkEnableOption "kakoune editor") // { default = true; }; - kak.ide = (mkEnableOption "kakoune with ide plugins") // { default = false; }; - kak.rust = mkEnableOption "Rust support in Kakoune"; + kak.ts = mkEnableOption "TypeScript support in Kakoune"; kak.haskell = mkEnableOption "Haskell support in Kakoune"; + kak.python = mkEnableOption "Python 3.9 support in Kakoune"; + kak.nix = (mkEnableOption "Nix support in Kakoune") // { default = true; }; }; - config = mkIf (config.editor.kak.enable || config.editor.kak.ide) { + config = mkIf (config.editor.kak.enable) { environment.systemPackages = with pkgs; [ (pkgs.kakoune.override { diff --git a/modules/kak/kak-lsp.nix b/modules/kak/kak-lsp.nix new file mode 100644 index 0000000..c8d681c --- /dev/null +++ b/modules/kak/kak-lsp.nix @@ -0,0 +1,121 @@ +{ + # Feature flags + typescript ? false, + haskell ? false, + python ? false, + rust ? false, + nix ? true, + + # Build context + pkgs, + lib +}: + +with lib; +with pkgs; + +let semantic-tokens = + let mk = (name: value: '' + [[semantic_tokens]] + token = "${name}" + face = "${value}" + ''); in concatStringsSep "\n" (mapAttrsToList mk { + "enumMember" = "variant"; + "enum" = "enum"; + "union" = "union"; + "struct" = "struct"; + "typeAlias" = "alias"; + "builtinType" = "primitive"; + "trait" = "trait"; + "interface" = "trait"; + "method" = "method"; + "function" = "function"; + "namespace" = "module"; + "boolean" = "literal"; + "character" = "literal"; + "number" = "literal"; + "string" = "string"; + "keyword" = "keyword"; + "documentation" = "comment"; + "comment" = "comment"; + "escapeSequence" = "format"; + "formatSpecifier" = "format"; + "operator" = "operator"; + "arithmetic" = "operator"; + "bitwise" = "operator"; + "comparison" = "operator"; + "logical" = "operator"; + "macro" = "macro"; + "lifetime" = "lifetime"; + "variable" = "variable"; + "attribute" = "attribute"; + "punctuation" = "punctuation"; + }); + + kak-lsp-config-text = + (optionalString (rust || haskell) semantic-tokens) + ++ (optionalString rust '' + [language.rust] + filetypes = [ "rust" ] + roots = [ "Cargo.toml" ] + command = "rust-analyzer" + [language.rust.settings.rust-analyzer] + semanticTokens = true + diagnostics.enabled = [ "unresolved-proc-macro" ] + cargo.loadOutDirsFromCheck = true + procMacro.enable = false + '') + ++ (optionalString nix '' + [language.nix] + filetypes = [ "nix" ] + roots = [ "flake.nix", "shell.nix", ".git", ".hg" ] + command = "rnix-lsp" + '') + ++ (optionalString haskell '' + [language.haskell] + filetypes = [ "haskell" ] + roots = [ "Setup.hs", "stack.yaml", "*.cabal" ] + command = "haskell-language-server-wrapper" + args = [ "--lsp" ] + '') + ++ (optionalString python '' + [language.python] + filetypes = [ "python" ] + roots = [ "setup.py", ".git", ".hg" ] + command = "pylsp" + '') + ++ (optionalString typescript '' + [language.typescript] + filetypes = ["typescript", "javascript"] + roots = ["package.json"] + command = "rslint-lsp" + ''); + + kak-lsp-config = (pkgs.writeTextFile (rec { + name = "kak-lsp.toml"; + destination = "/share/kak-lsp/${name}"; + text = kak-lsp-config-text; + })); + +in (symlinkJoin { + + paths = with kakounePlugins; [ + + # The language server client + kak-lsp + + # Overwrite kak-lsp.toml + kak-lsp-config + + ] ++ (optional nix rnix-lsp) + ++ (optional typescript rslint) + ++ (optional haskell haskell-language-server) + ++ (optional python python39Packages.python-lsp-server) + ++ (optional rust rust-analyzer); + + name = "kak-lsp-${kak-lsp.version}"; + nativeBuildInputs = [ makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/kak-lsp --add-flags "--config $out/share/kak-lsp/kak-lsp.toml" + ''; +}) diff --git a/modules/kak/kakoune.nix b/modules/kak/kakoune.nix index fc079c0..a4cedfe 100644 --- a/modules/kak/kakoune.nix +++ b/modules/kak/kakoune.nix @@ -12,6 +12,9 @@ # outside of the package extraPlugins ? [], + # Plugins + kak-crosshairs, + # Color theme theme, @@ -56,7 +59,7 @@ in (pkgs.kakoune.override { kakrc # Plugins - crosshairs + kak-crosshairs ] ++ extraPlugins; }) diff --git a/modules/kak/kakrc.nix b/modules/kak/kakrc.nix index c329359..80a85ca 100644 --- a/modules/kak/kakrc.nix +++ b/modules/kak/kakrc.nix @@ -16,53 +16,149 @@ lib, }: - # If any of the language features are enabled, enable the - # extra language server-related keybinds and options. -let ide = typescript || haskell || python || rust || nix; + +let keybinds = '' + map global insert :buffer-next + map global normal :buffer-next + ''; - # Generic keybinds - keybinds = '' + # Initialization code for IDE mode needed for every supported + # language. + ide-init = '' + eval %sh{ kak-lsp --kakoune -s $kak_session } + lsp-enable-window + ''; + + # Implies `ide-init`. Adds inlay diagnostics support, code actions + # and hover. + ide-core = '' + + ${ide-init} + + lsp-inlay-diagnostics-enable window + + hook window ModeChange .*:.*:insert %{ + remove-highlighter window/lsp_diagnostics + } + + hook window ModeChange .*:insert:normal %{ + lsp-inlay-diagnostics-enable window + } + + map buffer normal ': lsp-code-actions' + map buffer normal ': lsp-hover' ''; - # IDE mode enables the language server protocol client - # and adds keybinds for lsp-hover and lsp-code-actions. - # If `rust` is enabled, lsp-semantic-tokens is also used. - ide-config = (lib.optionalString ide '' + # Implies `ide-core`, which implies `ide-init`. + ide-full = '' + + ${ide-core} + hook window -group semtok BufReload .* lsp-semantic-tokens + hook window -group semtok NormalIdle .* lsp-semantic-tokens + hook window -group semtok InsertIdle .* lsp-semantic-tokens + + hook -once -always window WinSetOption filetype=.* %{ + remove-hooks window semtok + } + + map global normal ': lsp-next-function' + map global normal ': lsp-previous-function' + map global normal ': lsp-previous-location *goto*' + map global normal ': lsp-next-location *goto*' + + ''; in + + + # Nix hacking-related configuration. Nix has a very weak language + # server, and it basically only supports `ide-init` (for completions). +let nix-config = (lib.optionalString nix '' + hook global WinSetOption filetype=nix %{ + ${ide-init} + } ''); - # Sometimes work requires me to touch the frontend. Ew - typescript-config = (lib.optionalString typescript '' - + # Sometimes work requires me to touch the frontend. Ew. `ide-core` + # suffices here. + typescript-config = (lib.optionalString typescript '' + hook global WinSetOption filetype=(javascript|typescript) %{ + ${ide-core} + } ''); - # Haskell development - haskell-config = (lib.optionalString haskell '' - - ''); - - # Python-related config + # Python-related config. Python does not support more features than + # those in `ide-core`. python-config = (lib.optionalString python '' + hook global WinSetOption filetype=python %{ + ${ide-core} + + face window keyword rgb:${green.bright} + face window meta keyword + + } ''); - # Rust development + # Haskell development. Haskell has a language server with + # the features in `ide-full`. + haskell-config = (lib.optionalString haskell '' + hook global WinSetOption filetype=haskell %{ + + ${ide-full} + + set-option buffer tabstop 2 + + face global variable rgb:${purple.normal} + face global attribute keyword + face global operator keyword + face global keyword rgb:${blue.bright} + face global value string + face global meta rgb:${pink.normal} + + } + ''); + + # Rust development. Rust's language servers all support the + # `ide-full` features. rust-config = (lib.optionalString rust '' + hook global WinSetOption filetype=rust %{ + ${ide-full} + + hook global -group yeet ModuleLoaded rust %{ + + # Override the Rust highlighting with semantic + # tokens supplied by the LSP client + remove-hooks global rust-highlight + remove-highlighter shared/rust + + # Request tokens + lsp-semantic-tokens + + # Self-destruct this hook (it should only run once) + remove-hooks global yeet + + } + + } ''); - # Nix hacking-related configuration - nix-config = (lib.optionalString nix '' - - ''); - - in pkgs.writeTextFile (rec { name = "kakrc.kak"; destination = "/share/kak/autoload/${name}"; text = with theme; '' + add-highlighter global/ number-lines -separator ' │ ' -hlcursor + + set global tabstop 4 + + face global InlayHint rgb:828282 + face global InlayDiagnosticWarning rgb:a39e31+f + face global InlayDiagnosticError rgb:ad494f+f + face global InlayDiagnosticHint rgb:4d965a+f + face global InlayDiagnosticInfo rgb:4d965a+f + '' ++ keybinds ++ typescript-config ++ haskell-config