Merge pull request #245 from NotAShelf/new-tree-structure

treewide: restructure neovim-flake tree
This commit is contained in:
NotAShelf 2024-04-14 12:09:44 +00:00 committed by GitHub
commit b1d6ec75ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
272 changed files with 2428 additions and 2350 deletions

View File

@ -18,18 +18,18 @@ inputs: let
};
mainConfig = isMaximal: {
config = {
vim = {
viAlias = true;
vimAlias = true;
debugMode = {
enable = false;
level = 20;
logFile = "/tmp/nvim.log";
};
config.vim = {
viAlias = true;
vimAlias = true;
debugMode = {
enable = false;
level = 20;
logFile = "/tmp/nvim.log";
};
vim.lsp = {
spellcheck.vim-dirtytalk.enable = true;
lsp = {
formatOnSave = true;
lspkind.enable = false;
lightbulb.enable = true;
@ -41,14 +41,14 @@ inputs: let
nvim-docs-view.enable = isMaximal;
};
vim.debugger = {
debugger = {
nvim-dap = {
enable = true;
ui.enable = true;
};
};
vim.languages = {
languages = {
enableLSP = true;
enableFormat = true;
enableTreesitter = true;
@ -81,7 +81,7 @@ inputs: let
};
};
vim.visuals = {
visuals = {
enable = true;
nvimWebDevicons.enable = true;
scrollBar.enable = true;
@ -105,70 +105,71 @@ inputs: let
};
};
vim.statusline = {
statusline = {
lualine = {
enable = true;
theme = "catppuccin";
};
};
vim.theme = {
theme = {
enable = true;
name = "catppuccin";
style = "mocha";
transparent = false;
};
vim.autopairs.enable = true;
vim.autocomplete = {
autopairs.enable = true;
autocomplete = {
enable = true;
type = "nvim-cmp";
};
vim.filetree = {
filetree = {
nvimTree = {
enable = true;
};
};
vim.tabline = {
tabline = {
nvimBufferline.enable = true;
};
vim.treesitter.context.enable = true;
treesitter.context.enable = true;
vim.binds = {
binds = {
whichKey.enable = true;
cheatsheet.enable = true;
};
vim.telescope.enable = true;
telescope.enable = true;
vim.git = {
git = {
enable = true;
gitsigns.enable = true;
gitsigns.codeActions = false; # throws an annoying debug message
};
vim.minimap = {
minimap = {
minimap-vim.enable = false;
codewindow.enable = isMaximal; # lighter, faster, and uses lua for configuration
};
vim.dashboard = {
dashboard = {
dashboard-nvim.enable = false;
alpha.enable = isMaximal;
};
vim.notify = {
notify = {
nvim-notify.enable = true;
};
vim.projects = {
projects = {
project-nvim.enable = isMaximal;
};
vim.utility = {
utility = {
ccc.enable = isMaximal;
vim-wakatime.enable = isMaximal;
icon-picker.enable = isMaximal;
@ -184,21 +185,21 @@ inputs: let
};
};
vim.notes = {
notes = {
obsidian.enable = false; # FIXME: neovim fails to build if obsidian is enabled
orgmode.enable = false;
mind-nvim.enable = isMaximal;
todo-comments.enable = true;
};
vim.terminal = {
terminal = {
toggleterm = {
enable = true;
lazygit.enable = true;
};
};
vim.ui = {
ui = {
borders.enable = true;
noice.enable = true;
colorizer.enable = true;
@ -220,26 +221,26 @@ inputs: let
};
};
vim.assistant = {
assistant = {
copilot = {
enable = isMaximal;
cmp.enable = isMaximal;
};
};
vim.session = {
session = {
nvim-session-manager.enable = false;
};
vim.gestures = {
gestures = {
gesture-nvim.enable = false;
};
vim.comments = {
comments = {
comment-nvim.enable = true;
};
vim.presence = {
presence = {
neocord.enable = true;
};
};

View File

@ -1,21 +1,40 @@
{
inputs,
pkgs,
lib ? import ../lib/stdlib-extended.nix pkgs.lib,
nmdSrc,
lib ? import ../lib/stdlib-extended.nix pkgs.lib inputs,
...
}: let
nmd = import nmdSrc {
inherit lib;
# The DocBook output of `nixos-render-docs` doesn't have the change
# `nmd` uses to work around the broken stylesheets in
# `docbook-xsl-ns`, so we restore the patched version here.
pkgs =
pkgs
// {
docbook-xsl-ns =
pkgs.docbook-xsl-ns.override {withManOptDedupPatch = true;};
};
};
inherit (lib.modules) mkForce evalModules;
inherit (lib.strings) hasPrefix removePrefix;
inherit (lib.attrsets) isAttrs mapAttrs optionalAttrs recursiveUpdate isDerivation;
# From home-manager:
#
# Recursively replace each derivation in the given attribute set
# with the same derivation but with the `outPath` attribute set to
# the string `"\${pkgs.attribute.path}"`. This allows the
# documentation to refer to derivations through their values without
# establishing an actual dependency on the derivation output.
#
# This is not perfect, but it seems to cover a vast majority of use
# cases.
#
# Caveat: even if the package is reached by a different means, the
# path above will be shown and not e.g.
# `${config.services.foo.package}`.
scrubDerivations = prefixPath: attrs: let
scrubDerivation = name: value: let
pkgAttrName = prefixPath + "." + name;
in
if isAttrs value
then
scrubDerivations pkgAttrName value
// optionalAttrs (isDerivation value) {
outPath = "\${${pkgAttrName}}";
}
else value;
in
mapAttrs scrubDerivation attrs;
# Make sure the used package is scrubbed to avoid actually
# instantiating derivations.
@ -23,30 +42,30 @@
imports = [
{
_module.args = {
pkgs = lib.mkForce (nmd.scrubDerivations "pkgs" pkgs);
pkgs_i686 = lib.mkForce {};
pkgs = mkForce (scrubDerivations "pkgs" pkgs);
pkgs_i686 = mkForce {};
};
}
];
};
dontCheckDefinitions = {_module.check = false;};
githubDeclaration = user: repo: subpath: let
urlRef = "main";
in {
url = "https://github.com/${user}/${repo}/blob/${urlRef}/${subpath}";
name = "<${repo}/${subpath}>";
};
# Specify the path to the module entrypoint
nvimPath = toString ./..;
buildOptionsDocs = args @ {
modules,
includeModuleSystemOptions ? true,
...
}: let
inherit ((lib.evalModules {inherit modules;})) options;
inherit ((evalModules {inherit modules;})) options;
# Declaration of the Github site URL.
githubDeclaration = user: repo: subpath: let
urlRef = "github.com";
branch = "main";
in {
url = "https://${urlRef}/${user}/${repo}/blob/${branch}/${subpath}";
name = "<${repo}/${subpath}>";
};
in
pkgs.buildPackages.nixosOptionsDoc ({
options =
@ -54,15 +73,14 @@
then options
else builtins.removeAttrs options ["_module"];
transformOptions = opt:
opt
// {
# Clean up declaration sites to not refer to the Home Manager
recursiveUpdate opt {
# Clean up declaration sites to not refer to the neovim-flakee
# source tree.
declarations = map (decl:
if lib.hasPrefix nvimPath (toString decl)
if hasPrefix nvimPath (toString decl)
then
githubDeclaration "notashelf" "neovim-flake"
(lib.removePrefix "/" (lib.removePrefix nvimPath (toString decl)))
(removePrefix "/" (removePrefix nvimPath (toString decl)))
else if decl == "lib/modules.nix"
then
# TODO: handle this in a better way (may require upstream
@ -86,6 +104,7 @@
release-config = builtins.fromJSON (builtins.readFile ../release.json);
revision = "release-${release-config.release}";
# Generate the `man home-configuration.nix` package
nvf-configuration-manual =
pkgs.runCommand "neovim-flake-reference-manpage" {
@ -95,32 +114,36 @@
# Generate manpages.
mkdir -p $out/share/man/man5
mkdir -p $out/share/man/man1
nixos-render-docs -j $NIX_BUILD_CORES options manpage \
--revision ${revision} \
${nvimModuleDocs.optionsJSON}/share/doc/nixos/options.json \
$out/share/man/man5/neovim-flake.5
cp ${./neovim-flake.1} $out/share/man/man1/neovim-flake.1
'';
# Generate the HTML manual pages
neovim-flake-manual = pkgs.callPackage ./manual.nix {
inherit (inputs) nmd;
inherit revision;
outputPath = "share/doc/neovim-flake";
nmd = nmdSrc;
options = {
neovim-flake = nvimModuleDocs.optionsJSON;
};
};
html = neovim-flake-manual;
htmlOpenTool = pkgs.callPackage ./html-open-tool.nix {} {inherit html;};
in {
inherit nmdSrc;
inherit (inputs) nmd;
options = {
# TODO: Use `hmOptionsDocs.optionsJSON` directly once upstream
# `nixosOptionsDoc` is more customizable.
json =
pkgs.runCommand "options.json" {
meta.description = "List of Home Manager options in JSON format";
meta.description = "List of neovim-flake options in JSON format";
} ''
mkdir -p $out/{share/doc,nix-support}
cp -a ${nvimModuleDocs.optionsJSON}/share/doc/nixos $out/share/doc/neovim-flake

2329
flake.lock

File diff suppressed because it is too large Load Diff

409
flake.nix
View File

@ -22,7 +22,7 @@
flake = {
lib = {
inherit (import ./lib/stdlib-extended.nix nixpkgs.lib) nvim;
inherit (import ./lib/stdlib-extended.nix nixpkgs.lib inputs) nvim;
inherit (import ./configuration.nix inputs) neovimConfiguration;
};
@ -68,129 +68,6 @@
# TODO: get zig from the zig overlay instead of nixpkgs
zig.url = "github:mitchellh/zig-overlay";
# LSP plugins
nvim-lspconfig = {
# url = "github:neovim/nvim-lspconfig?ref=v0.1.3";
# Use master for nil_ls
url = "github:neovim/nvim-lspconfig";
flake = false;
};
lspsaga = {
url = "github:tami5/lspsaga.nvim";
flake = false;
};
lspkind = {
url = "github:onsails/lspkind-nvim";
flake = false;
};
trouble = {
url = "github:folke/trouble.nvim";
flake = false;
};
nvim-treesitter-context = {
url = "github:nvim-treesitter/nvim-treesitter-context";
flake = false;
};
nvim-lightbulb = {
url = "github:kosayoda/nvim-lightbulb";
flake = false;
};
nvim-code-action-menu = {
url = "github:weilbith/nvim-code-action-menu";
flake = false;
};
lsp-signature = {
url = "github:ray-x/lsp_signature.nvim";
flake = false;
};
lsp-lines = {
url = "sourcehut:~whynothugo/lsp_lines.nvim";
flake = false;
};
none-ls = {
# https://github.com/nvimtools/none-ls.nvim/issues/58
url = "github:nvimtools/none-ls.nvim/bb680d752cec37949faca7a1f509e2fe67ab418a";
flake = false;
};
nvim-docs-view = {
url = "github:amrbashir/nvim-docs-view";
flake = false;
};
# language support
sqls-nvim = {
url = "github:nanotee/sqls.nvim";
flake = false;
};
rust-tools = {
url = "github:simrat39/rust-tools.nvim";
flake = false;
};
flutter-tools = {
url = "github:akinsho/flutter-tools.nvim";
flake = false;
};
neodev-nvim = {
url = "github:folke/neodev.nvim";
flake = false;
};
elixir-ls = {
url = "github:elixir-lsp/elixir-ls";
flake = false;
};
elixir-tools = {
url = "github:elixir-tools/elixir-tools.nvim";
flake = false;
};
glow-nvim = {
url = "github:ellisonleao/glow.nvim";
flake = false;
};
image-nvim = {
url = "github:3rd/image.nvim";
flake = false;
};
# Tidal cycles
tidalcycles = {
url = "github:mitchmindtree/tidalcycles.nix";
inputs.vim-tidal-src.url = "github:tidalcycles/vim-tidal";
};
# Copying/Registers
registers = {
url = "github:tversteeg/registers.nvim";
flake = false;
};
nvim-neoclip = {
url = "github:AckslD/nvim-neoclip.lua";
flake = false;
};
# Telescope
telescope = {
url = "github:nvim-telescope/telescope.nvim";
flake = false;
};
# Langauge server (use master instead of nixpkgs)
rnix-lsp.url = "github:nix-community/rnix-lsp";
nil = {
@ -199,393 +76,521 @@
inputs.flake-utils.follows = "flake-utils";
};
### Plugins
# Tidal cycles
tidalcycles = {
url = "github:mitchmindtree/tidalcycles.nix";
inputs.vim-tidal-src.url = "github:tidalcycles/vim-tidal";
};
# LSP plugins
plugin-nvim-lspconfig = {
# url = "github:neovim/nvim-lspconfig?ref=v0.1.3";
# Use master for nil_ls
url = "github:neovim/nvim-lspconfig";
flake = false;
};
plugin-lspsaga = {
url = "github:tami5/lspsaga.nvim";
flake = false;
};
plugin-lspkind = {
url = "github:onsails/lspkind-nvim";
flake = false;
};
plugin-trouble = {
url = "github:folke/trouble.nvim";
flake = false;
};
plugin-nvim-treesitter-context = {
url = "github:nvim-treesitter/nvim-treesitter-context";
flake = false;
};
plugin-nvim-lightbulb = {
url = "github:kosayoda/nvim-lightbulb";
flake = false;
};
plugin-nvim-code-action-menu = {
url = "github:weilbith/nvim-code-action-menu";
flake = false;
};
plugin-lsp-signature = {
url = "github:ray-x/lsp_signature.nvim";
flake = false;
};
plugin-lsp-lines = {
url = "sourcehut:~whynothugo/lsp_lines.nvim";
flake = false;
};
plugin-none-ls = {
# https://github.com/nvimtools/none-ls.nvim/issues/58
url = "github:nvimtools/none-ls.nvim/bb680d752cec37949faca7a1f509e2fe67ab418a";
flake = false;
};
plugin-nvim-docs-view = {
url = "github:amrbashir/nvim-docs-view";
flake = false;
};
# language support
plugin-sqls-nvim = {
url = "github:nanotee/sqls.nvim";
flake = false;
};
plugin-rust-tools = {
url = "github:simrat39/rust-tools.nvim";
flake = false;
};
plugin-flutter-tools = {
url = "github:akinsho/flutter-tools.nvim";
flake = false;
};
plugin-neodev-nvim = {
url = "github:folke/neodev.nvim";
flake = false;
};
plugin-elixir-ls = {
url = "github:elixir-lsp/elixir-ls";
flake = false;
};
plugin-elixir-tools = {
url = "github:elixir-tools/elixir-tools.nvim";
flake = false;
};
plugin-glow-nvim = {
url = "github:ellisonleao/glow.nvim";
flake = false;
};
plugin-image-nvim = {
url = "github:3rd/image.nvim";
flake = false;
};
# Copying/Registers
plugin-registers = {
url = "github:tversteeg/registers.nvim";
flake = false;
};
plugin-nvim-neoclip = {
url = "github:AckslD/nvim-neoclip.lua";
flake = false;
};
# Telescope
plugin-telescope = {
url = "github:nvim-telescope/telescope.nvim";
flake = false;
};
# Debuggers
nvim-dap = {
plugin-nvim-dap = {
url = "github:mfussenegger/nvim-dap";
flake = false;
};
nvim-dap-ui = {
plugin-nvim-dap-ui = {
url = "github:rcarriga/nvim-dap-ui";
flake = false;
};
# Filetrees
nvim-tree-lua = {
plugin-nvim-tree-lua = {
url = "github:nvim-tree/nvim-tree.lua";
flake = false;
};
# Tablines
nvim-bufferline-lua = {
plugin-nvim-bufferline-lua = {
url = "github:akinsho/nvim-bufferline.lua";
flake = false;
};
# Statuslines
lualine = {
plugin-lualine = {
url = "github:hoob3rt/lualine.nvim";
flake = false;
};
nvim-cmp = {
plugin-nvim-cmp = {
url = "github:hrsh7th/nvim-cmp";
flake = false;
};
cmp-buffer = {
plugin-cmp-buffer = {
url = "github:hrsh7th/cmp-buffer";
flake = false;
};
cmp-nvim-lsp = {
plugin-cmp-nvim-lsp = {
url = "github:hrsh7th/cmp-nvim-lsp";
flake = false;
};
cmp-vsnip = {
plugin-cmp-vsnip = {
url = "github:hrsh7th/cmp-vsnip";
flake = false;
};
cmp-path = {
plugin-cmp-path = {
url = "github:hrsh7th/cmp-path";
flake = false;
};
cmp-treesitter = {
plugin-cmp-treesitter = {
url = "github:ray-x/cmp-treesitter";
flake = false;
};
# snippets
vim-vsnip = {
plugin-vim-vsnip = {
url = "github:hrsh7th/vim-vsnip";
flake = false;
};
# Presence
neocord = {
plugin-neocord = {
url = "github:IogaMaster/neocord";
flake = false; # uses flake-utils, avoid the flake
};
# Autopairs
nvim-autopairs = {
plugin-nvim-autopairs = {
url = "github:windwp/nvim-autopairs";
flake = false;
};
nvim-ts-autotag = {
plugin-nvim-ts-autotag = {
url = "github:windwp/nvim-ts-autotag";
flake = false;
};
# Commenting
kommentary = {
url = "github:b3nj5m1n/kommentary";
flake = false;
};
comment-nvim = {
plugin-comment-nvim = {
url = "github:numToStr/Comment.nvim";
flake = false;
};
todo-comments = {
plugin-todo-comments = {
url = "github:folke/todo-comments.nvim";
flake = false;
};
# Buffer tools
bufdelete-nvim = {
plugin-bufdelete-nvim = {
url = "github:famiu/bufdelete.nvim";
flake = false;
};
# Dashboard Utilities
dashboard-nvim = {
plugin-dashboard-nvim = {
url = "github:glepnir/dashboard-nvim";
flake = false;
};
alpha-nvim = {
plugin-alpha-nvim = {
url = "github:goolord/alpha-nvim";
flake = false;
};
vim-startify = {
plugin-vim-startify = {
url = "github:mhinz/vim-startify";
flake = false;
};
# Themes
tokyonight = {
plugin-tokyonight = {
url = "github:folke/tokyonight.nvim";
flake = false;
};
onedark = {
plugin-onedark = {
url = "github:navarasu/onedark.nvim";
flake = false;
};
catppuccin = {
plugin-catppuccin = {
url = "github:catppuccin/nvim";
flake = false;
};
dracula = {
plugin-dracula = {
url = "github:Mofiqul/dracula.nvim";
flake = false;
};
oxocarbon = {
plugin-oxocarbon = {
url = "github:glyh/oxocarbon.nvim/lualine-support";
flake = false;
};
gruvbox = {
plugin-gruvbox = {
url = "github:ellisonleao/gruvbox.nvim";
flake = false;
};
rose-pine = {
plugin-rose-pine = {
url = "github:rose-pine/neovim";
flake = false;
};
# Rust crates
crates-nvim = {
plugin-crates-nvim = {
url = "github:Saecki/crates.nvim";
flake = false;
};
# Project Management
project-nvim = {
plugin-project-nvim = {
url = "github:ahmedkhalf/project.nvim";
flake = false;
};
# Visuals
nvim-cursorline = {
plugin-nvim-cursorline = {
url = "github:yamatsum/nvim-cursorline";
flake = false;
};
scrollbar-nvim = {
plugin-scrollbar-nvim = {
url = "github:petertriho/nvim-scrollbar";
flake = false;
};
cinnamon-nvim = {
plugin-cinnamon-nvim = {
url = "github:declancm/cinnamon.nvim";
flake = false;
};
cellular-automaton = {
plugin-cellular-automaton = {
url = "github:Eandrju/cellular-automaton.nvim";
flake = false;
};
indent-blankline = {
plugin-indent-blankline = {
url = "github:lukas-reineke/indent-blankline.nvim";
flake = false;
};
nvim-web-devicons = {
plugin-nvim-web-devicons = {
url = "github:nvim-tree/nvim-web-devicons";
flake = false;
};
gitsigns-nvim = {
plugin-gitsigns-nvim = {
url = "github:lewis6991/gitsigns.nvim";
flake = false;
};
fidget-nvim = {
plugin-fidget-nvim = {
url = "github:j-hui/fidget.nvim";
flake = false;
};
highlight-undo = {
plugin-highlight-undo = {
url = "github:tzachar/highlight-undo.nvim";
flake = false;
};
# Minimap
minimap-vim = {
plugin-minimap-vim = {
url = "github:wfxr/minimap.vim";
flake = false;
};
codewindow-nvim = {
plugin-codewindow-nvim = {
url = "github:gorbit99/codewindow.nvim";
flake = false;
};
# Notifications
nvim-notify = {
plugin-nvim-notify = {
url = "github:rcarriga/nvim-notify";
flake = false;
};
# Utilities
ccc = {
plugin-ccc = {
url = "github:uga-rosa/ccc.nvim";
flake = false;
};
diffview-nvim = {
plugin-diffview-nvim = {
url = "github:sindrets/diffview.nvim";
flake = false;
};
icon-picker-nvim = {
plugin-icon-picker-nvim = {
url = "github:ziontee113/icon-picker.nvim";
flake = false;
};
which-key = {
plugin-which-key = {
url = "github:folke/which-key.nvim";
flake = false;
};
cheatsheet-nvim = {
plugin-cheatsheet-nvim = {
url = "github:sudormrfbin/cheatsheet.nvim";
flake = false;
};
gesture-nvim = {
plugin-gesture-nvim = {
url = "github:notomo/gesture.nvim";
flake = false;
};
hop-nvim = {
plugin-hop-nvim = {
url = "github:phaazon/hop.nvim";
flake = false;
};
leap-nvim = {
plugin-leap-nvim = {
url = "github:ggandor/leap.nvim";
flake = false;
};
smartcolumn = {
plugin-smartcolumn = {
url = "github:m4xshen/smartcolumn.nvim";
flake = false;
};
nvim-surround = {
plugin-nvim-surround = {
url = "github:kylechui/nvim-surround";
flake = false;
};
# Note-taking
obsidian-nvim = {
plugin-obsidian-nvim = {
url = "github:epwalsh/obsidian.nvim";
flake = false;
};
orgmode-nvim = {
plugin-orgmode-nvim = {
url = "github:nvim-orgmode/orgmode";
flake = false;
};
mind-nvim = {
plugin-mind-nvim = {
url = "github:phaazon/mind.nvim";
flake = false;
};
# Spellchecking
vim-dirtytalk = {
plugin-vim-dirtytalk = {
url = "github:psliwka/vim-dirtytalk";
flake = false;
};
# Terminal
toggleterm-nvim = {
plugin-toggleterm-nvim = {
url = "github:akinsho/toggleterm.nvim";
flake = false;
};
# UI
nvim-navbuddy = {
plugin-nvim-navbuddy = {
url = "github:SmiteshP/nvim-navbuddy";
flake = false;
};
nvim-navic = {
plugin-nvim-navic = {
url = "github:SmiteshP/nvim-navic";
flake = false;
};
noice-nvim = {
plugin-noice-nvim = {
url = "github:folke/noice.nvim";
flake = false;
};
modes-nvim = {
plugin-modes-nvim = {
url = "github:mvllow/modes.nvim";
flake = false;
};
nvim-colorizer-lua = {
plugin-nvim-colorizer-lua = {
url = "github:NvChad/nvim-colorizer.lua";
flake = false;
};
vim-illuminate = {
plugin-vim-illuminate = {
url = "github:RRethy/vim-illuminate";
flake = false;
};
# Assistant
copilot-lua = {
plugin-copilot-lua = {
url = "github:zbirenbaum/copilot.lua";
flake = false;
};
copilot-cmp = {
plugin-copilot-cmp = {
url = "github:zbirenbaum/copilot-cmp";
flake = false;
};
# Session management
nvim-session-manager = {
plugin-nvim-session-manager = {
url = "github:Shatur/neovim-session-manager";
flake = false;
};
# Dependencies
plenary-nvim = {
plugin-plenary-nvim = {
# (required by crates-nvim)
url = "github:nvim-lua/plenary.nvim";
flake = false;
};
dressing-nvim = {
plugin-dressing-nvim = {
# (required by icon-picker-nvim)
url = "github:stevearc/dressing.nvim";
flake = false;
};
vim-markdown = {
plugin-vim-markdown = {
# (required by obsidian-nvim)
url = "github:preservim/vim-markdown";
flake = false;
};
tabular = {
plugin-tabular = {
# (required by vim-markdown)
url = "github:godlygeek/tabular";
flake = false;
};
nui-nvim = {
plugin-nui-nvim = {
# (required by noice.nvim)
url = "github:MunifTanjim/nui.nvim";
flake = false;
};
vim-repeat = {
plugin-vim-repeat = {
# (required by leap.nvim)
url = "github:tpope/vim-repeat";
flake = false;
};
nvim-nio = {
plugin-nvim-nio = {
# (required nvim-dap-ui)
url = "github:nvim-neotest/nvim-nio";
flake = false;

View File

@ -1,15 +1,19 @@
# Home Manager module
packages: inputs: {
pkgs,
config,
pkgs,
lib ? pkgs.lib,
self,
...
}:
with lib; let
}: let
inherit (lib) maintainers;
inherit (lib.modules) mkIf;
inherit (lib.options) mkOption mkEnableOption literalExpression;
inherit (lib.types) attrsOf anything package;
cfg = config.programs.neovim-flake;
inherit (import ../../configuration.nix inputs) neovimConfiguration;
set = neovimConfiguration {
builtPackage = neovimConfiguration {
inherit pkgs;
modules = [cfg.settings];
};
@ -17,11 +21,21 @@ in {
meta.maintainers = with maintainers; [NotAShelf];
options.programs.neovim-flake = {
enable = mkEnableOption "A NeoVim IDE with a focus on configurability and extensibility.";
enable = mkEnableOption "neovim-flake, the extensible neovim-wrapper";
builtPackage = mkOption {
type = package;
default = builtPackage;
internal = true;
description = ''
The built neovim-flake package, wrapped with the user's configuration.
'';
};
settings = mkOption {
type = types.attrsOf types.anything;
type = attrsOf anything;
default = {};
description = "Attribute set of neovim-flake preferences.";
example = literalExpression ''
{
vim.viAlias = false;
@ -39,11 +53,10 @@ in {
};
}
'';
description = "Attribute set of neoflake preferences.";
};
};
config = mkIf cfg.enable {
home.packages = [set.neovim];
home.packages = [builtPackage];
};
}

62
flake/modules/nixos.nix Normal file
View File

@ -0,0 +1,62 @@
# Home Manager module
packages: inputs: {
config,
pkgs,
lib ? pkgs.lib,
...
}: let
inherit (lib) maintainers;
inherit (lib.modules) mkIf;
inherit (lib.options) mkOption mkEnableOption literalExpression;
inherit (lib.types) attrsOf package anything;
cfg = config.programs.neovim-flake;
inherit (import ../../configuration.nix inputs) neovimConfiguration;
builtPackage = neovimConfiguration {
inherit pkgs;
modules = [cfg.settings];
};
in {
meta.maintainers = with maintainers; [NotAShelf];
options.programs.neovim-flake = {
enable = mkEnableOption "neovim-flake, the extensible neovim-wrapper";
builtPackage = mkOption {
type = package;
default = builtPackage;
internal = true;
description = ''
The built neovim-flake package, wrapped with the user's configuration.
'';
};
settings = mkOption {
type = attrsOf anything;
default = {};
description = "Attribute set of neovim-flake preferences.";
example = literalExpression ''
{
vim.viAlias = false;
vim.vimAlias = true;
vim.lsp = {
enable = true;
formatOnSave = true;
lightbulb.enable = true;
lspsaga.enable = false;
nvimCodeActionMenu.enable = true;
trouble.enable = true;
lspSignature.enable = true;
rust.enable = false;
nix = true;
};
}
'';
};
};
config = mkIf cfg.enable {
environment.systemPackages = [builtPackage];
};
}

View File

@ -5,10 +5,7 @@
pkgs,
...
}: let
docs = import ../docs {
inherit pkgs;
nmdSrc = inputs.nmd;
};
docs = import ../docs {inherit pkgs inputs;};
in {
packages =
{

View File

@ -66,7 +66,7 @@
mkSetLuaBinding = binding: action:
mkLuaBinding binding.value action binding.description;
pushDownDefault = attr: mapAttrs (_name: value: mkDefault value) attr;
pushDownDefault = attr: mapAttrs (_: value: mkDefault value) attr;
};
in
binds

11
lib/config.nix Normal file
View File

@ -0,0 +1,11 @@
{lib}: let
inherit (lib.options) mkOption;
inherit (lib.types) bool;
in {
mkBool = value: description:
mkOption {
type = bool;
default = value;
inherit description;
};
}

View File

@ -107,4 +107,14 @@ in {
entryAfter = entryBetween [];
entryBefore = before: entryBetween before [];
mkLuarcSection = section: ''
-- SECTION: ${section.name}
${section.data}
'';
mkVimrcSection = section: ''
" SECTION: ${section.name}
${section.data}
'';
}

View File

@ -1,6 +1,11 @@
{lib}: {
types = import ./types {inherit lib;};
{
inputs,
lib,
...
}: {
types = import ./types {inherit inputs lib;};
config = import ./config.nix {inherit lib;};
binds = import ./binds.nix {inherit lib;};
dag = import ./dag.nix {inherit lib;};
languages = import ./languages.nix {inherit lib;};

View File

@ -1,75 +1,21 @@
# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/stdlib-extended.nix
# Just a convenience function that returns the given Nixpkgs standard
# library extended with the HM library.
nixpkgsLib: let
mkNvimLib = import ./.;
in
nixpkgsLib.extend (self: super: rec {
nvim = mkNvimLib {lib = self;};
# Convenience function that returns the given Nixpkgs standard library
# extended with our functions using `lib.extend`.
nixpkgsLib: inputs:
nixpkgsLib.extend (self: super: {
# WARNING: New functions should not be added here, but to files
# imported by `./default.nix` under their own categories. If your
# function does not fit to any of the existing categories, create
# a new file and import it in `./default.nix.`
mkLuaBinding = key: action: desc:
self.mkIf (key != null) {
"${key}" = {
inherit action desc;
lua = true;
silent = true;
};
};
# Makes our custom functions available under `lib.nvim` where stdlib-extended.nix is imported
# with the appropriate arguments. For end-users, a `lib` output will be accessible from the flake.
# E.g. for an input called `neovim-flake`, `inputs.neovim-flake.lib.nvim` will return the set
# below.
nvim = import ./. {
inherit inputs;
lib = self;
};
mkExprBinding = key: action: desc:
self.mkIf (key != null) {
"${key}" = {
inherit action desc;
lua = true;
silent = true;
expr = true;
};
};
mkBinding = key: action: desc:
self.mkIf (key != null) {
"${key}" = {
inherit action desc;
silent = true;
};
};
mkMappingOption = description: default:
self.mkOption {
type = self.types.nullOr self.types.str;
inherit default description;
};
# Utility function that takes two attrsets:
# { someKey = "some_value" } and
# { someKey = { description = "Some Description"; }; }
# and merges them into
# { someKey = { value = "some_value"; description = "Some Description"; }; }
addDescriptionsToMappings = actualMappings: mappingDefinitions:
self.attrsets.mapAttrs (name: value: let
isNested = self.isAttrs value;
returnedValue =
if isNested
then addDescriptionsToMappings actualMappings."${name}" mappingDefinitions."${name}"
else {
value = value;
description = mappingDefinitions."${name}".description;
};
in
returnedValue)
actualMappings;
mkSetBinding = binding: action:
mkBinding binding.value action binding.description;
mkSetExprBinding = binding: action:
mkExprBinding binding.value action binding.description;
mkSetLuaBinding = binding: action:
mkLuaBinding binding.value action binding.description;
pushDownDefault = attr: self.mapAttrs (name: value: self.mkDefault value) attr;
# For forward compatibility.
literalExpression = super.literalExpression or super.literalExample;
})
# For forward compatibility.
literalExpression = super.literalExpression or super.literalExample;
})

View File

@ -1,5 +1,5 @@
# From home-manager: https://github.com/nix-community/home-manager/blob/master/modules/lib/types-dag.nix
# Used for ordering config text.
# Used for ordering configuration text.
{lib}: let
inherit
(lib)
@ -59,8 +59,8 @@ in rec {
name = "dagOf";
description = "DAG of ${elemType.description}";
inherit (attrEquivalent) check merge emptyValue;
inherit (elemType) getSubModules;
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
getSubModules = elemType.getSubModules;
substSubModules = m: dagOf (elemType.substSubModules m);
functor = (defaultFunctor name) // {wrapped = elemType;};
nestedTypes.elemType = elemType;

View File

@ -1,6 +1,10 @@
{lib}: let
{
inputs,
lib,
...
}: let
typesDag = import ./dag.nix {inherit lib;};
typesPlugin = import ./plugins.nix {inherit lib;};
typesPlugin = import ./plugins.nix {inherit inputs lib;};
typesLanguage = import ./languages.nix {inherit lib;};
in {
inherit (typesDag) dagOf;

View File

@ -1,139 +1,58 @@
{lib}:
with lib; let
# Plugin must be same as input name from flake.nix
availablePlugins = [
# TODO: sort by category
"nvim-treesitter-context"
"gitsigns-nvim"
"plenary-nvim"
"nvim-lspconfig"
"nvim-treesitter"
"lspsaga"
"lspkind"
"nvim-lightbulb"
"lsp-signature"
"nvim-tree-lua"
"nvim-bufferline-lua"
"lualine"
"nvim-autopairs"
"nvim-ts-autotag"
"nvim-web-devicons"
"tokyonight"
"bufdelete-nvim"
"nvim-cmp"
"cmp-nvim-lsp"
"cmp-buffer"
"cmp-vsnip"
"cmp-path"
"cmp-treesitter"
"crates-nvim"
"vim-vsnip"
"nvim-code-action-menu"
"trouble"
"none-ls"
"which-key"
"indent-blankline"
"nvim-cursorline"
"sqls-nvim"
"glow-nvim"
"telescope"
"rust-tools"
"onedark"
"catppuccin"
"dracula"
"oxocarbon"
"gruvbox"
"rose-pine"
"minimap-vim"
"dashboard-nvim"
"alpha-nvim"
"scrollbar-nvim"
"codewindow-nvim"
"nvim-notify"
"cinnamon-nvim"
"cheatsheet-nvim"
"ccc"
"cellular-automaton"
"neocord"
"icon-picker-nvim"
"dressing-nvim"
"orgmode-nvim"
"obsidian-nvim"
"vim-markdown"
"tabular"
"toggleterm-nvim"
"noice-nvim"
"nui-nvim"
"copilot-lua"
"tabnine-nvim"
"nvim-session-manager"
"gesture-nvim"
"comment-nvim"
"kommentary"
"mind-nvim"
"fidget-nvim"
"diffview-nvim"
"todo-comments"
"flutter-tools"
"flutter-tools-patched"
"hop-nvim"
"leap-nvim"
"modes-nvim"
"vim-repeat"
"smartcolumn"
"project-nvim"
"neodev-nvim"
"elixir-ls"
"elixir-tools"
"nvim-colorizer-lua"
"vim-illuminate"
"nvim-surround"
"nvim-dap"
"nvim-dap-ui"
"nvim-navic"
"nvim-navbuddy"
"copilot-cmp"
"lsp-lines"
"vim-dirtytalk"
"highlight-undo"
"nvim-docs-view"
"image-nvim"
"nvim-nio"
];
{
inputs,
lib,
...
}: let
inherit (lib.options) mkOption;
inherit (lib.attrsets) attrNames mapAttrs' filterAttrs nameValuePair;
inherit (lib.strings) hasPrefix removePrefix isString;
inherit (lib.types) submodule either package enum str lines attrsOf anything listOf nullOr;
# Get the names of all flake inputs that start with the given prefix.
fromInputs = {
inputs,
prefix,
}:
mapAttrs' (n: v: nameValuePair (removePrefix prefix n) {src = v;}) (filterAttrs (n: _: hasPrefix prefix n) inputs);
# Get the names of all flake inputs that start with the given prefix.
pluginInputNames = attrNames (fromInputs {
inherit inputs;
prefix = "plugin-";
});
# You can either use the name of the plugin or a package.
pluginType = with types;
nullOr (
either
package
(enum availablePlugins)
);
pluginType = nullOr (
either
package
(enum (pluginInputNames ++ ["nvim-treesitter" "flutter-tools-patched" "vim-repeat"]))
);
pluginsType = types.listOf pluginType;
pluginsType = listOf pluginType;
extraPluginType = with types;
submodule {
options = {
package = mkOption {
type = pluginType;
description = "Plugin Package.";
};
extraPluginType = submodule {
options = {
package = mkOption {
type = pluginType;
description = "Plugin Package.";
};
after = mkOption {
type = listOf str;
default = [];
description = "Setup this plugin after the following ones.";
};
after = mkOption {
type = listOf str;
default = [];
description = "Setup this plugin after the following ones.";
};
setup = mkOption {
type = lines;
default = "";
description = "Lua code to run during setup.";
example = "require('aerial').setup {}";
};
setup = mkOption {
type = lines;
default = "";
description = "Lua code to run during setup.";
example = "require('aerial').setup {}";
};
};
};
in {
inherit extraPluginType;
inherit extraPluginType fromInputs;
pluginsOpt = {
description,
@ -156,23 +75,25 @@ in {
lib.mergeOneOption val defs;
};
# opts is a attrset of options, example:
# ```
# mkPluginSetupOption "telescope" {
# file_ignore_patterns = mkOption {
# description = "...";
# type = types.listOf types.str;
# default = [];
# };
# layout_config.horizontal = mkOption {...};
# }
# ```
/*
opts is a attrset of options, example:
```
mkPluginSetupOption "telescope" {
file_ignore_patterns = mkOption {
description = "...";
type = types.listOf types.str;
default = [];
};
layout_config.horizontal = mkOption {...};
}
```
*/
mkPluginSetupOption = pluginName: opts:
mkOption {
description = "Option table to pass into the setup function of " + pluginName;
default = {};
type = types.submodule {
freeformType = with types; attrsOf anything;
type = submodule {
freeformType = attrsOf anything;
options = opts;
};
};

View File

@ -1,188 +0,0 @@
{
lib,
config,
...
}: let
inherit (builtins) concatStringsSep;
inherit (lib.modules) mkIf;
inherit (lib.lists) optionals;
inherit (lib.strings) optionalString;
inherit (lib.nvim.dag) entryAfter;
cfg = config.vim;
in {
config = {
vim.startPlugins = ["plenary-nvim"] ++ optionals (cfg.spellChecking.enableProgrammingWordList) ["vim-dirtytalk"];
vim.maps.normal =
mkIf cfg.disableArrows {
"<up>" = {
action = "<nop>";
noremap = false;
};
"<down>" = {
action = "<nop>";
noremap = false;
};
"<left>" = {
action = "<nop>";
noremap = false;
};
"<right>" = {
action = "<nop>";
noremap = false;
};
}
// mkIf cfg.mapLeaderSpace {
"<space>" = {
action = "<nop>";
};
};
vim.maps.insert = mkIf cfg.disableArrows {
"<up>" = {
action = "<nop>";
noremap = false;
};
"<down>" = {
action = "<nop>";
noremap = false;
};
"<left>" = {
action = "<nop>";
noremap = false;
};
"<right>" = {
action = "<nop>";
noremap = false;
};
};
vim.configRC.basic = entryAfter ["globalsScript"] ''
" Settings that are set for everything
set encoding=utf-8
set mouse=${cfg.mouseSupport}
set tabstop=${toString cfg.tabWidth}
set shiftwidth=${toString cfg.tabWidth}
set softtabstop=${toString cfg.tabWidth}
set expandtab
set cmdheight=${toString cfg.cmdHeight}
set updatetime=${toString cfg.updateTime}
set shortmess+=c
set tm=${toString cfg.mapTimeout}
set hidden
set cursorlineopt=${toString cfg.cursorlineOpt}
set scrolloff=${toString cfg.scrollOffset}
${optionalString cfg.debugMode.enable ''
" Debug mode settings
set verbose=${toString cfg.debugMode.level}
set verbosefile=${cfg.debugMode.logFile}
''}
${optionalString cfg.splitBelow ''
set splitbelow
''}
${optionalString cfg.splitRight ''
set splitright
''}
${optionalString cfg.showSignColumn ''
set signcolumn=yes
''}
${optionalString cfg.autoIndent ''
set autoindent
''}
${optionalString cfg.preventJunkFiles ''
set noswapfile
set nobackup
set nowritebackup
''}
${optionalString (cfg.bell == "none") ''
set noerrorbells
set novisualbell
''}
${optionalString (cfg.bell == "on") ''
set novisualbell
''}
${optionalString (cfg.bell == "visual") ''
set noerrorbells
''}
${optionalString (cfg.lineNumberMode == "relative") ''
set relativenumber
''}
${optionalString (cfg.lineNumberMode == "number") ''
set number
''}
${optionalString (cfg.lineNumberMode == "relNumber") ''
set number relativenumber
''}
${optionalString cfg.useSystemClipboard ''
set clipboard+=unnamedplus
''}
${optionalString cfg.mapLeaderSpace ''
let mapleader=" "
let maplocalleader=" "
''}
${optionalString cfg.syntaxHighlighting ''
syntax on
''}
${optionalString (!cfg.wordWrap) ''
set nowrap
''}
${optionalString cfg.hideSearchHighlight ''
set nohlsearch
set incsearch
''}
${optionalString cfg.colourTerm ''
set termguicolors
set t_Co=256
''}
${optionalString (!cfg.enableEditorconfig) ''
let g:editorconfig = v:false
''}
${optionalString cfg.spellChecking.enable ''
set spell
set spelllang=${concatStringsSep "," cfg.spellChecking.languages}${optionalString cfg.spellChecking.enableProgrammingWordList ",programming"}
''}
${optionalString (cfg.leaderKey != null) ''
let mapleader = "${toString cfg.leaderKey}"
''}
${optionalString (cfg.searchCase == "ignore") ''
set nosmartcase
set ignorecase
''}
${optionalString (cfg.searchCase == "smart") ''
set smartcase
set ignorecase
''}
${optionalString (cfg.searchCase == "sensitive") ''
set nosmartcase
set noignorecase
''}
'';
};
}

View File

@ -0,0 +1,304 @@
{
config,
lib,
...
}: let
inherit (builtins) map mapAttrs toJSON filter;
inherit (lib.options) mkOption;
inherit (lib.attrsets) filterAttrs getAttrs attrValues attrNames;
inherit (lib.strings) optionalString isString concatStringsSep;
inherit (lib.misc) mapAttrsFlatten;
inherit (lib.trivial) showWarnings;
inherit (lib.types) bool str oneOf attrsOf nullOr attrs submodule lines;
inherit (lib.nvim.types) dagOf;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.dag) entryAnywhere entryAfter topoSort mkLuarcSection mkVimrcSection;
inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.vim) valToVim;
inherit (lib.nvim.config) mkBool;
cfg = config.vim;
wrapLuaConfig = luaConfig: ''
lua << EOF
${optionalString cfg.enableLuaLoader "vim.loader.enable()"}
${luaConfig}
EOF
'';
# Most of the keybindings code is highly inspired by pta2002/nixvim.
# Thank you!
mapConfigOptions = {
silent =
mkBool false
"Whether this mapping should be silent. Equivalent to adding <silent> to a map.";
nowait =
mkBool false
"Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
script =
mkBool false
"Equivalent to adding <script> to a map.";
expr =
mkBool false
"Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
unique =
mkBool false
"Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
noremap =
mkBool true
"Whether to use the 'noremap' variant of the command, ignoring any custom mappings on the defined action. It is highly advised to keep this on, which is the default.";
desc = mkOption {
type = nullOr str;
default = null;
description = "A description of this keybind, to be shown in which-key, if you have it enabled.";
};
};
genMaps = mode: maps: let
/*
Take a user-defined action (string or attrs) and return the following attribute set:
{
action = (string) the actual action to map to this key
config = (attrs) the configuration options for this mapping (noremap, silent...)
}
*/
normalizeAction = action: let
# Extract the values of the config options that have been explicitly set by the user
config =
filterAttrs (_: v: v != null)
(getAttrs (attrNames mapConfigOptions) action);
in {
config =
if config == {}
then {"__empty" = null;}
else config;
action =
if action.lua
then mkLuaInline action.action
else action.action;
};
in
attrValues (mapAttrs
(key: action: let
normalizedAction = normalizeAction action;
in {
inherit (normalizedAction) action config;
inherit key;
inherit mode;
})
maps);
mapOption = submodule {
options =
mapConfigOptions
// {
action = mkOption {
type = str;
description = "The action to execute.";
};
lua = mkOption {
type = bool;
description = ''
If true, `action` is considered to be lua code.
Thus, it will not be wrapped in `""`.
'';
default = false;
};
};
};
mapOptions = mode:
mkOption {
description = "Mappings for ${mode} mode";
type = attrsOf mapOption;
default = {};
};
in {
options = {
vim = {
configRC = mkOption {
description = "vimrc contents";
type = oneOf [(dagOf lines) str];
default = {};
};
luaConfigRC = mkOption {
description = "vim lua config";
type = oneOf [(dagOf lines) str];
default = {};
};
builtConfigRC = mkOption {
internal = true;
type = lines;
description = "The built config for neovim after resolving the DAG";
};
globals = mkOption {
default = {};
description = "Set containing global variable values";
type = attrs;
};
maps = mkOption {
type = submodule {
options = {
normal = mapOptions "normal";
insert = mapOptions "insert";
select = mapOptions "select";
visual = mapOptions "visual and select";
terminal = mapOptions "terminal";
normalVisualOp = mapOptions "normal, visual, select and operator-pending (same as plain 'map')";
visualOnly = mapOptions "visual only";
operator = mapOptions "operator-pending";
insertCommand = mapOptions "insert and command-line";
lang = mapOptions "insert, command-line and lang-arg";
command = mapOptions "command-line";
};
};
default = {};
description = ''
Custom keybindings for any mode.
For plain maps (e.g. just 'map' or 'remap') use maps.normalVisualOp.
'';
example = ''
maps = {
normal."<leader>m" = {
silent = true;
action = "<cmd>make<CR>";
}; # Same as nnoremap <leader>m <silent> <cmd>make<CR>
};
'';
};
enableLuaLoader = lib.options.mkEnableOption ''
experimental Lua module loader to speed up the start up process
'';
};
};
config = let
filterNonNull = mappings: filterAttrs (_name: value: value != null) mappings;
globalsScript =
mapAttrsFlatten (name: value: "let g:${name}=${valToVim value}")
(filterNonNull cfg.globals);
toLuaBindings = mode: maps:
map (value: ''
vim.keymap.set(${toLuaObject mode}, ${toLuaObject value.key}, ${toLuaObject value.action}, ${toLuaObject value.config})
'') (genMaps mode maps);
# I'm not sure if every one of these will work.
allmap = toLuaBindings "" config.vim.maps.normalVisualOp;
nmap = toLuaBindings "n" config.vim.maps.normal;
vmap = toLuaBindings "v" config.vim.maps.visual;
xmap = toLuaBindings "x" config.vim.maps.visualOnly;
smap = toLuaBindings "s" config.vim.maps.select;
imap = toLuaBindings "i" config.vim.maps.insert;
cmap = toLuaBindings "c" config.vim.maps.command;
tmap = toLuaBindings "t" config.vim.maps.terminal;
lmap = toLuaBindings "l" config.vim.maps.lang;
omap = toLuaBindings "o" config.vim.maps.operator;
icmap = toLuaBindings "ic" config.vim.maps.insertCommand;
resolveDag = {
name,
dag,
mapResult,
}: let
# When the value is a string, default it to dag.entryAnywhere
finalDag = mapAttrs (_: value:
if isString value
then entryAnywhere value
else value)
dag;
sortedDag = topoSort finalDag;
result =
if sortedDag ? result
then mapResult sortedDag.result
else abort ("Dependency cycle in ${name}: " + toJSON sortedDag);
in
result;
in {
vim = {
startPlugins = map (x: x.package) (attrValues cfg.extraPlugins);
configRC = {
globalsScript = entryAnywhere (concatStringsSep "\n" globalsScript);
luaScript = let
mapResult = result: (wrapLuaConfig (concatStringsSep "\n" (map mkLuarcSection result)));
luaConfig = resolveDag {
name = "lua config script";
dag = cfg.luaConfigRC;
inherit mapResult;
};
in
entryAfter ["globalsScript"] luaConfig;
extraPluginConfigs = let
mapResult = r: (wrapLuaConfig (concatStringsSep "\n" (map mkLuarcSection r)));
extraPluginsDag = mapAttrs (_: {
after,
setup,
...
}:
entryAfter after setup)
cfg.extraPlugins;
pluginConfig = resolveDag {
name = "extra plugins config";
dag = extraPluginsDag;
inherit mapResult;
};
in
entryAfter ["luaScript"] pluginConfig;
# This is probably not the right way to set the config. I'm not sure how it should look like.
mappings = let
maps = [
nmap
imap
vmap
xmap
smap
cmap
omap
tmap
lmap
icmap
allmap
];
mapConfig = wrapLuaConfig (concatStringsSep "\n" (map (v: concatStringsSep "\n" v) maps));
in
entryAfter ["globalsScript"] mapConfig;
};
builtConfigRC = let
# Catch assertions and warnings
# and throw for each failed assertion. If no assertions are found, show warnings.
failedAssertions = map (x: x.message) (filter (x: !x.assertion) config.assertions);
baseSystemAssertWarn =
if failedAssertions != []
then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
else showWarnings config.warnings;
mapResult = result: (concatStringsSep "\n" (map mkVimrcSection result));
vimConfig = resolveDag {
name = "vim config script";
dag = cfg.configRC;
inherit mapResult;
};
in
baseSystemAssertWarn vimConfig;
};
};
}

View File

@ -1,6 +1,6 @@
_: {
{
imports = [
./config.nix
./module.nix
./options.nix
];
}

View File

@ -0,0 +1,87 @@
{
pkgs,
lib,
...
}: let
inherit (lib.options) mkEnableOption mkOption literalExpression;
inherit (lib.types) path int package bool str listOf attrsOf;
inherit (lib.nvim.types) pluginsOpt extraPluginType;
in {
options.vim = {
package = mkOption {
type = package;
default = pkgs.neovim-unwrapped;
description = ''
The neovim package to use.
You will need to use an unwrapped package for this option to work as intended.
'';
};
debugMode = {
enable = mkEnableOption "debug mode";
level = mkOption {
type = int;
default = 20;
description = "Set the debug level";
};
logFile = mkOption {
type = path;
default = "/tmp/nvim.log";
description = "Set the log file";
};
};
viAlias = mkOption {
description = "Enable vi alias";
type = bool;
default = true;
};
vimAlias = mkOption {
description = "Enable vim alias";
type = bool;
default = true;
};
startPlugins = pluginsOpt {
default = [];
description = "List of plugins to startup.";
};
optPlugins = pluginsOpt {
default = [];
description = "List of plugins to optionally load";
};
extraPlugins = mkOption {
type = attrsOf extraPluginType;
default = {};
description = ''
List of plugins and related config.
Note that these are setup after builtin plugins.
'';
example = literalExpression ''
with pkgs.vimPlugins; {
aerial = {
package = aerial-nvim;
setup = "require('aerial').setup {}";
};
harpoon = {
package = harpoon;
setup = "require('harpoon').setup {}";
after = ["aerial"];
};
}'';
};
luaPackages = mkOption {
type = listOf str;
default = [];
description = ''
List of lua packages to install.
'';
};
};
}

View File

@ -1,394 +1,6 @@
{
config,
lib,
...
}: let
inherit (builtins) attrValues attrNames map mapAttrs toJSON isString concatStringsSep filter;
inherit (lib.options) mkOption literalExpression mdDoc;
inherit (lib.attrsets) filterAttrs getAttrs;
inherit (lib.strings) optionalString;
inherit (lib.misc) mapAttrsFlatten;
inherit (lib.trivial) showWarnings;
inherit (lib.types) bool str listOf oneOf attrsOf nullOr attrs submodule unspecified lines;
inherit (lib.nvim.types) dagOf pluginsOpt extraPluginType;
inherit (lib.nvim.dag) entryAnywhere entryAfter topoSort;
inherit (lib.generators) mkLuaInline;
inherit (lib.nvim.lua) toLuaObject;
inherit (lib.nvim.vim) valToVim;
cfg = config.vim;
wrapLuaConfig = luaConfig: ''
lua << EOF
${optionalString cfg.enableLuaLoader ''
vim.loader.enable()
''}
${luaConfig}
EOF
'';
mkBool = value: description:
mkOption {
type = bool;
default = value;
inherit description;
};
# Most of the keybindings code is highly inspired by pta2002/nixvim. Thank you!
mapConfigOptions = {
silent =
mkBool false
"Whether this mapping should be silent. Equivalent to adding <silent> to a map.";
nowait =
mkBool false
"Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
script =
mkBool false
"Equivalent to adding <script> to a map.";
expr =
mkBool false
"Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
unique =
mkBool false
"Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
noremap =
mkBool true
"Whether to use the 'noremap' variant of the command, ignoring any custom mappings on the defined action. It is highly advised to keep this on, which is the default.";
desc = mkOption {
type = nullOr str;
default = null;
description = "A description of this keybind, to be shown in which-key, if you have it enabled.";
};
};
genMaps = mode: maps: let
/*
Take a user-defined action (string or attrs) and return the following attribute set:
{
action = (string) the actual action to map to this key
config = (attrs) the configuration options for this mapping (noremap, silent...)
}
*/
normalizeAction = action: let
# Extract the values of the config options that have been explicitly set by the user
config =
filterAttrs (_: v: v != null)
(getAttrs (attrNames mapConfigOptions) action);
in {
config =
if config == {}
then {"__empty" = null;}
else config;
action =
if action.lua
then mkLuaInline action.action
else action.action;
};
in
attrValues (mapAttrs
(key: action: let
normalizedAction = normalizeAction action;
in {
inherit (normalizedAction) action config;
inherit key;
inherit mode;
})
maps);
mapOption = submodule {
options =
mapConfigOptions
// {
action = mkOption {
type = str;
description = "The action to execute.";
};
lua = mkOption {
type = bool;
description = ''
If true, `action` is considered to be lua code.
Thus, it will not be wrapped in `""`.
'';
default = false;
};
};
};
mapOptions = mode:
mkOption {
description = "Mappings for ${mode} mode";
type = attrsOf mapOption;
default = {};
};
in {
options = {
assertions = mkOption {
type = listOf unspecified;
internal = true;
default = [];
example = literalExpression ''
[
{
assertion = false;
message = "you can't enable this for that reason";
}
]
'';
};
warnings = mkOption {
internal = true;
default = [];
type = listOf str;
example = ["The `foo' service is deprecated and will go away soon!"];
description = mdDoc ''
This option allows modules to show warnings to users during
the evaluation of the system configuration.
'';
};
vim = {
viAlias = mkOption {
description = "Enable vi alias";
type = bool;
default = true;
};
vimAlias = mkOption {
description = "Enable vim alias";
type = bool;
default = true;
};
configRC = mkOption {
description = "vimrc contents";
type = oneOf [(dagOf lines) str];
default = {};
};
luaConfigRC = mkOption {
description = "vim lua config";
type = oneOf [(dagOf lines) str];
default = {};
};
builtConfigRC = mkOption {
internal = true;
type = lines;
description = "The built config for neovim after resolving the DAG";
};
startPlugins = pluginsOpt {
default = [];
description = "List of plugins to startup.";
};
optPlugins = pluginsOpt {
default = [];
description = "List of plugins to optionally load";
};
extraPlugins = mkOption {
type = attrsOf extraPluginType;
default = {};
description = ''
List of plugins and related config.
Note that these are setup after builtin plugins.
'';
example = literalExpression ''
with pkgs.vimPlugins; {
aerial = {
package = aerial-nvim;
setup = "require('aerial').setup {}";
};
harpoon = {
package = harpoon;
setup = "require('harpoon').setup {}";
after = ["aerial"];
};
}'';
};
luaPackages = mkOption {
type = listOf str;
default = [];
description = ''
List of lua packages to install.
'';
};
globals = mkOption {
default = {};
description = "Set containing global variable values";
type = attrs;
};
maps = mkOption {
type = submodule {
options = {
normal = mapOptions "normal";
insert = mapOptions "insert";
select = mapOptions "select";
visual = mapOptions "visual and select";
terminal = mapOptions "terminal";
normalVisualOp = mapOptions "normal, visual, select and operator-pending (same as plain 'map')";
visualOnly = mapOptions "visual only";
operator = mapOptions "operator-pending";
insertCommand = mapOptions "insert and command-line";
lang = mapOptions "insert, command-line and lang-arg";
command = mapOptions "command-line";
};
};
default = {};
description = ''
Custom keybindings for any mode.
For plain maps (e.g. just 'map' or 'remap') use maps.normalVisualOp.
'';
example = ''
maps = {
normal."<leader>m" = {
silent = true;
action = "<cmd>make<CR>";
}; # Same as nnoremap <leader>m <silent> <cmd>make<CR>
};
'';
};
};
};
config = let
filterNonNull = mappings: filterAttrs (_name: value: value != null) mappings;
globalsScript =
mapAttrsFlatten (name: value: "let g:${name}=${valToVim value}")
(filterNonNull cfg.globals);
toLuaBindings = mode: maps:
map (value: ''
vim.keymap.set(${toLuaObject mode}, ${toLuaObject value.key}, ${toLuaObject value.action}, ${toLuaObject value.config})
'') (genMaps mode maps);
# I'm not sure if every one of these will work.
allmap = toLuaBindings "" config.vim.maps.normalVisualOp;
nmap = toLuaBindings "n" config.vim.maps.normal;
vmap = toLuaBindings "v" config.vim.maps.visual;
xmap = toLuaBindings "x" config.vim.maps.visualOnly;
smap = toLuaBindings "s" config.vim.maps.select;
imap = toLuaBindings "i" config.vim.maps.insert;
cmap = toLuaBindings "c" config.vim.maps.command;
tmap = toLuaBindings "t" config.vim.maps.terminal;
lmap = toLuaBindings "l" config.vim.maps.lang;
omap = toLuaBindings "o" config.vim.maps.operator;
icmap = toLuaBindings "ic" config.vim.maps.insertCommand;
resolveDag = {
name,
dag,
mapResult,
}: let
# When the value is a string, default it to dag.entryAnywhere
finalDag = mapAttrs (_: value:
if isString value
then entryAnywhere value
else value)
dag;
sortedDag = topoSort finalDag;
result =
if sortedDag ? result
then mapResult sortedDag.result
else abort ("Dependency cycle in ${name}: " + toJSON sortedDag);
in
result;
in {
vim = {
startPlugins = map (x: x.package) (attrValues cfg.extraPlugins);
configRC = {
globalsScript = entryAnywhere (concatStringsSep "\n" globalsScript);
luaScript = let
mkSection = r: ''
-- SECTION: ${r.name}
${r.data}
'';
mapResult = r: (wrapLuaConfig (concatStringsSep "\n" (map mkSection r)));
luaConfig = resolveDag {
name = "lua config script";
dag = cfg.luaConfigRC;
inherit mapResult;
};
in
entryAfter ["globalsScript"] luaConfig;
extraPluginConfigs = let
mkSection = r: ''
-- SECTION: ${r.name}
${r.data}
'';
mapResult = r: (wrapLuaConfig (concatStringsSep "\n" (map mkSection r)));
extraPluginsDag = mapAttrs (_: {
after,
setup,
...
}:
entryAfter after setup)
cfg.extraPlugins;
pluginConfig = resolveDag {
name = "extra plugins config";
dag = extraPluginsDag;
inherit mapResult;
};
in
entryAfter ["luaScript"] pluginConfig;
# This is probably not the right way to set the config. I'm not sure how it should look like.
mappings = let
maps = [
nmap
imap
vmap
xmap
smap
cmap
omap
tmap
lmap
icmap
allmap
];
mapConfig = wrapLuaConfig (concatStringsSep "\n" (map (v: concatStringsSep "\n" v) maps));
in
entryAfter ["globalsScript"] mapConfig;
};
builtConfigRC = let
failedAssertions = map (x: x.message) (filter (x: !x.assertion) config.assertions);
baseSystemAssertWarn =
if failedAssertions != []
then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
else showWarnings config.warnings;
mkSection = r: ''
" SECTION: ${r.name}
${r.data}
'';
mapResult = r: (concatStringsSep "\n" (map mkSection r));
vimConfig = resolveDag {
name = "vim config script";
dag = cfg.configRC;
inherit mapResult;
};
in
baseSystemAssertWarn vimConfig;
};
};
imports = [
./build
./warnings
];
}

View File

@ -0,0 +1,31 @@
{lib, ...}: let
inherit (lib.options) mkOption literalExpression;
inherit (lib.types) listOf str unspecified;
in {
options = {
assertions = mkOption {
type = listOf unspecified;
internal = true;
default = [];
example = literalExpression ''
[
{
assertion = false;
message = "you can't enable this for that reason";
}
]
'';
};
warnings = mkOption {
internal = true;
default = [];
type = listOf str;
example = ["The `foo' service is deprecated and will go away soon!"];
description = ''
This option allows modules to show warnings to users during
the evaluation of the system configuration.
'';
};
};
}

View File

@ -9,8 +9,10 @@ inputs: {
inherit (pkgs) wrapNeovimUnstable vimPlugins;
inherit (pkgs.vimUtils) buildVimPlugin;
inherit (pkgs.neovimUtils) makeNeovimConfig;
inherit (lib.attrsets) recursiveUpdate;
inherit (lib.asserts) assertMsg;
extendedLib = import ../lib/stdlib-extended.nix lib;
extendedLib = import ../lib/stdlib-extended.nix lib inputs;
nvimModules = import ./modules.nix {
inherit check pkgs;
@ -19,7 +21,7 @@ inputs: {
module = extendedLib.evalModules {
modules = [configuration] ++ nvimModules;
specialArgs = {modulesPath = toString ./.;} // extraSpecialArgs;
specialArgs = recursiveUpdate {modulesPath = toString ./.;} extraSpecialArgs;
};
vimOptions = module.config.vim;
@ -27,11 +29,11 @@ inputs: {
extraLuaPackages = ps: map (x: ps.${x}) vimOptions.luaPackages;
buildPlug = {pname, ...} @ args:
assert lib.asserts.assertMsg (pname != "nvim-treesitter") "Use buildTreesitterPlug for building nvim-treesitter.";
assert assertMsg (pname != "nvim-treesitter") "Use buildTreesitterPlug for building nvim-treesitter.";
buildVimPlugin (args
// {
version = "master";
src = getAttr pname inputs;
src = getAttr ("plugin-" + pname) inputs;
});
buildTreesitterPlug = grammars: vimPlugins.nvim-treesitter.withPlugins (_: grammars);

View File

@ -3,46 +3,60 @@
lib,
check ? true,
}: let
modules = [
./completion
./theme
./core
./basic
./statusline
./tabline
./filetree
./visuals
./lsp
./treesitter
./autopairs
./snippets
./git
./minimap
./dashboard
./utility
./rich-presence
./notes
./terminal
./ui
./assistant
./session
./comments
./projects
./languages
./debugger
inherit (lib.modules) mkDefault;
inherit (lib.lists) concatLists;
core = map (p: ./core + "/${p}") [
"build"
"warnings"
];
neovim = map (p: ./neovim + "/${p}") [
"basic"
"mappings"
];
plugins = map (p: ./plugins + "/${p}") [
"assistant"
"autopairs"
"comments"
"completion"
"dashboard"
"debugger"
"filetree"
"git"
"languages"
"lsp"
"minimap"
"notes"
"projects"
"rich-presence"
"session"
"snippets"
"spellcheck"
"statusline"
"tabline"
"terminal"
"theme"
"treesitter"
"ui"
"utility"
"visuals"
];
allModules = concatLists [core neovim plugins];
pkgsModule = {config, ...}: {
config = {
_module = {
inherit check;
args = {
baseModules = modules;
pkgsPath = lib.mkDefault pkgs.path;
pkgs = lib.mkDefault pkgs;
baseModules = allModules;
pkgsPath = mkDefault pkgs.path;
pkgs = mkDefault pkgs;
};
};
};
};
in
modules ++ [pkgsModule]
allModules ++ [pkgsModule]

View File

@ -1,54 +1,22 @@
{
pkgs,
config,
lib,
...
}: let
inherit (lib.options) mkEnableOption mkOption;
inherit (lib.types) package path str bool int listOf enum nullOr;
inherit (lib.options) mkOption literalExpression;
inherit (lib.strings) optionalString;
inherit (lib.types) enum bool str int nullOr;
inherit (lib.nvim.dag) entryAfter;
cfg = config.vim;
in {
options.vim = {
package = mkOption {
type = package;
default = pkgs.neovim-unwrapped;
description = ''
The neovim package to use. You will need to use an unwrapped package for this option to work as intended.
'';
};
debugMode = {
enable = mkEnableOption "debug mode";
level = mkOption {
type = int;
default = 20;
description = "Set the debug level";
};
logFile = mkOption {
type = path;
default = "/tmp/nvim.log";
description = "Set the log file";
};
};
enableLuaLoader = mkEnableOption "experimental Lua module loader to speed up the start up process";
leaderKey = mkOption {
type = nullOr str;
default = null;
description = "The leader key to be used internally";
};
spellChecking = {
enable = mkEnableOption "neovim's built-in spellchecking";
enableProgrammingWordList = mkEnableOption "vim-dirtytalk, a wordlist for programmers, that includes programming words";
languages = mkOption {
type = listOf str;
description = "The languages to be used for spellchecking";
default = ["en"];
example = ["en" "de"];
};
};
colourTerm = mkOption {
type = bool;
default = true;
@ -114,16 +82,14 @@ in {
lineNumberMode = mkOption {
type = enum ["relative" "number" "relNumber" "none"];
default = "relNumber";
description = ''
How line numbers are displayed. Available options are
none, relative, number, relNumber
'';
example = literalExpression "none";
description = "How line numbers are displayed.";
};
preventJunkFiles = mkOption {
type = bool;
default = false;
description = "Prevent swapfile, backupfile from being created";
description = "Prevent swapfile and backupfile from being created";
};
tabWidth = mkOption {
@ -197,4 +163,124 @@ in {
description = "Set the case sensitivity of search";
};
};
config.vim.configRC.basic = entryAfter ["globalsScript"] ''
" Settings that are set for everything
set encoding=utf-8
set mouse=${cfg.mouseSupport}
set tabstop=${toString cfg.tabWidth}
set shiftwidth=${toString cfg.tabWidth}
set softtabstop=${toString cfg.tabWidth}
set expandtab
set cmdheight=${toString cfg.cmdHeight}
set updatetime=${toString cfg.updateTime}
set shortmess+=c
set tm=${toString cfg.mapTimeout}
set hidden
set cursorlineopt=${toString cfg.cursorlineOpt}
set scrolloff=${toString cfg.scrollOffset}
${optionalString cfg.debugMode.enable ''
" Debug mode settings
set verbose=${toString cfg.debugMode.level}
set verbosefile=${cfg.debugMode.logFile}
''}
${optionalString cfg.splitBelow ''
set splitbelow
''}
${optionalString cfg.splitRight ''
set splitright
''}
${optionalString cfg.showSignColumn ''
set signcolumn=yes
''}
${optionalString cfg.autoIndent ''
set autoindent
''}
${optionalString cfg.preventJunkFiles ''
set noswapfile
set nobackup
set nowritebackup
''}
${optionalString (cfg.bell == "none") ''
set noerrorbells
set novisualbell
''}
${optionalString (cfg.bell == "on") ''
set novisualbell
''}
${optionalString (cfg.bell == "visual") ''
set noerrorbells
''}
${optionalString (cfg.lineNumberMode == "relative") ''
set relativenumber
''}
${optionalString (cfg.lineNumberMode == "number") ''
set number
''}
${optionalString (cfg.lineNumberMode == "relNumber") ''
set number relativenumber
''}
${optionalString cfg.useSystemClipboard ''
set clipboard+=unnamedplus
''}
${optionalString cfg.mapLeaderSpace ''
let mapleader=" "
let maplocalleader=" "
''}
${optionalString cfg.syntaxHighlighting ''
syntax on
''}
${optionalString (!cfg.wordWrap) ''
set nowrap
''}
${optionalString cfg.hideSearchHighlight ''
set nohlsearch
set incsearch
''}
${optionalString cfg.colourTerm ''
set termguicolors
set t_Co=256
''}
${optionalString (!cfg.enableEditorconfig) ''
let g:editorconfig = v:false
''}
${optionalString (cfg.leaderKey != null) ''
let mapleader = "${toString cfg.leaderKey}"
''}
${optionalString (cfg.searchCase == "ignore") ''
set nosmartcase
set ignorecase
''}
${optionalString (cfg.searchCase == "smart") ''
set smartcase
set ignorecase
''}
${optionalString (cfg.searchCase == "sensitive") ''
set nosmartcase
set noignorecase
''}
'';
}

View File

@ -0,0 +1,6 @@
{
imports = [
./configrc.nix
./spellcheck.nix
];
}

View File

@ -0,0 +1,34 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
inherit (lib.options) mkEnableOption literalExpression mkOption;
inherit (lib.strings) concatStringsSep;
inherit (lib.lists) optionals;
inherit (lib.types) listOf str;
inherit (lib.nvim.dag) entryAfter;
cfg = config.vim.spellChecking;
in {
options.vim.spellChecking = {
enable = mkEnableOption "neovim's built-in spellchecking";
languages = mkOption {
type = listOf str;
default = ["en"];
example = literalExpression ''["en" "de"]'';
description = "The languages to be used for spellchecking";
};
};
config = mkIf cfg.enable {
vim = {
configRC.spellchecking = entryAfter ["basic"] ''
" Spellchecking
set spell
set spelllang=${concatStringsSep "," cfg.languages}
'';
};
};
}

View File

@ -0,0 +1,5 @@
{
config = {
vim.startPlugins = ["plenary-nvim"];
};
}

View File

@ -0,0 +1,8 @@
{
imports = [
./basic
./mappings
./config.nix
];
}

View File

@ -0,0 +1,57 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf;
cfg = config.vim;
in {
vim.maps = {
normal =
mkIf cfg.disableArrows {
"<up>" = {
action = "<nop>";
noremap = false;
};
"<down>" = {
action = "<nop>";
noremap = false;
};
"<left>" = {
action = "<nop>";
noremap = false;
};
"<right>" = {
action = "<nop>";
noremap = false;
};
}
// mkIf cfg.mapLeaderSpace {
"<space>" = {
action = "<nop>";
};
};
insert = mkIf cfg.disableArrows {
"<up>" = {
action = "<nop>";
noremap = false;
};
"<down>" = {
action = "<nop>";
noremap = false;
};
"<left>" = {
action = "<nop>";
noremap = false;
};
"<right>" = {
action = "<nop>";
noremap = false;
};
};
};
}

View File

@ -9,8 +9,7 @@
inherit (lib.nvim.binds) mkBinding;
inherit (lib.nvim.dag) entryAnywhere;
inherit (lib.nvim.lua) toLuaObject;
# TODO: move this to its own module
inherit (lib) pushDownDefault;
inherit (lib.nvim.binds) pushDownDefault;
cfg = config.vim.filetree.nvimTree;
self = import ./nvimtree.nix {inherit pkgs lib;};

View File

@ -5,10 +5,8 @@
}: let
inherit (builtins) toJSON;
inherit (lib.modules) mkIf mkMerge;
inherit (lib.nvim.binds) addDescriptionsToMappings mkSetExprBinding mkSetLuaBinding;
inherit (lib.nvim.binds) addDescriptionsToMappings mkSetExprBinding mkSetLuaBinding pushDownDefault;
inherit (lib.nvim.dag) entryAnywhere;
# TODO: move this to its own module
inherit (lib) pushDownDefault;
cfg = config.vim.git;

Some files were not shown because too many files have changed in this diff Show More