Compare commits

..

No commits in common. "af6d975129768cce36ac4c46198ab2b3ebaafad3" and "ad9473a9166fc7e220449c9fd7625f8c52e05423" have entirely different histories.

19 changed files with 375 additions and 193 deletions

View file

@ -1,7 +1,6 @@
# nix # 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 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 - 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]) # Taste (Continuously Learned by [CommandCode][cmd])

6
flake.lock generated
View file

@ -126,11 +126,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1779297405, "lastModified": 1779145538,
"narHash": "sha256-VFoBwH7ZjVxCnvZTb5ODRXt70sLtWMxstive0N+RS50=", "narHash": "sha256-j2RQqBLYhPuddU6C8n5hGKboXq1tDLCZ7bWe5/LgTHM=",
"owner": "BirdeeHub", "owner": "BirdeeHub",
"repo": "nix-wrapper-modules", "repo": "nix-wrapper-modules",
"rev": "e7ed7a1205945befdf2e0d73ba7df91d935e5af1", "rev": "597b35c93dd0ab0ae38758e3193582b2fd259aa1",
"type": "github" "type": "github"
}, },
"original": { "original": {

128
flake.nix
View file

@ -1,10 +1,11 @@
# Copyright (c) 2026 Daniel # Copyright (c) 2026 BirdeeHub
# Licensed under the MIT license # Licensed under the MIT license
{ {
description = "Daniel's NixCats"; description = "Daniel's NixCats";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
#nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
wrappers = { wrappers = {
url = "github:BirdeeHub/nix-wrapper-modules"; url = "github:BirdeeHub/nix-wrapper-modules";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
@ -45,7 +46,7 @@
gitPlugins = true; gitPlugins = true;
julia = false; julia = false;
lua = true; lua = true;
markdown = true; markdown = false;
nix = true; nix = true;
optional = false; optional = false;
python = false; python = false;
@ -53,20 +54,46 @@
}; };
settings = { settings = {
lang_packages = { lang_packages = {
python = []; python = with pkgs.python3Packages; [
r = []; duckdb
julia = []; 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"; binName = "vv";
}; };
wrapperSettings = pkgs: let wrapperSettings = pkgs: let
cfg = mkWrapperConfig pkgs; cfg = mkWrapperConfig pkgs;
def = pkgs.lib.mkDefault;
in in
wrapper.config.wrap { wrapper.config.wrap {
inherit pkgs; 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 = [ systems = [
@ -77,39 +104,54 @@
forAllSystems = nixpkgs.lib.genAttrs systems; forAllSystems = nixpkgs.lib.genAttrs systems;
extra_pkg_config = {
allowUnfree = true;
};
overlayDefs = import ./overlays inputs; overlayDefs = import ./overlays inputs;
dependencyOverlays = overlayDefs.dependencyOverlays;
dependencyOverlay = overlayDefs.dependencyOverlay;
mkPkgs = system: mkPkgs = system:
import nixpkgs { import nixpkgs {
inherit system; inherit system;
config = { allowUnfree = true; }; config = extra_pkg_config;
overlays = [ overlayDefs.dependencyOverlay ]; overlays = [dependencyOverlay];
}; };
module = (import ./modules/neovim.nix) inputs; module = nixpkgs.lib.modules.importApply ./modules/neovim.nix inputs;
wrapper = wrappers.lib.evalModule module; wrapper = wrappers.lib.evalModule module;
in { in {
overlays = { overlays = {
# overlay `vv` wraps the module with default settings only.
# For the fully-configured binary (including mkWrapperConfig overrides),
# use `packages.<system>.default` instead.
default = nixpkgs.lib.composeManyExtensions [ default = nixpkgs.lib.composeManyExtensions [
overlayDefs.dependencyOverlay dependencyOverlay
(final: prev: { (final: prev: {
vv = wrapper.config.wrap {pkgs = final;}; vv = wrapper.config.wrap {pkgs = final;};
}) })
]; ];
dependencies = overlayDefs.dependencyOverlay; dependencies = dependencyOverlay;
vv = self.overlays.default;
}; };
wrapperModules.default = module; wrapperModules = {
wrapperConfigs.default = wrapper.config; default = module;
neovim = self.wrapperModules.default;
};
wrappers = {
default = wrapper.config;
neovim = self.wrappers.default;
};
packages = forAllSystems ( packages = forAllSystems (
system: let system: let
pkgs = mkPkgs system; pkgs = mkPkgs system;
nvimPkg = wrapperSettings pkgs;
in { in {
default = wrapperSettings pkgs; default = nvimPkg;
vv = nvimPkg;
} }
); );
@ -123,29 +165,14 @@
devShells = forAllSystems ( devShells = forAllSystems (
system: let system: let
pkgs = mkPkgs system; pkgs = mkPkgs system;
cfg = mkWrapperConfig pkgs;
nvimPkg = wrapperSettings 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 pythonPackages = let
python_packages_fn = python_packages_fn =
if pkgs ? basePythonPackages if pkgs ? basePythonPackages
then ps: pkgs.basePythonPackages ps ++ pythonPkgs then ps: pkgs.basePythonPackages ps ++ cfg.settings.lang_packages.python
else _: pythonPkgs; else _: cfg.settings.lang_packages.python;
in in
with pkgs; [ with pkgs; [
(python3.withPackages python_packages_fn) (python3.withPackages python_packages_fn)
@ -156,7 +183,7 @@
]; ];
rPackages = let rPackages = let
r_packages = (pkgs.baseRPackages or []) ++ rPkgs; r_packages = (pkgs.baseRPackages or []) ++ cfg.settings.lang_packages.r;
in in
with pkgs; [ with pkgs; [
(rWrapper.override {packages = r_packages;}) (rWrapper.override {packages = r_packages;})
@ -170,7 +197,7 @@
]; ];
juliaPackages = let 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]; in [julia_with_packages];
markdownPackages = with pkgs; [ markdownPackages = with pkgs; [
@ -181,15 +208,16 @@
shellPackages = shellPackages =
[nvimPkg] [nvimPkg]
++ pkgs.lib.optionals wrapper.config.cats.python pythonPackages ++ pkgs.lib.optionals cfg.cats.python pythonPackages
++ pkgs.lib.optionals wrapper.config.cats.r rPackages ++ pkgs.lib.optionals cfg.cats.r rPackages
++ pkgs.lib.optionals wrapper.config.cats.julia juliaPackages ++ pkgs.lib.optionals cfg.cats.julia juliaPackages
++ pkgs.lib.optionals wrapper.config.cats.markdown markdownPackages; ++ pkgs.lib.optionals cfg.cats.markdown markdownPackages;
in { in {
default = pkgs.mkShell { default = pkgs.mkShell {
name = "vShell"; name = "vShell";
packages = shellPackages; packages = shellPackages;
nativeBuildInputs = pkgs.lib.optionals wrapper.config.cats.optional [ pkgs.devenv ]; nativeBuildInputs = with pkgs; [] ++ (pkgs.lib.optionals cfg.cats.optional [devenv]);
inputsFrom = [];
shellHook = '' shellHook = ''
echo 'I am a NixShell' echo 'I am a NixShell'
export R_HOME=$(R RHOME) export R_HOME=$(R RHOME)
@ -206,11 +234,18 @@
pkgs = mkPkgs system; pkgs = mkPkgs system;
nvimPkg = wrapperSettings pkgs; nvimPkg = wrapperSettings pkgs;
in { 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" BINARY_PATH="${nvimPkg}/bin/vv"
if [ ! -x "$BINARY_PATH" ]; then if [ ! -x "$BINARY_PATH" ]; then
echo "Error: Binary not found or not executable" echo "Error: Binary n not found or not executable"
exit 1 exit 1
fi fi
@ -223,11 +258,6 @@
cat version_output.txt >> $out cat version_output.txt >> $out
fi fi
''; '';
module-eval =
let _ = wrapper.config;
in pkgs.runCommand "check-module-eval" {} ''
echo "Module evaluation successful" > $out
'';
} }
); );

View file

@ -1,35 +1,32 @@
-- Add the key mappings only for Markdown files in a zk notebook. -- Add the key mappings only for Markdown files in a zk notebook.
local nix = require("config.nix") if require("zk.util").notebook_root(vim.fn.expand('%:p')) ~= nil then
if nix.get_cat("markdown", false) then local map = vim.keymap.set
if require("zk.util").notebook_root(vim.fn.expand('%:p')) ~= nil then -- Open the link under the caret.
local map = vim.keymap.set map("n", "<CR>", "<Cmd>lua vim.lsp.buf.definition()<CR>", { noremap = true, silent = false, buffer = true })
-- Open the link under the caret.
map("n", "<CR>", "<Cmd>lua vim.lsp.buf.definition()<CR>", { noremap = true, silent = false, buffer = true })
-- Create a new note after asking for its title. -- Create a new note after asking for its title.
-- This overrides the global `<leader>zn` mapping to create the note in the same directory as the current buffer. -- This overrides the global `<leader>zn` mapping to create the note in the same directory as the current buffer.
map("n", "<leader>zhn", "<Cmd>ZkNew { dir = vim.fn.expand('%:p:h'), title = vim.fn.input('Title: ') }<CR>", map("n", "<leader>zhn", "<Cmd>ZkNew { dir = vim.fn.expand('%:p:h'), title = vim.fn.input('Title: ') }<CR>",
{ noremap = true, silent = false, buffer = true, desc = "Note (here)" }) { 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. -- Create a new note in the same directory as the current buffer, using the current selection for title.
map("v", "<leader>zhnt", ":'<,'>ZkNewFromTitleSelection { dir = vim.fn.expand('%:p:h') }<CR>", map("v", "<leader>zhnt", ":'<,'>ZkNewFromTitleSelection { dir = vim.fn.expand('%:p:h') }<CR>",
{ noremap = true, silent = false, buffer = true, desc = "Note from selection (title)" }) { 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. -- 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", "<leader>zhnc", map("v", "<leader>zhnc",
":'<,'>ZkNewFromContentSelection { dir = vim.fn.expand('%:p:h'), title = vim.fn.input('Title: ') }<CR>", ":'<,'>ZkNewFromContentSelection { dir = vim.fn.expand('%:p:h'), title = vim.fn.input('Title: ') }<CR>",
{ noremap = true, silent = false, buffer = true, desc = "Note from selection (content)" }) { noremap = true, silent = false, buffer = true, desc = "Note from selection (content)" })
-- Open notes linking to the current buffer. -- Open notes linking to the current buffer.
map("n", "<leader>zb", "<Cmd>ZkBacklinks<CR>", { noremap = true, silent = false, buffer = true, desc = "Backlinks" }) map("n", "<leader>zb", "<Cmd>ZkBacklinks<CR>", { noremap = true, silent = false, buffer = true, desc = "Backlinks" })
-- Alternative for backlinks using pure LSP and showing the source context. -- Alternative for backlinks using pure LSP and showing the source context.
--map('n', '<leader>zb', '<Cmd>lua vim.lsp.buf.references()<CR>', opts) --map('n', '<leader>zb', '<Cmd>lua vim.lsp.buf.references()<CR>', opts)
-- Open notes linked by the current buffer. -- Open notes linked by the current buffer.
map("n", "<leader>zL", "<Cmd>ZkLinks<CR>", { noremap = true, silent = false, buffer = true, desc = "Links" }) map("n", "<leader>zL", "<Cmd>ZkLinks<CR>", { noremap = true, silent = false, buffer = true, desc = "Links" })
map("n", "<leader>zi", "<Cmd>ZkInsertLink<CR>", { noremap = true, silent = false, buffer = true, desc = "Insert link" }) map("n", "<leader>zi", "<Cmd>ZkInsertLink<CR>", { noremap = true, silent = false, buffer = true, desc = "Insert link" })
-- Preview a linked note. -- Preview a linked note.
-- Open the code actions for a visual selection. -- Open the code actions for a visual selection.
map("v", "<leader>za", ":'<,'>lua vim.lsp.buf.range_code_action()<CR>", map("v", "<leader>za", ":'<,'>lua vim.lsp.buf.range_code_action()<CR>",
{ noremap = true, silent = false, buffer = true, desc = "Code actions" }) { noremap = true, silent = false, buffer = true, desc = "Code actions" })
end
end end

View file

@ -14,6 +14,7 @@
Available categories: Available categories:
- clickhouse: Clickhouse client and tools - clickhouse: Clickhouse client and tools
- customPlugins: local plugin specs
- external: external tools and integrations - external: external tools and integrations
- general: core Neovim plugins/features - general: core Neovim plugins/features
- gitPlugins: git-related plugins - gitPlugins: git-related plugins
@ -24,6 +25,7 @@
- optional: optional tools and utilities - optional: optional tools and utilities
- python: Python tooling and plugins - python: Python tooling and plugins
- r: R tooling and plugins - r: R tooling and plugins
- test: test-only tooling (disabled by default)
- treesitterParsers: Treesitter parsers - treesitterParsers: Treesitter parsers
- utils: general utilities - utils: general utilities
''; '';
@ -31,16 +33,18 @@
config.cats = { config.cats = {
clickhouse = lib.mkDefault false; clickhouse = lib.mkDefault false;
customPlugins = lib.mkDefault true;
external = lib.mkDefault true; external = lib.mkDefault true;
general = lib.mkDefault true; general = lib.mkDefault true;
gitPlugins = lib.mkDefault true; gitPlugins = lib.mkDefault true;
julia = lib.mkDefault false; julia = lib.mkDefault false;
lua = lib.mkDefault true; lua = lib.mkDefault true;
markdown = lib.mkDefault true; markdown = lib.mkDefault false;
nix = lib.mkDefault true; nix = lib.mkDefault true;
optional = lib.mkDefault false; optional = lib.mkDefault false;
python = lib.mkDefault false; python = lib.mkDefault false;
r = lib.mkDefault true; r = lib.mkDefault true;
test = lib.mkDefault false;
treesitterParsers = lib.mkDefault true; treesitterParsers = lib.mkDefault true;
utils = lib.mkDefault true; utils = lib.mkDefault true;
}; };

View file

@ -16,7 +16,7 @@
# Lua packages available to neovim (for :lua require()) # Lua packages available to neovim (for :lua require())
config.settings.nvim_lua_env = lp: 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 # Binary name for the wrapper
config.binName = lib.mkDefault "vv"; config.binName = lib.mkDefault "vv";
@ -25,10 +25,10 @@
config.settings.block_normal_config = true; config.settings.block_normal_config = true;
# Don't symlink the config (we wrap it instead) # 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 # Create additional aliases for the binary
config.settings.aliases = lib.mkDefault [ "vvim" ]; config.settings.aliases = [ "vvim" ];
# Enable wrapper handling of spec runtimeDeps (template pattern). # Enable wrapper handling of spec runtimeDeps (template pattern).
config.settings.autowrapRuntimeDeps = true; config.settings.autowrapRuntimeDeps = true;

View file

@ -7,11 +7,11 @@
# Environment variables set for the wrapper. # Environment variables set for the wrapper.
# These are available when running neovim. # These are available when running neovim.
config.env = lib.mkMerge [ config.env = lib.mkMerge [
(lib.mkIf (config.cats.python or true) { (lib.mkIf (config.cats.python or false) {
UV_PYTHON_DOWNLOADS = "never"; UV_PYTHON_DOWNLOADS = "never";
UV_PYTHON = pkgs.python.interpreter; UV_PYTHON = pkgs.python.interpreter;
}) })
(lib.mkIf (config.cats.r or true) { (lib.mkIf (config.cats.r or false) {
RNVIM_COMPLDIR = "$PWD/.r-compl"; RNVIM_COMPLDIR = "$PWD/.r-compl";
R_LIBS_USER = "${pkgs.nvimcom}/library:$PWD/.Rlibs"; R_LIBS_USER = "${pkgs.nvimcom}/library:$PWD/.Rlibs";
TMPDIR = "$PWD/.r-tmp"; TMPDIR = "$PWD/.r-tmp";
@ -20,7 +20,7 @@
# Environment variables with defaults (can be overridden by user) # Environment variables with defaults (can be overridden by user)
config.envDefault = lib.mkMerge [ 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"; R_LIBS_USER = "${pkgs.nvimcom}/library:$PWD/.Rlibs";
}) })
]; ];

View file

@ -15,7 +15,7 @@
nvim-host.enable = true; nvim-host.enable = true;
nvim-host.package = "${pkgs.neovide}/bin/neovide"; nvim-host.package = "${pkgs.neovide}/bin/neovide";
nvim-host.argv0 = "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 = { m = {

View file

@ -26,7 +26,7 @@
}; };
default = { }; default = { };
description = '' 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. Intended for flake.nix overrides via wrapper.config.wrap.
''; '';
}; };

View file

@ -10,13 +10,14 @@ let
let let
is_enabled = if spec ? enable then spec.enable else true; is_enabled = if spec ? enable then spec.enable else true;
has_runtime_deps = (spec.runtimeDeps or false) == runtime_deps_type; has_runtime_deps = (spec.runtimeDeps or false) == runtime_deps_type;
packages = spec.runtimePackages or [ ]; packages = spec.extraPackages or [ ];
in in
acc ++ lib.optionals (is_enabled && has_runtime_deps) packages acc ++ lib.optionals (is_enabled && has_runtime_deps) packages
) )
[ ]; [ ];
prefix_packages = collect_runtime_packages "prefix"; prefix_packages = collect_runtime_packages "prefix";
suffix_packages = collect_runtime_packages "suffix";
to_path_specs = packages: [ to_path_specs = packages: [
{ {
@ -30,4 +31,5 @@ let
in in
{ {
config.prefixVar = lib.optionals (prefix_packages != [ ]) (to_path_specs prefix_packages); config.prefixVar = lib.optionals (prefix_packages != [ ]) (to_path_specs prefix_packages);
config.suffixVar = lib.optionals (suffix_packages != [ ]) (to_path_specs suffix_packages);
} }

View file

@ -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.<name> 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;
}
];
}

View file

@ -5,14 +5,24 @@
wlib, wlib,
... ...
}: { }: {
# ============================================================================
# SPEC MODULE DEFAULTS
# ============================================================================
# Define default options available to all specs
config.specMods = {parentSpec ? null, ...}: { config.specMods = {parentSpec ? null, ...}: {
options.runtimePkgs = lib.mkOption { options.extraPackages = lib.mkOption {
type = lib.types.listOf wlib.types.stringable; type = lib.types.listOf wlib.types.stringable;
default = []; 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 = { config.specs.external = {
data = lib.mkDefault null; data = lib.mkDefault null;
before = ["INIT_MAIN"]; before = ["INIT_MAIN"];
@ -20,7 +30,7 @@
vim.o.shell = "${pkgs.zsh}/bin/zsh" vim.o.shell = "${pkgs.zsh}/bin/zsh"
''; '';
runtimeDeps = "prefix"; runtimeDeps = "prefix";
runtimePkgs = with pkgs; [ extraPackages = with pkgs; [
perl perl
ruby ruby
shfmt shfmt
@ -29,11 +39,15 @@
]; ];
}; };
# ============================================================================
# OPTIONAL TOOLS SPEC
# ============================================================================
config.specs.optional = lib.mkIf (config.cats.optional or true) { config.specs.optional = lib.mkIf (config.cats.optional or true) {
data = lib.mkDefault null; data = lib.mkDefault null;
runtimeDeps = "prefix"; runtimeDeps = "prefix";
before = ["INIT_MAIN"]; before = ["INIT_MAIN"];
runtimePkgs = with pkgs; [ extraPackages = with pkgs; [
bat bat
broot broot
devenv devenv
@ -62,38 +76,54 @@
]; ];
}; };
# ============================================================================
# MARKDOWN SPEC
# ============================================================================
config.specs.markdown = lib.mkIf (config.cats.markdown or true) { config.specs.markdown = lib.mkIf (config.cats.markdown or true) {
data = lib.mkDefault null; data = lib.mkDefault null;
runtimeDeps = "prefix"; runtimeDeps = "prefix";
runtimePkgs = with pkgs; [ extraPackages = with pkgs; [
python313Packages.pylatexenc python313Packages.pylatexenc
quarto quarto
zk zk
]; ];
}; };
# ============================================================================
# NIX SPEC
# ============================================================================
config.specs.nix = lib.mkIf (config.cats.nix or true) { config.specs.nix = lib.mkIf (config.cats.nix or true) {
data = lib.mkDefault null; data = lib.mkDefault null;
runtimeDeps = "prefix"; runtimeDeps = "prefix";
runtimePkgs = with pkgs; [ extraPackages = with pkgs; [
alejandra alejandra
nix-doc nix-doc
nixd nixd
]; ];
}; };
# ============================================================================
# LUA SPEC
# ============================================================================
config.specs.lua = lib.mkIf (config.cats.lua or true) { config.specs.lua = lib.mkIf (config.cats.lua or true) {
data = lib.mkDefault null; data = lib.mkDefault null;
runtimeDeps = "prefix"; runtimeDeps = "prefix";
runtimePkgs = with pkgs; [ extraPackages = with pkgs; [
lua-language-server lua-language-server
]; ];
}; };
# ============================================================================
# PYTHON SPEC
# ============================================================================
config.specs.python = lib.mkIf (config.cats.python or true) { config.specs.python = lib.mkIf (config.cats.python or true) {
data = lib.mkDefault null; data = lib.mkDefault null;
runtimeDeps = "prefix"; runtimeDeps = "prefix";
runtimePkgs = let extraPackages = let
python_packages_fn = python_packages_fn =
if pkgs ? basePythonPackages if pkgs ? basePythonPackages
then ps: pkgs.basePythonPackages ps ++ config.settings.lang_packages.python 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) { config.specs.r = lib.mkIf (config.cats.r or true) {
data = lib.mkDefault null; data = lib.mkDefault null;
runtimeDeps = "prefix"; runtimeDeps = "prefix";
runtimePkgs = let extraPackages = let
r_packages = (pkgs.baseRPackages or []) ++ config.settings.lang_packages.r; r_packages = (pkgs.baseRPackages or []) ++ config.settings.lang_packages.r;
in in
with pkgs; [ with pkgs; [
@ -125,22 +159,30 @@
]; ];
}; };
# ============================================================================
# JULIA SPEC
# ============================================================================
config.specs.julia = lib.mkIf (config.cats.julia or true) { config.specs.julia = lib.mkIf (config.cats.julia or true) {
data = lib.mkDefault null; data = lib.mkDefault null;
runtimeDeps = "prefix"; runtimeDeps = "prefix";
runtimePkgs = let extraPackages = let
julia_with_packages = julia_with_packages =
pkgs.julia-bin.withPackages config.settings.lang_packages.julia; pkgs.julia-bin.withPackages config.settings.lang_packages.julia;
in [julia_with_packages]; in [julia_with_packages];
}; };
# ============================================================================
# CLICKHOUSE SPEC
# ============================================================================
config.specs.clickhouse = lib.mkIf (config.cats.clickhouse or true) { config.specs.clickhouse = lib.mkIf (config.cats.clickhouse or true) {
data = lib.mkDefault null; data = lib.mkDefault null;
runtimeDeps = "prefix"; runtimeDeps = "prefix";
runtimePkgs = with pkgs; [ extraPackages = with pkgs; [
clickhouse-lts clickhouse-lts
]; ];
}; };
config.runtimePkgs = config.specCollect (acc: v: acc ++ (v.runtimePkgs or [])) []; config.extraPackages = config.specCollect (acc: v: acc ++ (v.extraPackages or [])) [];
} }

View file

@ -4,11 +4,11 @@
lib, lib,
... ...
}: { }: {
config.specs.gitPlugins = lib.mkIf (config.cats.gitPlugins or true) { config.specs.gitPlugins = {
data = []; data = [];
}; };
config.specs.r = lib.mkIf (config.cats.r or true) { config.specs.r = {
data = with pkgs.vimPlugins; [ data = with pkgs.vimPlugins; [
pkgs.r-nvim pkgs.r-nvim
quarto-nvim quarto-nvim
@ -19,14 +19,14 @@
]; ];
}; };
config.specs.markdown-lazy = lib.mkIf (config.cats.markdown or true) { config.specs.markdown-lazy = {
lazy = true; lazy = true;
data = [ data = [
config.nvim-lib.neovimPlugins.cmp-pandoc-references config.nvim-lib.neovimPlugins.cmp-pandoc-references
]; ];
}; };
config.specs.general = lib.mkIf (config.cats.general or true) { config.specs.general = {
data = with pkgs.vimPlugins; [ data = with pkgs.vimPlugins; [
lze lze
lzextras lzextras
@ -79,7 +79,7 @@
]; ];
}; };
config.specs.lua = lib.mkIf (config.cats.lua or true) { config.specs.lua = {
data = with pkgs.vimPlugins; [ data = with pkgs.vimPlugins; [
luvit-meta luvit-meta
{ {
@ -89,7 +89,7 @@
]; ];
}; };
config.specs.markdown = lib.mkIf (config.cats.markdown or true) { config.specs.markdown = {
data = with pkgs.vimPlugins; [ data = with pkgs.vimPlugins; [
quarto-nvim quarto-nvim
render-markdown-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; [ data = with pkgs.vimPlugins; [
blink-cmp blink-cmp
nvim-lspconfig 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; [ data = with pkgs.vimPlugins.nvim-treesitter-parsers; [
bash bash
c c
@ -158,7 +158,7 @@
]; ];
}; };
config.specs.utils-lazy = lib.mkIf (config.cats.utils or true) { config.specs.utils-lazy = {
lazy = true; lazy = true;
data = with pkgs.vimPlugins; [ data = with pkgs.vimPlugins; [
blink-compat blink-compat
@ -175,7 +175,7 @@
]; ];
}; };
config.specs.gitPlugins-lazy = lib.mkIf (config.cats.gitPlugins or true) { config.specs.gitPlugins-lazy = {
lazy = true; lazy = true;
data = []; data = [];
}; };

View file

@ -7,10 +7,16 @@ inputs:
... ...
}: }:
{ {
# ============================================================================
# IMPORTS
# ============================================================================
# Import the base neovim wrapper module and all configuration modules
imports = [ imports = [
wlib.wrapperModules.neovim wlib.wrapperModules.neovim
./module/specs/deps.nix ./module/specs/deps.nix
./module/specs/plugins.nix ./module/specs/plugins.nix
./module/specs/cats-enable.nix
./module/settings/core.nix ./module/settings/core.nix
./module/settings/cats.nix ./module/settings/cats.nix
./module/settings/env.nix ./module/settings/env.nix
@ -19,6 +25,11 @@ inputs:
./module/settings/runtime-path.nix ./module/settings/runtime-path.nix
]; ];
# ============================================================================
# HELPER FUNCTIONS
# ============================================================================
# Utilities for working with plugin inputs
options.nvim-lib.neovimPlugins = lib.mkOption { options.nvim-lib.neovimPlugins = lib.mkOption {
readOnly = true; readOnly = true;
type = lib.types.attrsOf wlib.types.stringable; 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.settings.cats = config.cats;
config.info.cats = config.cats; config.info.cats = config.cats;
config.info.nixCats_config_location = config.settings.config_directory; config.info.nixCats_config_location = config.settings.config_directory;

View file

@ -4,8 +4,9 @@ let
rOverlay = import ./r.nix {inherit inputs;}; rOverlay = import ./r.nix {inherit inputs;};
rNvimNixOverlay = inputs.r-nvim-nix.overlays.default; rNvimNixOverlay = inputs.r-nvim-nix.overlays.default;
pythonOverlay = import ./python.nix {inherit inputs;}; franOverlay = inputs.fran.overlays.default;
pluginsOverlay = import ./plugins.nix {inherit inputs;}; pythonOverlay = import ./python.nix inputs;
pluginsOverlay = import ./plugins.nix inputs;
dependencyOverlays = [ dependencyOverlays = [
rOverlay rOverlay
@ -14,11 +15,6 @@ let
pluginsOverlay pluginsOverlay
]; ];
dependencyOverlay = lib.composeManyExtensions dependencyOverlays; 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 in
{ {
inherit inherit
@ -30,6 +26,20 @@ in
dependencyOverlays dependencyOverlays
dependencyOverlay; dependencyOverlay;
# Named exports for downstream composition.
default = dependencyOverlay; default = dependencyOverlay;
dependencies = dependencyOverlays; dependencies = dependencyOverlays;
overlays = {
inherit
rOverlay
rNvimNixOverlay
franOverlay
pythonOverlay
pluginsOverlay
dependencyOverlays
dependencyOverlay;
default = dependencyOverlay;
dependencies = dependencyOverlays;
};
} }

View file

@ -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, inputs,
... ...
}: final: prev: let }: final: prev: let
# R packages from rstats-on-nix for the current system
rpkgs = import inputs.rixpkgs { rpkgs = import inputs.rixpkgs {
system = prev.stdenv.hostPlatform.system; system = prev.stdenv.hostPlatform.system;
overlays = [inputs.fran.overlays.default]; 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 { in {
inherit rpkgs; inherit rpkgs;
baseRPackages = [ ]; baseRPackages = reqPkgs;
rWrapper = rpkgs.rWrapper.override {packages = [ ];};
quarto = rpkgs.quarto.override {extraRPackages = [ ];}; # 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;}; updateR = import ../scripts/updater.nix {pkgs = final;};
} }

View file

@ -390,25 +390,23 @@ end)
-- zk -- zk
now_if_args(function() now_if_args(function()
if nix.get_cat("markdown", false) then require("zk").setup({
require("zk").setup({ picker = "minipick",
picker = "minipick", lsp = {
lsp = { -- `config` is passed to `vim.lsp.start_client(config)`
-- `config` is passed to `vim.lsp.start_client(config)` config = {
config = { cmd = { "zk", "lsp" },
cmd = { "zk", "lsp" }, name = "zk",
name = "zk", -- on_attach = ...
-- on_attach = ... -- etc, see `:h vim.lsp.start_client()`
-- 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" },
},
}, },
})
end -- automatically attach buffers in a zk notebook that match the given filetypes
auto_attach = {
enabled = true,
filetypes = { "markdown" },
},
},
})
end) end)

View file

@ -71,45 +71,41 @@ end)
now(function() now(function()
vim.treesitter.language.register("markdown", { "quarto", "rmd" }) vim.treesitter.language.register("markdown", { "quarto", "rmd" })
if nix.get_cat({ "r", "markdown" }, false) then vim.api.nvim_create_autocmd("FileType", {
vim.api.nvim_create_autocmd("FileType", { pattern = { "quarto" },
pattern = { "quarto" }, callback = function()
callback = function() require("otter").activate()
require("otter").activate() end,
end, })
})
require("otter").setup({ require("otter").setup({
lsp = { lsp = {
diagnostic_update_events = { "BufWritePost", "InsertLeave" }, diagnostic_update_events = { "BufWritePost", "InsertLeave" },
}, },
buffers = { buffers = {
set_filetype = true, set_filetype = true,
write_to_disk = true, write_to_disk = true,
}, },
}) })
end
end) end)
later(function() later(function()
if nix.get_cat({ "r", "markdown" }, false) then require("quarto").setup({
require("quarto").setup({ lspFeatures = {
lspFeatures = { enabled = true,
chunks = "curly",
languages = { "r", "python", "julia" },
diagnostics = {
enabled = true, enabled = true,
chunks = "curly", triggers = { "BufWritePost" },
languages = { "r", "python", "julia" },
diagnostics = {
enabled = true,
triggers = { "BufWritePost" },
},
completion = {
enabled = true,
},
}, },
codeRunner = { completion = {
enabled = true, enabled = true,
default_method = "slime",
}, },
}) },
end codeRunner = {
enabled = true,
default_method = "slime",
},
})
end) end)

View file

@ -1,7 +1,6 @@
local add = Config.add local add = Config.add
local now_if_args = Config.now_if_args local now_if_args = Config.now_if_args
local later = MiniDeps.later local later = MiniDeps.later
local nix = require('config.nix')
if not Config.isNixCats then if not Config.isNixCats then
local m_add = MiniDeps.add local m_add = MiniDeps.add
@ -13,21 +12,19 @@ end
-- lua -- lua
later(function() later(function()
if nix.get_cat("lua", false) then add("luvit-meta")
add("luvit-meta") add("lazydev")
add("lazydev") require("lazydev").setup({
require("lazydev").setup({ library = {
library = { -- See the configuration section for more details
-- See the configuration section for more details -- Load luvit types when the `vim.uv` word is found
-- Load luvit types when the `vim.uv` word is found "lua",
"lua", "mini.nvim",
"mini.nvim", "MiniDeps",
"MiniDeps", { path = "luvit-meta/library", words = { "vim%.uv" } },
{ path = "luvit-meta/library", words = { "vim%.uv" } }, { path = "${3rd}/luv/library", words = { "vim%.uv" } },
{ path = "${3rd}/luv/library", words = { "vim%.uv" } }, },
}, })
})
end
end) end)
-- Markdown -- Markdown