feat(neovim): finish transition to nixvim

This commit is contained in:
oddlama 2023-11-26 00:59:03 +01:00
parent 052fded8e2
commit 2f4c2df735
No known key found for this signature in database
GPG key ID: 14EFE510775FE39A
31 changed files with 806 additions and 2131 deletions

View file

@ -1,22 +1,28 @@
# TODO whichkey
# TODO vim illuminate
# TODO keybinds
# TODO dap dapui
# TODO neotree left darker
# TODO neotree focsed shows lualine wrongly (full instead of nothing)
# TODO lualine inactive ------ is ugly
# TODO move lines. gomove again?
# TODO vim-wordmotion vs https://github.com/chrisgrieser/nvim-various-textobjs
# TODO blankline cur indent too bright
{
lib,
pkgs,
...
}: {
# TODO use programs.nixvim? and split stuff a little.
home.shellAliases.nixvim = lib.getExe (pkgs.nixvim.makeNixvim {
# TODO away once we are ready to switch (prevents shada and undohist currently)
package = pkgs.neovim-clean;
imports = [
./alpha.nix
./appearance.nix
./completion.nix
./git.nix
./globals.nix
./languages.nix
./lsp.nix
./misc.nix
./neo-tree.nix
./onedark.nix
./web-devicons.nix
];
programs.nixvim = {
enable = true;
# TODO for wayland:
# clipboard.providers.wl-copy.enable = true;
@ -68,72 +74,7 @@
}
];
options = {
# -------------------------------------------------------------------------------------------------
# General
# -------------------------------------------------------------------------------------------------
undolevels = 1000000; # Set maximum undo levels
undofile = true; # Enable persistent undo which persists undo history across vim sessions
updatetime = 300; # Save swap file after 300ms
mouse = "a"; # Enable full mouse support
# -------------------------------------------------------------------------------------------------
# Editor visuals
# -------------------------------------------------------------------------------------------------
termguicolors = true; # Enable true color in terminals
splitkeep = "screen"; # Try not to move text when opening/closing splits
wrap = false; # Do not wrap text longer than the window's width
scrolloff = 2; # Keep 2 lines above and below the cursor.
sidescrolloff = 2; # Keep 2 lines left and right of the cursor.
number = true; # Show line numbers
cursorline = true; # Enable cursorline, colorscheme only shows this in number column
wildmode = ["list" "full"]; # Only complete the longest common prefix and list all results
fillchars = {stlnc = "";}; # Show separators in inactive window statuslines
# FIXME: disabled because this really fucks everything up in the terminal.
title = false; # Sets the window title
# titlestring = "%t%( %M%)%( (%{expand(\"%:~:.:h\")})%) - nvim"; # The format for the window title
# -------------------------------------------------------------------------------------------------
# Editing behavior
# -------------------------------------------------------------------------------------------------
whichwrap = ""; # Never let the curser switch to the next line when reaching line end
ignorecase = true; # Ignore case in search by default
smartcase = true; # Be case sensitive when an upper-case character is included
expandtab = false;
tabstop = 4; # Set indentation of tabs to be equal to 4 spaces.
shiftwidth = 4;
softtabstop = 4;
shiftround = true; # Round indentation commands to next multiple of shiftwidth
# r = insert comment leader when hitting <Enter> in insert mode
# q = allow explicit formatting with gq
# j = remove comment leaders when joining lines if it makes sense
formatoptions = "rqj";
# Allow the curser to be positioned on cells that have no actual character;
# Like moving beyond EOL or on any visual 'space' of a tab character
virtualedit = "all";
selection = "old"; # Do not include line ends in past the-line selections
smartindent = true; # Use smart auto indenting for all file types
# Wait 500 milliseconds for characters to arrive in a mapped sequence.
# Afterwards, which-key will be opened
timeout = true;
timeoutlen = 500;
# Wait 20 (instead of 50) milliseconds for characters to arrive in the TUI.
ttimeout = true;
ttimeoutlen = 20;
grepprg = "rg --vimgrep --smart-case --follow"; # Replace grep with ripgrep
};
# TODO split into files
keymaps = let
keymap = mode: key: action: desc: {
inherit action key mode;
@ -262,677 +203,8 @@
# TODO: ... keybinds + telescope integration
];
plugins = {
# -------------------------------------------------------------------------------------------------
# Library plugins
# -------------------------------------------------------------------------------------------------
notify = {
enable = true;
stages = "static";
render.__raw = ''"compact"'';
icons = {
debug = "";
error = "󰅙";
info = "";
trace = "󰰥";
warn = "";
};
};
# -------------------------------------------------------------------------------------------------
# Appearance
# -------------------------------------------------------------------------------------------------
# Statusline
lualine = {
enable = true;
extensions = ["fzf" "nvim-dap-ui" "symbols-outline" "trouble" "neo-tree" "quickfix" "fugitive"];
componentSeparators = null;
# componentSeparators.left = "|";
# componentSeparators.right = "|";
# sectionSeparators.left = "";
# sectionSeparators.right = "";
sections = {
lualine_a = ["mode"];
lualine_b = ["branch" "filename"];
lualine_c = ["diff" "diagnostics"];
lualine_x = ["encoding" "fileformat" "filetype"];
lualine_y = ["progress"];
lualine_z = ["location"];
};
inactiveSections = {
lualine_a = ["filename"];
lualine_b = [];
lualine_c = ["diagnostics"];
lualine_x = [];
lualine_y = [];
lualine_z = ["location"];
};
};
# Line indentation markers
indent-blankline.enable = true;
# Rainbow parentheses
rainbow-delimiters.enable = true;
# Status updates for LSP progress in right bottom corner.
fidget.enable = true;
# Show colors
nvim-colorizer.enable = true;
# Breadcrumbs
# TODO navic.enable = true; or dropbar?
# -------------------------------------------------------------------------------------------------
# Language support
# -------------------------------------------------------------------------------------------------
treesitter = {
enable = true;
# TODO (autocmd * zR needed) folding = true;
indent = true;
incrementalSelection = {
enable = true;
keymaps = {
initSelection = "<C-Space>";
nodeIncremental = "<C-Space>";
scopeIncremental = "<C-S-Space>";
nodeDecremental = "<C-B>";
};
};
nixvimInjections = true;
};
# Show the current function / context in topmost line
treesitter-context.enable = true;
# Cargo.toml dependency completion
crates-nvim = {
enable = true;
extraOptions = {
src.cmp.enabled = true;
};
};
# Rust specific LSP tools
rust-tools = {
enable = true;
server.check.command = "clippy";
};
# -------------------------------------------------------------------------------------------------
# Editing
# -------------------------------------------------------------------------------------------------
# Commenting
comment-nvim.enable = true;
# Extend vim's "%" key
vim-matchup.enable = true;
# ----------------------------------------------------------------------------------------------------
# Functionality
# ----------------------------------------------------------------------------------------------------
# Fzf picker for arbitrary stuff
telescope = {
enable = true;
enabledExtensions = ["fzf" "notify" "ui-select"];
extensions.fzf-native.enable = true;
};
# Startup screen
alpha = {
enable = true;
layout = let
padding = val: {
type = "padding";
inherit val;
};
in [
(padding 2)
{
opts = {
hl = "Type";
position = "center";
};
type = "text";
val = [
" "
" "
" "
" "
" "
" "
];
}
(padding 2)
{
type = "group";
opts.spacing = 1;
val = [
{
command = ":enew<CR>";
desc = " New file";
shortcut = "e";
}
{
command = ":qa<CR>";
desc = "󰅙 Quit Neovim";
shortcut = "q";
}
];
}
];
};
# Filebrowser
neo-tree = {
enable = true;
sortCaseInsensitive = true;
usePopupsForInput = false;
popupBorderStyle = "rounded";
# TODO window_opts.winblend = 0;
window = {
width = 34;
position = "left";
mappings = {
"<CR>" = "open_with_window_picker";
"s" = "split_with_window_picker";
"v" = "vsplit_with_window_picker";
"t" = "open_tabnew";
"z" = "close_all_nodes";
"Z" = "expand_all_nodes";
"a".__raw = ''{ "add", config = { show_path = "relative" } }'';
"A".__raw = ''{ "add_directory", config = { show_path = "relative" } }'';
"c".__raw = ''{ "copy", config = { show_path = "relative" } }'';
"m".__raw = ''{ "move", config = { show_path = "relative" } }'';
};
};
defaultComponentConfigs = {
modified.symbol = "~ ";
indent.withExpanders = true;
name.trailingSlash = true;
gitStatus.symbols = {
added = "+";
deleted = "";
modified = "";
renamed = "";
untracked = "?";
ignored = "󰛑";
unstaged = ""; # 󰄱
staged = "󰄵";
conflict = "";
};
};
filesystem = {
window.mappings = {
"gA" = "git_add_all";
"ga" = "git_add_file";
"gu" = "git_unstage_file";
};
groupEmptyDirs = true;
followCurrentFile.enabled = true;
useLibuvFileWatcher = true;
filteredItems = {
hideDotfiles = false;
hideByName = [".git"];
};
};
};
# Undo tree
undotree = {
enable = true;
focusOnToggle = true;
windowLayout = 4;
};
# -------------------------------------------------------------------------------------------------
# Git
# -------------------------------------------------------------------------------------------------
# Git status in signcolumn
gitsigns.enable = true;
# Git commands
fugitive.enable = true;
diffview.enable = true;
# Manage git from within neovim
neogit = {
enable = true;
disableBuiltinNotifications = true;
};
# -------------------------------------------------------------------------------------------------
# Completion
# -------------------------------------------------------------------------------------------------
lsp = {
enable = true;
preConfig = ''
local lsp_symbol = function(name, icon)
vim.fn.sign_define(
"DiagnosticSign" .. name,
{ text = icon, numhl = "Diagnostic" .. name, texthl = "Diagnostic" .. name }
)
end
lsp_symbol("Error", "󰅙")
lsp_symbol("Info", "")
lsp_symbol("Hint", "󰌵")
lsp_symbol("Warn", "")
'';
servers = {
bashls.enable = true;
cssls.enable = true;
html.enable = true;
lua-ls.enable = true;
rust-analyzer = {
enable = true;
settings = {
checkOnSave = true;
check.command = "clippy";
};
};
nil_ls = {
enable = true;
settings = {
formatting.command = [(lib.getExe pkgs.alejandra) "--quiet"];
};
};
nixd.enable = true;
};
#keymaps = {
# diagnostic = {
# "<leader>k" = "goto_prev";
# "<leader>j" = "goto_next";
# };
# lspBuf = {
# "gd" = "definition";
# "gD" = "references";
# "<leader>lt" = "type_definition";
# "gi" = "implementation";
# "K" = "hover";
# "<leader>k" = "hover";
# "<leader>r" = "rename";
# };
#};
};
none-ls = {
enable = true;
sources = {
code_actions = {
# gitsigns.enable = true;
shellcheck.enable = true;
};
diagnostics = {
deadnix.enable = true;
gitlint.enable = true;
luacheck.enable = true;
protolint.enable = true;
shellcheck.enable = true;
};
formatting = {
alejandra.enable = true;
jq.enable = true;
markdownlint.enable = true;
rustfmt.enable = true;
sqlfluff.enable = true;
shfmt.enable = true;
stylua.enable = true;
};
};
};
luasnip = {
enable = true;
extraConfig = {
history = true;
# Update dynamic snippets while typing
updateevents = "TextChanged,TextChangedI";
enable_autosnippets = true;
};
};
cmp_luasnip.enable = true;
cmp-cmdline.enable = true;
cmp-cmdline-history.enable = true;
cmp-path.enable = true;
cmp-emoji.enable = true;
cmp-treesitter.enable = true;
cmp-nvim-lsp.enable = true;
cmp-nvim-lsp-document-symbol.enable = true;
cmp-nvim-lsp-signature-help.enable = true;
nvim-cmp = {
enable = true;
sources = [
{name = "nvim_lsp_signature_help";}
{name = "nvim_lsp";}
{name = "nvim_lsp_document_symbol";}
{name = "path";}
{name = "treesitter";}
{name = "luasnip";}
{name = "emoji";}
];
mappingPresets = ["insert"];
mapping = {
"<CR>" = ''
cmp.mapping.confirm({
behavior = cmp.ConfirmBehavior.Replace,
select = false,
})
'';
"<C-d>" = "cmp.mapping.scroll_docs(-4)";
"<C-f>" = "cmp.mapping.scroll_docs(4)";
"<C-e>" = "cmp.mapping.abort()";
"<Tab>" = {
modes = ["i" "s"];
action = ''
function(fallback)
local has_words_before = function()
local line, col = table.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
if cmp.visible() then
cmp.select_next_item()
elseif require("luasnip").expandable() then
require("luasnip").expand()
elseif require("luasnip").expand_or_locally_jumpable() then
require("luasnip").expand_or_jump()
elseif has_words_before() then
cmp.complete()
else
fallback()
end
end
'';
};
"<S-Tab>" = {
modes = ["i" "s"];
action = ''
function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end
'';
};
};
formatting.fields = ["abbr" "kind" "menu"];
formatting.format = ''
function(_, vim_item)
local icons = {
Namespace = "󰌗",
Text = "󰉿",
Method = "󰆧",
Function = "󰆧",
Constructor = "",
Field = "󰜢",
Variable = "󰀫",
Class = "󰠱",
Interface = "",
Module = "",
Property = "󰜢",
Unit = "󰑭",
Value = "󰎠",
Enum = "",
Keyword = "󰌋",
Snippet = "",
Color = "󰏘",
File = "󰈚",
Reference = "󰈇",
Folder = "󰉋",
EnumMember = "",
Constant = "󰏿",
Struct = "󰙅",
Event = "",
Operator = "󰆕",
TypeParameter = "󰊄",
Table = "",
Object = "󰅩",
Tag = "",
Array = "󰅪",
Boolean = "",
Number = "",
Null = "󰟢",
String = "󰉿",
Calendar = "",
Watch = "󰥔",
Package = "",
Copilot = "",
Codeium = "",
TabNine = "",
}
vim_item.kind = string.format("%s %s", icons[vim_item.kind], vim_item.kind)
return vim_item
end
'';
snippet.expand = "luasnip";
};
# TODO use "ray-x/lsp_signature.nvim"
# TODO dap.enable = true;
# -------------------------------------------------------------------------------------------------
# Miscellaneous
# -------------------------------------------------------------------------------------------------
# Quickfix menu
trouble.enable = true;
# Highlight certain keywords
todo-comments.enable = true;
# TODO use { "liuchengxu/vista.vim", cmd = "Vista" }
which-key.enable = true;
};
extraPlugins = with pkgs.vimPlugins; [
# navarasu's one dark
onedark-nvim
telescope-ui-select-nvim
nvim-web-devicons
nvim-window-picker
# Replace built-in LSP prompts and windows
dressing-nvim
# Multicursor
vim-visual-multi
# Show invalid whitespace
vim-better-whitespace
# Show latex math equations
nabla-nvim
# Modify Surrounding things like parenthesis and quotes
vim-sandwich
# TODO mini.align better?
vim-easy-align
# Case changer
text-case-nvim
# camelcase (and similar) word motions and textobjects
vim-wordmotion
# Gpg integration
vim-gnupg
# TODO temporary
vim-startuptime
];
extraConfigLuaPre = ''
vim.g.operator_sandwich_no_default_key_mappings = 1
vim.g.textobj_sandwich_no_default_key_mappings = 1
vim.g.wordmotion_nomap = 1
'';
extraConfigLua = ''
local onedark = require "onedark"
onedark.setup {
toggle_style_key = "<nop>",
colors = {
fg = "#abb2bf",
black = "#181a1f",
bg0 = "#1e222a",
bg1 = "#252931",
bg2 = "#282c34",
bg3 = "#353b45",
bg_d = "#191c21",
bg_blue = "#73b8f1",
bg_yellow = "#ebd09c",
dark_cyan = "#2b6f77",
dark_red = "#993939",
dark_yellow = "#93691d",
grey = "#42464e",
grey_fg = "#565c64",
grey_fg2 = "#6f737b",
light_grey = "#6f737b",
baby_pink = "#de8c92",
pink = "#ff75a0",
nord_blue = "#81a1c1",
sun = "#ebcb8b",
light_purple = "#de98fd",
dark_purple = "#c882e7",
teal = "#519aba",
dark_pink = "#fca2aa",
light_blue = "#a3b8ef",
vibrant_green = "#7eca9c",
red = "#e06c75",
orange = "#d19a66",
yellow = "#e5c07b",
green = "#98c379",
cyan = "#56b6c2",
blue = "#61afef",
purple = "#c678dd",
diff_add = "#31392b",
diff_delete = "#382b2c",
diff_change = "#1c3448",
diff_text = "#2c5372",
},
highlights = {
CursorLine = { bg = "$bg0" },
FloatBorder = { fg = "$blue" },
NeoTreeTabActive = { fg = "$fg", bg = "$bg_d" },
NeoTreeTabInactive = { fg = "$grey", bg = "$black" },
NeoTreeTabSeparatorActive = { fg = "$black", bg = "$black" },
NeoTreeTabSeparatorInactive = { fg = "$black", bg = "$black" },
NeoTreeWinSeparator = { fg = "$bg_d", bg = "$bg_d" },
NeoTreeVertSplit = { fg = "$bg_d", bg = "$bg_d" },
VisualMultiMono = { fg = "$purple", bg = "$diff_change" },
VisualMultiExtend = { bg = "$diff_change" },
VisualMultiCursor = { fg = "$purple", bg = "$diff_change" },
VisualMultiInsert = { fg = "$blue", bg = "$diff_change" },
},
}
vim.g.VM_Mono_hl = "VisualMultiMono"
vim.g.VM_Extend_hl = "VisualMultiExtend"
vim.g.VM_Cursor_hl = "VisualMultiCursor"
vim.g.VM_Insert_hl = "VisualMultiInsert"
onedark.load()
'';
extraConfigLuaPost = ''
require("nvim-web-devicons").setup {
override = {
default_icon = { icon = "󰈚", name = "Default", },
c = { icon = "", name = "c", },
css = { icon = "", name = "css", },
dart = { icon = "", name = "dart", },
deb = { icon = "", name = "deb", },
Dockerfile = { icon = "", name = "Dockerfile", },
html = { icon = "", name = "html", },
jpeg = { icon = "󰉏", name = "jpeg", },
jpg = { icon = "󰉏", name = "jpg", },
js = { icon = "󰌞", name = "js", },
kt = { icon = "󱈙", name = "kt", },
lock = { icon = "󰌾", name = "lock", },
lua = { icon = "", name = "lua", },
mp3 = { icon = "󰎆", name = "mp3", },
mp4 = { icon = "", name = "mp4", },
out = { icon = "", name = "out", },
png = { icon = "󰉏", name = "png", },
py = { icon = "", name = "py", },
["robots.txt"] = { icon = "󰚩", name = "robots", },
toml = { icon = "", name = "toml", },
ts = { icon = "󰛦", name = "ts", },
ttf = { icon = "", name = "TrueTypeFont", },
rb = { icon = "", name = "rb", },
rpm = { icon = "", name = "rpm", },
vue = { icon = "󰡄", name = "vue", },
woff = { icon = "", name = "WebOpenFontFormat", },
woff2 = { icon = "", name = "WebOpenFontFormat2", },
xz = { icon = "", name = "xz", },
zip = { icon = "", name = "zip", },
},
default = true,
}
local cmp = require "cmp"
cmp.setup.cmdline(":", {
mapping = cmp.mapping.preset.cmdline(),
sources = {
{ name = "cmdline" },
{ name = "cmp-cmdline-history" },
},
})
require("window-picker").setup {
hint = "floating-big-letter",
filter_rules = {
bo = {
filetype = { "neo-tree", "neo-tree-popup", "notify", "quickfix" },
buftype = { "terminal", "quickfix", "prompt" },
},
},
floating_big_letter = {
font = "ansi-shadow",
},
selection_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
show_prompt = false,
}
require("dressing").setup {
input = {
prefer_width = 80,
max_width = { 140, 0.9 },
min_width = { 80, 0.6 },
win_options = {
winblend = 0,
},
},
}
'';
});
home.packages = let
nvimConfig = pkgs.neovimUtils.makeNeovimConfig {
wrapRc = false;
withPython3 = true;
withRuby = true;
withNodeJs = true;
extraPython3Packages = p: with p; [openai];
};
in [(pkgs.wrapNeovimUnstable pkgs.neovim-unwrapped nvimConfig)];
};
home.sessionVariables.EDITOR = "nvim";
home.shellAliases.vimdiff = "nvim -d";
xdg.configFile = {
"nvim/ftplugin".source = ./ftplugin;
"nvim/init.lua".source = ./init.lua;
"nvim/lua".source = ./lua;
};
}