diff --git a/flake.lock b/flake.lock index b4d2e42..fc63e01 100644 --- a/flake.lock +++ b/flake.lock @@ -432,11 +432,11 @@ "vim-yazi": { "flake": false, "locked": { - "lastModified": 1720634904, - "narHash": "sha256-HrNNrLAewzyebKZ2m1wBJxcVn2w2UjapeHRAZQDN/5U=", + "lastModified": 1721070270, + "narHash": "sha256-kURiv1MUjcu5N0pE2tz1/JG5X8WMTbH+0yTJCzS+U30=", "owner": "mikavilpas", "repo": "yazi.nvim", - "rev": "c0841f4902204844db7def936b6702fa73b8cff0", + "rev": "f63312b3e07cb0dac14e4e64df3f84482c9c3646", "type": "github" }, "original": { diff --git a/modules/editor/vim.nix b/modules/editor/vim.nix deleted file mode 100644 index c5dcdce..0000000 --- a/modules/editor/vim.nix +++ /dev/null @@ -1,901 +0,0 @@ -{ config, lib, pkgs, inputs, ... }: - -let cfg = config.modules.editor.vim; -in { - options.modules.editor.vim = { enable = lib.my.mkBoolOpt false; }; - - config = lib.mkIf cfg.enable { - home-manager.users.${config.user.name} = { - imports = [ inputs.nixvim.homeManagerModules.nixvim ]; - programs.nixvim = { - enable = true; - package = pkgs.unstable.neovim-unwrapped; - vimAlias = true; - - globals.mapleader = " "; - - opts = { - # Keep visual indentation on wrapped lines - breakindent = true; - - # Hide command line unless needed - cmdheight = 0; - - # Insert mode completion options - completeopt = [ "menu" "menuone" "noselect" ]; - - # Raise a dialog asking if you wish to save the current file(s) - confirm = true; - - # Copy previous indentation on autoindenting - copyindent = true; - - # Highlight current line - cursorline = true; - - # Enable linematch diff algorithm - diffopt.__raw = /*lua*/ '' - vim.list_extend(vim.opt.diffopt:get(), { "algorithm:histogram", "linematch:60" }) - ''; - - # Expand to spaces - expandtab = false; - - # Disable `~` on nonexistent lines - fillchars = { eob = " "; }; - - # Enable fold with all code unfolded - foldcolumn = "1"; - foldenable = true; - foldlevel = 99; - foldlevelstart = 99; - - # Ignore case in search patterns - ignorecase = true; - - # Show substitution preview in split window - inccommand = "split"; - # Infer casing on word completion - infercase = true; - - # Global statusline - laststatus = 3; - - # Wrap lines at 'breakat' - linebreak = true; - - # Enable list mode - list = true; - - # Set custom strings for list mode - # - tabulations are shown as ‒▶ - # - trailing spaces are shown as · - # - multiple non-leading consecutive spaces are shown as bullets (·) - # - non-breakable spaces are shown as ⎕ - listchars = "tab:» ,trail:·,multispace:·,lead: ,nbsp:␣"; - - # Enable mouse support - mouse = "a"; - - # Show line numbers - number = true; - - # Preserve indentation as much as possible - preserveindent = true; - - # Height of the popup menu - pumheight = 10; - - # Display line numbers relative to current line - relativenumber = false; - - # Number of spaces to use for indentation - shiftwidth = 2; - - # Disable search count wrap and startup messages - shortmess.__raw = /*lua*/ '' - vim.tbl_deep_extend("force", vim.opt.shortmess:get(), { s = true, I = true }) - ''; - - # Disable showing modes in command line - showmode = false; - - # Show tabline when needed - showtabline = 1; - - # Show signs column - signcolumn = "yes"; - - # Override ignorecase if search pattern contains uppercase characters - smartcase = true; - - # Number of spaces input on - softtabstop = 2; - - # Open horizontal split below (:split) - splitbelow = true; - - # Open vertical split to the right (:vsplit) - splitright = true; - - # Number of spaces to represent a - tabstop = 2; - - # Enables 24-bit RGB color - termguicolors = true; - - # Shorter timeout duration - timeoutlen = 500; - - # Set window title to the filename - title = true; - - # Save undo history to undo file (in $XDG_STATE_HOME/nvim/undo) - undofile = true; - - viewoptions.__raw = /*lua*/ '' - vim.tbl_filter(function(val) return val ~= "curdir" end, vim.opt.viewoptions:get()) - ''; - - # Enable virtual edit in visual block mode - # This has the effect of selecting empty cells beyond lines boundaries - virtualedit = "block"; - - # Disable line wrapping - wrap = false; - - # Disable making a backup before overwriting a file - writebackup = false; - - # Sync clipboard between OS and Neovim. - clipboard = "unnamedplus"; - }; - - keymaps = [ - # Search - { - key = ""; - action = "Telescope fd layout_strategy=vertical"; - } - { - key = "sh"; - action = "Telescope help_tags"; - options.desc = "Search help"; - } - { - key = "sk"; - action = "Telescope keymaps"; - options.desc = "Search keymaps"; - } - { - key = "ss"; - action = "Telescope"; - options.desc = "Search select Telescope"; - } - { - key = "/"; - action = "Telescope live_grep layout_strategy=vertical"; - options.desc = "Grep (root dir)"; - } - { - key = "sR"; - action = "Telescope resume"; - options.desc = "Search resume"; - } - { - key = "cx"; - action = "Telescope diagnostics layout_strategy=vertical"; - options.desc = "Search diagnostics"; - } - # File - { - key = "fs"; - action.__raw = /*lua*/'' - function() - vim.lsp.buf.format() - vim.cmd.write() - end - ''; - options.desc = "Format and save buffer"; - } - { - mode = "n"; - key = "fn"; - action = "enew"; - options.desc = "New File"; - } - # Project - { - key = "ps"; - action = "wa"; - options.desc = "Save all buffers"; - } - # Git - { - key = "gg"; - action = "Neogit"; - } - # Buffers - { - key = "bb"; - action = "Telescope buffers layout_strategy=vertical"; - options.desc = "Switch buffer"; - } - { - key = ","; - action = "Telescope buffers layout_strategy=vertical"; - options.desc = "Switch buffer"; - } - { - key = "bn"; - action = "bnext"; - options.desc = "Next buffer"; - } - { - key = "bp"; - action = "bprev"; - options.desc = "Previous buffer"; - } - { - key = "bl"; - action = "e #"; - options.desc = "Other buffer"; - } - { - key = "bk"; - action = "bd"; - options.desc = "Delete buffer and Window"; - } - { - key = "bd"; - action = "bd"; - options.desc = "Delete buffer and Window"; - } - # Windows - { - mode = "n"; - key = "ww"; - action = "p"; - options = { desc = "Other Window"; remap = true; }; - } - { - mode = "n"; - key = "wd"; - action = "c"; - options = { desc = "Delete Window"; remap = true; }; - } - { - mode = "n"; - key = "ws"; - action = "s"; - options = { desc = "Split Window Below"; remap = true; }; - } - { - mode = "n"; - key = "wv"; - action = "v"; - options = { desc = "Split Window Right"; remap = true; }; - } - { - mode = "n"; - key = ""; - action = "j"; - options = { desc = "Go to Lower Winddow"; remap = true; }; - } - { - mode = "n"; - key = "wj"; - action = "j"; - options = { desc = "Go to Lower Winddow"; remap = true; }; - } - { - mode = "n"; - key = ""; - action = "k"; - options = { desc = "Go to Upper Winddow"; remap = true; }; - } - { - mode = "n"; - key = "wk"; - action = "k"; - options = { desc = "Go to Upper Winddow"; remap = true; }; - } - { - mode = "n"; - key = ""; - action = "l"; - options = { desc = "Go to Right Winddow"; remap = true; }; - } - { - mode = "n"; - key = "wl"; - action = "l"; - options = { desc = "Go to Right Winddow"; remap = true; }; - } - { - mode = "n"; - key = ""; - action = "h"; - options = { desc = "Go to Left Winddow"; remap = true; }; - } - { - mode = "n"; - key = "wh"; - action = "h"; - options = { desc = "Go to Left Winddow"; remap = true; }; - } - # Move lines - { - mode = "n"; - key = ""; - action = "m .+1=="; - options.desc = "Move Down"; - } - { - mode = "n"; - key = ""; - action = "m .-2=="; - options.desc = "Move Up"; - } - { - mode = "i"; - key = ""; - action = "m .+1==gi"; - options.desc = "Move Down"; - } - { - mode = "i"; - key = ""; - action = "m .-2==gi"; - options.desc = "Move Up"; - } - { - mode = "v"; - key = ""; - action = ":m '>+1gv=gv"; - options.desc = "Move Down"; - } - { - mode = "v"; - key = ""; - action = ":m '<-2gv=gv"; - options.desc = "Move Up"; - } - # Better indenting - { - mode = "v"; - key = "<"; - action = "", true, true, true) - end - if opts.skip_next and next ~= "" and next:match(opts.skip_next) then - return o - end - if opts.skip_ts and #opts.skip_ts > 0 then - local ok, captures = pcall(vim.treesitter.get_captures_at_pos, 0, cursor[1] - 1, math.max(cursor[2] - 1, 0)) - for _, capture in ipairs(ok and captures or {}) do - if vim.tbl_contains(opts.skip_ts, capture.capture) then - return o - end - end - end - if opts.skip_unbalanced and next == c and c ~= o then - local _, count_open = line:gsub(vim.pesc(pair:sub(1, 1)), "") - local _, count_close = line:gsub(vim.pesc(pair:sub(2, 2)), "") - if count_close > count_open then - return o - end - end - return open(pair, neigh_pattern) - end - end - ''; - } - { - pkg = pkgs.vimPlugins.lualine-nvim; - event = "VeryLazy"; - init = /*lua*/ '' - function() - vim.g.lualine_laststatus = vim.o.laststatus - if vim.fn.argc(-1) > 0 then - -- set an empty statusline till lualine loads - vim.o.statusline = " " - else - -- hide the statusline on the starter page - vim.o.laststatus = 0 - end - end - ''; - opts.__raw = /*lua*/ '' - { - options = { - icons_enabled = true, - } - } - ''; - } - { - pkg = pkgs.unstable.vimPlugins.neogit; - dependencies = [ pkgs.vimPlugins.plenary-nvim pkgs.vimPlugins.diffview-nvim pkgs.vimPlugins.telescope-nvim ]; - event = "VeryLazy"; - config = true; - } - { - pkg = pkgs.vimPlugins.gitsigns-nvim; - opts.__raw = /*lua*/ '' - { - on_attach = function(buffer) - local gs = package.loaded.gitsigns - - local function map(mode, l ,r, desc) - vim.keymap.set(mode, l, r, { buffer = buffer, desc = desc}) - end - - map("n", "g;", function() - if vim.wo.diff then - vim.cmd.normal({ "]c", bang = true }) - else - gs.nav_hunk("next") - end - end, "Next Hunk") - map("n", "g,", function() - if vim.wo.diff then - vim.cmd.normal({ "[c", bang = true }) - else - gs.nav_hunk("prev") - end - end, "Prev Hunk") - map({ "n", "v" }, "gs", gs.stage_hunk, "Stage Hunk") - map({ "n", "v" }, "gr", gs.reset_hunk, "Reset Hunk") - map("n", "gS", gs.stage_buffer, "Stage Buffer") - map("n", "gu", gs.undo_stage_hunk, "Undo Stage Hunk") - map("n", "gR", gs.reset_buffer, "Reset Buffer") - map("n", "gp", gs.preview_hunk_inline, "Preview Hunk Inline") - map("n", "gb", function() gs.blame_line({ full = true }) end, "Blame Line") - map("n", "gd", gs.diffthis, "Diff This") - map("n", "gD", function() gs.diffthis("~") end, "Diff This ~") - map('n', 'tb', gs.toggle_current_line_blame, "Toggle current line blame") - map({ "o", "x" }, "ih", ":Gitsigns select_hunk", "GitSigns Select Hunk") - end, - } - ''; - } - { - pkg = - (pkgs.vimUtils.buildVimPlugin { - name = "yazi.nvim"; - src = inputs.vim-yazi; - }); - event = "VeryLazy"; - keys.__raw = /*lua*/ '' - { - { ".", function() require("yazi").yazi() end, desc = "Open file manager" }, - { "", desc = "Decrement Selection", mode = "x" }, - } - ''; - opts.__raw = /*lua*/ '' - { - open_for_directories = true, - } - ''; - } - { - pkg = pkgs.unstable.vimPlugins.fidget-nvim; - opts.__raw = /*lua*/ '' - { - logger = { level = vim.log.levels.WARN }, - notification = { filter = vim.log.levels.INFO }, - } - ''; - } - { - pkg = pkgs.unstable.vimPlugins.indent-blankline-nvim; - event = "VeryLazy"; - main = "ibl"; - opts = { - scope.enabled = false; - }; - } - { - pkg = pkgs.unstable.vimPlugins.vim-sleuth; - } - { - pkg = pkgs.unstable.vimPlugins.comment-nvim; - } - { - pkg = pkgs.vimPlugins.leap-nvim; - config = /*lua*/ '' - function (_, opts) - local leap = require("leap") - for k, v in pairs(opts) do - leap.opts[k] = v - end - leap.add_default_mappings(true) - end - ''; - } - { - pkg = pkgs.vimPlugins.telescope-nvim; - dependencies = [ - pkgs.vimPlugins.plenary-nvim - pkgs.vimPlugins.nvim-web-devicons - pkgs.vimPlugins.telescope-ui-select-nvim - pkgs.vimPlugins.telescope-fzf-native-nvim - ]; - opts.__raw = /*lua*/ '' - { - defaults = { - layout_config = { - vertical = { width = 0.9 } - }, - }, - } - ''; - } - { - pkg = pkgs.vimPlugins.nvim-treesitter.withAllGrammars; - lazy.__raw = "vim.fn.argc(-1) == 0"; - init = /*lua*/ '' - function(plugin) - -- PERF: add nvim-treesitter queries to the rtp and it's custom query predicates early - -- This is needed because a bunch of plugins no longer `require("nvim-treesitter")`, which - -- no longer trigger the **nvim-treesitter** module to be loaded in time. - -- Luckily, the only things that those plugins need are the custom queries, which we make available - -- during startup. - require("lazy.core.loader").add_to_rtp(plugin) - require("nvim-treesitter.query_predicates") - end - ''; - cmd = [ "TSUpdateSync" "TSUpdate" "TSInstall" ]; - keys.__raw = /*lua*/ '' - { - { "", desc = "Increment Selection" }, - { "", desc = "Decrement Selection", mode = "x" }, - } - ''; - opts.__raw = /*lua*/ '' - { - highlight = { enable = true }, - indent = { enable = true }, - ensure_installed = "all", - parser_install_dir = vim.fs.joinpath(vim.fn.stdpath('data'), 'site'), - incremental_selection = { - enable = true, - keymaps = { - init_selection = "", - node_incremental = "", - scope_incremental = false, - node_decremental = "", - }, - }, - ignore_install = { "org" }, - } - ''; - config = /*lua*/ '' - function (_, opts) - require("nvim-treesitter.configs").setup(opts) - vim.opt.runtimepath:prepend(vim.fs.joinpath(vim.fn.stdpath('data'), 'site')) - end - ''; - } - { - pkg = pkgs.unstable.vimPlugins.which-key-nvim; - event = "VimEnter"; - config = /*lua*/ '' - function () - require('which-key').setup() - require('which-key').register { - ['b'] = { name = 'Buffer', _ = 'which_key_ignore' }, - ['c'] = { name = 'Code', _ = 'which_key_ignore' }, - ['d'] = { name = 'Document', _ = 'which_key_ignore' }, - ['f'] = { name = 'File', _ = 'which_key_ignore' }, - ['g'] = { name = 'Git', _ = 'which_key_ignore' }, - ['o'] = { name = 'Org', _ = 'which_key_ignore' }, - ['n'] = { name = 'Org-roam', _ = 'which_key_ignore' }, - ['p'] = { name = 'Project', _ = 'which_key_ignore' }, - ['r'] = { name = 'Rename', _ = 'which_key_ignore' }, - ['s'] = { name = 'Search', _ = 'which_key_ignore' }, - ['w'] = { name = 'Window', _ = 'which_key_ignore' }, - ['t'] = { name = 'Toggle', _ = 'which_key_ignore' }, - ['q'] = { name = 'Quit/Session', _ = 'which_key_ignore' }, - } - end - ''; - } - { - pkg = pkgs.vimPlugins.nvim-lspconfig; - config = /*lua*/ '' - function () - vim.api.nvim_create_autocmd('LspAttach', { - group = vim.api.nvim_create_augroup('lsp-attach', { clear = true }), - callback = function(event) - local map = function(keys, func, desc) - vim.keymap.set('n', keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) - end - - map('gd', require('telescope.builtin').lsp_definitions, 'Go to definition') - map('gr', require('telescope.builtin').lsp_references, 'Go to references') - map('gI', require('telescope.builtin').lsp_implementations, 'Goto implementation') - map('gD', vim.lsp.buf.declaration, 'Go to declaration') - map('gT', require('telescope.builtin').lsp_type_definitions, 'Type definition') - map('cD', require('telescope.builtin').lsp_document_symbols, 'Document symbols') - map('cw', require('telescope.builtin').lsp_dynamic_workspace_symbols, 'Workspace symbols ') - map('cd', vim.diagnostic.open_float, 'Line diagnostics') - map('c,', vim.diagnostic.goto_prev, 'Previous diagnostics') - map('c;', vim.diagnostic.goto_next, 'Next diagnostics') - map('cr', vim.lsp.buf.rename, 'Rename') - map('ca', vim.lsp.buf.code_action, 'Code action') - map('K', vim.lsp.buf.hover, 'Hover Documentation') - end - }) - - local has_cmp, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") - local capabilities = vim.tbl_deep_extend( - "force", - {}, - vim.lsp.protocol.make_client_capabilities(), - has_cmp and cmp_nvim_lsp.default_capabilities() or {} - ) - - local function setup(server, server_opts) - local server_opts_with_caps = vim.tbl_deep_extend("force", { - capabilities = vim.deepcopy(capabilities), - }, server_opts) - - require("lspconfig")[server].setup(server_opts_with_caps) - end - - setup("yamlls", {}) - setup("typos_lsp", { - init_options = { diagnosticSeverity = "Hint" } - }) - setup("tsserver", {}) - setup("terraformls", {}) - setup("sqls", {}) - setup("nixd", {}) - setup("marksman", {}) - setup("lua_ls", {}) - setup("jsonls", { cmd = { "${pkgs.vscode-langservers-extracted}/bin/vscode-json-language-server", "--stdio" } }) - setup("html", { cmd = { "${pkgs.vscode-langservers-extracted}/bin/vscode-html-language-server", "--stdio" } }) - setup("eslint", { cmd = { "${pkgs.vscode-langservers-extracted}/bin/vscode-eslint-language-server", "--stdio" } }) - setup("dockerls", { cmd = { "${pkgs.dockerfile-language-server-nodejs}/bin/docker-langserver", "--stdio" } }) - setup("docker_compose_language_service", {}) - setup("cssls", { cmd = { "${pkgs.vscode-langservers-extracted}/bin/vscode-css-language-server", "--stdio" } }) - setup("bashls", {}) - setup("ansiblels", { cmd = { "${pkgs.ansible-language-server}/bin/ansible-language-server", "--stdio" } }) - end - ''; - } - { - pkg = pkgs.unstable.vimPlugins.nvim-metals; - dependencies = [ pkgs.vimPlugins.plenary-nvim ]; - ft = [ "scala" "sbt" ]; - opts.__raw = /*lua*/ '' - function() - local metals_config = require("metals").bare_config() - metals_config.on_attach = function(client, bufnr) - vim.keymap.set( - "n", - "me", - function() require("telescope").extensions.metals.commands() end, - { noremap=true, silent=true, buffer = bufn, desc = "Metals commands"} - ) - vim.keymap.set( - "n", - "co", - "MetalsOrganizeImports", - { noremap=true, silent=true, buffer = bufn, desc = "Organize imports"} - ) - end - metals_config.init_options.statusBarProvider = "off" - metals_config.settings = { - showImplicitArguments = true, - } - return metals_config - end - ''; - config = /*lua*/ '' - function (self, metals_config) - local nvim_metals_group = vim.api.nvim_create_augroup("nvim-metals", { clear = true }) - vim.api.nvim_create_autocmd("FileType", { - pattern = self.ft, - callback = function() - require("metals").initialize_or_attach(metals_config) - end, - group = nvim_metals_group, - }) - end - ''; - } - { - pkg = pkgs.unstable.vimPlugins.nvim-cmp; - event = "InsertEnter"; - dependencies = [ - pkgs.unstable.vimPlugins.cmp-nvim-lsp - pkgs.unstable.vimPlugins.cmp-path - pkgs.unstable.vimPlugins.cmp-buffer - ]; - opts.__raw = /*lua*/ '' - function() - local cmp = require("cmp") - return { - mapping = { - [""] = cmp.mapping.complete(), - [""] = cmp.mapping.scroll_docs(-4), - [""] = cmp.mapping.close(), - [""] = cmp.mapping.scroll_docs(4), - [""] = cmp.mapping.confirm({ select = true }), - [""] = cmp.mapping.confirm({ select = true }), - [""] = cmp.mapping(cmp.mapping.select_prev_item(), { "i", "s" }), - [""] = cmp.mapping(cmp.mapping.select_next_item(), { "i", "s" }), - }, - sources = { - { name = "nvim_lsp" }, - { name = "path" }, - { name = "buffer" }, - { name = "orgmode" }, - }, - } - end - ''; - } - { - pkg = pkgs.unstable.vimPlugins.nvim-spectre; - cmd = "Spectre"; - opts = { open_cmd = "noswapfile vnew"; }; - keys.__raw = /*lua*/ '' - { - { "sr", function() require("spectre").open() end, desc = "Replace in Files (Spectre)" }, - } - ''; - } - { - pkg = pkgs.unstable.vimPlugins.persistence-nvim; - event = "BufReadPre"; - opts.__raw = /*lua*/ '' - { options =vim.opt.sessionoptions:get() } - ''; - keys.__raw = /*lua*/ '' - { - { "qs", function() require("persistence").load() end, desc = "Restore Session" }, - { "ql", function() require("persistence").load({ last = true }) end, desc = "Restore Last Session" }, - { "qd", function() require("persistence").stop() end, desc = "Don't Save Current Session" }, - } - ''; - } - - # Disabled for now as it tries to write org grammar to its own directory in the nix store - # https://github.com/nvim-orgmode/orgmode/blob/95fb795a422f0455e03d13a3f83525f1d00793ad/lua/orgmode/utils/treesitter/install.lua#L9 - # { - # pkg = pkgs.unstable.vimPlugins.orgmode; - # event = "VeryLazy"; - # ft = [ "org" ]; - # config = /*lua*/ '' - # function () - # require('orgmode').setup({ - # org_agend_files = '~/Nextcloud/Org/**/*', - # org_default_notes_file = '~/Nextcloud/Org/refile.org', - # }) - # end - # ''; - # } - # { - # pkg = (pkgs.vimUtils.buildVimPlugin { - # name = "org-roam.nvim"; - # src = inputs.vim-org-roam; - # }); - # dependencies = [ pkgs.unstable.vimPlugins.orgmode ]; - # event = "VeryLazy"; - # ft = [ "org" ]; - # config = /*lua*/ '' - # function () - # require('org-roam').setup({ - # directory = '~/Nextcloud/OrgRoam', - # }) - # end - # ''; - # } - ]; - }; - }; - colorschemes.gruvbox = { - enable = true; - package = pkgs.unstable.vimPlugins.gruvbox-nvim; - settings = { - overrides = { - Include = { link = "GruvboxRed"; }; - "@constructor" = { link = "GruvboxYellow"; }; - "@function.builtin" = { link = "GruvboxFg1"; }; - "@function.call" = { link = "GruvboxFg1"; }; - "@function.macro" = { link = "GruvboxFg1"; }; - "@function.method.call.scala" = { link = "GruvboxFg1"; }; - "@method.call" = { link = "GruvboxFg1"; }; - "@variable.member.scala" = { link = "GruvboxFg1"; }; - "@lsp.type.type.scala" = { link = ""; }; - "@lsp.type.method.scala" = { link = ""; }; - "@lsp.type.modifier.scala" = { link = "GruvboxOrange"; }; - "@lsp.type.typeParameter.scala" = { link = "GruvboxAqua"; }; - - "@lsp.type.type.nix" = { link = ""; }; - "@lsp.type.method.nix" = { link = ""; }; - "@lsp.type.macro.nix" = { link = ""; }; - "@lsp.type.interface.nix" = { link = ""; }; - }; - }; - }; - }; - - home.packages = with pkgs.unstable; [ - ripgrep - fd - nodejs - opentofu - nixfmt-rfc-style - nixpkgs-fmt - coursier - - # LSP - yaml-language-server - typos-lsp - nodePackages.typescript-language-server - terraform-ls - sqls - nixd - marksman - lua-language-server - docker-compose-language-service - bash-language-server - ]; - }; - }; -} diff --git a/modules/editor/vim/.neoconf.json b/modules/editor/vim/.neoconf.json new file mode 100644 index 0000000..7c48087 --- /dev/null +++ b/modules/editor/vim/.neoconf.json @@ -0,0 +1,15 @@ +{ + "neodev": { + "library": { + "enabled": true, + "plugins": true + } + }, + "neoconf": { + "plugins": { + "lua_ls": { + "enabled": true + } + } + } +} diff --git a/modules/editor/vim/lua/config/autocmds.lua b/modules/editor/vim/lua/config/autocmds.lua new file mode 100644 index 0000000..27e9e06 --- /dev/null +++ b/modules/editor/vim/lua/config/autocmds.lua @@ -0,0 +1,3 @@ +-- Autocmds are automatically loaded on the VeryLazy event +-- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua +-- Add any additional autocmds here diff --git a/modules/editor/vim/lua/config/keymaps.lua b/modules/editor/vim/lua/config/keymaps.lua new file mode 100644 index 0000000..51b6fca --- /dev/null +++ b/modules/editor/vim/lua/config/keymaps.lua @@ -0,0 +1,21 @@ +-- Keymaps are automatically loaded on the VeryLazy event +-- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua +-- Add any additional keymaps here + +local map = vim.keymap.set + +-- Windows +map("n", "ww", "p", { desc = "Other Window", remap = true }) +map("n", "wd", "c", { desc = "Delete Window", remap = true }) +map("n", "ws", "s", { desc = "Split Window Below", remap = true }) +map("n", "wv", "v", { desc = "Split Window Right", remap = true }) +map("n", "wj", "j", { desc = "Go to Lower Window", remap = true }) +map("n", "wk", "k", { desc = "Go to Upper Window", remap = true }) +map("n", "wl", "l", { desc = "Go to Right Window", remap = true }) +map("n", "wh", "h", { desc = "Go to Left Window", remap = true }) + +-- File +map("n", "fs", "w", { desc = "Save File" }) + +-- Buffer +map("n", "bk", LazyVim.ui.bufremove, { desc = "Delete Buffer" }) diff --git a/modules/editor/vim/lua/config/options.lua b/modules/editor/vim/lua/config/options.lua new file mode 100644 index 0000000..3ea1454 --- /dev/null +++ b/modules/editor/vim/lua/config/options.lua @@ -0,0 +1,3 @@ +-- Options are automatically loaded before lazy.nvim startup +-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua +-- Add any additional options here diff --git a/modules/editor/vim/lua/plugins/core.lua b/modules/editor/vim/lua/plugins/core.lua new file mode 100644 index 0000000..c68d952 --- /dev/null +++ b/modules/editor/vim/lua/plugins/core.lua @@ -0,0 +1,9 @@ +return { + { "ellisonleao/gruvbox.nvim" }, + { + "LazyVim/LazyVim", + opts = { + colorscheme = "gruvbox", + } + }, +} diff --git a/modules/editor/vim/lua/plugins/disabled.lua b/modules/editor/vim/lua/plugins/disabled.lua new file mode 100644 index 0000000..2da374f --- /dev/null +++ b/modules/editor/vim/lua/plugins/disabled.lua @@ -0,0 +1,7 @@ +return { + { "folke/tokyonight.nvim", enabled = false }, + { "catppuccin", enabled = false }, + { "williamboman/mason.nvim", enabled = false }, + { "williamboman/mason-lspconfig.nvim", enabled = false }, + { "jay-babu/mason-nvim-dap.nvim", enabled = false }, +} diff --git a/modules/editor/vim/lua/plugins/neogit.lua b/modules/editor/vim/lua/plugins/neogit.lua new file mode 100644 index 0000000..85d0d49 --- /dev/null +++ b/modules/editor/vim/lua/plugins/neogit.lua @@ -0,0 +1,15 @@ +return { + { + "NeogitOrg/neogit", + dependencies = { "nvim-lua/plenary.nvim", "sindrets/diffview.nvim", "nvim-telescope/telescope.nvim" }, + event = "VeryLazy", + keys = { + { + "gg", + "Neogit", + desc = "Neogit", + }, + }, + config = true, + }, +} diff --git a/modules/editor/vim/lua/plugins/nix.lua b/modules/editor/vim/lua/plugins/nix.lua new file mode 100644 index 0000000..621934c --- /dev/null +++ b/modules/editor/vim/lua/plugins/nix.lua @@ -0,0 +1,36 @@ +return { + { + "mfussenegger/nvim-lint", + opts = { + linters_by_ft = { + nix = { + "statix", + }, + }, + }, + }, + { + "neovim/nvim-lspconfig", + opts = { + servers = { + nixd = { + settings = { + nixd = { + formatting = { + command = { "nixfmt" } + } + } + }, + }, + }, + }, + }, + { + "stevearc/conform.nvim", + opts = { + formatters_by_ft = { + nix = { "nixpkgs-fmt" }, + }, + }, + }, +} diff --git a/modules/editor/vim/lua/plugins/treesitter.lua b/modules/editor/vim/lua/plugins/treesitter.lua new file mode 100644 index 0000000..924a8a6 --- /dev/null +++ b/modules/editor/vim/lua/plugins/treesitter.lua @@ -0,0 +1,10 @@ +return { + { + "nvim-treesitter/nvim-treesitter", + opts = { + auto_install = false, + ensure_installed = {}, + parser_install_dir = vim.fs.joinpath(vim.fn.stdpath('data'), 'site'), + }, + }, +} diff --git a/modules/editor/vim/lua/plugins/yazi.lua b/modules/editor/vim/lua/plugins/yazi.lua new file mode 100644 index 0000000..cdbf964 --- /dev/null +++ b/modules/editor/vim/lua/plugins/yazi.lua @@ -0,0 +1,18 @@ +return { + { + "mikavilpas/yazi.nvim", + event = "VeryLazy", + keys = { + { + ".", + function() + require("yazi").yazi() + end, + desc = "Open the file manager", + }, + }, + opts = { + open_for_directories = true, + }, + } +} diff --git a/modules/editor/vim/vim.nix b/modules/editor/vim/vim.nix new file mode 100644 index 0000000..6622811 --- /dev/null +++ b/modules/editor/vim/vim.nix @@ -0,0 +1,509 @@ +{ + config, + lib, + pkgs, + inputs, + ... +}: + +let + cfg = config.modules.editor.vim; +in +{ + options.modules.editor.vim = { + enable = lib.my.mkBoolOpt false; + }; + + config = lib.mkIf cfg.enable { + home-manager.users.${config.user.name} = { + imports = [ inputs.nixvim.homeManagerModules.nixvim ]; + + programs.neovim = { + enable = true; + package = pkgs.unstable.neovim-unwrapped; + vimAlias = true; + vimdiffAlias = true; + withNodeJs = true; + plugins = + (with pkgs.unstable.vimPlugins; [ + # base distro + LazyVim + conform-nvim + nvim-lint + markdown-preview-nvim + headlines-nvim + + # theme + gruvbox-nvim + + # UI + bufferline-nvim + gitsigns-nvim + neogit + diffview-nvim + edgy-nvim + dashboard-nvim + toggleterm-nvim + trouble-nvim + lualine-nvim + which-key-nvim + nvim-web-devicons + mini-nvim + noice-nvim + nui-nvim + nvim-notify + nvim-lsp-notify + neo-tree-nvim + nvim-navic + dressing-nvim + aerial-nvim + + # project management + project-nvim + neoconf-nvim + persistence-nvim + + # smart typing + indent-blankline-nvim + guess-indent-nvim + vim-illuminate + + # LSP + nvim-lspconfig + nvim-lightbulb # lightbulb for quick actions + # nvim-code-action-menu # code action menu + neodev-nvim + SchemaStore-nvim # load known formats for json and yaml + nvim-metals + + # cmp plugins + nvim-cmp # completion plugin + cmp-buffer # buffer completions + cmp-path # path completions + cmp_luasnip # snipper completions + cmp-nvim-lsp # LSP completions + + # snippets + luasnip # snippet engine + nvim-snippets + friendly-snippets # a bunch of snippets to use + + # search functionality + plenary-nvim + telescope-nvim + telescope-fzf-native-nvim + nvim-spectre + flash-nvim + + # treesitter + nvim-treesitter-context + nvim-ts-autotag + nvim-treesitter-textobjects + nvim-treesitter.withAllGrammars + + # comments + ts-comments-nvim + nvim-ts-context-commentstring + todo-comments-nvim + + # leap + vim-repeat + leap-nvim + flit-nvim + + # DAP + nvim-dap + nvim-dap-ui + nvim-dap-virtual-text + + # neotest + neotest + neotest-rust + + # SQL + vim-dadbod + vim-dadbod-ui + vim-dadbod-completion + + lazy-nvim + lazydev-nvim + vim-startuptime + ]) + ++ [ + # File manager + (pkgs.vimUtils.buildVimPlugin { + name = "yazi.nvim"; + src = inputs.vim-yazi; + }) + ]; + + extraPackages = with pkgs; [ + gcc # needed for nvim-treesitter + + # HTML, CSS, JSON + vscode-langservers-extracted + + # Nix + nixd + statix + nixfmt-rfc-style + + # SQL + sqlfluff + + # LazyVim defaults + stylua + shfmt + + # Markdown extra + nodePackages.markdownlint-cli + marksman + + # Docker extra + nodePackages.dockerfile-language-server-nodejs + hadolint + docker-compose-language-service + + # JSON and YAML extras + nodePackages.yaml-language-server + + # Custom + editorconfig-checker + shellcheck + ]; + + extraLuaConfig = # lua + '' + require("gruvbox").setup({ + overrides = { + Include = { ["link"] = "GruvboxRed" }, + ["@constructor"] = { ["link"] = "GruvboxYellow" }, + ["@function.builtin"] = { ["link"] = "GruvboxFg1" }, + ["@function.call"] = { ["link"] = "GruvboxFg1" }, + ["@function.macro"] = { ["link"] = "GruvboxFg1" }, + ["@function.method.call.scala"] = { ["link"] = "GruvboxFg1" }, + ["@method.call"] = { ["link"] = "GruvboxFg1" }, + ["@variable.member.scala"] = { ["link"] = "GruvboxFg1" }, + ["@lsp.type.type.scala"] = { ["link"] = "" }, + ["@lsp.type.method.scala"] = { ["link"] = "" }, + ["@lsp.type.modifier.scala"] = { ["link"] = "GruvboxOrange" }, + ["@lsp.type.typeParameter.scala"] = { ["link"] = "GruvboxAqua" }, + ["@lsp.type.type.nix"] = { ["link"] = "" }, + ["@lsp.type.method.nix"] = { ["link"] = "" }, + ["@lsp.type.macro.nix"] = { ["link"] = "" }, + ["@lsp.type.interface.nix"] = { ["link"] = "" }, + }, + }) + + require("lazy").setup({ + spec = { + { "LazyVim/LazyVim", import = "lazyvim.plugins" }, + -- import any extras modules here + { import = "lazyvim.plugins.extras.dap.core" }, + { import = "lazyvim.plugins.extras.dap.nlua" }, + { import = "lazyvim.plugins.extras.ui.edgy" }, + { import = "lazyvim.plugins.extras.coding.mini-comment" }, + { import = "lazyvim.plugins.extras.editor.aerial" }, + { import = "lazyvim.plugins.extras.editor.leap" }, + { import = "lazyvim.plugins.extras.editor.navic" }, + { import = "lazyvim.plugins.extras.lang.docker" }, + { import = "lazyvim.plugins.extras.lang.json" }, + { import = "lazyvim.plugins.extras.lang.markdown" }, + { import = "lazyvim.plugins.extras.lang.sql" }, + { import = "lazyvim.plugins.extras.lang.yaml" }, + { import = "lazyvim.plugins.extras.lang.scala" }, + { import = "lazyvim.plugins.extras.test.core" }, + -- import/override with your plugins + { import = "plugins" }, + }, + defaults = { + -- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup. + -- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default. + lazy = false, + -- It's recommended to leave version=false for now, since a lot the plugin that support versioning, + -- have outdated releases, which may break your Neovim install. + version = false, -- always use the latest git commit + -- version = "*", -- try installing the latest stable version for plugins that support semver + }, + performance = { + -- Used for NixOS + reset_packpath = false, + rtp = { + reset = false, + -- disable some rtp plugins + disabled_plugins = { + "gzip", + -- "matchit", + -- "matchparen", + -- "netrwPlugin", + "tarPlugin", + "tohtml", + "tutor", + "zipPlugin", + }, + } + }, + dev = { + path = "${ + pkgs.vimUtils.packDir + config.home-manager.users.${config.user.name}.programs.neovim.finalPackage.passthru.packpathDirs + }/pack/myNeovimPackages/start", + patterns = {"folke", "nvim-telescope", "hrsh7th", "akinsho", "stevearc", "LazyVim", "catppuccin", "saadparwaiz1", "nvimdev", "rafamadriz", "lewis6991", "lukas-reineke", "nvim-lualine", "L3MON4D3", "williamboman", "echasnovski", "nvim-neo-tree", "MunifTanjim", "mfussenegger", "rcarriga", "neovim", "nvim-pack", "nvim-treesitter", "windwp", "JoosepAlviste", "nvim-tree", "nvim-lua", "RRethy", "dstein64", "Saecki", "ggandor", "iamcco", "nvim-neotest", "rouge8", "theHamsta", "SmiteshP", "jbyuki", "simrat39", "b0o", "tpope", "kosayoda", "ellisonleao", "NeogitOrg", "sindrets", "scalameta", "garymjr", "mikavilpas","kristijanhusak"}, + }, + install = { + missing = false, + }, + }) + ''; + }; + + xdg.configFile."nvim/lua" = { + recursive = true; + source = ./lua; + }; + + programs.nixvim = { + enable = false; + package = pkgs.unstable.neovim-unwrapped; + vimAlias = true; + + keymaps = [ + # Search + { + key = "cx"; + action = "Telescope diagnostics layout_strategy=vertical"; + options.desc = "Search diagnostics"; + } + # Project + { + key = "ps"; + action = "wa"; + options.desc = "Save all buffers"; + } + ]; + + plugins = { + lazy = { + enable = true; + plugins = [ + { + pkg = pkgs.vimPlugins.gitsigns-nvim; + opts.__raw = # lua + '' + { + on_attach = function(buffer) + local gs = package.loaded.gitsigns + + local function map(mode, l ,r, desc) + vim.keymap.set(mode, l, r, { buffer = buffer, desc = desc}) + end + + map("n", "g;", function() + if vim.wo.diff then + vim.cmd.normal({ "]c", bang = true }) + else + gs.nav_hunk("next") + end + end, "Next Hunk") + map("n", "g,", function() + if vim.wo.diff then + vim.cmd.normal({ "[c", bang = true }) + else + gs.nav_hunk("prev") + end + end, "Prev Hunk") + map({ "n", "v" }, "gs", gs.stage_hunk, "Stage Hunk") + map({ "n", "v" }, "gr", gs.reset_hunk, "Reset Hunk") + map("n", "gS", gs.stage_buffer, "Stage Buffer") + map("n", "gu", gs.undo_stage_hunk, "Undo Stage Hunk") + map("n", "gR", gs.reset_buffer, "Reset Buffer") + map("n", "gp", gs.preview_hunk_inline, "Preview Hunk Inline") + map("n", "gb", function() gs.blame_line({ full = true }) end, "Blame Line") + map("n", "gd", gs.diffthis, "Diff This") + map("n", "gD", function() gs.diffthis("~") end, "Diff This ~") + map('n', 'tb', gs.toggle_current_line_blame, "Toggle current line blame") + map({ "o", "x" }, "ih", ":Gitsigns select_hunk", "GitSigns Select Hunk") + end, + } + ''; + } + { + pkg = pkgs.unstable.vimPlugins.which-key-nvim; + event = "VimEnter"; + config = # lua + '' + function () + require('which-key').setup() + require('which-key').register { + ['b'] = { name = 'Buffer', _ = 'which_key_ignore' }, + ['c'] = { name = 'Code', _ = 'which_key_ignore' }, + ['d'] = { name = 'Document', _ = 'which_key_ignore' }, + ['f'] = { name = 'File', _ = 'which_key_ignore' }, + ['g'] = { name = 'Git', _ = 'which_key_ignore' }, + ['o'] = { name = 'Org', _ = 'which_key_ignore' }, + ['n'] = { name = 'Org-roam', _ = 'which_key_ignore' }, + ['p'] = { name = 'Project', _ = 'which_key_ignore' }, + ['r'] = { name = 'Rename', _ = 'which_key_ignore' }, + ['s'] = { name = 'Search', _ = 'which_key_ignore' }, + ['w'] = { name = 'Window', _ = 'which_key_ignore' }, + ['t'] = { name = 'Toggle', _ = 'which_key_ignore' }, + ['q'] = { name = 'Quit/Session', _ = 'which_key_ignore' }, + } + end + ''; + } + { + pkg = pkgs.vimPlugins.nvim-lspconfig; + config = # lua + '' + function () + vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('lsp-attach', { clear = true }), + callback = function(event) + local map = function(keys, func, desc) + vim.keymap.set('n', keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) + end + + map('gd', require('telescope.builtin').lsp_definitions, 'Go to definition') + map('gr', require('telescope.builtin').lsp_references, 'Go to references') + map('gI', require('telescope.builtin').lsp_implementations, 'Goto implementation') + map('gD', vim.lsp.buf.declaration, 'Go to declaration') + map('gT', require('telescope.builtin').lsp_type_definitions, 'Type definition') + map('cD', require('telescope.builtin').lsp_document_symbols, 'Document symbols') + map('cw', require('telescope.builtin').lsp_dynamic_workspace_symbols, 'Workspace symbols ') + map('cd', vim.diagnostic.open_float, 'Line diagnostics') + map('c,', vim.diagnostic.goto_prev, 'Previous diagnostics') + map('c;', vim.diagnostic.goto_next, 'Next diagnostics') + map('cr', vim.lsp.buf.rename, 'Rename') + map('ca', vim.lsp.buf.code_action, 'Code action') + map('K', vim.lsp.buf.hover, 'Hover Documentation') + end + }) + + local has_cmp, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") + local capabilities = vim.tbl_deep_extend( + "force", + {}, + vim.lsp.protocol.make_client_capabilities(), + has_cmp and cmp_nvim_lsp.default_capabilities() or {} + ) + + local function setup(server, server_opts) + local server_opts_with_caps = vim.tbl_deep_extend("force", { + capabilities = vim.deepcopy(capabilities), + }, server_opts) + + require("lspconfig")[server].setup(server_opts_with_caps) + end + + setup("yamlls", {}) + setup("typos_lsp", { + init_options = { diagnosticSeverity = "Hint" } + }) + setup("tsserver", {}) + setup("terraformls", {}) + setup("marksman", {}) + setup("lua_ls", {}) + setup("jsonls", { cmd = { "${pkgs.vscode-langservers-extracted}/bin/vscode-json-language-server", "--stdio" } }) + setup("html", { cmd = { "${pkgs.vscode-langservers-extracted}/bin/vscode-html-language-server", "--stdio" } }) + setup("eslint", { cmd = { "${pkgs.vscode-langservers-extracted}/bin/vscode-eslint-language-server", "--stdio" } }) + setup("dockerls", { cmd = { "${pkgs.dockerfile-language-server-nodejs}/bin/docker-langserver", "--stdio" } }) + setup("docker_compose_language_service", {}) + setup("cssls", { cmd = { "${pkgs.vscode-langservers-extracted}/bin/vscode-css-language-server", "--stdio" } }) + setup("bashls", {}) + setup("ansiblels", { cmd = { "${pkgs.ansible-language-server}/bin/ansible-language-server", "--stdio" } }) + end + ''; + } + { + pkg = pkgs.unstable.vimPlugins.nvim-cmp; + event = "InsertEnter"; + dependencies = [ + pkgs.unstable.vimPlugins.cmp-nvim-lsp + pkgs.unstable.vimPlugins.cmp-path + pkgs.unstable.vimPlugins.cmp-buffer + ]; + opts.__raw = # lua + '' + function() + local cmp = require("cmp") + return { + mapping = { + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.scroll_docs(-4), + [""] = cmp.mapping.close(), + [""] = cmp.mapping.scroll_docs(4), + [""] = cmp.mapping.confirm({ select = true }), + [""] = cmp.mapping.confirm({ select = true }), + [""] = cmp.mapping(cmp.mapping.select_prev_item(), { "i", "s" }), + [""] = cmp.mapping(cmp.mapping.select_next_item(), { "i", "s" }), + }, + sources = { + { name = "nvim_lsp" }, + { name = "path" }, + { name = "buffer" }, + { name = "orgmode" }, + }, + } + end + ''; + } + + # Disabled for now as it tries to write org grammar to its own directory in the nix store + # https://github.com/nvim-orgmode/orgmode/blob/95fb795a422f0455e03d13a3f83525f1d00793ad/lua/orgmode/utils/treesitter/install.lua#L9 + # { + # pkg = pkgs.unstable.vimPlugins.orgmode; + # event = "VeryLazy"; + # ft = [ "org" ]; + # config = /*lua*/ '' + # function () + # require('orgmode').setup({ + # org_agend_files = '~/Nextcloud/Org/**/*', + # org_default_notes_file = '~/Nextcloud/Org/refile.org', + # }) + # end + # ''; + # } + # { + # pkg = (pkgs.vimUtils.buildVimPlugin { + # name = "org-roam.nvim"; + # src = inputs.vim-org-roam; + # }); + # dependencies = [ pkgs.unstable.vimPlugins.orgmode ]; + # event = "VeryLazy"; + # ft = [ "org" ]; + # config = /*lua*/ '' + # function () + # require('org-roam').setup({ + # directory = '~/Nextcloud/OrgRoam', + # }) + # end + # ''; + # } + ]; + }; + }; + }; + + home.packages = with pkgs.unstable; [ + ripgrep + fd + nodejs + opentofu + coursier + + # LSP + yaml-language-server + typos-lsp + nodePackages.typescript-language-server + terraform-ls + sqls + nixd + marksman + lua-language-server + docker-compose-language-service + bash-language-server + ]; + }; + }; +}