Initial commit

This commit is contained in:
stherm 2026-03-06 08:31:13 +01:00
commit 430194beda
109 changed files with 9066 additions and 0 deletions

View file

@ -0,0 +1,106 @@
{
inputs,
config,
lib,
...
}:
let
cfg = config.programs.nixvim;
inherit (lib) mkDefault mkIf;
in
{
imports = [
inputs.nixvim.nixosModules.nixvim
./plugins
./spellfiles.nix
];
config = {
programs.nixvim = {
enable = true; # Enable globally on NixOS
defaultEditor = mkDefault true;
viAlias = mkDefault true;
vimAlias = mkDefault true;
# Removed home-manager specific options like 'enableMan' which is handled differently or not needed in system module context
# Removed clipboard.providers.wl-copy as it's home-manager specific.
# System-wide clipboard integration for headless servers is less critical but can be added if needed.
# vim.g.*
globals = {
mapleader = mkDefault " ";
};
# vim.opt.*
opts = {
# behavior
cursorline = mkDefault true; # highlights the line under the cursor
mouse = mkDefault "a"; # enable mouse support
nu = mkDefault true; # line numbers
relativenumber = mkDefault true; # relative line numbers
scrolloff = mkDefault 20; # keeps some context above/below cursor
signcolumn = mkDefault "yes"; # reserve space for signs (e.g., GitGutter)
undofile = mkDefault true; # persistent undo
updatetime = mkDefault 500; # ms to wait for trigger an event (default 4000ms)
wrap = mkDefault true; # wraps text if it exceeds the width of the window
# search
ignorecase = mkDefault true; # ignore case in search patterns
smartcase = mkDefault true; # smart case
incsearch = mkDefault true; # incremental search
hlsearch = mkDefault true; # highlight search
# windows
splitbelow = mkDefault true; # new windows are created below current
splitright = mkDefault true; # new windows are created to the right of current
equalalways = mkDefault true; # window sizes are automatically updated.
# tabs
expandtab = mkDefault true; # convert tabs into spaces
shiftwidth = mkDefault 2; # number of spaces to use for each step of (auto)indent
smartindent = mkDefault true; # smart autoindenting on new lines
softtabstop = mkDefault 2; # number of spaces in tab when editing
tabstop = mkDefault 2; # number of visual spaces per tab
# spell checking
spell = mkDefault true;
spelllang = mkDefault [
"en_us"
"de_20"
];
};
# vim.diagnostic.config.*
diagnostic.settings = {
virtual_text = {
spacing = 4;
prefix = "";
severity_sort = true;
};
signs = true;
underline = true;
update_in_insert = false;
};
extraConfigLua = ''
vim.cmd "set noshowmode" -- Hides "--INSERT--" mode indicator
'';
keymaps = import ./keymaps.nix;
};
environment = {
variables = {
EDITOR = mkIf cfg.enable "nvim";
VISUAL = mkIf cfg.enable "nvim";
};
shellAliases = {
v = mkIf cfg.enable "nvim";
};
};
};
}

View file

@ -0,0 +1,347 @@
[
# cursor navigation
{
# scroll down, recenter
key = "<C-d>";
action = "<C-d>zz";
mode = "n";
}
{
# scroll up, recenter
key = "<C-u>";
action = "<C-u>zz";
mode = "n";
}
# searching
{
# center cursor after search next
key = "n";
action = "nzzzv";
mode = "n";
}
{
# center cursor after search previous
key = "N";
action = "Nzzzv";
mode = "n";
}
{
# ex command
key = "<leader>pv";
action = "<cmd>Ex<CR>";
mode = "n";
}
# search and replace
{
# search and replace word under cursor
key = "<leader>s";
action = ":%s/<C-r><C-w>/<C-r><C-w>/gI<Left><Left><Left>";
mode = "n";
}
# search and replace selected text
{
key = "<leader>s";
action = "y:%s/<C-r>0/<C-r>0/gI<Left><Left><Left>";
mode = "v";
}
# clipboard operations
{
# copy to system clipboard in visual mode
key = "<C-c>";
action = ''"+y '';
mode = "v";
}
{
# paste from system clipboard in visual mode
key = "<C-v>";
action = ''"+p '';
mode = "v";
}
{
# yank to system clipboard
key = "<leader>Y";
action = "+Y";
mode = "n";
}
{
# replace selected text with clipboard content
key = "<leader>p";
action = "_dP";
mode = "x";
}
{
# delete without copying to clipboard
key = "<leader>d";
action = "_d";
mode = [
"n"
"v"
];
}
# line operations
{
# move lines down in visual mode
key = "J";
action = ":m '>+1<CR>gv=gv";
mode = "v";
}
{
# move lines up in visual mode
key = "K";
action = ":m '<-2<CR>gv=gv";
mode = "v";
}
{
# join lines
key = "J";
action = "mzJ`z";
mode = "n";
}
# quickfix
{
# Run make command
key = "<leader>m";
action = "<cmd>:make<CR>";
mode = "n";
}
{
# previous quickfix item
key = "<C-A-J>";
action = "<cmd>cprev<CR>zz";
mode = "n";
}
{
# next quickfix item
key = "<C-A-K>";
action = "<cmd>cnext<CR>zz";
mode = "n";
}
# location list navigation
{
# previous location list item
key = "<leader>j";
action = "<cmd>lprev<CR>zz";
mode = "n";
}
{
# next location list item
key = "<leader>k";
action = "<cmd>lnext<CR>zz";
mode = "n";
}
# disabling keys
{
# disable the 'Q' key
key = "Q";
action = "<nop>";
mode = "n";
}
# text selection
{
# select whole buffer
key = "<C-a>";
action = "ggVG";
mode = "n";
}
# window operations
{
# focus next window
key = "<C-j>";
action = ":wincmd W<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
{
# focus previous window
key = "<C-k>";
action = ":wincmd w<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
# window size adjustments
{
# increase window width
key = "<C-l>";
action = ":vertical resize +5<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
{
# decrease window width
key = "<C-h>";
action = ":vertical resize -5<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
# window closing and opening
{
# close current window
key = "<leader-S>c";
action = ":q<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
{
# new vertical split at $HOME
key = "<leader>n";
action = ":vsp $HOME<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
# window split orientation toggling
{
# toggle split orientation
key = "<leader>t";
action = ":wincmd T<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
# spell checking
{
# toggle spell checking
key = "<leader>ss";
action = ":setlocal spell!<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
{
# switch to english spell checking
key = "<leader>se";
action = ":setlocal spelllang=en_us<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
{
# switch to german spell checking
key = "<leader>sg";
action = ":setlocal spelllang=de_20<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
{
# move to next misspelling
key = "]s";
action = "]szz";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
{
# move to previous misspelling
key = "[s";
action = "[szz";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
{
# correction suggestions for a misspelled word
key = "z=";
action = "z=";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
{
# adding words to the dictionary
key = "zg";
action = "zg";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
# buffer navigation
{
# next buffer
key = "<C-S-J>";
action = ":bnext<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
{
# previous buffer
key = "<C-S-K>";
action = ":bprevious<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
{
# close current buffer
key = "<leader>bd";
action = ":bdelete<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
{
# apply code action
key = "<leader>ca";
action = ":lua vim.lsp.buf.code_action()<CR>";
options = {
noremap = true;
silent = true;
};
mode = "n";
}
]

View file

@ -0,0 +1,54 @@
{ config, lib, ... }:
let
cfg = config.programs.nixvim;
plugin = cfg.plugins.cmp;
inherit (lib) mkDefault mkIf;
in
{
programs.nixvim = {
plugins = {
cmp = {
enable = mkDefault true;
settings = {
autoEnableSources = mkDefault true;
experimental.ghost_text = mkDefault true;
snippet.expand = mkDefault "luasnip";
formatting.fields = mkDefault [
"kind"
"abbr"
"menu"
];
sources = [
{ name = "git"; }
{ name = "nvim_lsp"; }
{
name = "buffer";
option.get_bufnrs.__raw = "vim.api.nvim_list_bufs";
keywordLength = 3;
}
{
name = "path";
keywordLength = 3;
}
{ name = "luasnip"; }
];
mapping = {
"<C-Space>" = "cmp.mapping.complete()";
"<C-d>" = "cmp.mapping.scroll_docs(-4)";
"<C-e>" = "cmp.mapping.close()";
"<C-f>" = "cmp.mapping.scroll_docs(4)";
"<C-CR>" = "cmp.mapping.confirm({ select = true })";
"<S-Tab>" = "cmp.mapping(cmp.mapping.select_prev_item(), {'i', 's'})";
"<Tab>" = "cmp.mapping(cmp.mapping.select_next_item(), {'i', 's'})";
};
};
};
cmp-cmdline = mkIf plugin.enable { enable = mkDefault false; }; # autocomplete for cmdline
cmp_luasnip = mkIf plugin.enable { enable = mkDefault true; };
luasnip = mkIf plugin.enable { enable = mkDefault true; };
cmp-treesitter = mkIf (plugin.enable && cfg.plugins.treesitter.enable) { enable = mkDefault true; };
};
};
}

View file

@ -0,0 +1,18 @@
{ lib, ... }:
{
imports = [
./cmp.nix
./lsp.nix
./lualine.nix
./telescope.nix
# ./treesitter.nix # HOTFIX: does not build
./trouble.nix
];
config.programs.nixvim.plugins = {
markdown-preview.enable = lib.mkDefault true;
# warning: Nixvim: `plugins.web-devicons` was enabled automatically because the following plugins are enabled. This behaviour is deprecated. Please explicitly define `plugins.web-devicons.enable`
web-devicons.enable = true;
};
}

View file

@ -0,0 +1,69 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.nixvim;
plugin = cfg.plugins.lsp;
inherit (lib) mkDefault mkIf optional;
in
{
config = {
programs.nixvim = {
plugins = {
lsp-format = mkIf plugin.enable { enable = mkDefault true; };
lsp = {
enable = mkDefault true;
postConfig = "";
keymaps = {
silent = mkDefault true;
diagnostic = mkDefault {
# Navigate in diagnostics
"<leader>k" = "goto_prev";
"<leader>j" = "goto_next";
};
lspBuf = mkDefault {
gd = "definition";
gD = "references";
gt = "type_definition";
gi = "implementation";
K = "hover";
"<F2>" = "rename";
};
};
servers = {
bashls.enable = mkDefault true;
clangd.enable = mkDefault true;
cssls.enable = mkDefault true;
dockerls.enable = mkDefault true;
gopls.enable = mkDefault true;
html.enable = mkDefault true;
jsonls.enable = mkDefault true;
nixd.enable = mkDefault true;
pyright.enable = mkDefault true;
rust_analyzer = {
enable = mkDefault true;
installCargo = mkDefault true;
installRustc = mkDefault true;
settings.rustfmt.overrideCommand = mkDefault [
"${pkgs.rustfmt}/bin/rustfmt --edition 2021" # --config tab_spaces=2"
];
};
texlab.enable = mkDefault true;
vhdl_ls.enable = mkDefault true;
yamlls.enable = mkDefault true;
};
};
};
};
home.packages = optional (cfg.enable && plugin.servers.nixd.enable) pkgs.nixfmt;
};
}

View file

@ -0,0 +1,18 @@
{ config, lib, ... }:
let
cfg = config.programs.nixvim;
plugin = cfg.plugins.lualine;
inherit (lib) mkDefault;
in
{
config = {
programs.nixvim = {
plugins.lualine = {
enable = mkDefault true;
settings.options.icons_enabled = mkDefault false;
};
};
};
}

View file

@ -0,0 +1,52 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.nixvim;
plugin = cfg.plugins.telescope;
inherit (lib) mkDefault optionals;
in
{
config = {
programs.nixvim = {
plugins.telescope = {
enable = mkDefault true;
extensions = {
file-browser.enable = mkDefault true;
fzf-native.enable = mkDefault true;
live-grep-args.enable = mkDefault true;
manix.enable = mkDefault true;
};
keymaps = mkDefault {
"<C-e>" = "file_browser";
"<C-p>" = "git_files";
"<leader>bl" = "buffers";
"<leader>fd" = "diagnostics";
"<leader>ff" = "find_files";
"<leader>fg" = "live_grep";
"<leader>fh" = "help_tags";
"<leader>fm" = "man_pages";
"<leader>fn" = "manix";
"<leader>fo" = "oldfiles";
"<space>fb" = "file_browser";
};
};
keymaps = optionals plugin.enable [
{
key = "<C-f>";
action = ":lua require('telescope').extensions.live_grep_args.live_grep_args()<CR>";
mode = "n";
}
];
};
home.packages = optionals plugin.enable [
pkgs.ripgrep # for "live_grep"
];
};
}

View file

@ -0,0 +1,42 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.nixvim;
plugin = cfg.plugins.treesitter;
cc = "${pkgs.gcc}/bin/gcc";
inherit (lib) mkDefault mkIf;
in
{
config = {
programs.nixvim = {
plugins.treesitter = {
enable = mkDefault true;
nixvimInjections = mkDefault true;
settings = {
folding.enable = mkDefault true;
highlight.enable = mkDefault true;
indent.enable = mkDefault true;
};
};
plugins.treesitter-context = mkIf plugin.enable { enable = mkDefault true; };
plugins.treesitter-textobjects = mkIf plugin.enable { enable = mkDefault true; };
};
# Fix for: ERROR `cc` executable not found.
home.sessionVariables = mkIf plugin.enable {
CC = mkDefault cc;
};
# Fix for: WARNING `tree-sitter` executable not found
home.packages = mkIf plugin.enable [
plugin.package
];
};
}

View file

@ -0,0 +1,43 @@
{ config, lib, ... }:
let
cfg = config.programs.nixvim;
plugin = cfg.plugins.trouble;
inherit (lib) mkDefault mkIf;
in
{
config = {
programs.nixvim = {
plugins.trouble = {
enable = mkDefault true;
};
keymaps = mkIf plugin.enable [
{
mode = "n";
key = "<leader>xq";
action = "<CMD>Trouble qflist toggle<CR>";
options = {
desc = "Trouble quifick toggle";
};
}
{
mode = "n";
key = "<leader>xl";
action = "<CMD>Trouble loclist toggle<CR>";
options = {
desc = "Trouble loclist toggle";
};
}
{
mode = "n";
key = "<leader>xx";
action = "<CMD>Trouble diagnostics toggle<CR>";
options = {
desc = "Trouble diagnostics toggle";
};
}
];
};
};
}

View file

@ -0,0 +1,26 @@
{ config, pkgs, ... }:
let
spellDir = config.xdg.dataHome + "/nvim/site/spell";
baseUrl = "http://ftp.de.vim.org/runtime/spell";
in
{
home.file = {
de-spl = {
enable = true;
source = pkgs.fetchurl {
url = baseUrl + "/de.utf-8.spl";
sha256 = "sha256-c8cQfqM5hWzb6SHeuSpFk5xN5uucByYdobndGfaDo9E=";
};
target = spellDir + "/de.utf8.spl";
};
de-sug = {
enable = true;
source = pkgs.fetchurl {
url = baseUrl + "/de.utf-8.sug";
sha256 = "sha256-E9Ds+Shj2J72DNSopesqWhOg6Pm6jRxqvkerqFcUqUg=";
};
target = spellDir + "/de.utf8.sug";
};
};
}