dotfiles/home/common/nvim.nix

442 lines
17 KiB
Nix
Raw Normal View History

2023-03-15 16:41:44 +07:00
{ config, pkgs, lib, ... }:
{
imports = [ ./options.nix ];
2023-03-15 16:41:44 +07:00
/*
VIM config backup:
syntax on
au FileType markdown set colorcolumn=73 textwidth=72
au FileType gitcommit set colorcolumn=73
highlight NormalFloat guibg=NONE
au BufReadPre * set foldmethod=syntax
au BufReadPost * folddoc foldopen!
autocmd BufReadPost * if @% !~# '\.git[\/\\]COMMIT_EDITMSG$' && line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
*/
2023-03-15 17:43:16 +07:00
# welcome to my cursed DSL
2023-03-15 16:41:44 +07:00
programs.neovim = let
notlua = config.notlua;
notlua-nvim = notlua.neovim { inherit (config.programs.neovim) plugins extraLuaPackages; };
inherit (notlua.keywords) CALL RAW PROP SET LET DEFUN IF APPLY OR EQ RETURN ELSE ATTR MCALL LETREC;
inherit (notlua.utils) compile;
inherit (notlua-nvim.stdlib) vim string require print;
inherit (notlua-nvim.keywords) REQ REQ' REQLET;
in let
vimcmd = name: CALL (RAW "vim.cmd.${name}");
vimg = name: PROP vim.g name;
2023-03-15 16:41:44 +07:00
keymapSetSingle = opts@{
mode,
lhs,
rhs,
noremap ? true,
silent ? true,
...
}: let
2023-03-15 19:14:37 +07:00
opts'' = opts // { inherit noremap silent; };
2023-03-15 16:41:44 +07:00
opts' = lib.filterAttrs (k: v:
k != "keys" && k != "mode" && k != "lhs" && k != "rhs" && k != "desc"
# defaults to false
2023-03-15 19:14:37 +07:00
&& ((k != "silent" && k != "noremap") || (builtins.isBool v && v))) opts'';
in vim.keymap.set mode lhs rhs opts';
2023-03-15 16:41:44 +07:00
keymapSetMulti = opts@{
keys,
mode,
noremap ? true,
silent ? true,
...
}: let
opts'' = opts // { inherit noremap silent; };
opts' = lib.filterAttrs (k: v:
k != "keys" && k != "lhs" && k != "rhs" && k != "desc"
# defaults to false
&& ((k != "silent" && k != "noremap") || (builtins.isBool v && v))) opts'';
in (lib.mapAttrsToList (k: {rhs, desc}: keymapSetSingle (opts' // {
lhs = k; inherit rhs;
})) keys) ++ [
(which-key.register (lib.mapAttrs (k: v: [v.rhs v.desc]) keys) opts')
2023-03-15 16:41:44 +07:00
];
keymapSetNs = args: keymapSetMulti (args // { mode = "n"; });
kmSetNs = keys: keymapSetNs { inherit keys; };
2023-03-15 17:43:16 +07:00
keymapSetVs = args: keymapSetMulti (args // { mode = "v"; });
kmSetVs = keys: keymapSetVs { inherit keys; };
which-key = REQ "which-key";
luasnip = REQ "luasnip";
cmp = REQ "cmp";
2023-03-15 16:41:44 +07:00
in {
enable = true;
defaultEditor = true;
package = pkgs.neovim-unwrapped;
extraPackages = with pkgs; [
rust-analyzer
nodePackages_latest.bash-language-server shellcheck
nodePackages_latest.typescript-language-server
nodePackages_latest.svelte-language-server
clang-tools_latest
2023-03-15 16:41:44 +07:00
nodePackages_latest.vscode-langservers-extracted
nil
marksman
taplo
2023-03-15 19:14:37 +07:00
ripgrep
2023-03-15 16:41:44 +07:00
(python3.withPackages (p: with p; [
python-lsp-server
pylsp-mypy
python-lsp-server.optional-dependencies.pyflakes
python-lsp-server.optional-dependencies.mccabe
python-lsp-server.optional-dependencies.pycodestyle
]))
];
# extraPython3Packages = pyPkgs: with pyPkgs; [
# ];
viAlias = true;
vimAlias = true;
vimdiffAlias = true;
2023-03-15 16:41:44 +07:00
extraLuaConfig = (compile "main" [
(SET (vimg "vimsyn_embed") "l")
(LET (vim.api.nvim_create_augroup "nvimrc" { clear = true; }) (group:
lib.mapAttrsToList (k: v: vim.api.nvim_create_autocmd k { inherit group; callback = v; }) {
BufReadPre = DEFUN (SET vim.o.foldmethod "syntax");
BufEnter = { buf, ... }:
(LET (vim.filetype.match { inherit buf; }) (filetype: [
(IF (APPLY OR (map (EQ filetype) [ "gitcommit" "markdown" ])) (LET vim.o.colorcolumn (old_colorcolumn: [
(SET vim.o.colorcolumn "73")
(vim.api.nvim_create_autocmd "BufLeave" {
callback = DEFUN [
(SET vim.o.colorcolumn old_colorcolumn)
# return true = delete autocommand
(RETURN true)
];
})
])))
(IF (EQ filetype "markdown") (LET vim.o.textwidth (old_textwidth: [
(SET vim.o.textwidth 72)
(vim.api.nvim_create_autocmd "BufLeave" {
callback = DEFUN [
(SET vim.o.textwidth old_textwidth)
(RETURN true)
];
})
])))
]));
BufWinEnter = { buf, ... }:
(LET (vim.filetype.match { inherit buf; }) (filetype: [
(vimcmd "folddoc" "foldopen!")
(IF (EQ filetype "gitcommit")
(CALL vim.cmd {
cmd = "normal";
bang = true;
args = [ "gg" ];
})
ELSE
(CALL vim.cmd {
cmd = "normal";
bang = true;
args = [ "g`\"" ];
})
)
]));
}
))
2023-03-15 16:41:44 +07:00
]);
plugins = let ps = pkgs.vimPlugins; in map (x: if x?config && x?plugin then { type = "lua"; } // x else x) [
ps.vim-svelte
2023-03-15 16:41:44 +07:00
# TODO remove on next nvim update (0.8.3/0.9)
ps.vim-nix
2023-03-15 16:41:44 +07:00
{ plugin = pkgs.vimUtils.buildVimPluginFrom2Nix {
pname = "vscode-nvim";
version = "2023-02-10";
src = pkgs.fetchFromGitHub {
owner = "Mofiqul";
repo = "vscode.nvim";
rev = "db9ee339b5556aa832ca58871fd18f9467a18520";
sha256 = "sha256-X2IgIjO5NNq7vJdl09hBY1TFqHlsfF1xfllKr4osILI=";
};
};
config = compile "vscode_nvim" [
((REQ "vscode").setup {
transparent = true;
color_overrides = {
vscGray = "#745b5f";
vscViolet = "#${config.colors.magenta}";
vscBlue = "#6ddfd8";
vscDarkBlue = "#${config.colors.blue}";
vscGreen = "#${config.colors.green}";
vscBlueGreen = "#73bf88";
vscLightGreen = "#6acf6e";
vscRed = "#${config.colors.red}";
vscOrange = "#e89666";
vscLightRed = "#e64e4e";
vscYellowOrange = "#e8b166";
vscYellow = "#${config.colors.yellow}";
vscPink = "#cf83c4";
};
})
(vim.api.nvim_set_hl 0 "NormalFloat" {
bg = "NONE";
})
]; }
{ plugin = ps.nvim-web-devicons;
config = compile "nvim_web_devicons" ((REQ "nvim-web-devicons").setup {}); }
{ plugin = ps.nvim-tree-lua;
config = compile "nvim_tree_lua" (REQLET "nvim-tree" "nvim-tree.api" (nvim-tree: nvim-tree-api: [
(SET (vimg "loaded_netrw") 1)
(SET (vimg "loaded_netrwPlugin") 1)
(SET vim.o.termguicolors true)
(nvim-tree.setup {}) # :help nvim-tree-setup
2023-03-15 17:43:16 +07:00
(kmSetNs {
"<C-N>" = {
rhs = nvim-tree-api.tree.toggle;
2023-03-15 17:43:16 +07:00
desc = "Toggle NvimTree";
};
2023-03-15 16:41:44 +07:00
})
])); }
ps.vim-sleuth
ps.luasnip
{ plugin = ps.nvim-cmp;
2023-03-15 16:41:44 +07:00
config = let
border = (name: [
[ "" name ]
[ "" name ]
[ "" name ]
[ "" name ]
[ "" name ]
[ "" name ]
[ "" name ]
[ "" name ]
]);
in compile "nvim_cmp" (REQLET "cmp" "lspkind" (cmp: lspkind:
# call is required because cmp.setup is a table
(CALL cmp.setup {
2023-03-15 16:41:44 +07:00
snippet = {
expand = { body, ... }: luasnip.lsp_expand body {};
2023-03-15 16:41:44 +07:00
};
view = { };
window = {
completion = {
border = border "CmpBorder";
winhighlight = "Normal:CmpPmenu,CursorLine:PmenuSel,Search:None";
};
documentation = {
border = border "CmpDocBorder";
};
};
formatting = {
format = _: vim_item: let kind = PROP vim_item "kind"; in [
(SET kind (string.format "%s %s" (ATTR lspkind kind) kind))
(RETURN vim_item)
2023-03-15 16:41:44 +07:00
];
};
mapping = {
"<C-p>" = cmp.mapping.select_prev_item {};
"<C-n>" = cmp.mapping.select_next_item {};
"<C-space>" = cmp.mapping.complete {};
"<C-e>" = cmp.mapping.close {};
"<cr>" = cmp.mapping.confirm {
behavior = cmp.ConfirmBehavior.Replace;
2023-03-15 16:41:44 +07:00
select = false;
};
"<tab>" = CALL cmp.mapping (fallback:
(IF
(CALL cmp.visible)
(CALL cmp.select_next_item)
(CALL luasnip.expand_or_jumpable)
(vim.api.nvim_feedkeys
(vim.api.nvim_replace_termcodes "<Plug>luasnip-expand-or-jump" true true true)
""
false)
ELSE
(CALL fallback)))
[ "i" "s" ];
"<S-tab>" = CALL cmp.mapping (fallback:
(IF
(CALL cmp.visible)
(CALL cmp.select_prev_item)
(luasnip.jumpable (-1))
(vim.api.nvim_feedkeys
(vim.api.nvim_replace_termcodes "<Plug>luasnip-jump-prev" true true true)
""
false)
ELSE
(CALL fallback)))
[ "i" "s" ];
2023-03-15 16:41:44 +07:00
};
sources = cmp.config.sources [
2023-03-15 16:41:44 +07:00
{ name = "nvim_lsp"; }
{ name = "luasnip"; }
];
2023-03-15 16:41:44 +07:00
})
2023-03-15 17:43:16 +07:00
)); }
ps.lspkind-nvim
ps.cmp_luasnip
ps.cmp-nvim-lsp
{ plugin = ps.nvim-autopairs;
config = compile "nvim_autopairs" (REQLET "nvim-autopairs.completion.cmp" "nvim-autopairs" (cmp-autopairs: nvim-autopairs: [
(nvim-autopairs.setup {
2023-03-15 16:41:44 +07:00
disable_filetype = [ "TelescopePrompt" "vim" ];
})
(MCALL cmp.event "on" "confirm_done" (cmp-autopairs.on_confirm_done {}))
2023-03-15 16:41:44 +07:00
])); }
{ plugin = ps.comment-nvim;
2023-03-15 16:41:44 +07:00
config = compile "comment_nvim" [
((REQ "Comment").setup {})
2023-03-15 17:43:16 +07:00
(kmSetNs {
"<space>/" = {
rhs = PROP (REQ "Comment.api").toggle "linewise.current";
2023-03-15 17:43:16 +07:00
desc = "Comment current line";
};
2023-03-15 16:41:44 +07:00
})
2023-03-15 17:43:16 +07:00
(kmSetVs {
"<space>/" = {
rhs = "<esc><cmd>lua require('Comment.api').toggle.linewise(vim.fn.visualmode())<cr>";
desc = "Comment selection";
};
2023-03-15 16:41:44 +07:00
})
]; }
{ plugin = ps.nvim-lspconfig;
config = compile "nvim_lspconfig" (
let lsp = name: builtins.seq
# ensure an lsp exists (otherwise lspconfig will still create an empty config for some reason)
(REQ "lspconfig.server_configurations.${name}")
# metatables, son! they harden in response to physical trauma
(REQ' (PROP (require "lspconfig") name));
in [
2023-03-15 16:41:44 +07:00
# See `:help vim.diagnostic.*` for documentation on any of the below functions
(kmSetNs {
"<space>e" = {
rhs = vim.diagnostic.open_float;
desc = "Show diagnostics in a floating window.";
};
"[d" = {
rhs = vim.diagnostic.goto_prev;
desc = "Move to the previous diagnostic in the current buffer.";
};
"]d" = {
rhs = vim.diagnostic.goto_next;
desc = "Get the next diagnostic closest to the cursor position.";
};
"<space>q" = {
rhs = vim.diagnostic.setloclist;
desc = "Add buffer diagnostics to the location list.";
};
})
(LET
2023-03-15 16:41:44 +07:00
# LET on_attach
(client: bufnr: [
2023-03-15 16:41:44 +07:00
# Enable completion triggered by <c-x><c-o>
(vim.api.nvim_buf_set_option bufnr "omnifunc" "v:lua.vim.lsp.omnifunc")
2023-03-15 16:41:44 +07:00
# Mappings.
# See `:help vim.lsp.*` for documentation on any of the below functions
(kmSetNs {
"gD" = {
rhs = vim.lsp.buf.declaration;
desc = "Jumps to the declaration of the symbol under the cursor."; };
"gd" = {
rhs = vim.lsp.buf.definition;
desc = "Jumps to the definition of the symbol under the cursor."; };
"K" = {
rhs = vim.lsp.buf.hover;
desc = "Displays hover information about the symbol under the cursor in a floating window."; };
"gi" = {
rhs = vim.lsp.buf.implementation;
desc = "Lists all the implementations for the symbol under the cursor in the quickfix window."; };
"<C-h>" = {
rhs = vim.lsp.buf.signature_help;
desc = "Displays signature information about the symbol under the cursor in a floating window."; };
"<space>wa" = {
rhs = vim.lsp.buf.add_workspace_folder;
desc = "Add a folder to the workspace folders."; };
"<space>wr" = {
rhs = vim.lsp.buf.remove_workspace_folder;
desc = "Remove a folder from the workspace folders."; };
"<space>wl" = {
rhs = DEFUN (print (CALL vim.inspect (CALL vim.lsp.buf.list_workspace_folders)));
2023-03-15 16:41:44 +07:00
desc = "List workspace folders."; };
"<space>D" = {
rhs = vim.lsp.buf.type_definition;
desc = "Jumps to the definition of the type of the symbol under the cursor."; };
"<space>rn" = {
rhs = vim.lsp.buf.rename;
desc = "Rename old_fname to new_fname"; };
"<space>ca" = {
rhs = vim.lsp.buf.code_action;
desc = "Selects a code action available at the current cursor position."; };
"gr" = {
rhs = vim.lsp.buf.references;
desc = "Lists all the references to the symbol under the cursor in the quickfix window."; };
"<space>f" = {
rhs = (DEFUN (vim.lsp.buf.format {async = true;}));
2023-03-15 16:41:44 +07:00
desc = "Formats a buffer."; };
})
])
2023-03-15 16:41:44 +07:00
# LET rust_settings
{ rust-analyzer = {
assist.emitMustUse = true;
cargo.buildScripts.enable = true;
check.command = "clippy";
procMacro.enable = true;
}; }
# LET capabilities
(vim.tbl_extend
2023-03-15 16:41:44 +07:00
"keep"
((REQ "cmp_nvim_lsp").default_capabilities {})
(CALL vim.lsp.protocol.make_client_capabilities))
2023-03-15 16:41:44 +07:00
# BEGIN
(on_attach: rust_settings: capabilities: [
(LETREC
2023-03-15 16:41:44 +07:00
# LETREC on_attach_rust
(on_attach_rust: client: bufnr: [
(vim.api.nvim_create_user_command "RustAndroid" (opts: [
(vim.lsp.set_log_level "debug")
((lsp "rust_analyzer").setup {
2023-03-15 16:41:44 +07:00
on_attach = on_attach_rust;
inherit capabilities;
settings = vim.tbl_deep_extend
2023-03-15 16:41:44 +07:00
"keep"
config.rustAnalyzerAndroidSettings
rust_settings;
2023-03-15 16:41:44 +07:00
})
]) {})
(CALL on_attach client bufnr)
2023-03-15 16:41:44 +07:00
])
# BEGIN
(let setupLsp' = { name, settings ? {} }: (lsp name).setup {
2023-03-15 16:41:44 +07:00
inherit on_attach capabilities settings;
};
setupLsp = args: setupLsp' (if builtins.isString args then { name = args; } else args);
in (on_attach_rust: [
2023-03-15 19:14:37 +07:00
# (vim.lsp.set_log_level "debug")
(map setupLsp [
2023-03-15 16:41:44 +07:00
# see https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md
2023-03-15 19:14:37 +07:00
"bashls"
"clangd"
2023-03-15 16:41:44 +07:00
# https://github.com/python-lsp/python-lsp-server/blob/develop/CONFIGURATION.md
{ name = "pylsp"; settings = {
pylsp.plugins.pylsp_mypy.enabled = true;
}; }
2023-03-15 19:14:37 +07:00
"svelte"
"html"
"cssls"
"tsserver"
"jsonls"
"nil_ls"
"taplo"
"marksman"
2023-03-15 16:41:44 +07:00
])
((lsp "rust_analyzer").setup {
2023-03-15 16:41:44 +07:00
on_attach = on_attach_rust;
settings = rust_settings;
inherit capabilities;
})
]))) # END
])) # END
]); }
{ plugin = ps.which-key-nvim;
2023-03-15 16:41:44 +07:00
config = compile "which_key_nvim" [
(SET vim.o.timeout true)
(SET vim.o.timeoutlen 500)
(which-key.setup {})
2023-03-15 16:41:44 +07:00
]; }
];
};
}