Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat blink #510

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
34 changes: 34 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,16 @@
flake = false;
};

plugin-blink-cmp = {
url = "github:saghen/blink.cmp";
flake = false;
};

plugin-blink-compat = {
url = "github:saghen/blink.compat";
flake = false;
};

plugin-nvim-cmp = {
url = "github:hrsh7th/nvim-cmp";
flake = false;
Expand Down
31 changes: 31 additions & 0 deletions modules/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,37 @@
pname = "flutter-tools";
patches = [../patches/flutter-tools.patch];
};
blink-cmp = let
version = inputs.plugin-blink-cmp.shortRev or inputs.plugin-blink-cmp.shortDirtyRev or "dirty";
src = inputs.plugin-blink-cmp;
blink-fuzzy-lib = pkgs.rustPlatform.buildRustPackage {
pname = "blink-fuzzy-lib";
inherit version src;

env = {
# TODO: remove this if plugin stops using nightly rust
RUSTC_BOOTSTRAP = true;
};
cargoLock = {
lockFile = "${src}/Cargo.lock";
outputHashes = {
"frizbee-0.1.0" = "sha256-pt6sMsRyjXrbrTK7t/YvWeen/n3nU8UUaiNYTY1LczE=";
};
};
};
libExt =
if pkgs.hostPlatform.isDarwin
then "dylib"
else "so";
in
buildPlug {
pname = "blink-cmp";
inherit version src;
preInstall = ''
mkdir -p target/release
ln -s ${blink-fuzzy-lib}/lib/libblink_cmp_fuzzy.${libExt} target/release/libblink_cmp_fuzzy.${libExt}
'';
};
};

buildConfigPlugins = plugins:
Expand Down
4 changes: 2 additions & 2 deletions modules/plugins/assistant/copilot/config.nix
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ in {
};
};

autocomplete.nvim-cmp = {
sources = {copilot = "[Copilot]";};
autocomplete = {
nvim-cmp.sources = {copilot = "[Copilot]";};
sourcePlugins = ["copilot-cmp"];
};

Expand Down
92 changes: 92 additions & 0 deletions modules/plugins/completion/blink-cmp/blink-cmp.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption mkOption literalMD;
inherit (lib.types) listOf str either attrsOf submodule enum anything int;
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.";
};

providers = mkOption {
type = attrsOf providerType;
default = {};
description = "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";

"<Up>" = ["select_prev" "fallback"];
"<C-n>" = [
(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"
];
};
```
'';
};
};

mappings = {
complete = mkMappingOption "Complete [blink.cmp]" "<C-Space>";
confirm = mkMappingOption "Confirm [blink.cmp]" "<CR>";
next = mkMappingOption "Next item [blink.cmp]" "<Tab>";
previous = mkMappingOption "Previous item [blink.cmp]" "<S-Tab>";
close = mkMappingOption "Close [blink.cmp]" "<C-e>";
scrollDocsUp = mkMappingOption "Scroll docs up [blink.cmp]" "<C-d>";
scrollDocsDown = mkMappingOption "Scroll docs down [blink.cmp]" "<C-f>";
};
};
}
105 changes: 105 additions & 0 deletions modules/plugins/completion/blink-cmp/config.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
{
lib,
config,
...
}: let
inherit (lib.modules) mkIf mkDefault;
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;
autocompleteCfg = config.vim.autocomplete;
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)})")
autocompleteCfg.sourcePlugins))}
'';
};
};

autocomplete = {
enableSharedCmpSources = true;

blink-cmp.setupOpts = {
sources = {
default = ["lsp" "path" "snippets" "buffer"] ++ (attrNames autocompleteCfg.nvim-cmp.sources);
providers =
mapAttrs (name: _: {
inherit name;
module = "blink.compat.source";
})
autocompleteCfg.nvim-cmp.sources;
};
snippets = mkIf config.vim.snippets.luasnip.enable {
expand = mkLuaInline ''
function(snippet)
return require("luasnip").lsp_expand(snippet)
end
'';
active = mkLuaInline ''
function(filter)
if filter and filter.direction then
return require('luasnip').jumpable(filter.direction)
end
return require('luasnip').in_snippet()
end
'';
jump = mkLuaInline "function(direction) require('luasnip').jump(direction) end";
};

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"
];
};
};
};
};
}
3 changes: 3 additions & 0 deletions modules/plugins/completion/blink-cmp/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
imports = [./blink-cmp.nix ./config.nix];
}
34 changes: 34 additions & 0 deletions modules/plugins/completion/config.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
lib,
config,
...
}: let
inherit (builtins) typeOf tryEval;
inherit (lib.modules) mkIf;
inherit (lib.nvim.attrsets) mapListToAttrs;
cfg = config.vim.autocomplete;

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.enableSharedCmpSources {
startPlugins = ["rtp-nvim"];
lazy.plugins =
mapListToAttrs (package: {
name = getPluginName package;
value = {
inherit package;
lazy = true;
after = ''
local path = vim.fn.globpath(vim.o.packpath, 'pack/*/opt/${getPluginName package}')
require("rtp_nvim").source_after_plugin_dir(path)
'';
};
})
cfg.sourcePlugins;
};
}
4 changes: 4 additions & 0 deletions modules/plugins/completion/default.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{
imports = [
./config.nix
./options.nix

./nvim-cmp
./blink-cmp
];
}
Loading
Loading