diff --git a/.commandcode/taste/taste.md b/.commandcode/taste/taste.md index 54e4488..4b588b2 100644 --- a/.commandcode/taste/taste.md +++ b/.commandcode/taste/taste.md @@ -1,7 +1,6 @@ # nix - For R.nvim in the Nix wrapper, both RNVIM_COMPLDIR (C server compilation) and a writable R_LIBS_USER directory (nvimcom R package installation) must be configured — fixing only one leaves permission errors in the other. Confidence: 0.65 - For R.nvim writable directories (RNVIM_COMPLDIR, R_LIBS_USER, TMPDIR), prefer project-local paths (e.g., $PWD/.Rlibs) over global cache paths — the cache approach may let the build succeed but still fail at runtime. Confidence: 0.70 -- Do not use lib.mkDefault on values consumed by lib.optionals or other boolean-checking functions — mkDefault wraps values in a priority set that fails "expected a Boolean" at evaluation time. Use plain booleans for inline conditionals, reserving mkDefault for module options resolved by the merge system. Confidence: 0.70 # Taste (Continuously Learned by [CommandCode][cmd]) diff --git a/flake.lock b/flake.lock index 698ccf9..9fbb80f 100644 --- a/flake.lock +++ b/flake.lock @@ -126,11 +126,11 @@ ] }, "locked": { - "lastModified": 1779297405, - "narHash": "sha256-VFoBwH7ZjVxCnvZTb5ODRXt70sLtWMxstive0N+RS50=", + "lastModified": 1779145538, + "narHash": "sha256-j2RQqBLYhPuddU6C8n5hGKboXq1tDLCZ7bWe5/LgTHM=", "owner": "BirdeeHub", "repo": "nix-wrapper-modules", - "rev": "e7ed7a1205945befdf2e0d73ba7df91d935e5af1", + "rev": "597b35c93dd0ab0ae38758e3193582b2fd259aa1", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 2780328..fa1140a 100644 --- a/flake.nix +++ b/flake.nix @@ -1,10 +1,11 @@ -# Copyright (c) 2026 Daniel +# Copyright (c) 2026 BirdeeHub # Licensed under the MIT license { description = "Daniel's NixCats"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + #nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; wrappers = { url = "github:BirdeeHub/nix-wrapper-modules"; inputs.nixpkgs.follows = "nixpkgs"; @@ -45,7 +46,7 @@ gitPlugins = true; julia = false; lua = true; - markdown = true; + markdown = false; nix = true; optional = false; python = false; @@ -53,20 +54,46 @@ }; settings = { lang_packages = { - python = []; - r = []; - julia = []; + python = with pkgs.python3Packages; [ + duckdb + polars + ]; + r = with pkgs.rpkgs.rPackages; [ + arrow + broom + data_table + janitor + languageserver + styler + pkgs.nvimcom + ]; + julia = ["DataFramesMeta" "QuackIO"]; }; + colorscheme = "cyberdream"; + background = "dark"; + wrapRc = true; }; binName = "vv"; }; wrapperSettings = pkgs: let cfg = mkWrapperConfig pkgs; + def = pkgs.lib.mkDefault; in wrapper.config.wrap { inherit pkgs; - inherit (cfg) settings binName; + cats = pkgs.lib.mapAttrs (_: v: def v) cfg.cats; + settings = { + lang_packages = { + python = def cfg.settings.lang_packages.python; + r = def cfg.settings.lang_packages.r; + julia = def cfg.settings.lang_packages.julia; + }; + colorscheme = def cfg.settings.colorscheme; + background = def cfg.settings.background; + wrapRc = def cfg.settings.wrapRc; + }; + binName = def cfg.binName; }; systems = [ @@ -77,39 +104,54 @@ forAllSystems = nixpkgs.lib.genAttrs systems; + extra_pkg_config = { + allowUnfree = true; + }; + overlayDefs = import ./overlays inputs; + dependencyOverlays = overlayDefs.dependencyOverlays; + + dependencyOverlay = overlayDefs.dependencyOverlay; + mkPkgs = system: import nixpkgs { inherit system; - config = { allowUnfree = true; }; - overlays = [ overlayDefs.dependencyOverlay ]; + config = extra_pkg_config; + overlays = [dependencyOverlay]; }; - module = (import ./modules/neovim.nix) inputs; + module = nixpkgs.lib.modules.importApply ./modules/neovim.nix inputs; wrapper = wrappers.lib.evalModule module; in { overlays = { - # overlay `vv` wraps the module with default settings only. - # For the fully-configured binary (including mkWrapperConfig overrides), - # use `packages..default` instead. default = nixpkgs.lib.composeManyExtensions [ - overlayDefs.dependencyOverlay + dependencyOverlay (final: prev: { vv = wrapper.config.wrap {pkgs = final;}; }) ]; - dependencies = overlayDefs.dependencyOverlay; + dependencies = dependencyOverlay; + vv = self.overlays.default; }; - wrapperModules.default = module; - wrapperConfigs.default = wrapper.config; + wrapperModules = { + default = module; + neovim = self.wrapperModules.default; + }; + + wrappers = { + default = wrapper.config; + neovim = self.wrappers.default; + }; packages = forAllSystems ( system: let pkgs = mkPkgs system; + nvimPkg = wrapperSettings pkgs; in { - default = wrapperSettings pkgs; + default = nvimPkg; + vv = nvimPkg; } ); @@ -123,29 +165,14 @@ devShells = forAllSystems ( system: let pkgs = mkPkgs system; + cfg = mkWrapperConfig pkgs; nvimPkg = wrapperSettings pkgs; - pythonPkgs = with pkgs.python3Packages; [ - duckdb - polars - ]; - - rPkgs = (with pkgs.rpkgs.rPackages; [ - arrow - broom - data_table - janitor - languageserver - styler - ]) ++ [ pkgs.nvimcom ]; - - juliaPkgs = ["DataFramesMeta" "QuackIO"]; - pythonPackages = let python_packages_fn = if pkgs ? basePythonPackages - then ps: pkgs.basePythonPackages ps ++ pythonPkgs - else _: pythonPkgs; + then ps: pkgs.basePythonPackages ps ++ cfg.settings.lang_packages.python + else _: cfg.settings.lang_packages.python; in with pkgs; [ (python3.withPackages python_packages_fn) @@ -156,7 +183,7 @@ ]; rPackages = let - r_packages = (pkgs.baseRPackages or []) ++ rPkgs; + r_packages = (pkgs.baseRPackages or []) ++ cfg.settings.lang_packages.r; in with pkgs; [ (rWrapper.override {packages = r_packages;}) @@ -170,7 +197,7 @@ ]; juliaPackages = let - julia_with_packages = pkgs.julia-bin.withPackages juliaPkgs; + julia_with_packages = pkgs.julia-bin.withPackages cfg.settings.lang_packages.julia; in [julia_with_packages]; markdownPackages = with pkgs; [ @@ -181,15 +208,16 @@ shellPackages = [nvimPkg] - ++ pkgs.lib.optionals wrapper.config.cats.python pythonPackages - ++ pkgs.lib.optionals wrapper.config.cats.r rPackages - ++ pkgs.lib.optionals wrapper.config.cats.julia juliaPackages - ++ pkgs.lib.optionals wrapper.config.cats.markdown markdownPackages; + ++ pkgs.lib.optionals cfg.cats.python pythonPackages + ++ pkgs.lib.optionals cfg.cats.r rPackages + ++ pkgs.lib.optionals cfg.cats.julia juliaPackages + ++ pkgs.lib.optionals cfg.cats.markdown markdownPackages; in { default = pkgs.mkShell { name = "vShell"; packages = shellPackages; - nativeBuildInputs = pkgs.lib.optionals wrapper.config.cats.optional [ pkgs.devenv ]; + nativeBuildInputs = with pkgs; [] ++ (pkgs.lib.optionals cfg.cats.optional [devenv]); + inputsFrom = []; shellHook = '' echo 'I am a NixShell' export R_HOME=$(R RHOME) @@ -206,11 +234,18 @@ pkgs = mkPkgs system; nvimPkg = wrapperSettings pkgs; in { - default = pkgs.runCommand "check-vv" {} '' + default = nvimPkg; + module-eval = let + _ = wrapper.config; + in + pkgs.runCommand "check-module-eval" {} '' + echo "Module evaluation successful" > $out + ''; + package-build = pkgs.runCommand "check-vv" {} '' BINARY_PATH="${nvimPkg}/bin/vv" if [ ! -x "$BINARY_PATH" ]; then - echo "Error: Binary not found or not executable" + echo "Error: Binary n not found or not executable" exit 1 fi @@ -223,11 +258,6 @@ cat version_output.txt >> $out fi ''; - module-eval = - let _ = wrapper.config; - in pkgs.runCommand "check-module-eval" {} '' - echo "Module evaluation successful" > $out - ''; } ); diff --git a/ftplugin/markdown.lua b/ftplugin/markdown.lua index db316fc..b673b60 100644 --- a/ftplugin/markdown.lua +++ b/ftplugin/markdown.lua @@ -1,35 +1,32 @@ -- Add the key mappings only for Markdown files in a zk notebook. -local nix = require("config.nix") -if nix.get_cat("markdown", false) then - if require("zk.util").notebook_root(vim.fn.expand('%:p')) ~= nil then - local map = vim.keymap.set - -- Open the link under the caret. - map("n", "", "lua vim.lsp.buf.definition()", { noremap = true, silent = false, buffer = true }) +if require("zk.util").notebook_root(vim.fn.expand('%:p')) ~= nil then + local map = vim.keymap.set + -- Open the link under the caret. + map("n", "", "lua vim.lsp.buf.definition()", { noremap = true, silent = false, buffer = true }) - -- Create a new note after asking for its title. - -- This overrides the global `zn` mapping to create the note in the same directory as the current buffer. - map("n", "zhn", "ZkNew { dir = vim.fn.expand('%:p:h'), title = vim.fn.input('Title: ') }", - { noremap = true, silent = false, buffer = true, desc = "Note (here)" }) - -- Create a new note in the same directory as the current buffer, using the current selection for title. - map("v", "zhnt", ":'<,'>ZkNewFromTitleSelection { dir = vim.fn.expand('%:p:h') }", - { noremap = true, silent = false, buffer = true, desc = "Note from selection (title)" }) - -- Create a new note in the same directory as the current buffer, using the current selection for note content and asking for its title. - map("v", "zhnc", - ":'<,'>ZkNewFromContentSelection { dir = vim.fn.expand('%:p:h'), title = vim.fn.input('Title: ') }", - { noremap = true, silent = false, buffer = true, desc = "Note from selection (content)" }) + -- Create a new note after asking for its title. + -- This overrides the global `zn` mapping to create the note in the same directory as the current buffer. + map("n", "zhn", "ZkNew { dir = vim.fn.expand('%:p:h'), title = vim.fn.input('Title: ') }", + { noremap = true, silent = false, buffer = true, desc = "Note (here)" }) + -- Create a new note in the same directory as the current buffer, using the current selection for title. + map("v", "zhnt", ":'<,'>ZkNewFromTitleSelection { dir = vim.fn.expand('%:p:h') }", + { noremap = true, silent = false, buffer = true, desc = "Note from selection (title)" }) + -- Create a new note in the same directory as the current buffer, using the current selection for note content and asking for its title. + map("v", "zhnc", + ":'<,'>ZkNewFromContentSelection { dir = vim.fn.expand('%:p:h'), title = vim.fn.input('Title: ') }", + { noremap = true, silent = false, buffer = true, desc = "Note from selection (content)" }) - -- Open notes linking to the current buffer. - map("n", "zb", "ZkBacklinks", { noremap = true, silent = false, buffer = true, desc = "Backlinks" }) - -- Alternative for backlinks using pure LSP and showing the source context. - --map('n', 'zb', 'lua vim.lsp.buf.references()', opts) - -- Open notes linked by the current buffer. - map("n", "zL", "ZkLinks", { noremap = true, silent = false, buffer = true, desc = "Links" }) - map("n", "zi", "ZkInsertLink", { noremap = true, silent = false, buffer = true, desc = "Insert link" }) + -- Open notes linking to the current buffer. + map("n", "zb", "ZkBacklinks", { noremap = true, silent = false, buffer = true, desc = "Backlinks" }) + -- Alternative for backlinks using pure LSP and showing the source context. + --map('n', 'zb', 'lua vim.lsp.buf.references()', opts) + -- Open notes linked by the current buffer. + map("n", "zL", "ZkLinks", { noremap = true, silent = false, buffer = true, desc = "Links" }) + map("n", "zi", "ZkInsertLink", { noremap = true, silent = false, buffer = true, desc = "Insert link" }) - -- Preview a linked note. - -- Open the code actions for a visual selection. - map("v", "za", ":'<,'>lua vim.lsp.buf.range_code_action()", - { noremap = true, silent = false, buffer = true, desc = "Code actions" }) + -- Preview a linked note. + -- Open the code actions for a visual selection. + map("v", "za", ":'<,'>lua vim.lsp.buf.range_code_action()", + { noremap = true, silent = false, buffer = true, desc = "Code actions" }) - end end diff --git a/modules/module/settings/cats.nix b/modules/module/settings/cats.nix index 13758d4..3da043e 100644 --- a/modules/module/settings/cats.nix +++ b/modules/module/settings/cats.nix @@ -14,6 +14,7 @@ Available categories: - clickhouse: Clickhouse client and tools + - customPlugins: local plugin specs - external: external tools and integrations - general: core Neovim plugins/features - gitPlugins: git-related plugins @@ -24,6 +25,7 @@ - optional: optional tools and utilities - python: Python tooling and plugins - r: R tooling and plugins + - test: test-only tooling (disabled by default) - treesitterParsers: Treesitter parsers - utils: general utilities ''; @@ -31,16 +33,18 @@ config.cats = { clickhouse = lib.mkDefault false; + customPlugins = lib.mkDefault true; external = lib.mkDefault true; general = lib.mkDefault true; gitPlugins = lib.mkDefault true; julia = lib.mkDefault false; lua = lib.mkDefault true; - markdown = lib.mkDefault true; + markdown = lib.mkDefault false; nix = lib.mkDefault true; optional = lib.mkDefault false; python = lib.mkDefault false; r = lib.mkDefault true; + test = lib.mkDefault false; treesitterParsers = lib.mkDefault true; utils = lib.mkDefault true; }; diff --git a/modules/module/settings/core.nix b/modules/module/settings/core.nix index ec9bb5c..42e9e11 100644 --- a/modules/module/settings/core.nix +++ b/modules/module/settings/core.nix @@ -16,7 +16,7 @@ # Lua packages available to neovim (for :lua require()) config.settings.nvim_lua_env = lp: - lib.optionals (config.cats.general or true) [ lp.tiktoken_core ]; + lib.optionals (config.cats.general or false) [ lp.tiktoken_core ]; # Binary name for the wrapper config.binName = lib.mkDefault "vv"; @@ -25,10 +25,10 @@ config.settings.block_normal_config = true; # Don't symlink the config (we wrap it instead) - config.settings.dont_link = lib.mkDefault false; + config.settings.dont_link = false; # Create additional aliases for the binary - config.settings.aliases = lib.mkDefault [ "vvim" ]; + config.settings.aliases = [ "vvim" ]; # Enable wrapper handling of spec runtimeDeps (template pattern). config.settings.autowrapRuntimeDeps = true; diff --git a/modules/module/settings/env.nix b/modules/module/settings/env.nix index 2fcab8a..14e0a32 100644 --- a/modules/module/settings/env.nix +++ b/modules/module/settings/env.nix @@ -7,11 +7,11 @@ # Environment variables set for the wrapper. # These are available when running neovim. config.env = lib.mkMerge [ - (lib.mkIf (config.cats.python or true) { + (lib.mkIf (config.cats.python or false) { UV_PYTHON_DOWNLOADS = "never"; UV_PYTHON = pkgs.python.interpreter; }) - (lib.mkIf (config.cats.r or true) { + (lib.mkIf (config.cats.r or false) { RNVIM_COMPLDIR = "$PWD/.r-compl"; R_LIBS_USER = "${pkgs.nvimcom}/library:$PWD/.Rlibs"; TMPDIR = "$PWD/.r-tmp"; @@ -20,7 +20,7 @@ # Environment variables with defaults (can be overridden by user) config.envDefault = lib.mkMerge [ - (lib.mkIf (config.cats.r or true) { + (lib.mkIf (config.cats.r or false) { R_LIBS_USER = "${pkgs.nvimcom}/library:$PWD/.Rlibs"; }) ]; diff --git a/modules/module/settings/hosts.nix b/modules/module/settings/hosts.nix index f248a00..0743979 100644 --- a/modules/module/settings/hosts.nix +++ b/modules/module/settings/hosts.nix @@ -15,7 +15,7 @@ nvim-host.enable = true; nvim-host.package = "${pkgs.neovide}/bin/neovide"; nvim-host.argv0 = "neovide"; - nvim-host.flags."--neovim-bin" = "${builtins.placeholder "out"}/bin/${config.binName}"; + nvim-host.flags."--neovim-bin" = "${placeholder "out"}/bin/${config.binName}"; }; m = { diff --git a/modules/module/settings/lang-packages.nix b/modules/module/settings/lang-packages.nix index 531b811..3315363 100644 --- a/modules/module/settings/lang-packages.nix +++ b/modules/module/settings/lang-packages.nix @@ -26,7 +26,7 @@ }; default = { }; description = '' - Language-specific package overrides appended to each language spec's runtimePackages. + Language-specific package overrides appended to each language spec's extraPackages. Intended for flake.nix overrides via wrapper.config.wrap. ''; }; diff --git a/modules/module/settings/runtime-path.nix b/modules/module/settings/runtime-path.nix index b321019..96c5d0f 100644 --- a/modules/module/settings/runtime-path.nix +++ b/modules/module/settings/runtime-path.nix @@ -10,13 +10,14 @@ let let is_enabled = if spec ? enable then spec.enable else true; has_runtime_deps = (spec.runtimeDeps or false) == runtime_deps_type; - packages = spec.runtimePackages or [ ]; + packages = spec.extraPackages or [ ]; in acc ++ lib.optionals (is_enabled && has_runtime_deps) packages ) [ ]; prefix_packages = collect_runtime_packages "prefix"; + suffix_packages = collect_runtime_packages "suffix"; to_path_specs = packages: [ { @@ -30,4 +31,5 @@ let in { config.prefixVar = lib.optionals (prefix_packages != [ ]) (to_path_specs prefix_packages); + config.suffixVar = lib.optionals (suffix_packages != [ ]) (to_path_specs suffix_packages); } diff --git a/modules/module/specs/cats-enable.nix b/modules/module/specs/cats-enable.nix new file mode 100644 index 0000000..f5a9826 --- /dev/null +++ b/modules/module/specs/cats-enable.nix @@ -0,0 +1,51 @@ +{ config, lib, ... }: +{ + # This module implements category-based enabling of specs. + # It runs early (order 200) so other specMaps can see the enable flags. + # + # How it works: + # 1. For each spec, extract its name (removing -lazy suffix if present) + # 2. Check if there's a corresponding cats. toggle + # 3. Set spec.value.enable based on the cats toggle (default: true) + # 4. This allows specs to be conditionally included based on config.cats settings + # + # Example: If config.cats.python = false, then specs.python.enable = false + + config.specMaps = lib.mkOrder 200 [ + { + name = "CATS_ENABLE"; + data = + list: + map ( + v: + if v.type == "spec" || v.type == "parent" then + let + # Extract spec name, handling lazy specs (remove -lazy suffix) + specName = + if v.name == null then + null + else if lib.hasSuffix "-lazy" v.name then + lib.removeSuffix "-lazy" v.name + else + v.name; + + # Check if this spec has a corresponding cat toggle + catEnabled = + if specName != null && builtins.hasAttr specName config.cats then + config.cats.${specName} + else + true; # Default to enabled if no cat toggle exists + in + v + // { + value = v.value // { + # Use explicit enable if set, otherwise use cat toggle + enable = if v.value ? enable then v.value.enable else catEnabled; + }; + } + else + v + ) list; + } + ]; +} diff --git a/modules/module/specs/deps.nix b/modules/module/specs/deps.nix index c3a40ea..a8bfaf6 100644 --- a/modules/module/specs/deps.nix +++ b/modules/module/specs/deps.nix @@ -5,14 +5,24 @@ wlib, ... }: { + # ============================================================================ + # SPEC MODULE DEFAULTS + # ============================================================================ + # Define default options available to all specs + config.specMods = {parentSpec ? null, ...}: { - options.runtimePkgs = lib.mkOption { + options.extraPackages = lib.mkOption { type = lib.types.listOf wlib.types.stringable; default = []; - description = "a runtimePkgs spec field to put packages to suffix to the PATH"; + description = "a extraPackages spec field to put packages to suffix to the PATH"; }; }; + # ============================================================================ + # EXTERNAL TOOLS SPEC + # ============================================================================ + # Core system tools and utilities + config.specs.external = { data = lib.mkDefault null; before = ["INIT_MAIN"]; @@ -20,7 +30,7 @@ vim.o.shell = "${pkgs.zsh}/bin/zsh" ''; runtimeDeps = "prefix"; - runtimePkgs = with pkgs; [ + extraPackages = with pkgs; [ perl ruby shfmt @@ -29,11 +39,15 @@ ]; }; + # ============================================================================ + # OPTIONAL TOOLS SPEC + # ============================================================================ + config.specs.optional = lib.mkIf (config.cats.optional or true) { data = lib.mkDefault null; runtimeDeps = "prefix"; before = ["INIT_MAIN"]; - runtimePkgs = with pkgs; [ + extraPackages = with pkgs; [ bat broot devenv @@ -62,38 +76,54 @@ ]; }; + # ============================================================================ + # MARKDOWN SPEC + # ============================================================================ + config.specs.markdown = lib.mkIf (config.cats.markdown or true) { data = lib.mkDefault null; runtimeDeps = "prefix"; - runtimePkgs = with pkgs; [ + extraPackages = with pkgs; [ python313Packages.pylatexenc quarto zk ]; }; + # ============================================================================ + # NIX SPEC + # ============================================================================ + config.specs.nix = lib.mkIf (config.cats.nix or true) { data = lib.mkDefault null; runtimeDeps = "prefix"; - runtimePkgs = with pkgs; [ + extraPackages = with pkgs; [ alejandra nix-doc nixd ]; }; + # ============================================================================ + # LUA SPEC + # ============================================================================ + config.specs.lua = lib.mkIf (config.cats.lua or true) { data = lib.mkDefault null; runtimeDeps = "prefix"; - runtimePkgs = with pkgs; [ + extraPackages = with pkgs; [ lua-language-server ]; }; + # ============================================================================ + # PYTHON SPEC + # ============================================================================ + config.specs.python = lib.mkIf (config.cats.python or true) { data = lib.mkDefault null; runtimeDeps = "prefix"; - runtimePkgs = let + extraPackages = let python_packages_fn = if pkgs ? basePythonPackages then ps: pkgs.basePythonPackages ps ++ config.settings.lang_packages.python @@ -109,10 +139,14 @@ ]; }; + # ============================================================================ + # R SPEC + # ============================================================================ + config.specs.r = lib.mkIf (config.cats.r or true) { data = lib.mkDefault null; runtimeDeps = "prefix"; - runtimePkgs = let + extraPackages = let r_packages = (pkgs.baseRPackages or []) ++ config.settings.lang_packages.r; in with pkgs; [ @@ -125,22 +159,30 @@ ]; }; + # ============================================================================ + # JULIA SPEC + # ============================================================================ + config.specs.julia = lib.mkIf (config.cats.julia or true) { data = lib.mkDefault null; runtimeDeps = "prefix"; - runtimePkgs = let + extraPackages = let julia_with_packages = pkgs.julia-bin.withPackages config.settings.lang_packages.julia; in [julia_with_packages]; }; + # ============================================================================ + # CLICKHOUSE SPEC + # ============================================================================ + config.specs.clickhouse = lib.mkIf (config.cats.clickhouse or true) { data = lib.mkDefault null; runtimeDeps = "prefix"; - runtimePkgs = with pkgs; [ + extraPackages = with pkgs; [ clickhouse-lts ]; }; - config.runtimePkgs = config.specCollect (acc: v: acc ++ (v.runtimePkgs or [])) []; + config.extraPackages = config.specCollect (acc: v: acc ++ (v.extraPackages or [])) []; } diff --git a/modules/module/specs/plugins.nix b/modules/module/specs/plugins.nix index ff00a72..431005d 100644 --- a/modules/module/specs/plugins.nix +++ b/modules/module/specs/plugins.nix @@ -4,11 +4,11 @@ lib, ... }: { - config.specs.gitPlugins = lib.mkIf (config.cats.gitPlugins or true) { + config.specs.gitPlugins = { data = []; }; - config.specs.r = lib.mkIf (config.cats.r or true) { + config.specs.r = { data = with pkgs.vimPlugins; [ pkgs.r-nvim quarto-nvim @@ -19,14 +19,14 @@ ]; }; - config.specs.markdown-lazy = lib.mkIf (config.cats.markdown or true) { + config.specs.markdown-lazy = { lazy = true; data = [ config.nvim-lib.neovimPlugins.cmp-pandoc-references ]; }; - config.specs.general = lib.mkIf (config.cats.general or true) { + config.specs.general = { data = with pkgs.vimPlugins; [ lze lzextras @@ -79,7 +79,7 @@ ]; }; - config.specs.lua = lib.mkIf (config.cats.lua or true) { + config.specs.lua = { data = with pkgs.vimPlugins; [ luvit-meta { @@ -89,7 +89,7 @@ ]; }; - config.specs.markdown = lib.mkIf (config.cats.markdown or true) { + config.specs.markdown = { data = with pkgs.vimPlugins; [ quarto-nvim render-markdown-nvim @@ -104,7 +104,7 @@ ]; }; - config.specs.utils = lib.mkIf (config.cats.utils or true) { + config.specs.utils = { data = with pkgs.vimPlugins; [ blink-cmp nvim-lspconfig @@ -119,7 +119,7 @@ ]; }; - config.specs.treesitterParsers = lib.mkIf (config.cats.treesitterParsers or true) { + config.specs.treesitterParsers = { data = with pkgs.vimPlugins.nvim-treesitter-parsers; [ bash c @@ -158,7 +158,7 @@ ]; }; - config.specs.utils-lazy = lib.mkIf (config.cats.utils or true) { + config.specs.utils-lazy = { lazy = true; data = with pkgs.vimPlugins; [ blink-compat @@ -175,7 +175,7 @@ ]; }; - config.specs.gitPlugins-lazy = lib.mkIf (config.cats.gitPlugins or true) { + config.specs.gitPlugins-lazy = { lazy = true; data = []; }; diff --git a/modules/neovim.nix b/modules/neovim.nix index 64d2cda..ba0361c 100644 --- a/modules/neovim.nix +++ b/modules/neovim.nix @@ -7,10 +7,16 @@ inputs: ... }: { + # ============================================================================ + # IMPORTS + # ============================================================================ + # Import the base neovim wrapper module and all configuration modules + imports = [ wlib.wrapperModules.neovim ./module/specs/deps.nix ./module/specs/plugins.nix + ./module/specs/cats-enable.nix ./module/settings/core.nix ./module/settings/cats.nix ./module/settings/env.nix @@ -19,6 +25,11 @@ inputs: ./module/settings/runtime-path.nix ]; + # ============================================================================ + # HELPER FUNCTIONS + # ============================================================================ + # Utilities for working with plugin inputs + options.nvim-lib.neovimPlugins = lib.mkOption { readOnly = true; type = lib.types.attrsOf wlib.types.stringable; @@ -47,6 +58,11 @@ inputs: ]; }; + # ============================================================================ + # CONFIGURATION + # ============================================================================ + # Pass cats configuration to neovim and expose metadata + config.settings.cats = config.cats; config.info.cats = config.cats; config.info.nixCats_config_location = config.settings.config_directory; diff --git a/overlays/default.nix b/overlays/default.nix index 5a4cc6c..ebb6518 100644 --- a/overlays/default.nix +++ b/overlays/default.nix @@ -4,8 +4,9 @@ let rOverlay = import ./r.nix {inherit inputs;}; rNvimNixOverlay = inputs.r-nvim-nix.overlays.default; - pythonOverlay = import ./python.nix {inherit inputs;}; - pluginsOverlay = import ./plugins.nix {inherit inputs;}; + franOverlay = inputs.fran.overlays.default; + pythonOverlay = import ./python.nix inputs; + pluginsOverlay = import ./plugins.nix inputs; dependencyOverlays = [ rOverlay @@ -14,11 +15,6 @@ let pluginsOverlay ]; dependencyOverlay = lib.composeManyExtensions dependencyOverlays; - - # franOverlay provides R-specific tooling (radianWrapper, air-formatter). - # It is scoped to rixpkgs (via overlays/r.nix) rather than the global - # package set, since it only applies to R package derivations. - franOverlay = inputs.fran.overlays.default; in { inherit @@ -30,6 +26,20 @@ in dependencyOverlays dependencyOverlay; + # Named exports for downstream composition. default = dependencyOverlay; dependencies = dependencyOverlays; + + overlays = { + inherit + rOverlay + rNvimNixOverlay + franOverlay + pythonOverlay + pluginsOverlay + dependencyOverlays + dependencyOverlay; + default = dependencyOverlay; + dependencies = dependencyOverlays; + }; } diff --git a/overlays/r.nix b/overlays/r.nix index 14c02eb..a9961fb 100644 --- a/overlays/r.nix +++ b/overlays/r.nix @@ -1,15 +1,55 @@ +# R packages overlay (rix) +# +# This overlay provides access to R packages from rstats-on-nix. +# +# rstats-on-nix maintains snapshots of CRAN packages built with Nix: +# - Provides reproducible R package versions +# - Ensures binary cache availability for faster builds +# - Maintained by the rstats-on-nix community +# +# Available attributes after applying this overlay: +# - pkgs.rpkgs: R packages from rstats-on-nix +# - pkgs.rpkgs.rPackages: All CRAN packages +# - pkgs.rpkgs.quarto: Quarto publishing system +# - pkgs.rpkgs.rWrapper: R with package management +# - pkgs.rWrapper: R wrapper with standard packages pre-configured +# - pkgs.quarto: Quarto with R integration and standard packages +# +# Custom R packages and tools (radianWrapper, air-formatter) come from +# the fran overlay which should be applied separately. +# +# To use specific R packages, reference them via: +# with pkgs.rpkgs.rPackages; [ package1 package2 ] +# +# Update the R snapshot date in flake.nix inputs section: +# rixpkgs.url = "github:rstats-on-nix/nixpkgs/YYYY-MM-DD" { inputs, ... }: final: prev: let + # R packages from rstats-on-nix for the current system rpkgs = import inputs.rixpkgs { system = prev.stdenv.hostPlatform.system; overlays = [inputs.fran.overlays.default]; - }; + }; # rixpkgs.legacyPackages.${prev.stdenv.hostPlatform.system}; + + # nvimcom and rnvimserver are provided by the r-nvim-nix flake overlay + # (inputs.r-nvim-nix.overlays.default) + + # Standard R packages used by default in rWrapper and quarto + reqPkgs = with rpkgs.rPackages; [ + # languageserver + ]; in { inherit rpkgs; - baseRPackages = [ ]; - rWrapper = rpkgs.rWrapper.override {packages = [ ];}; - quarto = rpkgs.quarto.override {extraRPackages = [ ];}; + baseRPackages = reqPkgs; + + # R wrapper with standard packages + rWrapper = rpkgs.rWrapper.override {packages = reqPkgs;}; + + # Quarto with R integration + quarto = rpkgs.quarto.override {extraRPackages = reqPkgs;}; + + # Update helper for rix updateR = import ../scripts/updater.nix {pkgs = final;}; } diff --git a/plugin/20_startup.lua b/plugin/20_startup.lua index 0404b2c..ca18bd8 100644 --- a/plugin/20_startup.lua +++ b/plugin/20_startup.lua @@ -390,25 +390,23 @@ end) -- zk now_if_args(function() - if nix.get_cat("markdown", false) then - require("zk").setup({ - picker = "minipick", - lsp = { - -- `config` is passed to `vim.lsp.start_client(config)` - config = { - cmd = { "zk", "lsp" }, - name = "zk", - -- on_attach = ... - -- etc, see `:h vim.lsp.start_client()` - }, - - -- automatically attach buffers in a zk notebook that match the given filetypes - auto_attach = { - enabled = true, - filetypes = { "markdown" }, - }, - + require("zk").setup({ + picker = "minipick", + lsp = { + -- `config` is passed to `vim.lsp.start_client(config)` + config = { + cmd = { "zk", "lsp" }, + name = "zk", + -- on_attach = ... + -- etc, see `:h vim.lsp.start_client()` }, - }) - end + + -- automatically attach buffers in a zk notebook that match the given filetypes + auto_attach = { + enabled = true, + filetypes = { "markdown" }, + }, + + }, + }) end) diff --git a/plugin/21_datascience.lua b/plugin/21_datascience.lua index 2e9f86c..62d8f49 100644 --- a/plugin/21_datascience.lua +++ b/plugin/21_datascience.lua @@ -71,45 +71,41 @@ end) now(function() vim.treesitter.language.register("markdown", { "quarto", "rmd" }) - if nix.get_cat({ "r", "markdown" }, false) then - vim.api.nvim_create_autocmd("FileType", { - pattern = { "quarto" }, - callback = function() - require("otter").activate() - end, - }) + vim.api.nvim_create_autocmd("FileType", { + pattern = { "quarto" }, + callback = function() + require("otter").activate() + end, + }) - require("otter").setup({ - lsp = { - diagnostic_update_events = { "BufWritePost", "InsertLeave" }, - }, - buffers = { - set_filetype = true, - write_to_disk = true, - }, - }) - end + require("otter").setup({ + lsp = { + diagnostic_update_events = { "BufWritePost", "InsertLeave" }, + }, + buffers = { + set_filetype = true, + write_to_disk = true, + }, + }) end) later(function() - if nix.get_cat({ "r", "markdown" }, false) then - require("quarto").setup({ - lspFeatures = { + require("quarto").setup({ + lspFeatures = { + enabled = true, + chunks = "curly", + languages = { "r", "python", "julia" }, + diagnostics = { enabled = true, - chunks = "curly", - languages = { "r", "python", "julia" }, - diagnostics = { - enabled = true, - triggers = { "BufWritePost" }, - }, - completion = { - enabled = true, - }, + triggers = { "BufWritePost" }, }, - codeRunner = { + completion = { enabled = true, - default_method = "slime", }, - }) - end + }, + codeRunner = { + enabled = true, + default_method = "slime", + }, + }) end) diff --git a/plugin/22_languages.lua b/plugin/22_languages.lua index ed4682a..1983b25 100644 --- a/plugin/22_languages.lua +++ b/plugin/22_languages.lua @@ -1,7 +1,6 @@ local add = Config.add local now_if_args = Config.now_if_args local later = MiniDeps.later -local nix = require('config.nix') if not Config.isNixCats then local m_add = MiniDeps.add @@ -13,21 +12,19 @@ end -- lua later(function() - if nix.get_cat("lua", false) then - add("luvit-meta") - add("lazydev") - require("lazydev").setup({ - library = { - -- See the configuration section for more details - -- Load luvit types when the `vim.uv` word is found - "lua", - "mini.nvim", - "MiniDeps", - { path = "luvit-meta/library", words = { "vim%.uv" } }, - { path = "${3rd}/luv/library", words = { "vim%.uv" } }, - }, - }) - end + add("luvit-meta") + add("lazydev") + require("lazydev").setup({ + library = { + -- See the configuration section for more details + -- Load luvit types when the `vim.uv` word is found + "lua", + "mini.nvim", + "MiniDeps", + { path = "luvit-meta/library", words = { "vim%.uv" } }, + { path = "${3rd}/luv/library", words = { "vim%.uv" } }, + }, + }) end) -- Markdown