commit fee1650bef91021d709ba98ae2f9e55cb7689067
parent 7cab67b466c0d9778e0f9d66d71d22d02729572f
Author: Chris <chris@echoz.io>
Date: Sun, 22 Feb 2026 21:44:16 +0100
refactor: restructure vim config
Diffstat:
22 files changed, 389 insertions(+), 404 deletions(-)
diff --git a/modules/neovim/default.nix b/modules/neovim/default.nix
@@ -1,180 +1,31 @@
{
lib,
pkgs,
+ config,
...
}:
-let
- runtime = luaRuntime // lspRuntime // ftpluginRuntime // treesitterRuntime;
-
- initLua = generateInitLua runtime {
- cheat-sheet.file = ./cheat-sheet.txt;
- init = { };
- };
-
- luaRuntime = importLuaDir "lua" ./lua;
- ftpluginRuntime = importLuaDir "ftplugin" ./ftplugin;
-
- lspRuntime = generateLspRuntime {
- nixd = {
- cmd = [ (lib.getExe pkgs.nixd) ];
- filetypes = [ "nix" ];
- root_markers = [
- "flake.nix"
- ".git"
- ];
- settings.nixd.formatting.command = [ (lib.getExe pkgs.nixfmt) ];
- };
-
- gopls = {
- cmd = [ (lib.getExe pkgs.gopls) ];
- filetypes = [
- "go"
- "gomod"
- "gowork"
- "gotmpl"
- ];
- root_markers = [
- "go.work"
- "go.mod"
- ".git"
- ];
- };
-
- typescript-language-server = {
- cmd = [
- (lib.getExe pkgs.typescript-language-server)
- "--stdio"
- ];
- filetypes = [
- "javascript"
- "typescript"
- ];
- root_markers = [
- [
- "jsconfig.json"
- "tsconfig.json"
- ]
- "package.json"
- ".git"
- ];
- init_options.hostInfo = "neovim";
- };
+{
+ imports = lib.pipe ./plugins [
+ builtins.readDir
+ (lib.filterAttrs (name: type: type == "regular"))
+ builtins.attrNames
+ (builtins.filter (name: !isNull (builtins.match "^.*\.nix$" name)))
+ (map (name: ./plugins + "/${name}"))
+ ];
- ruff = {
- cmd = [
- (lib.getExe pkgs.ruff)
- "server"
- ];
- filetypes = [ "python" ];
- root_markers = [
- "pyproject.toml"
- "ruff.toml"
- ".ruff.toml"
- ".git"
- ];
+ options.programs.neovim = {
+ plugins = lib.mkOption {
+ type = with lib.types; listOf pathInStore;
};
- basedpyright = {
- cmd = [
- (lib.getExe' pkgs.basedpyright "basedpyright-langserver")
- "--stdio"
- ];
- filetypes = [ "python" ];
- root_markers = [
- "pyrightconfig.json"
- "pyproject.toml"
- "setup.py"
- ".git"
- ];
- settings.basedpyright = {
- analysis.typeCheckingMode = "basic";
- };
- };
-
- lua-language-server = {
- cmd = [ (lib.getExe pkgs.lua-language-server) ];
- filetypes = [ "lua" ];
- settings.Lua."diagnostics.globals" = [ "vim" ];
+ customPlugins = lib.mkOption {
+ type = with lib.types; attrsOf (attrsOf str);
};
};
- treesitterRuntime =
- let
- languages = [
- "typescript"
- "javascript"
- "nix"
- "lua"
- "go"
- "python"
- ];
-
- grammars = pkgs.symlinkJoin {
- name = "neovim-grammars";
- paths = lib.mapAttrsToList (_: grammar: pkgs.neovimUtils.grammarToPlugin grammar) (
- lib.filterAttrs (
- _: drv:
- lib.isDerivation drv
- && builtins.elem (builtins.head (builtins.match "^tree-sitter-(.*)$" drv.pname)) languages
- ) pkgs.tree-sitter-grammars
- );
- };
- in
- {
- parser.source = grammars + "/parser";
- queries.source = grammars + "/queries";
- };
-
- generateLspRuntime =
- lsps:
- (lib.mapAttrs' (name: config: {
- name = "lsp/${name}.lua";
- value.text = "return ${lib.generators.toLua { } config}";
- }) lsps)
- // {
- "lua/lsp.lua".text = ''
- local M = {}
- function M.setup()
- vim.lsp.enable(${lib.generators.toLua { indent = " "; } (builtins.attrNames lsps)})
- end
- return M
- '';
- };
-
- importLuaDir =
- prefix: path:
- lib.pipe (builtins.readDir path) [
- (lib.mapAttrs' (
- name: type: {
- name = "${prefix}/${name}";
- value =
- if type == "regular" && builtins.match "^.*.lua$" name != null then
- { source = path + "/${name}"; }
- else
- null;
- }
- ))
- (lib.filterAttrs (_: value: value != null))
- ];
-
- generateInitLua =
- runtime: args:
- lib.pipe runtime [
- builtins.attrNames
- (builtins.map (builtins.match "^lua/(.*).lua$"))
- (builtins.filter builtins.isList)
- (builtins.map builtins.head)
- (builtins.map (name: "require('${name}').setup(${lib.generators.toLua { } (args.${name} or { })})"))
- (builtins.concatStringsSep "\n")
- ];
-in
-{
- programs.neovim = {
+ config.programs.neovim = {
enable = true;
- inherit runtime;
- configure.customLuaRC = initLua;
-
defaultEditor = true;
viAlias = true;
vimAlias = true;
@@ -188,9 +39,23 @@ in
src = pkgs.fetchFromGitHub {
owner = "neovim";
repo = "neovim";
- rev = "e4ce0c7270e52ecaf586a0ddcee262e2f1adaabc";
- hash = "sha256-orLpmRiDOsxYOOm8hYvpy7bgDURC/gzvGgy/hz4aDHs=";
+ rev = "ea3942f222789c0ad16befc61071f883052d8099";
+ hash = "sha256-d5KmAKiqhiXtfQDTzlp0Ci7s0hkX4pfA0KTXora8LEk=";
};
};
+
+ configure.packages.plugins.start =
+ let
+ writeVimPlugin =
+ name: files:
+ pkgs.vimUtils.toVimPlugin (
+ pkgs.symlinkJoin {
+ inherit name;
+ paths = lib.mapAttrsToList pkgs.writeTextDir files;
+ }
+ );
+ in
+ config.programs.neovim.plugins
+ ++ (lib.mapAttrsToList writeVimPlugin config.programs.neovim.customPlugins);
};
}
diff --git a/modules/neovim/ftplugin/mail.lua b/modules/neovim/ftplugin/mail.lua
@@ -1 +0,0 @@
-vim.opt.textwidth = 72
diff --git a/modules/neovim/lua/cheat-sheet.lua b/modules/neovim/lua/cheat-sheet.lua
@@ -1,32 +0,0 @@
-local M = {}
-
-function M.setup(opts)
- M.file = opts.file or "/dev/null"
- M.lines = {}
-
- for line in io.lines(M.file) do
- table.insert(M.lines, line)
- end
-
- vim.keymap.set({'n','v'}, '<C-/>', function()
- local buf = vim.api.nvim_create_buf(false, true)
- vim.api.nvim_buf_set_keymap(buf, 'n', 'q', ':q<CR>', {
- silent = true,
- nowait = true,
- })
- vim.api.nvim_buf_set_lines(buf, 0, -1, false, M.lines)
- local win = vim.api.nvim_open_win(buf, true, {
- title = 'Cheat sheet',
- relative = 'editor',
- row = math.floor(vim.o.lines * 0.10),
- col = math.floor(vim.o.columns * 0.10),
- height = math.floor(vim.o.lines * 0.80),
- width = math.floor(vim.o.columns * 0.80),
- style = 'minimal',
- title_pos = 'center',
- focusable = true,
- })
- end)
-end
-
-return M
diff --git a/modules/neovim/lua/code.lua b/modules/neovim/lua/code.lua
@@ -1,20 +0,0 @@
-local M = {}
-
-function M.setup()
- vim.opt.signcolumn = "yes"
- vim.opt.completeopt = { "fuzzy", "menu", "menuone", "noinsert", "popup" }
-
- vim.diagnostic.config({ virtual_text = true })
-
- vim.lsp.config('*', {
- root_markers = { '.git' },
- on_attach = function(client, bufnr)
- vim.lsp.completion.enable(true, client.id, bufnr, {})
- end,
- })
-
- vim.keymap.set({ 'n', 'v' }, 'gqb', vim.lsp.buf.format)
- vim.keymap.set({ 'n', 'v' }, '<C-W>a', vim.diagnostic.setloclist)
-end
-
-return M
diff --git a/modules/neovim/lua/general.lua b/modules/neovim/lua/general.lua
@@ -1,19 +0,0 @@
-local M = {}
-
-function M.setup()
- vim.opt.tabstop = 2
- vim.opt.shiftwidth = 2
- vim.opt.expandtab = true
-
- vim.opt.number = true
- vim.opt.relativenumber = true
-
- vim.opt.scrolloff = 5
-
- vim.opt.cursorline = true
- vim.opt.textwidth = 100
- vim.opt.colorcolumn = '+1'
- vim.opt.formatoptions = 'cqj'
-end
-
-return M
diff --git a/modules/neovim/lua/listchars.lua b/modules/neovim/lua/listchars.lua
@@ -1,31 +0,0 @@
-local M = {}
-
-function M.setup()
- vim.opt.list = true
- vim.opt.listchars = {
- trail = '~',
- tab = '| ',
- leadmultispace = ':' .. string.rep(' ', vim.opt.shiftwidth:get() - 1),
- }
-
- local function update()
- local listchars = vim.opt_local.listchars:get()
- listchars.leadmultispace = ':' .. string.rep(' ', vim.opt_local.shiftwidth:get() - 1)
- vim.opt_local.listchars = listchars
- end
-
- local group = vim.api.nvim_create_augroup('ListcharsLeadmultispaceWidth', { clear = true }),
-
- vim.api.nvim_create_autocmd('OptionSet', {
- group = group,
- pattern = 'shiftwidth',
- callback = update,
- })
-
- vim.api.nvim_create_autocmd({ 'FileType', 'BufWinEnter' }, {
- group = group,
- callback = update,
- })
-end
-
-return M
diff --git a/modules/neovim/lua/netrw.lua b/modules/neovim/lua/netrw.lua
@@ -1,13 +0,0 @@
-local M = {}
-
-function M.setup()
- vim.g.netrw_banner = 0
-
- -- absolute 30 cols/rows
- vim.g.netrw_winsize = -30
-
- -- tree style
- vim.g.netrw_liststyle = 3
-end
-
-return M
diff --git a/modules/neovim/lua/return-to-last-line.lua b/modules/neovim/lua/return-to-last-line.lua
@@ -1,15 +0,0 @@
-local M = {}
-
-function M.setup()
- vim.api.nvim_create_autocmd('BufReadPost', {
- group = vim.api.nvim_create_augroup('ReturnToLastLine', { clear = true }),
- callback = function()
- local last = vim.fn.line([['"]])
- if last > 1 and last < vim.fn.line("$") then
- vim.cmd([[normal! g'"]])
- end
- end
- })
-end
-
-return M
diff --git a/modules/neovim/lua/style.lua b/modules/neovim/lua/style.lua
@@ -1,32 +0,0 @@
-local M = {}
-
-function M.setup()
- vim.api.nvim_set_hl(0, 'Normal', { bg='none' })
- vim.api.nvim_set_hl(0, 'StatusLine', { bg='none' })
- vim.api.nvim_set_hl(0, 'StatusLineNC', { bg='none', fg='gray' })
- vim.api.nvim_set_hl(0, 'WinBar', { bg='none' })
- vim.api.nvim_set_hl(0, 'WinBarNC', { bg='none', fg='gray' })
- vim.api.nvim_set_hl(0, 'NormalFloat', { bg='none' })
- vim.api.nvim_set_hl(0, 'FloatBorder', { bg='none' })
- vim.api.nvim_set_hl(0, 'Pmenu', { bg='none' })
- vim.api.nvim_set_hl(0, 'PmenuBorder', { bg='none' })
-
- vim.opt.winborder = "rounded";
- vim.opt.pumborder = "rounded";
-
- vim.opt.cmdheight = 0
-
- -- Raise cmdheight to make recording status visible
- vim.api.nvim_create_autocmd("RecordingEnter", {
- callback = function()
- vim.opt.cmdheight = 1
- end,
- })
- vim.api.nvim_create_autocmd("RecordingLeave", {
- callback = function()
- vim.opt.cmdheight = 0
- end,
- })
-end
-
-return M
diff --git a/modules/neovim/lua/system-clipboard.lua b/modules/neovim/lua/system-clipboard.lua
@@ -1,12 +0,0 @@
-local M = {}
-
-function M.setup()
- vim.keymap.set({'n','v'}, '<C-c>', '"+y')
- vim.keymap.set({'n','v'}, '<C-v>', '"+p')
- vim.keymap.set({'n','v'}, '<C-x>', '"+d')
-
- -- Use C-q for block visual mode
- vim.keymap.set({'n','v'}, '<C-q>', '<C-v>', { noremap = true})
-end
-
-return M
diff --git a/modules/neovim/lua/undodir.lua b/modules/neovim/lua/undodir.lua
@@ -1,8 +0,0 @@
-local M = {}
-
-function M.setup()
- vim.opt.undofile = true
- vim.opt.undodir = vim.fn.stdpath('data') .. '/undodir'
-end
-
-return M
diff --git a/modules/neovim/lua/wildmenu.lua b/modules/neovim/lua/wildmenu.lua
@@ -1,13 +0,0 @@
-local M = {}
-
-function M.setup()
- vim.opt.path = vim.o.path .. '**'
- vim.opt.wildmenu = true
- vim.opt.wildignore = {
- "**/.direnv/**",
- "**/node_modules/**",
- "**/vendor/**",
- };
-end
-
-return M
diff --git a/modules/neovim/lua/winbar.lua b/modules/neovim/lua/winbar.lua
@@ -1,42 +0,0 @@
-local M = {}
-
-function M.setup()
- vim.api.nvim_create_autocmd({'BufEnter', 'BufAdd', 'BufDelete', 'BufLeave', 'BufModifiedSet', 'BufWrite'}, {
- group = vim.api.nvim_create_augroup("WinBarBuffers", { clear = true }),
- pattern = "*",
- callback = function()
- local buffers = {}
- local current = vim.api.nvim_win_get_buf(0)
-
- for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
- if vim.bo[bufnr].buflisted then
- local name = vim.fn.fnamemodify(vim.fn.bufname(bufnr), ":t")
- if name == "" then name = "[No name]" end
-
- local highlight = bufnr == current and "WinBar" or "WinBarNC"
- local modified = vim.bo[bufnr].modified and "*" or ""
-
- table.insert(buffers, string.format(
- "%%#%s# %d:%s%s %%*",
- highlight, bufnr, name, modified
- ))
- end
- end
-
- if #buffers > 1 and vim.bo[current].buflisted then
- vim.opt_local.winbar = table.concat(buffers)
- vim.keymap.set({'n','v'}, '<C-n>', ':bn<cr>', { buffer = current })
- vim.keymap.set({'n','v'}, '<C-p>', ':bp<cr>', { buffer = current })
-
- else
- vim.opt_local.winbar = ""
- pcall(function()
- vim.keymap.del({'n','v'}, '<C-n>', { buffer = current })
- vim.keymap.del({'n','v'}, '<C-p>', { buffer = current })
- end)
- end
- end
- })
-end
-
-return M
diff --git a/modules/neovim/plugins/cheat-sheet.nix b/modules/neovim/plugins/cheat-sheet.nix
@@ -0,0 +1,33 @@
+{
+ programs.neovim.customPlugins.cheat-sheet = {
+ "plugin/cheat-sheet.lua" = # lua
+ ''
+ local file = '${../cheat-sheet.txt}'
+ local lines = {}
+
+ for line in io.lines(file) do
+ table.insert(lines, line)
+ end
+
+ vim.keymap.set({'n','v'}, '<C-/>', function()
+ local buf = vim.api.nvim_create_buf(false, true)
+ vim.api.nvim_buf_set_keymap(buf, 'n', 'q', ':q<CR>', {
+ silent = true,
+ nowait = true,
+ })
+ vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
+ local win = vim.api.nvim_open_win(buf, true, {
+ title = 'Cheat sheet',
+ relative = 'editor',
+ row = math.floor(vim.o.lines * 0.10),
+ col = math.floor(vim.o.columns * 0.10),
+ height = math.floor(vim.o.lines * 0.80),
+ width = math.floor(vim.o.columns * 0.80),
+ style = 'minimal',
+ title_pos = 'center',
+ focusable = true,
+ })
+ end)
+ '';
+ };
+}
diff --git a/modules/neovim/plugins/clipboard.nix b/modules/neovim/plugins/clipboard.nix
@@ -0,0 +1,13 @@
+{
+ programs.neovim.customPlugins.clipboard = {
+ "plugin/clipboard.nix" = # lua
+ ''
+ vim.keymap.set({'n','v'}, '<C-c>', '"+y')
+ vim.keymap.set({'n','v'}, '<C-v>', '"+p')
+ vim.keymap.set({'n','v'}, '<C-x>', '"+d')
+
+ -- Use C-q for block visual mode
+ vim.keymap.set({'n','v'}, '<C-q>', '<C-v>', { noremap = true})
+ '';
+ };
+}
diff --git a/modules/neovim/plugins/general.nix b/modules/neovim/plugins/general.nix
@@ -0,0 +1,36 @@
+{
+ programs.neovim.customPlugins.general = {
+ "plugin/general.lua" = # lua
+ ''
+ vim.opt.tabstop = 2
+ vim.opt.shiftwidth = 2
+ vim.opt.expandtab = true
+
+ vim.opt.number = true
+ vim.opt.relativenumber = true
+
+ vim.opt.scrolloff = 5
+
+ vim.opt.cursorline = true
+ vim.opt.textwidth = 100
+ vim.opt.colorcolumn = '+1'
+ vim.opt.formatoptions = 'cqj'
+
+ vim.opt.undofile = true
+ vim.opt.undodir = vim.fn.stdpath('data') .. '/undodir'
+
+ vim.opt.path = vim.o.path .. '**'
+ vim.opt.wildmenu = true
+ vim.opt.wildignore = {
+ "**/.direnv/**",
+ "**/node_modules/**",
+ "**/vendor/**",
+ };
+ '';
+
+ "ftplugin/mail.lua" = # lua
+ ''
+ vim.opt.textwidth = 72
+ '';
+ };
+}
diff --git a/modules/neovim/plugins/listchars.nix b/modules/neovim/plugins/listchars.nix
@@ -0,0 +1,32 @@
+{
+ programs.neovim.customPlugins.listchars = {
+ "plugin/listchars.lua" = # lua
+ ''
+ vim.opt.list = true
+ vim.opt.listchars = {
+ trail = '~',
+ tab = '| ',
+ leadmultispace = ':' .. string.rep(' ', vim.opt.shiftwidth:get() - 1),
+ }
+
+ local function update()
+ local listchars = vim.opt_local.listchars:get()
+ listchars.leadmultispace = ':' .. string.rep(' ', vim.opt_local.shiftwidth:get() - 1)
+ vim.opt_local.listchars = listchars
+ end
+
+ local group = vim.api.nvim_create_augroup('ListcharsLeadmultispaceWidth', { clear = true }),
+
+ vim.api.nvim_create_autocmd('OptionSet', {
+ group = group,
+ pattern = 'shiftwidth',
+ callback = update,
+ })
+
+ vim.api.nvim_create_autocmd({ 'FileType', 'BufWinEnter' }, {
+ group = group,
+ callback = update,
+ })
+ '';
+ };
+}
diff --git a/modules/neovim/plugins/lsp.nix b/modules/neovim/plugins/lsp.nix
@@ -0,0 +1,109 @@
+{
+ lib,
+ pkgs,
+ config,
+ ...
+}:
+{
+ options.programs.neovim.languageServers = lib.mkOption {
+ type = with lib.types; attrsOf anything;
+ };
+
+ config.programs.neovim = {
+ languageServers = {
+ nixd = {
+ cmd = [ (lib.getExe pkgs.nixd) ];
+ filetypes = [ "nix" ];
+ root_markers = [
+ "flake.nix"
+ ".git"
+ ];
+ settings.nixd.formatting.command = [ (lib.getExe pkgs.nixfmt) ];
+ };
+
+ gopls = {
+ cmd = [ (lib.getExe pkgs.gopls) ];
+ filetypes = [
+ "go"
+ "gomod"
+ ];
+ root_markers = [
+ "go.work"
+ "go.mod"
+ ".git"
+ ];
+ };
+
+ typescript-language-server = {
+ cmd = [
+ (lib.getExe pkgs.typescript-language-server)
+ "--stdio"
+ ];
+ filetypes = [
+ "javascript"
+ "typescript"
+ ];
+ root_markers = [
+ [
+ "jsconfig.json"
+ "tsconfig.json"
+ ]
+ "package.json"
+ ".git"
+ ];
+ init_options.hostInfo = "neovim";
+ };
+
+ basedpyright = {
+ cmd = [
+ (lib.getExe' pkgs.basedpyright "basedpyright-langserver")
+ "--stdio"
+ ];
+ filetypes = [ "python" ];
+ root_markers = [
+ "pyrightconfig.json"
+ "pyproject.toml"
+ "setup.py"
+ ".git"
+ ];
+ settings.basedpyright = {
+ analysis.typeCheckingMode = "basic";
+ };
+ };
+
+ lua-language-server = {
+ cmd = [ (lib.getExe pkgs.lua-language-server) ];
+ filetypes = [ "lua" ];
+ settings.Lua."diagnostics.globals" = [ "vim" ];
+ };
+ };
+
+ customPlugins.lsp = {
+ "plugin/lsp.lua" = # lua
+ ''
+ vim.opt.signcolumn = "yes"
+ vim.opt.completeopt = { "fuzzy", "menu", "menuone", "noinsert", "popup" }
+
+ vim.diagnostic.config({ virtual_text = true })
+
+ vim.lsp.config('*', {
+ root_markers = { '.git' },
+ on_attach = function(client, bufnr)
+ vim.lsp.completion.enable(true, client.id, bufnr, {})
+ end,
+ })
+
+ vim.keymap.set({ 'n', 'v' }, 'gqb', vim.lsp.buf.format)
+ vim.keymap.set({ 'n', 'v' }, '<C-W>a', vim.diagnostic.setloclist)
+
+ vim.lsp.enable(${
+ lib.generators.toLua { } (builtins.attrNames config.programs.neovim.languageServers)
+ })
+ '';
+ }
+ // (lib.mapAttrs' (name: config: {
+ name = "lsp/${name}.lua";
+ value = "return ${lib.generators.toLua { } config}";
+ }) config.programs.neovim.languageServers);
+ };
+}
diff --git a/modules/neovim/plugins/remember-position.nix b/modules/neovim/plugins/remember-position.nix
@@ -0,0 +1,16 @@
+{
+ programs.neovim.customPlugins.remember-position= {
+ "plugin/remember-position.lua" = # lua
+ ''
+ vim.api.nvim_create_autocmd('BufReadPost', {
+ group = vim.api.nvim_create_augroup('ReturnToLastLine', { clear = true }),
+ callback = function()
+ local last = vim.fn.line([['"]])
+ if last > 1 and last < vim.fn.line("$") then
+ vim.cmd([[normal! g'"]])
+ end
+ end
+ })
+ '';
+ };
+}
diff --git a/modules/neovim/plugins/style.nix b/modules/neovim/plugins/style.nix
@@ -0,0 +1,33 @@
+{
+ programs.neovim.customPlugins.style = {
+ "plugin/style.lua" = # lua
+ ''
+ vim.api.nvim_set_hl(0, 'Normal', { bg='none' })
+ vim.api.nvim_set_hl(0, 'StatusLine', { bg='none' })
+ vim.api.nvim_set_hl(0, 'StatusLineNC', { bg='none', fg='gray' })
+ vim.api.nvim_set_hl(0, 'WinBar', { bg='none' })
+ vim.api.nvim_set_hl(0, 'WinBarNC', { bg='none', fg='gray' })
+ vim.api.nvim_set_hl(0, 'NormalFloat', { bg='none' })
+ vim.api.nvim_set_hl(0, 'FloatBorder', { bg='none' })
+ vim.api.nvim_set_hl(0, 'Pmenu', { bg='none' })
+ vim.api.nvim_set_hl(0, 'PmenuBorder', { bg='none' })
+
+ vim.opt.winborder = "rounded";
+ vim.opt.pumborder = "rounded";
+
+ vim.opt.cmdheight = 0
+
+ -- Raise cmdheight to make recording status visible
+ vim.api.nvim_create_autocmd("RecordingEnter", {
+ callback = function()
+ vim.opt.cmdheight = 1
+ end,
+ })
+ vim.api.nvim_create_autocmd("RecordingLeave", {
+ callback = function()
+ vim.opt.cmdheight = 0
+ end,
+ })
+ '';
+ };
+}
diff --git a/modules/neovim/plugins/tree-sitter.nix b/modules/neovim/plugins/tree-sitter.nix
@@ -0,0 +1,40 @@
+{ pkgs, ... }:
+{
+ programs.neovim.plugins = [
+ (pkgs.vimPlugins.nvim-treesitter.withAllGrammars // { runtimeDeps = [ pkgs.tree-sitter ]; })
+ ];
+ programs.neovim.customPlugins.treesitter-config = {
+ "plugin/tree-sitter-config.lua" = # lua
+ ''
+ require('nvim-treesitter.config').setup({
+ highlight = {
+ enable = true,
+ disable = {},
+ },
+ textobjects = {
+ select = {
+ enable = true,
+ lookahead = true,
+ keymaps = {
+ ["af"] = "@function.outer",
+ ["if"] = "@function.inner",
+ ["ac"] = "@class.outer",
+ ["ic"] = "@class.inner",
+ },
+ },
+ },
+ })
+
+
+ vim.api.nvim_create_autocmd('FileType', {
+ group = vim.api.nvim_create_augroup('TreeSitterStart', { clear = true }),
+ callback = function(args)
+ local language = vim.treesitter.language.get_lang(vim.bo[args.buf].filetype)
+ if vim.treesitter.language.add(language) then
+ vim.treesitter.start(args.buf, language)
+ end
+ end
+ })
+ '';
+ };
+}
diff --git a/modules/neovim/plugins/winbar.nix b/modules/neovim/plugins/winbar.nix
@@ -0,0 +1,46 @@
+{
+ programs.neovim.customPlugins.winbar = {
+ "plugin/winbar.lua" = # lua
+ ''
+ vim.api.nvim_create_autocmd(
+ {'BufEnter', 'BufAdd', 'BufDelete', 'BufLeave', 'BufModifiedSet', 'BufWrite'},
+ {
+ group = vim.api.nvim_create_augroup("WinBarBuffers", { clear = true }),
+ pattern = "*",
+ callback = function()
+ local buffers = {}
+ local current = vim.api.nvim_win_get_buf(0)
+
+ for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
+ if vim.bo[bufnr].buflisted then
+ local name = vim.fn.fnamemodify(vim.fn.bufname(bufnr), ":t")
+ if name == "" then name = "[No name]" end
+
+ local highlight = bufnr == current and "WinBar" or "WinBarNC"
+ local modified = vim.bo[bufnr].modified and "*" or ""
+
+ table.insert(buffers, string.format(
+ "%%#%s# %d:%s%s %%*",
+ highlight, bufnr, name, modified
+ ))
+ end
+ end
+
+ if #buffers > 1 and vim.bo[current].buflisted then
+ vim.opt_local.winbar = table.concat(buffers)
+ vim.keymap.set({'n','v'}, '<C-n>', ':bn<cr>', { buffer = current })
+ vim.keymap.set({'n','v'}, '<C-p>', ':bp<cr>', { buffer = current })
+
+ else
+ vim.opt_local.winbar = ""
+ pcall(function()
+ vim.keymap.del({'n','v'}, '<C-n>', { buffer = current })
+ vim.keymap.del({'n','v'}, '<C-p>', { buffer = current })
+ end)
+ end
+ end
+ }
+ )
+ '';
+ };
+}