feat: refactor and separate LSP/language configurations

This commit is contained in:
NotAShelf 2023-04-17 23:27:27 +03:00
parent 7a71f06763
commit 6b512f132a
No known key found for this signature in database
GPG key ID: F0D14CCB5ED5AA22
30 changed files with 1266 additions and 522 deletions

View file

@ -25,25 +25,23 @@ inputs: let
}; };
}; };
vim.lsp = { vim.languages = {
enable = true; enableLSP = true;
formatOnSave = true; enableFormat = true;
lightbulb.enable = true; enableTreesitter = true;
lspsaga.enable = false; enableExtraDiagnostics = true;
nvimCodeActionMenu.enable = true;
trouble.enable = true; nix.enable = true;
lspSignature.enable = true;
rust.enable = isMaximal;
python = isMaximal;
clang.enable = isMaximal; clang.enable = isMaximal;
sql = isMaximal; sql.enable = isMaximal;
ts = isMaximal; rust = {
go = isMaximal; enable = isMaximal;
zig.enable = isMaximal; crates.enable = true;
nix = {
enable = true;
formatter = "alejandra";
}; };
ts.enable = isMaximal;
go.enable = isMaximal;
zig.enable = isMaximal;
python.enable = isMaximal;
}; };
vim.visuals = { vim.visuals = {
@ -101,24 +99,14 @@ inputs: let
nvimBufferline.enable = true; nvimBufferline.enable = true;
}; };
vim.treesitter = { vim.treesitter.context.enable = true;
enable = true;
context.enable = true;
};
vim.binds = { vim.binds = {
whichKey.enable = true; whichKey.enable = true;
cheatsheet.enable = true; cheatsheet.enable = true;
}; };
vim.telescope = { vim.telescope.enable = true;
enable = true;
};
vim.markdown = {
enable = true;
glow.enable = true;
};
vim.git = { vim.git = {
enable = true; enable = true;

View file

@ -49,7 +49,6 @@
... ...
}: { }: {
devShells.default = pkgs.mkShell {nativeBuildInputs = [config.packages.nix];}; devShells.default = pkgs.mkShell {nativeBuildInputs = [config.packages.nix];};
}; };
}; };

View file

@ -2,4 +2,5 @@
dag = import ./dag.nix {inherit lib;}; dag = import ./dag.nix {inherit lib;};
booleans = import ./booleans.nix {inherit lib;}; booleans = import ./booleans.nix {inherit lib;};
types = import ./types {inherit lib;}; types = import ./types {inherit lib;};
languages = import ./languages.nix {inherit lib;};
} }

25
lib/languages.nix Normal file
View file

@ -0,0 +1,25 @@
# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/booleans.nix
{lib}: {
# Converts a boolean to a yes/no string. This is used in lots of
# configuration formats.
diagnosticsToLua = {
lang,
config,
diagnostics,
}:
lib.listToAttrs
(map (v: let
type =
if builtins.isString v
then v
else builtins.getAttr v.type;
package =
if builtins.isString v
then diagnostics.${type}.package
else v.package;
in {
name = "${lang}-diagnostics-${type}";
value = diagnostics.${type}.nullConfig package;
})
config);
}

View file

@ -1,7 +1,9 @@
{lib}: let {lib}: let
typesDag = import ./dag.nix {inherit lib;}; typesDag = import ./dag.nix {inherit lib;};
typesPlugin = import ./plugins.nix {inherit lib;}; typesPlugin = import ./plugins.nix {inherit lib;};
typesLanguage = import ./languages.nix {inherit lib;};
in { in {
inherit (typesDag) dagOf; inherit (typesDag) dagOf;
inherit (typesPlugin) pluginsOpt; inherit (typesPlugin) pluginsOpt;
inherit (typesLanguage) diagnostics;
} }

26
lib/types/languages.nix Normal file
View file

@ -0,0 +1,26 @@
{lib}:
with lib; let
diagnosticSubmodule = {...}: {
options = {
type = mkOption {
description = "Type of diagnostic to enable";
type = attrNames diagnostics;
};
package = mkOption {
description = "Diagnostics package";
type = types.package;
};
};
};
in {
diagnostics = {
langDesc,
diagnostics,
defaultDiagnostics,
}:
mkOption {
description = "List of ${langDesc} diagnostics to enable";
type = with types; listOf (either (enum (attrNames diagnostics)) (submodule diagnosticSubmodule));
default = defaultDiagnostics;
};
}

View file

@ -1,4 +1,5 @@
{ {
pkgs,
lib, lib,
config, config,
... ...
@ -6,15 +7,22 @@
with lib; with lib;
with builtins; let with builtins; let
cfg = config.vim.autocomplete; cfg = config.vim.autocomplete;
builtSources =
concatMapStringsSep "\n" (x: "{ name = '${x}'},") cfg.sources;
in { in {
config = mkIf cfg.enable { config = mkIf cfg.enable {
vim.startPlugins = [ vim.startPlugins = [
"vim-vsnip"
"nvim-cmp" "nvim-cmp"
"cmp-buffer" "cmp-buffer"
"cmp-vsnip" "cmp-vsnip"
"cmp-path" "cmp-path"
"cmp-treesitter" ];
vim.autocomplete.sources = [
"nvim-cmp"
"vsnip"
"buffer"
"path"
]; ];
vim.luaConfigRC.completion = mkIf (cfg.type == "nvim-cmp") (nvim.dag.entryAnywhere '' vim.luaConfigRC.completion = mkIf (cfg.type == "nvim-cmp") (nvim.dag.entryAnywhere ''
@ -35,12 +43,7 @@ in {
end, end,
}, },
sources = { sources = {
${optionalString (config.vim.lsp.enable) "{ name = 'nvim_lsp' },"} ${builtSources}
${optionalString (config.vim.lsp.rust.enable) "{ name = 'crates' },"}
{ name = 'vsnip' },
{ name = 'treesitter' },
{ name = 'path' },
{ name = 'buffer' },
}, },
mapping = { mapping = {
['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }), ['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),

View file

@ -1,16 +1,21 @@
{ {
pkgs,
lib, lib,
config, config,
... ...
}: }:
with lib; with lib;
with builtins; { with builtins; let
cfg = config.vim.autocomplete;
builtSources =
concatMapStringsSep "\n" (x: "{ name = '${x}'},") cfg.sources;
in {
options.vim = { options.vim = {
autocomplete = { autocomplete = {
enable = mkOption { enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
description = "Enable autocomplete via nvim-cmp"; description = "enable autocomplete";
}; };
type = mkOption { type = mkOption {
@ -18,6 +23,12 @@ with builtins; {
default = "nvim-cmp"; default = "nvim-cmp";
description = "Set the autocomplete plugin. Options: [nvim-cmp]"; description = "Set the autocomplete plugin. Options: [nvim-cmp]";
}; };
sources = mkOption {
description = "List of source names for nvim-cmp";
type = with types; listOf str;
default = [];
};
}; };
}; };
} }

View file

@ -0,0 +1,96 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.languages.clang;
defaultServer = "ccls";
servers = {
ccls = {
package = pkgs.ccls;
lspConfig = ''
lspconfig.ccls.setup{
capabilities = capabilities;
on_attach=default_on_attach;
cmd = {"${pkgs.ccls}/bin/ccls"};
${optionalString (cfg.lsp.opts != null) "init_options = ${cfg.lsp.cclsOpts}"}
}
'';
};
};
in {
options.vim.languages.clang = {
enable = mkEnableOption "C/C++ language support";
cHeader = mkOption {
description = ''
C syntax for headers. Can fix treesitter errors, see:
https://www.reddit.com/r/neovim/comments/orfpcd/question_does_the_c_parser_from_nvimtreesitter/
'';
type = types.bool;
default = false;
};
treesitter = {
enable = mkOption {
description = "Enable C/C++ treesitter";
type = types.bool;
default = config.vim.languages.enableTreesitter;
};
cPackage = mkOption {
description = "C treesitter grammar to use";
type = types.package;
default = pkgs.vimPlugins.nvim-treesitter.builtGrammars.c;
};
cppPackage = mkOption {
description = "C++ treesitter grammar to use";
type = types.package;
default = pkgs.vimPlugins.nvim-treesitter.builtGrammars.cpp;
};
};
lsp = {
enable = mkOption {
description = "Enable clang LSP support";
type = types.bool;
default = config.vim.languages.enableLSP;
};
server = mkOption {
description = "The clang LSP server to use";
type = with types; enum (attrNames servers);
default = defaultServer;
};
package = mkOption {
description = "clang LSP server package";
type = types.package;
default = servers.${cfg.lsp.server}.package;
};
opts = mkOption {
description = "Options to pass to clang LSP server";
type = with types; nullOr str;
default = null;
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.cHeader {
vim.configRC.c-header = nvim.dag.entryAnywhere "let g:c_syntax_for_h = 1";
})
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.cPackage cfg.treesitter.cppPackage];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.clang-lsp = servers.${cfg.lsp.server}.lspConfig;
})
]);
}

View file

@ -0,0 +1,27 @@
{lib, ...}:
with lib; let
mkEnable = desc:
mkOption {
description = "Turn on ${desc} for enabled langauges by default";
type = types.bool;
default = false;
};
in {
imports = [
./clang.nix
./go.nix
./nix.nix
./python.nix
./rust.nix
./sql.nix
./ts.nix
./zig.nix
];
options.vim.languages = {
enableLSP = mkEnable "LSP";
enableTreesitter = mkEnable "treesitter";
enableFormat = mkEnable "formatting";
enableExtraDiagnostics = mkEnable "extra diagnostics";
};
}

71
modules/languages/go.nix Normal file
View file

@ -0,0 +1,71 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.languages.go;
defaultServer = "gopls";
servers = {
gopls = {
package = pkgs.gopls;
lspConfig = ''
lspconfig.gopls.setup {
capabilities = capabilities;
on_attach = default_on_attach;
cmd = {"${cfg.lsp.package}/bin/gopls", "serve"},
}
'';
};
};
in {
options.vim.languages.go = {
enable = mkEnableOption "Go language support";
treesitter = {
enable = mkOption {
description = "Enable Go treesitter";
type = types.bool;
default = config.vim.languages.enableTreesitter;
};
package = mkOption {
description = "Go treesitter grammar to use";
type = types.package;
default = pkgs.vimPlugins.nvim-treesitter.builtGrammars.go;
};
};
lsp = {
enable = mkOption {
description = "Enable Go LSP support";
type = types.bool;
default = config.vim.languages.enableLSP;
};
server = mkOption {
description = "Go LSP server to use";
type = with types; enum (attrNames servers);
default = defaultServer;
};
package = mkOption {
description = "Go LSP server package";
type = types.package;
default = servers.${cfg.lsp.server}.package;
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.go-lsp = servers.${cfg.lsp.server}.lspConfig;
})
]);
}

161
modules/languages/nix.nix Normal file
View file

@ -0,0 +1,161 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.languages.nix;
useFormat = "on_attach = default_on_attatch";
noFormat = "on_attach = attach_keymaps";
defaultServer = "nil";
servers = {
rnix = {
package = pkgs.rnix-lsp;
internalFormatter = true;
lspConfig = ''
lspconfig.rnix.setup{
capabilities = capabilities,
${
if (cfg.format.enable && cfg.format.type == "nixpkgs-fmt")
then useFormat
else noFormat
},
cmd = {"${cfg.lsp.package}/bin/rnix-lsp"},
}
'';
};
nil = {
package = pkgs.nil;
internalFormatter = cfg.format.type != "nixpkgs-fmt";
lspConfig = ''
lspconfig.nil_ls.setup{
capabilities = capabilities,
${
if cfg.format.enable
then useFormat
else noFormat
},
cmd = {"${cfg.lsp.package}/bin/nil"},
${optionalString cfg.format.enable ''
settings = {
["nil"] = {
${optionalString (cfg.format.type == "alejandra")
''
formatting = {
command = {"${cfg.format.package}/bin/alejandra", "--quiet"},
},
''}
${optionalString (cfg.format.type == "nixpkgs-fmt")
''
formatting = {
command = {"${cfg.format.package}/bin/nixpkgs-fmt"},
},
''}
''}
},
};
}
'';
};
};
defaultFormat = "alejandra";
formats = {
alejandra = {
package = pkgs.alejandra;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.alejandra.with({
command = "${cfg.format.package}/bin/alejandra"
})
)
'';
};
nixpkgs-fmt = {
package = pkgs.nixpkgs-fmt;
# Never need to use null-ls for nixpkgs-fmt
};
};
in {
options.vim.languages.nix = {
enable = mkEnableOption "Nix language support";
treesitter = {
enable = mkOption {
description = "Enable Nix treesitter";
type = types.bool;
default = config.vim.languages.enableTreesitter;
};
package = mkOption {
description = "Nix treesitter grammar to use";
type = types.package;
default = pkgs.vimPlugins.nvim-treesitter.builtGrammars.nix;
};
};
lsp = {
enable = mkOption {
description = "Enable Nix LSP support";
type = types.bool;
default = config.vim.languages.enableLSP;
};
server = mkOption {
description = "Nix LSP server to use";
type = types.str;
default = defaultServer;
};
package = mkOption {
description = "Nix LSP server package";
type = types.package;
default = servers.${cfg.lsp.server}.package;
};
};
format = {
enable = mkOption {
description = "Enable Nix formatting";
type = types.bool;
default = config.vim.languages.enableFormat;
};
type = mkOption {
description = "Nix formatter to use";
type = with types; enum (attrNames formats);
default = defaultFormat;
};
package = mkOption {
description = "Nix formatter package";
type = types.package;
default = formats.${cfg.format.type}.package;
};
};
};
config = mkIf cfg.enable (mkMerge [
{
vim.configRC.nix = nvim.dag.entryAnywhere ''
autocmd filetype nix setlocal tabstop=2 shiftwidth=2 softtabstop=2
'';
}
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.nix-lsp = servers.${cfg.lsp.server}.lspConfig;
})
(mkIf (cfg.format.enable && !servers.${cfg.lsp.server}.internalFormatter) {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.nix-format = formats.${cfg.format.type}.nullConfig;
})
]);
}

View file

@ -0,0 +1,108 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.languages.python;
defaultServer = "pyright";
servers = {
pyright = {
package = pkgs.nodePackages.pyright;
lspConfig = ''
lspconfig.pyright.setup{
capabilities = capabilities;
on_attach = default_on_attach;
cmd = {"${cfg.lsp.package}/bin/pyright-langserver", "--stdio"}
}
'';
};
};
defaultFormat = "black";
formats = {
black = {
package = pkgs.black;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.black.with({
command = "${cfg.format.package}/bin/black",
})
)
'';
};
};
in {
options.vim.languages.python = {
enable = mkEnableOption "Python language support";
treesitter = {
enable = mkOption {
description = "Enable Python treesitter";
type = types.bool;
default = config.vim.languages.enableTreesitter;
};
package = mkOption {
description = "Python treesitter grammar to use";
type = types.package;
default = pkgs.vimPlugins.nvim-treesitter.builtGrammars.python;
};
};
lsp = {
enable = mkOption {
description = "Enable Python LSP support";
type = types.bool;
default = config.vim.languages.enableLSP;
};
server = mkOption {
description = "Python LSP server to use";
type = with types; enum (attrNames servers);
default = defaultServer;
};
package = mkOption {
description = "Python LSP server package";
type = types.package;
default = servers.${cfg.lsp.server}.package;
};
};
format = {
enable = mkOption {
description = "Enable Python formatting";
type = types.bool;
default = config.vim.languages.enableFormat;
};
type = mkOption {
description = "Python formatter to use";
type = with types; enum (attrNames formats);
default = defaultFormat;
};
package = mkOption {
description = "Python formatter package";
type = types.package;
default = formats.${cfg.format.type}.package;
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.python-lsp = servers.${cfg.lsp.server}.lspConfig;
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.python-format = formats.${cfg.format.type}.nullConfig;
})
]);
}

113
modules/languages/rust.nix Normal file
View file

@ -0,0 +1,113 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.languages.rust;
in {
options.vim.languages.rust = {
enable = mkEnableOption "Rust language support";
treesitter = {
enable = mkOption {
description = "Enable Rust treesitter";
type = types.bool;
default = config.vim.languages.enableTreesitter;
};
package = mkOption {
description = "Rust treesitter grammar to use";
type = types.package;
default = pkgs.vimPlugins.nvim-treesitter.builtGrammars.rust;
};
};
crates = {
enable = mkEnableOption "crates-nvim, tools for managing dependencies";
codeActions = mkOption {
description = "Enable code actions through null-ls";
type = types.bool;
default = true;
};
};
lsp = {
enable = mkOption {
description = "Rust LSP support (rust-analyzer with extra tools)";
type = types.bool;
default = config.vim.languages.enableLSP;
};
package = mkOption {
description = "rust-analyzer package";
type = types.package;
default = pkgs.rust-analyzer;
};
opts = mkOption {
description = "Options to pass to rust analyzer";
type = types.str;
default = "";
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.crates.enable {
vim.lsp.null-ls.enable = mkIf cfg.crates.codeActions true;
vim.startPlugins = ["crates-nvim"];
vim.autocomplete.sources = ["crates"];
vim.luaConfigRC.rust-crates = nvim.dag.entryAnywhere ''
require('crates').setup {
null_ls = {
enabled = ${boolToString cfg.crates.codeActions},
name = "crates.nvim",
}
}
'';
})
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.startPlugins = ["rust-tools"];
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.rust-lsp = ''
local rt = require('rust-tools')
rust_on_attach = function(client, bufnr)
default_on_attach(client, bufnr)
local opts = { noremap=true, silent=true, buffer = bufnr }
vim.keymap.set("n", "<leader>ris", rt.inlay_hints.set, opts)
vim.keymap.set("n", "<leader>riu", rt.inlay_hints.unset, opts)
vim.keymap.set("n", "<leader>rr", rt.runnables.runnables, opts)
vim.keymap.set("n", "<leader>rp", rt.parent_module.parent_module, opts)
vim.keymap.set("n", "<leader>rm", rt.expand_macro.expand_macro, opts)
vim.keymap.set("n", "<leader>rc", rt.open_cargo_toml.open_cargo_toml, opts)
vim.keymap.set("n", "<leader>rg", function() rt.crate_graph.view_crate_graph("x11", nil) end, opts)
end
local rustopts = {
tools = {
autoSetHints = true,
hover_with_actions = false,
inlay_hints = {
only_current_line = false,
}
},
server = {
capabilities = capabilities,
on_attach = rust_on_attach,
cmd = {"${cfg.lsp.package}/bin/rust-analyzer"},
settings = {
${cfg.lsp.opts}
}
}
}
rt.setup(rustopts)
'';
})
]);
}

160
modules/languages/sql.nix Normal file
View file

@ -0,0 +1,160 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.languages.sql;
sqlfluffDefault = pkgs.sqlfluff;
defaultServer = "sqls";
servers = {
sqls = {
package = pkgs.sqls;
lspConfig = ''
lspconfig.sqls.setup {
on_attach = function(client)
client.server_capabilities.execute_command = true
on_attach_keymaps(client, bufnr)
require'sqls'.setup{}
end,
cmd = { "${cfg.lsp.package}/bin/sqls", "-config", string.format("%s/config.yml", vim.fn.getcwd()) }
}
'';
};
};
defaultFormat = "sqlfluff";
formats = {
sqlfluff = {
package = sqlfluffDefault;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.sqlfluff.with({
command = "${cfg.format.package}/bin/sqlfluff",
extra_args = {"--dialect", "${cfg.dialect}"}
})
)
'';
};
};
defaultDiagnostics = ["sqlfluff"];
diagnostics = {
sqlfluff = {
package = sqlfluffDefault;
nullConfig = pkg: ''
table.insert(
ls_sources,
null_ls.builtins.diagnostics.sqlfluff.with({
command = "${pkg}/bin/sqlfluff",
extra_args = {"--dialect", "${cfg.dialect}"}
})
)
'';
};
};
in {
options.vim.languages.sql = {
enable = mkEnableOption "SQL language support";
dialect = mkOption {
description = "SQL dialect for sqlfluff (if used)";
type = types.str;
default = "ansi";
};
treesitter = {
enable = mkOption {
description = "Enable SQL treesitter";
type = types.bool;
default = config.vim.languages.enableTreesitter;
};
package = mkOption {
description = "SQL treesitter grammar to use";
type = types.package;
default = pkgs.vimPlugins.nvim-treesitter.builtGrammars.sql;
};
};
lsp = {
enable = mkOption {
description = "Enable SQL LSP support";
type = types.bool;
default = config.vim.languages.enableLSP;
};
server = mkOption {
description = "SQL LSP server to use";
type = with types; enum (attrNames servers);
default = defaultServer;
};
package = mkOption {
description = "SQL LSP server package";
type = types.package;
default = servers.${cfg.lsp.server}.package;
};
};
format = {
enable = mkOption {
description = "Enable SQL formatting";
type = types.bool;
default = config.vim.languages.enableFormat;
};
type = mkOption {
description = "SQL formatter to use";
type = with types; enum (attrNames formats);
default = defaultFormat;
};
package = mkOption {
description = "SQL formatter package";
type = types.package;
default = formats.${cfg.format.type}.package;
};
};
extraDiagnostics = {
enable = mkOption {
description = "Enable extra SQL diagnostics";
type = types.bool;
default = config.vim.languages.enableExtraDiagnostics;
};
types = lib.nvim.types.diagnostics {
langDesc = "SQL";
inherit diagnostics;
inherit defaultDiagnostics;
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.startPlugins = ["sqls-nvim"];
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.sql-lsp = servers.${cfg.lsp.server}.lspConfig;
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources."sql-format" = formats.${cfg.format.type}.nullConfig;
})
(mkIf cfg.extraDiagnostics.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources = lib.nvim.languages.diagnosticsToLua {
lang = "sql";
config = cfg.extraDiagnostics.types;
inherit diagnostics;
};
})
]);
}

153
modules/languages/ts.nix Normal file
View file

@ -0,0 +1,153 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.languages.ts;
defaultServer = "tsserver";
servers = {
tsserver = {
package = pkgs.nodePackages.typescript-language-server;
lspConfig = ''
lspconfig.tsserver.setup {
capabilities = capabilities;
on_attach = attach_keymaps,
cmd = { "${cfg.lsp.package}/bin/typescript-language-server", "--stdio" }
}
'';
};
};
# TODO: specify packages
defaultFormat = "prettier";
formats = {
prettier = {
package = pkgs.nodePackages.prettier;
nullConfig = ''
table.insert(
ls_sources,
null_ls.builtins.formatting.prettier.with({
command = "${cfg.format.package}/bin/prettier",
})
)
'';
};
};
# TODO: specify packages
defaultDiagnostics = ["eslint"];
diagnostics = {
eslint = {
package = pkgs.nodePackages.eslint;
nullConfig = pkg: ''
table.insert(
ls_sources,
null_ls.builtins.diagnostics.eslint.with({
command = "${pkg}/bin/eslint",
})
)
'';
};
};
in {
options.vim.languages.ts = {
enable = mkEnableOption "SQL language support";
treesitter = {
enable = mkOption {
description = "Enable Typescript/Javascript treesitter";
type = types.bool;
default = config.vim.languages.enableTreesitter;
};
tsPackage = mkOption {
description = "Typescript treesitter grammar to use";
type = types.package;
default = pkgs.vimPlugins.nvim-treesitter.builtGrammars.tsx;
};
jsPackage = mkOption {
description = "Javascript treesitter grammar to use";
type = types.package;
default = pkgs.vimPlugins.nvim-treesitter.builtGrammars.javascript;
};
};
lsp = {
enable = mkOption {
description = "Enable Typescript/Javascript LSP support";
type = types.bool;
default = config.vim.languages.enableLSP;
};
server = mkOption {
description = "Typescript/Javascript LSP server to use";
type = with types; enum (attrNames servers);
default = defaultServer;
};
package = mkOption {
description = "Typescript/Javascript LSP server package";
type = types.package;
default = servers.${cfg.lsp.server}.package;
};
};
format = {
enable = mkOption {
description = "Enable Typescript/Javascript formatting";
type = types.bool;
default = config.vim.languages.enableFormat;
};
type = mkOption {
description = "Typescript/Javascript formatter to use";
type = with types; enum (attrNames formats);
default = defaultFormat;
};
package = mkOption {
description = "Typescript/Javascript formatter package";
type = types.package;
default = formats.${cfg.format.type}.package;
};
};
extraDiagnostics = {
enable = mkOption {
description = "Enable extra Typescript/Javascript diagnostics";
type = types.bool;
default = config.vim.languages.enableExtraDiagnostics;
};
types = lib.nvim.types.diagnostics {
langDesc = "Typescript/Javascript";
inherit diagnostics;
inherit defaultDiagnostics;
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.tsPackage cfg.treesitter.jsPackage];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.ts-lsp = servers.${cfg.lsp.server}.lspConfig;
})
(mkIf cfg.format.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources.ts-format = formats.${cfg.format.type}.nullConfig;
})
(mkIf cfg.extraDiagnostics.enable {
vim.lsp.null-ls.enable = true;
vim.lsp.null-ls.sources = lib.nvim.languages.diagnosticsToLua {
lang = "ts";
config = cfg.extraDiagnostics.types;
inherit diagnostics;
};
})
]);
}

68
modules/languages/zig.nix Normal file
View file

@ -0,0 +1,68 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.languages.zig;
in {
options.vim.languages.zig = {
enable = mkEnableOption "SQL language support";
treesitter = {
enable = mkOption {
description = "Enable Zig treesitter";
type = types.bool;
default = config.vim.languages.enableTreesitter;
};
package = mkOption {
description = "Zig treesitter grammar to use";
type = types.package;
default = pkgs.vimPlugins.nvim-treesitter.builtGrammars.zig;
};
};
lsp = {
enable = mkOption {
description = "Zig LSP support (zls)";
type = types.bool;
default = config.vim.languages.enableLSP;
};
package = mkOption {
description = "ZLS package";
type = types.package;
default = pkgs.nodePackages.pyright;
};
zigPackage = mkOption {
description = "Zig package used by ZLS";
type = types.package;
default = pkgs.zig;
};
};
};
config = mkIf cfg.enable (mkMerge [
(mkIf cfg.treesitter.enable {
vim.treesitter.enable = true;
vim.treesitter.grammars = [cfg.treesitter.package];
})
(mkIf cfg.lsp.enable {
vim.lsp.lspconfig.enable = true;
vim.lsp.lspconfig.sources.zig-lsp = ''
lspconfig.zls.setup {
capabilities = capabilities,
on_attach=default_on_attach,
cmd = {"${cfg.lsp.package}/bin/zls"},
settings = {
["zls"] = {
zig_exe_path = "${cfg.lsp.zigPackage}/bin/zig",
zig_lib_path = "${cfg.lsp.zigPackage}/lib/zig",
}
}
}
'';
})
]);
}

View file

@ -1,64 +1,21 @@
{ {
pkgs,
config, config,
lib, lib,
pkgs,
... ...
}: }:
with lib; with lib;
with builtins; let with builtins; let
cfg = config.vim.lsp; cfg = config.vim.lsp;
usingNvimCmp = config.vim.autocomplete.enable && config.vim.autocomplete.type == "nvim-cmp";
in { in {
config = mkIf cfg.enable ( config = mkIf cfg.enable {
let vim.startPlugins = optional usingNvimCmp "cmp-nvim-lsp";
writeIf = cond: msg:
if cond
then msg
else "";
in {
vim.startPlugins =
[
"nvim-lspconfig"
"null-ls"
(
if (config.vim.autocomplete.enable && (config.vim.autocomplete.type == "nvim-cmp"))
then "cmp-nvim-lsp"
else null
)
(
if cfg.sql
then "sqls-nvim"
else null
)
]
++ (
if cfg.rust.enable
then [
"crates-nvim"
"rust-tools"
]
else []
);
vim.configRC.lsp = nvim.dag.entryAnywhere '' vim.autocomplete.sources = ["nvim_lsp"];
${
if cfg.nix.enable
then ''
autocmd filetype nix setlocal tabstop=2 shiftwidth=2 softtabstop=2
''
else ""
}
${ vim.luaConfigRC.lsp-setup = ''
if cfg.clang.c_header vim.g.formatsave = ${boolToString cfg.formatOnSave};
then ''
" c syntax for header (otherwise breaks treesitter highlighting)
" https://www.reddit.com/r/neovim/comments/orfpcd/question_does_the_c_parser_from_nvimtreesitter/
let g:c_syntax_for_h = 1
''
else ""
}
'';
vim.luaConfigRC.lsp = nvim.dag.entryAnywhere ''
local attach_keymaps = function(client, bufnr) local attach_keymaps = function(client, bufnr)
local opts = { noremap=true, silent=true } local opts = { noremap=true, silent=true }
@ -78,70 +35,6 @@ in {
vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>ln', '<cmd>lua vim.lsp.buf.rename()<CR>', opts) vim.api.nvim_buf_set_keymap(bufnr, 'n', '<leader>ln', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
end end
local null_ls = require("null-ls")
local null_helpers = require("null-ls.helpers")
local null_methods = require("null-ls.methods")
local ls_sources = {
${writeIf cfg.python
''
null_ls.builtins.formatting.black.with({
command = "${pkgs.black}/bin/black",
}),
''}
-- Commented out for now
--${writeIf (config.vim.git.enable && config.vim.git.gitsigns.enable) ''
-- null_ls.builtins.code_actions.gitsigns,
--''}
${writeIf cfg.sql
''
null_helpers.make_builtin({
method = null_methods.internal.FORMATTING,
filetypes = { "sql" },
generator_opts = {
to_stdin = true,
ignore_stderr = true,
suppress_errors = true,
command = "${pkgs.sqlfluff}/bin/sqlfluff",
args = {
"fix",
"-",
},
},
factory = null_helpers.formatter_factory,
}),
null_ls.builtins.diagnostics.sqlfluff.with({
command = "${pkgs.sqlfluff}/bin/sqlfluff",
extra_args = {"--dialect", "postgres"}
}),
''}
${writeIf
(cfg.nix.enable
&& cfg.nix.server == "rnix"
&& cfg.nix.formatter == "alejandra")
''
null_ls.builtins.formatting.alejandra.with({
command = "${pkgs.alejandra}/bin/alejandra"
}),
''}
${writeIf cfg.ts
''
null_ls.builtins.diagnostics.eslint,
null_ls.builtins.formatting.prettier,
''}
}
vim.g.formatsave = ${
if cfg.formatOnSave
then "true"
else "false"
};
-- Enable formatting -- Enable formatting
format_callback = function(client, bufnr) format_callback = function(client, bufnr)
vim.api.nvim_create_autocmd("BufWritePre", { vim.api.nvim_create_autocmd("BufWritePre", {
@ -163,190 +56,8 @@ in {
format_callback(client, bufnr) format_callback(client, bufnr)
end end
-- Enable null-ls
require('null-ls').setup({
diagnostics_format = "[#{m}] #{s} (#{c})",
debounce = 250,
default_timeout = 5000,
sources = ls_sources,
on_attach=default_on_attach
})
-- Enable lspconfig
local lspconfig = require('lspconfig')
local capabilities = vim.lsp.protocol.make_client_capabilities() local capabilities = vim.lsp.protocol.make_client_capabilities()
${ ${optionalString usingNvimCmp "capabilities = require('cmp_nvim_lsp').default_capabilities()"}
let '';
cfg = config.vim.autocomplete;
in
writeIf cfg.enable (
if cfg.type == "nvim-cmp"
then ''
capabilities = require('cmp_nvim_lsp').default_capabilities()
''
else ""
)
}
${writeIf cfg.rust.enable ''
-- Rust config
local rt = require('rust-tools')
rust_on_attach = function(client, bufnr)
default_on_attach(client, bufnr)
local opts = { noremap=true, silent=true, buffer = bufnr }
vim.keymap.set("n", "<leader>ris", rt.inlay_hints.set, opts)
vim.keymap.set("n", "<leader>riu", rt.inlay_hints.unset, opts)
vim.keymap.set("n", "<leader>rr", rt.runnables.runnables, opts)
vim.keymap.set("n", "<leader>rp", rt.parent_module.parent_module, opts)
vim.keymap.set("n", "<leader>rm", rt.expand_macro.expand_macro, opts)
vim.keymap.set("n", "<leader>rc", rt.open_cargo_toml.open_cargo_toml, opts)
vim.keymap.set("n", "<leader>rg", function() rt.crate_graph.view_crate_graph("x11", nil) end, opts)
end
local rustopts = {
tools = {
autoSetHints = true,
hover_with_actions = false,
inlay_hints = {
only_current_line = false,
}
},
server = {
capabilities = capabilities,
on_attach = rust_on_attach,
cmd = {"${pkgs.rust-analyzer}/bin/rust-analyzer"},
settings = {
${cfg.rust.rustAnalyzerOpts}
}
}
}
require('crates').setup {
null_ls = {
enabled = true,
name = "crates.nvim",
}
}
rt.setup(rustopts)
''}
${optionalString cfg.zig.enable ''
-- Zig config
lspconfig.zls.setup {
capabilities = capabilities,
on_attach=default_on_attach,
cmd = {"${pkgs.zls}/bin/zls"},
settings = {
["zls"] = {
zig_exe_path = "${pkgs.zig}/bin/zig",
zig_lib_path = "${pkgs.zig}/lib/zig",
}
}
}
''}
${writeIf cfg.python ''
-- Python config
lspconfig.pyright.setup{
capabilities = capabilities;
on_attach=default_on_attach;
cmd = {"${pkgs.nodePackages.pyright}/bin/pyright-langserver", "--stdio"}
}
''}
${writeIf cfg.nix.enable (
(writeIf (cfg.nix.server == "rnix") ''
-- Nix (rnix) config
lspconfig.rnix.setup{
capabilities = capabilities,
${writeIf (cfg.nix.formatter == "alejandra")
''
on_attach = function(client, bufnr)
attach_keymaps(client, bufnr)
end,
''}
${writeIf (cfg.nix.formatter == "nixpkgs-fmt")
''
on_attach = default_on_attach,
''}
cmd = {"${cfg.nix.pkg}/bin/rnix-lsp"},
}
'')
+ (writeIf (cfg.nix.server == "nil") ''
-- Nix (nil) config
lspconfig.nil_ls.setup{
capabilities = capabilities,
on_attach=default_on_attach,
cmd = {"${cfg.nix.pkg}/bin/nil"},
settings = {
["nil"] = {
${writeIf (cfg.nix.formatter == "alejandra")
''
formatting = {
command = {"${pkgs.alejandra}/bin/alejandra", "--quiet"},
},
''}
${writeIf (cfg.nix.formatter == "nixpkgs-fmt")
''
formatting = {
command = {"${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt"},
},
''}
},
}; };
} }
'')
)}
${writeIf cfg.clang.enable ''
-- CCLS (clang) config
lspconfig.ccls.setup{
capabilities = capabilities;
on_attach=default_on_attach;
cmd = {"${pkgs.ccls}/bin/ccls"};
${
if cfg.clang.cclsOpts == ""
then ""
else "init_options = ${cfg.clang.cclsOpts}"
}
}
''}
${writeIf cfg.sql ''
-- SQLS config
lspconfig.sqls.setup {
on_attach = function(client)
client.server_capabilities.execute_command = true
on_attach_keymaps(client, bufnr)
require'sqls'.setup{}
end,
cmd = {"${pkgs.sqls}/bin/sqls", "-config", string.format("%s/config.yml", vim.fn.getcwd()) }
}
''}
${writeIf cfg.go ''
-- Go config
lspconfig.gopls.setup {
capabilities = capabilities;
on_attach = default_on_attach;
cmd = {"${pkgs.gopls}/bin/gopls", "serve"},
}
''}
${writeIf cfg.ts ''
-- TS config
lspconfig.tsserver.setup {
capabilities = capabilities;
on_attach = function(client, bufnr)
attach_keymaps(client, bufnr)
end,
cmd = { "${pkgs.nodePackages.typescript-language-server}/bin/typescript-language-server", "--stdio" }
}
''}
'';
}
);
}

View file

@ -4,6 +4,10 @@
./config.nix ./config.nix
./module.nix ./module.nix
./lspconfig
./lspsaga
./null-ls
# lsp plugins # lsp plugins
./lspsaga ./lspsaga
./nvim-code-action-menu ./nvim-code-action-menu

View file

@ -6,6 +6,8 @@
with lib; with lib;
with builtins; { with builtins; {
options.vim.lsp.dart.flutter-tools = { options.vim.lsp.dart.flutter-tools = {
enable = mkEnableOption "Enable flutter-tools for flutter support";
color = { color = {
enable = mkEnableOption "Whether or mot to highlight color variables at all"; enable = mkEnableOption "Whether or mot to highlight color variables at all";

View file

@ -0,0 +1,25 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.lsp;
in {
config = mkIf cfg.lspconfig.enable (mkMerge [
{
vim.lsp.enable = true;
vim.startPlugins = ["nvim-lspconfig"];
vim.luaConfigRC.lspconfig = nvim.dag.entryAfter ["lsp-setup"] ''
local lspconfig = require('lspconfig')
'';
}
{
vim.luaConfigRC = mapAttrs (_: v: (nvim.dag.entryAfter ["lspconfig"] v)) cfg.lspconfig.sources;
}
]);
}

View file

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

View file

@ -0,0 +1,18 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; {
options.vim.lsp.lspconfig = {
enable = mkEnableOption "nvim-lspconfig, also enabled automatically";
sources = mkOption {
description = "nvim-lspconfig sources";
type = with types; attrsOf str;
default = {};
};
};
}

View file

@ -1,73 +1,13 @@
{ {
pkgs,
config, config,
lib, lib,
pkgs,
... ...
}: }:
with lib; with lib;
with builtins; let with builtins; {
cfg = config.vim.lsp;
in {
options.vim.lsp = { options.vim.lsp = {
enable = mkEnableOption "Enable neovim LSP support. Requires language specific LSPs to be anabled to take effect"; enable = mkEnableOption "LSP, also enabled automatically through null-ls and lspconfig options";
formatOnSave = mkEnableOption "Format on save"; formatOnSave = mkEnableOption "format on save";
nix = {
enable = mkEnableOption "Nix LSP";
server = mkOption {
type = with types; enum ["rnix" "nil"];
default = "nil";
description = "Which LSP to use";
};
pkg = mkOption {
type = types.package;
default =
if (cfg.nix.server == "rnix")
then pkgs.rnix-lsp
else pkgs.nil;
description = "The LSP package to use";
};
formatter = mkOption {
type = with types; enum ["nixpkgs-fmt" "alejandra"];
default = "alejandra";
description = "Which nix formatter to use";
};
};
rust = {
enable = mkEnableOption "Rust LSP";
rustAnalyzerOpts = mkOption {
type = types.str;
default = ''
["rust-analyzer"] = {
experimental = {
procAttrMacros = true,
},
},
'';
description = "Options to pass to rust analyzer";
};
};
python = mkEnableOption "Python LSP";
clang = {
enable = mkEnableOption "C language LSP";
c_header = mkEnableOption "C syntax header files";
cclsOpts = mkOption {
type = types.str;
default = "";
};
};
dart = {
enable = mkEnableOption "Dart Language LSP";
flutter-tools = {
enable = mkEnableOption "";
};
};
sql = mkEnableOption "SQL Language LSP";
go = mkEnableOption "Go language LSP";
ts = mkEnableOption "TS language LSP";
zig.enable = mkEnableOption "Zig language LSP";
}; };
} }

View file

@ -0,0 +1,36 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.lsp;
in {
config = mkIf cfg.null-ls.enable (mkMerge [
{
vim.lsp.enable = true;
vim.startPlugins = ["null-ls"];
vim.luaConfigRC.null_ls-setup = nvim.dag.entryAnywhere ''
local null_ls = require("null-ls")
local null_helpers = require("null-ls.helpers")
local null_methods = require("null-ls.methods")
local ls_sources = {}
'';
vim.luaConfigRC.null_ls = nvim.dag.entryAfter ["null_ls-setup" "lsp-setup"] ''
require('null-ls').setup({
diagnostics_format = "[#{m}] #{s} (#{c})",
debounce = 250,
default_timeout = 5000,
sources = ls_sources,
on_attach=default_on_attach
})
'';
}
{
vim.luaConfigRC = mapAttrs (_: v: (nvim.dag.entryBetween ["null_ls"] ["null_ls-setup"] v)) cfg.null-ls.sources;
}
]);
}

View file

@ -0,0 +1,6 @@
_: {
imports = [
./config.nix
./null-ls.nix
];
}

View file

@ -0,0 +1,20 @@
{
pkgs,
config,
lib,
...
}:
with lib;
with builtins; let
cfg = config.vim.lsp;
in {
options.vim.lsp.null-ls = {
enable = mkEnableOption "null-ls, also enabled automatically";
sources = mkOption {
description = "null-ls sources";
type = with types; attrsOf str;
default = {};
};
};
}

View file

@ -30,6 +30,7 @@
./session ./session
./comments ./comments
./projects ./projects
./languages
]; ];
pkgsModule = {config, ...}: { pkgsModule = {config, ...}: {

View file

@ -1,4 +1,5 @@
{ {
pkgs,
config, config,
lib, lib,
... ...
@ -6,33 +7,24 @@
with lib; with lib;
with builtins; let with builtins; let
cfg = config.vim.treesitter; cfg = config.vim.treesitter;
usingNvimCmp = config.vim.autocomplete.enable && config.vim.autocomplete.type == "nvim-cmp";
in { in {
config = mkIf cfg.enable ( config = mkIf cfg.enable {
let vim.startPlugins =
writeIf = cond: msg: ["nvim-treesitter"]
if cond ++ optional cfg.autotagHtml "nvim-ts-autotag"
then msg ++ optional usingNvimCmp "cmp-treesitter";
else "";
in { vim.autocomplete.sources = ["treesitter"];
vim.startPlugins = [
"nvim-treesitter"
(
if cfg.autotagHtml
then "nvim-ts-autotag"
else null
)
];
# For some reason treesitter highlighting does not work on start if this is set before syntax on # For some reason treesitter highlighting does not work on start if this is set before syntax on
vim.configRC.treesitter = writeIf cfg.fold (nvim.dag.entryBefore ["basic"] '' vim.configRC.treesitter-fold = mkIf cfg.fold (nvim.dag.entryBefore ["basic"] ''
" Tree-sitter based folding
set foldmethod=expr set foldmethod=expr
set foldexpr=nvim_treesitter#foldexpr() set foldexpr=nvim_treesitter#foldexpr()
set nofoldenable set nofoldenable
''); '');
vim.luaConfigRC.treesitter = nvim.dag.entryAnywhere '' vim.luaConfigRC.treesitter = nvim.dag.entryAnywhere ''
-- Treesitter config
require'nvim-treesitter.configs'.setup { require'nvim-treesitter.configs'.setup {
highlight = { highlight = {
enable = true, enable = true,
@ -52,13 +44,12 @@ in {
}, },
}, },
${writeIf cfg.autotagHtml '' ${optionalString cfg.autotagHtml ''
autotag = { autotag = {
enable = true, enable = true,
}, },
''} ''}
} }
''; '';
} };
);
} }

View file

@ -5,51 +5,23 @@
... ...
}: }:
with lib; with lib;
with builtins; { with builtins; let
cfg = config.vim.treesitter;
usingNvimCmp = config.vim.autocomplete.enable && config.vim.autocomplete.type == "nvim-cmp";
in {
options.vim.treesitter = { options.vim.treesitter = {
enable = mkOption { enable = mkEnableOption "treesitter, also enabled automatically through language options";
default = false;
type = types.bool;
description = "Enable tree-sitter [nvim-treesitter]";
};
fold = mkOption { fold = mkEnableOption "fold with treesitter";
default = false;
type = types.bool;
description = "Enable fold with tree-sitter";
};
autotagHtml = mkOption { autotagHtml = mkEnableOption "autoclose and rename html tag";
default = false;
type = types.bool;
description = "Enable autoclose and rename html tag [nvim-ts-autotag]";
};
grammars = mkOption { grammars = mkOption {
type = with types; listOf package; type = with types; listOf package;
default = with (pkgs.vimPlugins.nvim-treesitter.builtGrammars); default = [];
[
c
cpp
nix
python
rust
markdown
comment
toml
make
tsx
html
javascript
css
graphql
json
zig
]
++ (optional config.vim.notes.orgmode.enable org); # add orgmode grammar if enabled
description = '' description = ''
List of treesitter grammars to install. List of treesitter grammars to install. For supported languages
When enabling a language, its treesitter grammar is added for you. use the `vim.language.<lang>.treesitter` option
''; '';
}; };
}; };