nix-wrapper-modules port. Basic modules.nix, gotta port the lua still.

This commit is contained in:
Gabe Venberg 2026-03-08 23:01:58 +01:00
parent 0499b13274
commit 7c9d33f7bb
20 changed files with 1375 additions and 1730 deletions

View file

@ -1,4 +1,89 @@
# Gabes `nixCats` Configuration
# Neovim module
My preferred way of setting up neovim. This configuration has organically grown since 2016,
originally as a vimscript config, then as a lua config, then as a nixvim config, and finally a nix/lua hybrid.
This is a demonstration of the [neovim module](https://birdeehub.github.io/nix-wrapper-modules/wrapperModules/neovim.html)
It makes use of the tips in the [tips and tricks](https://birdeehub.github.io/nix-wrapper-modules/wrapperModules/neovim.html#tips-and-tricks) section of the documentation.
This template configuration is by no means a perfect, complete configuration.
However, it is plenty to start on, and covers some interesting ways to use the module (and how to lazily load plugins and config).
This configuration is 1 `lua` file, however the whole set of directories from a normal `neovim` configuration directory are available.
To see what directories you can put stuff in, see: [:help 'rtp'](https://neovim.io/doc/user/options.html#'rtp')
The main reason it is in 1 file is that it is following the style of [kickstart.nvim](https://github.com/nvim-lua/kickstart.nvim).
The other reason it is in 1 file, is that it makes it a cleaner experience to init this template into an existing configuration.
This template config uses [lze](https://github.com/BirdeeHub/lze) for lazy loading of the configuration.
You may also be interested in [lz.n](https://github.com/lumen-oss/lz.n) for this purpose.
Both achieve the same general result and main interface,
but have different underlying implementations and thus have different handler features.
Both are fantastic for lazy loading with both nix and the builtin plugin manager.
You may also decide you don't need lazy loading at all. This is fine, many plugins mostly handle that themselves.
To initialize this template flake into the current directory, run:
```bash
nix flake init -t github:BirdeeHub/nix-wrapper-modules#neovim
```
It will not replace existing files.
If you are using `zsh` you may need to escape the `#`
To build it from that directory
```bash
nix build .
```
It exports a package! (and other things)
If you don't want your config in a separate flake, just call the `module.nix` file like:
```nix
inputs: # <-- get the library somehow
{ pkgs, ... }: {
# call the module and install the package (nixos example)
environment.systemPackages = [ (inputs.nix-wrapper-modules.lib.evalPackage [ ./module.nix { inherit pkgs; } ]) ];
}
```
There are a lot of other ways to install it as well, see [the getting started documentation](https://birdeehub.github.io/nix-wrapper-modules/md/getting-started.html)
You may also wish to view the `flake.nix` of this template, as it demonstrates some of those things when setting up its outputs.
---
The nix in this template is not as simple as it could possibly be, as it demonstrates some things
from the [tips and tricks](https://birdeehub.github.io/nix-wrapper-modules/wrapperModules/neovim.html#tips-and-tricks) section of the documentation.
If you wanted as simple as possible, you could use something more like the following as your `module.nix`
```nix
{ wlib, config, pkgs, lib, ... }:
imports = [ wlib.wrapperModules.neovim ];
specs.general = with pkgs.vimPlugins; [
# plugins which are loaded at startup ...
];
specs.lazy = {
lazy = true;
data = with pkgs.vimPlugins; [
# plugins which are not loaded until you vim.cmd.packadd them ...
];
};
extraPackages = with pkgs; [
# lsps, formatters, etc...
];
settings.config_directory = ./.; # or lib.generators.mkLuaInline "vim.fn.stdpath('config')";
}
```
At the same time, you may find that the `module.nix` file from this template is not massively more complex than that either,
and contains some useful tricks and information.

83
flake.lock generated
View file

@ -1,40 +1,79 @@
{
"nodes": {
"nixCats": {
"locked": {
"lastModified": 1769578476,
"narHash": "sha256-4+KbiBcC6hQ3sh0UbPXjy6TOfLh9yhskRlfPzyZ2FH4=",
"owner": "BirdeeHub",
"repo": "nixCats-nvim",
"rev": "48f8be4bdafccfa19ceaaf08071a15eca36fdb1d",
"type": "github"
},
"original": {
"owner": "BirdeeHub",
"repo": "nixCats-nvim",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1770141374,
"narHash": "sha256-yD4K/vRHPwXbJf5CK3JkptBA6nFWUKNX/jlFp2eKEQc=",
"owner": "nixos",
"lastModified": 1772674223,
"narHash": "sha256-/suKbHSaSmuC9UY7G0VRQ3aO+QKqxAQPQ19wG7QNkF8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "41965737c1797c1d83cfb0b644ed0840a6220bd1",
"rev": "66d9241e3dc2296726dc522e62dbfe89c7b449f3",
"type": "github"
},
"original": {
"owner": "nixos",
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"plugins-lze": {
"flake": false,
"locked": {
"lastModified": 1772337062,
"narHash": "sha256-joi1087b2iDmwOHv7/0YCrDPucbu0osbS8WQmDYoyE4=",
"owner": "BirdeeHub",
"repo": "lze",
"rev": "f50a84a5d84f6b16e254091e755f5a9e839a9924",
"type": "github"
},
"original": {
"owner": "BirdeeHub",
"repo": "lze",
"type": "github"
}
},
"plugins-lzextras": {
"flake": false,
"locked": {
"lastModified": 1772336997,
"narHash": "sha256-BsoZTfXpISPeTnTQWtnZkDXzvo9ocILB5IO2vU8IvAM=",
"owner": "BirdeeHub",
"repo": "lzextras",
"rev": "abdda956a2947d0617133a018992d035fc5781da",
"type": "github"
},
"original": {
"owner": "BirdeeHub",
"repo": "lzextras",
"type": "github"
}
},
"root": {
"inputs": {
"nixCats": "nixCats",
"nixpkgs": "nixpkgs"
"nixpkgs": "nixpkgs",
"plugins-lze": "plugins-lze",
"plugins-lzextras": "plugins-lzextras",
"wrappers": "wrappers"
}
},
"wrappers": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1772662098,
"narHash": "sha256-BKxBM4RNWP+5q0ZQ6v3JlJ0e6fFj/YoYNZ7/OpgabdU=",
"owner": "BirdeeHub",
"repo": "nix-wrapper-modules",
"rev": "2c0a3b795766b25d15ad1ec9eef3a06160154c9a",
"type": "github"
},
"original": {
"owner": "BirdeeHub",
"repo": "nix-wrapper-modules",
"type": "github"
}
}
},

483
flake.nix
View file

@ -1,436 +1,75 @@
# Copyright (c) 2023 BirdeeHub and Gabriel Venberg
# Licensed under the MIT license
{
description = "Gabes neovim config, based on NixCats";
description = "Flake exporting a configured neovim package";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
nixCats.url = "github:BirdeeHub/nixCats-nvim";
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
wrappers = {
url = "github:BirdeeHub/nix-wrapper-modules";
inputs.nixpkgs.follows = "nixpkgs";
};
plugins-lze = {
url = "github:BirdeeHub/lze";
flake = false;
};
plugins-lzextras = {
url = "github:BirdeeHub/lzextras";
flake = false;
};
};
# see :help nixCats.flake.outputs
outputs = {
self,
nixpkgs,
wrappers,
...
} @ inputs: let
inherit (inputs.nixCats) utils;
luaPath = ./.;
# this is flake-utils eachSystem
forEachSystem = utils.eachSystem nixpkgs.lib.platforms.all;
extra_pkg_config = {
# allowUnfree = true;
forAllSystems = nixpkgs.lib.genAttrs [
"x86_64-linux"
"aarch64-linux"
];
module = nixpkgs.lib.modules.importApply ./module.nix inputs;
wrapper = wrappers.lib.evalModule module;
in {
formatter = forAllSystems (system: nixpkgs.legacyPackages.${system}.alejandra);
overlays = {
neovim = final: prev: {neovim = wrapper.config.wrap {pkgs = final;};};
default = self.overlays.neovim;
};
# 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-<pluginName>`
# 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.
];
# see :help nixCats.flake.outputs.categories
# and
# :help nixCats.flake.outputs.categoryDefinitions.scheme
categoryDefinitions = {
pkgs,
settings,
categories,
extra,
name,
mkPlugin,
...
} @ packageDef: let
colorschemes = with pkgs.vimPlugins; {
"onedark" = onedark-nvim;
"catppuccin" = catppuccin-nvim;
"tokyonight" = tokyonight-nvim;
"nord" = nord-nvim;
"gruvbox" = gruvbox-nvim;
wrapperModules = {
neovim = module;
default = self.wrapperModules.neovim;
};
wrappers = {
neovim = wrapper.config;
default = self.wrappers.neovim;
};
packages = forAllSystems (
system: let
pkgs = import nixpkgs {inherit system;};
in {
neovim = wrapper.config.wrap {inherit pkgs;};
default = self.packages.${system}.neovim;
}
);
# `wrappers.neovim.enable = true`
nixosModules = {
default = self.nixosModules.neovim;
neovim = wrappers.lib.mkInstallModule {
name = "neovim";
value = module;
};
in {
# 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 = with pkgs; {
# some categories of stuff.
always = [
universal-ctags
ripgrep
fd
fzf
lazygit
zoxide
];
markdown = [
mermaid-cli
imagemagick
texliveSmall
];
git = [
lazygit
git
];
lsp = {
rust = [
rust-analyzer
cargo
];
lua = [
lua-language-server
];
nix = [
nix-doc
nixd
alejandra
];
python = [
basedpyright
ruff
];
C = [
libclang
];
bash = [
shellcheck
bash-language-server
];
typst = [
tinymist
];
};
format = [
];
};
# This is for plugins that will load at startup without using packadd:
startupPlugins = with pkgs.vimPlugins; {
always = [
lze
lzextras
plenary-nvim
oil-nvim
nvim-web-devicons
snacks-nvim
nvim-numbertoggle
lualine-nvim
which-key-nvim
todo-comments-nvim
marks-nvim
];
lsp = {
rust = [
rustaceanvim
];
};
debug = [
nvim-nio
];
treesitter = [
comment-nvim
rainbow-delimiters-nvim
nvim-treesitter.withAllGrammars
treesj
];
allcolorschemes = colorschemes;
# You can retreive information from the
# packageDefinitions of the package this was packaged with.
# :help nixCats.flake.outputs.categoryDefinitions.scheme
themer = builtins.getAttr (categories.colorscheme or "gruvbox") colorschemes;
# 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 = with pkgs.vimPlugins; {
debug = {
default = [
nvim-dap
nvim-dap-ui
nvim-dap-virtual-text
venn-nvim
];
};
lint = [
nvim-lint
];
format = [
conform-nvim
];
markdown = [
markdown-preview-nvim
];
lsp = {
default = [
trouble-nvim
lualine-lsp-progress
nvim-lspconfig
];
zk = [
zk-nvim
];
lua = [
lazydev-nvim
];
typst = [
typst-preview-nvim
];
};
git = [
gitsigns-nvim
];
always = [
nvim-surround
leap-nvim
];
completion = [
luasnip
friendly-snippets
cmp-cmdline
blink-cmp
blink-emoji-nvim
blink-compat
colorful-menu-nvim
];
extra = [
vim-startuptime
];
};
# shared libraries to be added to LD_LIBRARY_PATH
# variable available to nvim runtime
sharedLibraries = {
};
# environmentVariables:
# this section is for environmentVariables that should be available
# at RUN TIME for plugins. Will be available to path within neovim terminal
environmentVariables = {
};
# 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 = {
};
# populates $LUA_PATH and $LUA_CPATH
extraLuaPackages = {
};
# 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 = {
debug = [
["debug" "default"]
];
lsp = [
["lsp" "default"]
};
# `wrappers.neovim.enable = true`
# You can set any of the options.
# But that is how you enable it.
homeModules = {
default = self.homeModules.neovim;
neovim = wrappers.lib.mkInstallModule {
name = "neovim";
value = module;
loc = [
"home"
"packages"
];
};
};
# 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.
nvim = {
pkgs,
name,
...
} @ misc: {
# these also recieve our pkgs variable
# see :help nixCats.flake.outputs.packageDefinitions
settings = {
suffix-path = true;
suffix-LD = true;
# 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 = [];
wrapRc = true;
configDirName = "nvim";
};
categories = {
always = true;
git = true;
treesitter = true;
markdown = true;
lsp = true;
completion = true;
debug = true;
lspDebugMode = false;
allcolorschemes = true;
colorscheme = "gruvbox";
};
extra = {
};
};
nvim-minimal = {
pkgs,
name,
...
} @ misc: {
settings = {
suffix-path = true;
suffix-LD = true;
# 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"];
wrapRc = true;
configDirName = "nvim-minimal";
};
categories = {
always = true;
treesitter = true;
completion = true;
lspDebugMode = false;
lsp = false;
git = false;
themer = true;
colorscheme = "gruvbox";
};
extra = {
};
};
};
defaultPackageName = "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
# <see :h nixCats.module for options>
# }
# 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
# 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;
formatter = pkgs.alejandra;
# 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;
});
};
}

150
init.lua
View file

@ -1,60 +1,96 @@
--[[
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,
-- NOTE: Welcome to your neovim configuration!
-- The first 100ish lines are setup,
-- the rest is usage of lze and various core plugins!
vim.loader.enable() -- <- bytecode caching
do
-- Set up a global in a way that also handles non-nix compat
local ok
ok, _G.nixInfo = pcall(require, vim.g.nix_info_plugin_name)
if not ok then
package.loaded[vim.g.nix_info_plugin_name] = setmetatable({}, {
__call = function (_, default) return default end
})
_G.nixInfo = require(vim.g.nix_info_plugin_name)
-- If you always use the fetcher function to fetch nix values,
-- rather than indexing into the tables directly,
-- it will use the value you specified as the default
-- TODO: for non-nix compat, vim.pack.add in another file and require here.
end
nixInfo.isNix = vim.g.nix_info_plugin_name ~= nil
---@module 'lzextras'
---@type lzextras | lze
nixInfo.lze = setmetatable(require('lze'), getmetatable(require('lzextras')))
function nixInfo.get_nix_plugin_path(name)
return nixInfo(nil, "plugins", "lazy", name) or nixInfo(nil, "plugins", "start", name)
end
end
nixInfo.lze.register_handlers {
{
-- adds an `auto_enable` field to lze specs
-- if true, will disable it if not installed by nix.
-- if string, will disable if that name was not installed by nix.
-- if a table of strings, it will disable if any were not.
spec_field = "auto_enable",
set_lazy = false,
modify = function(plugin)
if vim.g.nix_info_plugin_name then
if type(plugin.auto_enable) == "table" then
for _, name in pairs(plugin.auto_enable) do
if not nixInfo.get_nix_plugin_path(name) then
plugin.enabled = false
break
end
end
elseif type(plugin.auto_enable) == "string" then
if not nixInfo.get_nix_plugin_path(plugin.auto_enable) then
plugin.enabled = false
end
elseif type(plugin.auto_enable) == "boolean" and plugin.auto_enable then
if not nixInfo.get_nix_plugin_path(plugin.name) then
plugin.enabled = false
end
end
end
return plugin
end,
},
{
-- we made an options.settings.cats with the value of enable for our top level specs
-- give for_cat = "name" to disable if that one is not enabled
spec_field = "for_cat",
set_lazy = false,
modify = function(plugin)
if vim.g.nix_info_plugin_name then
if type(plugin.for_cat) == "string" then
plugin.enabled = nixInfo(false, "settings", "cats", plugin.for_cat)
end
end
return plugin
end,
},
-- 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
-- It is (unfortunately) important that it be registered after the above 2,
-- as it also relies on the modify hook, and the value of enabled at that point
nixInfo.lze.lsp,
}
--[[
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.
--]]
-- NOTE: This config uses lzextras.lsp handler https://github.com/BirdeeHub/lzextras?tab=readme-ov-file#lsp-handler
-- Because we have the paths, we can set a more performant fallback function
-- for when you don't provide a filetype to trigger on yourself.
-- If you do provide a filetype, this will never be called.
nixInfo.lze.h.lsp.set_ft_fallback(function(name)
local lspcfg = nixInfo.get_nix_plugin_path "nvim-lspconfig"
if lspcfg then
local ok, cfg = pcall(dofile, lspcfg .. "/lsp/" .. name .. ".lua")
return (ok and cfg or {}).filetypes or {}
else
-- the less performant thing we are trying to avoid at startup
return (vim.lsp.config[name] or {}).filetypes or {}
end
end)
--[[
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')
require('opts')
require('keys')
require('plugins')

37
lua/keys.lua Normal file
View file

@ -0,0 +1,37 @@
-- [[ Basic Keymaps ]]
-- Keymaps for better default experience
-- See `:help vim.keymap.set()`
vim.keymap.set("v", "J", ":m '>+1<CR>gv=gv", { desc = 'Moves Line Down' })
vim.keymap.set("v", "K", ":m '<-2<CR>gv=gv", { desc = 'Moves Line Up' })
vim.keymap.set("n", "<C-d>", "<C-d>zz", { desc = 'Scroll Down' })
vim.keymap.set("n", "<C-u>", "<C-u>zz", { desc = 'Scroll Up' })
vim.keymap.set("n", "n", "nzzzv", { desc = 'Next Search Result' })
vim.keymap.set("n", "N", "Nzzzv", { desc = 'Previous Search Result' })
-- 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', '<leader>e', vim.diagnostic.open_float, { desc = 'Open floating diagnostic message' })
vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagnostics list' })
vim.keymap.set('n', '[d', function() vim.diagnostic.jump({ count = -1, float = true }) end,
{ desc = 'Go to previous diagnostic' })
vim.keymap.set('n', ']d', function() vim.diagnostic.jump({ count = 1, float = true }) end,
{ desc = 'Go to next diagnostic' })
-- moving between splits
vim.keymap.set('n', '<C-h>', '<C-w>h', { desc = 'move to right split' })
vim.keymap.set('n', '<C-j>', '<C-w>j', { desc = 'move to below split' })
vim.keymap.set('n', '<C-k>', '<C-w>k', { desc = 'move to above split' })
vim.keymap.set('n', '<C-l>', '<C-w>l', { desc = 'move to left split' })
-- You should instead use these keybindings so that they are still easy to use, but dont conflict
vim.keymap.set({ "v", "x", "n" }, '<leader>y', '"+y', { noremap = true, silent = true, desc = 'Yank to clipboard' })
vim.keymap.set({ "n", "v", "x" }, '<leader>Y', '"+yy', { noremap = true, silent = true, desc = 'Yank line to clipboard' })
vim.keymap.set({ 'n', 'v', 'x' }, '<leader>p', '"+p', { noremap = true, silent = true, desc = 'Paste from clipboard' })
vim.keymap.set('i', '<C-p>', '<C-r><C-p>+',
{ noremap = true, silent = true, desc = 'Paste from clipboard from within insert mode' })
vim.keymap.set("x", "<leader>P", '"_dP',
{ noremap = true, silent = true, desc = 'Paste over selection without erasing unnamed register' })

View file

@ -1,261 +0,0 @@
local catUtils = require('nixCatsUtils')
if (catUtils.isNixCats and nixCats('lspDebugMode')) then
vim.lsp.set_log_level("debug")
end
local Snacks = require("snacks")
vim.keymap.set("n", "<leader>lI", Snacks.picker.lsp_implementations, { desc = "Goto [I]mplementation" })
vim.keymap.set("n", "<leader>lR", Snacks.picker.lsp_references, { desc = "Goto [R]eferences" })
vim.keymap.set("n", "<leader>li", Snacks.picker.diagnostics, { desc = "D[i]agnostics" })
vim.keymap.set("n", "<leader>ls", Snacks.picker.lsp_symbols, { desc = "Document [S]ymbols" })
vim.keymap.set("n", "<leader>lws", Snacks.picker.lsp_workspace_symbols, { desc = "[W]orkspace [S]ymbols" })
vim.keymap.set("n", "<leader>lD", vim.lsp.buf.declaration, { desc = "Goto [D]eclaration" })
vim.keymap.set("n", "<leader>lt", vim.lsp.buf.type_definition, { desc = "Type [D]efinition" })
vim.keymap.set({"n", "v",}, "<leader>la", vim.lsp.buf.code_action, { desc = "[C]ode Action" })
vim.keymap.set("n", "<leader>ld", vim.lsp.buf.definition, { desc = "Goto [D]efinition" })
vim.keymap.set("n", "<leader>lf", vim.lsp.buf.format, { desc = "Format buffer" })
vim.keymap.set("n", "<leader>lh", vim.lsp.buf.hover, { desc = "Hover Documentation" })
vim.keymap.set("n", "<leader>lr", vim.lsp.buf.rename, { desc = "[R]ename" })
vim.keymap.set("n", "<leader>ls", vim.lsp.buf.signature_help, { desc = "Signature Documentation" })
vim.keymap.set("n", "<leader>lwa", vim.lsp.buf.add_workspace_folder, { desc = "[W]orkspace [A]dd Folder" })
vim.keymap.set("n", "<leader>lwl", function() print(vim.inspect(vim.lsp.buf.list_workspace_folders())) end,
{ desc = "[W]orkspace [L]ist Folders" })
vim.keymap.set("n", "<leader>lwr", vim.lsp.buf.remove_workspace_folder, { desc = "[W]orkspace [R]emove Folder" })
-- setup lsp progress notifications
local progress = vim.defaulttable()
vim.api.nvim_create_autocmd("LspProgress", {
callback = function(ev)
local client = vim.lsp.get_client_by_id(ev.data.client_id)
local value = ev.data.params
.value --[[@as {percentage?: number, title?: string, message?: string, kind: "begin" | "report" | "end"}]]
if not client or type(value) ~= "table" then
return
end
local p = progress[client.id]
for i = 1, #p + 1 do
if i == #p + 1 or p[i].token == ev.data.params.token then
p[i] = {
token = ev.data.params.token,
msg = ("[%3d%%] %s%s"):format(
value.kind == "end" and 100 or value.percentage or 100,
value.title or "",
value.message and (" **%s**"):format(value.message) or ""
),
done = value.kind == "end",
}
break
end
end
local msg = {} ---@type string[]
progress[client.id] = vim.tbl_filter(function(v)
return table.insert(msg, v.msg) or not v.done
end, p)
local spinner = { "", "", "", "", "", "", "", "", "", "" }
vim.notify(table.concat(msg, "\n"), "info", {
id = "lsp_progress",
title = client.name,
opts = function(notif)
notif.icon = #progress[client.id] == 0 and ""
or spinner[math.floor(vim.uv.hrtime() / (1e6 * 80)) % #spinner + 1]
end,
})
end,
})
-- 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 = "lsp",
on_require = { "lspconfig" },
-- rustaceanvim and zk-nvim dont require("lspconfig")
ft = { "markdown", "rust" },
-- NOTE: define a function for lsp,
-- and it will run for all specs with type(plugin.lsp) == table
-- when their filetype trigger loads them
lsp = function(plugin)
vim.lsp.config(plugin.name, plugin.lsp or {})
vim.lsp.enable(plugin.name)
end,
},
{
"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 = "lsp.lua",
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('lsp.lua'),
-- provide a table containing filetypes,
-- and then whatever your functions defined in the function type specs expect.
-- in our case, it just expects the normal lspconfig setup options,
-- but with a default on_attach and capabilities
lsp = {
-- if you provide the filetypes it doesn't ask lspconfig for the filetypes
filetypes = { 'lua' },
settings = {
Lua = {
runtime = { version = 'LuaJIT' },
formatters = {
ignoreComments = true,
},
signatureHelp = { enabled = true },
diagnostics = {
globals = { "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
},
{
"basedpyright",
enabled = nixCats("lsp.python"),
lsp = {},
},
{
"bashls",
enabled = nixCats("lsp.bash"),
lsp = {},
},
{
"clangd",
enabled = nixCats("lsp.c"),
lsp = {},
},
{
"ruff",
enabled = nixCats("lsp.python"),
lsp = {},
},
{
"tinymist",
enabled = nixCats("lsp.tinymist"),
lsp = {
filetypes = { "typst" },
settings = {
formatterMode = "typstyle",
},
},
},
{
"nixd",
enabled = catUtils.isNixCats and nixCats('lsp.nix'),
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")
},
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 = { "alejandra" }
},
diagnostic = {
suppress = {
"sema-escaping-with"
}
}
}
},
},
},
{
"rustaceanvim",
for_cat = "lsp.rust",
},
{
"zk-nvim",
for_cat = "lsp.zk",
ft = "markdown",
after = function()
require("zk").setup({ picker = "snacks_picker" })
vim.api.nvim_set_keymap("n", "<leader>zb", "<Cmd>ZkBackLinks<CR>", { desc = "Show [B]acklinkgs" })
vim.api.nvim_set_keymap("n", "<leader>zl", "<Cmd>ZkLinks<CR>", { desc = "Show [L]inks" })
vim.api.nvim_set_keymap("n", "<leader>zi", ":'<,'>ZkInsertLink<CR>", { desc = "[I]nsert link" })
vim.api.nvim_set_keymap("n", "<leader>zn", "<Cmd>ZkNew { title = vim.fn.input('Title: ') }<CR>",
{ desc = "[N]ew note" })
vim.api.nvim_set_keymap("n", "<leader>zo", "<Cmd>ZkNotes { sort = { 'modified' } }<CR>", { desc = "[O]pen notes" })
vim.api.nvim_set_keymap("n", "<leader>zt", "<Cmd>ZkTags<CR>", { desc = "Search [T]ags" })
vim.api.nvim_set_keymap("v", "<leader>zf", ":'<,'>ZkMatch<CR>", { desc = "[F]ind note from selection" })
vim.api.nvim_set_keymap("v", "<leader>zn", ":'<,'>ZkNewFromTitleSelection<CR>", {
desc =
"[N]ew note from selection"
})
end
},
}

View file

@ -1,20 +0,0 @@
-- TODO: split up the plugins a bit.
-- 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")

View file

@ -1,92 +0,0 @@
-- TODO: completley out of date
-- 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", },
{ 'ellisonleao/gruvbox.nvim', },
{ '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.

View file

@ -1,156 +0,0 @@
local load_w_after = function(name)
vim.cmd.packadd(name)
vim.cmd.packadd(name .. '/after')
end
return {
{
"cmp-cmdline",
for_cat = "completion",
on_plugin = { "blink.cmp" },
load = load_w_after,
},
{
"blink.compat",
for_cat = "completion",
dep_of = { "cmp-cmdline" },
},
{
"luasnip",
for_cat = "completion",
dep_of = { "blink.cmp" },
after = function(_)
vim.cmd.packadd("friendly-snippets")
local luasnip = require 'luasnip'
require('luasnip.loaders.from_vscode').lazy_load()
luasnip.config.setup {}
local ls = require('luasnip')
vim.keymap.set({ "i", "s" }, "<M-n>", function()
if ls.choice_active() then
ls.change_choice(1)
end
end)
end,
},
{
"colorful-menu.nvim",
for_cat = "completion",
on_plugin = { "blink.cmp" },
},
{
"blink-emoji.nvim",
for_cat = "completion",
on_plugin = { "blink.cmp" },
},
{
"blink.cmp",
for_cat = "completion",
event = "DeferredUIEnter",
after = function(_)
require("blink.cmp").setup({
-- 'default' (recommended) for mappings similar to built-in completions (C-y to accept)
-- See :h blink-cmp-config-keymap for configuring keymaps
keymap = { preset = "enter", },
cmdline = {
enabled = true,
completion = {
menu = {
auto_show = true,
},
},
sources = function()
local type = vim.fn.getcmdtype()
-- Search forward and backward
if type == '/' or type == '?' then return { 'buffer' } end
-- Commands
if type == ':' or type == '@' then return { 'cmdline', 'cmp_cmdline' } end
return {}
end,
},
fuzzy = {
sorts = {
'exact',
-- defaults
'score',
'sort_text',
},
},
signature = {
enabled = true,
window = {
show_documentation = true,
},
},
completion = {
list = {
selection = {
preselect = false,
auto_insert = false,
},
},
menu = {
draw = {
treesitter = { 'lsp' },
components = {
label = {
text = function(ctx)
return require("colorful-menu").blink_components_text(ctx)
end,
highlight = function(ctx)
return require("colorful-menu").blink_components_highlight(ctx)
end,
},
},
},
},
documentation = {
auto_show = true,
},
},
snippets = {
preset = 'luasnip',
active = function(filter)
local snippet = require "luasnip"
local blink = require "blink.cmp"
if snippet.in_snippet() and not blink.is_visible() then
return true
else
if not snippet.in_snippet() and vim.fn.mode() == "n" then snippet.unlink_current() end
return false
end
end,
},
sources = {
default = { 'lsp', 'path', 'snippets', 'buffer', 'omni', 'emoji', },
providers = {
path = {
score_offset = 50,
},
lsp = {
score_offset = 40,
},
snippets = {
score_offset = 40,
},
emoji = {
module = "blink-emoji",
name = "Emoji",
score_offset = 15,
opts = { insert = true },
},
cmp_cmdline = {
name = 'cmp_cmdline',
module = 'blink.compat.source',
score_offset = -100,
opts = {
cmp_name = 'cmdline',
},
},
},
},
})
end,
},
}

View file

@ -1,84 +0,0 @@
return {
"gitsigns.nvim",
for_cat = 'git',
event = "DeferredUIEnter",
-- cmd = { "" },
-- ft = "",
-- keys = "",
-- colorscheme = "",
after = function()
require('gitsigns').setup({
-- See `:help gitsigns.txt`
signs = {
add = { text = '+' },
change = { text = '~' },
delete = { text = '_' },
topdelete = { text = '' },
changedelete = { text = '~' },
},
on_attach = function(bufnr)
local gs = package.loaded.gitsigns
local function map(mode, l, r, opts)
opts = opts or {}
opts.buffer = bufnr
vim.keymap.set(mode, l, r, opts)
end
-- Navigation
map({ 'n', 'v' }, ']c', function()
if vim.wo.diff then
return ']c'
end
vim.schedule(function()
gs.next_hunk()
end)
return '<Ignore>'
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 '<Ignore>'
end, { expr = true, desc = 'Jump to previous hunk' })
-- Actions
-- visual mode
map('v', '<leader>hs', function()
gs.stage_hunk { vim.fn.line '.', vim.fn.line 'v' }
end, { desc = 'stage git hunk' })
map('v', '<leader>hr', function()
gs.reset_hunk { vim.fn.line '.', vim.fn.line 'v' }
end, { desc = 'reset git hunk' })
-- normal mode
map('n', '<leader>gs', gs.stage_hunk, { desc = 'git stage hunk' })
map('n', '<leader>gr', gs.reset_hunk, { desc = 'git reset hunk' })
map('n', '<leader>gS', gs.stage_buffer, { desc = 'git Stage buffer' })
map('n', '<leader>gu', gs.undo_stage_hunk, { desc = 'undo stage hunk' })
map('n', '<leader>gR', gs.reset_buffer, { desc = 'git Reset buffer' })
map('n', '<leader>gp', gs.preview_hunk, { desc = 'preview git hunk' })
map('n', '<leader>gb', function()
gs.blame_line { full = false }
end, { desc = 'git blame line' })
map('n', '<leader>gd', gs.diffthis, { desc = 'git diff against index' })
map('n', '<leader>gD', function()
gs.diffthis '~'
end, { desc = 'git diff against last commit' })
-- Toggles
map('n', '<leader>gtb', gs.toggle_current_line_blame, { desc = 'toggle git blame line' })
map('n', '<leader>gtd', gs.toggle_deleted, { desc = 'toggle git show deleted' })
-- Text object
map({ 'o', 'x' }, 'ih', ':<C-U>Gitsigns select_hunk<CR>', { desc = 'select git hunk' })
end,
})
vim.cmd([[hi GitSignsAdd guifg=#04de21]])
vim.cmd([[hi GitSignsChange guifg=#83fce6]])
vim.cmd([[hi GitSignsDelete guifg=#fa2525]])
end,
}

View file

@ -1,279 +0,0 @@
local colorschemeName = nixCats('colorscheme')
if not require('nixCatsUtils').isNixCats then
colorschemeName = 'gruvbox'
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", "<Esc>", 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('always') 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 = false,
view_options = {
show_hidden = true
},
columns = {
"icon",
"permissions",
"size",
-- "mtime",
},
keymaps = {
["g?"] = "actions.show_help",
["<CR>"] = "actions.select",
["<C-s>"] = "actions.select_vsplit",
["<C-h>"] = "actions.select_split",
["<C-t>"] = "actions.select_tab",
["<C-p>"] = "actions.preview",
["<C-c>"] = "actions.close",
["<C-l>"] = "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", "-", "<cmd>Oil<CR>", { noremap = true, desc = 'Open Parent Directory' })
vim.keymap.set("n", "<leader>-", "<cmd>Oil .<CR>", { noremap = true, desc = 'Open nvim root directory' })
end
if nixCats("always") then
-- Potentially checkout the lazygit module.
local Snacks = require("snacks")
local config = {
bufdelete = { enable = true },
dim = { enable = true },
git = { enable = true },
input = { enable = true },
notifier = { enable = true },
terminal = { enable = true },
toggle = { enable = true },
quickfile = { enable = true },
scope = { enable = true },
statuscolumn = { enable = true },
explorer = { replace_netrw = true },
picker = {
enabled = true,
ui_select = true,
matcher = {
fuzzy = true,
frecency = true,
},
previewers = {
diff = {
builtin = true, -- use Neovim for previewing diffs (true) or use an external tool (false)
cmd = { "delta" }, -- example to show a diff with delta
},
git = {
builtin = true, -- use Neovim for previewing git output (true) or use git (false)
},
},
},
indent = {
enabled = true,
animate = { enabled = false },
scope = { enabled = true },
chunk = { enabled = true },
},
image = { enabled = false, inline = false, float = false },
lazygit = { enabled = false, configure = false },
}
if nixCats("markdown") then
config.image.enable = true
end
if nixCats("git") then
config.lazygit.enable = true
end
Snacks.setup(config)
-- setup keybinds.
vim.keymap.set("n", "<leader>bd", Snacks.bufdelete.delete, { desc = "delete buffer" })
vim.keymap.set("n", "<leader>t", function() Snacks.explorer() end, { desc = "File [T]ree" })
vim.keymap.set("n", "<leader>i", Snacks.image.hover, { desc = "[I]mage preview" })
-- picker keybinds
vim.keymap.set("n", "<leader>fGb", Snacks.picker.grep_buffers, { desc = "[G]rep buffers" })
vim.keymap.set("n", "<leader>fGl", Snacks.picker.lines, { desc = "[L]ines in buffer" })
vim.keymap.set("n", "<leader>fb", Snacks.picker.buffers, { desc = "[B]uffers" })
vim.keymap.set("n", "<leader>ff", Snacks.picker.files, { desc = "[F]iles" })
vim.keymap.set("n", "<leader>fg", Snacks.picker.grep, { desc = "[G]rep all" })
vim.keymap.set("n", "<leader>fh", Snacks.picker.help, { desc = "[H]elp" })
vim.keymap.set("n", "<leader>fi", Snacks.picker.icons, { desc = "[I]cons" })
vim.keymap.set("n", "<leader>fm", Snacks.picker.marks, { desc = "[M]arks" })
vim.keymap.set("n", "<leader>fs", Snacks.picker.spelling, { desc = "[S]pelling" })
vim.keymap.set("n", "<leader>ft", Snacks.picker.treesitter, { desc = "[T]reesitter" })
vim.keymap.set("n", "<leader>fu", Snacks.picker.undo, { desc = "[U]ndo" })
vim.keymap.set("n", "<leader>fz", Snacks.picker.zoxide, { desc = "[Z]oxide" })
-- picker git keybinds
vim.keymap.set("n", "<leader>gB", Snacks.git.blame_line, { desc = "[G]it [B]lame" })
vim.keymap.set("n", "<leader>gb", Snacks.picker.git_branches, { desc = "[G]it [B]ranch" })
vim.keymap.set("n", "<leader>gl", Snacks.picker.git_log, { desc = "[G]it [L]og" })
vim.keymap.set("n", "<leader>gd", Snacks.picker.git_diff, { desc = "[G]it [D]iff" })
vim.keymap.set("n", "<leader>gt", Snacks.lazygit.open, { desc = "lazy[G]it [T]UI" })
-- setup toggles
Snacks.toggle.option("spell", { name = "spelling" }):map("<leader>cs")
Snacks.toggle.option("relativenumber", { name = "Relative Numbering" }):map("<leader>n")
Snacks.toggle.dim():map("<leader>d")
-- terminal keybinds
vim.keymap.set("n", "<leader>s", function()
Snacks.terminal.toggle(nil, { win = { position = "float" } })
end, { desc = "terminal" })
vim.keymap.set("t", "<esc>", function(self)
self.esc_timer = self.esc_timer or (vim.uv or vim.loop).new_timer()
if self.esc_timer:is_active() then
self.esc_timer:stop()
vim.cmd("stopinsert")
else
self.esc_timer:start(200, 0, function() end)
return "<esc>"
end
end, { expr = true, desc = "Double tap to escape terminal" })
-- setup rename autocmds
local prev = { new_name = "", old_name = "" } -- Prevents duplicate events
vim.api.nvim_create_autocmd("User", {
pattern = "OilActionsPost",
callback = function(event)
if event.data.actions.type == "move" then
Snacks.rename.on_rename_file(event.data.actions.src_url, event.data.actions.dest_url)
end
end,
})
end
require('lze').load {
{ import = "myLuaConf.plugins.treesitter", },
{ import = "myLuaConf.plugins.completion", },
{ import = "myLuaConf.plugins.gitsigns", },
{ import = "myLuaConf.plugins.lualine", },
{ import = "myLuaConf.plugins.which-key", },
{
"markdown-preview.nvim",
-- NOTE: for_cat is a custom handler that just sets enabled value for us,
-- based on result of nixCats('cat.name') and allows us to set a different default if we wish
-- it is defined in luaUtils template in lua/nixCatsUtils/lzUtils.lua
-- you could replace this with enabled = nixCats('cat.name') == true
-- if you didnt care to set a different default for when not using nix than the default you already set
for_cat = 'markdown',
cmd = { "MarkdownPreview", "MarkdownPreviewStop", "MarkdownPreviewToggle", },
ft = "markdown",
keys = {
{ "<leader>pmp", "<cmd>MarkdownPreview <CR>", mode = { "n" }, noremap = true, desc = "markdown preview" },
{ "<leader>pms", "<cmd>MarkdownPreviewStop <CR>", mode = { "n" }, noremap = true, desc = "markdown preview stop" },
{ "<leader>pmt", "<cmd>MarkdownPreviewToggle <CR>", mode = { "n" }, noremap = true, desc = "markdown preview toggle" },
},
before = function()
vim.g.mkdp_auto_close = 0
end,
},
{
"typst-preview.nvim",
for_cat = "lsp.typst",
ft = "typst",
cmd = { "TypstPreview", "TypstPreviewStop", "TypstPreviewToggle", },
keys = {
{ "<leader>ptp", "<cmd>TypstPreview <CR>", mode = { "n" }, noremap = true, desc = "typst preview" },
{ "<leader>pts", "<cmd>TypstPreviewStop <CR>", mode = { "n" }, noremap = true, desc = "typst preview stop" },
{ "<leader>ptt", "<cmd>TypstPreviewToggle <CR>", mode = { "n" }, noremap = true, desc = "typst preview toggle" },
},
after = function()
require('typst-preview').setup {}
end
},
{
"leap.nvim",
for_cat = 'always',
event = "DeferredUIEnter",
keys = {
{ "s", "<Plug>(leap)", mode = { "n", "x", "o", "v" }, noremap = true, desc = "leap to char sequence" }
},
},
{
"nvim-surround",
for_cat = 'always',
event = "DeferredUIEnter",
after = function()
require('nvim-surround').setup()
end,
},
{
"marks.nvim",
for_cat = "always",
after = function()
require('marks').setup({})
end
},
{
"venn.nvim",
for_cat = "always",
keys = {
{ "<leader>v", function() Toggle_venn() end, desc = "toggle diagram drawing" }
},
before = function()
-- venn.nvim: enable or disable keymappings
function _G.Toggle_venn()
local venn_enabled = vim.inspect(vim.b.venn_enabled)
if venn_enabled == "nil" then
vim.b.venn_enabled = true
vim.o.virtualedit = "all"
-- draw a line on HJKL keystokes
vim.api.nvim_buf_set_keymap(0, "n", "J", "<C-v>j:VBox<CR>", { noremap = true })
vim.api.nvim_buf_set_keymap(0, "n", "K", "<C-v>k:VBox<CR>", { noremap = true })
vim.api.nvim_buf_set_keymap(0, "n", "L", "<C-v>l:VBox<CR>", { noremap = true })
vim.api.nvim_buf_set_keymap(0, "n", "H", "<C-v>h:VBox<CR>", { noremap = true })
-- draw a box by pressing "f" with visual selection
vim.api.nvim_buf_set_keymap(0, "v", "f", ":VBox<CR>", { noremap = true })
else
vim.o.virtualedit = ""
vim.api.nvim_buf_del_keymap(0, "n", "J")
vim.api.nvim_buf_del_keymap(0, "n", "K")
vim.api.nvim_buf_del_keymap(0, "n", "L")
vim.api.nvim_buf_del_keymap(0, "n", "H")
vim.api.nvim_buf_del_keymap(0, "v", "f")
vim.b.venn_enabled = nil
end
end
end
},
{
"vim-startuptime",
for_cat = 'extra',
cmd = { "StartupTime" },
before = function(_)
vim.g.startuptime_event_width = 0
vim.g.startuptime_tries = 10
vim.g.startuptime_exe_path = nixCats.packageBinPath
end,
}
}

View file

@ -1,43 +0,0 @@
return {
"lualine.nvim",
for_cat = 'always',
-- cmd = { "" },
event = "DeferredUIEnter",
-- ft = "",
-- keys = "",
-- colorscheme = "",
after = function()
require('lualine').setup({
options = {
alwaysDivideMiddle = true,
icons_enabled = true,
component_separators = { left = '', right = '' },
section_separators = { left = '', right = '' },
},
inactive_sections = {
lualine_a = {},
lualine_b = {},
lualine_c = { "filename" },
lualine_x = { "filetype" },
lualine_y = {},
lualine_z = {},
},
sections = {
lualine_a = { "mode" },
lualine_b = { "branch", "diff", "diagnostics" },
lualine_c = { { "filename", path = 1 } },
lualine_x = { "encoding", "fileformat", "filetype" },
lualine_y = { "progress" },
lualine_z = { "location" },
},
tabline = {
lualine_a = { { "buffers", mode = 4 } },
lualine_b = {},
lualine_c = {},
lualine_x = {},
lualine_y = {},
lualine_z = { { "tabs", mode = 2 } }
},
})
end,
}

View file

@ -1,42 +0,0 @@
-- [[ Configure Treesitter ]]
-- See `:help nvim-treesitter`
return {
{
"nvim-treesitter",
for_cat = 'treesitter',
-- cmd = { "" },
event = "DeferredUIEnter",
-- ft = "",
-- keys = "",
-- colorscheme = "",
load = function(name)
vim.cmd.packadd(name)
vim.cmd.packadd("rainbow-delimiters.nvim")
end,
after = function(plugin)
-- [[ Configure Treesitter ]]
-- See `:help nvim-treesitter`
require('nvim-treesitter').setup {
highlight = { enable = true, },
indent = { enable = false, },
}
end,
},
{
"comment.nvim",
for_cat = 'treesitter',
after = function(plugin)
require('Comment').setup()
end,
},
{
"treesj",
for_cat = 'treesitter',
keys = { { "<leader>j", "<cmd>TSJToggle<CR>", mode = { "n" }, desc = "Treesitter join" }, },
after = function(_)
require("treesj").setup({
use_default_keymaps = false
})
end
},
}

View file

@ -1,21 +0,0 @@
return {
"which-key.nvim",
for_cat = 'always',
after = function()
require('which-key').setup({
})
require('which-key').add {
{ "<leader>g", group = "[g]it" },
{ "<leader>z", group = "[z]ettelkasten" },
{ "<leader>gt", group = "[t]oggle" },
{ "<leader>p", group = "[p]review" },
{ "<leader>pt", group = "[p]review [t]ypst" },
{ "<leader>pm", group = "[p]review [m]arkdown" },
{ "<leader>f", group = "[f]ind" },
{ "<leader>t", group = "[t]ree" },
{ "<leader>c", group = "[c]heck" },
{ "<leader>l", group = "[l]sp" },
{ "<leader>lw", group = "[l]sp [w]orkspace" },
}
end,
}

View file

@ -1,40 +0,0 @@
--[[
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

View file

@ -1,129 +0,0 @@
--[[
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

View file

@ -1,36 +0,0 @@
--[[
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

View file

@ -1,4 +1,4 @@
-- NOTE: These 2 need to be set up before any plugins are loaded.
-- NOTE: These 2 should be set up before any plugins with keybinds are loaded.
vim.g.mapleader = ';'
vim.g.maplocalleader = ';'
@ -6,9 +6,13 @@ vim.g.maplocalleader = ';'
-- See `:help vim.o`
-- NOTE: You can change these options as you wish!
-- allow .nvim.lua in current dir and parents (project config)
vim.o.exrc = false -- can be toggled off in that file to stop it from searching further
-- Sets how neovim will display certain whitespace characters in the editor.
-- See `:help 'list'`
-- and `:help 'listchars'`
-- and `:help 'showbreak'`
vim.opt.list = true
vim.opt.listchars = { eol = "", extends = "", nbsp = "", precedes = "", tab = ">-", trail = "" }
vim.opt.showbreak = "";
@ -29,6 +33,7 @@ vim.opt.scrolloff = 10
-- Make line numbers default
vim.opt.number = true
vim.opt.numberwidth = 3
-- Enable mouse mode
vim.opt.mouse = 'a'
@ -40,10 +45,6 @@ vim.opt.wrapmargin = 0
-- get nice visual guides for 80, 100, and 120 cols.
vim.opt.colorcolumn = { "90", "100", "120", }
-- add line numbers
vim.opt.number = true
vim.opt.numberwidth = 3
-- Indent
vim.opt.smarttab = true
vim.opt.expandtab = true
@ -95,22 +96,6 @@ vim.api.nvim_create_autocmd('TextYankPost', {
vim.g.netrw_liststyle = 0
vim.g.netrw_banner = 0
-- [[ Basic Keymaps ]]
-- make quick system clipboard opts easier
vim.keymap.set({ 'n', 'v', 'x' }, '<leader>p', '"+p', { noremap = true, silent = true, desc = 'Paste from clipboard' })
vim.keymap.set({ "v", "x", "n" }, '<leader>y', '"+y', { noremap = true, silent = true, desc = 'Yank to clipboard' })
vim.keymap.set({ "n", "v", "x" }, '<leader>Y', '"+yy', { noremap = true, silent = true, desc = 'Yank line to clipboard' })
vim.keymap.set('i', '<C-p>', '<C-r><C-p>+',
{ noremap = true, silent = true, desc = 'Paste from clipboard from within insert mode' })
-- 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', '<leader>d', vim.diagnostic.open_float, { desc = 'Open floating diagnostic message' })
-- moving between splits
vim.keymap.set('n', '<C-h>', '<C-w>h', { desc = 'move to right split' })
vim.keymap.set('n', '<C-j>', '<C-w>j', { desc = 'move to below split' })
vim.keymap.set('n', '<C-k>', '<C-w>k', { desc = 'move to above split' })
vim.keymap.set('n', '<C-l>', '<C-w>l', { desc = 'move to left split' })
vim.g.netrw_liststyle=0
vim.g.netrw_banner=0

743
lua/plugins.lua Normal file
View file

@ -0,0 +1,743 @@
-- NOTE: You will likely want to break this up into more files.
-- You can call this more than once.
-- You can also include other files from within the specs via an `import` spec.
-- see https://github.com/BirdeeHub/lze?tab=readme-ov-file#structuring-your-plugins
nixInfo.lze.load {
{
-- lze specs need a name
"trigger_colorscheme",
-- lazy loaded colorscheme.
-- This means you will need to add the colorscheme you want to lze sometime before VimEnter is done
event = "VimEnter",
-- Also, lze can load more than just plugins.
-- The default load field contains vim.cmd.packadd
-- Here we override it to schedule when our colorscheme is loaded
load = function(_name)
-- schedule so it runs after VimEnter
vim.schedule(function()
vim.cmd.colorscheme(nixInfo("onedark_dark", "settings", "colorscheme"))
vim.schedule(function()
-- I like this color. Use vim.schedule again to set it after the colorscheme is finished
vim.cmd([[hi LineNr guifg=#bb9af7]])
end)
end)
end
},
{
-- NOTE: view these names in the info plugin!
-- :lua nixInfo.lze.debug.display(nixInfo.plugins)
-- The display function is from lzextras
"onedarkpro.nvim",
auto_enable = true, -- <- auto enable is useful here
colorscheme = { "onedark", "onedark_dark", "onedark_vivid", "onelight" },
},
{
"vim-moonfly-colors",
auto_enable = true,
colorscheme = "moonfly",
},
{
"snacks.nvim",
auto_enable = true,
-- snacks makes a global, and then lazily loads itself
lazy = false,
-- priority only affects startup plugins
-- unless otherwise specified by a particular handler
priority = 1000,
after = function(plugin)
-- I also like this color
vim.api.nvim_set_hl(0, "MySnacksIndent", { fg = "#32a88f" })
require('snacks').setup({
explorer = { replace_netrw = true, },
picker = {
sources = {
explorer = {
auto_close = true,
},
},
},
git = {},
terminal = {},
scope = {},
indent = {
scope = {
hl = 'MySnacksIndent',
},
chunk = {
-- enabled = true,
hl = 'MySnacksIndent',
}
},
statuscolumn = {
left = { "mark", "git" }, -- priority of signs on the left (high to low)
right = { "sign", "fold" }, -- priority of signs on the right (high to low)
folds = {
open = false, -- show open fold icons
git_hl = false, -- use Git Signs hl for fold icons
},
git = {
-- patterns to match Git signs
patterns = { "GitSign", "MiniDiffSign" },
},
refresh = 50, -- refresh at most every 50ms
},
-- make sure lazygit always reopens the correct program
-- hopefully this can be removed one day
lazygit = {
config = {
os = {
editPreset = "nvim-remote",
edit = vim.v.progpath .. [=[ --server "$NVIM" --remote-send '<cmd>lua nixInfo.lazygit_fix({{filename}})<CR>']=],
editAtLine = vim.v.progpath .. [=[ --server "$NVIM" --remote-send '<cmd>lua nixInfo.lazygit_fix({{filename}}, {{line}})<CR>']=],
openDirInEditor = vim.v.progpath .. [=[ --server "$NVIM" --remote-send '<cmd>lua nixInfo.lazygit_fix({{dir}})<CR>']=],
-- this one isnt a remote command, make sure it gets our config regardless of if we name it nvim or not
editAtLineAndWait = nixInfo(vim.v.progpath, "progpath") .. " +{{line}} {{filename}}",
},
},
},
})
-- Handle the backend of those remote commands.
-- hopefully this can be removed one day
nixInfo.lazygit_fix = function(path, line)
local prev = vim.fn.bufnr("#")
local prev_win = vim.fn.bufwinid(prev)
vim.api.nvim_feedkeys("q", "n", false)
if line then
vim.api.nvim_buf_call(prev, function()
vim.cmd.edit(path)
local buf = vim.api.nvim_get_current_buf()
vim.schedule(function()
if buf then
vim.api.nvim_win_set_buf(prev_win, buf)
vim.api.nvim_win_set_cursor(0, { line or 0, 0})
end
end)
end)
else
vim.api.nvim_buf_call(prev, function()
vim.cmd.edit(path)
local buf = vim.api.nvim_get_current_buf()
vim.schedule(function()
if buf then
vim.api.nvim_win_set_buf(prev_win, buf)
end
end)
end)
end
end
-- NOTE: we aren't loading this lazily, and the keybinds already are so it is fine to just set these here
vim.keymap.set("n", "-", function() Snacks.explorer.open() end, { desc = 'Snacks file explorer' })
vim.keymap.set("n", "<c-\\>", function() Snacks.terminal.open() end, { desc = 'Snacks Terminal' })
vim.keymap.set("n", "<leader>_", function() Snacks.lazygit.open() end, { desc = 'Snacks LazyGit' })
vim.keymap.set('n', "<leader>sf", function() Snacks.picker.smart() end, { desc = "Smart Find Files" })
vim.keymap.set('n', "<leader><leader>s", function() Snacks.picker.buffers() end, { desc = "Search Buffers" })
-- find
vim.keymap.set('n', "<leader>ff", function() Snacks.picker.files() end, { desc = "Find Files" })
vim.keymap.set('n', "<leader>fg", function() Snacks.picker.git_files() end, { desc = "Find Git Files" })
-- Grep
vim.keymap.set('n', "<leader>sb", function() Snacks.picker.lines() end, { desc = "Buffer Lines" })
vim.keymap.set('n', "<leader>sB", function() Snacks.picker.grep_buffers() end, { desc = "Grep Open Buffers" })
vim.keymap.set('n', "<leader>sg", function() Snacks.picker.grep() end, { desc = "Grep" })
vim.keymap.set({ "n", "x" }, "<leader>sw", function() Snacks.picker.grep_word() end, { desc = "Visual selection or ord" })
-- search
vim.keymap.set('n', "<leader>sb", function() Snacks.picker.lines() end, { desc = "Buffer Lines" })
vim.keymap.set('n', "<leader>sd", function() Snacks.picker.diagnostics() end, { desc = "Diagnostics" })
vim.keymap.set('n', "<leader>sD", function() Snacks.picker.diagnostics_buffer() end, { desc = "Buffer Diagnostics" })
vim.keymap.set('n', "<leader>sh", function() Snacks.picker.help() end, { desc = "Help Pages" })
vim.keymap.set('n', "<leader>sj", function() Snacks.picker.jumps() end, { desc = "Jumps" })
vim.keymap.set('n', "<leader>sk", function() Snacks.picker.keymaps() end, { desc = "Keymaps" })
vim.keymap.set('n', "<leader>sl", function() Snacks.picker.loclist() end, { desc = "Location List" })
vim.keymap.set('n', "<leader>sm", function() Snacks.picker.marks() end, { desc = "Marks" })
vim.keymap.set('n', "<leader>sM", function() Snacks.picker.man() end, { desc = "Man Pages" })
vim.keymap.set('n', "<leader>sq", function() Snacks.picker.qflist() end, { desc = "Quickfix List" })
vim.keymap.set('n', "<leader>sR", function() Snacks.picker.resume() end, { desc = "Resume" })
vim.keymap.set('n', "<leader>su", function() Snacks.picker.undo() end, { desc = "Undo History" })
end
},
{
"nvim-lspconfig",
auto_enable = true,
-- NOTE: define a function for lsp,
-- and it will run for all specs with type(plugin.lsp) == table
-- when their filetype trigger loads them
lsp = function(plugin)
vim.lsp.config(plugin.name, plugin.lsp or {})
vim.lsp.enable(plugin.name)
end,
-- set up our on_attach function once before the spec loads
before = function(_)
vim.lsp.config('*', {
on_attach = function(_, bufnr)
-- we create a function that lets us more easily define mappings specific
-- for LSP related items. It sets the mode, buffer and description for us each time.
local nmap = function(keys, func, desc)
if desc then
desc = 'LSP: ' .. desc
end
vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc })
end
nmap('<leader>rn', vim.lsp.buf.rename, '[R]e[n]ame')
nmap('<leader>ca', vim.lsp.buf.code_action, '[C]ode [A]ction')
nmap('gd', vim.lsp.buf.definition, '[G]oto [D]efinition')
nmap('<leader>D', vim.lsp.buf.type_definition, 'Type [D]efinition')
nmap('gr', function() Snacks.picker.lsp_references() end, '[G]oto [R]eferences')
nmap('gI', function() Snacks.picker.lsp_implementations() end, '[G]oto [I]mplementation')
nmap('<leader>ds', function() Snacks.picker.lsp_symbols() end, '[D]ocument [S]ymbols')
nmap('<leader>ws', function() Snacks.picker.lsp_workspace_symbols() end, '[W]orkspace [S]ymbols')
-- See `:help K` for why this keymap
nmap('K', vim.lsp.buf.hover, 'Hover Documentation')
nmap('<C-k>', vim.lsp.buf.signature_help, 'Signature Documentation')
-- Lesser used LSP functionality
nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
nmap('<leader>wa', vim.lsp.buf.add_workspace_folder, '[W]orkspace [A]dd Folder')
nmap('<leader>wr', vim.lsp.buf.remove_workspace_folder, '[W]orkspace [R]emove Folder')
nmap('<leader>wl', function()
print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
end, '[W]orkspace [L]ist Folders')
-- Create a command `:Format` local to the LSP buffer
vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_)
vim.lsp.buf.format()
end, { desc = 'Format current buffer with LSP' })
end
})
end,
},
{
"mason.nvim",
enabled = not nixInfo.isNix,
priority = 100, -- <- run lsp hook before lspconfig's hook
on_plugin = { "nvim-lspconfig" },
lsp = function(plugin)
vim.cmd.MasonInstall(plugin.name)
end,
},
{
-- lazydev makes your lua lsp load only the relevant definitions for a file.
-- It also gives us a nice way to correlate globals we create with files.
"lazydev.nvim",
auto_enable = true,
cmd = { "LazyDev" },
ft = "lua",
after = function(_)
require('lazydev').setup({
library = {
{ words = { "nixInfo%.lze" }, path = nixInfo("lze", "plugins", "start", "lze") .. '/lua', },
{ words = { "nixInfo%.lze" }, path = nixInfo("lzextras", "plugins", "start", "lzextras") .. '/lua' },
},
})
end,
},
{
-- name of the lsp
"lua_ls",
for_cat = "lua",
-- provide a table containing filetypes,
-- and then whatever your functions defined in the function type specs expect.
-- in our case, it just expects the normal lspconfig setup options,
-- but with a default on_attach and capabilities
lsp = {
-- if you provide the filetypes it doesn't ask lspconfig for the filetypes
-- (meaning it doesn't call the callback function we defined in the main init.lua)
filetypes = { 'lua' },
settings = {
Lua = {
signatureHelp = { enabled = true },
diagnostics = {
globals = { "nixInfo", "vim", },
disable = { 'missing-fields' },
},
},
},
},
-- also these are regular specs and you can use before and after and all the other normal fields
},
{
"nixd",
enabled = nixInfo.isNix, -- mason doesn't have nixd
for_cat = "nix",
lsp = {
filetypes = { "nix" },
settings = {
nixd = {
nixpkgs = {
expr = [[import <nixpkgs> {}]],
},
options = {
},
formatting = {
command = { "alejandra" }
},
diagnostic = {
suppress = {
"sema-escaping-with"
}
}
}
},
},
},
{
"nvim-treesitter",
lazy = false,
auto_enable = true,
after = function(plugin)
---@param buf integer
---@param language string
local function treesitter_try_attach(buf, language)
-- check if parser exists and load it
if not vim.treesitter.language.add(language) then
return false
end
-- enables syntax highlighting and other treesitter features
vim.treesitter.start(buf, language)
-- enables treesitter based folds
vim.wo.foldexpr = "v:lua.vim.treesitter.foldexpr()"
vim.wo.foldmethod = "expr"
-- ensure folds are open to begin with
vim.o.foldlevel = 99
-- enables treesitter based indentation
vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
return true
end
local installable_parsers = require("nvim-treesitter").get_available()
vim.api.nvim_create_autocmd("FileType", {
callback = function(args)
local buf, filetype = args.buf, args.match
local language = vim.treesitter.language.get_lang(filetype)
if not language then
return
end
if not treesitter_try_attach(buf,language) then
if vim.tbl_contains(installable_parsers, language) then
-- not already installed, so try to install them via nvim-treesitter if possible
require("nvim-treesitter").install(language):await(function()
treesitter_try_attach(buf, language)
end)
end
end
end,
})
end,
},
{
"nvim-treesitter-textobjects",
auto_enable = true,
lazy = false,
before = function(plugin)
-- https://github.com/nvim-treesitter/nvim-treesitter-textobjects/tree/main?tab=readme-ov-file#using-a-package-manager
-- Disable entire built-in ftplugin mappings to avoid conflicts.
-- See https://github.com/neovim/neovim/tree/master/runtime/ftplugin for built-in ftplugins.
vim.g.no_plugin_maps = true
-- Or, disable per filetype (add as you like)
-- vim.g.no_python_maps = true
-- vim.g.no_ruby_maps = true
-- vim.g.no_rust_maps = true
-- vim.g.no_go_maps = true
end,
after = function(plugin)
require("nvim-treesitter-textobjects").setup {
select = {
-- Automatically jump forward to textobj, similar to targets.vim
lookahead = true,
-- You can choose the select mode (default is charwise 'v')
--
-- Can also be a function which gets passed a table with the keys
-- * query_string: eg '@function.inner'
-- * method: eg 'v' or 'o'
-- and should return the mode ('v', 'V', or '<c-v>') or a table
-- mapping query_strings to modes.
selection_modes = {
['@parameter.outer'] = 'v', -- charwise
['@function.outer'] = 'V', -- linewise
-- ['@class.outer'] = '<c-v>', -- blockwise
},
-- If you set this to `true` (default is `false`) then any textobject is
-- extended to include preceding or succeeding whitespace. Succeeding
-- whitespace has priority in order to act similarly to eg the built-in
-- `ap`.
--
-- Can also be a function which gets passed a table with the keys
-- * query_string: eg '@function.inner'
-- * selection_mode: eg 'v'
-- and should return true of false
include_surrounding_whitespace = false,
},
}
-- keymaps
-- You can use the capture groups defined in `textobjects.scm`
vim.keymap.set({ "x", "o" }, "am", function()
require "nvim-treesitter-textobjects.select".select_textobject("@function.outer", "textobjects")
end)
vim.keymap.set({ "x", "o" }, "im", function()
require "nvim-treesitter-textobjects.select".select_textobject("@function.inner", "textobjects")
end)
vim.keymap.set({ "x", "o" }, "ac", function()
require "nvim-treesitter-textobjects.select".select_textobject("@class.outer", "textobjects")
end)
vim.keymap.set({ "x", "o" }, "ic", function()
require "nvim-treesitter-textobjects.select".select_textobject("@class.inner", "textobjects")
end)
-- You can also use captures from other query groups like `locals.scm`
vim.keymap.set({ "x", "o" }, "as", function()
require "nvim-treesitter-textobjects.select".select_textobject("@local.scope", "locals")
end)
-- NOTE: for more textobjects options, see the following link.
-- This template is using the new `main` branch of the repo.
-- https://github.com/nvim-treesitter/nvim-treesitter-textobjects/tree/main
end,
},
{
"conform.nvim",
auto_enable = true,
-- cmd = { "" },
-- event = "",
-- ft = "",
keys = {
{ "<leader>FF", desc = "[F]ormat [F]ile" },
},
-- colorscheme = "",
after = function (plugin)
local conform = require("conform")
conform.setup({
formatters_by_ft = {
-- NOTE: download some formatters
-- and configure them here
lua = nixInfo(nil, "settings", "cats", "lua") and { "stylua" } or nil,
-- go = { "gofmt", "golint" },
-- templ = { "templ" },
-- Conform will run multiple formatters sequentially
-- python = { "isort", "black" },
-- Use a sub-list to run only the first available formatter
-- javascript = { { "prettierd", "prettier" } },
},
})
vim.keymap.set({ "n", "v" }, "<leader>FF", function()
conform.format({
lsp_fallback = true,
async = false,
timeout_ms = 1000,
})
end, { desc = "[F]ormat [F]ile" })
end,
},
{
"nvim-lint",
auto_enable = true,
-- cmd = { "" },
event = "FileType",
-- ft = "",
-- keys = "",
-- colorscheme = "",
after = function (plugin)
require('lint').linters_by_ft = {
-- NOTE: download some linters
-- and configure them here
-- markdown = {'vale',},
-- javascript = { 'eslint' },
-- typescript = { 'eslint' },
}
vim.api.nvim_create_autocmd({ "BufWritePost" }, {
callback = function()
require("lint").try_lint()
end,
})
end,
},
{
"cmp-cmdline",
auto_enable = true,
on_plugin = { "blink.cmp" },
load = nixInfo.lze.loaders.with_after,
},
{
"blink.compat",
auto_enable = true,
dep_of = { "cmp-cmdline" },
},
{
"colorful-menu.nvim",
auto_enable = true,
on_plugin = { "blink.cmp" },
},
{
"blink.cmp",
auto_enable = true,
event = "DeferredUIEnter",
after = function (_)
require("blink.cmp").setup({
-- 'default' (recommended) for mappings similar to built-in completions (C-y to accept)
-- See :h blink-cmp-config-keymap for configuring keymaps
keymap = {
preset = 'default',
},
cmdline = {
enabled = true,
completion = {
menu = {
auto_show = true,
},
},
sources = function()
local type = vim.fn.getcmdtype()
-- Search forward and backward
if type == '/' or type == '?' then return { 'buffer' } end
-- Commands
if type == ':' or type == '@' then return { 'cmdline', 'cmp_cmdline' } end
return {}
end,
},
fuzzy = {
sorts = {
'exact',
-- defaults
'score',
'sort_text',
},
},
signature = {
enabled = true,
window = {
show_documentation = true,
},
},
completion = {
menu = {
draw = {
treesitter = { 'lsp' },
components = {
label = {
text = function(ctx)
return require("colorful-menu").blink_components_text(ctx)
end,
highlight = function(ctx)
return require("colorful-menu").blink_components_highlight(ctx)
end,
},
},
},
},
documentation = {
auto_show = true,
},
},
sources = {
default = { 'lsp', 'path', 'buffer', 'omni' },
providers = {
path = {
score_offset = 50,
},
lsp = {
score_offset = 40,
},
cmp_cmdline = {
name = 'cmp_cmdline',
module = 'blink.compat.source',
score_offset = -100,
opts = {
cmp_name = 'cmdline',
},
},
},
},
})
end,
},
{
"nvim-surround",
auto_enable = true,
event = "DeferredUIEnter",
-- keys = "",
after = function(plugin)
require('nvim-surround').setup()
end,
},
{
"vim-startuptime",
auto_enable = true,
cmd = { "StartupTime" },
before = function(_)
vim.g.startuptime_event_width = 0
vim.g.startuptime_tries = 10
vim.g.startuptime_exe_path = nixInfo(vim.v.progpath, "progpath")
end,
},
{
"fidget.nvim",
auto_enable = true,
event = "DeferredUIEnter",
-- keys = "",
after = function(plugin)
require('fidget').setup({})
end,
},
{
"lualine.nvim",
auto_enable = true,
-- cmd = { "" },
event = "DeferredUIEnter",
-- ft = "",
-- keys = "",
-- colorscheme = "",
after = function (plugin)
require('lualine').setup({
options = {
icons_enabled = false,
theme = nixInfo("onedark_dark", "settings", "colorscheme"),
component_separators = '|',
section_separators = '',
},
sections = {
lualine_c = {
{ 'filename', path = 1, status = true, },
},
},
inactive_sections = {
lualine_b = {
{ 'filename', path = 3, status = true, },
},
lualine_x = {'filetype'},
},
tabline = {
lualine_a = { 'buffers' },
-- if you use lualine-lsp-progress, I have mine here instead of fidget
-- lualine_b = { 'lsp_progress', },
lualine_z = { 'tabs' }
},
})
end,
},
{
"gitsigns.nvim",
auto_enable = true,
event = "DeferredUIEnter",
-- cmd = { "" },
-- ft = "",
-- keys = "",
-- colorscheme = "",
after = function (plugin)
require('gitsigns').setup({
-- See `:help gitsigns.txt`
signs = {
add = { text = '+' },
change = { text = '~' },
delete = { text = '_' },
topdelete = { text = '' },
changedelete = { text = '~' },
},
on_attach = function(bufnr)
local gs = package.loaded.gitsigns
local function map(mode, l, r, opts)
opts = opts or {}
opts.buffer = bufnr
vim.keymap.set(mode, l, r, opts)
end
-- Navigation
map({ 'n', 'v' }, ']c', function()
if vim.wo.diff then
return ']c'
end
vim.schedule(function()
gs.next_hunk()
end)
return '<Ignore>'
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 '<Ignore>'
end, { expr = true, desc = 'Jump to previous hunk' })
-- Actions
-- visual mode
map('v', '<leader>hs', function()
gs.stage_hunk { vim.fn.line '.', vim.fn.line 'v' }
end, { desc = 'stage git hunk' })
map('v', '<leader>hr', function()
gs.reset_hunk { vim.fn.line '.', vim.fn.line 'v' }
end, { desc = 'reset git hunk' })
-- normal mode
map('n', '<leader>gs', gs.stage_hunk, { desc = 'git stage hunk' })
map('n', '<leader>gr', gs.reset_hunk, { desc = 'git reset hunk' })
map('n', '<leader>gS', gs.stage_buffer, { desc = 'git Stage buffer' })
map('n', '<leader>gu', gs.undo_stage_hunk, { desc = 'undo stage hunk' })
map('n', '<leader>gR', gs.reset_buffer, { desc = 'git Reset buffer' })
map('n', '<leader>gp', gs.preview_hunk, { desc = 'preview git hunk' })
map('n', '<leader>gb', function()
gs.blame_line { full = false }
end, { desc = 'git blame line' })
map('n', '<leader>gd', gs.diffthis, { desc = 'git diff against index' })
map('n', '<leader>gD', function()
gs.diffthis '~'
end, { desc = 'git diff against last commit' })
-- Toggles
map('n', '<leader>gtb', gs.toggle_current_line_blame, { desc = 'toggle git blame line' })
map('n', '<leader>gtd', gs.toggle_deleted, { desc = 'toggle git show deleted' })
-- Text object
map({ 'o', 'x' }, 'ih', ':<C-U>Gitsigns select_hunk<CR>', { desc = 'select git hunk' })
end,
})
vim.cmd([[hi GitSignsAdd guifg=#04de21]])
vim.cmd([[hi GitSignsChange guifg=#83fce6]])
vim.cmd([[hi GitSignsDelete guifg=#fa2525]])
end,
},
{
"which-key.nvim",
auto_enable = true,
-- cmd = { "" },
event = "DeferredUIEnter",
-- ft = "",
-- keys = "",
-- colorscheme = "",
after = function (plugin)
require('which-key').setup({
})
require('which-key').add {
{ "<leader><leader>", group = "buffer commands" },
{ "<leader><leader>_", hidden = true },
{ "<leader>c", group = "[c]ode" },
{ "<leader>c_", hidden = true },
{ "<leader>d", group = "[d]ocument" },
{ "<leader>d_", hidden = true },
{ "<leader>g", group = "[g]it" },
{ "<leader>g_", hidden = true },
{ "<leader>m", group = "[m]arkdown" },
{ "<leader>m_", hidden = true },
{ "<leader>r", group = "[r]ename" },
{ "<leader>r_", hidden = true },
{ "<leader>s", group = "[s]earch" },
{ "<leader>s_", hidden = true },
{ "<leader>t", group = "[t]oggles" },
{ "<leader>t_", hidden = true },
{ "<leader>w", group = "[w]orkspace" },
{ "<leader>w_", hidden = true },
}
end,
},
}

284
module.nix Normal file
View file

@ -0,0 +1,284 @@
inputs: {
config,
wlib,
lib,
pkgs,
...
}: {
imports = [wlib.wrapperModules.neovim];
# NOTE: see the tips and tricks section or the bottom of this file + flake inputs to understand this value
options.nvim-lib.neovimPlugins = lib.mkOption {
readOnly = true;
type = lib.types.attrsOf wlib.types.stringable;
# Makes plugins autobuilt from our inputs available with
# `config.nvim-lib.neovimPlugins.<name_without_prefix>`
default = config.nvim-lib.pluginsFromPrefix "plugins-" inputs;
};
# choose a directory for your config.
config.settings.config_directory = ./.;
# you can also use an impure path!
# config.settings.config_directory = lib.generators.mkLuaInline "vim.fn.stdpath('config')";
# config.settings.config_directory = "/home/<USER>/.config/nvim";
# If you do that, it will not be provisioned by nix, but it will have normal reload for quick edits!
# If you want to install multiple neovim derivations via home.packages or environment.systemPackages
# in order to prevent path collisions:
# set this to true:
# config.settings.dont_link = true;
# and make sure these dont share values:
# config.binName = "nvim";
# config.settings.aliases = [ ];
# To add a wrapped $out/bin/${config.binName}-neovide to the resulting neovim derivation
# config.hosts.neovide.nvim-host.enable = true;
# You can declare your own options!
options.settings.colorscheme = lib.mkOption {
type = lib.types.str;
default = "onedark_dark";
};
options.settings.minimal = lib.mkOption {
type = lib.types.bool;
default = false;
};
config.settings.colorscheme = "gruvbox"; # <- just demonstrating that it is an option
# and grab it in lua with `require(vim.g.nix_info_plugin_name)("onedark", "settings", "colorscheme") == "moonfly"`
config.specs.colorscheme = {
lazy = true;
enable = lib.mkIf config.settings.minimal (lib.mkDefault true);
data = builtins.getAttr config.settings.colorscheme (
with pkgs.vimPlugins; {
"onedark_dark" = onedarkpro-nvim;
"onedark_vivid" = onedarkpro-nvim;
"onedark" = onedarkpro-nvim;
"onelight" = onedarkpro-nvim;
"moonfly" = vim-moonfly-colors;
"catppuccin" = catppuccin-nvim;
"tokyonight" = tokyonight-nvim;
"nord" = nord-nvim;
"gruvbox" = gruvbox-nvim;
}
);
};
config.specs.lze = {
enable = lib.mkIf config.settings.minimal (lib.mkDefault true);
data = [
config.nvim-lib.neovimPlugins.lze
config.nvim-lib.neovimPlugins.lzextras
];
};
config.specs.general = {
# this would ensure any config included from nix in here will be ran after any provided by the `lze` spec
# If we provided any from within either spec, anyway
after = ["lze"];
enable = lib.mkIf config.settings.minimal (lib.mkDefault true);
extraPackages = with pkgs; [
ripgrep
fd
fzf
zoxide
git
lazygit
tree-sitter
];
# here we chose a DAL of plugins, but we can also pass a single plugin, or null
data = with pkgs.vimPlugins; [
snacks-nvim
lualine-nvim
plenary-nvim
oil-nvim
nvim-web-devicons
nvim-numbertoggle
lualine-nvim
marks-nvim
];
};
config.specs.lazy = {
after = ["lze"];
enable = lib.mkIf config.settings.minimal (lib.mkDefault true);
lazy = true;
data = with pkgs.vimPlugins; [
gitsigns-nvim
nvim-surround
treesj
which-key-nvim
todo-comments-nvim
comment-nvim
rainbow-delimiters-nvim
nvim-treesitter.withAllGrammars
];
};
config.specs.completion = {
after = ["lze"];
lazy = true;
enable = lib.mkIf config.settings.minimal false;
data = with pkgs.vimPlugins; [
luasnip
friendly-snippets
cmp-cmdline
blink-cmp
blink-emoji-nvim
blink-compat
colorful-menu-nvim
];
};
config.specs.markdown = {
after = ["general" "lazy"];
enable = lib.mkIf config.settings.minimal false;
lazy = true;
data = with pkgs.vimPlugins; [
markdown-preview-nvim
];
extraPackages = with pkgs; [
mermaid-cli
imagemagick
texliveSmall
];
};
config.specs.lsp = {
enable = lib.mkIf config.settings.minimal false;
after = ["general" "lazy"];
lazy = true;
data = with pkgs.vimPlugins; [
trouble-nvim
lualine-lsp-progress
nvim-lspconfig
];
};
config.specs.zk = {
after = ["general" "lazy"];
data = with pkgs.vimPlugins; [
zk-nvim
];
extraPackages = with pkgs; [
zk
];
};
config.specs.typst = {
name = "typst";
after = ["general" "lazy"];
data = with pkgs.vimPlugins; [
typst-preview-nvim
];
extraPackages = with pkgs; [
typst
tinymist
];
};
config.specs.nix = {
name = "nix";
after = ["general" "lazy"];
data = null;
extraPackages = with pkgs; [
nixd
alejandra
];
};
config.specs.lua = {
name = "lua";
after = ["general" "lazy"];
data = with pkgs.vimPlugins; [
lazydev-nvim
];
extraPackages = with pkgs; [
lua-language-server
stylua
];
};
config.specs.rust = {
name = "rust";
after = ["general" "lazy"];
data = with pkgs.vimPlugins; [
rustaceanvim
];
extraPackages = with pkgs; [
rust-analyzer
cargo
];
};
config.specs.python = {
name = "python";
after = ["general" "lazy"];
data = null;
extraPackages = with pkgs; [
ty
ruff
];
};
config.specs.C = {
name = "C";
after = ["general" "lazy"];
data = null;
extraPackages = with pkgs; [
libclang
];
};
config.specs.bash = {
name = "bash";
after = ["general" "lazy"];
lazy = true;
data = null;
extraPackages = with pkgs; [
shellcheck
bash-language-server
];
};
config.specMods = lib.mkMerge [
{
options.extraPackages = lib.mkOption {
type = lib.types.listOf wlib.types.stringable;
default = [];
description = "a extraPackages spec field to put packages to suffix to the PATH";
};
}
# Makes enable be false by default if minimal is set.
(lib.mkIf config.settings.minimal (
{parentSpec, ...}: {
config.enable = lib.mkOverride 1400 (parentSpec.enable or false); # 1400 is 100 higher than mkOptionDefault (1500)
}
))
];
config.extraPackages = config.specCollect (acc: v: acc ++ (v.extraPackages or [])) [];
# Inform our lua of which top level specs are enabled
options.settings.cats = lib.mkOption {
readOnly = true;
type = lib.types.attrsOf lib.types.bool;
default = builtins.mapAttrs (_: v: v.enable) config.specs;
};
# build plugins from inputs set
options.nvim-lib.pluginsFromPrefix = lib.mkOption {
type = lib.types.raw;
readOnly = true;
default = prefix: inputs:
lib.pipe inputs [
builtins.attrNames
(builtins.filter (s: lib.hasPrefix prefix s))
(map (
input: let
name = lib.removePrefix prefix input;
in {
inherit name;
value = config.nvim-lib.mkPlugin name inputs.${input};
}
))
builtins.listToAttrs
];
};
}