commit 9a78fd2d538d1befa302c724eb1844b5b936948d Author: Gabe Venberg Date: Fri Jun 27 21:05:54 2025 +0200 inital commit, initalized from nix flake init -t github:BirdeeHub/nixCats-nvim#example. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..be5b321 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/result +/tags +/.luarc.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..1157d64 --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +# Example `nixCats` Configuration + +This directory contains an example of the suggested, idiomatic way to manage a neovim configuration using `nixCats`. It leverages [`lze`](https://github.com/BirdeeHub/lze) for lazy loading, although [`lz.n`](https://github.com/nvim-neorocks/lz.n) can be used instead to similar effect. It also includes a fallback mechanism using `paq` and `mason`, allowing you to load the directory without `nix` if needed. + +This setup serves as a strong starting point for a `Neovim` configuration—think of it as `kickstart.nvim`, but using `nixCats` **instead of** `lazy.nvim` and `mason`, rather than in addition to them. It also follows a modular approach, spreading the configuration across multiple files rather than consolidating everything into one. + +While this is not a "perfect" configuration, nor does it claim to be, it is **a well-structured, recommended way to use `nixCats`**. You are encouraged to customize it to fit your needs. `nixCats` itself is just the `nix`-based package manager, along with its associated [Lua plugin](https://nixcats.org/nixCats_plugin.html). + +## Why Use This Approach? + +Using `nixCats` in this way provides a **simpler, more transparent** experience compared to solutions like `lazy.nvim`, which hijack normal plugin loading. + +It leverages the normal packpath methods of loading plugins both at startup and lazily, allowing you to know what is going on behind the scenes. + +It avoids duplicating functionality between nix and other nvim based download managers, avoiding compatibility issues. + +You can still have a config that works without nix using this method if desired without undue difficulty. + +## Directory Structure + +This configuration primarily uses the following directory structure: + +- The `lua/` directory for core configurations. +- The `after/plugin/` directory to demonstrate compatibility. + +While this structure works well, you are encouraged to further modularize your setup by utilizing any of the runtime directories checked by Neovim: + +- `ftplugin/` for file-type-specific configurations. +- `plugin/` for global plugin configurations. +- Even `pack/*/{start,opt}/` work if you want to make a plugin inside your configuration. +- And so on... + +If you are unfamiliar with the above, refer to the [Neovim runtime path documentation](https://neovim.io/doc/user/options.html#'rtp'). + +--- + +> "Idiomatic" here means: +> +> - This configuration does **not** use `lazy.nvim`, and does not use `mason.nvim` when nix is involved. +> - `nixCats` is responsible for downloading all plugins. +> - Plugins are only loaded if their respective category is enabled. +> - The [Lua utilities template](https://github.com/BirdeeHub/nixCats-nvim/tree/main/templates/luaUtils/lua/nixCatsUtils) is used (see [`:h nixCats.luaUtils`](https://nixcats.org/nixCats_luaUtils.html)). +> - [`lze`](https://github.com/BirdeeHub/lze) or [`lz.n`](https://github.com/nvim-neorocks/lz.n) is used for lazy loading. diff --git a/after/plugin/colors.lua b/after/plugin/colors.lua new file mode 100644 index 0000000..9b3d8cf --- /dev/null +++ b/after/plugin/colors.lua @@ -0,0 +1 @@ +vim.cmd([[hi LineNr guifg=#bb9af7]]) diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..6cb497d --- /dev/null +++ b/flake.lock @@ -0,0 +1,43 @@ +{ + "nodes": { + "nixCats": { + "locked": { + "lastModified": 1750385475, + "narHash": "sha256-jxssG9BjbGlxXGhAhtwIIaazpQxROpO0919aGaKuIiY=", + "owner": "BirdeeHub", + "repo": "nixCats-nvim", + "rev": "0dbb19a5688f045e6e8b4f9f35bc32cdb777b1a9", + "type": "github" + }, + "original": { + "owner": "BirdeeHub", + "repo": "nixCats-nvim", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1750215678, + "narHash": "sha256-Rc/ytpamXRf6z8UA2SGa4aaWxUXRbX2MAWIu2C8M+ok=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "5395fb3ab3f97b9b7abca147249fa2e8ed27b192", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixCats": "nixCats", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..9e233bb --- /dev/null +++ b/flake.nix @@ -0,0 +1,535 @@ +# Copyright (c) 2023 BirdeeHub +# Licensed under the MIT license + +# Welcome to the main example config of nixCats! +# there is a minimal flake the starter templates use +# within the nix directory without the nixpkgs input, +# but this one would work too! +# Every config based on nixCats is a full nixCats. + +# This example config doesnt use lazy.nvim, and +# it loads everything via nix. + +# It has some useful tricks +# in it, especially for lsps, so if you have any questions, +# first look through the docs, and then here! +# It has examples of most of the things you would want to do +# in your main nvim configuration. + +# If there is still not adequate info, ask in discussions +# on the nixCats repo (or open a PR to add the info to the help!) +{ + description = "A Lua-natic's neovim flake, with extra cats! nixCats!"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + nixCats.url = "github:BirdeeHub/nixCats-nvim"; + + # see :help nixCats.flake.inputs + # If you want your plugin to be loaded by the standard overlay, + # i.e. if it wasnt on nixpkgs, but doesnt have an extra build step. + # Then you should name it "plugins-something" + # If you wish to define a custom build step not handled by nixpkgs, + # then you should name it in a different format, and deal with that in the + # overlay defined for custom builds in the overlays directory. + # for specific tags, branches and commits, see: + # https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html#examples + + # No longer fetched to avoid forcing people to import it, but this remains here as a tutorial. + # How to import it into your config is shown farther down in the startupPlugins set. + # You put it here like this, and then below you would use it with `pkgs.neovimPlugins.hlargs` + + # "plugins-hlargs" = { + # url = "github:m-demare/hlargs.nvim"; + # flake = false; + # }; + + # neovim-nightly-overlay = { + # url = "github:nix-community/neovim-nightly-overlay"; + # }; + + }; + + # see :help nixCats.flake.outputs + outputs = { self, nixpkgs, ... }@inputs: let + inherit (inputs.nixCats) utils; + luaPath = ./.; + # this is flake-utils eachSystem + forEachSystem = utils.eachSystem nixpkgs.lib.platforms.all; + # the following extra_pkg_config contains any values + # which you want to pass to the config set of nixpkgs + # import nixpkgs { config = extra_pkg_config; inherit system; } + # will not apply to module imports + # as that will have your system values + extra_pkg_config = { + # allowUnfree = true; + }; + # management of the system variable is one of the harder parts of using flakes. + + # so I have done it here in an interesting way to keep it out of the way. + # It gets resolved within the builder itself, and then passed to your + # categoryDefinitions and packageDefinitions. + + # this allows you to use ${pkgs.system} whenever you want in those sections + # without fear. + + # see :help nixCats.flake.outputs.overlays + dependencyOverlays = /* (import ./overlays inputs) ++ */ [ + # This overlay grabs all the inputs named in the format + # `plugins-` + # Once we add this overlay to our nixpkgs, we are able to + # use `pkgs.neovimPlugins`, which is a set of our plugins. + (utils.standardPluginOverlay inputs) + # add any other flake overlays here. + + # when other people mess up their overlays by wrapping them with system, + # you may instead call this function on their overlay. + # it will check if it has the system in the set, and if so return the desired overlay + # (utils.fixSystemizedOverlay inputs.codeium.overlays + # (system: inputs.codeium.overlays.${system}.default) + # ) + ]; + + # see :help nixCats.flake.outputs.categories + # and + # :help nixCats.flake.outputs.categoryDefinitions.scheme + categoryDefinitions = { pkgs, settings, categories, extra, name, mkPlugin, ... }@packageDef: { + # to define and use a new category, simply add a new list to a set here, + # and later, you will include categoryname = true; in the set you + # provide when you build the package using this builder function. + # see :help nixCats.flake.outputs.packageDefinitions for info on that section. + + # lspsAndRuntimeDeps: + # this section is for dependencies that should be available + # at RUN TIME for plugins. Will be available to PATH within neovim terminal + # this includes LSPs + lspsAndRuntimeDeps = { + # some categories of stuff. + general = with pkgs; [ + universal-ctags + ripgrep + fd + ]; + # these names are arbitrary. + lint = with pkgs; [ + ]; + # but you can choose which ones you want + # per nvim package you export + debug = with pkgs; { + go = [ delve ]; + }; + go = with pkgs; [ + gopls + gotools + go-tools + gccgo + ]; + # and easily check if they are included in lua + format = with pkgs; [ + ]; + neonixdev = { + # also you can do this. + inherit (pkgs) nix-doc lua-language-server nixd; + # and each will be its own sub category + }; + }; + + # This is for plugins that will load at startup without using packadd: + startupPlugins = { + debug = with pkgs.vimPlugins; [ + nvim-nio + ]; + general = with pkgs.vimPlugins; { + # you can make subcategories!!! + # (always isnt a special name, just the one I chose for this subcategory) + always = [ + lze + lzextras + vim-repeat + plenary-nvim + nvim-notify + ]; + extra = [ + oil-nvim + nvim-web-devicons + ]; + }; + # You can retreive information from the + # packageDefinitions of the package this was packaged with. + # :help nixCats.flake.outputs.categoryDefinitions.scheme + themer = with pkgs.vimPlugins; + (builtins.getAttr (categories.colorscheme or "onedark") { + # Theme switcher without creating a new category + "onedark" = onedark-nvim; + "catppuccin" = catppuccin-nvim; + "catppuccin-mocha" = catppuccin-nvim; + "tokyonight" = tokyonight-nvim; + "tokyonight-day" = tokyonight-nvim; + } + ); + # This is obviously a fairly basic usecase for this, but still nice. + }; + + # not loaded automatically at startup. + # use with packadd and an autocommand in config to achieve lazy loading + # or a tool for organizing this like lze or lz.n! + # to get the name packadd expects, use the + # `:NixCats pawsible` command to see them all + optionalPlugins = { + debug = with pkgs.vimPlugins; { + # it is possible to add default values. + # there is nothing special about the word "default" + # but we have turned this subcategory into a default value + # via the extraCats section at the bottom of categoryDefinitions. + default = [ + nvim-dap + nvim-dap-ui + nvim-dap-virtual-text + ]; + go = [ nvim-dap-go ]; + }; + lint = with pkgs.vimPlugins; [ + nvim-lint + ]; + format = with pkgs.vimPlugins; [ + conform-nvim + ]; + markdown = with pkgs.vimPlugins; [ + markdown-preview-nvim + ]; + neonixdev = with pkgs.vimPlugins; [ + lazydev-nvim + ]; + general = { + blink = with pkgs.vimPlugins; [ + luasnip + cmp-cmdline + blink-cmp + blink-compat + colorful-menu-nvim + ]; + treesitter = with pkgs.vimPlugins; [ + nvim-treesitter-textobjects + nvim-treesitter.withAllGrammars + # This is for if you only want some of the grammars + # (nvim-treesitter.withPlugins ( + # plugins: with plugins; [ + # nix + # lua + # ] + # )) + ]; + telescope = with pkgs.vimPlugins; [ + telescope-fzf-native-nvim + telescope-ui-select-nvim + telescope-nvim + ]; + always = with pkgs.vimPlugins; [ + nvim-lspconfig + lualine-nvim + gitsigns-nvim + vim-sleuth + vim-fugitive + vim-rhubarb + nvim-surround + ]; + extra = with pkgs.vimPlugins; [ + fidget-nvim + # lualine-lsp-progress + which-key-nvim + comment-nvim + undotree + indent-blankline-nvim + vim-startuptime + # If it was included in your flake inputs as plugins-hlargs, + # this would be how to add that plugin in your config. + # pkgs.neovimPlugins.hlargs + ]; + }; + }; + + # shared libraries to be added to LD_LIBRARY_PATH + # variable available to nvim runtime + sharedLibraries = { + general = with pkgs; [ # <- this would be included if any of the subcategories of general are + # libgit2 + ]; + }; + + # environmentVariables: + # this section is for environmentVariables that should be available + # at RUN TIME for plugins. Will be available to path within neovim terminal + environmentVariables = { + test = { + default = { + CATTESTVARDEFAULT = "It worked!"; + }; + subtest1 = { + CATTESTVAR = "It worked!"; + }; + subtest2 = { + CATTESTVAR3 = "It didn't work!"; + }; + }; + }; + + # If you know what these are, you can provide custom ones by category here. + # If you dont, check this link out: + # https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/setup-hooks/make-wrapper.sh + extraWrapperArgs = { + test = [ + '' --set CATTESTVAR2 "It worked again!"'' + ]; + }; + + # lists of the functions you would have passed to + # python.withPackages or lua.withPackages + # do not forget to set `hosts.python3.enable` in package settings + + # get the path to this python environment + # in your lua config via + # vim.g.python3_host_prog + # or run from nvim terminal via :!-python3 + python3.libraries = { + test = (_:[]); + }; + # populates $LUA_PATH and $LUA_CPATH + extraLuaPackages = { + general = [ (_:[]) ]; + }; + + # see :help nixCats.flake.outputs.categoryDefinitions.default_values + # this will enable test.default and debug.default + # if any subcategory of test or debug is enabled + # WARNING: use of categories argument in this set will cause infinite recursion + # The categories argument of this function is the FINAL value. + # You may use it in any of the other sets. + extraCats = { + test = [ + [ "test" "default" ] + ]; + debug = [ + [ "debug" "default" ] + ]; + go = [ + [ "debug" "go" ] # yes it has to be a list of lists + ]; + }; + }; + + + + + # packageDefinitions: + + # Now build a package with specific categories from above + # All categories you wish to include must be marked true, + # but false may be omitted. + # This entire set is also passed to nixCats for querying within the lua. + # It is directly translated to a Lua table, and a get function is defined. + # The get function is to prevent errors when querying subcategories. + + # see :help nixCats.flake.outputs.packageDefinitions + packageDefinitions = { + # the name here is the name of the package + # and also the default command name for it. + nixCats = { pkgs, name, ... }@misc: { + # these also recieve our pkgs variable + # see :help nixCats.flake.outputs.packageDefinitions + settings = { + suffix-path = true; + suffix-LD = true; + # The name of the package, and the default launch name, + # and the name of the .desktop file, is `nixCats`, + # or, whatever you named the package definition in the packageDefinitions set. + # WARNING: MAKE SURE THESE DONT CONFLICT WITH OTHER INSTALLED PACKAGES ON YOUR PATH + # That would result in a failed build, as nixos and home manager modules validate for collisions on your path + aliases = [ "vim" "vimcat" ]; + + # explained below in the `regularCats` package's definition + # OR see :help nixCats.flake.outputs.settings for all of the settings available + wrapRc = true; + configDirName = "nixCats-nvim"; + # neovim-unwrapped = inputs.neovim-nightly-overlay.packages.${pkgs.system}.neovim; + hosts.python3.enable = true; + hosts.node.enable = true; + }; + # enable the categories you want from categoryDefinitions + categories = { + markdown = true; + general = true; + lint = true; + format = true; + neonixdev = true; + test = { + subtest1 = true; + }; + + # enabling this category will enable the go category, + # and ALSO debug.go and debug.default due to our extraCats in categoryDefinitions. + # go = true; # <- disabled but you could enable it with override or module on install + + # this does not have an associated category of plugins, + # but lua can still check for it + lspDebugMode = false; + # you could also pass something else: + # see :help nixCats + themer = true; + colorscheme = "onedark"; + }; + extra = { + # to keep the categories table from being filled with non category things that you want to pass + # there is also an extra table you can use to pass extra stuff. + # but you can pass all the same stuff in any of these sets and access it in lua + nixdExtras = { + nixpkgs = ''import ${pkgs.path} {}''; + # or inherit nixpkgs; + }; + }; + }; + regularCats = { pkgs, ... }@misc: { + settings = { + suffix-path = true; + suffix-LD = true; + # IMPURE PACKAGE: normal config reload + # include same categories as main config, + # will load from vim.fn.stdpath('config') + wrapRc = false; + # or tell it some other place to load + # unwrappedCfgPath = "/some/path/to/your/config"; + + # configDirName: will now look for nixCats-nvim within .config and .local and others + # this can be changed so that you can choose which ones share data folders for auths + # :h $NVIM_APPNAME + configDirName = "nixCats-nvim"; + + aliases = [ "testCat" ]; + + # If you wanted nightly, uncomment this, and the flake input. + # neovim-unwrapped = inputs.neovim-nightly-overlay.packages.${pkgs.system}.neovim; + # Probably add the cache stuff they recommend too. + }; + categories = { + markdown = true; + general = true; + neonixdev = true; + lint = true; + format = true; + test = true; + # go = true; # <- disabled but you could enable it with override or module on install + lspDebugMode = false; + themer = true; + colorscheme = "catppuccin"; + }; + extra = { + # nixCats.extra("path.to.val") will perform vim.tbl_get(nixCats.extra, "path" "to" "val") + # this is different from the main nixCats("path.to.cat") in that + # the main nixCats("path.to.cat") will report true if `path.to = true` + # even though path.to.cat would be an indexing error in that case. + # this is to mimic the concept of "subcategories" but may get in the way of just fetching values. + nixdExtras = { + nixpkgs = ''import ${pkgs.path} {}''; + # or inherit nixpkgs; + }; + # yes even tortured inputs work. + theBestCat = "says meow!!"; + theWorstCat = { + thing'1 = [ "MEOW" '']]' ]=][=[HISSS]]"[['' ]; + thing2 = [ + { + thing3 = [ "give" "treat" ]; + } + "I LOVE KEYBOARDS" + (utils.mkLuaInline ''[[I am a]] .. [[ lua ]] .. type("value")'') + ]; + thing4 = "couch is for scratching"; + }; + }; + }; + }; + + defaultPackageName = "nixCats"; + # I did not here, but you might want to create a package named nvim. + + # defaultPackageName is also passed to utils.mkNixosModules and utils.mkHomeModules + # and it controls the name of the top level option set. + # If you made a package named `nixCats` your default package as we did here, + # the modules generated would be set at: + # config.nixCats = { + # enable = true; + # packageNames = [ "nixCats" ]; # <- the packages you want installed + # + # } + # In addition, every package exports its own module via passthru, and is overrideable. + # so you can yourpackage.homeModule and then the namespace would be that packages name. + in + # you shouldnt need to change much past here, but you can if you wish. + # but you should at least eventually try to figure out whats going on here! + # see :help nixCats.flake.outputs.exports + forEachSystem (system: let + # and this will be our builder! it takes a name from our packageDefinitions as an argument, and builds an nvim. + nixCatsBuilder = utils.baseBuilder luaPath { + # we pass in the things to make a pkgs variable to build nvim with later + inherit nixpkgs system dependencyOverlays extra_pkg_config; + # and also our categoryDefinitions and packageDefinitions + } categoryDefinitions packageDefinitions; + # call it with our defaultPackageName + defaultPackage = nixCatsBuilder defaultPackageName; + + # this pkgs variable is just for using utils such as pkgs.mkShell + # within this outputs set. + pkgs = import nixpkgs { inherit system; }; + # The one used to build neovim is resolved inside the builder + # and is passed to our categoryDefinitions and packageDefinitions + in { + # these outputs will be wrapped with ${system} by utils.eachSystem + + # this will generate a set of all the packages + # in the packageDefinitions defined above + # from the package we give it. + # and additionally output the original as default. + packages = utils.mkAllWithDefault defaultPackage; + + # choose your package for devShell + # and add whatever else you want in it. + devShells = { + default = pkgs.mkShell { + name = defaultPackageName; + packages = [ defaultPackage ]; + inputsFrom = [ ]; + shellHook = '' + ''; + }; + }; + + }) // (let + # we also export a nixos module to allow reconfiguration from configuration.nix + nixosModule = utils.mkNixosModules { + moduleNamespace = [ defaultPackageName ]; + inherit defaultPackageName dependencyOverlays luaPath + categoryDefinitions packageDefinitions extra_pkg_config nixpkgs; + }; + # and the same for home manager + homeModule = utils.mkHomeModules { + moduleNamespace = [ defaultPackageName ]; + inherit defaultPackageName dependencyOverlays luaPath + categoryDefinitions packageDefinitions extra_pkg_config nixpkgs; + }; + in { + + # these outputs will be NOT wrapped with ${system} + + # this will make an overlay out of each of the packageDefinitions defined above + # and set the default overlay to the one named here. + 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/init.lua b/init.lua new file mode 100644 index 0000000..57b52e5 --- /dev/null +++ b/init.lua @@ -0,0 +1,60 @@ +--[[ +NOTE: +if you plan to always load your nixCats via nix, +you can safely ignore this setup call, +and the require('myLuaConf.non_nix_download') call below it. +as well as the entire lua/myLuaConf/non_nix_download file. +Unless you want the lzUtils file, or the lazy wrapper, you also wont need lua/nixCatsUtils + +IF YOU DO NOT DO THIS SETUP CALL: +the result will be that, when you load this folder without using nix, +the global nixCats function which you use everywhere +to check for categories will throw an error. +This setup function will give it a default value. +Of course, if you only ever download nvim with nix, this isnt needed.]] +--[[ ----------------------------------- ]] +--[[ This setup function will provide ]] +--[[ a default value for the nixCats('') ]] +--[[ function so that it will not throw ]] +--[[ an error if not loaded via nixCats ]] +--[[ ----------------------------------- ]] +require('nixCatsUtils').setup { + non_nix_value = true, +} +--[[ +Nix puts the plugins +into the directories paq-nvim expects them to be in, +because both follow the normal neovim scheme. +So you just put the URLs and build steps in there, and use its opt option to do the same +thing as putting a plugin in nixCat's optionalPlugins field. +then load the plugins via paq-nvim +YOU are in charge of putting the plugin +urls and build steps in there, which will only be used when not on nix, +and you should keep any setup functions +OUT of that file, as they are ONLY loaded when this +configuration is NOT loaded via nix. +--]] +require("myLuaConf.non_nix_download") +-- OK, again, that isnt needed if you load this setup via nix, but it is an option. + +--[[ +outside of when you want to use the nixCats global command +to decide if something should be loaded, or to pass info from nix to lua, +thats pretty much everything specific to nixCats that +needs to be in your config. +If you always want to load it via nix, +you pretty much dont need this file at all, and you also won't need +anything within lua/nixCatsUtils, nor will that be in the default template. +that directory is addable via the luaUtils template. +it is not required, but has some useful utility functions. +--]] + +--[[ +ok thats enough for 1 file. Off to lua/myLuaConf/init.lua +all the config starts there in this example config. +This config is loadable with and without nix due to the above, +and the lua/myLuaConf/non_nix_download.lua file. +the rest is just example of how to configure nvim making use of various +features of nixCats and using the plugin lze for lazy loading. +--]] +require('myLuaConf') diff --git a/lua/myLuaConf/LSPs/init.lua b/lua/myLuaConf/LSPs/init.lua new file mode 100644 index 0000000..8754c97 --- /dev/null +++ b/lua/myLuaConf/LSPs/init.lua @@ -0,0 +1,166 @@ +local catUtils = require('nixCatsUtils') +if (catUtils.isNixCats and nixCats('lspDebugMode')) then + vim.lsp.set_log_level("debug") +end + +-- NOTE: This file uses lzextras.lsp handler https://github.com/BirdeeHub/lzextras?tab=readme-ov-file#lsp-handler +-- This is a slightly more performant fallback function +-- for when you don't provide a filetype to trigger on yourself. +-- nixCats gives us the paths, which is faster than searching the rtp! +local old_ft_fallback = require('lze').h.lsp.get_ft_fallback() +require('lze').h.lsp.set_ft_fallback(function(name) + local lspcfg = nixCats.pawsible({ "allPlugins", "opt", "nvim-lspconfig" }) or nixCats.pawsible({ "allPlugins", "start", "nvim-lspconfig" }) + if lspcfg then + local ok, cfg = pcall(dofile, lspcfg .. "/lsp/" .. name .. ".lua") + if not ok then + ok, cfg = pcall(dofile, lspcfg .. "/lua/lspconfig/configs/" .. name .. ".lua") + end + return (ok and cfg or {}).filetypes or {} + else + return old_ft_fallback(name) + end +end) +require('lze').load { + { + "nvim-lspconfig", + for_cat = "general.core", + on_require = { "lspconfig" }, + -- 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, + before = function(_) + vim.lsp.config('*', { + on_attach = require('myLuaConf.LSPs.on_attach'), + }) + end, + }, + { + "mason.nvim", + -- only run it when not on nix + enabled = not catUtils.isNixCats, + on_plugin = { "nvim-lspconfig" }, + load = function(name) + vim.cmd.packadd(name) + vim.cmd.packadd("mason-lspconfig.nvim") + require('mason').setup() + -- auto install will make it install servers when lspconfig is called on them. + require('mason-lspconfig').setup { automatic_installation = true, } + end, + }, + { + -- lazydev makes your lsp way better in your config without needing extra lsp configuration. + "lazydev.nvim", + for_cat = "neonixdev", + cmd = { "LazyDev" }, + ft = "lua", + after = function(_) + require('lazydev').setup({ + library = { + { words = { "nixCats" }, path = (nixCats.nixCatsPath or "") .. '/lua' }, + }, + }) + end, + }, + { + -- name of the lsp + "lua_ls", + enabled = nixCats('lua') or nixCats('neonixdev') or false, + -- 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 = { "nixCats", "vim", }, + disable = { 'missing-fields' }, + }, + telemetry = { enabled = false }, + }, + }, + }, + -- also these are regular specs and you can use before and after and all the other normal fields + }, + { + "gopls", + for_cat = "go", + -- if you don't provide the filetypes it asks lspconfig for them + lsp = { + filetypes = { "go", "gomod", "gowork", "gotmpl" }, + }, + }, + { + "rnix", + -- mason doesn't have nixd + enabled = not catUtils.isNixCats, + lsp = { + filetypes = { "nix" }, + }, + }, + { + "nil_ls", + -- mason doesn't have nixd + enabled = not catUtils.isNixCats, + lsp = { + filetypes = { "nix" }, + }, + }, + { + "nixd", + enabled = catUtils.isNixCats and (nixCats('nix') or nixCats('neonixdev')) or false, + lsp = { + filetypes = { "nix" }, + settings = { + nixd = { + -- nixd requires some configuration. + -- luckily, the nixCats plugin is here to pass whatever we need! + -- we passed this in via the `extra` table in our packageDefinitions + -- for additional configuration options, refer to: + -- https://github.com/nix-community/nixd/blob/main/nixd/docs/configuration.md + nixpkgs = { + -- in the extras set of your package definition: + -- nixdExtras.nixpkgs = ''import ${pkgs.path} {}'' + expr = nixCats.extra("nixdExtras.nixpkgs") or [[import {}]], + }, + options = { + -- If you integrated with your system flake, + -- you should use inputs.self as the path to your system flake + -- that way it will ALWAYS work, regardless + -- of where your config actually was. + nixos = { + -- nixdExtras.nixos_options = ''(builtins.getFlake "path:${builtins.toString inputs.self.outPath}").nixosConfigurations.configname.options'' + expr = nixCats.extra("nixdExtras.nixos_options") + }, + -- If you have your config as a separate flake, inputs.self would be referring to the wrong flake. + -- You can override the correct one into your package definition on import in your main configuration, + -- or just put an absolute path to where it usually is and accept the impurity. + ["home-manager"] = { + -- nixdExtras.home_manager_options = ''(builtins.getFlake "path:${builtins.toString inputs.self.outPath}").homeConfigurations.configname.options'' + expr = nixCats.extra("nixdExtras.home_manager_options") + } + }, + formatting = { + command = { "nixfmt" } + }, + diagnostic = { + suppress = { + "sema-escaping-with" + } + } + } + }, + }, + }, +} diff --git a/lua/myLuaConf/LSPs/on_attach.lua b/lua/myLuaConf/LSPs/on_attach.lua new file mode 100644 index 0000000..5e2661c --- /dev/null +++ b/lua/myLuaConf/LSPs/on_attach.lua @@ -0,0 +1,47 @@ +return 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') + + -- NOTE: why are these functions that call the telescope builtin? + -- because otherwise they would load telescope eagerly when this is defined. + -- due to us using the on_require handler to make sure it is available. + if nixCats('general.telescope') then + nmap('gr', function() require('telescope.builtin').lsp_references() end, '[G]oto [R]eferences') + nmap('gI', function() require('telescope.builtin').lsp_implementations() end, '[G]oto [I]mplementation') + nmap('ds', function() require('telescope.builtin').lsp_document_symbols() end, '[D]ocument [S]ymbols') + nmap('ws', function() require('telescope.builtin').lsp_dynamic_workspace_symbols() end, '[W]orkspace [S]ymbols') + end -- TODO: someone who knows the builtin versions of these to do instead help me out please. + + nmap('D', vim.lsp.buf.type_definition, 'Type [D]efinition') + + -- 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 diff --git a/lua/myLuaConf/debug.lua b/lua/myLuaConf/debug.lua new file mode 100644 index 0000000..4ea7293 --- /dev/null +++ b/lua/myLuaConf/debug.lua @@ -0,0 +1,119 @@ +require('lze').load { + { + "nvim-dap", + -- NOTE: I dont want to figure out mason tools installer for this, so I only enabled debug if nix loaded config + for_cat = { cat = 'debug', default = false }, + -- cmd = { "" }, + -- event = "", + -- ft = "", + keys = { + { "", desc = "Debug: Start/Continue" }, + { "", desc = "Debug: Step Into" }, + { "", desc = "Debug: Step Over" }, + { "", desc = "Debug: Step Out" }, + { "b", desc = "Debug: Toggle Breakpoint" }, + { "B", desc = "Debug: Set Breakpoint" }, + { "", desc = "Debug: See last session result." }, + }, + -- colorscheme = "", + load = (require('nixCatsUtils').isNixCats and function(name) + vim.cmd.packadd(name) + vim.cmd.packadd("nvim-dap-ui") + vim.cmd.packadd("nvim-dap-virtual-text") + end) or function(name) + vim.cmd.packadd(name) + vim.cmd.packadd("nvim-dap-ui") + vim.cmd.packadd("nvim-dap-virtual-text") + vim.cmd.packadd("mason-nvim-dap.nvim") + end, + after = function (plugin) + local dap = require 'dap' + local dapui = require 'dapui' + + -- Basic debugging keymaps, feel free to change to your liking! + vim.keymap.set('n', '', dap.continue, { desc = 'Debug: Start/Continue' }) + vim.keymap.set('n', '', dap.step_into, { desc = 'Debug: Step Into' }) + vim.keymap.set('n', '', dap.step_over, { desc = 'Debug: Step Over' }) + vim.keymap.set('n', '', dap.step_out, { desc = 'Debug: Step Out' }) + vim.keymap.set('n', 'b', dap.toggle_breakpoint, { desc = 'Debug: Toggle Breakpoint' }) + vim.keymap.set('n', 'B', function() + dap.set_breakpoint(vim.fn.input 'Breakpoint condition: ') + end, { desc = 'Debug: Set Breakpoint' }) + + -- Toggle to see last session result. Without this, you can't see session output in case of unhandled exception. + vim.keymap.set('n', '', dapui.toggle, { desc = 'Debug: See last session result.' }) + + dap.listeners.after.event_initialized['dapui_config'] = dapui.open + dap.listeners.before.event_terminated['dapui_config'] = dapui.close + dap.listeners.before.event_exited['dapui_config'] = dapui.close + + -- Dap UI setup + -- For more information, see |:help nvim-dap-ui| + dapui.setup { + -- Set icons to characters that are more likely to work in every terminal. + -- Feel free to remove or use ones that you like more! :) + -- Don't feel like these are good choices. + icons = { expanded = '▾', collapsed = '▸', current_frame = '*' }, + controls = { + icons = { + pause = '⏸', + play = '▶', + step_into = '⏎', + step_over = '⏭', + step_out = '⏮', + step_back = 'b', + run_last = '▶▶', + terminate = '⏹', + disconnect = '⏏', + }, + }, + } + + require("nvim-dap-virtual-text").setup { + enabled = true, -- enable this plugin (the default) + enabled_commands = true, -- create commands DapVirtualTextEnable, DapVirtualTextDisable, DapVirtualTextToggle, (DapVirtualTextForceRefresh for refreshing when debug adapter did not notify its termination) + highlight_changed_variables = true, -- highlight changed values with NvimDapVirtualTextChanged, else always NvimDapVirtualText + highlight_new_as_changed = false, -- highlight new variables in the same way as changed variables (if highlight_changed_variables) + show_stop_reason = true, -- show stop reason when stopped for exceptions + commented = false, -- prefix virtual text with comment string + only_first_definition = true, -- only show virtual text at first definition (if there are multiple) + all_references = false, -- show virtual text on all all references of the variable (not only definitions) + clear_on_continue = false, -- clear virtual text on "continue" (might cause flickering when stepping) + --- A callback that determines how a variable is displayed or whether it should be omitted + --- variable Variable https://microsoft.github.io/debug-adapter-protocol/specification#Types_Variable + --- buf number + --- stackframe dap.StackFrame https://microsoft.github.io/debug-adapter-protocol/specification#Types_StackFrame + --- node userdata tree-sitter node identified as variable definition of reference (see `:h tsnode`) + --- options nvim_dap_virtual_text_options Current options for nvim-dap-virtual-text + --- string|nil A text how the virtual text should be displayed or nil, if this variable shouldn't be displayed + display_callback = function(variable, buf, stackframe, node, options) + if options.virt_text_pos == 'inline' then + return ' = ' .. variable.value + else + return variable.name .. ' = ' .. variable.value + end + end, + -- position of virtual text, see `:h nvim_buf_set_extmark()`, default tries to inline the virtual text. Use 'eol' to set to end of line + virt_text_pos = vim.fn.has 'nvim-0.10' == 1 and 'inline' or 'eol', + + -- experimental features: + all_frames = false, -- show virtual text for all stack frames not only current. Only works for debugpy on my machine. + virt_lines = false, -- show virtual lines instead of virtual text (will flicker!) + virt_text_win_col = nil -- position the virtual text at a fixed window column (starting from the first text column) , + -- e.g. 80 to position at column 80, see `:h nvim_buf_set_extmark()` + } + + -- NOTE: Install lang specific config + -- either in here, or in a separate plugin spec as demonstrated for go below. + + end, + }, + { + "nvim-dap-go", + for_cat = { cat = 'debug.go', default = false }, + on_plugin = { "nvim-dap", }, + after = function(plugin) + require("dap-go").setup() + end, + }, +} diff --git a/lua/myLuaConf/format.lua b/lua/myLuaConf/format.lua new file mode 100644 index 0000000..7f7cce2 --- /dev/null +++ b/lua/myLuaConf/format.lua @@ -0,0 +1,38 @@ +require('lze').load { + { + "conform.nvim", + for_cat = 'format', + -- 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 in lspsAndRuntimeDeps + -- and configure them here + -- lua = { "stylua" }, + -- 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, + }, +} diff --git a/lua/myLuaConf/init.lua b/lua/myLuaConf/init.lua new file mode 100644 index 0000000..efbe66c --- /dev/null +++ b/lua/myLuaConf/init.lua @@ -0,0 +1,36 @@ + +-- NOTE: various, non-plugin config +require('myLuaConf.opts_and_keys') + +-- NOTE: register an extra lze handler with the spec_field 'for_cat' +-- that makes enabling an lze spec for a category slightly nicer +require("lze").register_handlers(require('nixCatsUtils.lzUtils').for_cat) + +-- NOTE: Register another one from lzextras. This one makes it so that +-- you can set up lsps within lze specs, +-- and trigger lspconfig setup hooks only on the correct filetypes +require('lze').register_handlers(require('lzextras').lsp) +-- demonstrated in ./LSPs/init.lua + +-- NOTE: general plugins +require("myLuaConf.plugins") + +-- NOTE: obviously, more plugins, but more organized by what they do below + +require("myLuaConf.LSPs") + +-- NOTE: we even ask nixCats if we included our debug stuff in this setup! (we didnt) +-- But we have a good base setup here as an example anyway! +if nixCats('debug') then + require('myLuaConf.debug') +end +-- NOTE: we included these though! Or, at least, the category is enabled. +-- these contain nvim-lint and conform setups. +if nixCats('lint') then + require('myLuaConf.lint') +end +if nixCats('format') then + require('myLuaConf.format') +end +-- NOTE: I didnt actually include any linters or formatters in this configuration, +-- but it is enough to serve as an example. diff --git a/lua/myLuaConf/lint.lua b/lua/myLuaConf/lint.lua new file mode 100644 index 0000000..d58638a --- /dev/null +++ b/lua/myLuaConf/lint.lua @@ -0,0 +1,26 @@ +require('lze').load { + { + "nvim-lint", + for_cat = 'lint', + -- cmd = { "" }, + event = "FileType", + -- ft = "", + -- keys = "", + -- colorscheme = "", + after = function (plugin) + require('lint').linters_by_ft = { + -- NOTE: download some linters in lspsAndRuntimeDeps + -- and configure them here + -- markdown = {'vale',}, + -- javascript = { 'eslint' }, + -- typescript = { 'eslint' }, + } + + vim.api.nvim_create_autocmd({ "BufWritePost" }, { + callback = function() + require("lint").try_lint() + end, + }) + end, + }, +} diff --git a/lua/myLuaConf/non_nix_download.lua b/lua/myLuaConf/non_nix_download.lua new file mode 100644 index 0000000..49c4533 --- /dev/null +++ b/lua/myLuaConf/non_nix_download.lua @@ -0,0 +1,91 @@ +-- load the plugins via paq-nvim when not on nix +-- YOU are in charge of putting the plugin +-- urls and build steps in here, which will only be used when not on nix. +-- and you should keep any setup functions OUT of this file + +-- again, you dont need this file if you only use nix to load the config, +-- this is a fallback only, and is optional. +require('nixCatsUtils.catPacker').setup({ +--[[ ------------------------------------------ ]] +--[[ The way to think of this is, its very ]] +--[[ similar to the main nix file for nixCats ]] +--[[ ]] +--[[ It can be used to download your plugins, ]] +--[[ and it has an opt for optional plugins. ]] +--[[ ]] +--[[ We dont want to handle anything about ]] +--[[ loading those plugins here, so that we can ]] +--[[ use the same loading code that we use for ]] +--[[ our normal nix-loaded config. ]] +--[[ we will do all our loading and configuring ]] +--[[ elsewhere in our configuration, so that ]] +--[[ we dont have to write it twice. ]] +--[[ ------------------------------------------ ]] + { "BirdeeHub/lze", }, + { "BirdeeHub/lzextras", }, + { "stevearc/oil.nvim", }, + { 'joshdick/onedark.vim', }, + { 'nvim-tree/nvim-web-devicons', }, + { 'nvim-lua/plenary.nvim', }, + { 'tpope/vim-repeat', }, + { 'rcarriga/nvim-notify', }, + + { 'nvim-treesitter/nvim-treesitter-textobjects', opt = true, }, + { 'nvim-treesitter/nvim-treesitter', build = ':TSUpdate', opt = true, }, + + { 'nvim-telescope/telescope-fzf-native.nvim', build = ':!which make && make', opt = true, }, + { 'nvim-telescope/telescope-ui-select.nvim', opt = true, }, + {'nvim-telescope/telescope.nvim', opt = true, }, + + -- lsp + { 'williamboman/mason.nvim', opt = true, }, + { 'williamboman/mason-lspconfig.nvim', opt = true, }, + { 'j-hui/fidget.nvim', opt = true, }, + { 'neovim/nvim-lspconfig', opt = true, }, + + -- NOTE: we take care of lazy loading elsewhere in an autocommand + -- so that we can use the same code on and off nix. + -- so here we just tell it not to auto load it + { 'folke/lazydev.nvim', opt = true, }, + + -- completion + { 'L3MON4D3/LuaSnip', opt = true, as = "luasnip", }, + { 'hrsh7th/cmp-cmdline', opt = true, }, + { 'Saghen/blink.cmp', opt = true, }, + { 'Saghen/blink.compat', opt = true, }, + { 'xzbdmw/colorful-menu.nvim', opt = true, }, + + -- lint and format + { 'mfussenegger/nvim-lint', opt = true, }, + { 'stevearc/conform.nvim', opt = true, }, + + -- dap + { 'nvim-neotest/nvim-nio', opt = true, }, + { 'rcarriga/nvim-dap-ui', opt = true, }, + { 'theHamsta/nvim-dap-virtual-text', opt = true, }, + { 'jay-babu/mason-nvim-dap.nvim', opt = true, }, + { 'mfussenegger/nvim-dap', opt = true, }, + + -- { 'm-demare/hlargs.nvim', }, + { 'mbbill/undotree', opt = true, }, + { 'tpope/vim-fugitive', opt = true, }, + { 'tpope/vim-rhubarb', opt = true, }, + { 'tpope/vim-sleuth', opt = true, }, + { 'folke/which-key.nvim', opt = true, }, + { 'lewis6991/gitsigns.nvim', opt = true, }, + { 'nvim-lualine/lualine.nvim', opt = true, }, + { 'lukas-reineke/indent-blankline.nvim', opt = true, }, + { 'numToStr/Comment.nvim', opt = true, as = "comment.nvim", }, + { 'kylechui/nvim-surround', opt = true, }, + { + "iamcco/markdown-preview.nvim", + build = ":call mkdp#util#install()", + opt = true, + }, + + -- all the rest of the setup will be done using the normal setup functions later, + -- thus working regardless of what method loads the plugins. + -- only stuff pertaining to downloading should be added to paq. + +}) +-- OK, again, that isnt needed if you load this setup via nix, but it is an option. diff --git a/lua/myLuaConf/opts_and_keys.lua b/lua/myLuaConf/opts_and_keys.lua new file mode 100644 index 0000000..b1b254c --- /dev/null +++ b/lua/myLuaConf/opts_and_keys.lua @@ -0,0 +1,136 @@ +-- NOTE: These 2 need to be set up before any plugins are loaded. +vim.g.mapleader = ' ' +vim.g.maplocalleader = ' ' + +-- [[ Setting options ]] +-- See `:help vim.o` +-- NOTE: You can change these options as you wish! + +-- Sets how neovim will display certain whitespace characters in the editor. +-- See `:help 'list'` +-- and `:help 'listchars'` +vim.opt.list = true +vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' } + +-- Set highlight on search +vim.opt.hlsearch = true +vim.keymap.set('n', '', 'nohlsearch') + +-- Preview substitutions live, as you type! +vim.opt.inccommand = 'split' + +-- Minimal number of screen lines to keep above and below the cursor. +vim.opt.scrolloff = 10 + +-- Make line numbers default +vim.wo.number = true + +-- Enable mouse mode +vim.o.mouse = 'a' + +-- Indent +-- vim.o.smarttab = true +vim.opt.cpoptions:append('I') +vim.o.expandtab = true +-- vim.o.smartindent = true +-- vim.o.autoindent = true +-- vim.o.tabstop = 4 +-- vim.o.softtabstop = 4 +-- vim.o.shiftwidth = 4 + +-- stops line wrapping from being confusing +vim.o.breakindent = true + +-- Save undo history +vim.o.undofile = true + +-- Case-insensitive searching UNLESS \C or capital in search +vim.o.ignorecase = true +vim.o.smartcase = true + +-- Keep signcolumn on by default +vim.wo.signcolumn = 'yes' +vim.wo.relativenumber = true + +-- Decrease update time +vim.o.updatetime = 250 +vim.o.timeoutlen = 300 + +-- Set completeopt to have a better completion experience +vim.o.completeopt = 'menu,preview,noselect' + +-- NOTE: You should make sure your terminal supports this +vim.o.termguicolors = true + +-- [[ Disable auto comment on enter ]] +-- See :help formatoptions +vim.api.nvim_create_autocmd("FileType", { + desc = "remove formatoptions", + callback = function() + vim.opt.formatoptions:remove({ "c", "r", "o" }) + end, +}) + +-- [[ 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', { + callback = function() + vim.highlight.on_yank() + end, + group = highlight_group, + pattern = '*', +}) + +vim.g.netrw_liststyle=0 +vim.g.netrw_banner=0 +-- [[ Basic Keymaps ]] + +-- 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("n", "", "zz", { desc = 'Scroll Down' }) +vim.keymap.set("n", "", "zz", { desc = 'Scroll Up' }) +vim.keymap.set("n", "n", "nzzzv", { desc = 'Next Search Result' }) +vim.keymap.set("n", "N", "Nzzzv", { desc = 'Previous Search Result' }) + +vim.keymap.set("n", "[", "bprev", { desc = 'Previous buffer' }) +vim.keymap.set("n", "]", "bnext", { desc = 'Next buffer' }) +vim.keymap.set("n", "l", "b#", { desc = 'Last buffer' }) +vim.keymap.set("n", "d", "bdelete", { desc = 'delete buffer' }) + +-- see help sticky keys on windows +vim.cmd([[command! W w]]) +vim.cmd([[command! Wq wq]]) +vim.cmd([[command! WQ wq]]) +vim.cmd([[command! Q q]]) + +-- Remap for dealing with word wrap +vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true }) +vim.keymap.set('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true }) + +-- Diagnostic keymaps +vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Go to previous diagnostic message' }) +vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Go to next diagnostic message' }) +vim.keymap.set('n', 'e', vim.diagnostic.open_float, { desc = 'Open floating diagnostic message' }) +vim.keymap.set('n', 'q', vim.diagnostic.setloclist, { desc = 'Open diagnostics list' }) + + +-- kickstart.nvim starts you with this. +-- But it constantly clobbers your system clipboard whenever you delete anything. + +-- Sync clipboard between OS and Neovim. +-- Remove this option if you want your OS clipboard to remain independent. +-- See `:help 'clipboard'` +-- vim.o.clipboard = 'unnamedplus' + +-- You should instead use these keybindings so that they are still easy to use, but dont conflict +vim.keymap.set({"v", "x", "n"}, 'y', '"+y', { noremap = true, silent = true, desc = 'Yank to clipboard' }) +vim.keymap.set({"n", "v", "x"}, 'Y', '"+yy', { noremap = true, silent = true, desc = 'Yank line to clipboard' }) +vim.keymap.set({"n", "v", "x"}, '', 'gg0vG$', { noremap = true, silent = true, desc = 'Select all' }) +vim.keymap.set({'n', 'v', 'x'}, 'p', '"+p', { noremap = true, silent = true, desc = 'Paste from clipboard' }) +vim.keymap.set('i', '', '+', { noremap = true, silent = true, desc = 'Paste from clipboard from within insert mode' }) +vim.keymap.set("x", "P", '"_dP', { noremap = true, silent = true, desc = 'Paste over selection without erasing unnamed register' }) + + diff --git a/lua/myLuaConf/plugins/completion.lua b/lua/myLuaConf/plugins/completion.lua new file mode 100644 index 0000000..f144c14 --- /dev/null +++ b/lua/myLuaConf/plugins/completion.lua @@ -0,0 +1,140 @@ +local load_w_after = function(name) + vim.cmd.packadd(name) + vim.cmd.packadd(name .. '/after') +end + +return { + { + "cmp-cmdline", + for_cat = "general.blink", + on_plugin = { "blink.cmp" }, + load = load_w_after, + }, + { + "blink.compat", + for_cat = "general.blink", + dep_of = { "cmp-cmdline" }, + }, + { + "luasnip", + for_cat = "general.blink", + dep_of = { "blink.cmp" }, + after = function (_) + 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 = "general.blink", + on_plugin = { "blink.cmp" }, + }, + { + "blink.cmp", + for_cat = "general.blink", + 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, + }, + }, + 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' }, + providers = { + path = { + score_offset = 50, + }, + lsp = { + score_offset = 40, + }, + snippets = { + score_offset = 40, + }, + cmp_cmdline = { + name = 'cmp_cmdline', + module = 'blink.compat.source', + score_offset = -100, + opts = { + cmp_name = 'cmdline', + }, + }, + }, + }, + }) + end, + }, +} diff --git a/lua/myLuaConf/plugins/init.lua b/lua/myLuaConf/plugins/init.lua new file mode 100644 index 0000000..5d55953 --- /dev/null +++ b/lua/myLuaConf/plugins/init.lua @@ -0,0 +1,315 @@ +local colorschemeName = nixCats('colorscheme') +if not require('nixCatsUtils').isNixCats then + colorschemeName = 'onedark' +end +-- Could I lazy load on colorscheme with lze? +-- sure. But I was going to call vim.cmd.colorscheme() during startup anyway +-- this is just an example, feel free to do a better job! +vim.cmd.colorscheme(colorschemeName) + +local ok, notify = pcall(require, "notify") +if ok then + notify.setup({ + on_open = function(win) + vim.api.nvim_win_set_config(win, { focusable = false }) + end, + }) + vim.notify = notify + vim.keymap.set("n", "", function() + notify.dismiss({ silent = true, }) + end, { desc = "dismiss notify popup and clear hlsearch" }) +end + +-- NOTE: you can check if you included the category with the thing wherever you want. +if nixCats('general.extra') then + -- I didnt want to bother with lazy loading this. + -- I could put it in opt and put it in a spec anyway + -- and then not set any handlers and it would load at startup, + -- but why... I guess I could make it load + -- after the other lze definitions in the next call using priority value? + -- didnt seem necessary. + vim.g.loaded_netrwPlugin = 1 + require("oil").setup({ + default_file_explorer = true, + 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", + }, + }) + vim.keymap.set("n", "-", "Oil", { noremap = true, desc = 'Open Parent Directory' }) + vim.keymap.set("n", "-", "Oil .", { noremap = true, desc = 'Open nvim root directory' }) +end + +require('lze').load { + { import = "myLuaConf.plugins.telescope", }, + { import = "myLuaConf.plugins.treesitter", }, + { import = "myLuaConf.plugins.completion", }, + { + "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 = 'general.markdown', + cmd = { "MarkdownPreview", "MarkdownPreviewStop", "MarkdownPreviewToggle", }, + ft = "markdown", + keys = { + {"mp", "MarkdownPreview ", mode = {"n"}, noremap = true, desc = "markdown preview"}, + {"ms", "MarkdownPreviewStop ", mode = {"n"}, noremap = true, desc = "markdown preview stop"}, + {"mt", "MarkdownPreviewToggle ", mode = {"n"}, noremap = true, desc = "markdown preview toggle"}, + }, + before = function(plugin) + vim.g.mkdp_auto_close = 0 + end, + }, + { + "undotree", + for_cat = 'general.extra', + cmd = { "UndotreeToggle", "UndotreeHide", "UndotreeShow", "UndotreeFocus", "UndotreePersistUndo", }, + keys = { { "U", "UndotreeToggle", mode = { "n" }, desc = "Undo Tree" }, }, + before = function(_) + vim.g.undotree_WindowLayout = 1 + vim.g.undotree_SplitWidth = 40 + end, + }, + { + "comment.nvim", + for_cat = 'general.extra', + event = "DeferredUIEnter", + after = function(plugin) + require('Comment').setup() + end, + }, + { + "indent-blankline.nvim", + for_cat = 'general.extra', + event = "DeferredUIEnter", + after = function(plugin) + require("ibl").setup() + end, + }, + { + "nvim-surround", + for_cat = 'general.always', + event = "DeferredUIEnter", + -- keys = "", + after = function(plugin) + require('nvim-surround').setup() + end, + }, + { + "vim-startuptime", + for_cat = 'general.extra', + cmd = { "StartupTime" }, + before = function(_) + vim.g.startuptime_event_width = 0 + vim.g.startuptime_tries = 10 + vim.g.startuptime_exe_path = nixCats.packageBinPath + end, + }, + { + "fidget.nvim", + for_cat = 'general.extra', + event = "DeferredUIEnter", + -- keys = "", + after = function(plugin) + require('fidget').setup({}) + end, + }, + -- { + -- "hlargs", + -- for_cat = 'general.extra', + -- event = "DeferredUIEnter", + -- -- keys = "", + -- dep_of = { "nvim-lspconfig" }, + -- after = function(plugin) + -- require('hlargs').setup { + -- color = '#32a88f', + -- } + -- vim.cmd([[hi clear @lsp.type.parameter]]) + -- vim.cmd([[hi link @lsp.type.parameter Hlargs]]) + -- end, + -- }, + { + "lualine.nvim", + for_cat = 'general.always', + -- cmd = { "" }, + event = "DeferredUIEnter", + -- ft = "", + -- keys = "", + -- colorscheme = "", + after = function (plugin) + + require('lualine').setup({ + options = { + icons_enabled = false, + theme = colorschemeName, + 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", + for_cat = 'general.always', + 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", + for_cat = 'general.extra', + -- 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/myLuaConf/plugins/telescope.lua b/lua/myLuaConf/plugins/telescope.lua new file mode 100644 index 0000000..ccd0482 --- /dev/null +++ b/lua/myLuaConf/plugins/telescope.lua @@ -0,0 +1,126 @@ +-- Telescope is a fuzzy finder that comes with a lot of different things that +-- it can fuzzy find! It's more than just a "file finder", it can search +-- many different aspects of Neovim, your workspace, LSP, and more! +-- +-- The easiest way to use telescope, is to start by doing something like: +-- :Telescope help_tags +-- +-- After running this command, a window will open up and you're able to +-- type in the prompt window. You'll see a list of help_tags options and +-- a corresponding preview of the help. +-- +-- Two important keymaps to use while in telescope are: +-- - Insert mode: +-- - Normal mode: ? +-- +-- This opens a window that shows you all of the keymaps for the current +-- telescope picker. This is really useful to discover what Telescope can +-- do as well as how to actually do it! + +-- [[ Configure Telescope ]] +-- See `:help telescope` and `:help telescope.setup()` + +-- Telescope live_grep in git root +-- Function to find the git root directory based on the current buffer's path +local function find_git_root() + -- Use the current buffer's path as the starting point for the git search + local current_file = vim.api.nvim_buf_get_name(0) + local current_dir + local cwd = vim.fn.getcwd() + -- If the buffer is not associated with a file, return nil + if current_file == "" then + current_dir = cwd + else + -- Extract the directory from the current file's path + current_dir = vim.fn.fnamemodify(current_file, ":h") + end + + -- Find the Git root directory from the current file's path + local git_root = vim.fn.systemlist("git -C " .. vim.fn.escape(current_dir, " ") .. " rev-parse --show-toplevel")[1] + if vim.v.shell_error ~= 0 then + print("Not a git repository. Searching on current working directory") + return cwd + end + return git_root +end + +-- Custom live_grep function to search in git root +local function live_grep_git_root() + local git_root = find_git_root() + if git_root then + require('telescope.builtin').live_grep({ + search_dirs = { git_root }, + }) + end +end + +return { + { + "telescope.nvim", + for_cat = 'general.telescope', + cmd = { "Telescope", "LiveGrepGitRoot" }, + -- NOTE: our on attach function defines keybinds that call telescope. + -- so, the on_require handler will load telescope when we use those. + on_require = { "telescope", }, + -- event = "", + -- ft = "", + keys = { + { "sM", 'Telescope notify', mode = {"n"}, desc = '[S]earch [M]essage', }, + { "sp",live_grep_git_root, mode = {"n"}, desc = '[S]earch git [P]roject root', }, + { "/", function() + -- Slightly advanced example of overriding default behavior and theme + -- You can pass additional configuration to telescope to change theme, layout, etc. + require('telescope.builtin').current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { + winblend = 10, + previewer = false, + }) + end, mode = {"n"}, desc = '[/] Fuzzily search in current buffer', }, + { "s/", function() + require('telescope.builtin').live_grep { + grep_open_files = true, + prompt_title = 'Live Grep in Open Files', + } + end, mode = {"n"}, desc = '[S]earch [/] in Open Files' }, + { "s", function() return require('telescope.builtin').buffers() end, mode = {"n"}, desc = '[ ] Find existing buffers', }, + { "s.", function() return require('telescope.builtin').oldfiles() end, mode = {"n"}, desc = '[S]earch Recent Files ("." for repeat)', }, + { "sr", function() return require('telescope.builtin').resume() end, mode = {"n"}, desc = '[S]earch [R]esume', }, + { "sd", function() return require('telescope.builtin').diagnostics() end, mode = {"n"}, desc = '[S]earch [D]iagnostics', }, + { "sg", function() return require('telescope.builtin').live_grep() end, mode = {"n"}, desc = '[S]earch by [G]rep', }, + { "sw", function() return require('telescope.builtin').grep_string() end, mode = {"n"}, desc = '[S]earch current [W]ord', }, + { "ss", function() return require('telescope.builtin').builtin() end, mode = {"n"}, desc = '[S]earch [S]elect Telescope', }, + { "sf", function() return require('telescope.builtin').find_files() end, mode = {"n"}, desc = '[S]earch [F]iles', }, + { "sk", function() return require('telescope.builtin').keymaps() end, mode = {"n"}, desc = '[S]earch [K]eymaps', }, + { "sh", function() return require('telescope.builtin').help_tags() end, mode = {"n"}, desc = '[S]earch [H]elp', }, + }, + -- colorscheme = "", + load = function (name) + vim.cmd.packadd(name) + vim.cmd.packadd("telescope-fzf-native.nvim") + vim.cmd.packadd("telescope-ui-select.nvim") + end, + after = function (plugin) + require('telescope').setup { + -- You can put your default mappings / updates / etc. in here + -- All the info you're looking for is in `:help telescope.setup()` + -- + defaults = { + mappings = { + i = { [''] = 'to_fuzzy_refine' }, + }, + }, + -- pickers = {} + extensions = { + ['ui-select'] = { + require('telescope.themes').get_dropdown(), + }, + }, + } + + -- Enable telescope extensions, if they are installed + pcall(require('telescope').load_extension, 'fzf') + pcall(require('telescope').load_extension, 'ui-select') + + vim.api.nvim_create_user_command('LiveGrepGitRoot', live_grep_git_root, {}) + end, + }, +} diff --git a/lua/myLuaConf/plugins/treesitter.lua b/lua/myLuaConf/plugins/treesitter.lua new file mode 100644 index 0000000..d16989d --- /dev/null +++ b/lua/myLuaConf/plugins/treesitter.lua @@ -0,0 +1,78 @@ +-- [[ Configure Treesitter ]] +-- See `:help nvim-treesitter` +return { + { + "nvim-treesitter", + for_cat = 'general.treesitter', + -- cmd = { "" }, + event = "DeferredUIEnter", + -- ft = "", + -- keys = "", + -- colorscheme = "", + load = function (name) + vim.cmd.packadd(name) + vim.cmd.packadd("nvim-treesitter-textobjects") + end, + after = function (plugin) + -- [[ Configure Treesitter ]] + -- See `:help nvim-treesitter` + require('nvim-treesitter.configs').setup { + highlight = { enable = true, }, + indent = { enable = false, }, + incremental_selection = { + enable = true, + keymaps = { + init_selection = '', + node_incremental = '', + scope_incremental = '', + node_decremental = '', + }, + }, + textobjects = { + select = { + enable = true, + lookahead = true, -- Automatically jump forward to textobj, similar to targets.vim + keymaps = { + -- You can use the capture groups defined in textobjects.scm + ['aa'] = '@parameter.outer', + ['ia'] = '@parameter.inner', + ['af'] = '@function.outer', + ['if'] = '@function.inner', + ['ac'] = '@class.outer', + ['ic'] = '@class.inner', + }, + }, + move = { + enable = true, + set_jumps = true, -- whether to set jumps in the jumplist + goto_next_start = { + [']m'] = '@function.outer', + [']]'] = '@class.outer', + }, + goto_next_end = { + [']M'] = '@function.outer', + [']['] = '@class.outer', + }, + goto_previous_start = { + ['[m'] = '@function.outer', + ['[['] = '@class.outer', + }, + goto_previous_end = { + ['[M'] = '@function.outer', + ['[]'] = '@class.outer', + }, + }, + swap = { + enable = true, + swap_next = { + ['a'] = '@parameter.inner', + }, + swap_previous = { + ['A'] = '@parameter.inner', + }, + }, + }, + } + end, + }, +} diff --git a/lua/nixCatsUtils/catPacker.lua b/lua/nixCatsUtils/catPacker.lua new file mode 100644 index 0000000..4cfe835 --- /dev/null +++ b/lua/nixCatsUtils/catPacker.lua @@ -0,0 +1,40 @@ +--[[ + 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 + bootstrap_paq(vim.list_extend({"savq/paq-nvim"},v)) + end +end +return M diff --git a/lua/nixCatsUtils/init.lua b/lua/nixCatsUtils/init.lua new file mode 100644 index 0000000..b6a6128 --- /dev/null +++ b/lua/nixCatsUtils/init.lua @@ -0,0 +1,129 @@ +--[[ + 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/lua/nixCatsUtils/lzUtils.lua b/lua/nixCatsUtils/lzUtils.lua new file mode 100644 index 0000000..2e2393d --- /dev/null +++ b/lua/nixCatsUtils/lzUtils.lua @@ -0,0 +1,36 @@ +--[[ + 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 = {} +-- A nixCats specific lze handler that you can use to conditionally enable by category easier. +-- at the start of your config, register with +-- require('lze').register_handlers(require('nixCatsUtils.lzUtils').for_cat) +-- before any calls to require('lze').load using the handler have been made. +-- accepts: +-- for_cat = { "your" "cat" }; +-- for_cat = { cat = { "your" "cat" }, default = bool } +-- for_cat = "your.cat"; +-- for_cat = { cat = "your.cat", default = bool } +-- where default is an alternate value for when nixCats was NOT used to install the config +M.for_cat = { + spec_field = "for_cat", + set_lazy = false, + modify = function(plugin) + if type(plugin.for_cat) == "table" and plugin.for_cat.cat ~= nil then + if vim.g[ [[nixCats-special-rtp-entry-nixCats]] ] ~= nil then + plugin.enabled = nixCats(plugin.for_cat.cat) or false + else + plugin.enabled = plugin.for_cat.default + end + else + plugin.enabled = nixCats(plugin.for_cat) or false + end + return plugin + end, +} + +return M