From 504c56bf7d6b4f8aaae7fda08aa9acae0a6d41d4 Mon Sep 17 00:00:00 2001 From: Ching Pei Yang Date: Sat, 11 Jan 2025 21:02:01 +0100 Subject: [PATCH] blink: init --- .../completion/blink-cmp/blink-cmp.nix | 120 ++++++++++++++++++ .../plugins/completion/blink-cmp/config.nix | 90 +++++++++++++ .../plugins/completion/blink-cmp/default.nix | 6 + modules/plugins/completion/default.nix | 1 + 4 files changed, 217 insertions(+) create mode 100644 modules/plugins/completion/blink-cmp/blink-cmp.nix create mode 100644 modules/plugins/completion/blink-cmp/config.nix create mode 100644 modules/plugins/completion/blink-cmp/default.nix diff --git a/modules/plugins/completion/blink-cmp/blink-cmp.nix b/modules/plugins/completion/blink-cmp/blink-cmp.nix new file mode 100644 index 00000000..b6155284 --- /dev/null +++ b/modules/plugins/completion/blink-cmp/blink-cmp.nix @@ -0,0 +1,120 @@ +{lib, ...}: let + inherit (lib.options) mkEnableOption mkOption literalMD; + inherit (lib.types) listOf str either attrsOf submodule enum anything int nullOr; + inherit (lib.generators) mkLuaInline; + inherit (lib.nvim.types) mkPluginSetupOption luaInline; + inherit (lib.nvim.binds) mkMappingOption; + inherit (lib.nvim.config) mkBool; + + keymapType = submodule { + freeformType = attrsOf (listOf (either str luaInline)); + options = { + preset = mkOption { + type = enum ["default" "none" "super-tab" "enter"]; + default = "none"; + description = "keymap presets"; + }; + }; + }; + + providerType = submodule { + freeformType = anything; + options = { + module = mkOption { + type = str; + description = "module of the provider"; + }; + }; + }; +in { + options.vim.autocomplete.blink-cmp = { + enable = mkEnableOption "blink.cmp"; + setupOpts = mkPluginSetupOption "blink.cmp" { + sources = { + default = mkOption { + type = listOf str; + default = ["lsp" "path" "snippets" "buffer"]; + description = "Default list of sources to enable for completion."; + }; + + cmdline = mkOption { + type = nullOr (listOf str); + default = []; + description = "List of sources to enable for cmdline. Null means use default source list."; + }; + + providers = mkOption { + type = attrsOf providerType; + default = {}; + description = "Providers"; + }; + + transform_items = mkOption { + type = nullOr luaInline; + default = mkLuaInline "function(_, items) return items end"; + defaultText = '' + Our default does nothing. If you want blink.cmp's default, which + lowers the score for snippets, set this option to null. + ''; + description = '' + Function to use when transforming the items before they're returned + for all providers. + ''; + }; + }; + + completion = { + documentation = { + auto_show = mkBool true "Show documentation whenever an item is selected"; + auto_show_delay_ms = mkOption { + type = int; + default = 200; + description = "Delay before auto show triggers"; + }; + }; + }; + + keymap = mkOption { + type = keymapType; + default = {}; + description = "blink.cmp keymap"; + example = literalMD '' + ```nix + vim.autocomplete.blink-cmp.setupOpts.keymap = { + preset = "none"; + + "" = ["select_prev" "fallback"]; + "" = [ + (lib.generators.mkLuaInline '''' + function(cmp) + if some_condition then return end -- runs the next command + return true -- doesn't run the next command + end, + '''') + "select_next" + ]; + }; + ``` + ''; + }; + + fuzzy = { + prebuilt_binaries = { + download = mkBool false '' + Auto-downloads prebuilt binaries. Do not enable, it doesn't work on nix + ''; + }; + }; + }; + + mappings = { + complete = mkMappingOption "Complete [blink.cmp]" ""; + confirm = mkMappingOption "Confirm [blink.cmp]" ""; + next = mkMappingOption "Next item [blink.cmp]" ""; + previous = mkMappingOption "Previous item [blink.cmp]" ""; + close = mkMappingOption "Close [blink.cmp]" ""; + scrollDocsUp = mkMappingOption "Scroll docs up [blink.cmp]" ""; + scrollDocsDown = mkMappingOption "Scroll docs down [blink.cmp]" ""; + }; + }; +} diff --git a/modules/plugins/completion/blink-cmp/config.nix b/modules/plugins/completion/blink-cmp/config.nix new file mode 100644 index 00000000..1141b7e9 --- /dev/null +++ b/modules/plugins/completion/blink-cmp/config.nix @@ -0,0 +1,90 @@ +{ + lib, + config, + ... +}: let + inherit (lib.modules) mkIf; + inherit (lib.strings) optionalString; + inherit (lib.generators) mkLuaInline; + inherit (lib.nvim.lua) toLuaObject; + inherit (builtins) concatStringsSep typeOf tryEval attrNames mapAttrs; + + cfg = config.vim.autocomplete.blink-cmp; + cmpCfg = config.vim.autocomplete.nvim-cmp; + inherit (cfg) mappings; + + getPluginName = plugin: + if typeOf plugin == "string" + then plugin + else if (plugin ? pname && (tryEval plugin.pname).success) + then plugin.pname + else plugin.name; +in { + vim = mkIf cfg.enable { + startPlugins = ["blink-compat"]; + lazy.plugins = { + blink-cmp = { + package = "blink-cmp"; + setupModule = "blink.cmp"; + inherit (cfg) setupOpts; + + # TODO: lazy disabled until lspconfig is lazy loaded + # + # event = ["InsertEnter" "CmdlineEnter"]; + + after = '' + ${optionalString config.vim.lazy.enable + (concatStringsSep "\n" (map + (package: "require('lz.n').trigger_load(${toLuaObject (getPluginName package)})") + cmpCfg.sourcePlugins))} + ''; + }; + }; + + autocomplete = { + blink-cmp.setupOpts = { + sources = { + default = ["lsp" "path" "snippets" "buffer"] ++ (attrNames cmpCfg.sources); + providers = + mapAttrs (name: _: { + inherit name; + module = "blink.compat.source"; + }) + cmpCfg.sources; + }; + snippets = mkIf config.vim.snippets.luasnip.enable { + preset = "luasnip"; + }; + + keymap = { + ${mappings.complete} = ["show" "fallback"]; + ${mappings.close} = ["hide" "fallback"]; + ${mappings.scrollDocsUp} = ["scroll_documentation_up" "fallback"]; + ${mappings.scrollDocsDown} = ["scroll_documentation_down" "fallback"]; + ${mappings.confirm} = ["accept" "fallback"]; + + ${mappings.next} = [ + "select_next" + "snippet_forward" + (mkLuaInline '' + function(cmp) + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + has_words_before = col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil + + if has_words_before then + return cmp.show() + end + end + '') + "fallback" + ]; + ${mappings.previous} = [ + "select_prev" + "snippet_backward" + "fallback" + ]; + }; + }; + }; + }; +} diff --git a/modules/plugins/completion/blink-cmp/default.nix b/modules/plugins/completion/blink-cmp/default.nix new file mode 100644 index 00000000..3e2d7e6b --- /dev/null +++ b/modules/plugins/completion/blink-cmp/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./blink-cmp.nix + ./config.nix + ]; +} diff --git a/modules/plugins/completion/default.nix b/modules/plugins/completion/default.nix index 0cae45f6..0c0a61a0 100644 --- a/modules/plugins/completion/default.nix +++ b/modules/plugins/completion/default.nix @@ -1,5 +1,6 @@ { imports = [ ./nvim-cmp + ./blink-cmp ]; }