diff --git a/.editorconfig b/.editorconfig index 2f767ae8..c7fdc76d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,7 +14,7 @@ indent_style = space indent_size = 2 trim_trailing_whitespace = false -[*.{js,json,nix,yml,yaml}] +[*.{js,json,nix,yml,yaml,toml}] indent_style = space indent_size = 2 tab_width = 2 diff --git a/.github/README.md b/.github/README.md index 01395211..7c0974c3 100644 --- a/.github/README.md +++ b/.github/README.md @@ -237,7 +237,7 @@ customizability of plugin inputs, which is one of our primary features. an imperative path (e.g., `~/.config/nvim`) for my Neovim configuration instead of a configuration generated from Nix? -**A**: Yes! Add `"~/.config.nvim"` to `vim.additionalRuntimePaths = [ ... ]` and +**A**: Yes! Add `"~/.config/nvim"` to `vim.additionalRuntimePaths = [ ... ]` and any plugins you want to load to `vim.startPlugins`. This will load your configuration from `~/.config/nvim`. You may still use `vim.*` to modify Neovim's behaviour with Nix. diff --git a/.github/typos.toml b/.github/typos.toml index 2ea46a8c..2cd18dde 100644 --- a/.github/typos.toml +++ b/.github/typos.toml @@ -1,5 +1,10 @@ -default.extend-ignore-words-re = ["(?i)(noice)", "befores", "annote", "viw"] -files.extend-exclude = [ -"npins/sources.json" +files.extend-exclude = ["npins/sources.json"] +default.extend-ignore-words-re = [ + "(?i)(noice)", + "befores", + "annote", + "viw", + "BA", # somehow "BANanaD3V" is valid, but BA is not... ] + diff --git a/.github/workflows/cachix.yml b/.github/workflows/cachix.yml index cac8ee51..959a04b6 100644 --- a/.github/workflows/cachix.yml +++ b/.github/workflows/cachix.yml @@ -36,7 +36,7 @@ jobs: - name: Install Nix uses: DeterminateSystems/nix-installer-action@main - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@v16 with: authToken: ${{ secrets.CACHIX_TOKEN }} extraPullNames: nix-community diff --git a/configuration.nix b/configuration.nix index 692337db..a243c970 100644 --- a/configuration.nix +++ b/configuration.nix @@ -234,6 +234,7 @@ isMaximal: { enable = false; cmp.enable = isMaximal; }; + codecompanion-nvim.enable = false; }; session = { diff --git a/docs/release-notes/rl-0.8.md b/docs/release-notes/rl-0.8.md index cf4dd169..9f05f60a 100644 --- a/docs/release-notes/rl-0.8.md +++ b/docs/release-notes/rl-0.8.md @@ -5,6 +5,8 @@ - `git-conflict` keybinds are now prefixed with `` to avoid conflicting with builtins. +- `alpha` is now configured with nix, default config removed. + [NotAShelf](https://github.com/notashelf): [typst-preview.nvim]: https://github.com/chomosuke/typst-preview.nvim @@ -52,6 +54,14 @@ - Add [yazi.nvim] as a companion plugin for Yazi, the terminal file manager. +- Add [](#opt-vim.autocmds) and [](#opt-vim.augroups) to allow declaring + autocommands via Nix. + +- Fix plugin `setupOpts` for yanky.nvim and assert if shada is configured as a + backend while shada is disabled in Neovim options. + +- Add [yazi.nvim] as a companion plugin for Yazi, the terminal file manager. + [amadaluzia](https://github.com/amadaluzia): [haskell-tools.nvim]: https://github.com/MrcJkb/haskell-tools.nvim @@ -149,16 +159,20 @@ [thamenato](https://github.com/thamenato): [ruff]: (https://github.com/astral-sh/ruff) +[cue]: (https://cuelang.org/) - Add [ruff] as a formatter option in `vim.languages.python.format.type`. +- Add [cue] support under `vim.languages.cue`. [ARCIII](https://github.com/ArmandoCIII): [leetcode.nvim]: https://github.com/kawre/leetcode.nvim +[codecompanion-nvim]: https://github.com/olimorris/codecompanion.nvim - Add `vim.languages.zig.dap` support through pkgs.lldb dap adapter. Code Inspiration from `vim.languages.clang.dap` implementation. - Add [leetcode.nvim] plugin under `vim.utility.leetcode-nvim`. +- Add [codecompanion.nvim] plugin under `vim.assistant.codecompanion-nvim`. [nezia1](https://github.com/nezia1): @@ -194,6 +208,10 @@ [golines](https://github.com/segmentio/golines) and [gofumpt](https://github.com/mvdan/gofumpt). +[UltraGhostie](https://github.com/UltraGhostie) + +- Add [harpoon](https://github.com/ThePrimeagen/harpoon) plugin for navigation + [MaxMur](https://github.com/TheMaxMur): - Add YAML support under `vim.languages.yaml`. @@ -201,18 +219,38 @@ [alfarel](https://github.com/alfarelcynthesis): - Add missing `yazi.nvim` dependency (`snacks.nvim`). -- Add [mkdir.nvim](https://github.com/jghauser/mkdir.nvim) plugin - for automatic creation of parent directories when editing a nested file. -- Add [nix-develop.nvim](https://github.com/figsoda/nix-develop.nvim) plugin - for in-neovim `nix develop`, `nix shell` and more. -- Add [direnv.vim](https://github.com/direnv/direnv.vim) plugin - for automatic syncing of nvim shell environment with direnv's. + +- Add [mkdir.nvim](https://github.com/jghauser/mkdir.nvim) plugin for automatic + creation of parent directories when editing a nested file. +- Add [nix-develop.nvim](https://github.com/figsoda/nix-develop.nvim) plugin for + in-neovim `nix develop`, `nix shell` and more. +- Add [direnv.vim](https://github.com/direnv/direnv.vim) plugin for automatic + syncing of nvim shell environment with direnv's. - Add [blink.cmp] source options and some default-disabled sources. - Add [blink.cmp] option to add - [friendly-snippets](https://github.com/rafamadriz/friendly-snippets) - so blink.cmp can source snippets from it. + [friendly-snippets](https://github.com/rafamadriz/friendly-snippets) so + blink.cmp can source snippets from it. [TheColorman](https://github.com/TheColorman): - Fix plugin `setupOpts` for `neovim-session-manager` having an invalid value for `autoload_mode`. + +[esdevries](https://github.com/esdevries): + +[projekt0n/github-nvim-theme]: https://github.com/projekt0n/github-nvim-theme + +- Add `github-nvim-theme` theme from [projekt0n/github-nvim-theme]. + +[BANanaD3V](https://github.com/BANanaD3V): + +- `alpha` is now configured with nix. + +[viicslen](https://github.com/viicslen): + +- Add `intelephense` language server support under + `vim.languages.php.lsp.server` + +[Butzist](https://github.com/butzist): + +- Add Helm chart support under `vim.languages.helm`. diff --git a/modules/neovim/init/autocmds.nix b/modules/neovim/init/autocmds.nix new file mode 100644 index 00000000..5da7bc55 --- /dev/null +++ b/modules/neovim/init/autocmds.nix @@ -0,0 +1,185 @@ +{ + config, + lib, + ... +}: let + inherit (lib.options) mkOption mkEnableOption literalExpression; + inherit (lib.lists) filter; + inherit (lib.strings) optionalString; + inherit (lib.types) nullOr submodule listOf str bool; + inherit (lib.nvim.types) luaInline; + inherit (lib.nvim.lua) toLuaObject; + inherit (lib.nvim.dag) entryAfter; + + autocommandType = submodule { + options = { + enable = + mkEnableOption "" + // { + default = true; + description = "Whether to enable this autocommand"; + }; + + event = mkOption { + type = nullOr (listOf str); + default = null; + example = ["BufRead" "BufWritePre"]; + description = "The event(s) that trigger the autocommand."; + }; + + pattern = mkOption { + type = nullOr (listOf str); + default = null; + example = ["*.lua" "*.vim"]; + description = "The file pattern(s) that determine when the autocommand applies)."; + }; + + callback = mkOption { + type = nullOr luaInline; + default = null; + example = literalExpression '' + mkLuaInline ''' + function() + print("Saving a Lua file...") + end + '''' + ''; + description = "The file pattern(s) that determine when the autocommand applies."; + }; + + command = mkOption { + type = nullOr str; + default = null; + description = "Vim command string instead of a Lua function."; + }; + + group = mkOption { + type = nullOr str; + default = null; + example = "MyAutoCmdGroup"; + description = "An optional autocommand group to manage related autocommands."; + }; + + desc = mkOption { + type = nullOr str; + default = null; + example = "Notify when saving a Lua file"; + description = "A description for the autocommand."; + }; + + once = mkOption { + type = bool; + default = false; + description = "Whether autocommand run only once."; + }; + + nested = mkOption { + type = bool; + default = false; + description = "Whether to allow nested autocommands to trigger."; + }; + }; + }; + + autogroupType = submodule { + options = { + enable = + mkEnableOption "" + // { + default = true; + description = "Whether to enable this autogroup"; + }; + + name = mkOption { + type = str; + example = "MyAutoCmdGroup"; + description = "The name of the autocommand group."; + }; + + clear = mkOption { + type = bool; + default = true; + description = '' + Whether to clear existing autocommands in this group before defining new ones. + This helps avoid duplicate autocommands. + ''; + }; + }; + }; + + cfg = config.vim; +in { + options.vim = { + augroups = mkOption { + type = listOf autogroupType; + default = []; + description = '' + A list of Neovim autogroups, which are used to organize and manage related + autocommands together. Groups allow multiple autocommands to be cleared + or redefined collectively, preventing duplicate definitions. + + Each autogroup consists of a name, a boolean indicating whether to clear + existing autocommands, and a list of associated autocommands. + ''; + }; + + autocmds = mkOption { + type = listOf autocommandType; + default = []; + description = '' + A list of Neovim autocommands to be registered. + + Each entry defines an autocommand, specifying events, patterns, optional + callbacks, commands, groups, and execution settings. + ''; + }; + }; + + config = { + vim = let + enabledAutocommands = filter (cmd: cmd.enable) cfg.autocmds; + enabledAutogroups = filter (au: au.enable) cfg.augroups; + in { + luaConfigRC = { + augroups = entryAfter ["pluginConfigs"] (optionalString (enabledAutogroups != []) '' + local nvf_autogroups = {} + for _, group in ipairs(${toLuaObject enabledAutogroups}) do + if group.name then + nvf_autogroups[group.name] = { clear = group.clear } + end + end + + for group_name, options in pairs(nvf_autogroups) do + vim.api.nvim_create_augroup(group_name, options) + end + ''); + + autocmds = entryAfter ["pluginConfigs"] (optionalString (enabledAutocommands != []) '' + local nvf_autocommands = ${toLuaObject enabledAutocommands} + for _, autocmd in ipairs(nvf_autocommands) do + vim.api.nvim_create_autocmd( + autocmd.event, + { + group = autocmd.group, + pattern = autocmd.pattern, + buffer = autocmd.buffer, + desc = autocmd.desc, + callback = autocmd.callback, + command = autocmd.command, + once = autocmd.once, + nested = autocmd.nested + } + ) + end + ''); + }; + }; + + assertions = [ + { + assertion = builtins.all (cmd: (cmd.command == null || cmd.callback == null)) cfg.autocmds; + message = "An autocommand cannot have both 'command' and 'callback' defined at the same time."; + } + ]; + }; +} diff --git a/modules/neovim/init/default.nix b/modules/neovim/init/default.nix index b0c7e0ce..ac9d29e5 100644 --- a/modules/neovim/init/default.nix +++ b/modules/neovim/init/default.nix @@ -1,5 +1,6 @@ { imports = [ + ./autocmds.nix ./basic.nix ./debug.nix ./highlight.nix diff --git a/modules/plugins/assistant/codecompanion/codecompanion-nvim.nix b/modules/plugins/assistant/codecompanion/codecompanion-nvim.nix new file mode 100644 index 00000000..9ebe30c0 --- /dev/null +++ b/modules/plugins/assistant/codecompanion/codecompanion-nvim.nix @@ -0,0 +1,278 @@ +{lib, ...}: let + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.types) int str enum nullOr attrs; + inherit (lib.nvim.types) mkPluginSetupOption luaInline; +in { + options.vim.assistant = { + codecompanion-nvim = { + enable = mkEnableOption "complementary neovim plugin for codecompanion.nvim"; + + setupOpts = mkPluginSetupOption "codecompanion-nvim" { + opts = { + send_code = mkEnableOption "code from being sent to the LLM."; + + log_level = mkOption { + type = enum ["DEBUG" "INFO" "ERROR" "TRACE"]; + default = "ERROR"; + description = "Change the level of logging."; + }; + + language = mkOption { + type = str; + default = "English"; + description = "Specify which language an LLM should respond in."; + }; + }; + + display = { + diff = { + enabled = + mkEnableOption "" + // { + default = true; + description = "a diff view to see the changes made by the LLM."; + }; + + close_chat_at = mkOption { + type = int; + default = 240; + description = '' + Close an open chat buffer if the + total columns of your display are less than... + ''; + }; + + layout = mkOption { + type = enum ["vertical" "horizontal"]; + default = "vertical"; + description = "Type of split for default provider."; + }; + + provider = mkOption { + type = enum ["default" "mini_diff"]; + default = "default"; + description = "The preferred kind of provider."; + }; + }; + + inline = { + layout = mkOption { + type = enum ["vertical" "horizontal" "buffer"]; + default = "vertical"; + description = "Customize how output is created in new buffer."; + }; + }; + + chat = { + auto_scroll = mkEnableOption "automatic page scrolling."; + + show_settings = mkEnableOption '' + LLM settings to appear at the top of the chat buffer. + ''; + + start_in_insert_mode = mkEnableOption '' + opening the chat buffer in insert mode. + ''; + + show_header_separator = mkEnableOption '' + header separators in the chat buffer. + + Set this to false if you're using an + external markdown formatting plugin. + ''; + + show_references = + mkEnableOption "" + // { + default = true; + description = "references in the chat buffer."; + }; + + show_token_count = + mkEnableOption "" + // { + default = true; + description = "the token count for each response."; + }; + + intro_message = mkOption { + type = str; + default = "Welcome to CodeCompanion ✨! Press ? for options."; + description = "Message to appear in chat buffer."; + }; + + separator = mkOption { + type = str; + default = "─"; + description = '' + The separator between the + different messages in the chat buffer. + ''; + }; + + icons = { + pinned_buffer = mkOption { + type = str; + default = " "; + description = "The icon to represent a pinned buffer."; + }; + + watched_buffer = mkOption { + type = str; + default = "👀 "; + description = "The icon to represent a watched buffer."; + }; + }; + }; + + action_palette = { + width = mkOption { + type = int; + default = 95; + description = "Width of the action palette."; + }; + + height = mkOption { + type = int; + default = 10; + description = "Height of the action palette."; + }; + + prompt = mkOption { + type = str; + default = "Prompt "; + description = "Prompt used for interactive LLM calls."; + }; + + provider = mkOption { + type = enum ["default" "telescope" "mini_pick"]; + default = "default"; + description = "Provider used for the action palette."; + }; + + opts = { + show_default_actions = + mkEnableOption "" + // { + default = true; + description = "showing default actions in the action palette."; + }; + + show_default_prompt_library = + mkEnableOption "" + // { + default = true; + description = '' + showing default prompt library in the action palette. + ''; + }; + }; + }; + }; + + adapters = mkOption { + type = nullOr luaInline; + default = null; + description = "An adapter is what connects Neovim to an LLM."; + }; + + strategies = { + chat = { + adapter = mkOption { + type = nullOr str; + default = null; + description = "Adapter used for the chat strategy."; + }; + + keymaps = mkOption { + type = nullOr attrs; + default = null; + description = "Define or override the default keymaps."; + }; + + variables = mkOption { + type = nullOr luaInline; + default = null; + description = '' + Define your own variables + to share specific content. + ''; + }; + + slash_commands = mkOption { + type = nullOr luaInline; + default = null; + description = '' + Slash Commands (invoked with /) let you dynamically + insert context into the chat buffer, + such as file contents or date/time. + ''; + }; + + tools = mkOption { + type = nullOr attrs; + default = null; + description = '' + Configure tools to perform specific + tasks when invoked by an LLM. + ''; + }; + + roles = mkOption { + type = nullOr luaInline; + default = null; + description = '' + The chat buffer places user and LLM responses under a H2 header. + These can be customized in the configuration. + ''; + }; + }; + + inline = { + adapter = mkOption { + type = nullOr str; + default = null; + description = "Adapter used for the inline strategy."; + }; + + variables = mkOption { + type = nullOr luaInline; + default = null; + description = '' + Define your own variables + to share specific content. + ''; + }; + + keymaps = { + accept_change = { + n = mkOption { + type = str; + default = "ga"; + description = "Accept the suggested change."; + }; + }; + + reject_change = { + n = mkOption { + type = str; + default = "gr"; + description = "Reject the suggested change."; + }; + }; + }; + }; + }; + + prompt_library = mkOption { + type = nullOr attrs; + default = null; + description = '' + A prompt library is a collection of prompts + that can be used in the action palette. + ''; + }; + }; + }; + }; +} diff --git a/modules/plugins/assistant/codecompanion/config.nix b/modules/plugins/assistant/codecompanion/config.nix new file mode 100644 index 00000000..6b427d28 --- /dev/null +++ b/modules/plugins/assistant/codecompanion/config.nix @@ -0,0 +1,27 @@ +{ + config, + lib, + ... +}: let + inherit (lib.modules) mkIf; + + cfg = config.vim.assistant.codecompanion-nvim; +in { + config = mkIf cfg.enable { + vim = { + startPlugins = [ + "plenary-nvim" + ]; + + lazy.plugins = { + codecompanion-nvim = { + package = "codecompanion-nvim"; + setupModule = "codecompanion"; + inherit (cfg) setupOpts; + }; + }; + + treesitter.enable = true; + }; + }; +} diff --git a/modules/plugins/assistant/codecompanion/default.nix b/modules/plugins/assistant/codecompanion/default.nix new file mode 100644 index 00000000..7f7b4452 --- /dev/null +++ b/modules/plugins/assistant/codecompanion/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./config.nix + ./codecompanion-nvim.nix + ]; +} diff --git a/modules/plugins/assistant/default.nix b/modules/plugins/assistant/default.nix index 5b5cf323..697d54f6 100644 --- a/modules/plugins/assistant/default.nix +++ b/modules/plugins/assistant/default.nix @@ -2,5 +2,6 @@ imports = [ ./chatgpt ./copilot + ./codecompanion ]; } diff --git a/modules/plugins/dashboard/alpha/alpha.nix b/modules/plugins/dashboard/alpha/alpha.nix index d5329cc7..90d02f30 100644 --- a/modules/plugins/dashboard/alpha/alpha.nix +++ b/modules/plugins/dashboard/alpha/alpha.nix @@ -1,7 +1,23 @@ {lib, ...}: let - inherit (lib.options) mkEnableOption; + inherit (lib.options) mkEnableOption mkOption; + inherit (lib.types) listOf attrsOf anything nullOr enum; in { options.vim.dashboard.alpha = { - enable = mkEnableOption "fast and fully programmable greeter for neovim [alpha.mvim]"; + enable = mkEnableOption "fast and fully programmable greeter for neovim [alpha.nvim]"; + theme = mkOption { + type = nullOr (enum ["dashboard" "startify" "theta"]); + default = "dashboard"; + description = "Alpha default theme to use"; + }; + layout = mkOption { + type = listOf (attrsOf anything); + default = []; + description = "Alpha dashboard layout"; + }; + opts = mkOption { + type = attrsOf anything; + default = {}; + description = "Optional global options"; + }; }; } diff --git a/modules/plugins/dashboard/alpha/config.nix b/modules/plugins/dashboard/alpha/config.nix index bb648a50..804189b9 100644 --- a/modules/plugins/dashboard/alpha/config.nix +++ b/modules/plugins/dashboard/alpha/config.nix @@ -5,8 +5,11 @@ }: let inherit (lib.modules) mkIf; inherit (lib.nvim.dag) entryAnywhere; + inherit (lib.nvim.lua) toLuaObject; cfg = config.vim.dashboard.alpha; + themeDefined = cfg.theme != null; + layoutDefined = cfg.layout != []; in { config = mkIf cfg.enable { vim.startPlugins = [ @@ -14,207 +17,30 @@ in { "nvim-web-devicons" ]; - # the entire credit for this dashboard configuration to https://github.com/Rishabh672003 - # honestly, excellent work - vim.pluginRC.alpha = entryAnywhere '' - local alpha = require("alpha") - local plenary_path = require("plenary.path") - local dashboard = require("alpha.themes.dashboard") - local cdir = vim.fn.getcwd() - local if_nil = vim.F.if_nil - - local nvim_web_devicons = { - enabled = true, - highlight = true, - } - - local function get_extension(fn) - local match = fn:match("^.+(%..+)$") - local ext = "" - if match ~= nil then - ext = match:sub(2) - end - return ext - end - - local function icon(fn) - local nwd = require("nvim-web-devicons") - local ext = get_extension(fn) - return nwd.get_icon(fn, ext, { default = true }) - end - - local function file_button(fn, sc, short_fn) - short_fn = short_fn or fn - local ico_txt - local fb_hl = {} - - if nvim_web_devicons.enabled then - local ico, hl = icon(fn) - local hl_option_type = type(nvim_web_devicons.highlight) - if hl_option_type == "boolean" then - if hl and nvim_web_devicons.highlight then - table.insert(fb_hl, { hl, 0, 3 }) - end - end - if hl_option_type == "string" then - table.insert(fb_hl, { nvim_web_devicons.highlight, 0, 3 }) - end - ico_txt = ico .. " " - else - ico_txt = "" - end - local file_button_el = dashboard.button(sc, ico_txt .. short_fn, "e " .. fn .. " ") - local fn_start = short_fn:match(".*[/\\]") - if fn_start ~= nil then - table.insert(fb_hl, { "Comment", #ico_txt - 2, #fn_start + #ico_txt }) - end - file_button_el.opts.hl = fb_hl - return file_button_el - end - - local default_mru_ignore = { "gitcommit" } - - local mru_opts = { - ignore = function(path, ext) - return (string.find(path, "COMMIT_EDITMSG")) or (vim.tbl_contains(default_mru_ignore, ext)) - end, - } - - --- @param start number - --- @param cwd string optional - --- @param items_number number optional number of items to generate, default = 10 - local function mru(start, cwd, items_number, opts) - opts = opts or mru_opts - items_number = if_nil(items_number, 15) - - local oldfiles = {} - for _, v in pairs(vim.v.oldfiles) do - if #oldfiles == items_number then - break - end - local cwd_cond - if not cwd then - cwd_cond = true - else - cwd_cond = vim.startswith(v, cwd) - end - local ignore = (opts.ignore and opts.ignore(v, get_extension(v))) or false - if (vim.fn.filereadable(v) == 1) and cwd_cond and not ignore then - oldfiles[#oldfiles + 1] = v - end - end - local target_width = 35 - - local tbl = {} - for i, fn in ipairs(oldfiles) do - local short_fn - if cwd then - short_fn = vim.fn.fnamemodify(fn, ":.") - else - short_fn = vim.fn.fnamemodify(fn, ":~") - end - - if #short_fn > target_width then - short_fn = plenary_path.new(short_fn):shorten(1, { -2, -1 }) - if #short_fn > target_width then - short_fn = plenary_path.new(short_fn):shorten(1, { -1 }) - end - end - - local shortcut = tostring(i + start - 1) - - local file_button_el = file_button(fn, shortcut, short_fn) - tbl[i] = file_button_el - end - return { - type = "group", - val = tbl, - opts = {}, - } - end - - local default_header = { - type = "text", - val = { - - [[███ ██ ███████ ██████ ██ ██ ██ ███ ███]], - [[████ ██ ██ ██ ██ ██ ██ ██ ████ ████]], - [[██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ████ ██]], - [[██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██]], - [[██ ████ ███████ ██████ ████ ██ ██ ██]], - - -- [[ __ ]], - -- [[ ___ ___ ___ __ __ /\_\ ___ ___ ]], - -- [[ / _ `\ / __`\ / __`\/\ \/\ \\/\ \ / __` __`\ ]], - -- [[/\ \/\ \/\ __//\ \_\ \ \ \_/ |\ \ \/\ \/\ \/\ \ ]], - -- [[\ \_\ \_\ \____\ \____/\ \___/ \ \_\ \_\ \_\ \_\]], - -- [[ \/_/\/_/\/____/\/___/ \/__/ \/_/\/_/\/_/\/_/]], - }, - opts = { - position = "center", - hl = "Type", - -- wrap = "overflow"; - }, - } - - local section_mru = { - type = "group", - val = { - { - type = "text", - val = "Recent files", - opts = { - hl = "SpecialComment", - shrink_margin = false, - position = "center", - }, - }, - { type = "padding", val = 1 }, - { - type = "group", - val = function() - return { mru(0, cdir) } - end, - opts = { shrink_margin = false }, - }, - }, - } - - local buttons = { - type = "group", - val = { - { type = "text", val = "Quick links", opts = { hl = "SpecialComment", position = "center" } }, - { type = "padding", val = 1 }, - -- TODO: buttons should be added based on whether or not the relevant plugin is available - dashboard.button("e", " New file", "ene"), -- available all the time - dashboard.button("SPC F", "󰈞 Find file"), -- telescope - dashboard.button("SPC ff", "󰊄 Live grep"), -- telescope - dashboard.button("SPC p", " Projects"), -- any project - dashboard.button("q", "󰅚 Quit", "qa"), -- available all the time - }, - position = "center", - } - - local config = { - layout = { - { type = "padding", val = 2 }, - default_header, - { type = "padding", val = 2 }, - section_mru, - { type = "padding", val = 2 }, - buttons, - }, - opts = { - margin = 5, - setup = function() - vim.cmd([[ - autocmd alpha_temp DirChanged * lua require('alpha').redraw() - ]]) - end, - }, - } - - alpha.setup(config) + vim.pluginRC.alpha = let + setupOpts = + if themeDefined + then lib.generators.mkLuaInline "require'alpha.themes.${cfg.theme}'.config" + else { + inherit (cfg) layout opts; + }; + in '' + require('alpha').setup(${toLuaObject setupOpts}) ''; + + assertions = [ + { + assertion = themeDefined || layoutDefined; + message = '' + One of 'theme' or 'layout' should be defined in Alpha configuration. + ''; + } + { + assertion = !(themeDefined && layoutDefined); + message = '' + 'theme' and 'layout' cannot be defined at the same time. + ''; + } + ]; }; } diff --git a/modules/plugins/languages/cue.nix b/modules/plugins/languages/cue.nix new file mode 100644 index 00000000..313e3233 --- /dev/null +++ b/modules/plugins/languages/cue.nix @@ -0,0 +1,51 @@ +{ + pkgs, + config, + lib, + ... +}: let + inherit (lib.options) mkEnableOption mkOption; + inherit (lib.modules) mkIf mkMerge; + inherit (lib.types) package; + inherit (lib.nvim.types) mkGrammarOption; + + cfg = config.vim.languages.cue; +in { + options.vim.languages.cue = { + enable = mkEnableOption "CUE language support"; + + treesitter = { + enable = mkEnableOption "CUE treesitter" // {default = config.vim.languages.enableTreesitter;}; + + package = mkGrammarOption pkgs "cue"; + }; + + lsp = { + enable = mkEnableOption "CUE LSP support" // {default = config.vim.languages.enableLSP;}; + + package = mkOption { + type = package; + default = pkgs.cue; + description = "cue lsp implementation"; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + (mkIf cfg.treesitter.enable { + vim.treesitter.enable = true; + vim.treesitter.grammars = [cfg.treesitter.package]; + }) + + (mkIf cfg.lsp.enable { + vim.lsp.lspconfig.enable = true; + vim.lsp.lspconfig.sources.cue-lsp = '' + lspconfig.cue.setup { + capabilities = capabilities, + on_attach = default_on_attach, + cmd = {"${cfg.lsp.package}/bin/cue", "lsp"}, + } + ''; + }) + ]); +} diff --git a/modules/plugins/languages/default.nix b/modules/plugins/languages/default.nix index 08d676b9..20acfb6c 100644 --- a/modules/plugins/languages/default.nix +++ b/modules/plugins/languages/default.nix @@ -5,6 +5,7 @@ in { ./asm.nix ./astro.nix ./bash.nix + ./cue.nix ./dart.nix ./clang.nix ./css.nix @@ -12,6 +13,7 @@ in { ./gleam.nix ./go.nix ./hcl.nix + ./helm.nix ./kotlin.nix ./html.nix ./haskell.nix diff --git a/modules/plugins/languages/helm.nix b/modules/plugins/languages/helm.nix new file mode 100644 index 00000000..d3fd636e --- /dev/null +++ b/modules/plugins/languages/helm.nix @@ -0,0 +1,89 @@ +{ + pkgs, + config, + lib, + ... +}: let + inherit (builtins) attrNames; + inherit (lib.options) mkEnableOption mkOption; + inherit (lib.modules) mkIf mkMerge; + inherit (lib.lists) isList; + inherit (lib.types) enum either listOf package str; + inherit (lib.nvim.types) mkGrammarOption; + inherit (lib.nvim.lua) expToLua; + + cfg = config.vim.languages.helm; + yamlCfg = config.vim.languages.yaml; + + helmCmd = + if isList cfg.lsp.package + then cfg.lsp.package + else ["${cfg.lsp.package}/bin/helm_ls" "serve"]; + yamlCmd = + if isList yamlCfg.lsp.package + then builtins.elemAt yamlCfg.lsp.package 0 + else "${yamlCfg.lsp.package}/bin/yaml-language-server"; + + defaultServer = "helm-ls"; + servers = { + helm-ls = { + package = pkgs.helm-ls; + lspConfig = '' + lspconfig.helm_ls.setup { + capabilities = capabilities, + on_attach = default_on_attach, + cmd = ${expToLua helmCmd}, + settings = { + ['helm-ls'] = { + yamlls = { + path = "${yamlCmd}" + } + } + } + } + ''; + }; + }; +in { + options.vim.languages.helm = { + enable = mkEnableOption "Helm language support"; + + treesitter = { + enable = mkEnableOption "Helm treesitter" // {default = config.vim.languages.enableTreesitter;}; + package = mkGrammarOption pkgs "helm"; + }; + + lsp = { + enable = mkEnableOption "Helm LSP support" // {default = config.vim.languages.enableLSP;}; + + server = mkOption { + description = "Helm LSP server to use"; + type = enum (attrNames servers); + default = defaultServer; + }; + + package = mkOption { + description = "Helm LSP server package"; + type = either package (listOf str); + default = servers.${cfg.lsp.server}.package; + }; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + (mkIf cfg.treesitter.enable { + vim.treesitter.enable = true; + vim.treesitter.grammars = [cfg.treesitter.package]; + }) + + (mkIf cfg.lsp.enable { + vim.lsp.lspconfig.enable = true; + vim.lsp.lspconfig.sources.helm-lsp = servers.${cfg.lsp.server}.lspConfig; + }) + + { + # Enables filetype detection + vim.startPlugins = [pkgs.vimPlugins.vim-helm]; + } + ]); +} diff --git a/modules/plugins/languages/nix.nix b/modules/plugins/languages/nix.nix index 1ae2693e..54c11af2 100644 --- a/modules/plugins/languages/nix.nix +++ b/modules/plugins/languages/nix.nix @@ -121,8 +121,6 @@ ) ''; }; - - nixpkgs-fmt = null; # removed }; defaultDiagnosticsProvider = ["statix" "deadnix"]; @@ -219,7 +217,6 @@ in { ${concatStringsSep ", " (attrNames formats)} ''; } - { assertion = cfg.lsp.server != "rnix"; message = '' diff --git a/modules/plugins/languages/php.nix b/modules/plugins/languages/php.nix index d921b11d..4dccc8cd 100644 --- a/modules/plugins/languages/php.nix +++ b/modules/plugins/languages/php.nix @@ -64,6 +64,26 @@ } ''; }; + + intelephense = { + package = pkgs.intelephense; + lspConfig = '' + lspconfig.intelephense.setup{ + capabilities = capabilities, + on_attach = default_on_attach, + cmd = ${ + if isList cfg.lsp.package + then expToLua cfg.lsp.package + else '' + { + "${getExe cfg.lsp.package}", + "--stdio" + }, + '' + } + } + ''; + }; }; in { options.vim.languages.php = { diff --git a/modules/plugins/languages/rust.nix b/modules/plugins/languages/rust.nix index 7e9cb627..aea10687 100644 --- a/modules/plugins/languages/rust.nix +++ b/modules/plugins/languages/rust.nix @@ -62,6 +62,15 @@ in { description = "Options to pass to rust analyzer"; type = str; default = ""; + example = '' + ['rust-analyzer'] = { + cargo = {allFeature = true}, + checkOnSave = true, + procMacro = { + enable = true, + }, + }, + ''; }; }; @@ -142,6 +151,9 @@ in { then expToLua cfg.lsp.package else ''{"${cfg.lsp.package}/bin/rust-analyzer"}'' }, + default_settings = { + ${cfg.lsp.opts} + }, on_attach = function(client, bufnr) default_on_attach(client, bufnr) local opts = { noremap=true, silent=true, buffer = bufnr } diff --git a/modules/plugins/languages/yaml.nix b/modules/plugins/languages/yaml.nix index ef17b964..c84b17cd 100644 --- a/modules/plugins/languages/yaml.nix +++ b/modules/plugins/languages/yaml.nix @@ -14,14 +14,27 @@ cfg = config.vim.languages.yaml; + onAttach = + if config.vim.languages.helm.lsp.enable + then '' + on_attach = function(client, bufnr) + local filetype = vim.bo[bufnr].filetype + if filetype == "helm" then + client.stop() + end + end'' + else "on_attach = default_on_attach"; + defaultServer = "yaml-language-server"; servers = { yaml-language-server = { package = pkgs.nodePackages.yaml-language-server; lspConfig = '' + + lspconfig.yamlls.setup { - capabilities = capabilities; - on_attach = default_on_attach; + capabilities = capabilities, + ${onAttach}, cmd = ${ if isList cfg.lsp.package then expToLua cfg.lsp.package diff --git a/modules/plugins/lsp/otter/config.nix b/modules/plugins/lsp/otter/config.nix index c8a2d3c6..b1b045d8 100644 --- a/modules/plugins/lsp/otter/config.nix +++ b/modules/plugins/lsp/otter/config.nix @@ -15,13 +15,12 @@ mappings = addDescriptionsToMappings cfg.otter-nvim.mappings mappingDefinitions; in { config = mkIf (cfg.enable && cfg.otter-nvim.enable) { - assertions = [ - { - assertion = !config.vim.utility.ccc.enable; - message = '' - ccc and otter have a breaking conflict. It's been reported upstream. Until it's fixed, disable one of them - ''; - } + warnings = [ + # TODO: remove warning when we update to nvim 0.11 + (mkIf config.vim.utility.ccc.enable '' + ccc and otter occasionally have small conflicts that will disappear with nvim 0.11. + In the meantime, otter handles it by throwing a warning, but both plugins will work. + '') ]; vim = { startPlugins = ["otter-nvim"]; diff --git a/modules/plugins/statusline/lualine/lualine.nix b/modules/plugins/statusline/lualine/lualine.nix index 6e95f03b..9943f78e 100644 --- a/modules/plugins/statusline/lualine/lualine.nix +++ b/modules/plugins/statusline/lualine/lualine.nix @@ -21,6 +21,17 @@ "codedark" "dracula" "everforest" + "github_dark" + "github_light" + "github_dark_dimmed" + "github_dark_default" + "github_light_default" + "github_dark_high_contrast" + "github_light_high_contrast" + "github_dark_colorblind" + "github_light_colorblind" + "github_dark_tritanopia" + "github_light_tritanopia" "gruvbox" "gruvbox_dark" "gruvbox_light" diff --git a/modules/plugins/theme/supported-themes.nix b/modules/plugins/theme/supported-themes.nix index 4029a1c0..0b5cb90b 100644 --- a/modules/plugins/theme/supported-themes.nix +++ b/modules/plugins/theme/supported-themes.nix @@ -195,4 +195,20 @@ in { vim.cmd.colorscheme("nord") ''; }; + github = { + setup = { + style ? "dark", + transparent ? false, + ... + }: '' + require('github-theme').setup({ + options = { + transparent = ${boolToString transparent}, + }, + }) + + vim.cmd[[colorscheme github_${style}]] + ''; + styles = ["dark" "light" "dark_dimmed" "dark_default" "light_default" "dark_high_contrast" "light_high_contrast" "dark_colorblind" "light_colorblind" "dark_tritanopia" "light_tritanopia"]; + }; } diff --git a/modules/plugins/utility/default.nix b/modules/plugins/utility/default.nix index 0f0956fb..a1574b97 100644 --- a/modules/plugins/utility/default.nix +++ b/modules/plugins/utility/default.nix @@ -6,6 +6,7 @@ ./direnv ./fzf-lua ./gestures + ./harpoon ./icon-picker ./images ./leetcode-nvim diff --git a/modules/plugins/utility/harpoon/config.nix b/modules/plugins/utility/harpoon/config.nix new file mode 100644 index 00000000..487e67e4 --- /dev/null +++ b/modules/plugins/utility/harpoon/config.nix @@ -0,0 +1,41 @@ +{ + options, + config, + lib, + ... +}: let + inherit (lib.modules) mkIf; + inherit (lib.nvim.binds) pushDownDefault mkKeymap; + + cfg = config.vim.navigation.harpoon; + + keys = cfg.mappings; + inherit (options.vim.navigation.harpoon) mappings; +in { + config = mkIf cfg.enable { + vim = { + startPlugins = ["plenary-nvim"]; + + lazy.plugins.harpoon = { + package = "harpoon"; + setupModule = "harpoon"; + inherit (cfg) setupOpts; + + cmd = ["Harpoon"]; + + keys = [ + (mkKeymap "n" keys.markFile "lua require('harpoon'):list():add()" {desc = mappings.markFile.description;}) + (mkKeymap "n" keys.listMarks "lua require('harpoon').ui:toggle_quick_menu(require('harpoon'):list())" {desc = mappings.listMarks.description;}) + (mkKeymap "n" keys.file1 "lua require('harpoon'):list():select(1)" {desc = mappings.file1.description;}) + (mkKeymap "n" keys.file2 "lua require('harpoon'):list():select(2)" {desc = mappings.file2.description;}) + (mkKeymap "n" keys.file3 "lua require('harpoon'):list():select(3)" {desc = mappings.file3.description;}) + (mkKeymap "n" keys.file4 "lua require('harpoon'):list():select(4)" {desc = mappings.file4.description;}) + ]; + }; + + binds.whichKey.register = pushDownDefault { + "a" = "Harpoon Mark"; + }; + }; + }; +} diff --git a/modules/plugins/utility/harpoon/default.nix b/modules/plugins/utility/harpoon/default.nix new file mode 100644 index 00000000..21637c5b --- /dev/null +++ b/modules/plugins/utility/harpoon/default.nix @@ -0,0 +1,6 @@ +{ + imports = [ + ./harpoon.nix + ./config.nix + ]; +} diff --git a/modules/plugins/utility/harpoon/harpoon.nix b/modules/plugins/utility/harpoon/harpoon.nix new file mode 100644 index 00000000..4478c938 --- /dev/null +++ b/modules/plugins/utility/harpoon/harpoon.nix @@ -0,0 +1,53 @@ +{lib, ...}: let + inherit (lib.options) mkEnableOption mkOption; + inherit (lib.types) bool; + inherit (lib.nvim.binds) mkMappingOption; + inherit (lib.nvim.types) mkPluginSetupOption luaInline; + inherit (lib.generators) mkLuaInline; +in { + options.vim.navigation.harpoon = { + mappings = { + markFile = mkMappingOption "Mark file [Harpoon]" "a"; + listMarks = mkMappingOption "List marked files [Harpoon]" ""; + file1 = mkMappingOption "Go to marked file 1 [Harpoon]" ""; + file2 = mkMappingOption "Go to marked file 2 [Harpoon]" ""; + file3 = mkMappingOption "Go to marked file 3 [Harpoon]" ""; + file4 = mkMappingOption "Go to marked file 4 [Harpoon]" ""; + }; + + enable = mkEnableOption "Quick bookmarks on keybinds [Harpoon]"; + + setupOpts = mkPluginSetupOption "Harpoon" { + defaults = { + save_on_toggle = mkOption { + type = bool; + default = false; + description = '' + Any time the ui menu is closed then we will save the + state back to the backing list, not to the fs + ''; + }; + sync_on_ui_close = mkOption { + type = bool; + default = false; + description = '' + Any time the ui menu is closed then the state of the + list will be sync'd back to the fs + ''; + }; + key = mkOption { + type = luaInline; + default = mkLuaInline '' + function() + return vim.loop.cwd() + end + ''; + description = '' + How the out list key is looked up. This can be useful + when using worktrees and using git remote instead of file path + ''; + }; + }; + }; + }; +} diff --git a/npins/sources.json b/npins/sources.json index a68a1ea4..a1d5d19c 100644 --- a/npins/sources.json +++ b/npins/sources.json @@ -243,6 +243,18 @@ "url": "https://github.com/ray-x/cmp-treesitter/archive/958fcfa0d8ce46d215e19cc3992c542f576c4123.tar.gz", "hash": "05as01c2f7i20zkzpqbq9n8ji9bcwd678ixmxnrz9vmz5zsj8q7i" }, + "codecompanion-nvim": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "olimorris", + "repo": "codecompanion.nvim" + }, + "branch": "main", + "revision": "dd81bd9176daba9ea507cd0457f662c0a15c001f", + "url": "https://github.com/olimorris/codecompanion.nvim/archive/dd81bd9176daba9ea507cd0457f662c0a15c001f.tar.gz", + "hash": "09a20q1hshp07nf9n8w4cxpa8s32vwyd4ya0gdnx5jp7g00dksrg" + }, "codewindow-nvim": { "type": "Git", "repository": { @@ -483,6 +495,18 @@ "url": "https://github.com/akinsho/git-conflict.nvim/archive/a1badcd070d176172940eb55d9d59029dad1c5a6.tar.gz", "hash": "05rnwhm1fmg3yb7j2xc9nmw262jc687qxhwabn97qarrk2da0r0a" }, + "github": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "projekt0n", + "repo": "github-nvim-theme" + }, + "branch": "main", + "revision": "c106c9472154d6b2c74b74565616b877ae8ed31d", + "url": "https://github.com/projekt0n/github-nvim-theme/archive/c106c9472154d6b2c74b74565616b877ae8ed31d.tar.gz", + "hash": "/A4hkKTzjzeoR1SuwwklraAyI8oMkhxrwBBV9xb59PA=" + }, "gitsigns-nvim": { "type": "Git", "repository": { @@ -519,6 +543,18 @@ "url": "https://github.com/ellisonleao/gruvbox.nvim/archive/089b60e92aa0a1c6fa76ff527837cd35b6f5ac81.tar.gz", "hash": "0mr8q2xi4s2anibll8lhxax7q1akyg687bp5r58gckkhi04064q4" }, + "harpoon": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "ThePrimeagen", + "repo": "harpoon" + }, + "branch": "harpoon2", + "revision": "ed1f853847ffd04b2b61c314865665e1dadf22c7", + "url": "https://github.com/ThePrimeagen/harpoon/archive/ed1f853847ffd04b2b61c314865665e1dadf22c7.tar.gz", + "hash": "1dcpdlna2lff9dlsh6i4v16qmn5r9279wdvn0ry3xg4abqwnzc9g" + }, "haskell-tools-nvim": { "type": "Git", "repository": { @@ -1780,9 +1816,9 @@ "repo": "otter.nvim" }, "branch": "main", - "revision": "21f042f4d1a9ff4788634ad76a10033eed13c7f2", - "url": "https://github.com/jmbuhr/otter.nvim/archive/21f042f4d1a9ff4788634ad76a10033eed13c7f2.tar.gz", - "hash": "1gi603ckyxljbhkg8jhwh2pf5kvgb676ykw3sv9gvi0c2s4fb55r" + "revision": "e37053d2c6a17463e705483122eee04d41e3d4af", + "url": "https://github.com/jmbuhr/otter.nvim/archive/e37053d2c6a17463e705483122eee04d41e3d4af.tar.gz", + "hash": "0sq7x2mcxl7z0j4s3a395fy0bzz13h4rxd03lp6674y6hsjxcm55" }, "oxocarbon": { "type": "Git",