diff --git a/.config/nvim/README.md b/.config/nvim/README.md new file mode 100644 index 0000000..56cfb3d --- /dev/null +++ b/.config/nvim/README.md @@ -0,0 +1,6 @@ +# Neovim configuration + +My neovim configuration. Available as a Nix flake [^nixcats]. When installing manually, +`paq.nvim` is used as a fallback plugin manager. + +[^nixcats]: Based on [this nixCats `example` template](https://github.com/BirdeeHub/nixCats-nvim/tree/77dffad8235eb77684fcb7599487c8e9f23d5b8f/templates/example) diff --git a/.config/nvim/flake.lock b/.config/nvim/flake.lock new file mode 100644 index 0000000..a1e599f --- /dev/null +++ b/.config/nvim/flake.lock @@ -0,0 +1,162 @@ +{ + "nodes": { + "nixCats": { + "locked": { + "lastModified": 1759730664, + "narHash": "sha256-boRlBQ/c4CaHsK/z04QL6+t81mcar37Io94HBX2GflY=", + "owner": "BirdeeHub", + "repo": "nixCats-nvim", + "rev": "77dffad8235eb77684fcb7599487c8e9f23d5b8f", + "type": "github" + }, + "original": { + "owner": "BirdeeHub", + "repo": "nixCats-nvim", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1760256791, + "narHash": "sha256-uTpzDHRASEDeFUuToWSQ46Re8beXyG9dx4W36FQa0/c=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "832e3b6db48508ae436c2c7bfc0cf914eac6938e", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "plugins-beancount-nvim": { + "flake": false, + "locked": { + "lastModified": 1707748314, + "narHash": "sha256-LuACGVB3kiaiJqoGtvFy6kbPNtqoGliKLDeR+Z7Wzbw=", + "owner": "polarmutex", + "repo": "beancount.nvim", + "rev": "869564aba3087ee5df8f282aa37555e314aa2152", + "type": "github" + }, + "original": { + "owner": "polarmutex", + "repo": "beancount.nvim", + "type": "github" + } + }, + "plugins-crazy-node-movement": { + "flake": false, + "locked": { + "lastModified": 1693654676, + "narHash": "sha256-hQcQEp39zFN2zphMfcr97yRVcuHhBsSkzKO7XNloDpQ=", + "owner": "theHamsta", + "repo": "crazy-node-movement", + "rev": "d5cf01cc44c5715501d3d6fe439af7c8b7fa5df2", + "type": "github" + }, + "original": { + "owner": "theHamsta", + "repo": "crazy-node-movement", + "type": "github" + } + }, + "plugins-helm-ls-nvim": { + "flake": false, + "locked": { + "lastModified": 1757598429, + "narHash": "sha256-nzuJxAAaEmuVYg9k0B8OKslxsihhg6RKlhz6E7xJTQU=", + "owner": "qvalentin", + "repo": "helm-ls.nvim", + "rev": "f36ecbd3e7b0b2ac8358a9d6a3213888e29943db", + "type": "github" + }, + "original": { + "owner": "qvalentin", + "repo": "helm-ls.nvim", + "type": "github" + } + }, + "plugins-mcphub-nvim": { + "flake": false, + "locked": { + "lastModified": 1759035242, + "narHash": "sha256-I6EbgY/2sAdtrxtmH0qbAAQvMCHhOsfolJfblV0fXOk=", + "owner": "ravitemer", + "repo": "mcphub.nvim", + "rev": "8ff40b5edc649959bb7e89d25ae18e055554859a", + "type": "github" + }, + "original": { + "owner": "ravitemer", + "repo": "mcphub.nvim", + "type": "github" + } + }, + "plugins-nvimkit-nvim": { + "flake": false, + "locked": { + "lastModified": 1721393835, + "narHash": "sha256-MdmrhLHMxrn6upu1chjKyitPZ5WkCQtpI465AKJXDOA=", + "owner": "jamesblckwell", + "repo": "nvimkit.nvim", + "rev": "af363d22699760f66988e8d36539a5753039217a", + "type": "github" + }, + "original": { + "owner": "jamesblckwell", + "repo": "nvimkit.nvim", + "type": "github" + } + }, + "plugins-shipwright-nvim": { + "flake": false, + "locked": { + "lastModified": 1711725275, + "narHash": "sha256-xh/2m//Cno5gPucjOYih79wVZj3X1Di/U3/IQhKXjc0=", + "owner": "rktjmp", + "repo": "shipwright.nvim", + "rev": "e596ab48328c31873f4f4d2e070243bf9de16ff3", + "type": "github" + }, + "original": { + "owner": "rktjmp", + "repo": "shipwright.nvim", + "type": "github" + } + }, + "plugins-tailwind-fold-nvim": { + "flake": false, + "locked": { + "lastModified": 1752559116, + "narHash": "sha256-8uefZIVsn9USEd6FyiO3m3TRKAS/vigU4t9Tk5ijd3c=", + "owner": "razak17", + "repo": "tailwind-fold.nvim", + "rev": "d9e7ca11691d252b35795726dff087bf013b2ebf", + "type": "github" + }, + "original": { + "owner": "razak17", + "repo": "tailwind-fold.nvim", + "type": "github" + } + }, + "root": { + "inputs": { + "nixCats": "nixCats", + "nixpkgs": "nixpkgs", + "plugins-beancount-nvim": "plugins-beancount-nvim", + "plugins-crazy-node-movement": "plugins-crazy-node-movement", + "plugins-helm-ls-nvim": "plugins-helm-ls-nvim", + "plugins-mcphub-nvim": "plugins-mcphub-nvim", + "plugins-nvimkit-nvim": "plugins-nvimkit-nvim", + "plugins-shipwright-nvim": "plugins-shipwright-nvim", + "plugins-tailwind-fold-nvim": "plugins-tailwind-fold-nvim" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/.config/nvim/flake.nix b/.config/nvim/flake.nix new file mode 100644 index 0000000..2206ad7 --- /dev/null +++ b/.config/nvim/flake.nix @@ -0,0 +1,212 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + nixCats.url = "github:BirdeeHub/nixCats-nvim"; + + plugins-shipwright-nvim = { + url = "github:rktjmp/shipwright.nvim"; + flake = false; + }; + plugins-crazy-node-movement = { + url = "github:theHamsta/crazy-node-movement"; + flake = false; + }; + plugins-beancount-nvim = { + url = "github:polarmutex/beancount.nvim"; + flake = false; + }; + plugins-tailwind-fold-nvim = { + url = "github:razak17/tailwind-fold.nvim"; + flake = false; + }; + plugins-nvimkit-nvim = { + url = "github:jamesblckwell/nvimkit.nvim"; + flake = false; + }; + plugins-mcphub-nvim = { + url = "github:ravitemer/mcphub.nvim"; + flake = false; + }; + plugins-helm-ls-nvim = { + url = "github:qvalentin/helm-ls.nvim"; + flake = false; + }; + + }; + + outputs = + { + self, + nixpkgs, + nixCats, + ... + }@inputs: + let + inherit (nixCats) utils; + luaPath = ./.; + forEachSystem = utils.eachSystem nixpkgs.lib.platforms.all; + extra_pkg_config = { }; + + dependencyOverlays = [ + (utils.standardPluginOverlay inputs) + ]; + + categoryDefinitions = + { + pkgs, + ... + }: + { + lspsAndRuntimeDeps = with pkgs; { + general = [ + tree-sitter + ]; + }; + + startupPlugins = { + general = with pkgs.vimPlugins; [ + eyeliner-nvim + fzf-lua + ltex_extra-nvim + nvim-lspconfig + lsp_lines-nvim + lsp-progress-nvim + neodev-nvim + SchemaStore-nvim + nvim-lint + conform-nvim + luasnip + cmp_luasnip + nvim-cmp + cmp-nvim-lsp + cmp-buffer + cmp-path + plenary-nvim + nui-nvim + trouble-nvim + pkgs.neovimPlugins.shipwright-nvim + lush-nvim + zenbones-nvim + pkgs.neovimPlugins.crazy-node-movement + nvim-treesitter.withAllGrammars + nvim-treesitter-textobjects + # nvim-treesitter-context + nvim-ts-context-commentstring + treesj + sniprun + gitsigns-nvim + nvim-highlight-colors + pkgs.neovimPlugins.tailwind-fold-nvim + auto-session + nvim-dbee + image-nvim + pkgs.neovimPlugins.beancount-nvim + pkgs.neovimPlugins.nvimkit-nvim + codecompanion-nvim + pkgs.neovimPlugins.mcphub-nvim + copilot-lua + copilot-cmp + pkgs.neovimPlugins.helm-ls-nvim + ]; + }; + + optionalPlugins = { + general = with pkgs.vimPlugins; [ + ]; + }; + + sharedLibraries = { + general = [ ]; + }; + + environmentVariables = { }; + }; + + packageDefinitions = { + nvim = + { ... }: + { + settings = { + suffix-path = true; + suffix-LD = true; + wrapRc = true; + aliases = [ "vim" ]; + }; + categories = { + general = true; + }; + }; + }; + defaultPackageName = "nvim"; + in + + forEachSystem ( + system: + let + nixCatsBuilder = utils.baseBuilder luaPath { + inherit + nixpkgs + system + dependencyOverlays + extra_pkg_config + ; + } categoryDefinitions packageDefinitions; + defaultPackage = nixCatsBuilder defaultPackageName; + pkgs = import nixpkgs { inherit system; }; + in + { + packages = utils.mkAllWithDefault defaultPackage; + + devShells = { + default = pkgs.mkShell { + name = defaultPackageName; + packages = [ defaultPackage ]; + inputsFrom = [ ]; + shellHook = ''''; + }; + }; + + } + ) + // ( + let + nixosModule = utils.mkNixosModules { + moduleNamespace = [ defaultPackageName ]; + inherit + defaultPackageName + dependencyOverlays + luaPath + categoryDefinitions + packageDefinitions + extra_pkg_config + nixpkgs + ; + }; + homeModule = utils.mkHomeModules { + moduleNamespace = [ defaultPackageName ]; + inherit + defaultPackageName + dependencyOverlays + luaPath + categoryDefinitions + packageDefinitions + extra_pkg_config + nixpkgs + ; + }; + in + { + + overlays = utils.makeOverlays luaPath { + inherit nixpkgs dependencyOverlays extra_pkg_config; + } categoryDefinitions packageDefinitions defaultPackageName; + + nixosModules.default = nixosModule; + homeModules.default = homeModule; + + inherit utils nixosModule homeModule; + inherit (utils) templates; + } + ); + +} diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua index 0fad537..2ed7ee5 100644 --- a/.config/nvim/init.lua +++ b/.config/nvim/init.lua @@ -1,9 +1,12 @@ +require("nixCatsUtils").setup({ non_nix_value = true }) -- https://github.com/BirdeeHub/nixCats-nvim/blob/77dffad8235eb77684fcb7599487c8e9f23d5b8f/templates/example/init.lua + require("vim") require("ftdetect") require("keymaps") require("highlight") -require("paq-setup") require("diagnostic") +require("paq-setup") -- when not on nixCats + -- vim.opt.background = "dark" -- vim.opt.laststatus = 3 diff --git a/.config/nvim/lua/nixCatsUtils/catPacker.lua b/.config/nvim/lua/nixCatsUtils/catPacker.lua new file mode 100644 index 0000000..bc28ccb --- /dev/null +++ b/.config/nvim/lua/nixCatsUtils/catPacker.lua @@ -0,0 +1,53 @@ +-- Source: https://github.com/BirdeeHub/nixCats-nvim/blob/main/templates/example/lua/nixCatsUtils/catPacker.lua +--[[ + This directory is the luaUtils template. + You can choose what things from it that you would like to use. + And then delete the rest. + Everything in this directory is optional. +--]] + +local M = {} +-- NOTE: This function is for defining a paq.nvim fallback method of downloading plugins +-- when nixCats was not used to install your config. +-- If you only ever load your config using nixCats, you don't need this file. + +-- it literally just only runs it when not on nixCats +-- all neovim package managers that use the regular plugin loading scheme +-- can be used this way, just do whatever the plugin manager needs to put it in the +-- opt directory for lazy loading, and add the build steps so that when theres no nix the steps are ran +function M.setup(v) + if not vim.g[ [[nixCats-special-rtp-entry-nixCats]] ] then + local function clone_paq() + local path = vim.fn.stdpath("data") .. "/site/pack/paqs/start/paq-nvim" + local is_installed = vim.fn.empty(vim.fn.glob(path)) == 0 + if not is_installed then + vim.fn.system({ "git", "clone", "--depth=1", "https://github.com/savq/paq-nvim.git", path }) + return true + end + end + local function bootstrap_paq(packages) + local first_install = clone_paq() + vim.cmd.packadd("paq-nvim") + local paq = require("paq") + if first_install then + vim.notify("Installing plugins... If prompted, hit Enter to continue.") + end + paq(packages) + paq.install() + end + + vim.api.nvim_create_autocmd("VimEnter", { + once = true, + callback = function() + local pkgs_count = #require("paq").query("to_install") + if pkgs_count < 1 then + return + end + vim.notify(string.format("There are %d to install", pkgs_count)) + end, + }) + + bootstrap_paq(vim.list_extend({ "savq/paq-nvim" }, v)) + end +end +return M diff --git a/.config/nvim/lua/nixCatsUtils/init.lua b/.config/nvim/lua/nixCatsUtils/init.lua new file mode 100644 index 0000000..c8253d8 --- /dev/null +++ b/.config/nvim/lua/nixCatsUtils/init.lua @@ -0,0 +1,136 @@ +-- Source: https://github.com/BirdeeHub/nixCats-nvim/blob/main/templates/example/lua/nixCatsUtils/init.lua +--[[ + This directory is the luaUtils template. + You can choose what things from it that you would like to use. + And then delete the rest. + Everything in this directory is optional. +--]] + +local M = {} + +--[[ + This file is for making your config still work WITHOUT nixCats. + When you don't use nixCats to load your config, + you wont have the nixCats plugin. + + The setup function defined here defines a mock nixCats plugin when nixCats wasnt used to load the config. + This will help avoid indexing errors when the nixCats plugin doesnt exist. + + NOTE: If you only ever use nixCats to load your config, you don't need this file. +--]] + +---@type boolean +M.isNixCats = vim.g[ [[nixCats-special-rtp-entry-nixCats]] ] ~= nil + +---@class nixCatsSetupOpts +---@field non_nix_value boolean|nil + +---This function will setup a mock nixCats plugin when not using nix +---It will help prevent you from running into indexing errors without a nixCats plugin from nix. +---If you loaded the config via nix, it does nothing +---non_nix_value defaults to true if not provided or is not a boolean. +---@param v nixCatsSetupOpts +function M.setup(v) + if not M.isNixCats then + local nixCats_default_value + if type(v) == "table" and type(v.non_nix_value) == "boolean" then + nixCats_default_value = v.non_nix_value + else + nixCats_default_value = true + end + local mk_with_meta = function(tbl) + return setmetatable(tbl, { + __call = function(_, attrpath) + local strtable = {} + if type(attrpath) == "table" then + strtable = attrpath + elseif type(attrpath) == "string" then + for key in attrpath:gmatch("([^%.]+)") do + table.insert(strtable, key) + end + else + print("function requires a table of strings or a dot separated string") + return + end + return vim.tbl_get(tbl, unpack(strtable)) + end, + }) + end + package.preload["nixCats"] = function() + local ncsub = { + get = function(_) + return nixCats_default_value + end, + cats = mk_with_meta({ + nixCats_config_location = vim.fn.stdpath("config"), + wrapRc = false, + }), + settings = mk_with_meta({ + nixCats_config_location = vim.fn.stdpath("config"), + configDirName = os.getenv("NVIM_APPNAME") or "nvim", + wrapRc = false, + }), + petShop = mk_with_meta({}), + extra = mk_with_meta({}), + pawsible = mk_with_meta({ + allPlugins = { + start = {}, + opt = {}, + }, + }), + configDir = vim.fn.stdpath("config"), + packageBinPath = os.getenv("NVIM_WRAPPER_PATH_NIX") or vim.v.progpath, + } + return setmetatable(ncsub, { + __call = function(_, cat) + return ncsub.get(cat) + end, + }) + end + _G.nixCats = require("nixCats") + end +end + +---allows you to guarantee a boolean is returned, and also declare a different +---default value than specified in setup when not using nix to load the config +---@overload fun(v: string|string[]): boolean +---@overload fun(v: string|string[], default: boolean): boolean +function M.enableForCategory(v, default) + if M.isNixCats or default == nil then + if nixCats(v) then + return true + else + return false + end + else + return default + end +end + +---if nix, return value of nixCats(v) else return default +---Exists to specify a different non_nix_value than the one in setup() +---@param v string|string[] +---@param default any +---@return any +function M.getCatOrDefault(v, default) + if M.isNixCats then + return nixCats(v) + else + return default + end +end + +---for conditionally disabling build steps on nix, as they are done via nix +---I should probably have named it dontAddIfCats or something. +---@overload fun(v: any): any|nil +---Will return the second value if nix, otherwise the first +---@overload fun(v: any, o: any): any +function M.lazyAdd(v, o) + if M.isNixCats then + return o + else + return v + end +end + +return M diff --git a/.config/nvim/lua/paq-setup.lua b/.config/nvim/lua/paq-setup.lua index 6deeba1..273f181 100644 --- a/.config/nvim/lua/paq-setup.lua +++ b/.config/nvim/lua/paq-setup.lua @@ -1,38 +1,4 @@ --- Automate paq installation {{{ -local function clone_paq() - local path = vim.fn.stdpath("data") .. "/site/pack/paqs/start/paq-nvim" - local is_installed = vim.fn.empty(vim.fn.glob(path)) == 0 - if not is_installed then - vim.fn.system({ "git", "clone", "--depth=1", "https://github.com/savq/paq-nvim.git", path }) - return true - end -end -local function bootstrap_paq(packages) - local first_install = clone_paq() - vim.cmd.packadd("paq-nvim") - local paq = require("paq") - if first_install then - vim.notify("Installing plugins... If prompted, hit Enter to continue.") - end - paq(packages) - paq.install() -end - -vim.api.nvim_create_autocmd("VimEnter", { - once = true, - callback = function() - local pkgs_count = #require("paq").query("to_install") - if pkgs_count < 1 then - return - end - vim.notify(string.format("There are %d to install", pkgs_count)) - end, -}) - --- }}} - --- Set up paq plugins {{{ -bootstrap_paq({ +require("nixCatsUtils.catPacker").setup({ { "savq/paq-nvim" }, { "jinh0/eyeliner.nvim" }, { "ibhagwan/fzf-lua" }, @@ -77,4 +43,3 @@ bootstrap_paq({ { "zbirenbaum/copilot-cmp" }, { "qvalentin/helm-ls.nvim", ft = "helm" }, }) --- }}} diff --git a/README.md b/README.md index 0a51aed..fb139a5 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,6 @@ bash <(curl -s https://git.hektormisplon.xyz/hektor/dots/raw/branch/master/.bin/ Note: will not set up *everything* (e.g. `/etc` configs, dependencies...), but should get you up and running. + +2025-10-04: I am migrating from Arch Linux to NixOS. For this transition, these +dotfiles are currently included as a subtree in my [NixOS repository](https://git.hektormisplon.xyz/hektor/nix).