diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml index 1b734bda22..f11da7110d 100644 --- a/.github/workflows/update.yml +++ b/.github/workflows/update.yml @@ -1,39 +1,45 @@ -name: update-flake-lock +name: update on: - workflow_dispatch: # allows manual triggering - inputs: - branch: - description: "Branch to update" - type: choice - options: - - "stable & unstable" - - "main" - - "nixos-24.05" + # Runs every Saturday at noon schedule: - - cron: "0 12 * * SAT" # runs weekly on Saturday at noon + - cron: "0 12 * * SAT" + # Allow manual triggering + workflow_dispatch: + inputs: + nixos-24.05: + type: boolean + description: Also update nixos-24.05 + +# Allow one concurrent update per branch +concurrency: + group: "update-${{ github.ref_name }}" + cancel-in-progress: true + +# Allow running workflows, pushing and creating PRs +permissions: + actions: write + contents: write + pull-requests: write jobs: - lockfile: - strategy: - matrix: - # This allows to update both stable & unstable branches, but not both when triggered - # manually - branch: ["main", "nixos-24.05"] - selectedBranch: ["${{ inputs.branch }}"] - exclude: - - selectedBranch: main - branch: "nixos-24.05" - - selectedBranch: "nixos-24.05" - branch: main + update: name: Update the flake inputs and generate options runs-on: ubuntu-latest timeout-minutes: 40 + steps: - name: Checkout repository uses: actions/checkout@v4 with: - token: ${{ secrets.GH_TOKEN_FOR_UPDATES }} - ref: "${{ matrix.branch }}" + ssh-key: ${{ secrets.CI_UPDATE_SSH_KEY }} + + # NOTE: If additional "inputs" are added, copy this step + - name: Update nixos-24.05 + if: inputs['nixos-24.05'] || github.event_name == 'schedule' + env: + GH_TOKEN: ${{ github.token }} + run: | + gh workflow run update.yml --ref nixos-24.05 - name: Install Nix uses: cachix/install-nix-action@v26 @@ -41,19 +47,79 @@ jobs: nix_path: nixpkgs=channel:nixos-unstable github_access_token: ${{ secrets.GITHUB_TOKEN }} + - name: Configure git + run: | + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + - name: Update flake.lock - id: update - uses: DeterminateSystems/update-flake-lock@v21 - with: - pr-title: "Update flake.lock (${{ matrix.branch }})" - token: ${{ secrets.GH_TOKEN_FOR_UPDATES }} - branch: "update_flake_lock_action-${{ matrix.branch }}" + id: flake_lock + run: | + old=$(git show --no-patch --format=%h) + nix flake update --commit-lock-file + new=$(git show --no-patch --format=%h) + if [ "$old" != "$new" ]; then + echo "body<> "$GITHUB_OUTPUT" + git show --no-patch --format=%b >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + fi - # TODO: do in one checkout + push the flake.lock update & the re-generation of the files - name: Update autogenerated files + id: generate run: | - git checkout update_flake_lock_action-${{ matrix.branch }} - nix run .#generate-files - git add ./generated - git commit -m "generated: Update files" - git push + old=$(git show --no-patch --format=%h) + nix run .#generate-files -- --commit + new=$(git show --no-patch --format=%h) + if [ "$old" != "$new" ]; then + body=$(git show --no-patch --format=%b) + echo "body<> "$GITHUB_OUTPUT" + if [ -n "$body" ]; then + # Multi-file changes are listed in the body + echo "$body" >> "$GITHUB_OUTPUT" + else + # Single-file changes are only in the summary, + # e.g. "generated: Updated none-ls.nix" + git show --no-patch --format=%s | \ + sed -e 's/^generated:/-/' >> "$GITHUB_OUTPUT" + fi + echo "EOF" >> "$GITHUB_OUTPUT" + fi + + - name: Create Pull Request + id: pr + uses: peter-evans/create-pull-request@v6 + with: + add-paths: "!**" + branch: update/${{ github.ref_name }} + delete-branch: true + title: | + [${{ github.ref_name }}] Update flake.lock & generated files + body: | + ## Flake lockfile + ``` + ${{ steps.flake_lock.outputs.body || 'No changes' }} + ``` + + ## Generate + ${{ steps.generate.outputs.body || 'No changes' }} + + - name: Print summary + if: ${{ steps.pr.outputs.pull-request-number }} + run: | + num="${{ steps.pr.outputs.pull-request-number }}" + pr_url="${{ steps.pr.outputs.pull-request-url }}" + pr_branch="${{ steps.pr.outputs.pull-request-branch }}" + head="${{ steps.pr.outputs.pull-request-head-sha }}" + operation="${{ steps.pr.outputs.pull-request-operation }}" + + # stdout + echo "${head:0:6} pushed to ${pr_branch}" + echo "${pr} was ${operation}." + + # markdown summary + echo "## ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY + echo >> $GITHUB_STEP_SUMMARY + echo "\`${head:0:6}\` pushed to \`${pr_branch}\`" >> $GITHUB_STEP_SUMMARY + echo >> $GITHUB_STEP_SUMMARY + echo "[#${num}](${pr_url}) was ${operation}." >> $GITHUB_STEP_SUMMARY + echo >> $GITHUB_STEP_SUMMARY diff --git a/flake-modules/dev/default.nix b/flake-modules/dev/default.nix index 52f09429cb..b5a6c2456a 100644 --- a/flake-modules/dev/default.nix +++ b/flake-modules/dev/default.nix @@ -49,6 +49,7 @@ "**.svg" "**/man/*.5" ]; + formatter.ruff-format.options = [ "--isolated" ]; }; }; } diff --git a/flake-modules/tests.nix b/flake-modules/tests.nix index 5b4840079d..7e6789d4d8 100644 --- a/flake-modules/tests.nix +++ b/flake-modules/tests.nix @@ -44,6 +44,8 @@ inherit pkgs helpers; inherit (pkgs) lib; }; + + maintainers = import ../tests/maintainers.nix { inherit pkgs; }; }; }; } diff --git a/flake-modules/updates/default.nix b/flake-modules/updates/default.nix index 6f23f23d57..cbfeb51f0a 100644 --- a/flake-modules/updates/default.nix +++ b/flake-modules/updates/default.nix @@ -9,6 +9,21 @@ repo_root=$(git rev-parse --show-toplevel) generated_dir=$repo_root/generated + commit= + while [ $# -gt 0 ]; do + case "$1" in + --commit) commit=1 + ;; + --*) echo "unknown option $1" + ;; + *) echo "unexpected argument $1" + ;; + esac + shift + done + + mkdir -p "$generated_dir" + echo "Rust-Analyzer" nix build .#rust-analyzer-options cat ./result >"$generated_dir"/rust-analyzer.nix @@ -21,7 +36,45 @@ nix build .#none-ls-builtins cat ./result >"$generated_dir"/none-ls.nix + git add --intent-to-add "$generated_dir" nix fmt + + if [ -n "$commit" ]; then + cd "$generated_dir" + git add . + + # Construct a msg body from `git status -- .` + body=$( + git status \ + --short \ + --ignored=no \ + --untracked-files=no \ + --no-ahead-behind \ + -- . \ + | sed \ + -e 's/^\s*\([A-Z]\)\s*/\1 /' \ + -e 's/^A/Added/' \ + -e 's/^M/Updated/' \ + -e 's/^R/Renamed/' \ + -e 's/^D/Removed/' \ + -e 's/^/- /' + ) + + # Construct the commit message based on the body + count=$(echo -n "$body" | wc -l) + if [ "$count" -gt 1 ] || [ ''${#body} -gt 50 ]; then + msg=$(echo -e "generated: Update\n\n$body") + else + msg="generated:''${body:1}" + fi + + # Commit if there are changes + if [ "$count" -gt 0 ]; then + echo "Committing $count changes..." + echo "$msg" + git commit -m "$msg" --no-verify + fi + fi ''; }; diff --git a/flake-modules/updates/none-ls.nix b/flake-modules/updates/none-ls.nix index 8a64284cce..7a3fe3ade4 100644 --- a/flake-modules/updates/none-ls.nix +++ b/flake-modules/updates/none-ls.nix @@ -5,7 +5,7 @@ pkgs, }: let - inherit (import ../../plugins/none-ls/packages.nix pkgs) packaged noPackage unpackaged; + inherit (import ../../plugins/none-ls/packages.nix pkgs) packaged noPackage; builtinSources = lib.trivial.importJSON "${vimPlugins.none-ls-nvim.src}/doc/builtins.json"; @@ -14,11 +14,11 @@ let toolNames = lib.unique (lib.flatten (lib.attrValues builtinSourceNames)); undeclaredTool = lib.filter ( - name: !(lib.hasAttr name packaged || lib.elem name noPackage || lib.elem name unpackaged) + name: !(lib.hasAttr name packaged || lib.elem name noPackage) ) toolNames; uselesslyDeclaredTool = lib.filter (name: !(lib.elem name toolNames)) ( - unpackaged ++ noPackage ++ (lib.attrNames packaged) + noPackage ++ (lib.attrNames packaged) ); in writeText "efmls-configs-sources.nix" ( diff --git a/flake.lock b/flake.lock index 2f6e855972..5d07f15054 100644 --- a/flake.lock +++ b/flake.lock @@ -42,11 +42,11 @@ ] }, "locked": { - "lastModified": 1719877454, - "narHash": "sha256-g5N1yyOSsPNiOlFfkuI/wcUjmtah+nxdImJqrSATjOU=", + "lastModified": 1719994518, + "narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "4e3583423212f9303aa1a6337f8dffb415920e4f", + "rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7", "type": "github" }, "original": { @@ -87,11 +87,11 @@ ] }, "locked": { - "lastModified": 1719259945, - "narHash": "sha256-F1h+XIsGKT9TkGO3omxDLEb/9jOOsI6NnzsXFsZhry4=", + "lastModified": 1720524665, + "narHash": "sha256-ni/87oHPZm6Gv0ECYxr1f6uxB0UKBWJ6HvS7lwLU6oY=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "0ff4381bbb8f7a52ca4a851660fc7a437a4c6e07", + "rev": "8d6a17d0cdf411c55f12602624df6368ad86fac1", "type": "github" }, "original": { @@ -128,11 +128,11 @@ ] }, "locked": { - "lastModified": 1719827439, - "narHash": "sha256-tneHOIv1lEavZ0vQ+rgz67LPNCgOZVByYki3OkSshFU=", + "lastModified": 1720734513, + "narHash": "sha256-neWQ8eNtLTd+YMesb7WjKl1SVCbDyCm46LUgP/g/hdo=", "owner": "nix-community", "repo": "home-manager", - "rev": "59ce796b2563e19821361abbe2067c3bb4143a7d", + "rev": "90ae324e2c56af10f20549ab72014804a3064c7f", "type": "github" }, "original": { @@ -148,11 +148,11 @@ ] }, "locked": { - "lastModified": 1719845423, - "narHash": "sha256-ZLHDmWAsHQQKnmfyhYSHJDlt8Wfjv6SQhl2qek42O7A=", + "lastModified": 1720845312, + "narHash": "sha256-yPhAsJTpyoIPQZJGC8Fw8W2lAXyhLoTn+HP20bmfkfk=", "owner": "lnl7", "repo": "nix-darwin", - "rev": "ec12b88104d6c117871fad55e931addac4626756", + "rev": "5ce8503cf402cf76b203eba4b7e402bea8e44abc", "type": "github" }, "original": { @@ -163,11 +163,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1719848872, - "narHash": "sha256-H3+EC5cYuq+gQW8y0lSrrDZfH71LB4DAf+TDFyvwCNA=", + "lastModified": 1720768451, + "narHash": "sha256-EYekUHJE2gxeo2pM/zM9Wlqw1Uw2XTJXOSAO79ksc4Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "00d80d13810dbfea8ab4ed1009b09100cca86ba8", + "rev": "7e7c39ea35c5cdd002cd4588b03a3fb9ece6fad9", "type": "github" }, "original": { @@ -211,11 +211,11 @@ ] }, "locked": { - "lastModified": 1719887753, - "narHash": "sha256-p0B2r98UtZzRDM5miGRafL4h7TwGRC4DII+XXHDHqek=", + "lastModified": 1720818892, + "narHash": "sha256-f52x9srIcqQm1Df3T+xYR5P6VfdnDFa2vkkcLhlTp6U=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "bdb6355009562d8f9313d9460c0d3860f525bc6c", + "rev": "5b002f8a53ed04c1a4177e7b00809d57bd2c696f", "type": "github" }, "original": { diff --git a/generated/rust-analyzer.nix b/generated/rust-analyzer.nix index de22018a01..d4cc6c7a5e 100644 --- a/generated/rust-analyzer.nix +++ b/generated/rust-analyzer.nix @@ -28,11 +28,20 @@ ]; }; }; + "rust-analyzer.assist.termSearch.borrowcheck" = { + description = '' + Enable borrow checking for term search code assists. If set to false, also there will be more suggestions, but some of them may not borrow-check. + ''; + pluginDefault = true; + type = { + kind = "boolean"; + }; + }; "rust-analyzer.assist.termSearch.fuel" = { description = '' - Term search fuel in "units of work" for assists (Defaults to 400). + Term search fuel in "units of work" for assists (Defaults to 1800). ''; - pluginDefault = 400; + pluginDefault = 1800; type = { kind = "integer"; maximum = null; @@ -683,9 +692,9 @@ }; "rust-analyzer.completion.termSearch.fuel" = { description = '' - Term search fuel in "units of work" for autocompletion (Defaults to 200). + Term search fuel in "units of work" for autocompletion (Defaults to 1000). ''; - pluginDefault = 200; + pluginDefault = 1000; type = { kind = "integer"; maximum = null; diff --git a/lib/helpers.nix b/lib/helpers.nix index 9303780438..876ec1e94c 100644 --- a/lib/helpers.nix +++ b/lib/helpers.nix @@ -8,13 +8,21 @@ let nixvimBuilders = import ./builders.nix { inherit lib pkgs; }; nixvimTypes = import ./types.nix { inherit lib nixvimOptions; }; nixvimUtils = import ./utils.nix { inherit lib nixvimTypes _nixvimTests; }; - nixvimOptions = import ./options.nix { inherit lib nixvimTypes nixvimUtils; }; + nixvimOptions = import ./options.nix { + inherit + lib + nixvimTypes + nixvimUtils + nixvimKeymaps + ; + }; nixvimDeprecation = import ./deprecation.nix { inherit lib; }; + nixvimKeymaps = import ./keymap-helpers.nix { inherit lib nixvimOptions nixvimTypes; }; in rec { maintainers = import ./maintainers.nix; lua = import ./to-lua.nix { inherit lib; }; - keymaps = import ./keymap-helpers.nix { inherit lib nixvimOptions nixvimTypes; }; + keymaps = nixvimKeymaps; autocmd = import ./autocmd-helpers.nix { inherit lib nixvimOptions nixvimTypes; }; neovim-plugin = import ./neovim-plugin.nix { inherit diff --git a/lib/maintainers.nix b/lib/maintainers.nix index 274718e813..589fc43e04 100644 --- a/lib/maintainers.nix +++ b/lib/maintainers.nix @@ -12,14 +12,6 @@ githubId = 1176328; name = "Alison Jenkins"; }; - MattSturgeon = { - email = "matt@sturgeon.me.uk"; - matrix = "@mattsturg:matrix.org"; - github = "MattSturgeon"; - githubId = 5046562; - name = "Matt Sturgeon"; - keys = [ { fingerprint = "7082 22EA 1808 E39A 83AC 8B18 4F91 844C ED1A 8299"; } ]; - }; DanielLaing = { email = "daniel@daniellaing.com"; matrix = "@bodleum:matrix.org"; @@ -78,4 +70,10 @@ githubId = 4646110; name = "Nikita Shirokov"; }; + psfloyd = { + email = "peter.racoon@gmail.com"; + github = "psfloyd"; + githubId = 30784060; + name = "Pedro Sánchez"; + }; } diff --git a/lib/neovim-plugin.nix b/lib/neovim-plugin.nix index 46d7969f96..cb14b5f0b7 100644 --- a/lib/neovim-plugin.nix +++ b/lib/neovim-plugin.nix @@ -48,9 +48,13 @@ with lib; extraPackages ? [ ], callSetup ? true, installPackage ? true, + # lazyLoad + allowLazyLoad ? true, + lazyLoad ? { }, }: let namespace = if isColorscheme then "colorschemes" else "plugins"; + cfg = config.${namespace}.${name}; in { meta = { @@ -99,21 +103,47 @@ with lib; example = settingsExample; }; } + // optionalAttrs allowLazyLoad { + lazyLoad = nixvimOptions.mkLazyLoadOption { + inherit originalName cfg; + optionsForPlugin = true; + lazyLoad = + { + after = optionalString callSetup '' + require('${luaName}')${setup}(${optionalString (cfg ? settings) (toLuaObject cfg.settings)}) + ''; + } + // (optionalAttrs (isColorscheme && colorscheme != null) { colorscheme = [ colorscheme ]; }) + // lazyLoad; + }; + } // extraOptions; config = let - cfg = config.${namespace}.${name}; extraConfigNamespace = if isColorscheme then "extraConfigLuaPre" else "extraConfigLua"; + lazyLoaded = cfg.lazyLoad.enable or false; in mkIf cfg.enable (mkMerge [ { extraPlugins = (optional installPackage cfg.package) ++ extraPlugins; inherit extraPackages; - ${extraConfigNamespace} = optionalString callSetup '' + ${extraConfigNamespace} = optionalString (callSetup && !lazyLoaded) '' require('${luaName}')${setup}(${optionalString (cfg ? settings) (toLuaObject cfg.settings)}) ''; + + plugins.lz-n.plugins = mkIf lazyLoaded [ cfg.lazyLoad ]; + assertions = [ + { + assertion = config.plugins.lz-n.enable || !lazyLoaded; + # TODO: replace with global option after adding backend + message = '' + Nixvim (${namespace}.${name}): You have to enable `plugins.lz-n` for `${namespace}.${name}.lazyLoad` to work. + ''; + } + ]; + } (optionalAttrs (isColorscheme && (colorscheme != null)) { colorscheme = mkDefault colorscheme; }) (extraConfig cfg) diff --git a/lib/options.nix b/lib/options.nix index 016d12d10c..07dffcca07 100644 --- a/lib/options.nix +++ b/lib/options.nix @@ -2,6 +2,7 @@ lib, nixvimTypes, nixvimUtils, + nixvimKeymaps, }: with lib; with nixvimUtils; @@ -368,4 +369,63 @@ rec { else example; }; + + mkLazyLoadOption = + { + originalName ? "this plugin", + cfg ? { }, + lazyLoad ? { }, + optionsForPlugin ? false, + }: + let + pluginDefault = { + enable = false; + name = originalName; + } // lazyLoad; + in + mkOption { + description = "Lazy-load settings for ${originalName}."; + type = + with nixvimTypes; + submodule { + options = with defaultNullOpts; { + # enable option only has an effect when it is a sub-option for a plugin generated by mkNeovimPlugin + enable = mkOption { + type = bool; + default = pluginDefault.enable; + description = "Enable lazy-loading for ${originalName}"; + # Only show this option when it is a sub-option for a plugin + visible = optionsForPlugin; + }; + name = mkOption { + type = str; + default = pluginDefault.name; + description = "The plugin's name (not the module name). This is what is passed to the load(name) function."; + }; + enabledInSpec = mkStrLuaFnOr bool pluginDefault.enabledInSpec or null '' + When false, or if the function returns false, then ${originalName} will not be included in the spec. + This option corresponds to the `enabled` property of lz.n. + ''; + beforeAll = mkLuaFn pluginDefault.beforeAll + or null "Always executed before any plugins are loaded."; + before = mkLuaFn pluginDefault.before or null "Executed before ${originalName} is loaded."; + after = mkLuaFn pluginDefault.after or null "Executed after ${originalName} is loaded."; + event = + mkNullable (listOf str) pluginDefault.event or null + "Lazy-load on event. Events can be specified as `BufEnter` or with a pattern like `BufEnter *.lua`"; + cmd = mkNullable (listOf str) pluginDefault.cmd or null "Lazy-load on command."; + ft = mkNullable (listOf str) pluginDefault.ft or null "Lazy-load on filetype."; + keys = mkNullable (listOf nixvimKeymaps.mapOptionSubmodule) pluginDefault.keys + or null "Lazy-load on key mapping. Use the same format as `config.keymaps`."; + colorscheme = mkNullable (listOf str) pluginDefault.colorscheme or null "Lazy-load on colorscheme."; + priority = mkNullable number pluginDefault.priority or null '' + Only useful for start plugins (not lazy-loaded) to force loading certain plugins first. + Default priority is 50 (or 1000 if colorscheme is set). + ''; + load = mkLuaFn pluginDefault.load + or null "Can be used to override the vim.g.lz_n.load() function for ${originalName}."; + }; + }; + default = pluginDefault; + }; } diff --git a/plugins/default.nix b/plugins/default.nix index c0ca58586a..2a69a367d6 100644 --- a/plugins/default.nix +++ b/plugins/default.nix @@ -68,6 +68,7 @@ ./languages/ledger.nix ./languages/lint.nix ./languages/ltex-extra.nix + ./languages/markdown/glow.nix ./languages/markdown/markdown-preview.nix ./languages/markdown/preview.nix ./languages/nix.nix @@ -117,6 +118,7 @@ ./pluginmanagers/packer.nix ./pluginmanagers/lazy.nix + ./pluginmanagers/lz-n.nix ./snippets/friendly-snippets.nix ./snippets/luasnip @@ -147,6 +149,7 @@ ./utils/bacon.nix ./utils/baleia.nix ./utils/better-escape.nix + ./utils/bufdelete.nix ./utils/ccc.nix ./utils/clipboard-image.nix ./utils/cloak.nix diff --git a/plugins/languages/markdown/glow.nix b/plugins/languages/markdown/glow.nix new file mode 100644 index 0000000000..f9b6c725dc --- /dev/null +++ b/plugins/languages/markdown/glow.nix @@ -0,0 +1,87 @@ +{ + lib, + helpers, + config, + pkgs, + ... +}: +helpers.neovim-plugin.mkNeovimPlugin config { + name = "glow"; + originalName = "glow.nvim"; + defaultPackage = pkgs.vimPlugins.glow-nvim; + + maintainers = [ lib.maintainers.getchoo ]; + + settingsOptions = { + glow_path = helpers.defaultNullOpts.mkStr (helpers.mkRaw "vim.fn.exepath('glow')") '' + Path to `glow` binary. + + If null or `""`, `glow` in your `$PATH` with be used if available. + + Using `glowPackage` is the recommended way to make `glow` available in your `$PATH`. + ''; + + install_path = helpers.defaultNullOpts.mkStr "~/.local/bin" '' + Path for installing `glow` binary if one is not found at `glow_path` or in your `$PATH`. + + Consider using `glowPackage` instead. + ''; + + border = helpers.defaultNullOpts.mkEnumFirstDefault [ + "shadow" + "none" + "double" + "rounded" + "solid" + "single" + ] "Style of the floating window's border."; + + style = helpers.defaultNullOpts.mkEnum [ + "dark" + "light" + ] (helpers.mkRaw "vim.opt.background") "Glow style."; + + pager = helpers.defaultNullOpts.mkBool false '' + Display output in a pager style. + ''; + + width = helpers.defaultNullOpts.mkInt 100 '' + Width of the floating window. + ''; + + height = helpers.defaultNullOpts.mkInt 100 '' + Height of the floating window. + ''; + + width_ratio = helpers.defaultNullOpts.mkNum 0.7 '' + Maximum width of the floating window relative to the window size. + ''; + + height_ratio = helpers.defaultNullOpts.mkNum 0.7 '' + Maximum height of the floating window relative to the window size. + ''; + }; + + settingsExample = { + border = "shadow"; + style = "dark"; + pager = false; + width = 80; + height = 100; + width_ratio = 0.7; + height_ratio = 0.7; + }; + + extraOptions = { + glowPackage = helpers.mkPackageOption { + description = '' + Which package to use for `glow` in your `$PATH`. + Set to `null` to disable its automatic installation. + ''; + default = pkgs.glow; + defaultText = lib.literalExpression "pkgs.glow"; + }; + }; + + extraConfig = cfg: { extraPackages = [ cfg.glowPackage ]; }; +} diff --git a/plugins/languages/qmk.nix b/plugins/languages/qmk.nix index 1b4dd71b20..2685277c5b 100644 --- a/plugins/languages/qmk.nix +++ b/plugins/languages/qmk.nix @@ -15,7 +15,8 @@ helpers.neovim-plugin.mkNeovimPlugin config { settingsOptions = { name = mkOption { - type = types.str; + type = with types; nullOr str; + default = null; example = "LAYOUT_preonic_grid"; description = '' The name of your layout, for example `LAYOUT_preonic_grid` for the preonic keyboard, for @@ -24,7 +25,8 @@ helpers.neovim-plugin.mkNeovimPlugin config { }; layout = mkOption { - type = with types; listOf str; + type = with types; nullOr (listOf str); + default = null; example = [ "x x" "x^x" diff --git a/plugins/languages/rust/rustaceanvim/default.nix b/plugins/languages/rust/rustaceanvim/default.nix index 3fb6c3eb1c..78fd23431f 100644 --- a/plugins/languages/rust/rustaceanvim/default.nix +++ b/plugins/languages/rust/rustaceanvim/default.nix @@ -34,7 +34,7 @@ helpers.neovim-plugin.mkNeovimPlugin config { "nightly" "rust-analyzer" ]; - settings = { + default_settings = { rust-analyzer = { inlayHints = { lifetimeElisionHints = { @@ -58,7 +58,23 @@ helpers.neovim-plugin.mkNeovimPlugin config { ''; in mkMerge [ - { extraPackages = [ cfg.rustAnalyzerPackage ]; } + { + extraPackages = [ cfg.rustAnalyzerPackage ]; + # TODO: remove after 24.11 + warnings = + optional + (hasAttrByPath [ + "settings" + "server" + "settings" + ] cfg) + '' + The `plugins.rustaceanvim.settings.server.settings' option has been renamed to `plugins.rustaceanvim.settings.server.default_settings'. + + Note that if you supplied an attrset and not a function you need to set this attr set in: + `plugins.rustaceanvim.settings.server.default_settings.rust-analyzer'. + ''; + } # If nvim-lspconfig is enabled: (mkIf config.plugins.lsp.enable { # Use the same `on_attach` callback as for the other LSP servers diff --git a/plugins/languages/rust/rustaceanvim/settings-options.nix b/plugins/languages/rust/rustaceanvim/settings-options.nix index b135ca46bf..5333dfd281 100644 --- a/plugins/languages/rust/rustaceanvim/settings-options.nix +++ b/plugins/languages/rust/rustaceanvim/settings-options.nix @@ -254,10 +254,10 @@ with lib; ``` ''; - settings = + default_settings = helpers.mkNullOrStrLuaFnOr (types.submodule { - options = import ../../../lsp/language-servers/rust-analyzer-config.nix lib helpers; + options.rust-analyzer = import ../../../lsp/language-servers/rust-analyzer-config.nix lib helpers; freeformType = with types; attrsOf anything; }) '' diff --git a/plugins/languages/treesitter/injections.scm b/plugins/languages/treesitter/injections.scm index 8823342242..fb7958161b 100644 --- a/plugins/languages/treesitter/injections.scm +++ b/plugins/languages/treesitter/injections.scm @@ -1,17 +1,40 @@ ;; extends (binding - attrpath: (attrpath (identifier) @_path) + attrpath: (attrpath + (identifier) @_path) expression: [ - (string_expression (string_fragment) @lua) - (indented_string_expression (string_fragment) @lua) + (string_expression + ((string_fragment) @injection.content + (#set! injection.language "lua"))) + (indented_string_expression + ((string_fragment) @injection.content + (#set! injection.language "lua"))) ] - (#match? @_path "^extraConfigLua(Pre|Post)?$")) + (#match? @_path "(^(extraConfigLua(Pre|Post)?|__raw))$")) + +(apply_expression + function: (_) @_func + argument: [ + (string_expression + ((string_fragment) @injection.content + (#set! injection.language "lua"))) + (indented_string_expression + ((string_fragment) @injection.content + (#set! injection.language "lua"))) + ] + (#match? @_func "(^|\\.)mkRaw$") + (#set! injection.combined)) (binding - attrpath: (attrpath (identifier) @_path) + attrpath: (attrpath + (identifier) @_path) expression: [ - (string_expression (string_fragment) @vim) - (indented_string_expression (string_fragment) @vim) + (string_expression + ((string_fragment) @injection.content + (#set! injection.language "vim"))) + (indented_string_expression + ((string_fragment) @injection.content + (#set! injection.language "vim"))) ] - (#match? @_path "^extraConfigVim(Pre|Post)?$")) + (#match? @_path "(^extraConfigVim(Pre|Post)?)$")) diff --git a/plugins/languages/treesitter/treesitter.nix b/plugins/languages/treesitter/treesitter.nix index 63131c3229..497d98bc07 100644 --- a/plugins/languages/treesitter/treesitter.nix +++ b/plugins/languages/treesitter/treesitter.nix @@ -134,20 +134,37 @@ helpers.neovim-plugin.mkNeovimPlugin config { ''; }; - ensure_installed = helpers.defaultNullOpts.mkListOf types.str [ ] '' - Either "all" or a list of languages to ensure installing. - ''; + ensure_installed = helpers.defaultNullOpts.mkNullable' { + type = + with helpers.nixvimTypes; + oneOf [ + (enum [ "all" ]) + (listOf (maybeRaw str)) + rawLua + ]; + pluginDefault = [ ]; + description = '' + Either `"all"` or a list of languages to ensure installing. + ''; + }; ignore_install = helpers.defaultNullOpts.mkListOf types.str [ ] '' - List of parsers to ignore installing. Used when `ensure_installed` is set to "all". + List of parsers to ignore installing. Used when `ensure_installed` is set to `"all"`. ''; - parser_install_dir = helpers.defaultNullOpts.mkStr "$XDG_DATA_HOME/nvim/treesitter" '' - Location of the parsers to be installed by the plugin (only needed when `nixGrammars` is disabled). + parser_install_dir = helpers.mkNullOrOption' { + type = with helpers.nixvimTypes; maybeRaw str; + # Backport the default from nvim-treesitter 1.0 + # The current default doesn't work on nix, as it is readonly + default.__raw = "vim.fs.joinpath(vim.fn.stdpath('data'), 'site')"; + pluginDefault = lib.literalMD "the plugin's package directory"; + description = '' + Location of the parsers to be installed by the plugin (only needed when `nixGrammars` is disabled). - This default might not work on your own install, please make sure that `$XDG_DATA_HOME` is set if you want to use the default. - Otherwise, change it to something that will work for you! - ''; + By default, parsers are installed to the "site" dir. + If set to `null` the _plugin default_ is used, which will not work on nix. + ''; + }; sync_install = helpers.defaultNullOpts.mkBool false '' Install parsers synchronously (only applied to `ensure_installed`). @@ -156,9 +173,9 @@ helpers.neovim-plugin.mkNeovimPlugin config { settingsExample = { auto_install = false; - ensure_installed = [ "all" ]; + ensure_installed = "all"; ignore_install = [ "rust" ]; - parser_install_dir = "$XDG_DATA_HOME/nvim/treesitter"; + parser_install_dir.__raw = "vim.fs.joinpath(vim.fn.stdpath('data'), 'treesitter')"; sync_install = false; highlight = { @@ -186,12 +203,7 @@ helpers.neovim-plugin.mkNeovimPlugin config { }; extraOptions = { - folding = mkOption { - type = types.bool; - default = true; - example = false; - description = "Whether to enable treesitter folding."; - }; + folding = mkEnableOption "tree-sitter based folding"; gccPackage = helpers.mkPackageOption { name = "gcc"; @@ -284,7 +296,7 @@ helpers.neovim-plugin.mkNeovimPlugin config { # NOTE: Upstream state that the parser MUST be at the beginning of runtimepath. # Otherwise the parsers from Neovim takes precedent, which may be incompatible with some queries. (optionalString (cfg.settings.parser_install_dir != null) '' - vim.opt.runtimepath:prepend("${cfg.settings.parser_install_dir}") + vim.opt.runtimepath:prepend(${helpers.toLuaObject cfg.settings.parser_install_dir}) '') + '' require('nvim-treesitter.configs').setup(${helpers.toLuaObject cfg.settings}) @@ -312,9 +324,9 @@ helpers.neovim-plugin.mkNeovimPlugin config { cfg.treesitterPackage ]; - opts = mkIf cfg.folding (mkDefault { - foldmethod = "expr"; - foldexpr = "nvim_treesitter#foldexpr()"; - }); + opts = mkIf cfg.folding { + foldmethod = mkDefault "expr"; + foldexpr = mkDefault "nvim_treesitter#foldexpr()"; + }; }; } diff --git a/plugins/none-ls/_mk-source-plugin.nix b/plugins/none-ls/_mk-source-plugin.nix new file mode 100644 index 0000000000..2cf25577b9 --- /dev/null +++ b/plugins/none-ls/_mk-source-plugin.nix @@ -0,0 +1,55 @@ +# mkSourcePlugin, returns a module +sourceType: sourceName: +{ + config, + pkgs, + lib, + helpers, + ... +}: +let + inherit (import ./packages.nix pkgs) packaged; + pkg = packaged.${sourceName}; + + cfg = config.plugins.none-ls; + cfg' = config.plugins.none-ls.sources.${sourceType}.${sourceName}; +in +{ + options.plugins.none-ls.sources.${sourceType}.${sourceName} = + { + enable = lib.mkEnableOption "the ${sourceName} ${sourceType} source for none-ls"; + withArgs = helpers.mkNullOrOption helpers.nixvimTypes.strLua '' + Raw Lua code passed as an argument to the source's `with` method. + ''; + } + # Only declare a package option if a package is required + // lib.optionalAttrs (packaged ? ${sourceName}) { + package = lib.mkOption ( + { + type = lib.types.nullOr lib.types.package; + description = + "Package to use for ${sourceName}." + + (lib.optionalString (pkg == null) ( + "\n\n" + + '' + Currently not packaged in nixpkgs. + Either set this to `null` and install ${sourceName} outside of nix, + or set this to a custom nix package. + '' + )); + } + // lib.optionalAttrs (pkg != null) { default = pkg; } + ); + }; + + config = lib.mkIf (cfg.enable && cfg'.enable) { + plugins.none-ls.settings.sources = lib.mkDefault [ + ( + "require('null-ls').builtins.${sourceType}.${sourceName}" + + lib.optionalString (cfg'.withArgs != null) ".with(${cfg'.withArgs})" + ) + ]; + + extraPackages = [ (cfg'.package or null) ]; + }; +} diff --git a/plugins/none-ls/default.nix b/plugins/none-ls/default.nix index e4e7b387cb..7b63befe2b 100644 --- a/plugins/none-ls/default.nix +++ b/plugins/none-ls/default.nix @@ -51,7 +51,7 @@ helpers.neovim-plugin.mkNeovimPlugin config { settingsPath = basePluginPath ++ [ "settings" ]; in [ - ./servers.nix + ./sources.nix (mkRenamedOptionModule oldPluginPath basePluginPath) (mkRenamedOptionModule (basePluginPath ++ [ "sourcesItems" ]) (settingsPath ++ [ "sources" ])) ]; diff --git a/plugins/none-ls/packages.nix b/plugins/none-ls/packages.nix index 146160fdf2..1b3f7edb76 100644 --- a/plugins/none-ls/packages.nix +++ b/plugins/none-ls/packages.nix @@ -1,46 +1,4 @@ pkgs: { - # builtin sources that are not packaged in nixpkgs - unpackaged = [ - "blade_formatter" - "bsfmt" - "bslint" - "cljstyle" - "cueimports" - "erb_lint" - "findent" - "forge_fmt" - "gccdiag" - "gersemi" - "markuplint" - "mlint" - "nginx_beautifier" - "npm_groovy_lint" - "ocdc" - "packer" - "perlimports" - "pint" - "pretty_php" - "purs_tidy" - "pyink" - "reek" - "regal" - "remark" - "rescript" - "saltlint" - "solhint" - "spectral" - "sqlfmt" - "sql_formatter" - "styler" - "stylint" - "swiftformat" - "swiftlint" - "textidote" - "textlint" - "twigcs" - "vacuum" - ]; - # builtin sources that don't require a package noPackage = [ "gitrebase" @@ -60,163 +18,205 @@ pkgs: { ]; # nixpkgs packages for a given source - packaged = { - inherit (pkgs) - actionlint - alejandra - asmfmt - astyle - bibclean - biome - buf - cbfmt - checkmake - checkstyle - clazy - codespell - commitlint - cppcheck - csharpier - deadnix - dfmt - djhtml - djlint - erlfmt - fantomas - fish - fnlfmt - fprettify - gitlint - gofumpt - golines - hadolint - hclfmt - isort - joker - just - ktlint - leptosfmt - mdformat - mdl - mypy - pmd - prettierd - proselint - protolint - pylint - revive - rstcheck - rubocop - rubyfmt - rufo - rustywind - scalafmt - selene - semgrep - shellharden - shfmt - smlfmt - sqlfluff - statix - stylelint - stylua - tfsec - topiary - treefmt - trivy - typstfmt - typstyle - uncrustify - usort - vale - verilator - yamlfix - yamlfmt - yamllint - yapf - zprint - zsh - ; - inherit (pkgs.nodePackages) alex prettier; - inherit (pkgs.python3.pkgs) black; - inherit (pkgs.phpPackages) phpmd phpstan; - inherit (pkgs.rubyPackages) htmlbeautifier; - inherit (pkgs.ocamlPackages) ocamlformat; - ansiblelint = pkgs.ansible-lint; - bean_check = pkgs.beancount; - bean_format = pkgs.beancount; - blackd = pkgs.black; - buildifier = pkgs.bazel-buildtools; - cfn_lint = pkgs.python3.pkgs.cfn-lint; - clang_format = pkgs.clang-tools; - clj_kondo = pkgs.clj-kondo; - cmake_format = pkgs.cmake-format; - cmake_lint = pkgs.cmake-format; - credo = pkgs.elixir; - crystal_format = pkgs.crystal; - cue_fmt = pkgs.cue; - d2_fmt = pkgs.d2; - dart_format = pkgs.dart; - dictionary = pkgs.curl; - dotenv_linter = pkgs.dotenv-linter; - dxfmt = pkgs.dioxus-cli; - editorconfig_checker = pkgs.editorconfig-checker; - elm_format = pkgs.elmPackages.elm-format; - emacs_scheme_mode = pkgs.emacs; - emacs_vhdl_mode = pkgs.emacs; - erb_format = pkgs.rubyPackages.erb-formatter; - fish_indent = pkgs.fish; - format_r = pkgs.R; - # TODO: Added 2024-06-13; remove 2024-09-13 - # Nixpkgs renamed to _3 & _4 without maintaining an alias - # Out of sync lock files could be using either attr name... - gdformat = pkgs.gdtoolkit_4 or pkgs.gdtoolkit; - gdlint = pkgs.gdtoolkit_4 or pkgs.gdtoolkit; - gitsigns = pkgs.git; - gleam_format = pkgs.gleam; - glslc = pkgs.shaderc; - gn_format = pkgs.gn; - gofmt = pkgs.go; - goimports = pkgs.gotools; - goimports_reviser = pkgs.goimports-reviser; - golangci_lint = pkgs.golangci-lint; - google_java_format = pkgs.google-java-format; - haml_lint = pkgs.mastodon; - haxe_formatter = pkgs.haxe; - isortd = pkgs.isort; - ltrs = pkgs.languagetool-rust; - markdownlint_cli2 = pkgs.markdownlint-cli2; - markdownlint = pkgs.nodePackages.markdownlint-cli; - mix = pkgs.elixir; - nimpretty = pkgs.nim; - nixfmt = pkgs.nixfmt-classic; - nixpkgs_fmt = pkgs.nixpkgs-fmt; - opacheck = pkgs.open-policy-agent; - opentofu_fmt = pkgs.opentofu; - pg_format = pkgs.pgformatter; - phpcbf = pkgs.phpPackages.php-codesniffer; - phpcsfixer = pkgs.phpPackages.php-cs-fixer; - phpcs = pkgs.phpPackages.php-codesniffer; - prisma_format = pkgs.nodePackages.prisma; - ptop = pkgs.fpc; - puppet_lint = pkgs.puppet-lint; - qmlformat = pkgs.qt6.qtdeclarative; - qmllint = pkgs.qt6.qtdeclarative; - racket_fixw = pkgs.racket; - raco_fmt = pkgs.racket; - rego = pkgs.open-policy-agent; - rpmspec = pkgs.rpm; - sqlformat = pkgs.python3.pkgs.sqlparse; - staticcheck = pkgs.go-tools; - surface = pkgs.elixir; - swift_format = pkgs.swift-format; - teal = pkgs.luaPackages.tl; - terraform_fmt = pkgs.terraform; - terraform_validate = pkgs.terraform; - tidy = pkgs.html-tidy; - verible_verilog_format = pkgs.verible; - vint = pkgs.vim-vint; - write_good = pkgs.write-good; - xmllint = pkgs.libxml2; - }; + packaged = + { + inherit (pkgs) + actionlint + alejandra + asmfmt + astyle + bibclean + biome + buf + cbfmt + checkmake + checkstyle + clazy + codespell + commitlint + cppcheck + csharpier + deadnix + dfmt + djhtml + djlint + erlfmt + fantomas + fish + fnlfmt + fprettify + gitlint + gofumpt + golines + hadolint + hclfmt + isort + joker + just + ktlint + leptosfmt + mdformat + mdl + mypy + pmd + prettierd + proselint + protolint + pylint + revive + rstcheck + rubocop + rubyfmt + rufo + rustywind + scalafmt + selene + semgrep + shellharden + shfmt + smlfmt + sqlfluff + statix + stylelint + stylua + tfsec + topiary + treefmt + trivy + typstfmt + typstyle + uncrustify + usort + vale + verilator + yamlfix + yamlfmt + yamllint + yapf + zprint + zsh + ; + inherit (pkgs.nodePackages) alex prettier; + inherit (pkgs.python3.pkgs) black; + inherit (pkgs.phpPackages) phpmd phpstan; + inherit (pkgs.rubyPackages) htmlbeautifier; + inherit (pkgs.ocamlPackages) ocamlformat; + ansiblelint = pkgs.ansible-lint; + bean_check = pkgs.beancount; + bean_format = pkgs.beancount; + blackd = pkgs.black; + buildifier = pkgs.bazel-buildtools; + cfn_lint = pkgs.python3.pkgs.cfn-lint; + clang_format = pkgs.clang-tools; + clj_kondo = pkgs.clj-kondo; + cmake_format = pkgs.cmake-format; + cmake_lint = pkgs.cmake-format; + credo = pkgs.elixir; + crystal_format = pkgs.crystal; + cue_fmt = pkgs.cue; + d2_fmt = pkgs.d2; + dart_format = pkgs.dart; + dictionary = pkgs.curl; + dotenv_linter = pkgs.dotenv-linter; + dxfmt = pkgs.dioxus-cli; + editorconfig_checker = pkgs.editorconfig-checker; + elm_format = pkgs.elmPackages.elm-format; + emacs_scheme_mode = pkgs.emacs; + emacs_vhdl_mode = pkgs.emacs; + erb_format = pkgs.rubyPackages.erb-formatter; + fish_indent = pkgs.fish; + format_r = pkgs.R; + # TODO: Added 2024-06-13; remove 2024-09-13 + # Nixpkgs renamed to _3 & _4 without maintaining an alias + # Out of sync lock files could be using either attr name... + gdformat = pkgs.gdtoolkit_4 or pkgs.gdtoolkit; + gdlint = pkgs.gdtoolkit_4 or pkgs.gdtoolkit; + gitsigns = pkgs.git; + gleam_format = pkgs.gleam; + glslc = pkgs.shaderc; + gn_format = pkgs.gn; + gofmt = pkgs.go; + goimports = pkgs.gotools; + goimports_reviser = pkgs.goimports-reviser; + golangci_lint = pkgs.golangci-lint; + google_java_format = pkgs.google-java-format; + haml_lint = pkgs.mastodon; + haxe_formatter = pkgs.haxe; + isortd = pkgs.isort; + ltrs = pkgs.languagetool-rust; + markdownlint_cli2 = pkgs.markdownlint-cli2; + markdownlint = pkgs.nodePackages.markdownlint-cli; + mix = pkgs.elixir; + nimpretty = pkgs.nim; + nixfmt = pkgs.nixfmt-classic; + nixpkgs_fmt = pkgs.nixpkgs-fmt; + opacheck = pkgs.open-policy-agent; + opentofu_fmt = pkgs.opentofu; + pg_format = pkgs.pgformatter; + phpcbf = pkgs.phpPackages.php-codesniffer; + phpcsfixer = pkgs.phpPackages.php-cs-fixer; + phpcs = pkgs.phpPackages.php-codesniffer; + prisma_format = pkgs.nodePackages.prisma; + ptop = pkgs.fpc; + puppet_lint = pkgs.puppet-lint; + qmlformat = pkgs.qt6.qtdeclarative; + qmllint = pkgs.qt6.qtdeclarative; + racket_fixw = pkgs.racket; + raco_fmt = pkgs.racket; + rego = pkgs.open-policy-agent; + rpmspec = pkgs.rpm; + sqlformat = pkgs.python3.pkgs.sqlparse; + staticcheck = pkgs.go-tools; + surface = pkgs.elixir; + swift_format = pkgs.swift-format; + teal = pkgs.luaPackages.tl; + terraform_fmt = pkgs.terraform; + terraform_validate = pkgs.terraform; + tidy = pkgs.html-tidy; + verible_verilog_format = pkgs.verible; + vint = pkgs.vim-vint; + write_good = pkgs.write-good; + xmllint = pkgs.libxml2; + } + # builtin sources that are not packaged in nixpkgs + // pkgs.lib.genAttrs [ + "blade_formatter" + "bsfmt" + "bslint" + "cljstyle" + "cueimports" + "erb_lint" + "findent" + "forge_fmt" + "gccdiag" + "gersemi" + "markuplint" + "mlint" + "nginx_beautifier" + "npm_groovy_lint" + "ocdc" + "packer" + "perlimports" + "pint" + "pretty_php" + "purs_tidy" + "pyink" + "reek" + "regal" + "remark" + "rescript" + "saltlint" + "solhint" + "spectral" + "sqlfmt" + "sql_formatter" + "styler" + "stylint" + "swiftformat" + "swiftlint" + "textidote" + "textlint" + "twigcs" + "vacuum" + ] (_: null); } diff --git a/plugins/none-ls/servers.nix b/plugins/none-ls/servers.nix deleted file mode 100644 index d37020017c..0000000000 --- a/plugins/none-ls/servers.nix +++ /dev/null @@ -1,82 +0,0 @@ -{ - pkgs, - config, - lib, - helpers, - ... -}: -let - noneLsBuiltins = import ../../generated/none-ls.nix; - - inherit (import ./packages.nix pkgs) packaged unpackaged; - - # Does this builitin require a package ? - builitinNeedsPackage = source: lib.hasAttr source packaged || lib.elem source unpackaged; -in -{ - imports = [ ./prettier.nix ]; - - options.plugins.none-ls.sources = lib.mapAttrs ( - sourceType: sources: - lib.listToAttrs ( - lib.map (source: { - name = source; - value = - { - enable = lib.mkEnableOption "the ${source} ${sourceType} source for none-ls"; - withArgs = helpers.mkNullOrOption helpers.nixvimTypes.strLua '' - Raw Lua code passed as an argument to the source's `with` method. - ''; - } - // lib.optionalAttrs (builitinNeedsPackage source) { - package = - let - pkg = packaged.${source} or null; - in - lib.mkOption ( - { - type = lib.types.nullOr lib.types.package; - description = - "Package to use for ${source} by none-ls. " - + (lib.optionalString (pkg == null) '' - Not handled in nixvim, either install externally and set to null or set the option with a derivation. - ''); - } - // lib.optionalAttrs (pkg != null) { default = pkg; } - ); - }; - }) sources - ) - ) noneLsBuiltins; - - config = - let - cfg = config.plugins.none-ls; - gitsignsEnabled = cfg.sources.code_actions.gitsigns.enable; - - flattenedSources = lib.flatten ( - lib.mapAttrsToList ( - sourceType: sources: - (lib.mapAttrsToList (sourceName: source: source // { inherit sourceType sourceName; }) sources) - ) cfg.sources - ); - - enabledSources = builtins.filter (source: source.enable) flattenedSources; - in - lib.mkIf cfg.enable { - plugins.none-ls.settings.sources = lib.mkIf (enabledSources != [ ]) ( - map ( - { - sourceType, - sourceName, - withArgs, - ... - }: - "require('null-ls').builtins.${sourceType}.${sourceName}" - + lib.optionalString (withArgs != null) ".with(${withArgs})" - ) enabledSources - ); - plugins.gitsigns.enable = lib.mkIf gitsignsEnabled true; - extraPackages = map (source: source.package or null) enabledSources; - }; -} diff --git a/plugins/none-ls/sources.nix b/plugins/none-ls/sources.nix new file mode 100644 index 0000000000..16a470230b --- /dev/null +++ b/plugins/none-ls/sources.nix @@ -0,0 +1,22 @@ +{ config, lib, ... }: +let + noneLsBuiltins = import ../../generated/none-ls.nix; + mkSourcePlugin = import ./_mk-source-plugin.nix; +in +{ + imports = + [ ./prettier.nix ] + ++ (lib.flatten ( + lib.mapAttrsToList (category: (lib.map (mkSourcePlugin category))) noneLsBuiltins + )); + + config = + let + cfg = config.plugins.none-ls; + gitsignsEnabled = cfg.sources.code_actions.gitsigns.enable; + in + lib.mkIf cfg.enable { + # Enable gitsigns if the gitsigns source is enabled + plugins.gitsigns.enable = lib.mkIf gitsignsEnabled true; + }; +} diff --git a/plugins/pluginmanagers/lz-n.nix b/plugins/pluginmanagers/lz-n.nix new file mode 100644 index 0000000000..8aa5fe6ed8 --- /dev/null +++ b/plugins/pluginmanagers/lz-n.nix @@ -0,0 +1,95 @@ +{ + lib, + helpers, + config, + pkgs, + ... +}: +let + inherit (lib) mkOption; + inherit (helpers) mkNullOrLuaFn' nixvimTypes mkLazyLoadOption; + + name = "lz-n"; + originalName = "lz.n"; +in +with lib; +helpers.neovim-plugin.mkNeovimPlugin config { + inherit name originalName; + maintainers = with helpers.maintainers; [ psfloyd ]; + defaultPackage = pkgs.vimPlugins.lz-n; + + settingsDescription = '' + The configuration options for **${originalName}** using `vim.g.lz_n`. + + `{ load = "fun"; }` -> `vim.g.lz_n = { load = fun, }` + ''; + + settingsOptions = { + load = mkNullOrLuaFn' { + description = '' + Function used by `lz.n` to load plugins. + ''; + default = null; + pluginDefault = "vim.cmd.packadd"; + }; + }; + + settingsExample = { + load = "vim.cmd.packadd"; + }; + + callSetup = false; # Does not use setup + + extraOptions = with nixvimTypes; { + plugins = mkOption { + description = "List of plugins processed by lz.n"; + default = [ ]; + type = listOf (mkLazyLoadOption { }).type; + }; + }; + + extraConfig = cfg: { + globals.lz_n = cfg.settings; + extraConfigLua = + let + processKeymap = + keymaps: + if keymaps == null then + null + else + map ( + keymap: + { + __unkeyed_1 = keymap.key; + __unkeyed_2 = keymap.action; + inherit (keymap) mode; + } + // keymap.options + ) keymaps; + pluginToLua = plugin: { + "__unkeyed" = plugin.name; + inherit (plugin) + beforeAll + before + after + event + cmd + ft + colorscheme + priority + load + ; + enabled = plugin.enabledInSpec; + keys = processKeymap plugin.keys; + }; + pluginListToLua = map pluginToLua; + plugins = pluginListToLua cfg.plugins; + pluginSpecs = if length plugins == 1 then head plugins else plugins; + in + mkIf (cfg.plugins != [ ]) '' + require('lz.n').load( + ${helpers.toLuaObject pluginSpecs} + ) + ''; + }; +} diff --git a/plugins/telescope/extensions/undo.nix b/plugins/telescope/extensions/undo.nix index dafe139a2e..c36e0b386e 100644 --- a/plugins/telescope/extensions/undo.nix +++ b/plugins/telescope/extensions/undo.nix @@ -77,9 +77,11 @@ telescopeHelpers.mkExtension { the side-by-side view even if this is set to false. ''; - diff_context_lines = helpers.defaultNullOpts.mkStrLuaOr types.ints.unsigned "vim.o.scrolloff" '' - Defaults to the scrolloff. - ''; + vim_diff_opts = { + ctxlen = helpers.defaultNullOpts.mkStrLuaOr types.ints.unsigned "vim.o.scrolloff" '' + Defaults to the scrolloff. + ''; + }; entry_format = helpers.defaultNullOpts.mkStr "state #$ID, $STAT, $TIME" '' The format to show on telescope for the different versions of the file. @@ -116,7 +118,7 @@ telescopeHelpers.mkExtension { "echo '$DIFF' | delta" ]; side_by_side = true; - diff_context_lines = 8; + vim_diff_opts.ctxlen = 8; entry_format = "state #$ID"; time_format = "!%Y-%m-%dT%TZ"; mappings = { diff --git a/plugins/utils/bufdelete.nix b/plugins/utils/bufdelete.nix new file mode 100644 index 0000000000..78c3c26449 --- /dev/null +++ b/plugins/utils/bufdelete.nix @@ -0,0 +1,70 @@ +{ + config, + helpers, + pkgs, + lib, + ... +}: +with lib; +helpers.vim-plugin.mkVimPlugin config { + name = "bufdelete"; + originalName = "bufdelete.nvim"; + defaultPackage = pkgs.vimPlugins.bufdelete-nvim; + globalPrefix = "bufdelete_"; + + maintainers = [ maintainers.MattSturgeon ]; + + description = '' + This plugin provides two commands, `:Bdelete` and `:Bwipeout`. + They work exactly the same as `:bdelete` and `:bwipeout`, + except they keep your window layout intact. + + There's also two Lua functions provided, `bufdelete` and `bufwipeout`, + which do the same thing as their command counterparts. + Both take three arguments, `buffers`, `force` and `switchable_buffers`. + + Here's an example of how to use the functions: + + ```lua + -- Forcibly delete current buffer + require('bufdelete').bufdelete(0, true) + + -- Wipeout buffer number 100 without force + require('bufdelete').bufwipeout(100) + + -- Delete buffer 7 and 30 without force. + require('bufdelete').bufdelete({7, 30}) + + -- Delete buffer matching foo.txt with force + require('bufdelete').bufdelete("foo.txt", true) + + -- Delete buffer matching foo.txt, buffer matching bar.txt and buffer 3 with force + require('bufdelete').bufdelete({"foo.txt", "bar.txt", 3}, true) + + -- Delete current buffer and switch to one of buffer 3, 5 or 10 + require('bufdelete').bufdelete(0, false, { 3, 5, 10 }) + ``` + + See the plugin's [README] for more details. + + [README]: https://github.com/famiu/bufdelete.nvim/?tab=readme-ov-file + ''; + + settingsOptions = { + buf_filter = helpers.defaultNullOpts.mkLuaFn null '' + Function that determines buffers that bufdelete.nvim can switch to, + instead of the default behavior of switching to any buffer. + + Must be a function that takes no argument and returns a list of buffers. + ''; + }; + + settingsExample = { + buf_filter = '' + function() + -- TODO: return a list of buffers + return { } + end + ''; + }; +} diff --git a/plugins/utils/dashboard.nix b/plugins/utils/dashboard.nix index c139841e36..42390afcc5 100644 --- a/plugins/utils/dashboard.nix +++ b/plugins/utils/dashboard.nix @@ -11,7 +11,7 @@ helpers.neovim-plugin.mkNeovimPlugin config { originalName = "dashboard-nvim"; defaultPackage = pkgs.vimPlugins.dashboard-nvim; - maintainers = [ helpers.maintainers.MattSturgeon ]; + maintainers = [ maintainers.MattSturgeon ]; # TODO introduced 2024-05-30: remove 2024-09-01 imports = diff --git a/plugins/utils/intellitab.nix b/plugins/utils/intellitab.nix index 0e31b434f6..3a50ead4b0 100644 --- a/plugins/utils/intellitab.nix +++ b/plugins/utils/intellitab.nix @@ -29,7 +29,7 @@ in } ]; plugins.treesitter = { - indent = true; + settings.indent.enable = true; }; }; } diff --git a/plugins/utils/refactoring.nix b/plugins/utils/refactoring.nix index 378f3fc514..bb227c2930 100644 --- a/plugins/utils/refactoring.nix +++ b/plugins/utils/refactoring.nix @@ -11,7 +11,7 @@ helpers.neovim-plugin.mkNeovimPlugin config { originalName = "refactoring.nvim"; defaultPackage = pkgs.vimPlugins.refactoring-nvim; - maintainers = [ helpers.maintainers.MattSturgeon ]; + maintainers = [ maintainers.MattSturgeon ]; # TODO: introduced 2024-05-24, remove on 2024-08-24 optionsRenamedToSettings = [ diff --git a/plugins/utils/tmux-navigator.nix b/plugins/utils/tmux-navigator.nix index 1a13f6afd2..15c7ea7245 100644 --- a/plugins/utils/tmux-navigator.nix +++ b/plugins/utils/tmux-navigator.nix @@ -12,7 +12,7 @@ helpers.vim-plugin.mkVimPlugin config { defaultPackage = pkgs.vimPlugins.vim-tmux-navigator; globalPrefix = "tmux_navigator_"; - maintainers = [ helpers.maintainers.MattSturgeon ]; + maintainers = [ maintainers.MattSturgeon ]; description = '' When combined with a set of tmux key bindings, the plugin will allow you to navigate seamlessly between vim splits and tmux panes using a consistent set of hotkeys. diff --git a/tests/fetch-tests.nix b/tests/fetch-tests.nix index 7cb5229e75..0e86a19c4d 100644 --- a/tests/fetch-tests.nix +++ b/tests/fetch-tests.nix @@ -53,10 +53,6 @@ let inherit pkgs lib helpers; config = { }; }; - nonels-sources-options = import ../plugins/none-ls/servers.nix { - inherit pkgs lib helpers; - config = { }; - }; }; inherit namespace; } diff --git a/tests/maintainers.nix b/tests/maintainers.nix new file mode 100644 index 0000000000..a9033aacff --- /dev/null +++ b/tests/maintainers.nix @@ -0,0 +1,21 @@ +{ + pkgs ? import { }, + lib ? pkgs.lib, +}: +let + inherit (lib) attrNames filter length; + nixvimList = import ../lib/maintainers.nix; + nixpkgsList = lib.maintainers; + duplicates = filter (name: nixpkgsList ? ${name}) (attrNames nixvimList); + count = length duplicates; +in +pkgs.runCommand "maintainers-test" { inherit count duplicates; } '' + if [ $count -gt 0 ]; then + echo "$count nixvim maintainers are also nixpkgs maintainers:" + for name in $duplicates; do + echo "- $name" + done + exit 1 + fi + touch $out +'' diff --git a/tests/test-sources/plugins/languages/markdown/glow.nix b/tests/test-sources/plugins/languages/markdown/glow.nix new file mode 100644 index 0000000000..a9c0d05665 --- /dev/null +++ b/tests/test-sources/plugins/languages/markdown/glow.nix @@ -0,0 +1,26 @@ +{ pkgs, ... }: +{ + empty = { + plugins.glow.enable = true; + }; + + defaults = { + plugins.glow = { + enable = true; + + glowPackage = pkgs.glow; + + settings = { + glow_path.__raw = "vim.fn.exepath('glow')"; + install_path = "~/.local/bin"; + border = "shadow"; + style = "dark"; + pager = false; + width = 80; + height = 100; + width_ratio = 0.7; + height_ratio = 0.7; + }; + }; + }; +} diff --git a/tests/test-sources/plugins/languages/rust/rustaceanvim.nix b/tests/test-sources/plugins/languages/rust/rustaceanvim.nix index a1318fa54e..7d5b0fd2ac 100644 --- a/tests/test-sources/plugins/languages/rust/rustaceanvim.nix +++ b/tests/test-sources/plugins/languages/rust/rustaceanvim.nix @@ -115,7 +115,7 @@ return { 'rust-analyzer', '--log-file', RustaceanConfig.server.logfile } end ''; - settings = '' + default_settings = '' function(project_root, default_settings) return require('rustaceanvim.config.server').load_rust_analyzer_settings(project_root, { default_settings = default_settings }) end @@ -143,7 +143,7 @@ plugins.rustaceanvim = { enable = true; - settings.server.settings = { + settings.server.default_settings.rust-analyzer = { linkedProjects = [ "foo/bar/hello" ]; numThreads = 42; joinLines.joinElseIf = true; diff --git a/tests/test-sources/plugins/languages/treesitter/treesitter.nix b/tests/test-sources/plugins/languages/treesitter/treesitter.nix index 11ea7c05a2..00f5a22633 100644 --- a/tests/test-sources/plugins/languages/treesitter/treesitter.nix +++ b/tests/test-sources/plugins/languages/treesitter/treesitter.nix @@ -8,7 +8,9 @@ auto_install = false; ensure_installed = [ ]; ignore_install = [ ]; - parser_install_dir = null; + # NOTE: This is our default, not the plugin's + parser_install_dir.__raw = "vim.fs.joinpath(vim.fn.stdpath('data'), 'site')"; + sync_install = false; highlight = { diff --git a/tests/test-sources/plugins/lsp/efmls-configs.nix b/tests/test-sources/plugins/lsp/efmls-configs.nix index 9c0bc02d28..4dfd270b12 100644 --- a/tests/test-sources/plugins/lsp/efmls-configs.nix +++ b/tests/test-sources/plugins/lsp/efmls-configs.nix @@ -15,31 +15,25 @@ brokenTools = [ - #Broken as of 16 of November 2023 - "phpstan" + # Broken as of 2024-07-08 + # TODO: re-enable this tests when fixed + "cpplint" + ] + ++ pkgs.lib.optionals (pkgs.stdenv.hostPlatform.system == "aarch64-linux") [ + # Broken as of 2024-07-13 + # TODO: re-enable this tests when fixed + "textlint" ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ - # As of 2024-05-22, python311Packages.k5test (one of ansible-lint's dependenvies) is broken on darwin - # TODO: re-enable this test when fixed - "ansible_lint" - # As of 2024-01-04, cbfmt is broken on darwin - # TODO: re-enable this test when fixed - "cbfmt" # As of 2024-01-04, texliveMedium is broken on darwin # TODO: re-enable those tests when fixed "chktex" "latexindent" ] ++ pkgs.lib.optionals (pkgs.stdenv.hostPlatform.system == "x86_64-darwin") [ - # As of 2024-01-04, dmd is broken on x86_64-darwin - # TODO: re-enable this test when fixed - "dmd" # As of 2024-01-04, luaformat is broken on x86_64-darwin # TODO: re-enable this test when fixed "lua_format" - # As of 2024-03-27, pkgs.graalvm-ce (a dependency of pkgs.clj-kondo) is broken on x86_64-darwin - # TODO: re-enable this test when fixed - "clj_kondo" ]; unpackaged = @@ -72,9 +66,6 @@ ++ (pkgs.lib.optionals pkgs.stdenv.isAarch64 [ "dmd" "smlfmt" - # As of 2024-03-11, swift-format is broken on aarch64 - # TODO: re-enable this test when fixed - # "swift_format" ]); # Fetch the valid enum members from the tool options diff --git a/tests/test-sources/plugins/none-ls.nix b/tests/test-sources/plugins/none-ls.nix index 6a9a43192a..9a13dcc89d 100644 --- a/tests/test-sources/plugins/none-ls.nix +++ b/tests/test-sources/plugins/none-ls.nix @@ -1,4 +1,3 @@ -{ pkgs, nonels-sources-options, ... }: { # Empty configuration empty = { @@ -100,95 +99,70 @@ }; with-sources = { - plugins.none-ls = { - # sandbox-exec: pattern serialization length 159032 exceeds maximum (65535) - enable = !pkgs.stdenv.isDarwin; - - sources = - let - options = nonels-sources-options.options.plugins.none-ls.sources; - - unpackaged = - [ - "blade_formatter" - "bsfmt" - "bslint" - "cljstyle" - "cueimports" - # As of 2024-03-22, pkgs.d2 is broken - # TODO: re-enable this test when fixed - "d2_fmt" - "erb_lint" - "findent" - "forge_fmt" - "gccdiag" - "gersemi" - "markuplint" - "mlint" - "nginx_beautifier" - "npm_groovy_lint" - "ocdc" - "packer" - "perlimports" - "pint" - "pretty_php" - "purs_tidy" - "pyink" - "reek" - "regal" - "remark" - "rescript" - "saltlint" - "solhint" - "spectral" - "sqlfmt" - "sql_formatter" - "styler" - "stylint" - "swiftformat" - "swiftlint" - "textidote" - "textlint" - "twigcs" - "vacuum" - "yamlfix" - ] - ++ (pkgs.lib.optionals (pkgs.stdenv.isDarwin && pkgs.stdenv.isx86_64) [ - # As of 2024-03-27, pkgs.graalvm-ce (a dependency of pkgs.clj-kondo) is broken on x86_64-darwin - # TODO: re-enable this test when fixed - "clj_kondo" - ]) - ++ (pkgs.lib.optionals pkgs.stdenv.isDarwin [ - # As of 2024-05-22, python311Packages.k5test (one of ansible-lint's dependenvies) is broken on darwin - # TODO: re-enable this test when fixed - "ansible_lint" - "clazy" - "gdformat" - "gdlint" - "haml_lint" - # As of 2024-06-29, pkgs.rubyfmt is broken on darwin - # TODO: re-enable this test when fixed - "rubyfmt" - "verilator" - "verible_verilog_format" - ]) - ++ (pkgs.lib.optionals pkgs.stdenv.isAarch64 [ - "semgrep" - "smlfmt" - # As of 2024-03-11, swift-format is broken on aarch64 - # TODO: re-enable this test when fixed - "swift_format" - ]); + module = + { + config, + options, + lib, + pkgs, + ... + }: + { + plugins.none-ls = { + # sandbox-exec: pattern serialization length 159032 exceeds maximum (65535) + enable = !pkgs.stdenv.isDarwin; - sources = pkgs.lib.mapAttrs ( - _: sources: - pkgs.lib.mapAttrs ( - source: _: - { enable = true; } // pkgs.lib.optionalAttrs (builtins.elem source unpackaged) { package = null; } - ) sources - ) options; - in - sources; - }; + sources = + let + disabled = + [ + # As of 2024-03-22, pkgs.d2 is broken + # TODO: re-enable this test when fixed + "d2_fmt" + # TODO: can this be re-enabled? + "yamlfix" + ] + ++ (lib.optionals (pkgs.stdenv.isDarwin && pkgs.stdenv.isx86_64) [ + # As of 2024-03-27, pkgs.graalvm-ce (a dependency of pkgs.clj-kondo) is broken on x86_64-darwin + # TODO: re-enable this test when fixed + "clj_kondo" + ]) + ++ (lib.optionals pkgs.stdenv.isDarwin [ + # As of 2024-05-22, python311Packages.k5test (one of ansible-lint's dependenvies) is broken on darwin + # TODO: re-enable this test when fixed + "ansible_lint" + "clazy" + "gdformat" + "gdlint" + "haml_lint" + # As of 2024-06-29, pkgs.rubyfmt is broken on darwin + # TODO: re-enable this test when fixed + "rubyfmt" + "verilator" + "verible_verilog_format" + ]) + ++ (lib.optionals pkgs.stdenv.isAarch64 [ + "semgrep" + "smlfmt" + # As of 2024-03-11, swift-format is broken on aarch64 + # TODO: re-enable this test when fixed + "swift_format" + ]); + in + # Enable every none-ls source that has an option + lib.mapAttrs ( + _: + lib.mapAttrs ( + sourceName: opts: + { + # Enable unless disabled above + enable = !(lib.elem sourceName disabled); + } + # Some sources have a package option with no default + // lib.optionalAttrs (opts ? package && !(opts.package ? default)) { package = null; } + ) + ) options.plugins.none-ls.sources; + }; + }; }; } diff --git a/tests/test-sources/plugins/pluginmanagers/lz-n.nix b/tests/test-sources/plugins/pluginmanagers/lz-n.nix new file mode 100644 index 0000000000..b89e10451f --- /dev/null +++ b/tests/test-sources/plugins/pluginmanagers/lz-n.nix @@ -0,0 +1,109 @@ +{ pkgs, ... }: +{ + # Empty configuration + empty = { + plugins.lz-n.enable = true; + }; + + # Settings + example = { + plugins.lz-n = { + enable = true; + settings = { + load = "vim.cmd.packadd"; + }; + }; + + }; + + test = { + extraPlugins = with pkgs.vimPlugins; [ + neo-tree-nvim + vimtex + telescope-nvim + nvim-biscuits + onedarker-nvim + ]; + plugins.treesitter.enable = true; + plugins.lz-n = { + enable = true; + plugins = [ + # enabledInSpec, on keys + { + name = "neo-tree.nvim"; + enabledInSpec = '' + function() + return false + end + ''; + keys = [ + { + mode = [ "n" ]; + key = "ft"; + action = "Neotree toggle"; + options = { + desc = "NeoTree toggle"; + }; + } + { + mode = [ + "n" + "v" + ]; + key = "gft"; + action = "Neotree toggle"; + options = { + desc = "NeoTree toggle"; + }; + } + ]; + after = # lua + '' + function() + require("neo-tree").setup() + end + ''; + } + # beforeAll, before, on filetype + { + name = "vimtex"; + ft = [ "plaintex" ]; + beforeAll = # lua + '' + function() + vim.g.vimtex_compiler_method = "latexrun" + end + ''; + before = # lua + '' + function() + vim.g.vimtex_compiler_method = "latexmk" + end + ''; + } + # On event + { + name = "nvim-biscuits"; + event = [ "BufEnter *.lua" ]; + after = '' + function() + require('nvim-biscuits').setup({}) + end + ''; + } + # On command no setup function, priority + { + name = "telescope.nvim"; + cmd = [ "Telescope" ]; + priority = 500; + } + # On colorschme + { + name = "onedarker.nvim"; + colorscheme = [ "onedarker" ]; + } + ]; + }; + }; + +} diff --git a/tests/test-sources/plugins/telescope/undo.nix b/tests/test-sources/plugins/telescope/undo.nix index cf89fe88d2..10b20c2c25 100644 --- a/tests/test-sources/plugins/telescope/undo.nix +++ b/tests/test-sources/plugins/telescope/undo.nix @@ -21,7 +21,7 @@ "echo '$DIFF' | delta" ]; side_by_side = true; - diff_context_lines = 8; + vim_diff_opts.ctxlen = 8; entry_format = "state #$ID"; time_format = "!%Y-%m-%dT%TZ"; mappings = { diff --git a/tests/test-sources/plugins/utils/bufdelete.nix b/tests/test-sources/plugins/utils/bufdelete.nix new file mode 100644 index 0000000000..45acb6a6a2 --- /dev/null +++ b/tests/test-sources/plugins/utils/bufdelete.nix @@ -0,0 +1,12 @@ +{ + empty = { + plugins.bufdelete.enable = true; + }; + + defaults = { + plugins.bufdelete = { + enable = true; + settings.buf_filter = null; + }; + }; +}