diff --git a/README.md b/README.md index 68ec53a..8a04a0d 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,3 @@ # Neovim module -This is a demonstration of the [neovim module](https://birdeehub.github.io/nix-wrapper-modules/wrapperModules/neovim.html) - -It makes use of the tips in the [tips and tricks](https://birdeehub.github.io/nix-wrapper-modules/wrapperModules/neovim.html#tips-and-tricks) section of the documentation. - -This template configuration is by no means a perfect, complete configuration. - -However, it is plenty to start on, and covers some interesting ways to use the module (and how to lazily load plugins and config). - -This configuration is 1 `lua` file, however the whole set of directories from a normal `neovim` configuration directory are available. - -To see what directories you can put stuff in, see: [:help 'rtp'](https://neovim.io/doc/user/options.html#'rtp') - -The main reason it is in 1 file is that it is following the style of [kickstart.nvim](https://github.com/nvim-lua/kickstart.nvim). - -The other reason it is in 1 file, is that it makes it a cleaner experience to init this template into an existing configuration. - -This template config uses [lze](https://github.com/BirdeeHub/lze) for lazy loading of the configuration. - -You may also be interested in [lz.n](https://github.com/lumen-oss/lz.n) for this purpose. - -Both achieve the same general result and main interface, -but have different underlying implementations and thus have different handler features. - -Both are fantastic for lazy loading with both nix and the builtin plugin manager. - -You may also decide you don't need lazy loading at all. This is fine, many plugins mostly handle that themselves. - -To initialize this template flake into the current directory, run: - -```bash -nix flake init -t github:BirdeeHub/nix-wrapper-modules#neovim -``` - -It will not replace existing files. - -If you are using `zsh` you may need to escape the `#` - -To build it from that directory - -```bash -nix build . -``` - -It exports a package! (and other things) - -If you don't want your config in a separate flake, just call the `module.nix` file like: - -```nix -inputs: # <-- get the library somehow -{ pkgs, ... }: { - # call the module and install the package (nixos example) - environment.systemPackages = [ (inputs.nix-wrapper-modules.lib.evalPackage [ ./module.nix { inherit pkgs; } ]) ]; -} -``` - -There are a lot of other ways to install it as well, see [the getting started documentation](https://birdeehub.github.io/nix-wrapper-modules/md/getting-started.html) - -You may also wish to view the `flake.nix` of this template, as it demonstrates some of those things when setting up its outputs. - ---- - -The nix in this template is not as simple as it could possibly be, as it demonstrates some things -from the [tips and tricks](https://birdeehub.github.io/nix-wrapper-modules/wrapperModules/neovim.html#tips-and-tricks) section of the documentation. - -If you wanted as simple as possible, you could use something more like the following as your `module.nix` - -```nix -{ wlib, config, pkgs, lib, ... }: - imports = [ wlib.wrapperModules.neovim ]; - specs.general = with pkgs.vimPlugins; [ - # plugins which are loaded at startup ... - ]; - specs.lazy = { - lazy = true; - data = with pkgs.vimPlugins; [ - # plugins which are not loaded until you vim.cmd.packadd them ... - ]; - }; - extraPackages = with pkgs; [ - # lsps, formatters, etc... - ]; - settings.config_directory = ./.; # or lib.generators.mkLuaInline "vim.fn.stdpath('config')"; -} -``` - -At the same time, you may find that the `module.nix` file from this template is not massively more complex than that either, -and contains some useful tricks and information. +A wrapper around nvim that includes the plugins I use day to day. diff --git a/flake.lock b/flake.lock index e934dd7..6836d9d 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1772674223, - "narHash": "sha256-/suKbHSaSmuC9UY7G0VRQ3aO+QKqxAQPQ19wG7QNkF8=", + "lastModified": 1773231277, + "narHash": "sha256-Xy3WEpUAbpsz8ydgvVAQAGGB/WB+8cNA5cshiL0McTI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "66d9241e3dc2296726dc522e62dbfe89c7b449f3", + "rev": "75690239f08f885ca9b0267580101f60d10fbe62", "type": "github" }, "original": { @@ -19,11 +19,11 @@ "plugins-lze": { "flake": false, "locked": { - "lastModified": 1772337062, - "narHash": "sha256-joi1087b2iDmwOHv7/0YCrDPucbu0osbS8WQmDYoyE4=", + "lastModified": 1772949858, + "narHash": "sha256-skLhmn/MvxOZbrBiceF/xiLRRmmEs6ZQS2sGrBrUyLU=", "owner": "BirdeeHub", "repo": "lze", - "rev": "f50a84a5d84f6b16e254091e755f5a9e839a9924", + "rev": "a3ba1a2d469d4ab26acb629aba8c7d70a6cbe558", "type": "github" }, "original": { @@ -35,11 +35,11 @@ "plugins-lzextras": { "flake": false, "locked": { - "lastModified": 1772336997, - "narHash": "sha256-BsoZTfXpISPeTnTQWtnZkDXzvo9ocILB5IO2vU8IvAM=", + "lastModified": 1772949841, + "narHash": "sha256-MQ1h2R5axM3u6mLNTDzXF/40o8+U0JOWb48UTQO9jfc=", "owner": "BirdeeHub", "repo": "lzextras", - "rev": "abdda956a2947d0617133a018992d035fc5781da", + "rev": "a6ac9a7bee380881af2dfbfd238ccb1697d677d7", "type": "github" }, "original": { @@ -63,11 +63,11 @@ ] }, "locked": { - "lastModified": 1772662098, - "narHash": "sha256-BKxBM4RNWP+5q0ZQ6v3JlJ0e6fFj/YoYNZ7/OpgabdU=", + "lastModified": 1773360496, + "narHash": "sha256-AQN5UhIc2WHvELT4TWIsD1W05ksLXWRkS5NjPm3jkc0=", "owner": "BirdeeHub", "repo": "nix-wrapper-modules", - "rev": "2c0a3b795766b25d15ad1ec9eef3a06160154c9a", + "rev": "8f1770c6d58a89a4757849713c0e6d9ace7b4ac3", "type": "github" }, "original": { diff --git a/init.lua b/init.lua index d8690a2..0662935 100644 --- a/init.lua +++ b/init.lua @@ -1,6 +1,5 @@ --- NOTE: Welcome to your neovim configuration! -- The first 100ish lines are setup, --- the rest is usage of lze and various core plugins! +-- the rest is usage of require(vim.g.nix_info_plugin_name)lze and various core plugins! vim.loader.enable() -- <- bytecode caching do -- Set up a global in a way that also handles non-nix compat @@ -17,9 +16,9 @@ do -- TODO: for non-nix compat, vim.pack.add in another file and require here. end nixInfo.isNix = vim.g.nix_info_plugin_name ~= nil - ---@module 'lzextras' + ---@module "lzextras" ---@type lzextras | lze - nixInfo.lze = setmetatable(require('lze'), getmetatable(require('lzextras'))) + nixInfo.lze = setmetatable(require("lze"), getmetatable(require("lzextras"))) function nixInfo.get_nix_plugin_path(name) return nixInfo(nil, "plugins", "lazy", name) or nixInfo(nil, "plugins", "start", name) end @@ -78,7 +77,7 @@ nixInfo.lze.register_handlers { -- NOTE: This config uses lzextras.lsp handler https://github.com/BirdeeHub/lzextras?tab=readme-ov-file#lsp-handler -- Because we have the paths, we can set a more performant fallback function --- for when you don't provide a filetype to trigger on yourself. +-- for when you don"t provide a filetype to trigger on yourself. -- If you do provide a filetype, this will never be called. nixInfo.lze.h.lsp.set_ft_fallback(function(name) local lspcfg = nixInfo.get_nix_plugin_path "nvim-lspconfig" @@ -91,6 +90,7 @@ nixInfo.lze.h.lsp.set_ft_fallback(function(name) end end) -require('opts') -require('keys') -require('plugins') +require("opts") +require("keys") +require("plugins") +require("lsp") diff --git a/lua/keys.lua b/lua/keys.lua index 8f0f9f7..b07a6e6 100644 --- a/lua/keys.lua +++ b/lua/keys.lua @@ -2,8 +2,8 @@ -- Keymaps for better default experience -- See `:help vim.keymap.set()` -vim.keymap.set("v", "J", ":m '>+1gv=gv", { desc = 'Moves Line Down' }) -vim.keymap.set("v", "K", ":m '<-2gv=gv", { desc = 'Moves Line Up' }) +vim.keymap.set("v", "J", ":m '>+1gv=gv", { desc = "Moves Line Down" }) +vim.keymap.set("v", "K", ":m '<-2gv=gv", { desc = "Moves Line Up" }) vim.keymap.set("n", "", "zz", { desc = 'Scroll Down' }) vim.keymap.set("n", "", "zz", { desc = 'Scroll Up' }) vim.keymap.set("n", "n", "nzzzv", { desc = 'Next Search Result' }) diff --git a/lua/lsp/C.lua b/lua/lsp/C.lua new file mode 100644 index 0000000..b382d76 --- /dev/null +++ b/lua/lsp/C.lua @@ -0,0 +1,7 @@ +return { + { + "clangd", + for_cat = "C", + lsp = {}, + }, +} diff --git a/lua/lsp/bash.lua b/lua/lsp/bash.lua new file mode 100644 index 0000000..c8bca4d --- /dev/null +++ b/lua/lsp/bash.lua @@ -0,0 +1,7 @@ +return { + { + "bashls", + for_cat = "bash", + lsp = {}, + }, +} diff --git a/lua/lsp/init.lua b/lua/lsp/init.lua new file mode 100644 index 0000000..66d1e61 --- /dev/null +++ b/lua/lsp/init.lua @@ -0,0 +1,92 @@ +local lspEnabled = nixInfo("settings", "cat", "lsp") + +if lspEnabled then + local Snacks = require("snacks") + vim.keymap.set("n", "lI", Snacks.picker.lsp_implementations, { desc = "Goto [I]mplementation" }) + vim.keymap.set("n", "lR", Snacks.picker.lsp_references, { desc = "Goto [R]eferences" }) + vim.keymap.set("n", "li", Snacks.picker.diagnostics, { desc = "D[i]agnostics" }) + vim.keymap.set("n", "ls", Snacks.picker.lsp_symbols, { desc = "Document [S]ymbols" }) + vim.keymap.set("n", "lws", Snacks.picker.lsp_workspace_symbols, { desc = "[W]orkspace [S]ymbols" }) + + vim.keymap.set("n", "lD", vim.lsp.buf.declaration, { desc = "Goto [D]eclaration" }) + vim.keymap.set("n", "lt", vim.lsp.buf.type_definition, { desc = "Type [D]efinition" }) + vim.keymap.set({ "n", "v", }, "la", vim.lsp.buf.code_action, { desc = "[C]ode Action" }) + vim.keymap.set("n", "ld", vim.lsp.buf.definition, { desc = "Goto [D]efinition" }) + vim.keymap.set("n", "lf", vim.lsp.buf.format, { desc = "Format buffer" }) + vim.keymap.set("n", "lh", vim.lsp.buf.hover, { desc = "Hover Documentation" }) + vim.keymap.set("n", "lr", vim.lsp.buf.rename, { desc = "[R]ename" }) + vim.keymap.set("n", "ls", vim.lsp.buf.signature_help, { desc = "Signature Documentation" }) + vim.keymap.set("n", "lwa", vim.lsp.buf.add_workspace_folder, { desc = "[W]orkspace [A]dd Folder" }) + vim.keymap.set("n", "lwl", function() print(vim.inspect(vim.lsp.buf.list_workspace_folders())) end, + { desc = "[W]orkspace [L]ist Folders" }) + vim.keymap.set("n", "lwr", vim.lsp.buf.remove_workspace_folder, { desc = "[W]orkspace [R]emove Folder" }) + + -- setup lsp progress notifications + local progress = vim.defaulttable() + vim.api.nvim_create_autocmd("LspProgress", { + callback = function(ev) + local client = vim.lsp.get_client_by_id(ev.data.client_id) + local value = ev.data.params + .value --[[@as {percentage?: number, title?: string, message?: string, kind: "begin" | "report" | "end"}]] + if not client or type(value) ~= "table" then + return + end + local p = progress[client.id] + + for i = 1, #p + 1 do + if i == #p + 1 or p[i].token == ev.data.params.token then + p[i] = { + token = ev.data.params.token, + msg = ("[%3d%%] %s%s"):format( + value.kind == "end" and 100 or value.percentage or 100, + value.title or "", + value.message and (" **%s**"):format(value.message) or "" + ), + done = value.kind == "end", + } + break + end + end + + local msg = {} ---@type string[] + progress[client.id] = vim.tbl_filter(function(v) + return table.insert(msg, v.msg) or not v.done + end, p) + + local spinner = { "⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏" } + vim.notify(table.concat(msg, "\n"), "info", { + id = "lsp_progress", + title = client.name, + opts = function(notif) + notif.icon = #progress[client.id] == 0 and " " + or spinner[math.floor(vim.uv.hrtime() / (1e6 * 80)) % #spinner + 1] + end, + }) + end, + }) +end + +require('lze').load { + { + "nvim-lspconfig", + for_cat = "lsp", + on_require = { "lspconfig" }, + -- rustaceanvim and zk-nvim dont require("lspconfig") + ft = { "markdown", "rust" }, + -- NOTE: define a function for lsp, + -- and it will run for all specs with type(plugin.lsp) == table + -- when their filetype trigger loads them + lsp = function(plugin) + vim.lsp.config(plugin.name, plugin.lsp or {}) + vim.lsp.enable(plugin.name) + end, + }, + { import = "lsp.lua" }, + { import = "lsp.python" }, + { import = "lsp.C" }, + { import = "lsp.nix" }, + { import = "lsp.typst" }, + { import = "lsp.bash" }, + { import = "lsp.zk" }, + { import = "lsp.rust" }, +} diff --git a/lua/lsp/lua.lua b/lua/lsp/lua.lua new file mode 100644 index 0000000..22f8cc2 --- /dev/null +++ b/lua/lsp/lua.lua @@ -0,0 +1,45 @@ +return { + { + -- lazydev makes your lsp way better in your config without needing extra lsp configuration. + "lazydev.nvim", + for_cat = "lua", + auto_enable = true, + cmd = { "LazyDev" }, + ft = "lua", + after = function(_) + require('lazydev').setup({ + library = { + { words = { "nixInfo%.lze" }, path = nixInfo("lze", "plugins", "start", "lze") .. '/lua', }, + { words = { "nixInfo%.lze" }, path = nixInfo("lzextras", "plugins", "start", "lzextras") .. '/lua' }, + }, + }) + end, + }, + { + -- name of the lsp + "lua_ls", + for_cat = "lua", + -- provide a table containing filetypes, + -- and then whatever your functions defined in the function type specs expect. + -- in our case, it just expects the normal lspconfig setup options, + -- but with a default on_attach and capabilities + lsp = { + -- if you provide the filetypes it doesn't ask lspconfig for the filetypes + filetypes = { 'lua' }, + settings = { + Lua = { + runtime = { version = 'LuaJIT' }, + formatters = { + ignoreComments = true, + }, + signatureHelp = { enabled = true }, + diagnostics = { + globals = { "nixInfo", "vim", }, + disable = { 'missing-fields' }, + }, + telemetry = { enabled = false }, + }, + }, + }, + }, +} diff --git a/lua/lsp/nix.lua b/lua/lsp/nix.lua new file mode 100644 index 0000000..4463427 --- /dev/null +++ b/lua/lsp/nix.lua @@ -0,0 +1,27 @@ +return { + { + "nixd", + enabled = nixInfo.isNix, -- mason doesn't have nixd + for_cat = "nix", + lsp = { + filetypes = { "nix" }, + settings = { + nixd = { + nixpkgs = { + expr = [[import {}]], + }, + options = { + }, + formatting = { + command = { "nixfmt" } + }, + diagnostic = { + suppress = { + "sema-escaping-with" + } + } + } + }, + }, + }, +} diff --git a/lua/lsp/python.lua b/lua/lsp/python.lua new file mode 100644 index 0000000..4bd6e38 --- /dev/null +++ b/lua/lsp/python.lua @@ -0,0 +1,12 @@ +return { + { + "ty", + for_cat = "python", + lsp = {}, + }, + { + "ruff", + for_cat = "python", + lsp = {}, + }, +} diff --git a/lua/lsp/rust.lua b/lua/lsp/rust.lua new file mode 100644 index 0000000..3ebc601 --- /dev/null +++ b/lua/lsp/rust.lua @@ -0,0 +1,6 @@ +return { + { + "rustaceanvim", + for_cat = "rust", + }, +} diff --git a/lua/lsp/typst.lua b/lua/lsp/typst.lua new file mode 100644 index 0000000..40dfe81 --- /dev/null +++ b/lua/lsp/typst.lua @@ -0,0 +1,13 @@ +return { + { + "tinymist", + for_cat = "typst", + lsp = { + filetypes = { "typst" }, + settings = { + formatterMode = "typstyle", + + }, + }, + }, +} diff --git a/lua/lsp/zk.lua b/lua/lsp/zk.lua new file mode 100644 index 0000000..13e663a --- /dev/null +++ b/lua/lsp/zk.lua @@ -0,0 +1,23 @@ +return { + { + "zk-nvim", + for_cat = "zk", + ft = "markdown", + after = function() + require("zk").setup({ picker = "snacks_picker" }) + + vim.api.nvim_set_keymap("n", "zb", "ZkBackLinks", { desc = "Show [B]acklinkgs" }) + vim.api.nvim_set_keymap("n", "zl", "ZkLinks", { desc = "Show [L]inks" }) + vim.api.nvim_set_keymap("n", "zi", ":'<,'>ZkInsertLink", { desc = "[I]nsert link" }) + vim.api.nvim_set_keymap("n", "zn", "ZkNew { title = vim.fn.input('Title: ') }", + { desc = "[N]ew note" }) + vim.api.nvim_set_keymap("n", "zo", "ZkNotes { sort = { 'modified' } }", { desc = "[O]pen notes" }) + vim.api.nvim_set_keymap("n", "zt", "ZkTags", { desc = "Search [T]ags" }) + vim.api.nvim_set_keymap("v", "zf", ":'<,'>ZkMatch", { desc = "[F]ind note from selection" }) + vim.api.nvim_set_keymap("v", "zn", ":'<,'>ZkNewFromTitleSelection", { + desc = + "[N]ew note from selection" + }) + end + }, +} diff --git a/lua/opts.lua b/lua/opts.lua index 92a89ea..49fb35c 100644 --- a/lua/opts.lua +++ b/lua/opts.lua @@ -1,6 +1,6 @@ -- NOTE: These 2 should be set up before any plugins with keybinds are loaded. -vim.g.mapleader = ';' -vim.g.maplocalleader = ';' +vim.g.mapleader = ";" +vim.g.maplocalleader = ";" -- [[ Setting options ]] -- See `:help vim.o` @@ -10,9 +10,9 @@ vim.g.maplocalleader = ';' vim.o.exrc = false -- can be toggled off in that file to stop it from searching further -- Sets how neovim will display certain whitespace characters in the editor. --- See `:help 'list'` --- and `:help 'listchars'` --- and `:help 'showbreak'` +-- See `:help "list"` +-- and `:help "listchars"` +-- and `:help "showbreak"` vim.opt.list = true vim.opt.listchars = { eol = "↲", extends = "⟩", nbsp = "␣", precedes = "⟨", tab = ">-", trail = "•" } vim.opt.showbreak = "↪"; @@ -20,10 +20,10 @@ vim.opt.showbreak = "↪"; -- Set highlight on search vim.opt.hlsearch = true vim.opt.incsearch = true -vim.keymap.set('n', '', 'nohlsearch') +vim.keymap.set("n", "", "nohlsearch") -- Preview substitutions live, as you type! -vim.opt.inccommand = 'split' +vim.opt.inccommand = "split" -- Automatically load changed files vim.opt.autoread = true @@ -36,7 +36,7 @@ vim.opt.number = true vim.opt.numberwidth = 3 -- Enable mouse mode -vim.opt.mouse = 'a' +vim.opt.mouse = "a" -- no hard wrapping vim.opt.textwidth = 0 @@ -62,7 +62,7 @@ vim.opt.ignorecase = true vim.opt.smartcase = true -- Keep signcolumn on by default -vim.opt.signcolumn = 'yes' +vim.opt.signcolumn = "yes" vim.opt.relativenumber = true -- Decrease update time @@ -70,7 +70,7 @@ vim.opt.updatetime = 250 vim.opt.timeoutlen = 300 -- Set completeopt to have a better completion experience -vim.opt.completeopt = { 'menu', 'preview', 'noselect' } +vim.opt.completeopt = { "menu", "preview", "noselect" } vim.opt.termguicolors = true @@ -85,13 +85,13 @@ vim.opt.formatoptions = "rojq" -- [[ Highlight on yank ]] -- See `:help vim.highlight.on_yank()` -local highlight_group = vim.api.nvim_create_augroup('YankHighlight', { clear = true }) -vim.api.nvim_create_autocmd('TextYankPost', { +local highlight_group = vim.api.nvim_create_augroup("YankHighlight", { clear = true }) +vim.api.nvim_create_autocmd("TextYankPost", { callback = function() vim.highlight.on_yank() end, group = highlight_group, - pattern = '*', + pattern = "*", }) vim.g.netrw_liststyle = 0 diff --git a/lua/plugins.lua b/lua/plugins.lua deleted file mode 100644 index 611819f..0000000 --- a/lua/plugins.lua +++ /dev/null @@ -1,743 +0,0 @@ --- NOTE: You will likely want to break this up into more files. --- You can call this more than once. --- You can also include other files from within the specs via an `import` spec. --- see https://github.com/BirdeeHub/lze?tab=readme-ov-file#structuring-your-plugins - -nixInfo.lze.load { - { - -- lze specs need a name - "trigger_colorscheme", - -- lazy loaded colorscheme. - -- This means you will need to add the colorscheme you want to lze sometime before VimEnter is done - event = "VimEnter", - -- Also, lze can load more than just plugins. - -- The default load field contains vim.cmd.packadd - -- Here we override it to schedule when our colorscheme is loaded - load = function(_name) - -- schedule so it runs after VimEnter - vim.schedule(function() - vim.cmd.colorscheme(nixInfo("onedark_dark", "settings", "colorscheme")) - vim.schedule(function() - -- I like this color. Use vim.schedule again to set it after the colorscheme is finished - vim.cmd([[hi LineNr guifg=#bb9af7]]) - end) - end) - end - }, - { - -- NOTE: view these names in the info plugin! - -- :lua nixInfo.lze.debug.display(nixInfo.plugins) - -- The display function is from lzextras - "onedarkpro.nvim", - auto_enable = true, -- <- auto enable is useful here - colorscheme = { "onedark", "onedark_dark", "onedark_vivid", "onelight" }, - }, - { - "vim-moonfly-colors", - auto_enable = true, - colorscheme = "moonfly", - }, - { - "snacks.nvim", - auto_enable = true, - -- snacks makes a global, and then lazily loads itself - lazy = false, - -- priority only affects startup plugins - -- unless otherwise specified by a particular handler - priority = 1000, - after = function(plugin) - -- I also like this color - vim.api.nvim_set_hl(0, "MySnacksIndent", { fg = "#32a88f" }) - require('snacks').setup({ - explorer = { replace_netrw = true, }, - picker = { - sources = { - explorer = { - auto_close = true, - }, - }, - }, - git = {}, - terminal = {}, - scope = {}, - indent = { - scope = { - hl = 'MySnacksIndent', - }, - chunk = { - -- enabled = true, - hl = 'MySnacksIndent', - } - }, - statuscolumn = { - left = { "mark", "git" }, -- priority of signs on the left (high to low) - right = { "sign", "fold" }, -- priority of signs on the right (high to low) - folds = { - open = false, -- show open fold icons - git_hl = false, -- use Git Signs hl for fold icons - }, - git = { - -- patterns to match Git signs - patterns = { "GitSign", "MiniDiffSign" }, - }, - refresh = 50, -- refresh at most every 50ms - }, - -- make sure lazygit always reopens the correct program - -- hopefully this can be removed one day - lazygit = { - config = { - os = { - editPreset = "nvim-remote", - edit = vim.v.progpath .. [=[ --server "$NVIM" --remote-send 'lua nixInfo.lazygit_fix({{filename}})']=], - editAtLine = vim.v.progpath .. [=[ --server "$NVIM" --remote-send 'lua nixInfo.lazygit_fix({{filename}}, {{line}})']=], - openDirInEditor = vim.v.progpath .. [=[ --server "$NVIM" --remote-send 'lua nixInfo.lazygit_fix({{dir}})']=], - -- this one isnt a remote command, make sure it gets our config regardless of if we name it nvim or not - editAtLineAndWait = nixInfo(vim.v.progpath, "progpath") .. " +{{line}} {{filename}}", - }, - }, - }, - }) - -- Handle the backend of those remote commands. - -- hopefully this can be removed one day - nixInfo.lazygit_fix = function(path, line) - local prev = vim.fn.bufnr("#") - local prev_win = vim.fn.bufwinid(prev) - vim.api.nvim_feedkeys("q", "n", false) - if line then - vim.api.nvim_buf_call(prev, function() - vim.cmd.edit(path) - local buf = vim.api.nvim_get_current_buf() - vim.schedule(function() - if buf then - vim.api.nvim_win_set_buf(prev_win, buf) - vim.api.nvim_win_set_cursor(0, { line or 0, 0}) - end - end) - end) - else - vim.api.nvim_buf_call(prev, function() - vim.cmd.edit(path) - local buf = vim.api.nvim_get_current_buf() - vim.schedule(function() - if buf then - vim.api.nvim_win_set_buf(prev_win, buf) - end - end) - end) - end - end - -- NOTE: we aren't loading this lazily, and the keybinds already are so it is fine to just set these here - vim.keymap.set("n", "-", function() Snacks.explorer.open() end, { desc = 'Snacks file explorer' }) - vim.keymap.set("n", "", function() Snacks.terminal.open() end, { desc = 'Snacks Terminal' }) - vim.keymap.set("n", "_", function() Snacks.lazygit.open() end, { desc = 'Snacks LazyGit' }) - vim.keymap.set('n', "sf", function() Snacks.picker.smart() end, { desc = "Smart Find Files" }) - vim.keymap.set('n', "s", function() Snacks.picker.buffers() end, { desc = "Search Buffers" }) - -- find - vim.keymap.set('n', "ff", function() Snacks.picker.files() end, { desc = "Find Files" }) - vim.keymap.set('n', "fg", function() Snacks.picker.git_files() end, { desc = "Find Git Files" }) - -- Grep - vim.keymap.set('n', "sb", function() Snacks.picker.lines() end, { desc = "Buffer Lines" }) - vim.keymap.set('n', "sB", function() Snacks.picker.grep_buffers() end, { desc = "Grep Open Buffers" }) - vim.keymap.set('n', "sg", function() Snacks.picker.grep() end, { desc = "Grep" }) - vim.keymap.set({ "n", "x" }, "sw", function() Snacks.picker.grep_word() end, { desc = "Visual selection or ord" }) - -- search - vim.keymap.set('n', "sb", function() Snacks.picker.lines() end, { desc = "Buffer Lines" }) - vim.keymap.set('n', "sd", function() Snacks.picker.diagnostics() end, { desc = "Diagnostics" }) - vim.keymap.set('n', "sD", function() Snacks.picker.diagnostics_buffer() end, { desc = "Buffer Diagnostics" }) - vim.keymap.set('n', "sh", function() Snacks.picker.help() end, { desc = "Help Pages" }) - vim.keymap.set('n', "sj", function() Snacks.picker.jumps() end, { desc = "Jumps" }) - vim.keymap.set('n', "sk", function() Snacks.picker.keymaps() end, { desc = "Keymaps" }) - vim.keymap.set('n', "sl", function() Snacks.picker.loclist() end, { desc = "Location List" }) - vim.keymap.set('n', "sm", function() Snacks.picker.marks() end, { desc = "Marks" }) - vim.keymap.set('n', "sM", function() Snacks.picker.man() end, { desc = "Man Pages" }) - vim.keymap.set('n', "sq", function() Snacks.picker.qflist() end, { desc = "Quickfix List" }) - vim.keymap.set('n', "sR", function() Snacks.picker.resume() end, { desc = "Resume" }) - vim.keymap.set('n', "su", function() Snacks.picker.undo() end, { desc = "Undo History" }) - end - }, - { - "nvim-lspconfig", - auto_enable = true, - -- NOTE: define a function for lsp, - -- and it will run for all specs with type(plugin.lsp) == table - -- when their filetype trigger loads them - lsp = function(plugin) - vim.lsp.config(plugin.name, plugin.lsp or {}) - vim.lsp.enable(plugin.name) - end, - -- set up our on_attach function once before the spec loads - before = function(_) - vim.lsp.config('*', { - on_attach = function(_, bufnr) - - -- we create a function that lets us more easily define mappings specific - -- for LSP related items. It sets the mode, buffer and description for us each time. - local nmap = function(keys, func, desc) - if desc then - desc = 'LSP: ' .. desc - end - vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc }) - end - - nmap('rn', vim.lsp.buf.rename, '[R]e[n]ame') - nmap('ca', vim.lsp.buf.code_action, '[C]ode [A]ction') - nmap('gd', vim.lsp.buf.definition, '[G]oto [D]efinition') - nmap('D', vim.lsp.buf.type_definition, 'Type [D]efinition') - nmap('gr', function() Snacks.picker.lsp_references() end, '[G]oto [R]eferences') - nmap('gI', function() Snacks.picker.lsp_implementations() end, '[G]oto [I]mplementation') - nmap('ds', function() Snacks.picker.lsp_symbols() end, '[D]ocument [S]ymbols') - nmap('ws', function() Snacks.picker.lsp_workspace_symbols() end, '[W]orkspace [S]ymbols') - - -- See `:help K` for why this keymap - nmap('K', vim.lsp.buf.hover, 'Hover Documentation') - nmap('', vim.lsp.buf.signature_help, 'Signature Documentation') - - -- Lesser used LSP functionality - nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') - nmap('wa', vim.lsp.buf.add_workspace_folder, '[W]orkspace [A]dd Folder') - nmap('wr', vim.lsp.buf.remove_workspace_folder, '[W]orkspace [R]emove Folder') - nmap('wl', function() - print(vim.inspect(vim.lsp.buf.list_workspace_folders())) - end, '[W]orkspace [L]ist Folders') - - -- Create a command `:Format` local to the LSP buffer - vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_) - vim.lsp.buf.format() - end, { desc = 'Format current buffer with LSP' }) - end - }) - end, - }, - { - "mason.nvim", - enabled = not nixInfo.isNix, - priority = 100, -- <- run lsp hook before lspconfig's hook - on_plugin = { "nvim-lspconfig" }, - lsp = function(plugin) - vim.cmd.MasonInstall(plugin.name) - end, - }, - { - -- lazydev makes your lua lsp load only the relevant definitions for a file. - -- It also gives us a nice way to correlate globals we create with files. - "lazydev.nvim", - auto_enable = true, - cmd = { "LazyDev" }, - ft = "lua", - after = function(_) - require('lazydev').setup({ - library = { - { words = { "nixInfo%.lze" }, path = nixInfo("lze", "plugins", "start", "lze") .. '/lua', }, - { words = { "nixInfo%.lze" }, path = nixInfo("lzextras", "plugins", "start", "lzextras") .. '/lua' }, - }, - }) - end, - }, - { - -- name of the lsp - "lua_ls", - for_cat = "lua", - -- provide a table containing filetypes, - -- and then whatever your functions defined in the function type specs expect. - -- in our case, it just expects the normal lspconfig setup options, - -- but with a default on_attach and capabilities - lsp = { - -- if you provide the filetypes it doesn't ask lspconfig for the filetypes - -- (meaning it doesn't call the callback function we defined in the main init.lua) - filetypes = { 'lua' }, - settings = { - Lua = { - signatureHelp = { enabled = true }, - diagnostics = { - globals = { "nixInfo", "vim", }, - disable = { 'missing-fields' }, - }, - }, - }, - }, - -- also these are regular specs and you can use before and after and all the other normal fields - }, - { - "nixd", - enabled = nixInfo.isNix, -- mason doesn't have nixd - for_cat = "nix", - lsp = { - filetypes = { "nix" }, - settings = { - nixd = { - nixpkgs = { - expr = [[import {}]], - }, - options = { - }, - formatting = { - command = { "alejandra" } - }, - diagnostic = { - suppress = { - "sema-escaping-with" - } - } - } - }, - }, - }, - { - "nvim-treesitter", - lazy = false, - auto_enable = true, - after = function(plugin) - ---@param buf integer - ---@param language string - local function treesitter_try_attach(buf, language) - -- check if parser exists and load it - if not vim.treesitter.language.add(language) then - return false - end - -- enables syntax highlighting and other treesitter features - vim.treesitter.start(buf, language) - - -- enables treesitter based folds - vim.wo.foldexpr = "v:lua.vim.treesitter.foldexpr()" - vim.wo.foldmethod = "expr" - -- ensure folds are open to begin with - vim.o.foldlevel = 99 - - -- enables treesitter based indentation - vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" - - return true - end - - local installable_parsers = require("nvim-treesitter").get_available() - vim.api.nvim_create_autocmd("FileType", { - callback = function(args) - local buf, filetype = args.buf, args.match - local language = vim.treesitter.language.get_lang(filetype) - if not language then - return - end - - if not treesitter_try_attach(buf,language) then - if vim.tbl_contains(installable_parsers, language) then - -- not already installed, so try to install them via nvim-treesitter if possible - require("nvim-treesitter").install(language):await(function() - treesitter_try_attach(buf, language) - end) - end - end - end, - }) - end, - }, - { - "nvim-treesitter-textobjects", - auto_enable = true, - lazy = false, - before = function(plugin) - -- https://github.com/nvim-treesitter/nvim-treesitter-textobjects/tree/main?tab=readme-ov-file#using-a-package-manager - -- Disable entire built-in ftplugin mappings to avoid conflicts. - -- See https://github.com/neovim/neovim/tree/master/runtime/ftplugin for built-in ftplugins. - vim.g.no_plugin_maps = true - - -- Or, disable per filetype (add as you like) - -- vim.g.no_python_maps = true - -- vim.g.no_ruby_maps = true - -- vim.g.no_rust_maps = true - -- vim.g.no_go_maps = true - end, - after = function(plugin) - require("nvim-treesitter-textobjects").setup { - select = { - -- Automatically jump forward to textobj, similar to targets.vim - lookahead = true, - -- You can choose the select mode (default is charwise 'v') - -- - -- Can also be a function which gets passed a table with the keys - -- * query_string: eg '@function.inner' - -- * method: eg 'v' or 'o' - -- and should return the mode ('v', 'V', or '') or a table - -- mapping query_strings to modes. - selection_modes = { - ['@parameter.outer'] = 'v', -- charwise - ['@function.outer'] = 'V', -- linewise - -- ['@class.outer'] = '', -- blockwise - }, - -- If you set this to `true` (default is `false`) then any textobject is - -- extended to include preceding or succeeding whitespace. Succeeding - -- whitespace has priority in order to act similarly to eg the built-in - -- `ap`. - -- - -- Can also be a function which gets passed a table with the keys - -- * query_string: eg '@function.inner' - -- * selection_mode: eg 'v' - -- and should return true of false - include_surrounding_whitespace = false, - }, - } - - -- keymaps - -- You can use the capture groups defined in `textobjects.scm` - vim.keymap.set({ "x", "o" }, "am", function() - require "nvim-treesitter-textobjects.select".select_textobject("@function.outer", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "im", function() - require "nvim-treesitter-textobjects.select".select_textobject("@function.inner", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "ac", function() - require "nvim-treesitter-textobjects.select".select_textobject("@class.outer", "textobjects") - end) - vim.keymap.set({ "x", "o" }, "ic", function() - require "nvim-treesitter-textobjects.select".select_textobject("@class.inner", "textobjects") - end) - -- You can also use captures from other query groups like `locals.scm` - vim.keymap.set({ "x", "o" }, "as", function() - require "nvim-treesitter-textobjects.select".select_textobject("@local.scope", "locals") - end) - - -- NOTE: for more textobjects options, see the following link. - -- This template is using the new `main` branch of the repo. - -- https://github.com/nvim-treesitter/nvim-treesitter-textobjects/tree/main - end, - }, - { - "conform.nvim", - auto_enable = true, - -- cmd = { "" }, - -- event = "", - -- ft = "", - keys = { - { "FF", desc = "[F]ormat [F]ile" }, - }, - -- colorscheme = "", - after = function (plugin) - local conform = require("conform") - - conform.setup({ - formatters_by_ft = { - -- NOTE: download some formatters - -- and configure them here - lua = nixInfo(nil, "settings", "cats", "lua") and { "stylua" } or nil, - -- go = { "gofmt", "golint" }, - -- templ = { "templ" }, - -- Conform will run multiple formatters sequentially - -- python = { "isort", "black" }, - -- Use a sub-list to run only the first available formatter - -- javascript = { { "prettierd", "prettier" } }, - }, - }) - - vim.keymap.set({ "n", "v" }, "FF", function() - conform.format({ - lsp_fallback = true, - async = false, - timeout_ms = 1000, - }) - end, { desc = "[F]ormat [F]ile" }) - end, - }, - { - "nvim-lint", - auto_enable = true, - -- cmd = { "" }, - event = "FileType", - -- ft = "", - -- keys = "", - -- colorscheme = "", - after = function (plugin) - require('lint').linters_by_ft = { - -- NOTE: download some linters - -- and configure them here - -- markdown = {'vale',}, - -- javascript = { 'eslint' }, - -- typescript = { 'eslint' }, - } - - vim.api.nvim_create_autocmd({ "BufWritePost" }, { - callback = function() - require("lint").try_lint() - end, - }) - end, - }, - { - "cmp-cmdline", - auto_enable = true, - on_plugin = { "blink.cmp" }, - load = nixInfo.lze.loaders.with_after, - }, - { - "blink.compat", - auto_enable = true, - dep_of = { "cmp-cmdline" }, - }, - { - "colorful-menu.nvim", - auto_enable = true, - on_plugin = { "blink.cmp" }, - }, - { - "blink.cmp", - auto_enable = true, - event = "DeferredUIEnter", - after = function (_) - require("blink.cmp").setup({ - -- 'default' (recommended) for mappings similar to built-in completions (C-y to accept) - -- See :h blink-cmp-config-keymap for configuring keymaps - keymap = { - preset = 'default', - }, - cmdline = { - enabled = true, - completion = { - menu = { - auto_show = true, - }, - }, - sources = function() - local type = vim.fn.getcmdtype() - -- Search forward and backward - if type == '/' or type == '?' then return { 'buffer' } end - -- Commands - if type == ':' or type == '@' then return { 'cmdline', 'cmp_cmdline' } end - return {} - end, - }, - fuzzy = { - sorts = { - 'exact', - -- defaults - 'score', - 'sort_text', - }, - }, - signature = { - enabled = true, - window = { - show_documentation = true, - }, - }, - completion = { - menu = { - draw = { - treesitter = { 'lsp' }, - components = { - label = { - text = function(ctx) - return require("colorful-menu").blink_components_text(ctx) - end, - highlight = function(ctx) - return require("colorful-menu").blink_components_highlight(ctx) - end, - }, - }, - }, - }, - documentation = { - auto_show = true, - }, - }, - sources = { - default = { 'lsp', 'path', 'buffer', 'omni' }, - providers = { - path = { - score_offset = 50, - }, - lsp = { - score_offset = 40, - }, - cmp_cmdline = { - name = 'cmp_cmdline', - module = 'blink.compat.source', - score_offset = -100, - opts = { - cmp_name = 'cmdline', - }, - }, - }, - }, - }) - end, - }, - { - "nvim-surround", - auto_enable = true, - event = "DeferredUIEnter", - -- keys = "", - after = function(plugin) - require('nvim-surround').setup() - end, - }, - { - "vim-startuptime", - auto_enable = true, - cmd = { "StartupTime" }, - before = function(_) - vim.g.startuptime_event_width = 0 - vim.g.startuptime_tries = 10 - vim.g.startuptime_exe_path = nixInfo(vim.v.progpath, "progpath") - end, - }, - { - "fidget.nvim", - auto_enable = true, - event = "DeferredUIEnter", - -- keys = "", - after = function(plugin) - require('fidget').setup({}) - end, - }, - { - "lualine.nvim", - auto_enable = true, - -- cmd = { "" }, - event = "DeferredUIEnter", - -- ft = "", - -- keys = "", - -- colorscheme = "", - after = function (plugin) - require('lualine').setup({ - options = { - icons_enabled = false, - theme = nixInfo("onedark_dark", "settings", "colorscheme"), - component_separators = '|', - section_separators = '', - }, - sections = { - lualine_c = { - { 'filename', path = 1, status = true, }, - }, - }, - inactive_sections = { - lualine_b = { - { 'filename', path = 3, status = true, }, - }, - lualine_x = {'filetype'}, - }, - tabline = { - lualine_a = { 'buffers' }, - -- if you use lualine-lsp-progress, I have mine here instead of fidget - -- lualine_b = { 'lsp_progress', }, - lualine_z = { 'tabs' } - }, - }) - end, - }, - { - "gitsigns.nvim", - auto_enable = true, - event = "DeferredUIEnter", - -- cmd = { "" }, - -- ft = "", - -- keys = "", - -- colorscheme = "", - after = function (plugin) - require('gitsigns').setup({ - -- See `:help gitsigns.txt` - signs = { - add = { text = '+' }, - change = { text = '~' }, - delete = { text = '_' }, - topdelete = { text = '‾' }, - changedelete = { text = '~' }, - }, - on_attach = function(bufnr) - local gs = package.loaded.gitsigns - - local function map(mode, l, r, opts) - opts = opts or {} - opts.buffer = bufnr - vim.keymap.set(mode, l, r, opts) - end - - -- Navigation - map({ 'n', 'v' }, ']c', function() - if vim.wo.diff then - return ']c' - end - vim.schedule(function() - gs.next_hunk() - end) - return '' - end, { expr = true, desc = 'Jump to next hunk' }) - - map({ 'n', 'v' }, '[c', function() - if vim.wo.diff then - return '[c' - end - vim.schedule(function() - gs.prev_hunk() - end) - return '' - end, { expr = true, desc = 'Jump to previous hunk' }) - - -- Actions - -- visual mode - map('v', 'hs', function() - gs.stage_hunk { vim.fn.line '.', vim.fn.line 'v' } - end, { desc = 'stage git hunk' }) - map('v', 'hr', function() - gs.reset_hunk { vim.fn.line '.', vim.fn.line 'v' } - end, { desc = 'reset git hunk' }) - -- normal mode - map('n', 'gs', gs.stage_hunk, { desc = 'git stage hunk' }) - map('n', 'gr', gs.reset_hunk, { desc = 'git reset hunk' }) - map('n', 'gS', gs.stage_buffer, { desc = 'git Stage buffer' }) - map('n', 'gu', gs.undo_stage_hunk, { desc = 'undo stage hunk' }) - map('n', 'gR', gs.reset_buffer, { desc = 'git Reset buffer' }) - map('n', 'gp', gs.preview_hunk, { desc = 'preview git hunk' }) - map('n', 'gb', function() - gs.blame_line { full = false } - end, { desc = 'git blame line' }) - map('n', 'gd', gs.diffthis, { desc = 'git diff against index' }) - map('n', 'gD', function() - gs.diffthis '~' - end, { desc = 'git diff against last commit' }) - - -- Toggles - map('n', 'gtb', gs.toggle_current_line_blame, { desc = 'toggle git blame line' }) - map('n', 'gtd', gs.toggle_deleted, { desc = 'toggle git show deleted' }) - - -- Text object - map({ 'o', 'x' }, 'ih', ':Gitsigns select_hunk', { desc = 'select git hunk' }) - end, - }) - vim.cmd([[hi GitSignsAdd guifg=#04de21]]) - vim.cmd([[hi GitSignsChange guifg=#83fce6]]) - vim.cmd([[hi GitSignsDelete guifg=#fa2525]]) - end, - }, - { - "which-key.nvim", - auto_enable = true, - -- cmd = { "" }, - event = "DeferredUIEnter", - -- ft = "", - -- keys = "", - -- colorscheme = "", - after = function (plugin) - require('which-key').setup({ - }) - require('which-key').add { - { "", group = "buffer commands" }, - { "_", hidden = true }, - { "c", group = "[c]ode" }, - { "c_", hidden = true }, - { "d", group = "[d]ocument" }, - { "d_", hidden = true }, - { "g", group = "[g]it" }, - { "g_", hidden = true }, - { "m", group = "[m]arkdown" }, - { "m_", hidden = true }, - { "r", group = "[r]ename" }, - { "r_", hidden = true }, - { "s", group = "[s]earch" }, - { "s_", hidden = true }, - { "t", group = "[t]oggles" }, - { "t_", hidden = true }, - { "w", group = "[w]orkspace" }, - { "w_", hidden = true }, - } - end, - }, -} diff --git a/lua/plugins/completion.lua b/lua/plugins/completion.lua new file mode 100644 index 0000000..d861e3a --- /dev/null +++ b/lua/plugins/completion.lua @@ -0,0 +1,156 @@ +local load_w_after = function(name) + vim.cmd.packadd(name) + vim.cmd.packadd(name .. '/after') +end + +return { + { + "cmp-cmdline", + for_cat = "lazy", + on_plugin = { "blink.cmp" }, + load = load_w_after, + }, + { + "blink.compat", + for_cat = "lazy", + dep_of = { "cmp-cmdline" }, + }, + { + "luasnip", + for_cat = "lazy", + dep_of = { "blink.cmp" }, + after = function(_) + vim.cmd.packadd("friendly-snippets") + local luasnip = require 'luasnip' + require('luasnip.loaders.from_vscode').lazy_load() + luasnip.config.setup {} + + local ls = require('luasnip') + + vim.keymap.set({ "i", "s" }, "", function() + if ls.choice_active() then + ls.change_choice(1) + end + end) + end, + }, + { + "colorful-menu.nvim", + for_cat = "lazy", + on_plugin = { "blink.cmp" }, + }, + { + "blink-emoji.nvim", + for_cat = "lazy", + on_plugin = { "blink.cmp" }, + }, + { + "blink.cmp", + for_cat = "lazy", + event = "DeferredUIEnter", + after = function(_) + require("blink.cmp").setup({ + -- 'default' (recommended) for mappings similar to built-in completions (C-y to accept) + -- See :h blink-cmp-config-keymap for configuring keymaps + keymap = { preset = "enter", }, + cmdline = { + enabled = true, + completion = { + menu = { + auto_show = true, + }, + }, + sources = function() + local type = vim.fn.getcmdtype() + -- Search forward and backward + if type == '/' or type == '?' then return { 'buffer' } end + -- Commands + if type == ':' or type == '@' then return { 'cmdline', 'cmp_cmdline' } end + return {} + end, + }, + fuzzy = { + sorts = { + 'exact', + -- defaults + 'score', + 'sort_text', + }, + }, + signature = { + enabled = true, + window = { + show_documentation = true, + }, + }, + completion = { + list = { + selection = { + preselect = false, + auto_insert = false, + }, + }, + menu = { + draw = { + treesitter = { 'lsp' }, + components = { + label = { + text = function(ctx) + return require("colorful-menu").blink_components_text(ctx) + end, + highlight = function(ctx) + return require("colorful-menu").blink_components_highlight(ctx) + end, + }, + }, + }, + }, + documentation = { + auto_show = true, + }, + }, + snippets = { + preset = 'luasnip', + active = function(filter) + local snippet = require "luasnip" + local blink = require "blink.cmp" + if snippet.in_snippet() and not blink.is_visible() then + return true + else + if not snippet.in_snippet() and vim.fn.mode() == "n" then snippet.unlink_current() end + return false + end + end, + }, + sources = { + default = { 'lsp', 'path', 'snippets', 'buffer', 'omni', 'emoji', }, + providers = { + path = { + score_offset = 50, + }, + lsp = { + score_offset = 40, + }, + snippets = { + score_offset = 40, + }, + emoji = { + module = "blink-emoji", + name = "Emoji", + score_offset = 15, + opts = { insert = true }, + }, + cmp_cmdline = { + name = 'cmp_cmdline', + module = 'blink.compat.source', + score_offset = -100, + opts = { + cmp_name = 'cmdline', + }, + }, + }, + }, + }) + end, + }, +} diff --git a/lua/plugins/gitsigns.lua b/lua/plugins/gitsigns.lua new file mode 100644 index 0000000..f75b4ab --- /dev/null +++ b/lua/plugins/gitsigns.lua @@ -0,0 +1,86 @@ +return { + { + "gitsigns.nvim", + for_cat = 'lazy', + event = "DeferredUIEnter", + -- cmd = { "" }, + -- ft = "", + -- keys = "", + -- colorscheme = "", + after = function() + require('gitsigns').setup({ + -- See `:help gitsigns.txt` + signs = { + add = { text = '+' }, + change = { text = '~' }, + delete = { text = '_' }, + topdelete = { text = '‾' }, + changedelete = { text = '~' }, + }, + on_attach = function(bufnr) + local gs = package.loaded.gitsigns + + local function map(mode, l, r, opts) + opts = opts or {} + opts.buffer = bufnr + vim.keymap.set(mode, l, r, opts) + end + + -- Navigation + map({ 'n', 'v' }, ']c', function() + if vim.wo.diff then + return ']c' + end + vim.schedule(function() + gs.next_hunk() + end) + return '' + end, { expr = true, desc = 'Jump to next hunk' }) + + map({ 'n', 'v' }, '[c', function() + if vim.wo.diff then + return '[c' + end + vim.schedule(function() + gs.prev_hunk() + end) + return '' + end, { expr = true, desc = 'Jump to previous hunk' }) + + -- Actions + -- visual mode + map('v', 'hs', function() + gs.stage_hunk { vim.fn.line '.', vim.fn.line 'v' } + end, { desc = 'stage git hunk' }) + map('v', 'hr', function() + gs.reset_hunk { vim.fn.line '.', vim.fn.line 'v' } + end, { desc = 'reset git hunk' }) + -- normal mode + map('n', 'gs', gs.stage_hunk, { desc = 'git stage hunk' }) + map('n', 'gr', gs.reset_hunk, { desc = 'git reset hunk' }) + map('n', 'gS', gs.stage_buffer, { desc = 'git Stage buffer' }) + map('n', 'gu', gs.undo_stage_hunk, { desc = 'undo stage hunk' }) + map('n', 'gR', gs.reset_buffer, { desc = 'git Reset buffer' }) + map('n', 'gp', gs.preview_hunk, { desc = 'preview git hunk' }) + map('n', 'gb', function() + gs.blame_line { full = false } + end, { desc = 'git blame line' }) + map('n', 'gd', gs.diffthis, { desc = 'git diff against index' }) + map('n', 'gD', function() + gs.diffthis '~' + end, { desc = 'git diff against last commit' }) + + -- Toggles + map('n', 'gtb', gs.toggle_current_line_blame, { desc = 'toggle git blame line' }) + map('n', 'gtd', gs.toggle_deleted, { desc = 'toggle git show deleted' }) + + -- Text object + map({ 'o', 'x' }, 'ih', ':Gitsigns select_hunk', { desc = 'select git hunk' }) + end, + }) + vim.cmd([[hi GitSignsAdd guifg=#04de21]]) + vim.cmd([[hi GitSignsChange guifg=#83fce6]]) + vim.cmd([[hi GitSignsDelete guifg=#fa2525]]) + end, + }, +} diff --git a/lua/plugins/init.lua b/lua/plugins/init.lua new file mode 100644 index 0000000..75916ad --- /dev/null +++ b/lua/plugins/init.lua @@ -0,0 +1,39 @@ +local colorschemeName = nixInfo("retrobox", "settings", "colorscheme") + +vim.cmd.colorscheme(colorschemeName) + +require("plugins.lualine") +require("plugins.oil") +require("plugins.snacks") + +require('lze').load { + { import = "plugins.treesitter", }, + { import = "plugins.gitsigns", }, + { import = "plugins.which-key", }, + { import = "plugins.completion", }, + { import = "plugins.preview.markdown", }, + { import = "plugins.preview.typst", }, + { + "leap.nvim", + for_cat = 'always', + event = "DeferredUIEnter", + keys = { + { "s", "(leap)", mode = { "n", "x", "o", "v" }, noremap = true, desc = "leap to char sequence" } + }, + }, + { + "nvim-surround", + for_cat = 'always', + event = "DeferredUIEnter", + after = function() + require('nvim-surround').setup() + end, + }, + { + "marks.nvim", + for_cat = "always", + after = function() + require('marks').setup({}) + end + }, +} diff --git a/lua/plugins/lualine.lua b/lua/plugins/lualine.lua new file mode 100644 index 0000000..8326653 --- /dev/null +++ b/lua/plugins/lualine.lua @@ -0,0 +1,36 @@ +-- lualine +require("lualine").setup({ + options = { + alwaysDivideMiddle = true, + icons_enabled = true, + component_separators = { left = "", right = "" }, + section_separators = { left = "", right = "" }, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = { "filename" }, + lualine_x = { "filetype" }, + lualine_y = {}, + lualine_z = {}, + }, + sections = { + lualine_a = { "mode" }, + lualine_b = { "branch", "diff", "diagnostics" }, + lualine_c = { { "filename", path = 1 } }, + lualine_x = { "encoding", "fileformat", "filetype" }, + lualine_y = { "progress" }, + lualine_z = { "location" }, + }, + tabline = { + lualine_a = { { "buffers", mode = 4 } }, + lualine_b = {}, + lualine_c = {}, + lualine_x = {}, + lualine_y = {}, + lualine_z = { { "tabs", mode = 2 } } + }, +}) + +-- marks.nvim +require("marks").setup({}) diff --git a/lua/plugins/oil.lua b/lua/plugins/oil.lua new file mode 100644 index 0000000..0acfa22 --- /dev/null +++ b/lua/plugins/oil.lua @@ -0,0 +1,45 @@ +-- oil.nvim +vim.g.loaded_netrwPlugin = 1 +require("oil").setup({ + default_file_explorer = false, + view_options = { + show_hidden = true + }, + columns = { + "icon", + "permissions", + "size", + -- "mtime", + }, + keymaps = { + ["g?"] = "actions.show_help", + [""] = "actions.select", + [""] = "actions.select_vsplit", + [""] = "actions.select_split", + [""] = "actions.select_tab", + [""] = "actions.preview", + [""] = "actions.close", + [""] = "actions.refresh", + ["-"] = "actions.parent", + ["_"] = "actions.open_cwd", + ["`"] = "actions.cd", + ["~"] = "actions.tcd", + ["gs"] = "actions.change_sort", + ["gx"] = "actions.open_external", + ["g."] = "actions.toggle_hidden", + ["g\\"] = "actions.toggle_trash", + }, +}) +-- setup rename autocmds +local prev = { new_name = "", old_name = "" } -- Prevents duplicate events +vim.api.nvim_create_autocmd("User", { + pattern = "OilActionsPost", + callback = function(event) + if event.data.actions.type == "move" then + Snacks.rename.on_rename_file(event.data.actions.src_url, event.data.actions.dest_url) + end + end, +}) +-- oil keybinds +vim.keymap.set("n", "-", "Oil", { noremap = true, desc = "Open Parent Directory" }) +vim.keymap.set("n", "-", "Oil .", { noremap = true, desc = "Open nvim root directory" }) diff --git a/lua/plugins/preview/markdown.lua b/lua/plugins/preview/markdown.lua new file mode 100644 index 0000000..c15a09b --- /dev/null +++ b/lua/plugins/preview/markdown.lua @@ -0,0 +1,19 @@ +return { + "markdown-preview.nvim", + -- NOTE: for_cat is a custom handler that just sets enabled value for us, + -- based on result of nixCats('cat.name') and allows us to set a different default if we wish + -- it is defined in luaUtils template in lua/nixCatsUtils/lzUtils.lua + -- you could replace this with enabled = nixCats('cat.name') == true + -- if you didnt care to set a different default for when not using nix than the default you already set + for_cat = 'markdown', + cmd = { "MarkdownPreview", "MarkdownPreviewStop", "MarkdownPreviewToggle", }, + ft = "markdown", + keys = { + { "Pmp", "MarkdownPreview ", mode = { "n" }, noremap = true, desc = "markdown preview" }, + { "Pms", "MarkdownPreviewStop ", mode = { "n" }, noremap = true, desc = "markdown preview stop" }, + { "Pmt", "MarkdownPreviewToggle ", mode = { "n" }, noremap = true, desc = "markdown preview toggle" }, + }, + before = function() + vim.g.mkdp_auto_close = 0 + end, +} diff --git a/lua/plugins/preview/typst.lua b/lua/plugins/preview/typst.lua new file mode 100644 index 0000000..5faa5dd --- /dev/null +++ b/lua/plugins/preview/typst.lua @@ -0,0 +1,14 @@ +return { + "typst-preview.nvim", + for_cat = "typst", + ft = "typst", + cmd = { "TypstPreview", "TypstPreviewStop", "TypstPreviewToggle", }, + keys = { + { "ptp", "TypstPreview ", mode = { "n" }, noremap = true, desc = "typst preview" }, + { "pts", "TypstPreviewStop ", mode = { "n" }, noremap = true, desc = "typst preview stop" }, + { "ptt", "TypstPreviewToggle ", mode = { "n" }, noremap = true, desc = "typst preview toggle" }, + }, + after = function() + require('typst-preview').setup {} + end +} diff --git a/lua/plugins/snacks.lua b/lua/plugins/snacks.lua new file mode 100644 index 0000000..3ed8815 --- /dev/null +++ b/lua/plugins/snacks.lua @@ -0,0 +1,87 @@ +-- snacks.nvim setup +require("snacks").setup({ + bufdelete = { enable = true }, + dim = { enable = true }, + git = { enable = true }, + input = { enable = true }, + notifier = { enable = true }, + terminal = { enable = true }, + toggle = { enable = true }, + quickfile = { enable = true }, + scope = { enable = true }, + statuscolumn = { enable = true }, + + explorer = { replace_netrw = true }, + picker = { + enabled = true, + ui_select = true, + matcher = { + fuzzy = true, + frecency = true, + }, + previewers = { + diff = { + builtin = true, -- use Neovim for previewing diffs (true) or use an external tool (false) + cmd = { "delta" }, -- example to show a diff with delta + }, + git = { + builtin = true, -- use Neovim for previewing git output (true) or use git (false) + }, + }, + }, + indent = { + enabled = true, + animate = { enabled = false }, + scope = { enabled = true }, + chunk = { enabled = true }, + }, + image = { enabled = false, inline = false, float = false }, + lazygit = { enabled = true, configure = false }, +}) +-- setup keybinds. +vim.keymap.set("n", "bd", Snacks.bufdelete.delete, { desc = "delete buffer" }) +vim.keymap.set("n", "t", function() Snacks.explorer() end, { desc = "File [T]ree" }) +vim.keymap.set("n", "i", Snacks.image.hover, { desc = "[I]mage preview" }) + +-- picker keybinds +vim.keymap.set("n", "fGb", Snacks.picker.grep_buffers, { desc = "[G]rep buffers" }) +vim.keymap.set("n", "fGl", Snacks.picker.lines, { desc = "[L]ines in buffer" }) +vim.keymap.set("n", "fb", Snacks.picker.buffers, { desc = "[B]uffers" }) +vim.keymap.set("n", "ff", Snacks.picker.files, { desc = "[F]iles" }) +vim.keymap.set("n", "fg", Snacks.picker.grep, { desc = "[G]rep all" }) +vim.keymap.set("n", "fh", Snacks.picker.help, { desc = "[H]elp" }) +vim.keymap.set("n", "fi", Snacks.picker.icons, { desc = "[I]cons" }) +vim.keymap.set("n", "fm", Snacks.picker.marks, { desc = "[M]arks" }) +vim.keymap.set("n", "fs", Snacks.picker.spelling, { desc = "[S]pelling" }) +vim.keymap.set("n", "ft", Snacks.picker.treesitter, { desc = "[T]reesitter" }) +vim.keymap.set("n", "fu", Snacks.picker.undo, { desc = "[U]ndo" }) +vim.keymap.set("n", "fz", Snacks.picker.zoxide, { desc = "[Z]oxide" }) + +-- picker git keybinds +vim.keymap.set("n", "gB", Snacks.git.blame_line, { desc = "[G]it [B]lame" }) +vim.keymap.set("n", "gb", Snacks.picker.git_branches, { desc = "[G]it [B]ranch" }) +vim.keymap.set("n", "gl", Snacks.picker.git_log, { desc = "[G]it [L]og" }) +vim.keymap.set("n", "gd", Snacks.picker.git_diff, { desc = "[G]it [D]iff" }) +vim.keymap.set("n", "gt", Snacks.lazygit.open, { desc = "lazy[G]it [T]UI" }) + +-- setup toggles +Snacks.toggle.option("spell", { name = "spelling" }):map("cs") +Snacks.toggle.option("relativenumber", { name = "Relative Numbering" }):map("n") +Snacks.toggle.dim():map("d") + +-- terminal keybinds +vim.keymap.set("n", "s", function() + Snacks.terminal.toggle(nil, { win = { position = "float" } }) +end, { desc = "terminal" }) + +-- double tap escape leaves terminal mode +vim.keymap.set("t", "", function(self) + self.esc_timer = self.esc_timer or (vim.uv or vim.loop).new_timer() + if self.esc_timer:is_active() then + self.esc_timer:stop() + vim.cmd("stopinsert") + else + self.esc_timer:start(200, 0, function() end) + return "" + end +end, { expr = true, desc = "Double tap to escape terminal" }) diff --git a/lua/plugins/treesitter.lua b/lua/plugins/treesitter.lua new file mode 100644 index 0000000..9b49fcf --- /dev/null +++ b/lua/plugins/treesitter.lua @@ -0,0 +1,36 @@ +-- [[ Configure Treesitter ]] +-- See `:help nvim-treesitter` +return { + { + "nvim-treesitter", + for_cat = 'lazy', + event = "DeferredUIEnter", + load = function(name) + vim.cmd.packadd(name) + vim.cmd.packadd("rainbow-delimiters.nvim") + end, + after = function() + require('nvim-treesitter').setup { + highlight = { enable = true, }, + indent = { enable = false, }, + } + end, + }, + { + "comment.nvim", + for_cat = 'lazy', + after = function(plugin) + require('Comment').setup() + end, + }, + { + "treesj", + for_cat = 'lazy', + keys = { { "j", "TSJToggle", mode = { "n" }, desc = "Treesitter join" }, }, + after = function(_) + require("treesj").setup({ + use_default_keymaps = false + }) + end + }, +} diff --git a/lua/plugins/which-key.lua b/lua/plugins/which-key.lua new file mode 100644 index 0000000..c91aa99 --- /dev/null +++ b/lua/plugins/which-key.lua @@ -0,0 +1,22 @@ +return { + { + "which-key.nvim", + for_cat = 'lazy', + after = function() + require('which-key').setup({}) + require('which-key').add { + { "g", group = "[g]it" }, + { "z", group = "[z]ettelkasten" }, + { "gt", group = "[t]oggle" }, + { "p", group = "[p]review" }, + { "pt", group = "[p]review [t]ypst" }, + { "pm", group = "[p]review [m]arkdown" }, + { "f", group = "[f]ind" }, + { "t", group = "[t]ree" }, + { "c", group = "[c]heck" }, + { "l", group = "[l]sp" }, + { "lw", group = "[l]sp [w]orkspace" }, + } + end, + }, +} diff --git a/module.nix b/module.nix index 825101d..5937917 100644 --- a/module.nix +++ b/module.nix @@ -38,7 +38,7 @@ inputs: { # You can declare your own options! options.settings.colorscheme = lib.mkOption { type = lib.types.str; - default = "onedark_dark"; + default = "gruvbox"; }; options.settings.minimal = lib.mkOption { type = lib.types.bool; @@ -47,7 +47,6 @@ inputs: { config.settings.colorscheme = "gruvbox"; # <- just demonstrating that it is an option # and grab it in lua with `require(vim.g.nix_info_plugin_name)("onedark", "settings", "colorscheme") == "moonfly"` config.specs.colorscheme = { - lazy = true; enable = lib.mkIf config.settings.minimal (lib.mkDefault true); data = builtins.getAttr config.settings.colorscheme ( with pkgs.vimPlugins; { @@ -82,6 +81,7 @@ inputs: { fzf zoxide git + delta lazygit tree-sitter ]; @@ -93,7 +93,6 @@ inputs: { oil-nvim nvim-web-devicons nvim-numbertoggle - lualine-nvim marks-nvim ]; };