feat: refactor and separate LSP/language configurations

This commit is contained in:
NotAShelf 2023-04-17 23:27:27 +03:00
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

@ -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",
}
}
}
'';
})
]);
}