treewide: rewrite autocompletion module and related stuff (#404)

* modules/completion: rewrite

* treewide: remove vsnip, add luasnip

* nvim-cmp: add default sorting

* nvim-cmp: load after luasnip

* lib: fix docs for mergelessListOf

* docs: add changelog entires for rewrite

* deprecations: add rewrite deprecations

* nvim-cmp: clarify in format description

* docs: fix option reference in release notes

* treewide: remove reduant `// {default = false;}`s

* luasnip: add missing `{option}` for option reference

* deprecations: add entry for vsnip

* nvim-autopairs: use multiline string

* nvim-dap: use outer attribute
This commit is contained in:
diniamo 2024-10-09 19:50:34 +02:00 committed by GitHub
commit 7dbd1cd8d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 512 additions and 483 deletions

View file

@ -1,5 +1,5 @@
{lib, ...}: let
inherit (lib.modules) mkRemovedOptionModule;
inherit (lib.modules) mkRemovedOptionModule mkRenamedOptionModule;
in {
imports = [
# 2024-06-06
@ -14,5 +14,26 @@ in {
available under `vim.ui.fastaction` as a replacement. Simply remove everything under
`vim.lsp.nvimCodeActionMenu`, and set `vim.ui.fastaction.enable` to `true`.
'')
(mkRemovedOptionModule ["vim" "autopairs" "enable"] ''
vim.autopairs.enable has been removed in favor of per-plugin modules.
You can enable nvim-autopairs with vim.autopairs.nvim-autopairs.enable instead.
'')
(mkRemovedOptionModule ["vim" "autopairs" "type"] ''
vim.autopairs.type has been removed in favor of per-plugin modules.
You can enable nvim-autopairs with vim.autopairs.nvim-autopairs.enable instead.
'')
(mkRemovedOptionModule ["vim" "autocomplete" "enable"] ''
vim.autocomplete.enable has been removed in favor of per-plugin modules.
You can enable nvim-cmp with vim.autocomplete.nvim-cmp.enable instead.
'')
(mkRemovedOptionModule ["vim" "autocomplete" "type"] ''
vim.autocomplete.type has been removed in favor of per-plugin modules.
You can enable nvim-cmp with vim.autocomplete.nvim-cmp.enable instead.
'')
(mkRemovedOptionModule ["vim" "snippets" "vsnip" "enable"] ''
vim.snippets.vsnip.enable has been removed in favor of the more modern luasnip.
'')
(mkRenamedOptionModule ["vim" "lsp" "lspkind" "mode"] ["vim" "lsp" "lspkind" "setupOpts" "mode"])
];
}

View file

@ -34,6 +34,8 @@ in {
"copilot-cmp"
];
vim.autocomplete.nvim-cmp.sources = {copilot = "[Copilot]";};
vim.pluginRC.copilot = entryAnywhere ''
require("copilot").setup(${toLuaObject cfg.setupOpts})

View file

@ -4,16 +4,17 @@
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.trivial) boolToString;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.autopairs;
cfg = config.vim.autopairs.nvim-autopairs;
in {
config = mkIf cfg.enable {
vim.startPlugins = ["nvim-autopairs"];
vim.pluginRC.autopairs = entryAnywhere ''
require("nvim-autopairs").setup({ map_cr = ${boolToString (!config.vim.autocomplete.enable)} })
'';
vim = {
startPlugins = ["nvim-autopairs"];
pluginRC.autopairs = entryAnywhere ''
require('nvim-autopairs').setup(${toLuaObject cfg.setupOpts})
'';
};
};
}

View file

@ -1,21 +1,14 @@
{lib, ...}: let
inherit (lib) mkRemovedOptionModule;
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.types) enum;
inherit (lib.options) mkEnableOption;
inherit (lib.nvim.types) mkPluginSetupOption;
in {
imports = [
(mkRemovedOptionModule ["vim" "autopairs" "nvim-compe"] "nvim-compe is deprecated and no longer suported.")
];
options.vim = {
autopairs = {
enable = mkEnableOption "autopairs" // {default = false;};
type = mkOption {
type = enum ["nvim-autopairs"];
default = "nvim-autopairs";
description = "Set the autopairs type. Options: nvim-autopairs [nvim-autopairs]";
};
};
options.vim.autopairs.nvim-autopairs = {
enable = mkEnableOption "autopairs";
setupOpts = mkPluginSetupOption "nvim-autopairs" {};
};
}

View file

@ -3,246 +3,115 @@
config,
...
}: let
inherit (builtins) toJSON;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.attrsets) attrNames mapAttrsToList;
inherit (lib.strings) concatMapStringsSep concatStringsSep optionalString;
inherit (lib.nvim.binds) addDescriptionsToMappings mkSetLuaBinding;
inherit (lib.nvim.dag) entryAnywhere entryAfter;
inherit (lib.modules) mkIf;
inherit (lib.strings) optionalString;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.binds) addDescriptionsToMappings;
inherit (lib.nvim.dag) entryAfter;
inherit (lib.nvim.lua) toLuaObject;
inherit (builtins) attrNames;
cfg = config.vim.autocomplete;
lspkindEnabled = config.vim.lsp.enable && config.vim.lsp.lspkind.enable;
self = import ./nvim-cmp.nix {inherit lib;};
mappingDefinitions = self.options.vim.autocomplete.mappings;
cfg = config.vim.autocomplete.nvim-cmp;
luasnipEnable = config.vim.snippets.luasnip.enable;
self = import ./nvim-cmp.nix {inherit lib config;};
mappingDefinitions = self.options.vim.autocomplete.nvim-cmp.mappings;
mappings = addDescriptionsToMappings cfg.mappings mappingDefinitions;
builtSources =
concatMapStringsSep
"\n"
(n: "{ name = '${n}'},")
(attrNames cfg.sources);
builtMaps =
concatStringsSep
"\n"
(mapAttrsToList
(n: v:
if v == null
then ""
else "${n} = '${v}',")
cfg.sources);
dagPlacement =
if lspkindEnabled
then entryAfter ["lspkind"]
else entryAnywhere;
in {
config = mkIf cfg.enable {
vim.startPlugins = [
"nvim-cmp"
"cmp-buffer"
"cmp-vsnip"
"cmp-path"
"vim-vsnip"
];
vim = {
startPlugins = [
"nvim-cmp"
"cmp-buffer"
"cmp-path"
];
vim.autocomplete.sources = {
"nvim-cmp" = null;
"vsnip" = "[VSnip]";
"buffer" = "[Buffer]";
"crates" = "[Crates]";
"path" = "[Path]";
"copilot" = "[Copilot]";
};
autocomplete.nvim-cmp.sources = {
nvim-cmp = null;
buffer = "[Buffer]";
path = "[Path]";
};
vim.maps.insert = mkMerge [
(mkSetLuaBinding mappings.complete ''
require('cmp').complete
'')
(let
defaultKeys =
if config.vim.autopairs.enable
then "require('nvim-autopairs').autopairs_cr()"
else "vim.api.nvim_replace_termcodes(${toJSON mappings.confirm.value}, true, false, true)";
in
mkSetLuaBinding mappings.confirm ''
function()
if not require('cmp').confirm({ select = true }) then
vim.fn.feedkeys(${defaultKeys}, 'n')
autocomplete.nvim-cmp.setupOpts = {
sources = map (s: {name = s;}) (attrNames cfg.sources);
# TODO: try to get nvim-cmp to follow global border style
window = mkIf config.vim.ui.borders.enable {
completion = mkLuaInline "cmp.config.window.bordered()";
documentation = mkLuaInline "cmp.config.window.bordered()";
};
formatting.format = cfg.format;
};
pluginRC.nvim-cmp = mkIf cfg.enable (entryAfter ["autopairs" "luasnip"] ''
local luasnip = require("luasnip")
local cmp = require("cmp")
cmp.setup(${toLuaObject cfg.setupOpts})
'');
# `cmp` and `luasnip` are defined above, in the `nvim-cmp` section
autocomplete.nvim-cmp.setupOpts.mapping = {
${mappings.complete.value} = mkLuaInline "cmp.mapping.complete()";
${mappings.close.value} = mkLuaInline "cmp.mapping.abort()";
${mappings.scrollDocsUp.value} = mkLuaInline "cmp.mapping.scroll_docs(-4)";
${mappings.scrollDocsDown.value} = mkLuaInline "cmp.mapping.scroll_docs(4)";
${mappings.confirm.value} = mkLuaInline ''
cmp.mapping(function(fallback)
if cmp.visible() then
${
if luasnipEnable
then ''
if luasnip.expandable() then
luasnip.expand()
else
cmp.confirm({ select = true })
end
''
else "cmp.confirm({ select = true })"
}
else
fallback()
end
end
'')
(mkSetLuaBinding mappings.next ''
function()
local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
end)
'';
local cmp = require('cmp')
${mappings.next.value} = mkLuaInline ''
cmp.mapping(function(fallback)
local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
local feedkey = function(key, mode)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
end
if cmp.visible() then
cmp.select_next_item()
${optionalString luasnipEnable ''
elseif luasnip.locally_jumpable(1) then
luasnip.jump(1)
''}
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end)
'';
if cmp.visible() then
cmp.select_next_item()
elseif vim.fn['vsnip#available'](1) == 1 then
feedkey("<Plug>(vsnip-expand-or-jump)", "")
elseif has_words_before() then
cmp.complete()
else
local termcode = vim.api.nvim_replace_termcodes(${toJSON mappings.next.value}, true, false, true)
vim.fn.feedkeys(termcode, 'n')
end
end
'')
(mkSetLuaBinding mappings.previous ''
function()
local cmp = require('cmp')
local feedkey = function(key, mode)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
end
if cmp.visible() then
cmp.select_prev_item()
elseif vim.fn['vsnip#available'](-1) == 1 then
feedkeys("<Plug>(vsnip-jump-prev)", "")
end
end
'')
(mkSetLuaBinding mappings.close ''
require('cmp').mapping.abort()
'')
(mkSetLuaBinding mappings.scrollDocsUp ''
require('cmp').mapping.scroll_docs(-4)
'')
(mkSetLuaBinding mappings.scrollDocsDown ''
require('cmp').mapping.scroll_docs(4)
'')
];
vim.maps.command = mkMerge [
(mkSetLuaBinding mappings.complete ''
require('cmp').complete
'')
(mkSetLuaBinding mappings.close ''
require('cmp').mapping.close()
'')
(mkSetLuaBinding mappings.scrollDocsUp ''
require('cmp').mapping.scroll_docs(-4)
'')
(mkSetLuaBinding mappings.scrollDocsDown ''
require('cmp').mapping.scroll_docs(4)
'')
];
vim.maps.select = mkMerge [
(mkSetLuaBinding mappings.next ''
function()
local cmp = require('cmp')
local has_words_before = function()
local line, col = unpack(vim.api.nvim_win_get_cursor(0))
return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end
local feedkey = function(key, mode)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
end
if cmp.visible() then
cmp.select_next_item()
elseif vim.fn['vsnip#available'](1) == 1 then
feedkey("<Plug>(vsnip-expand-or-jump)", "")
elseif has_words_before() then
cmp.complete()
else
local termcode = vim.api.nvim_replace_termcodes(${toJSON mappings.next.value}, true, false, true)
vim.fn.feedkeys(termcode, 'n')
end
end
'')
(mkSetLuaBinding mappings.previous ''
function()
local cmp = require('cmp')
local feedkey = function(key, mode)
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
end
if cmp.visible() then
cmp.select_prev_item()
elseif vim.fn['vsnip#available'](-1) == 1 then
feedkeys("<Plug>(vsnip-jump-prev)", "")
end
end
'')
];
# TODO: alternative snippet engines to vsnip
# https://github.com/hrsh7th/nvim-cmp/blob/main/doc/cmp.txt#L82
vim.pluginRC.completion = mkIf (cfg.type == "nvim-cmp") (dagPlacement ''
local nvim_cmp_menu_map = function(entry, vim_item)
-- name for each source
vim_item.menu = ({
${builtMaps}
})[entry.source.name]
return vim_item
end
${optionalString lspkindEnabled ''
lspkind_opts.before = ${cfg.formatting.format}
''}
local cmp = require'cmp'
cmp.setup({
${optionalString config.vim.ui.borders.enable ''
-- explicitly enabled by setting ui.borders.enable = true
-- TODO: try to get nvim-cmp to follow global border style
window = {
completion = cmp.config.window.bordered(),
documentation = cmp.config.window.bordered(),
},
''}
snippet = {
expand = function(args)
vim.fn["vsnip#anonymous"](args.body)
end,
},
sources = {
${builtSources}
},
completion = {
completeopt = 'menu,menuone,noinsert',
${optionalString (!cfg.alwaysComplete) "autocomplete = false"}
},
formatting = {
format =
${
if lspkindEnabled
then "lspkind.cmp_format(lspkind_opts)"
else cfg.formatting.format
},
}
})
${optionalString (config.vim.autopairs.enable && config.vim.autopairs.type == "nvim-autopairs") ''
local cmp_autopairs = require('nvim-autopairs.completion.cmp')
cmp.event:on('confirm_done', cmp_autopairs.on_confirm_done({ map_char = { text = ""} }))
''}
'');
vim.snippets.vsnip.enable =
if (cfg.type == "nvim-cmp")
then true
else config.vim.snippets.vsnip.enable;
${mappings.previous.value} = mkLuaInline ''
cmp.mapping(function(fallback)
if cmp.visible() then
cmp.select_prev_item()
${optionalString luasnipEnable ''
elseif luasnip.locally_jumpable(-1) then
luasnip.jump(-1)
''}
else
fallback()
end
end)
'';
};
};
};
}

View file

@ -1,4 +1,4 @@
_: {
{
imports = [
./config.nix
./nvim-cmp.nix

View file

@ -1,72 +1,103 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption mkOption literalMD;
{
lib,
config,
...
}: let
inherit (lib.options) mkEnableOption mkOption literalExpression literalMD;
inherit (lib.types) str attrsOf nullOr either;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.binds) mkMappingOption;
inherit (lib.types) enum attrsOf nullOr str bool;
inherit (lib.nvim.types) mkPluginSetupOption luaInline mergelessListOf;
inherit (lib.nvim.lua) toLuaObject;
inherit (builtins) isString;
cfg = config.vim.autocomplete.nvim-cmp;
in {
options.vim = {
autocomplete = {
enable = mkEnableOption "autocomplete" // {default = false;};
alwaysComplete = mkOption {
type = bool;
description = "Automatically show completion.";
default = true;
};
mappings = {
complete = mkMappingOption "Complete [nvim-cmp]" "<C-Space>";
confirm = mkMappingOption "Confirm [nvim-cmp]" "<CR>";
next = mkMappingOption "Next item [nvim-cmp]" "<Tab>";
previous = mkMappingOption "Previous item [nvim-cmp]" "<S-Tab>";
close = mkMappingOption "Close [nvim-cmp]" "<C-e>";
scrollDocsUp = mkMappingOption "Scroll docs up [nvim-cmp]" "<C-d>";
scrollDocsDown = mkMappingOption "Scroll docs down [nvim-cmp]" "<C-f>";
};
type = mkOption {
type = enum ["nvim-cmp"];
default = "nvim-cmp";
description = "Set the autocomplete plugin. Options: [nvim-cmp]";
};
sources = mkOption {
options.vim.autocomplete.nvim-cmp = {
enable = mkEnableOption "nvim-cmp";
setupOpts = mkPluginSetupOption "the autocomplete plugin" {
completion.completeopt = mkOption {
type = str;
default = "menu,menuone,noinsert";
description = ''
Attribute set of source names for nvim-cmp.
A comma-separated list of options for completion.
If an attribute set is provided, then the menu value of
`vim_item` in the format will be set to the value (if
utilizing the `nvim_cmp_menu_map` function).
Note: only use a single attribute name per attribute set
'';
type = attrsOf (nullOr str);
default = {};
example = ''
{nvim-cmp = null; buffer = "[Buffer]";}
See `:help completeopt` for the complete list.
'';
};
formatting = {
format = mkOption {
description = ''
The function used to customize the appearance of the completion menu.
sorting.comparators = mkOption {
type = mergelessListOf (either str luaInline);
default = [
"offset"
"exact"
"score"
"kind"
"length"
"sort_text"
];
description = ''
The comparator functions used for sorting completions.
If [](#opt-vim.lsp.lspkind.enable) is true, then the function
will be called before modifications from lspkind.
Default is to call the menu mapping function.
'';
type = str;
default = "nvim_cmp_menu_map";
example = literalMD ''
```lua
function(entry, vim_item)
return vim_item
end
```
'';
};
You can either pass a valid inline lua function
(see `:help cmp-config.sorting.comparators`),
or a string, in which case the builtin comparator with that name will
be used.
'';
apply = map (
c:
if isString c
then mkLuaInline ("cmp.config.compare." + c)
else c
);
};
};
mappings = {
complete = mkMappingOption "Complete [nvim-cmp]" "<C-Space>";
confirm = mkMappingOption "Confirm [nvim-cmp]" "<CR>";
next = mkMappingOption "Next item [nvim-cmp]" "<Tab>";
previous = mkMappingOption "Previous item [nvim-cmp]" "<S-Tab>";
close = mkMappingOption "Close [nvim-cmp]" "<C-e>";
scrollDocsUp = mkMappingOption "Scroll docs up [nvim-cmp]" "<C-d>";
scrollDocsDown = mkMappingOption "Scroll docs down [nvim-cmp]" "<C-f>";
};
format = mkOption {
type = luaInline;
default = mkLuaInline ''
function(entry, vim_item)
vim_item.menu = (${toLuaObject cfg.sources})[entry.source.name]
return vim_item
end
'';
defaultText = literalMD ''
```lua
function(entry, vim_item)
vim_item.menu = (''${toLuaObject config.vim.autocomplete.nvim-cmp.sources})[entry.source.name]
return vim_item
end
```
'';
description = ''
The function used to customize the completion menu entires. This is
outside of `setupOpts` to allow for an easier integration with
lspkind.nvim.
See `:help cmp-config.formatting.format`.
'';
};
sources = mkOption {
type = attrsOf (nullOr str);
default = {};
description = "The list of sources used by nvim-cmp";
example = literalExpression ''
{
nvim-cmp = null;
buffer = "[Buffer]";
}
'';
};
};
}

View file

@ -16,57 +16,61 @@
in {
config = mkMerge [
(mkIf cfg.enable {
vim.startPlugins = ["nvim-dap"];
vim = {
startPlugins = ["nvim-dap"];
vim.pluginRC =
{
# TODO customizable keymaps
nvim-dap = entryAnywhere ''
local dap = require("dap")
vim.fn.sign_define("DapBreakpoint", { text = "🛑", texthl = "ErrorMsg", linehl = "", numhl = "" })
'';
}
// mapAttrs (_: v: (entryAfter ["nvim-dap"] v)) cfg.sources;
pluginRC =
{
# TODO customizable keymaps
nvim-dap = entryAnywhere ''
local dap = require("dap")
vim.fn.sign_define("DapBreakpoint", { text = "🛑", texthl = "ErrorMsg", linehl = "", numhl = "" })
'';
}
// mapAttrs (_: v: (entryAfter ["nvim-dap"] v)) cfg.sources;
vim.maps.normal = mkMerge [
(mkSetLuaBinding mappings.continue "require('dap').continue")
(mkSetLuaBinding mappings.restart "require('dap').restart")
(mkSetLuaBinding mappings.terminate "require('dap').terminate")
(mkSetLuaBinding mappings.runLast "require('dap').run_last")
maps.normal = mkMerge [
(mkSetLuaBinding mappings.continue "require('dap').continue")
(mkSetLuaBinding mappings.restart "require('dap').restart")
(mkSetLuaBinding mappings.terminate "require('dap').terminate")
(mkSetLuaBinding mappings.runLast "require('dap').run_last")
(mkSetLuaBinding mappings.toggleRepl "require('dap').repl.toggle")
(mkSetLuaBinding mappings.hover "require('dap.ui.widgets').hover")
(mkSetLuaBinding mappings.toggleBreakpoint "require('dap').toggle_breakpoint")
(mkSetLuaBinding mappings.toggleRepl "require('dap').repl.toggle")
(mkSetLuaBinding mappings.hover "require('dap.ui.widgets').hover")
(mkSetLuaBinding mappings.toggleBreakpoint "require('dap').toggle_breakpoint")
(mkSetLuaBinding mappings.runToCursor "require('dap').run_to_cursor")
(mkSetLuaBinding mappings.stepInto "require('dap').step_into")
(mkSetLuaBinding mappings.stepOut "require('dap').step_out")
(mkSetLuaBinding mappings.stepOver "require('dap').step_over")
(mkSetLuaBinding mappings.stepBack "require('dap').step_back")
(mkSetLuaBinding mappings.runToCursor "require('dap').run_to_cursor")
(mkSetLuaBinding mappings.stepInto "require('dap').step_into")
(mkSetLuaBinding mappings.stepOut "require('dap').step_out")
(mkSetLuaBinding mappings.stepOver "require('dap').step_over")
(mkSetLuaBinding mappings.stepBack "require('dap').step_back")
(mkSetLuaBinding mappings.goUp "require('dap').up")
(mkSetLuaBinding mappings.goDown "require('dap').down")
];
(mkSetLuaBinding mappings.goUp "require('dap').up")
(mkSetLuaBinding mappings.goDown "require('dap').down")
];
};
})
(mkIf (cfg.enable && cfg.ui.enable) {
vim.startPlugins = ["nvim-dap-ui" "nvim-nio"];
vim = {
startPlugins = ["nvim-dap-ui" "nvim-nio"];
vim.pluginRC.nvim-dap-ui = entryAfter ["nvim-dap"] (''
local dapui = require("dapui")
dapui.setup()
''
+ optionalString cfg.ui.autoStart ''
dap.listeners.after.event_initialized["dapui_config"] = function()
dapui.open()
end
dap.listeners.before.event_terminated["dapui_config"] = function()
dapui.close()
end
dap.listeners.before.event_exited["dapui_config"] = function()
dapui.close()
end
'');
vim.maps.normal = mkSetLuaBinding mappings.toggleDapUI "require('dapui').toggle";
pluginRC.nvim-dap-ui = entryAfter ["nvim-dap"] (''
local dapui = require("dapui")
dapui.setup()
''
+ optionalString cfg.ui.autoStart ''
dap.listeners.after.event_initialized["dapui_config"] = function()
dapui.open()
end
dap.listeners.before.event_terminated["dapui_config"] = function()
dapui.close()
end
dap.listeners.before.event_exited["dapui_config"] = function()
dapui.close()
end
'');
maps.normal = mkSetLuaBinding mappings.toggleDapUI "require('dapui').toggle";
};
})
];
}

View file

@ -9,7 +9,7 @@
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.strings) optionalString;
inherit (lib.trivial) boolToString;
inherit (lib.lists) isList optionals;
inherit (lib.lists) isList;
inherit (lib.types) bool package str listOf either enum;
inherit (lib.nvim.types) mkGrammarOption;
inherit (lib.nvim.lua) expToLua;
@ -101,7 +101,7 @@ in {
vim = {
startPlugins = ["crates-nvim"];
lsp.null-ls.enable = mkIf cfg.crates.codeActions true;
autocomplete.sources = {"crates" = "[Crates]";};
autocomplete.nvim-cmp.sources = {crates = "[Crates]";};
pluginRC.rust-crates = entryAnywhere ''
require('crates').setup {
null_ls = {

View file

@ -11,7 +11,7 @@
inherit (lib.nvim.binds) addDescriptionsToMappings;
cfg = config.vim.lsp;
usingNvimCmp = config.vim.autocomplete.enable && config.vim.autocomplete.type == "nvim-cmp";
usingNvimCmp = config.vim.autocomplete.nvim-cmp.enable;
self = import ./module.nix {inherit config lib pkgs;};
mappingDefinitions = self.options.vim.lsp.mappings;
@ -25,7 +25,7 @@ in {
vim = {
startPlugins = optional usingNvimCmp "cmp-nvim-lsp";
autocomplete.sources = {"nvim_lsp" = "[LSP]";};
autocomplete.nvim-cmp.sources = {nvim_lsp = "[LSP]";};
pluginRC.lsp-setup = ''
vim.g.formatsave = ${boolToString cfg.formatOnSave};

View file

@ -3,18 +3,32 @@
lib,
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.modules) mkIf mkForce;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.lua) toLuaObject;
cfg = config.vim.lsp;
cfg = config.vim.lsp.lspkind;
in {
config = mkIf (cfg.enable && cfg.lspkind.enable) {
vim.startPlugins = ["lspkind"];
vim.pluginRC.lspkind = entryAnywhere ''
local lspkind = require'lspkind'
local lspkind_opts = {
mode = '${cfg.lspkind.mode}'
config = mkIf cfg.enable {
assertions = [
{
assertion = config.vim.autocomplete.nvim-cmp.enable;
message = ''
While lspkind supports Neovim's native lsp upstream, using that over
nvim-cmp isn't recommended, nor supported by nvf.
Please migrate to nvim-cmp if you want to use lspkind.
'';
}
'';
];
vim = {
startPlugins = ["lspkind"];
lsp.lspkind.setupOpts.before = config.vim.autocomplete.nvim-cmp.format;
autocomplete.nvim-cmp.setupOpts.formatting.format = mkForce (mkLuaInline ''
require("lspkind").cmp_format(${toLuaObject cfg.setupOpts})
'');
};
};
}

View file

@ -1,16 +1,22 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.types) enum;
inherit (lib.types) enum nullOr;
inherit (lib.nvim.types) mkPluginSetupOption luaInline;
in {
options.vim.lsp = {
lspkind = {
enable = mkEnableOption "vscode-like pictograms for lsp [lspkind]";
options.vim.lsp.lspkind = {
enable = mkEnableOption "vscode-like pictograms for lsp [lspkind]";
setupOpts = mkPluginSetupOption "lspkind.nvim" {
mode = mkOption {
description = "Defines how annotations are shown";
type = enum ["text" "text_symbol" "symbol_text" "symbol"];
default = "symbol_text";
};
before = mkOption {
description = "The function that will be called before lspkind's modifications are applied";
type = nullOr luaInline;
default = null;
};
};
};
}

View file

@ -45,10 +45,10 @@ in {
completion = {
nvim_cmp = mkOption {
# if using nvim-cmp, otherwise set to false
# If using nvim-cmp, otherwise set to false
type = bool;
description = "If using nvim-cmp, otherwise set to false";
default = config.vim.autocomplete.type == "nvim-cmp";
default = config.vim.autocomplete.nvim-cmp.enable;
};
};
};

View file

@ -1,5 +1,5 @@
{
imports = [
./vsnip
./luasnip
];
}

View file

@ -0,0 +1,17 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
cfg = config.vim.snippets.luasnip;
in {
config = mkIf cfg.enable {
vim = {
startPlugins = ["luasnip" "cmp-luasnip"] ++ cfg.providers;
autocomplete.nvim-cmp.sources = {luasnip = "[LuaSnip]";};
pluginRC.luasnip = cfg.loaders;
};
};
}

View file

@ -0,0 +1,6 @@
{
imports = [
./luasnip.nix
./config.nix
];
}

View file

@ -0,0 +1,36 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption mkOption literalExpression literalMD;
inherit (lib.types) listOf lines;
inherit (lib.nvim.types) pluginType;
in {
options.vim.snippets.luasnip = {
enable = mkEnableOption "luasnip";
providers = mkOption {
type = listOf pluginType;
default = ["friendly-snippets"];
description = ''
The snippet provider packages.
::: {.note}
These are simply appended to {option} `vim.startPlugins`.
:::
'';
example = literalExpression "[\"vimPlugins.vim-snippets\"]";
};
loaders = mkOption {
type = lines;
default = "require('luasnip.loaders.from_vscode').lazy_load()";
defaultText = literalMD ''
```lua
require('luasnip.loaders.from_vscode').lazy_load()
```
'';
description = "Lua code used to load snippet providers.";
example = literalMD ''
```lua
require("luasnip.loaders.from_snipmate").lazy_load()
```
'';
};
};
}

View file

@ -1,13 +0,0 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
cfg = config.vim.snippets.vsnip;
in {
config = mkIf cfg.enable {
vim.startPlugins = ["vim-vsnip"];
};
}

View file

@ -1,5 +0,0 @@
{
imports = [
./vsnip.nix
];
}

View file

@ -1,7 +0,0 @@
{lib, ...}: let
inherit (lib.options) mkEnableOption;
in {
options.vim.snippets.vsnip = {
enable = mkEnableOption "vim-vsnip: snippet LSP/VSCode's format";
};
}

View file

@ -4,10 +4,11 @@
...
}: let
inherit (lib.options) mkOption;
inherit (lib.attrsets) attrNames listToAttrs;
inherit (lib.attrsets) attrNames;
inherit (lib.strings) hasPrefix;
inherit (lib.types) bool lines enum;
inherit (lib.modules) mkIf;
inherit (lib.nvim.attrsets) mapListToAttrs;
inherit (lib.nvim.dag) entryBefore;
inherit (lib.nvim.types) hexColor;
@ -17,7 +18,8 @@
};
numbers = ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F"];
base16Options = listToAttrs (map (n: {
base16Options =
mapListToAttrs (n: {
name = "base0${n}";
value = mkOption {
description = "The base0${n} color to use";
@ -28,7 +30,7 @@
else "#${v}";
};
})
numbers);
numbers;
in {
options.vim.theme = {
enable = mkOption {

View file

@ -11,7 +11,7 @@
inherit (lib.nvim.dag) entryBefore entryAfter;
cfg = config.vim.treesitter;
usingNvimCmp = config.vim.autocomplete.enable && config.vim.autocomplete.type == "nvim-cmp";
usingNvimCmp = config.vim.autocomplete.nvim-cmp.enable;
self = import ./treesitter.nix {inherit pkgs lib;};
mappingDefinitions = self.options.vim.treesitter.mappings;
@ -21,7 +21,7 @@ in {
vim = {
startPlugins = ["nvim-treesitter"] ++ optional usingNvimCmp "cmp-treesitter";
autocomplete.sources = {"treesitter" = "[Treesitter]";};
autocomplete.nvim-cmp.sources = {treesitter = "[Treesitter]";};
treesitter.grammars = optionals cfg.addDefaultGrammars cfg.defaultGrammars;
maps = {

View file

@ -21,7 +21,7 @@ in {
mkBool true "override the lsp markdown formatter with Noice";
"cmp.entry.get_documentation" =
mkBool (config.vim.autocomplete.type == "nvim-cmp") "override cmp documentation with Noice";
mkBool config.vim.autocomplete.nvim-cmp.enable "override cmp documentation with Noice";
};
signature = {

View file

@ -4,7 +4,7 @@
...
}: let
inherit (builtins) map mapAttrs filter;
inherit (lib.attrsets) mapAttrsToList filterAttrs;
inherit (lib.attrsets) mapAttrsToList;
inherit (lib.strings) concatLines concatMapStringsSep;
inherit (lib.trivial) showWarnings;
inherit (lib.generators) mkLuaInline;