diff --git a/flake.lock b/flake.lock index d0f7e68..e86ce64 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,21 @@ { "nodes": { + "catppuccin": { + "flake": false, + "locked": { + "lastModified": 1713105352, + "narHash": "sha256-yTVou/WArEWygBBs2NFPI9Dm9iSGfwVftKFbOAGl8tk=", + "owner": "catppuccin", + "repo": "nvim", + "rev": "a1439ad7c584efb3d0ce14ccb835967f030450fe", + "type": "github" + }, + "original": { + "owner": "catppuccin", + "repo": "nvim", + "type": "github" + } + }, "cmp-luasnip": { "flake": false, "locked": { @@ -85,11 +101,11 @@ "gitsigns-nvim": { "flake": false, "locked": { - "lastModified": 1695571272, - "narHash": "sha256-VJCtDnPSo5RgSC+czSIOvqGhpUT0dzvCzbLtup+Ctyo=", + "lastModified": 1713620636, + "narHash": "sha256-UK3DyvrQ0kLm9wrMQ6tLDoDunoThbY/Yfjn+eCZpuMw=", "owner": "lewis6991", "repo": "gitsigns.nvim", - "rev": "bdeba1cec3faddd89146690c10b9a87949c0ee66", + "rev": "035da036e68e509ed158414416c827d022d914bd", "type": "github" }, "original": { @@ -117,17 +133,16 @@ "lspsaga-nvim": { "flake": false, "locked": { - "lastModified": 1665291018, - "narHash": "sha256-jkoEP5jeIZDAK/27gpNTXtW10/Ev9nB5RqUahPhja2Y=", + "lastModified": 1713695968, + "narHash": "sha256-DBfYJqVJ2zgHY3OI0ZirRn7kr34d5Gj9hi0K+UvuUdg=", "owner": "glepnir", "repo": "lspsaga.nvim", - "rev": "f33bc99d0ed3ed691a58b3339decf4e1933c3f9e", + "rev": "f20985499cd8ff0fbbfe8e7c770428ef764fc3be", "type": "github" }, "original": { "owner": "glepnir", "repo": "lspsaga.nvim", - "rev": "f33bc99d0ed3ed691a58b3339decf4e1933c3f9e", "type": "github" } }, @@ -197,11 +212,11 @@ }, "nix2lua": { "locked": { - "lastModified": 1709128456, - "narHash": "sha256-tRduS+XFI6VceWPQzjkuvlyn/Oe5NsQUS/wyEC69dvk=", + "lastModified": 1713645801, + "narHash": "sha256-pev5YkdskHDS4OpGdYb5F/44hKrFmqzCwNGs0vSzqM8=", "ref": "refs/heads/main", - "rev": "f152767145e61fea96eddb1b550ab3f25701e0ad", - "revCount": 18, + "rev": "3c08fa87d14704db1c1648b2486ed49e721dfe18", + "revCount": 37, "type": "git", "url": "https://git.pleshevski.ru/mynix/nix2lua" }, @@ -373,6 +388,7 @@ }, "root": { "inputs": { + "catppuccin": "catppuccin", "cmp-luasnip": "cmp-luasnip", "cmp-nvim-lsp": "cmp-nvim-lsp", "cmp-tabby": "cmp-tabby", @@ -398,8 +414,7 @@ "plenary-nvim": "plenary-nvim", "tabby-nvim": "tabby-nvim", "telescope-live-grep-args-nvim": "telescope-live-grep-args-nvim", - "telescope-nvim": "telescope-nvim", - "theme": "theme" + "telescope-nvim": "telescope-nvim" } }, "systems": { @@ -464,22 +479,6 @@ "repo": "telescope.nvim", "type": "github" } - }, - "theme": { - "flake": false, - "locked": { - "lastModified": 1695478950, - "narHash": "sha256-SV5DTVwcVv6YIb7TGNYwq6rtIG5pFKubK07snXhV7z8=", - "owner": "catppuccin", - "repo": "nvim", - "rev": "3d9a5ed556e289bce6c1fb0af89ec838360641b2", - "type": "github" - }, - "original": { - "owner": "catppuccin", - "repo": "nvim", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 4ef9530..36ba702 100644 --- a/flake.nix +++ b/flake.nix @@ -71,7 +71,7 @@ # https://github.com/glepnir/lspsaga.nvim lspsaga-nvim = { - url = "github:glepnir/lspsaga.nvim?rev=f33bc99d0ed3ed691a58b3339decf4e1933c3f9e"; + url = "github:glepnir/lspsaga.nvim"; flake = false; }; @@ -126,7 +126,7 @@ }; # https://github.com/catppuccin/nvim - theme = { + catppuccin = { url = "github:catppuccin/nvim"; flake = false; }; @@ -191,7 +191,7 @@ "lualine-nvim" "lualine-lsp-progress" "nvim-web-devicons" - "theme" + "catppuccin" # ux "hop-nvim" "nvim-orgmode" @@ -208,7 +208,7 @@ buildPlugin = name: vimUtils.buildVimPlugin { name = name; src = getAttr name inputs; - patches = lib.optional + patches = lib.optionals (pathExists ./patches/${name}) (map (patchName: ./patches/${name}/${patchName}) @@ -238,89 +238,63 @@ } // flake-utils.lib.eachDefaultSystem (system: let - inherit (builtins) mapAttrs; pkgs = import nixpkgs { inherit system; }; minimalNeovim = mkNeovim pkgs; - recommendedNeovim = (minimalNeovim.override { - enableDevIcons = true; - enableTabby = false; - - plugins = with minimalNeovim.nix2lua; { - nvimTree.settings = { - renderer = { + allNeovim = minimalNeovim.override (prev: { + modules = { + catppuccin = { }; + nvim-tree-lua = { + configs.renderer = { group_empty = true; full_name = true; }; }; - lualine.settings = { - options.ignore_focus = [ "NvimTree" ]; - sections = { - lualine_a = [ - [ "filename" (mkNamedField "path" 1) ] - ]; - lualine_b = [ "branch" "diff" "diagnostics" ]; - lualine_c = [ "lsp_progress" ]; - lualine_x = [ "filesize" "filetype" ]; - lualine_y = [ "progress" ]; - lualine_z = [ "location" "mode" ]; - }; + nvim-treesitter = { }; + gitsigns-nvim = { }; + neoformat = { }; + hop-nvim = { }; + telescope-nvim = { }; + nvim-cmp = { }; + lspconfig.languageServerConfigs = { + nil_ls = { }; }; }; + + plugins = with prev.nix2lua.lib; { + editorconfig-nvim = true; + lualine-lsp-progress = true; + lualine-nvim = pipe1 + (require "lualine") + (call "setup" { + options.ignore_focus = [ "NvimTree" ]; + sections = { + lualine_a = [ + [ "filename" (nf "path" 1) ] + ]; + lualine_b = [ "branch" "diff" "diagnostics" ]; + lualine_c = [ "lsp_progress" ]; + lualine_x = [ "filesize" "filetype" ]; + lualine_y = [ "progress" ]; + lualine_z = [ "location" "mode" ]; + }; + }); + nvim-colorizer = pipe1 + (require "colorizer") + (call0 "setup"); + }; }); - fullNeovim = recommendedNeovim.override { - plugins = recommendedNeovim.plugins // (with minimalNeovim.nix2lua; { - lspSaga.settings = { - border_style = "rounded"; - symbol_in_winbar.enable = false; - code_action_lightbulb.enable = false; - code_action_keys = { quit = ""; }; - definition_action_keys = { quit = ""; }; - rename_action_quit = ""; - }; - lspConfig = { - servers = { - nil_ls = { }; - tsserver = { }; - eslint = { }; - denols = { - root_dir = mkLuaRaw "root_pattern(\"deno.json\", \"deno.jsonc\")"; - }; - rust_analyzer = { - settings.rust-analyzer = { - "server.path" = "rust-analyzer"; - "updates.prompt" = false; - "updates.checkOnStartup" = false; - "checkOnSave.enable" = true; - "checkOnSave.command" = "clippy"; - "cargo.autoreload" = true; - }; - }; - }; - }; - tabbyml.enable = true; - }); - }; - packages = { - default = recommendedNeovim; - recommended = recommendedNeovim; - full = fullNeovim; minimal = minimalNeovim; - }; - mkApp = drv: { - type = "app"; - program = "${drv}/bin/nvim"; + all = allNeovim; }; in { inherit packages; - apps = mapAttrs (name: mkApp) packages; - devShells.default = pkgs.mkShell { packages = [ pkgs.stylua # lua formatter diff --git a/lib.nix b/lib.nix deleted file mode 100644 index fd5b3c1..0000000 --- a/lib.nix +++ /dev/null @@ -1,65 +0,0 @@ -{ lib, substituteAll, ... }: - -let - inherit (builtins) length elemAt isList isString hasAttr getAttr; - - ########################################################################### - # Helpers - - # Source: https://github.com/NixOS/nixpkgs/blob/d61bc96d16ca288c69b798b8e31eca64050098e3/lib/lists.nix - foldr = op: nul: list: - let - len = length list; - fold' = n: - if n == len - then nul - else op (elemAt list n) (fold' (n + 1)); - in - fold' 0; - - concatMap = op: list: - let - concat = (a: b: op a + b); - in - foldr concat "" list; - - ############################################################################ - # Configs - - optional = cond: val: - let - def = - if isList val then [ ] - else if isString val then "" - else null; - in - if cond then val else def; - - getAttrOpt = a: s: - if hasAttr a s then getAttr a s else null; - - ############################################################################# - # Lua - - mkLuaHeredoc = content: '' - lua << EOF - ${content} - EOF - ''; - - mkLuaRc = contents: concatMap mkLuaHeredoc contents; - - ############################################################################ - # Configs - - readSubFile = src: params: builtins.readFile - (substituteAll (params // { inherit src; })); - -in -{ - inherit (lib) importJSON attrByPath; - inherit foldr concatMap; - inherit optional getAttrOpt; - inherit mkLuaHeredoc mkLuaRc; - inherit readSubFile substituteAll; -} diff --git a/lib/vim.nix b/lib/vim.nix new file mode 100644 index 0000000..4a9e421 --- /dev/null +++ b/lib/vim.nix @@ -0,0 +1,42 @@ +{ nix2lua }: + +with nix2lua.lib; +{ + g = varName: expr: set "vim.g.${varName}" expr; + opt = varName: expr: set "vim.opt.${varName}" expr; + + fn' = fnName: args: call "vim.fn[\"${fnName}\"]" args; + fn.isdirectory = file: call1 "vim.fn.isdirectory" (var file); + + cmd' = expr: call1 "vim.cmd" expr; + cmd.cd = file: call1 "vim.cmd.cd" (var file); + + keymap.set = { mode, bind, command, opts ? { } }: + call "vim.keymap.set" [ mode bind command opts ]; + + /* + Parameters: + - {event} (string|array) Event(s) that will trigger the handler (callback or command). + - {opts} Options dict: + - group (string|integer) optional: autocommand group name or id to match against. + - pattern (string|array) optional: pattern(s) to match literally autocmd-pattern. + - buffer (integer) optional: buffer number for buffer-local autocommands autocmd-buflocal. Cannot be used with {pattern}. + - desc (string) optional: description (for documentation and troubleshooting). + - callback (function|string) optional: Lua function (or Vimscript function name, if string) called when the event(s) is triggered. Lua callback can return a truthy value (not false or nil) to delete the autocommand. Receives a table argument with these keys: + - id: (number) autocommand id + - event: (string) name of the triggered event autocmd-events + - group: (number|nil) autocommand group id, if any + - match: (string) expanded value of + - buf: (number) expanded value of + - file: (string) expanded value of + - data: (any) arbitrary data passed from nvim_exec_autocmds() + - command (string) optional: Vim command to execute on event. Cannot be used with {callback} + - once (boolean) optional: defaults to false. Run the autocommand only once autocmd-once. + - nested (boolean) optional: defaults to false. Run nested autocommands autocmd-nested. + */ + api.nvim_create_autocmd = event: opts: + call "vim.api.nvim_create_autocmd" [ event opts ]; + + api.nvim_create_augroup = name: opts: + call "vim.api.nvim_create_augroup" [ name opts ]; +} diff --git a/modules/catppuccin.nix b/modules/catppuccin.nix new file mode 100644 index 0000000..35ab80d --- /dev/null +++ b/modules/catppuccin.nix @@ -0,0 +1,13 @@ +{ nix2lua, vim, ... }: + + +{ flavour ? "frappe" }: + +with nix2lua.lib; +{ + catppuccin = [ + (vim.g "catppuccin_flavour" flavour) + (pipe1 (require "catppuccin") (call0 "setup")) + (vim.cmd' "colorscheme catppuccin") + ]; +} diff --git a/modules/gitsigns-nvim.nix b/modules/gitsigns-nvim.nix new file mode 100644 index 0000000..2c27106 --- /dev/null +++ b/modules/gitsigns-nvim.nix @@ -0,0 +1,60 @@ +{ nix2lua, vim, lib, ... }: + +with nix2lua.lib; + +let + defaultKeymaps = [ + { mode = "n"; bind = "]h"; command = raw "next_hunk"; } + { mode = "n"; bind = "[h"; command = raw "prev_hunk"; } + { mode = "n"; bind = "gs"; command = raw "gs.stage_hunk"; } + { mode = "n"; bind = "gr"; command = raw "gs.reset_hunk"; } + { mode = "n"; bind = "gu"; command = raw "gs.undo_stage_hunk"; } + { mode = "n"; bind = "gp"; command = raw "gs.preview_hunk"; } + { mode = "n"; bind = "gb"; command = lambda0 (call "gs.blame_line" { full = true; }); } + { mode = "n"; bind = "gd"; command = raw "gs.diffthis"; } + { mode = "n"; bind = "gD"; command = lambda0 (call "gs.diffthis" "~"); } + { mode = "n"; bind = "gtb"; command = raw "gs.toggle_current_line_blame"; } + { mode = "n"; bind = "gtd"; command = raw "gs.toggle_deleted"; } + ]; +in + +{ configs ? { } +, keymaps ? defaultKeymaps +, extraKeymaps ? [ ] +}: + +let + bufferedKeymaps = map + (args: lib.recursiveUpdate args { opts.buffer = var "bufnr"; }) + (keymaps ++ extraKeymaps); +in +{ + gitsigns-nvim = [ + (local (func "on_attach" [ "bufnr" ] ( + [ + (local (set "gs" (var "package.loaded.gitsigns"))) + + (local (func0 "next_hunk" + (ifelse (var "vim.wo.diff") + (call1 "vim.cmd.normal" [ "]h" (nf "bang" true) ]) + (call1 "gs.nav_hunk" "next") + ) + )) + (local (func0 "prev_hunk" + (ifelse (var "vim.wo.diff") + (call1 "vim.cmd.normal" [ "[h" (nf "bang" true) ]) + (call1 "gs.nav_hunk" "prev")) + )) + ] + ++ map vim.keymap.set bufferedKeymaps + ))) + + (pipe1 + (require "gitsigns") + (call "setup" (configs // { + on_attach = var "on_attach"; + })) + ) + ]; + +} diff --git a/modules/hop-nvim.nix b/modules/hop-nvim.nix new file mode 100644 index 0000000..5a657d4 --- /dev/null +++ b/modules/hop-nvim.nix @@ -0,0 +1,92 @@ +{ nix2lua, vim, ... }: + +with nix2lua.lib; + +let + hintDirAfter = var "hint.HintDirection.AFTER_CURSOR"; + hintDirBefore = var "hint.HintDirection.BEFORE_CURSOR"; + + defaultKeymaps = [ + { mode = ""; bind = "hc"; command = "HopChar1"; } + { + mode = ""; + bind = "hf"; + command = lambda0 (call "hop.hint_char1" { + direction = hintDirAfter; + current_line_only = true; + }); + } + { + mode = ""; + bind = "hF"; + command = lambda0 (call "hop.hint_char1" { + direction = hintDirBefore; + current_line_only = true; + }); + } + { + mode = ""; + bind = "hbc"; + command = lambda0 (call "hop.hint_char1" { direction = hintDirAfter; }); + } + { + mode = ""; + bind = "htc"; + command = lambda0 (call "hop.hint_char1" { direction = hintDirBefore; }); + } + { + mode = ""; + bind = "hw"; + command = "HopWord"; + } + { + mode = ""; + bind = "hbw"; + command = lambda0 (call "hop.hint_words" { direction = hintDirAfter; }); + } + { + mode = ""; + bind = "htw"; + command = lambda0 (call "hop.hint_words" { direction = hintDirBefore; }); + } + { + mode = ""; + bind = "hp"; + command = "HopPattern"; + } + { + mode = ""; + bind = "hbp"; + command = lambda0 (call "hop.hint_patterns" { direction = hintDirAfter; }); + } + { + mode = ""; + bind = "htp"; + command = lambda0 (call "hop.hint_patterns" { direction = hintDirBefore; }); + } + { + mode = ""; + bind = "hbv"; + command = lambda0 (call "hop.hint_vertical" { direction = hintDirAfter; }); + } + { + mode = ""; + bind = "htv"; + command = lambda0 (call "hop.hint_vertical" { direction = hintDirBefore; }); + } + ]; +in + +{ configs ? { } +, keymaps ? defaultKeymaps +, extraKeymaps ? [ ] +}: + +{ + hop-nvim = [ + (local (set "hop" (require "hop"))) + (pipe1 (var "hop") (call "setup" configs)) + + (local (set "hint" (require "hop.hint"))) + ] ++ map vim.keymap.set (keymaps ++ extraKeymaps); +} diff --git a/modules/lspconfig.nix b/modules/lspconfig.nix new file mode 100644 index 0000000..13af09e --- /dev/null +++ b/modules/lspconfig.nix @@ -0,0 +1,61 @@ +{ nix2lua, vim, lib, ... }: + +with nix2lua.lib; + +let + defaultDiagnosticKeymaps = [ + { mode = "n"; bind = "e"; command = raw "vim.diagnostic.open_float"; } + { mode = "n"; bind = "[d"; command = raw "vim.diagnostic.goto_prev"; } + { mode = "n"; bind = "]d"; command = raw "vim.diagnostic.goto_next"; } + { mode = "n"; bind = "q"; command = raw "vim.diagnostic.setloclist"; } + ]; + + defaultKeymaps = [ + { mode = "n"; bind = "gD"; command = raw "vim.lsp.buf.declaration"; } + { mode = "n"; bind = "gd"; command = raw "vim.lsp.buf.definition"; } + { mode = "n"; bind = "K"; command = raw "vim.lsp.buf.hover"; } + { mode = "n"; bind = "gi"; command = raw "vim.lsp.buf.implementation"; } + { mode = "n"; bind = "gr"; command = raw "vim.lsp.buf.references"; } + { mode = "n"; bind = "gy"; command = raw "vim.lsp.buf.type_definition"; } + { mode = "n"; bind = ""; command = raw "vim.lsp.buf.signature_help"; } + { mode = "n"; bind = "n"; command = raw "vim.lsp.buf.rename"; } + { mode = [ "n" "v" ]; bind = "a"; command = raw "vim.lsp.buf.code_action"; } + ]; + +in + +{ languageServerConfigs ? { } +, diagnosticKeymaps ? defaultDiagnosticKeymaps +, keymaps ? defaultKeymaps +}: + +{ + # dependencies + nvim-lspconfig = lib.flatten [ + (local (set "lspconfig" (require "lspconfig"))) + + (lib.flip lib.mapAttrsToList languageServerConfigs (ls: lsConfigs: + pipe [ + (var "lspconfig") + (var ls) + (call "setup" + (if builtins.isAttrs lsConfigs then lsConfigs + else { })) + ] + )) + + (map vim.keymap.set diagnosticKeymaps) + + (vim.api.nvim_create_autocmd "LspAttach" { + group = vim.api.nvim_create_augroup "UserLspConfig" { }; + callback = lambda [ "ev" ] + (lib.flatten [ + + (local (set "opts" { buffer = pipe1 (var "ev") (var "buf"); })) + + (lib.flip map keymaps (keymap: + vim.keymap.set (keymap // { opts = var "opts"; }))) + ]); + }) + ]; +} diff --git a/modules/neoformat.nix b/modules/neoformat.nix new file mode 100644 index 0000000..b18b198 --- /dev/null +++ b/modules/neoformat.nix @@ -0,0 +1,34 @@ +{ vim, ... }: + +{ configs ? { + neoformat_enabled_markdown = [ "denofmt" ]; + neoformat_rust_rustfmt = { + exe = "rustfmt"; + args = [ "--edition 2021" ]; + stdin = 1; + }; + } +}: + +let inherit (builtins) concatLists attrValues mapAttrs; in +let + baseConfigs = { + neoformat_try_node_exe = 1; + neoformat_only_msg_on_error = 1; + }; +in + +{ + neoformat = concatLists [ + (attrValues (mapAttrs vim.g (baseConfigs // configs))) + + [ + (vim.cmd' '' + aug fmt + au! + au BufWritePre * try | undojoin | Neoformat | catch /E790/ | Neoformat | endtry + aug END + '') + ] + ]; +} diff --git a/modules/nvim-cmp.nix b/modules/nvim-cmp.nix new file mode 100644 index 0000000..781d452 --- /dev/null +++ b/modules/nvim-cmp.nix @@ -0,0 +1,41 @@ +{ nix2lua, vim, ... }: + +with nix2lua.lib; + +let + defaultCmpKeymaps = { + "" = call "cmp.mapping.scroll_docs" (- 4); + "" = call "cmp.mapping.scroll_docs" 4; + "" = call0 "cmp.mapping.complete"; + "" = call0 "cmp.mapping.abort"; + "" = call "cmp.mapping.confirm" { select = true; }; + }; +in + +{ cmpKeymaps ? defaultCmpKeymaps +, extraCmpKeymaps ? { } +, cmpSources ? { } +}: + +{ + luasnip = true; + cmp-luasnip = true; + + nvim-cmp = [ + (vim.opt "completeopt" [ "menu" "menuone" "noselect" ]) + + (local (set "cmp" (require "cmp"))) + + (pipe1 + (var "cmp") + (call "setup" { + snippet.exand = lambda [ "args" ] + (pipe1 (require "luasnip") (call "lsp_expand" (var "args"))); + + mapping = call "cmp.mapping.preset.insert" (cmpKeymaps // extraCmpKeymaps); + + sources = call "cmp.config.sources" cmpSources; + }) + ) + ]; +} diff --git a/modules/nvim-tree-lua.nix b/modules/nvim-tree-lua.nix new file mode 100644 index 0000000..9ea511f --- /dev/null +++ b/modules/nvim-tree-lua.nix @@ -0,0 +1,55 @@ +{ nix2lua, vim, ... }: + +let + defaultKeymaps = [ + { mode = "n"; bind = "nt"; command = "NvimTreeToggle"; } + { mode = "n"; bind = "nf"; command = "NvimTreeFindFile"; } + ]; +in + +{ configs ? { } +, keymaps ? defaultKeymaps +, extraKeymaps ? [ ] +}: + +with nix2lua.lib; +let isEmptyVar = name: eq "" (var name); in +{ + nvim-web-devicons = true; + + nvim-tree-lua = ( + [ + (pipe1 (require "nvim-tree") (call "setup" configs)) + + (local (func "open_nvim_tree" [ "data" ] [ + # buffer is a [No Name] + (local (set "isNoNameBuffer" + (and + (isEmptyVar "data.file") + (isEmptyVar "vim.bo[data.buf].buftype") + ) + )) + + # buffer is a directory + (local (set "isDirectory" + (eq 1 (vim.fn.isdirectory "data.file")) + )) + + (if' (not (and (var "isNoNameBuffer") (var "isDirectory"))) + return_void + ) + + # change to the directory + (if' (var "isDirectory") + (vim.cmd.cd "data.file") + ) + + # open the tree + (pipe1 (require "nvim-tree.api") (call0 "tree.open")) + ])) + + (vim.api.nvim_create_autocmd [ "VimEnter" ] { callback = var "open_nvim_tree"; }) + ] + ++ map vim.keymap.set (keymaps ++ extraKeymaps) + ); +} diff --git a/modules/nvim-treesitter.nix b/modules/nvim-treesitter.nix new file mode 100644 index 0000000..ba94498 --- /dev/null +++ b/modules/nvim-treesitter.nix @@ -0,0 +1,208 @@ +{ nix2lua, pkgs, ... }: + +let + defaultGrammars = g: [ + # g.agda + # g.arduino + # g.astro + g.awk + g.bash + # g.beancount + # g.bibtex + # g.blueprint + # g.c + # g.c_sharp + # g.clojure + g.cmake + g.comment + # g.commonlisp + # g.cooklang + # g.cpp + # g.css + # g.cuda + # g.d + # g.d2 + # g.dart + # g.devicetree + g.diff + # g.dockerfile + # g.dot + # g.eex + # g.elixir + # g.elm + # g.elvish + g.embedded_template + # g.erlang + # g.fennel + # g.fish + # g.foam + # g.fortran + # g.fusion + # g.gdscript + g.git_rebase + g.gitattributes + g.gitignore + # g.gleam + # g.glimmer + # g.glsl + # g.go + # g.godot_resource + # g.gomod + # g.gowork + # g.graphql + # g.hack + # g.haskell + # g.hcl + # g.heex + # g.hjson + # g.hlsl + # g.hocon + # g.html + g.http + # g.java + # g.javascript + g.jq + g.jsdoc + g.json + # g.json5 + # g.jsonc + # g.jsonnet + # g.julia + # g.kotlin + # g.lalrpop + # g.latex + # g.ledger + # g.llvm + # g.lua + # g.m68k + g.make + g.markdown + g.markdown_inline + # g.menhir + # g.meson + # g.nickel + # g.ninja + g.nix + # g.norg + # g.ocaml + # g.ocaml_interface + # g.ocamllex + # g.org + # g.pascal + # g.perl + # g.php + # g.phpdoc + # g.pioasm + # g.prisma + # g.proto + # g.pug + # g.python + # g.ql + # g.qmljs + g.query + # g.r + # g.racket + # g.rasi + g.regex + # g.rego + # g.rnoweb + # g.rst + # g.ruby + # g.rust + # g.scala + g.scheme + # g.scss + # g.slint + # g.solidity + # g.sparql + # g.sql + # g.supercollider + # g.surface + # g.svelte + # g.swift + # g.sxhkdrc + # g.teal + # g.tiger + # g.tlaplus + g.todotxt + # g.toml + # g.tsx + # g.turtle + # g.twig + # g.typescript + # g.v + # g.vala + # g.verilog + # g.vhs + # g.vim + # g.vue + # g.wgsl + g.yaml + # g.yang + # g.zig + ]; +in + +{ allGrammars ? false +, withGrammars ? defaultGrammars +}: + +with nix2lua.lib; + + +let + extraGrammars = { + tree-sitter-d2 = { + language = "d2"; + version = "2023-06-21"; + src = pkgs.fetchFromGitea { + domain = "git.pleshevski.ru"; + owner = "pleshevskiy"; + repo = "tree-sitter-d2"; + rev = "8a9d50043d58eedf1e375b0e2059e43efd856902"; + sha256 = "sha256-ZhVjxo7Xi7DaHN3qabUcykflY74bUqPcOA410fA3zRk="; + }; + }; + }; + + tree-sitter = pkgs.tree-sitter.override { inherit extraGrammars; }; + customGrammars = tree-sitter.withPlugins (g: [ g.tree-sitter-d2 ]); + + nvimTreesitterWithGrammars = + if allGrammars then pkgs.vimPlugins.nvim-treesitter.withAllGrammars + else pkgs.vimPlugins.nvim-treesitter.withPlugins withGrammars; + + finalNvimTreesitter = nvimTreesitterWithGrammars.overrideAttrs (oldAttrs: { + passthru.dependencies = oldAttrs.passthru.dependencies ++ [ + (pkgs.runCommand "nvim-treesitter-d2-grammar" { } '' + mkdir -p $out/parser + ln -s ${customGrammars}/d2.so $out/parser/d2.so + '') + ]; + postPatch = '' + ln -s ${extraGrammars.tree-sitter-d2.src}/queries queries/d2 + ''; + }); +in +{ + override' = { + nvim-treesitter = finalNvimTreesitter; + }; + + nvim-treesitter = [ + (local (set "parser_config" + (pipe1 (require "nvim-treesitter.parsers") (call0 "get_parser_configs")) + )) + (set "parser_config.d2" { }) + + (pipe1 + (require "nvim-treesitter.configs") + (call "setup" { + ensure_installed = { }; + sync_install = false; + highlight.enable = true; + indent.enable = true; + }) + ) + ]; +} diff --git a/modules/telescope-nvim.nix b/modules/telescope-nvim.nix new file mode 100644 index 0000000..a85af5a --- /dev/null +++ b/modules/telescope-nvim.nix @@ -0,0 +1,34 @@ +{ nix2lua, vim, ... }: + +with nix2lua.lib; + +let + defaultKeymaps = [ + { mode = "n"; bind = "ff"; command = "Telescope find_files hidden=true"; } + { mode = "n"; bind = "fb"; command = "Telescope buffers"; } + { mode = "n"; bind = "fh"; command = "Telescope help_tags"; } + + { mode = "n"; bind = "fg"; command = lambda0 (call0 "telescope.extensions.live_grep_args.live_grep_args"); } + ]; +in + + +{ configs ? { } +, keymaps ? defaultKeymaps +, extraKeymaps ? [ ] + # TODO: add possibility to configure extensions +}: + +{ + # telescope requirements + plenary-nvim = true; + + # telescope extension + telescope-live-grep-args-nvim = true; + + telescope-nvim = [ + (local (set "telescope" (require "telescope"))) + (pipe1 (var "telescope") (call "setup" configs)) + (pipe1 (var "telescope") (call "load_extension" "live_grep_args")) + ] ++ map vim.keymap.set (keymaps ++ extraKeymaps); +} diff --git a/neovim.nix b/neovim.nix index 5e56e69..c014134 100644 --- a/neovim.nix +++ b/neovim.nix @@ -1,26 +1,22 @@ -{ enableDevIcons ? false -, enableTabby ? false -, enableOrgMode ? false -, viAlias ? false +{ viAlias ? false , vimAlias ? false , extraConfig ? "" , extraLuaConfig ? "" -, extraPlugins ? [ ] -, theme ? { } -, plugins ? { } , wrapNeovim , neovim-unwrapped -, tree-sitter , neovimPlugins +, pkgs , lib , nix2lua -, substituteAll -, callPackage +, plugins ? { } +, modules ? { } , ... }: + let plugins' = plugins; + modules' = modules; mergeAttrs = v: if builtins.isList v then @@ -33,40 +29,58 @@ let in let plugins = mergeAttrs plugins'; - inherit (builtins) catAttrs readFile; + modules = mergeAttrs modules'; - myLib = import ./lib.nix { inherit lib substituteAll; } // { - inherit (nix2lua.lib) toLua LuaNil; - }; + vim = import ./lib/vim.nix { inherit nix2lua; }; + importModule = moduleName: + import (./modules + "/${moduleName}.nix") { inherit nix2lua pkgs vim lib; }; + allModules = mergeAttrs (lib.mapAttrsToList importModule modules); - pluginParams = neovimPlugins // { - inherit tree-sitter plugins enableDevIcons enableTabby enableOrgMode; - themeCfg = theme; - lib = myLib; - }; + # Type: excludeOverride :: AttrSet -> AttrSet + excludeOverride = lib.filterAttrs (n: v: n != "override'"); + # Type: pluginsWithModules :: AttrSet + pluginsWithModules = mergeAttrs [ (excludeOverride allModules) plugins ]; - callPlugin = plugin: callPackage plugin pluginParams; - callPlugins = list: map callPlugin list; + overridedNeovimPlugins = + if allModules ? override' then neovimPlugins // allModules.override' + else neovimPlugins; - pluginsSettings = callPlugins [ - ./plugins/config - ./plugins/syntax - ./plugins/git - ./plugins/explorer - ./plugins/theme - ./plugins/lsp - ./plugins/formatter - ./plugins/ux - ]; + # Type: getPluginByName :: string -> derivation + getPluginByName = lib.flip lib.getAttr overridedNeovimPlugins; + # Type: allPlugins :: AttrSet -> [derivation] + allPlugins = map getPluginByName (lib.attrNames pluginsWithModules); - basePlugins = [ neovimPlugins.plenary-nvim ]; - customPlugins = catAttrs "plugins" pluginsSettings; - allPlugins = basePlugins ++ customPlugins ++ extraPlugins; + /* + Type: mkPluginLuaConfig :: string -> a -> string + */ + mkPluginLuaConfig = name: cfg: + with nix2lua.lib; + "-- Plugin: ${builtins.trace "Plugin: ${name}" name}\n" + + (if lib.isString cfg then cfg + else if lib.isAttrs cfg && cfg ? _type then toLua cfg + else if lib.isList cfg then toLua (spaceBetween cfg) + else if lib.isBool cfg then "" # Just skip lua config. Only enable the plugin. + else abort "[neovim] mkPluginLuaConfig: '${name}' has unsupported type '${builtins.typeOf cfg}'"); + pluginLuaConfigs = lib.mapAttrsToList mkPluginLuaConfig pluginsWithModules; - basicConfigs = map readFile [ ./config/basic.lua ]; - pluginConfigs = catAttrs "luaConfig" pluginsSettings; - allConfigs = basicConfigs ++ pluginConfigs ++ [ extraLuaConfig ]; + basicLuaConfigs = map builtins.readFile [ ./config/basic.lua ]; + + allLuaConfigs = basicLuaConfigs ++ pluginLuaConfigs; + + /* + Type: mkLuaHeredoc :: string -> string + */ + mkLuaHeredoc = content: '' + lua << EOF + ${content} + EOF + ''; + + /* + Type: mkLuaRc :: [string] -> string + */ + mkLuaRc = list: lib.concatLines (map mkLuaHeredoc list); in (wrapNeovim neovim-unwrapped { inherit viAlias; @@ -77,13 +91,13 @@ in withRuby = false; configure = { - customRC = extraConfig + myLib.mkLuaRc allConfigs; + customRC = extraConfig + mkLuaRc allLuaConfigs; packages.myVimPackages = { start = allPlugins; }; }; }).overrideAttrs (oldAttrs: { passthru = oldAttrs.passthru // { nix2lua = nix2lua.lib; - inherit plugins; + inherit plugins modules; }; }) diff --git a/plugins/lsp/default.nix b/plugins/lsp/default.nix index eae556d..dcb6562 100644 --- a/plugins/lsp/default.nix +++ b/plugins/lsp/default.nix @@ -18,14 +18,17 @@ let max_lines = 100; }; tabbymlSettings = lib.toLua (lib.attrByPath [ "tabbyml" "settings" ] tabbymlDefaultSettings plugins); - tabbymlLuaConfig = lib.optional tabbymlEnable + tabbymlLuaConfig = lib.optionalString tabbymlEnable (lib.readSubFile ./cmp-tabby.lua { inherit tabbymlSettings; }); - cmpSources = lib.toLua ([ - { name = "nvim_lsp"; } - { name = "luasnip"; } - { name = "orgmode"; } - ] ++ lib.optional tabbymlEnable [{ name = "cmp_tabby"; }]); + cmpSources = lib.toLua ( + [ + { name = "nvim_lsp"; } + { name = "luasnip"; } + { name = "orgmode"; } + ] + ++ lib.optional tabbymlEnable { name = "cmp_tabby"; } + ); cmpLuaConfig = lib.readSubFile ./nvim-cmp.lua { inherit cmpSources; }; lspconfigLuaConfig = lib.readSubFile ./lspconfig.lua @@ -37,7 +40,7 @@ let nvim-cmp # Autocompletion cmp-nvim-lsp # LSP source for nvim-cmp cmp-luasnip # Snippets source for nvim-cmp - ] ++ lib.optional tabbymlEnable [ cmp-tabby ]; + ] ++ lib.optional tabbymlEnable cmp-tabby; lspConfigServers = lib.toLua (lib.attrByPath [ "lspConfig" "servers" ] [ ] plugins); lspSagaSettings = lib.toLua (lib.attrByPath [ "lspSaga" "settings" ] { } plugins); diff --git a/plugins/theme/default.nix b/plugins/theme/default.nix index 54283b7..0c4f85b 100644 --- a/plugins/theme/default.nix +++ b/plugins/theme/default.nix @@ -27,10 +27,10 @@ in { luaConfig = themeConfig + (readFile (lib.substituteAll { src = ./lualine.lua; inherit lualineSettings; })) - + (lib.optional enableTabby (readFile ./tabby-nvim.lua)); + + (lib.optionalString enableTabby (readFile ./tabby-nvim.lua)); plugins = [ theme ] ++ lualinePlugins - ++ (lib.optional enableDevIcons [ nvim-web-devicons ]) - ++ (lib.optional enableTabby [ tabby-nvim ]); + ++ (lib.optional enableDevIcons nvim-web-devicons) + ++ (lib.optional enableTabby tabby-nvim); } diff --git a/plugins/ux/default.nix b/plugins/ux/default.nix index b7d398a..7e590c7 100644 --- a/plugins/ux/default.nix +++ b/plugins/ux/default.nix @@ -15,7 +15,7 @@ let orgmodeEnable = lib.attrByPath [ "orgmode" "enable" ] enableOrgMode plugins; orgmodeSettings = lib.toLua (lib.attrByPath [ "orgmode" "settings" ] { } plugins); - orgmodeLuaConfig = lib.optional orgmodeEnable + orgmodeLuaConfig = lib.optionalString orgmodeEnable (lib.readSubFile ./nvim-orgmode.lua { inherit orgmodeSettings; }); colorizerFiletypes = lib.toLua (lib.attrByPath [ "colorizer" "filetypes" ] lib.LuaNil plugins); @@ -28,5 +28,5 @@ in luaConfig = hopLuaConfig + orgmodeLuaConfig + colorizerLuaConfig; plugins = [ hop-nvim nvim-colorizer ] - ++ lib.optional orgmodeEnable [ nvim-orgmode org-bullets-nvim ]; + ++ lib.optionals orgmodeEnable [ nvim-orgmode org-bullets-nvim ]; }