mirror of
https://github.com/dwinkler1/nvimConfig.git
synced 2026-02-19 14:30:58 -05:00
init wrapper-module config
This commit is contained in:
commit
91755583fd
46 changed files with 4277 additions and 0 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
use flake
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
.DS_Store
|
||||
.direnv
|
||||
133
flake.lock
generated
Normal file
133
flake.lock
generated
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
{
|
||||
"nodes": {
|
||||
"fran": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"rixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1768802006,
|
||||
"narHash": "sha256-czGb4RwTBahNNK9S7ySXeTWIrn/jKH+74hN/uIS2XrM=",
|
||||
"owner": "dwinkler1",
|
||||
"repo": "fran",
|
||||
"rev": "a3879317519fd3685f3b7679a1de4c5ae65a7cb9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "dwinkler1",
|
||||
"repo": "fran",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1769598131,
|
||||
"narHash": "sha256-e7VO/kGLgRMbWtpBqdWl0uFg8Y2XWFMdz0uUJvlML8o=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "fa83fd837f3098e3e678e6cf017b2b36102c7211",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-25.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"plugins-cmp-pandoc-references": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1743491695,
|
||||
"narHash": "sha256-XsdneGNJzmRBggk8lz9JNDQYk7wbYfUAF2oZLXzFb9c=",
|
||||
"owner": "jmbuhr",
|
||||
"repo": "cmp-pandoc-references",
|
||||
"rev": "130eae4f75029d6495808e0ea4b769fa1ce4c9ac",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "jmbuhr",
|
||||
"repo": "cmp-pandoc-references",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"plugins-cmp-r": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1764700377,
|
||||
"narHash": "sha256-xb7VFWM/BKAkN7fg62y8n618t2qkQjdYbPwhBhLJwtk=",
|
||||
"owner": "R-nvim",
|
||||
"repo": "cmp-r",
|
||||
"rev": "70bfe8f4c062acc10266e24825439c009a0b1b89",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "R-nvim",
|
||||
"repo": "cmp-r",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"plugins-r": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1769736135,
|
||||
"narHash": "sha256-T4QgcBL+LCXvrEiRE2JW4jtUKl8DKzFHk8czGUO1jgY=",
|
||||
"owner": "R-nvim",
|
||||
"repo": "R.nvim",
|
||||
"rev": "2701ec64f5485e17c0e057081a9ae2058d776464",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "R-nvim",
|
||||
"repo": "R.nvim",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"rixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1768825970,
|
||||
"narHash": "sha256-m/BI9IO7tMuOSdVNSqr0knQ4V9R6rgSXyGQOp3FovSA=",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/rstats-on-nix/nixpkgs/archive/2026-01-19.tar.gz"
|
||||
},
|
||||
"original": {
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/rstats-on-nix/nixpkgs/archive/2026-01-19.tar.gz"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"fran": "fran",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"plugins-cmp-pandoc-references": "plugins-cmp-pandoc-references",
|
||||
"plugins-cmp-r": "plugins-cmp-r",
|
||||
"plugins-r": "plugins-r",
|
||||
"rixpkgs": "rixpkgs",
|
||||
"wrappers": "wrappers"
|
||||
}
|
||||
},
|
||||
"wrappers": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1769731670,
|
||||
"narHash": "sha256-iHq0bwOsDI5IkJuxVsljdztZdVKIBb8yO0RBRMrco68=",
|
||||
"owner": "BirdeeHub",
|
||||
"repo": "nix-wrapper-modules",
|
||||
"rev": "4622dd5ef8e152475fce48307d3bc77211249c6a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "BirdeeHub",
|
||||
"repo": "nix-wrapper-modules",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
202
flake.nix
Normal file
202
flake.nix
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
# Copyright (c) 2026 BirdeeHub
|
||||
# Licensed under the MIT license
|
||||
{
|
||||
description = "Daniel's NixCats";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
|
||||
wrappers = {
|
||||
url = "github:BirdeeHub/nix-wrapper-modules";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
rixpkgs.url = "https://github.com/rstats-on-nix/nixpkgs/archive/2026-01-19.tar.gz";
|
||||
|
||||
fran = {
|
||||
url = "github:dwinkler1/fran";
|
||||
inputs = {
|
||||
nixpkgs.follows = "rixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
"plugins-r" = {
|
||||
url = "github:R-nvim/R.nvim";
|
||||
flake = false;
|
||||
};
|
||||
"plugins-cmp-r" = {
|
||||
url = "github:R-nvim/cmp-r";
|
||||
flake = false;
|
||||
};
|
||||
"plugins-cmp-pandoc-references" = {
|
||||
url = "github:jmbuhr/cmp-pandoc-references";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs,
|
||||
wrappers,
|
||||
...
|
||||
} @ inputs: let
|
||||
wrapperSettings = pkgs:
|
||||
wrapper.config.wrap {
|
||||
inherit pkgs;
|
||||
cats = {
|
||||
clickhouse = false;
|
||||
gitPlugins = false;
|
||||
julia = false;
|
||||
lua = false;
|
||||
markdown = false;
|
||||
nix = true;
|
||||
optional = false;
|
||||
python = false;
|
||||
r = true;
|
||||
};
|
||||
|
||||
settings.lang_packages = {
|
||||
python = with pkgs.python3Packages; [
|
||||
duckdb
|
||||
polars
|
||||
];
|
||||
|
||||
r = with pkgs.rpkgs.rPackages; [
|
||||
arrow
|
||||
broom
|
||||
data_table
|
||||
duckdb
|
||||
janitor
|
||||
styler
|
||||
tidyverse
|
||||
];
|
||||
|
||||
julia = ["DataFramesMeta" "QuackIO"];
|
||||
};
|
||||
};
|
||||
|
||||
systems = [
|
||||
"aarch64-darwin"
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
|
||||
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 = extra_pkg_config;
|
||||
overlays = [dependencyOverlay];
|
||||
};
|
||||
|
||||
module = nixpkgs.lib.modules.importApply ./modules/neovim.nix inputs;
|
||||
wrapper = wrappers.lib.evalModule module;
|
||||
in {
|
||||
overlays = {
|
||||
default = nixpkgs.lib.composeManyExtensions [
|
||||
dependencyOverlay
|
||||
(final: prev: {
|
||||
n = wrapper.config.wrap {pkgs = final;};
|
||||
})
|
||||
];
|
||||
dependencies = dependencyOverlay;
|
||||
n = self.overlays.default;
|
||||
};
|
||||
|
||||
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 = nvimPkg;
|
||||
n = nvimPkg;
|
||||
vim = nvimPkg;
|
||||
nvim = nvimPkg;
|
||||
}
|
||||
);
|
||||
|
||||
formatter = forAllSystems (
|
||||
system: let
|
||||
pkgs = mkPkgs system;
|
||||
in
|
||||
pkgs.nixfmt-tree
|
||||
);
|
||||
|
||||
devShells = forAllSystems (
|
||||
system: let
|
||||
pkgs = mkPkgs system;
|
||||
nvimPkg = wrapperSettings pkgs;
|
||||
in {
|
||||
default = pkgs.mkShell {
|
||||
name = "n";
|
||||
packages = [nvimPkg];
|
||||
nativeBuildInputs = with pkgs; [] ++ (pkgs.lib.optionals self.wrappers.default.cats.optional [devenv]);
|
||||
inputsFrom = [];
|
||||
shellHook = "";
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
checks = forAllSystems (
|
||||
system: let
|
||||
pkgs = mkPkgs system;
|
||||
nvimPkg = wrapperSettings pkgs;
|
||||
in {
|
||||
default = nvimPkg;
|
||||
module-eval = let
|
||||
_ = wrapper.config;
|
||||
in
|
||||
pkgs.runCommand "check-module-eval" {} ''
|
||||
echo "Module evaluation successful" > $out
|
||||
'';
|
||||
package-build = pkgs.runCommand "check-n" {} ''
|
||||
BINARY_PATH="${nvimPkg}/bin/n"
|
||||
|
||||
if [ ! -x "$BINARY_PATH" ]; then
|
||||
echo "Error: Binary n not found or not executable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$BINARY_PATH" --version > version_output.txt 2>&1 || true
|
||||
|
||||
echo "Package validation successful" > $out
|
||||
echo "Binary location: $BINARY_PATH" >> $out
|
||||
if [ -s version_output.txt ]; then
|
||||
echo "Version output:" >> $out
|
||||
cat version_output.txt >> $out
|
||||
fi
|
||||
'';
|
||||
}
|
||||
);
|
||||
|
||||
nixosModules.default = wrappers.lib.mkInstallModule {
|
||||
name = "n";
|
||||
value = module;
|
||||
};
|
||||
|
||||
homeModules.default = wrappers.lib.mkInstallModule {
|
||||
name = "n";
|
||||
value = module;
|
||||
loc = ["home" "packages"];
|
||||
};
|
||||
};
|
||||
}
|
||||
6
ftplugin/julia.lua
Normal file
6
ftplugin/julia.lua
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
vim.b.slime_cell_delimiter = vim.b.slime_cell_delimiter or "# %%"
|
||||
|
||||
local ts_lib = Config.treesitter_helpers
|
||||
|
||||
local global_nodes_julia = { 'source_file', 'module_definition' }
|
||||
ts_lib.setup_keybindings(global_nodes_julia)
|
||||
32
ftplugin/markdown.lua
Normal file
32
ftplugin/markdown.lua
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
-- Add the key mappings only for Markdown files in a zk notebook.
|
||||
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", "<CR>", "<Cmd>lua vim.lsp.buf.definition()<CR>", { noremap = true, silent = false, buffer = true })
|
||||
|
||||
-- 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.
|
||||
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)" })
|
||||
-- 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>",
|
||||
{ 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", "<leader>zhnc",
|
||||
":'<,'>ZkNewFromContentSelection { dir = vim.fn.expand('%:p:h'), title = vim.fn.input('Title: ') }<CR>",
|
||||
{ noremap = true, silent = false, buffer = true, desc = "Note from selection (content)" })
|
||||
|
||||
-- Open notes linking to the current buffer.
|
||||
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.
|
||||
--map('n', '<leader>zb', '<Cmd>lua vim.lsp.buf.references()<CR>', opts)
|
||||
-- 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>zi", "<Cmd>ZkInsertLink<CR>", { noremap = true, silent = false, buffer = true, desc = "Insert link" })
|
||||
|
||||
-- Preview a linked note.
|
||||
-- Open the code actions for a visual selection.
|
||||
map("v", "<leader>za", ":'<,'>lua vim.lsp.buf.range_code_action()<CR>",
|
||||
{ noremap = true, silent = false, buffer = true, desc = "Code actions" })
|
||||
|
||||
end
|
||||
20
ftplugin/python.lua
Normal file
20
ftplugin/python.lua
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
vim.g.slime_python_ipython = 1
|
||||
vim.b.slime_cell_delimiter = vim.b.slime_cell_delimiter or "# %%"
|
||||
|
||||
local ts_lib = Config.treesitter_helpers
|
||||
local global_nodes_python = { 'module' }
|
||||
ts_lib.setup_keybindings(global_nodes_python)
|
||||
|
||||
local conform_format_group =
|
||||
vim.api.nvim_create_augroup("PythonConformFormat_" .. vim.api.nvim_get_current_buf(), { clear = true })
|
||||
vim.api.nvim_create_autocmd("BufWritePre", {
|
||||
group = conform_format_group,
|
||||
buffer = 0,
|
||||
callback = function()
|
||||
require("conform").format({
|
||||
timeout_ms = 1000,
|
||||
lsp_format = "prefer",
|
||||
})
|
||||
end,
|
||||
})
|
||||
56
ftplugin/r.lua
Normal file
56
ftplugin/r.lua
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
vim.b.slime_cell_delimiter = vim.b.slime_cell_delimiter or "## ----"
|
||||
|
||||
local assign_action = function()
|
||||
if vim.bo.filetype ~= "r" then
|
||||
return
|
||||
end
|
||||
|
||||
local ok, r_edit = pcall(require, "r.edit")
|
||||
if not ok then
|
||||
return
|
||||
end
|
||||
|
||||
if MiniTrailspace and MiniTrailspace.trim then
|
||||
MiniTrailspace.trim()
|
||||
end
|
||||
r_edit.assign()
|
||||
end
|
||||
|
||||
vim.api.nvim_buf_create_user_command(0, "RAssign", assign_action, { desc = "Trim trailing space and insert <-" })
|
||||
-- Settings
|
||||
vim.bo.comments = [[:#',:####,:###,:##,:#]]
|
||||
|
||||
-- Keymaps
|
||||
-- Note: These use <Plug> mappings provided by R.nvim
|
||||
vim.keymap.set("n", "<Enter>", "<Plug>RDSendLine", { buffer = true })
|
||||
vim.keymap.set("v", "<Enter>", "<Plug>RSendSelection", { buffer = true })
|
||||
|
||||
-- Assignment operator (--)
|
||||
vim.keymap.set("i", "--", "<Cmd>lua MiniTrailspace.trim()<CR><Plug>RInsertAssign", { buffer = true, noremap = true })
|
||||
|
||||
-- Pipe operator (;;)
|
||||
vim.keymap.set("i", ";;", "<Cmd>lua MiniTrailspace.trim()<CR><Plug>RInsertPipe<CR>", { buffer = true, noremap = true })
|
||||
|
||||
-- MiniClue / WhichKey hints
|
||||
local r_clues = {
|
||||
{ mode = "n", keys = "<localleader>a", desc = "+batch" },
|
||||
{ mode = "n", keys = "<localleader>b", desc = "+between/debug" },
|
||||
{ mode = "n", keys = "<localleader>c", desc = "+substitute" },
|
||||
{ mode = "n", keys = "<localleader>f", desc = "+functions" },
|
||||
{ mode = "n", keys = "<localleader>i", desc = "+install" },
|
||||
{ mode = "n", keys = "<localleader>k", desc = "+knit" },
|
||||
{ mode = "n", keys = "<localleader>p", desc = "+paragraph" },
|
||||
{ mode = "n", keys = "<localleader>r", desc = "+regular" },
|
||||
{ mode = "n", keys = "<localleader>s", desc = "+selection" },
|
||||
{ mode = "n", keys = "<localleader>t", desc = "+dput" },
|
||||
{ mode = "n", keys = "<localleader>u", desc = "+undebug" },
|
||||
}
|
||||
|
||||
vim.b.miniclue_config = {
|
||||
clues = {
|
||||
r_clues,
|
||||
},
|
||||
triggers = {
|
||||
{ mode = "n", keys = "<localleader>", desc = "+R" },
|
||||
},
|
||||
}
|
||||
11
ftplugin/sql.lua
Normal file
11
ftplugin/sql.lua
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
vim.g.omni_sql_default_compl_type = "syntax"
|
||||
|
||||
local ts_lib = Config.treesitter_helpers
|
||||
local global_nodes_sql = { 'program', 'cte' }
|
||||
ts_lib.setup_keybindings(global_nodes_sql)
|
||||
|
||||
-- SQL specific keybindings
|
||||
vim.keymap.set({ 'n' }, '<localleader>;', function()
|
||||
vim.api.nvim_call_function('slime#send', { ";\n" })
|
||||
end,
|
||||
{ noremap = true, silent = true, desc = "SQL statment return", buffer = true })
|
||||
28
init.lua
Normal file
28
init.lua
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
_G.Config = {}
|
||||
local nix = require('config.nix').init { non_nix_value = true }
|
||||
Config.isNixCats = nix.is_nix
|
||||
|
||||
|
||||
require('lze').register_handlers(require('nixCatsUtils.lzUtils').for_cat)
|
||||
|
||||
local mini_deps = require('mini.deps')
|
||||
|
||||
if not Config.isNixCats then
|
||||
local path_package = vim.fn.stdpath('data') .. '/site/'
|
||||
local mini_path = path_package .. 'pack/deps/start/mini.nvim'
|
||||
if not vim.uv.fs_stat(mini_path) then
|
||||
vim.cmd('echo "Installing `mini.nvim`" | redraw')
|
||||
local clone_cmd = {
|
||||
'git', 'clone', '--filter=blob:none',
|
||||
'https://github.com/echasnovski/mini.nvim', mini_path
|
||||
}
|
||||
vim.fn.system(clone_cmd)
|
||||
vim.cmd('packadd mini.nvim | helptags ALL')
|
||||
vim.cmd('echo "Installed `mini.nvim`" | redraw')
|
||||
end
|
||||
|
||||
-- Set up 'mini.deps' (customize to your liking)
|
||||
mini_deps.setup({ path = { package = path_package } })
|
||||
else
|
||||
mini_deps.setup()
|
||||
end
|
||||
166
lua/config/nix.lua
Normal file
166
lua/config/nix.lua
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
local M = {}
|
||||
|
||||
local function detect_nix()
|
||||
if vim.g.nix_info_plugin_name ~= nil then
|
||||
return true
|
||||
end
|
||||
if vim.g[ [[nixCats-special-rtp-entry-nixCats]] ] ~= nil then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
M.is_nix = detect_nix()
|
||||
M.non_nix_default = true
|
||||
|
||||
local function setup_nixcats(non_nix_value)
|
||||
if M.is_nix then
|
||||
return
|
||||
end
|
||||
|
||||
local ok, utils = pcall(require, "nixCatsUtils")
|
||||
if ok and utils and utils.setup then
|
||||
utils.setup { non_nix_value = non_nix_value }
|
||||
end
|
||||
end
|
||||
|
||||
local function init_from_nix_info()
|
||||
if vim.g.nix_info_plugin_name == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local ok, nix_info = pcall(require, vim.g.nix_info_plugin_name)
|
||||
if not ok or not nix_info then
|
||||
return nil
|
||||
end
|
||||
|
||||
local function cat_lookup(cat)
|
||||
if type(cat) == "table" then
|
||||
for _, name in ipairs(cat) do
|
||||
if nix_info(false, "settings", "cats", name) or nix_info(false, "info", "cats", name) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
return nix_info(false, "settings", "cats", cat) or nix_info(false, "info", "cats", cat)
|
||||
end
|
||||
|
||||
local nc = setmetatable({
|
||||
cats = nix_info.settings and nix_info.settings.cats or {},
|
||||
settings = nix_info.settings or {},
|
||||
get = function(_, default, ...) return nix_info(default, ...) end,
|
||||
}, {
|
||||
__call = function(_, default, ...)
|
||||
if select("#", ...) == 0 then
|
||||
return cat_lookup(default)
|
||||
end
|
||||
return nix_info(default, ...)
|
||||
end,
|
||||
__index = nix_info,
|
||||
})
|
||||
|
||||
_G.nixCats = nc
|
||||
package.preload['nixCats.cats'] = function()
|
||||
return setmetatable(_G.nixCats.cats or {}, getmetatable(_G.nixCats))
|
||||
end
|
||||
|
||||
return nc
|
||||
end
|
||||
|
||||
local function get_nixcats()
|
||||
if _G.nixCats then
|
||||
return _G.nixCats
|
||||
end
|
||||
|
||||
local nc = init_from_nix_info()
|
||||
if nc then
|
||||
return nc
|
||||
end
|
||||
|
||||
local ok, nc_module = pcall(require, "nixCats")
|
||||
if ok and nc_module then
|
||||
return nc_module
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function M.init(opts)
|
||||
local non_nix_value = true
|
||||
if type(opts) == "table" and type(opts.non_nix_value) == "boolean" then
|
||||
non_nix_value = opts.non_nix_value
|
||||
end
|
||||
|
||||
M.non_nix_default = non_nix_value
|
||||
setup_nixcats(non_nix_value)
|
||||
get_nixcats()
|
||||
M.is_nix = detect_nix()
|
||||
return M
|
||||
end
|
||||
|
||||
local function cat_enabled(nc, cat, default)
|
||||
if not nc then
|
||||
return default
|
||||
end
|
||||
|
||||
if type(cat) == "table" then
|
||||
for _, name in ipairs(cat) do
|
||||
if nc(name) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return default
|
||||
end
|
||||
|
||||
local val = nc(cat)
|
||||
if val == nil then
|
||||
return default
|
||||
end
|
||||
return val
|
||||
end
|
||||
|
||||
function M.get_cat(cat, default)
|
||||
if default == nil then
|
||||
default = M.non_nix_default
|
||||
end
|
||||
if not M.is_nix then
|
||||
return default
|
||||
end
|
||||
local nc = get_nixcats()
|
||||
return cat_enabled(nc, cat, default)
|
||||
end
|
||||
|
||||
function M.get_setting(default, ...)
|
||||
if not M.is_nix then
|
||||
return default
|
||||
end
|
||||
local nc = get_nixcats()
|
||||
if not nc then
|
||||
return default
|
||||
end
|
||||
|
||||
local value = nc(default, "settings", ...)
|
||||
if value == nil then
|
||||
return default
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
function M.get_info(default, ...)
|
||||
if not M.is_nix then
|
||||
return default
|
||||
end
|
||||
local nc = get_nixcats()
|
||||
if not nc then
|
||||
return default
|
||||
end
|
||||
|
||||
local value = nc(default, "info", ...)
|
||||
if value == nil then
|
||||
return default
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
return M
|
||||
129
lua/nixCatsUtils/init.lua
Normal file
129
lua/nixCatsUtils/init.lua
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
--[[
|
||||
This directory is the luaUtils template.
|
||||
You can choose what things from it that you would like to use.
|
||||
And then delete the rest.
|
||||
Everything in this directory is optional.
|
||||
--]]
|
||||
|
||||
local M = {}
|
||||
|
||||
--[[
|
||||
This file is for making your config still work WITHOUT nixCats.
|
||||
When you don't use nixCats to load your config,
|
||||
you wont have the nixCats plugin.
|
||||
|
||||
The setup function defined here defines a mock nixCats plugin when nixCats wasnt used to load the config.
|
||||
This will help avoid indexing errors when the nixCats plugin doesnt exist.
|
||||
|
||||
NOTE: If you only ever use nixCats to load your config, you don't need this file.
|
||||
--]]
|
||||
|
||||
---@type boolean
|
||||
M.isNixCats = vim.g.nix_info_plugin_name ~= nil or vim.g[ [[nixCats-special-rtp-entry-nixCats]] ] ~= nil
|
||||
|
||||
---@class nixCatsSetupOpts
|
||||
---@field non_nix_value boolean|nil
|
||||
|
||||
---This function will setup a mock nixCats plugin when not using nix
|
||||
---It will help prevent you from running into indexing errors without a nixCats plugin from nix.
|
||||
---If you loaded the config via nix, it does nothing
|
||||
---non_nix_value defaults to true if not provided or is not a boolean.
|
||||
---@param v nixCatsSetupOpts
|
||||
function M.setup(v)
|
||||
if not M.isNixCats then
|
||||
local nixCats_default_value
|
||||
if type(v) == "table" and type(v.non_nix_value) == "boolean" then
|
||||
nixCats_default_value = v.non_nix_value
|
||||
else
|
||||
nixCats_default_value = true
|
||||
end
|
||||
local mk_with_meta = function (tbl)
|
||||
return setmetatable(tbl, {
|
||||
__call = function(_, attrpath)
|
||||
local strtable = {}
|
||||
if type(attrpath) == "table" then
|
||||
strtable = attrpath
|
||||
elseif type(attrpath) == "string" then
|
||||
for key in attrpath:gmatch("([^%.]+)") do
|
||||
table.insert(strtable, key)
|
||||
end
|
||||
else
|
||||
print("function requires a table of strings or a dot separated string")
|
||||
return
|
||||
end
|
||||
return vim.tbl_get(tbl, unpack(strtable));
|
||||
end
|
||||
})
|
||||
end
|
||||
package.preload['nixCats'] = function ()
|
||||
local ncsub = {
|
||||
get = function(_) return nixCats_default_value end,
|
||||
cats = mk_with_meta({
|
||||
nixCats_config_location = vim.fn.stdpath('config'),
|
||||
wrapRc = false,
|
||||
}),
|
||||
settings = mk_with_meta({
|
||||
nixCats_config_location = vim.fn.stdpath('config'),
|
||||
configDirName = os.getenv("NVIM_APPNAME") or "nvim",
|
||||
wrapRc = false,
|
||||
}),
|
||||
petShop = mk_with_meta({}),
|
||||
extra = mk_with_meta({}),
|
||||
pawsible = mk_with_meta({
|
||||
allPlugins = {
|
||||
start = {},
|
||||
opt = {},
|
||||
},
|
||||
}),
|
||||
configDir = vim.fn.stdpath('config'),
|
||||
packageBinPath = os.getenv('NVIM_WRAPPER_PATH_NIX') or vim.v.progpath
|
||||
}
|
||||
return setmetatable(ncsub, {__call = function(_, cat) return ncsub.get(cat) end})
|
||||
end
|
||||
_G.nixCats = require('nixCats')
|
||||
end
|
||||
end
|
||||
|
||||
---allows you to guarantee a boolean is returned, and also declare a different
|
||||
---default value than specified in setup when not using nix to load the config
|
||||
---@overload fun(v: string|string[]): boolean
|
||||
---@overload fun(v: string|string[], default: boolean): boolean
|
||||
function M.enableForCategory(v, default)
|
||||
if M.isNixCats or default == nil then
|
||||
if nixCats(v) then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
else
|
||||
return default
|
||||
end
|
||||
end
|
||||
|
||||
---if nix, return value of nixCats(v) else return default
|
||||
---Exists to specify a different non_nix_value than the one in setup()
|
||||
---@param v string|string[]
|
||||
---@param default any
|
||||
---@return any
|
||||
function M.getCatOrDefault(v, default)
|
||||
if M.isNixCats then
|
||||
return nixCats(v)
|
||||
else
|
||||
return default
|
||||
end
|
||||
end
|
||||
|
||||
---for conditionally disabling build steps on nix, as they are done via nix
|
||||
---I should probably have named it dontAddIfCats or something.
|
||||
---@overload fun(v: any): any|nil
|
||||
---Will return the second value if nix, otherwise the first
|
||||
---@overload fun(v: any, o: any): any
|
||||
function M.lazyAdd(v, o)
|
||||
if M.isNixCats then
|
||||
return o
|
||||
else
|
||||
return v
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
37
lua/nixCatsUtils/lzUtils.lua
Normal file
37
lua/nixCatsUtils/lzUtils.lua
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
--[[
|
||||
This directory is the luaUtils template.
|
||||
You can choose what things from it that you would like to use.
|
||||
And then delete the rest.
|
||||
Everything in this directory is optional.
|
||||
--]]
|
||||
|
||||
local M = {}
|
||||
local nix = require('config.nix')
|
||||
-- A nixCats specific lze handler that you can use to conditionally enable by category easier.
|
||||
-- at the start of your config, register with
|
||||
-- require('lze').register_handlers(require('nixCatsUtils.lzUtils').for_cat)
|
||||
-- before any calls to require('lze').load using the handler have been made.
|
||||
-- accepts:
|
||||
-- for_cat = { "your" "cat" };
|
||||
-- for_cat = { cat = { "your" "cat" }, default = bool }
|
||||
-- for_cat = "your.cat";
|
||||
-- for_cat = { cat = "your.cat", default = bool }
|
||||
-- where default is an alternate value for when nixCats was NOT used to install the config
|
||||
M.for_cat = {
|
||||
spec_field = "for_cat",
|
||||
set_lazy = false,
|
||||
modify = function(plugin)
|
||||
if type(plugin.for_cat) == "table" and plugin.for_cat.cat ~= nil then
|
||||
local default = plugin.for_cat.default
|
||||
if default == nil then
|
||||
default = false
|
||||
end
|
||||
plugin.enabled = nix.get_cat(plugin.for_cat.cat, default)
|
||||
else
|
||||
plugin.enabled = nix.get_cat(plugin.for_cat, false)
|
||||
end
|
||||
return plugin
|
||||
end,
|
||||
}
|
||||
|
||||
return M
|
||||
196
lua/nix_smart_send.lua
Normal file
196
lua/nix_smart_send.lua
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
local M = {}
|
||||
|
||||
-- Helper function to check if value exists in list (optimized with early return)
|
||||
local function is_in_list(list, value)
|
||||
if not list or not value then
|
||||
return false
|
||||
end
|
||||
|
||||
for _, v in ipairs(list) do
|
||||
if v == value then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Define comment node types as constants
|
||||
local COMMENT_TYPES = {
|
||||
comment = true,
|
||||
block_comment = true,
|
||||
line_comment = true,
|
||||
}
|
||||
|
||||
function M.get_current_node()
|
||||
local ts_utils = require('nvim-treesitter.ts_utils')
|
||||
local cur_win = vim.api.nvim_get_current_win()
|
||||
return ts_utils.get_node_at_cursor(cur_win, true)
|
||||
end
|
||||
|
||||
function M.detect_global_node()
|
||||
local cur_node = M.get_current_node()
|
||||
local root
|
||||
|
||||
if not cur_node then
|
||||
-- print("No node detected")
|
||||
local parser = vim.treesitter.get_parser()
|
||||
if not parser then
|
||||
return nil
|
||||
end
|
||||
root = parser:parse()[1]:root()
|
||||
else
|
||||
root = cur_node:root()
|
||||
end
|
||||
|
||||
if not root then
|
||||
return nil
|
||||
end
|
||||
|
||||
return root:type()
|
||||
end
|
||||
|
||||
function M.move_to_next_non_empty_line()
|
||||
local ts_utils = require('nvim-treesitter.ts_utils')
|
||||
-- Search for the next non-empty line
|
||||
local line_num = vim.fn.search("[^;\\s]", "W")
|
||||
|
||||
if line_num <= 0 then
|
||||
-- print("No non-empty line found below the current position")
|
||||
return false
|
||||
end
|
||||
|
||||
-- Get the line content and find first non-whitespace character
|
||||
local line_content = vim.api.nvim_buf_get_lines(0, line_num - 1, line_num, false)[1]
|
||||
local first_non_ws = line_content:find("%S") or 1
|
||||
vim.api.nvim_win_set_cursor(0, { line_num, first_non_ws - 1 })
|
||||
|
||||
local node = M.get_current_node()
|
||||
if not node or not node:type() then
|
||||
-- print("No node found")
|
||||
return false
|
||||
end
|
||||
|
||||
local global_node_type = M.detect_global_node()
|
||||
|
||||
-- Skip comments and global nodes
|
||||
while node and (COMMENT_TYPES[node:type()] or node:type() == global_node_type) do
|
||||
line_num = line_num + 1
|
||||
local max_lines = vim.api.nvim_buf_line_count(0)
|
||||
|
||||
if line_num > max_lines then
|
||||
-- print("Reached end of buffer")
|
||||
return false
|
||||
end
|
||||
|
||||
-- Get the line content and find first non-whitespace character
|
||||
line_content = vim.api.nvim_buf_get_lines(0, line_num - 1, line_num, false)[1]
|
||||
first_non_ws = line_content:find("%S") or 1
|
||||
vim.api.nvim_win_set_cursor(0, { line_num, first_non_ws - 1 })
|
||||
node = ts_utils.get_node_at_cursor()
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function M.vselect_node(node)
|
||||
local ts_utils = require('nvim-treesitter.ts_utils')
|
||||
if not node then
|
||||
return false
|
||||
end
|
||||
|
||||
local cur_buf = vim.api.nvim_get_current_buf()
|
||||
ts_utils.update_selection(cur_buf, node, "V")
|
||||
return true
|
||||
end
|
||||
|
||||
function M.select_until_global(global_nodes)
|
||||
local ts_utils = require('nvim-treesitter.ts_utils')
|
||||
local root_node = M.detect_global_node()
|
||||
if not root_node and global_nodes then
|
||||
root_node = global_nodes[1]
|
||||
end
|
||||
|
||||
-- Use empty table if no global nodes provided
|
||||
global_nodes = global_nodes or {}
|
||||
|
||||
local node = ts_utils.get_node_at_cursor()
|
||||
if not node then
|
||||
-- print("No syntax node found at cursor position")
|
||||
return nil
|
||||
end
|
||||
|
||||
local node_type = node:type()
|
||||
|
||||
if node_type == root_node then
|
||||
-- print("Cursor is on the root " .. root_node .. " node or in an empty area.")
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Check if current node is a global
|
||||
if is_in_list(global_nodes, node_type) then
|
||||
if M.vselect_node(node) then
|
||||
return node
|
||||
end
|
||||
end
|
||||
|
||||
-- Traverse up the tree until we find a global node or reach the root
|
||||
local parent = node:parent()
|
||||
local parent_type = parent:type() or ""
|
||||
if parent and is_in_list(global_nodes, parent_type) then
|
||||
if M.vselect_node(node) then
|
||||
return node
|
||||
end
|
||||
end
|
||||
while parent and not is_in_list(global_nodes, parent:type()) do
|
||||
node = parent
|
||||
parent = node:parent()
|
||||
end
|
||||
|
||||
if M.vselect_node(node) then
|
||||
return node
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function M.slime_send_region()
|
||||
-- Check if slime plugin is available
|
||||
if not vim.fn.exists('*slime#send_op') then
|
||||
vim.notify("slime plugin not available", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
local slime_command = ":<C-u>call slime#send_op(visualmode(), 1)<CR>"
|
||||
local termcodes = vim.api.nvim_replace_termcodes(slime_command, true, true, true)
|
||||
|
||||
vim.api.nvim_feedkeys(termcodes, "x", true)
|
||||
end
|
||||
|
||||
function M.send_repl(global_nodes)
|
||||
local ts_utils = require('nvim-treesitter.ts_utils')
|
||||
local cur_node = M.get_current_node()
|
||||
|
||||
if not cur_node then
|
||||
M.move_to_next_non_empty_line()
|
||||
else
|
||||
local cur_type = cur_node:type()
|
||||
if COMMENT_TYPES[cur_type] or is_in_list(global_nodes, cur_type) then
|
||||
M.move_to_next_non_empty_line()
|
||||
end
|
||||
end
|
||||
|
||||
local sel_node = M.select_until_global(global_nodes)
|
||||
if not sel_node then
|
||||
-- print("No node selected for REPL")
|
||||
return
|
||||
end
|
||||
|
||||
-- Send the selected text to the terminal using vim-slime
|
||||
M.slime_send_region()
|
||||
|
||||
-- Move cursor and continue
|
||||
ts_utils.goto_node(sel_node, true)
|
||||
M.move_to_next_non_empty_line()
|
||||
end
|
||||
|
||||
return M
|
||||
51
modules/module/settings/cats.nix
Normal file
51
modules/module/settings/cats.nix
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options.cats = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.bool;
|
||||
description = ''
|
||||
Category toggles used to enable/disable specs by name.
|
||||
|
||||
Keys map directly to specs (e.g., `python` controls `specs.python`).
|
||||
Set a category to `false` to skip its dependency/plugin specs.
|
||||
|
||||
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
|
||||
- julia: Julia tooling and packages
|
||||
- lua: Lua tooling and LSPs
|
||||
- markdown: markdown tooling and plugins
|
||||
- nix: Nix tooling and plugins
|
||||
- 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
|
||||
'';
|
||||
};
|
||||
|
||||
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 false;
|
||||
markdown = lib.mkDefault false;
|
||||
nix = lib.mkDefault false;
|
||||
optional = lib.mkDefault false;
|
||||
python = lib.mkDefault false;
|
||||
r = lib.mkDefault false;
|
||||
test = lib.mkDefault false;
|
||||
treesitterParsers = lib.mkDefault true;
|
||||
utils = lib.mkDefault true;
|
||||
};
|
||||
}
|
||||
35
modules/module/settings/core.nix
Normal file
35
modules/module/settings/core.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
# Point to the directory containing init.lua, plugin/, lua/, etc.
|
||||
config.settings.config_directory = ../../..;
|
||||
|
||||
# Default colorscheme and background
|
||||
config.settings.colorscheme = "kanagawa";
|
||||
config.settings.background = "dark";
|
||||
|
||||
# Enable RC wrapping (allows neovim to find the config)
|
||||
config.settings.wrapRc = true;
|
||||
|
||||
# Lua packages available to neovim (for :lua require())
|
||||
config.settings.nvim_lua_env = lp:
|
||||
lib.optionals (config.cats.general or false) [ lp.tiktoken_core ];
|
||||
|
||||
# Binary name for the wrapper
|
||||
config.binName = "n";
|
||||
|
||||
# Prevent neovim from loading system-wide config
|
||||
config.settings.block_normal_config = true;
|
||||
|
||||
# Don't symlink the config (we wrap it instead)
|
||||
config.settings.dont_link = false;
|
||||
|
||||
# Create additional aliases for the binary
|
||||
config.settings.aliases = [ "vim" ];
|
||||
|
||||
# Enable wrapper handling of spec runtimeDeps (template pattern).
|
||||
config.settings.autowrapRuntimeDeps = true;
|
||||
}
|
||||
27
modules/module/settings/env.nix
Normal file
27
modules/module/settings/env.nix
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
# Environment variables set for the wrapper.
|
||||
# These are available when running neovim.
|
||||
config.env = lib.mkMerge [
|
||||
(lib.mkIf (config.cats.r or false) {
|
||||
R_LIBS_USER = "./.Rlibs";
|
||||
})
|
||||
(lib.mkIf (config.cats.python or false) {
|
||||
UV_PYTHON_DOWNLOADS = "never";
|
||||
UV_PYTHON = pkgs.python.interpreter;
|
||||
})
|
||||
(lib.mkIf (config.cats.test or false) {
|
||||
TESTVAR = "It worked!";
|
||||
})
|
||||
];
|
||||
|
||||
# Environment variables with defaults (can be overridden by user)
|
||||
config.envDefault = lib.mkIf (config.cats.test or false) {
|
||||
TESTVAR2 = "It worked again!";
|
||||
};
|
||||
}
|
||||
57
modules/module/settings/hosts.nix
Normal file
57
modules/module/settings/hosts.nix
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
config.hosts = lib.mkMerge [
|
||||
{
|
||||
node.nvim-host.enable = true;
|
||||
perl.nvim-host.enable = true;
|
||||
ruby.nvim-host.enable = true;
|
||||
|
||||
g = {
|
||||
nvim-host.enable = true;
|
||||
nvim-host.package = "${pkgs.neovide}/bin/neovide";
|
||||
nvim-host.argv0 = "neovide";
|
||||
nvim-host.flags."--neovim-bin" = "${placeholder "out"}/bin/${config.binName}";
|
||||
};
|
||||
|
||||
m = {
|
||||
nvim-host.enable = false;
|
||||
nvim-host.package = "${pkgs.uv}/bin/uv";
|
||||
nvim-host.argv0 = "uv";
|
||||
nvim-host.addFlag = [
|
||||
"run"
|
||||
"marimo"
|
||||
"edit"
|
||||
];
|
||||
};
|
||||
}
|
||||
(lib.mkIf (config.cats.julia or true) {
|
||||
jl = {
|
||||
nvim-host.enable = true;
|
||||
nvim-host.package = "${pkgs.julia-bin}/bin/julia";
|
||||
nvim-host.argv0 = "julia";
|
||||
nvim-host.addFlag = [
|
||||
"--project=@."
|
||||
];
|
||||
};
|
||||
})
|
||||
(lib.mkIf (config.cats.python or true) {
|
||||
python3.nvim-host.enable = true;
|
||||
})
|
||||
(lib.mkIf (config.cats.r or true) {
|
||||
r = {
|
||||
nvim-host.enable = true;
|
||||
nvim-host.package = "${pkgs.rWrapper}/bin/R";
|
||||
nvim-host.argv0 = "R";
|
||||
nvim-host.addFlag = [
|
||||
"--no-save"
|
||||
"--no-restore"
|
||||
];
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
39
modules/module/settings/lang-packages.nix
Normal file
39
modules/module/settings/lang-packages.nix
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
options.settings.lang_packages = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
python = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.package;
|
||||
default = [ ];
|
||||
description = "Additional Python-related packages appended to the python spec (overlay defaults remain).";
|
||||
};
|
||||
r = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.package;
|
||||
default = [ ];
|
||||
description = "Additional R-related packages appended to the r spec (overlay defaults remain).";
|
||||
};
|
||||
julia = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
description = "Additional Julia packages (names) passed to julia-bin.withPackages.";
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
Language-specific package overrides appended to each language spec's extraPackages.
|
||||
Intended for flake.nix overrides via wrapper.config.wrap.
|
||||
'';
|
||||
};
|
||||
|
||||
config.settings.lang_packages = {
|
||||
python = lib.mkDefault [ ];
|
||||
r = lib.mkDefault [ ];
|
||||
julia = lib.mkDefault [ ];
|
||||
};
|
||||
}
|
||||
35
modules/module/settings/runtime-path.nix
Normal file
35
modules/module/settings/runtime-path.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
collect_runtime_packages = runtime_deps_type:
|
||||
config.specCollect
|
||||
(acc: spec:
|
||||
let
|
||||
is_enabled = if spec ? enable then spec.enable else true;
|
||||
has_runtime_deps = (spec.runtimeDeps or false) == runtime_deps_type;
|
||||
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: [
|
||||
{
|
||||
data = [
|
||||
"PATH"
|
||||
":"
|
||||
"${lib.makeBinPath packages}"
|
||||
];
|
||||
}
|
||||
];
|
||||
in
|
||||
{
|
||||
config.prefixVar = lib.optionals (prefix_packages != [ ]) (to_path_specs prefix_packages);
|
||||
config.suffixVar = lib.optionals (suffix_packages != [ ]) (to_path_specs suffix_packages);
|
||||
}
|
||||
51
modules/module/specs/cats-enable.nix
Normal file
51
modules/module/specs/cats-enable.nix
Normal 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;
|
||||
}
|
||||
];
|
||||
}
|
||||
188
modules/module/specs/deps.nix
Normal file
188
modules/module/specs/deps.nix
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
wlib,
|
||||
...
|
||||
}: {
|
||||
# ============================================================================
|
||||
# SPEC MODULE DEFAULTS
|
||||
# ============================================================================
|
||||
# Define default options available to all specs
|
||||
|
||||
config.specMods = {parentSpec ? null, ...}: {
|
||||
options.extraPackages = lib.mkOption {
|
||||
type = lib.types.listOf wlib.types.stringable;
|
||||
default = [];
|
||||
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"];
|
||||
config = ''
|
||||
vim.o.shell = "${pkgs.zsh}/bin/zsh"
|
||||
'';
|
||||
runtimeDeps = "prefix";
|
||||
extraPackages = with pkgs; [
|
||||
perl
|
||||
ruby
|
||||
shfmt
|
||||
sqlfluff
|
||||
tree-sitter
|
||||
];
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# OPTIONAL TOOLS SPEC
|
||||
# ============================================================================
|
||||
|
||||
config.specs.optional = lib.mkIf (config.cats.optional or true) {
|
||||
data = lib.mkDefault null;
|
||||
runtimeDeps = "prefix";
|
||||
before = ["INIT_MAIN"];
|
||||
extraPackages = with pkgs; [
|
||||
bat
|
||||
broot
|
||||
devenv
|
||||
dust
|
||||
fd
|
||||
fzf
|
||||
gawk
|
||||
gh
|
||||
git
|
||||
hunspell
|
||||
hunspellDicts.de-at
|
||||
hunspellDicts.en-us
|
||||
ispell
|
||||
jq
|
||||
just
|
||||
lazygit
|
||||
man
|
||||
ncdu
|
||||
pigz
|
||||
poppler
|
||||
ripgrep
|
||||
tokei
|
||||
wget
|
||||
yq
|
||||
zathura
|
||||
];
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# MARKDOWN SPEC
|
||||
# ============================================================================
|
||||
|
||||
config.specs.markdown = lib.mkIf (config.cats.markdown or true) {
|
||||
data = lib.mkDefault null;
|
||||
runtimeDeps = "prefix";
|
||||
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";
|
||||
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";
|
||||
extraPackages = with pkgs; [
|
||||
lua-language-server
|
||||
];
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# PYTHON SPEC
|
||||
# ============================================================================
|
||||
|
||||
config.specs.python = lib.mkIf (config.cats.python or true) {
|
||||
data = lib.mkDefault null;
|
||||
runtimeDeps = "prefix";
|
||||
extraPackages = let
|
||||
python_packages_fn =
|
||||
if pkgs ? basePythonPackages
|
||||
then ps: pkgs.basePythonPackages ps ++ config.settings.lang_packages.python
|
||||
else _: config.settings.lang_packages.python;
|
||||
python_with_packages = pkgs.python3.withPackages python_packages_fn;
|
||||
in
|
||||
with pkgs; [
|
||||
python_with_packages
|
||||
nodejs
|
||||
ruff
|
||||
basedpyright
|
||||
uv
|
||||
];
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# R SPEC
|
||||
# ============================================================================
|
||||
|
||||
config.specs.r = lib.mkIf (config.cats.r or true) {
|
||||
data = lib.mkDefault null;
|
||||
runtimeDeps = "prefix";
|
||||
extraPackages = let
|
||||
r_packages = (pkgs.baseRPackages or []) ++ config.settings.lang_packages.r;
|
||||
in
|
||||
with pkgs; [
|
||||
(rWrapper.override {packages = r_packages;})
|
||||
radianWrapper
|
||||
(quarto.override {extraRPackages = r_packages;})
|
||||
air-formatter
|
||||
yaml-language-server
|
||||
updateR
|
||||
];
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# JULIA SPEC
|
||||
# ============================================================================
|
||||
|
||||
config.specs.julia = lib.mkIf (config.cats.julia or true) {
|
||||
data = lib.mkDefault null;
|
||||
runtimeDeps = "prefix";
|
||||
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";
|
||||
extraPackages = with pkgs; [
|
||||
clickhouse-lts
|
||||
];
|
||||
};
|
||||
|
||||
config.extraPackages = config.specCollect (acc: v: acc ++ (v.extraPackages or [])) [];
|
||||
}
|
||||
183
modules/module/specs/plugins.nix
Normal file
183
modules/module/specs/plugins.nix
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
config.specs.gitPlugins = {
|
||||
data = [ ];
|
||||
};
|
||||
|
||||
config.specs.r = {
|
||||
data = [
|
||||
config.nvim-lib.neovimPlugins.r
|
||||
];
|
||||
};
|
||||
|
||||
config.specs.markdown-lazy = {
|
||||
lazy = true;
|
||||
data = [
|
||||
config.nvim-lib.neovimPlugins.cmp-pandoc-references
|
||||
];
|
||||
};
|
||||
|
||||
config.specs.r-lazy = {
|
||||
lazy = true;
|
||||
data = [
|
||||
config.nvim-lib.neovimPlugins.cmp-r
|
||||
];
|
||||
};
|
||||
|
||||
config.specs.general = {
|
||||
data = with pkgs.vimPlugins; [
|
||||
lze
|
||||
lzextras
|
||||
plenary-nvim
|
||||
neogit
|
||||
{
|
||||
data = mini-nvim;
|
||||
pname = "mini.nvim";
|
||||
}
|
||||
{
|
||||
data = cyberdream-nvim;
|
||||
pname = "cyberdream";
|
||||
}
|
||||
{
|
||||
data = onedark-nvim;
|
||||
pname = "onedark";
|
||||
}
|
||||
{
|
||||
data = tokyonight-nvim;
|
||||
pname = "tokyonight";
|
||||
}
|
||||
{
|
||||
data = kanagawa-nvim;
|
||||
pname = "kanagawa";
|
||||
}
|
||||
{
|
||||
data = gruvbox-nvim;
|
||||
pname = "gruvbox";
|
||||
}
|
||||
{
|
||||
data = nord-nvim;
|
||||
pname = "nord";
|
||||
}
|
||||
{
|
||||
data = dracula-nvim;
|
||||
pname = "dracula";
|
||||
}
|
||||
{
|
||||
data = vscode-nvim;
|
||||
pname = "vscode";
|
||||
}
|
||||
{
|
||||
data = nightfox-nvim;
|
||||
pname = "nightfox";
|
||||
}
|
||||
{
|
||||
data = catppuccin-nvim;
|
||||
pname = "catppuccin";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
config.specs.lua = {
|
||||
data = with pkgs.vimPlugins; [
|
||||
luvit-meta
|
||||
{
|
||||
data = lazydev-nvim;
|
||||
pname = "lazydev";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
config.specs.markdown = {
|
||||
data = with pkgs.vimPlugins; [
|
||||
quarto-nvim
|
||||
render-markdown-nvim
|
||||
{
|
||||
data = otter-nvim;
|
||||
pname = "otter";
|
||||
}
|
||||
{
|
||||
data = zk-nvim;
|
||||
pname = "zk";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
config.specs.utils = {
|
||||
data = with pkgs.vimPlugins; [
|
||||
blink-cmp
|
||||
nvim-lspconfig
|
||||
nvim-treesitter-context
|
||||
nvim-treesitter-textobjects
|
||||
{
|
||||
data = pkgs.codecompanion-nvim;
|
||||
pname = "codecompanion";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
config.specs.treesitterParsers = {
|
||||
data = with pkgs.vimPlugins.nvim-treesitter-parsers; [
|
||||
bash
|
||||
c
|
||||
cpp
|
||||
csv
|
||||
diff
|
||||
dockerfile
|
||||
git_config
|
||||
git_rebase
|
||||
gitattributes
|
||||
gitcommit
|
||||
gitignore
|
||||
html
|
||||
javascript
|
||||
json
|
||||
julia
|
||||
latex
|
||||
lua
|
||||
luadoc
|
||||
make
|
||||
markdown
|
||||
markdown_inline
|
||||
nix
|
||||
python
|
||||
query
|
||||
r
|
||||
rnoweb
|
||||
regex
|
||||
sql
|
||||
toml
|
||||
vim
|
||||
vimdoc
|
||||
xml
|
||||
yaml
|
||||
zig
|
||||
];
|
||||
};
|
||||
|
||||
config.specs.utils-lazy = {
|
||||
lazy = true;
|
||||
data = with pkgs.vimPlugins; [
|
||||
blink-compat
|
||||
blink-copilot
|
||||
cmp-cmdline
|
||||
colorful-menu-nvim
|
||||
conform-nvim
|
||||
copilot-lua
|
||||
nvim-dap
|
||||
nvim-dap-ui
|
||||
nvim-dap-virtual-text
|
||||
nvim-lint
|
||||
vim-slime
|
||||
];
|
||||
};
|
||||
|
||||
config.specs.gitPlugins-lazy = {
|
||||
lazy = true;
|
||||
data = [ ];
|
||||
};
|
||||
}
|
||||
71
modules/neovim.nix
Normal file
71
modules/neovim.nix
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
inputs:
|
||||
{
|
||||
config,
|
||||
wlib,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
# ============================================================================
|
||||
# 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
|
||||
./module/settings/hosts.nix
|
||||
./module/settings/lang-packages.nix
|
||||
./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;
|
||||
default = config.nvim-lib.pluginsFromPrefix "plugins-" inputs;
|
||||
};
|
||||
|
||||
options.nvim-lib.pluginsFromPrefix = lib.mkOption {
|
||||
type = lib.types.raw;
|
||||
readOnly = true;
|
||||
default =
|
||||
prefix: inputs:
|
||||
lib.pipe inputs [
|
||||
builtins.attrNames
|
||||
(builtins.filter (s: lib.hasPrefix prefix s))
|
||||
(map (
|
||||
input:
|
||||
let
|
||||
name = lib.removePrefix prefix input;
|
||||
in
|
||||
{
|
||||
inherit name;
|
||||
value = config.nvim-lib.mkPlugin name inputs.${input};
|
||||
}
|
||||
))
|
||||
builtins.listToAttrs
|
||||
];
|
||||
};
|
||||
|
||||
# ============================================================================
|
||||
# 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;
|
||||
config.info.nixCats_wrapRc = config.settings.wrapRc or false;
|
||||
config.info.nixCats_configDirName = "nvim";
|
||||
}
|
||||
98
overlays/README.md
Normal file
98
overlays/README.md
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# Overlays
|
||||
|
||||
This directory contains composable Nix overlays used by the Neovim wrapper configuration. Each overlay is small and focused, so you can reuse or override them downstream.
|
||||
|
||||
## Files
|
||||
|
||||
- `r.nix`
|
||||
R-related overrides (rix overlay). Exposes `pkgs.rpkgs` from rstats-on-nix and creates pre-configured `rWrapper` and `quarto` with standard R packages.
|
||||
|
||||
- `python.nix`
|
||||
Python-related overrides and package additions (e.g., extra Python packages).
|
||||
|
||||
- `plugins.nix`
|
||||
Neovim plugin overrides (e.g., patching or pinning plugin derivations).
|
||||
|
||||
- `default.nix`
|
||||
Aggregates and exports the overlays in a composable way. Includes the fran overlay for custom R packages.
|
||||
|
||||
## Exports from `default.nix`
|
||||
|
||||
`overlays/default.nix` exposes:
|
||||
|
||||
- `rOverlay` - rix overlay for R packages from rstats-on-nix
|
||||
- `franOverlay` - fran overlay for custom R packages and tools
|
||||
- `pythonOverlay`
|
||||
- `pluginsOverlay`
|
||||
- `dependencyOverlays` (list of overlays in order)
|
||||
- `dependencyOverlay` (composed overlay via `lib.composeManyExtensions`)
|
||||
- `default` (alias of `dependencyOverlay`)
|
||||
- `dependencies` (alias of `dependencyOverlays`)
|
||||
|
||||
## Downstream usage examples
|
||||
|
||||
### Use the composed default overlay
|
||||
|
||||
```/dev/null/example.nix#L1-18
|
||||
{
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
overlayDefs = import ./overlays/default.nix inputs;
|
||||
in {
|
||||
nixpkgs.overlays = [
|
||||
overlayDefs.default
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### Use specific overlays only
|
||||
|
||||
```/dev/null/example.nix#L1-22
|
||||
{
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
overlayDefs = import ./overlays/default.nix inputs;
|
||||
in {
|
||||
nixpkgs.overlays = [
|
||||
overlayDefs.rOverlay
|
||||
overlayDefs.pluginsOverlay
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### Extend with your own overlay (composition)
|
||||
|
||||
```/dev/null/example.nix#L1-29
|
||||
{
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
overlayDefs = import ./overlays/default.nix inputs;
|
||||
myOverlay = final: prev: {
|
||||
# Example: override a package
|
||||
myTool = prev.myTool.override { /* ... */ };
|
||||
};
|
||||
in {
|
||||
nixpkgs.overlays = [
|
||||
overlayDefs.default
|
||||
myOverlay
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
## Adding a new overlay
|
||||
|
||||
1. Create a new overlay file in this directory (e.g., `foo.nix`).
|
||||
2. Import it in `overlays/default.nix` and add it to `dependencyOverlays`.
|
||||
3. Optionally expose it as a named export (e.g., `fooOverlay`) for downstream reuse.
|
||||
|
||||
## Notes
|
||||
|
||||
- Keep overlays composable and focused.
|
||||
- Avoid monolithic overlays; prefer small, purpose-specific overlays.
|
||||
- When overriding plugins, keep patches minimal and document the intent.
|
||||
42
overlays/default.nix
Normal file
42
overlays/default.nix
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
{ nixpkgs, ... }@inputs:
|
||||
let
|
||||
lib = nixpkgs.lib;
|
||||
|
||||
rOverlay = import ./r.nix inputs;
|
||||
franOverlay = inputs.fran.overlays.default;
|
||||
pythonOverlay = import ./python.nix inputs;
|
||||
pluginsOverlay = import ./plugins.nix inputs;
|
||||
|
||||
dependencyOverlays = [
|
||||
rOverlay
|
||||
franOverlay
|
||||
pythonOverlay
|
||||
pluginsOverlay
|
||||
];
|
||||
dependencyOverlay = lib.composeManyExtensions dependencyOverlays;
|
||||
in
|
||||
{
|
||||
inherit
|
||||
rOverlay
|
||||
franOverlay
|
||||
pythonOverlay
|
||||
pluginsOverlay
|
||||
dependencyOverlays
|
||||
dependencyOverlay;
|
||||
|
||||
# Named exports for downstream composition.
|
||||
default = dependencyOverlay;
|
||||
dependencies = dependencyOverlays;
|
||||
|
||||
overlays = {
|
||||
inherit
|
||||
rOverlay
|
||||
franOverlay
|
||||
pythonOverlay
|
||||
pluginsOverlay
|
||||
dependencyOverlays
|
||||
dependencyOverlay;
|
||||
default = dependencyOverlay;
|
||||
dependencies = dependencyOverlays;
|
||||
};
|
||||
}
|
||||
25
overlays/plugins.nix
Normal file
25
overlays/plugins.nix
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{ ... }:
|
||||
final: prev:
|
||||
{
|
||||
codecompanion-nvim = prev.vimPlugins.codecompanion-nvim.overrideAttrs {
|
||||
checkInputs = with prev.vimPlugins; [
|
||||
blink-cmp
|
||||
mini-nvim
|
||||
];
|
||||
dependencies = [ prev.vimPlugins.plenary-nvim ];
|
||||
nvimSkipModules = [
|
||||
"codecompanion.actions.static"
|
||||
"codecompanion.actions.init"
|
||||
"minimal"
|
||||
"codecompanion.providers.actions.fzf_lua"
|
||||
"codecompanion.providers.completion.cmp.setup"
|
||||
"codecompanion.providers.actions.telescope"
|
||||
"codecompanion.providers.actions.snacks"
|
||||
];
|
||||
};
|
||||
zk-nvim = prev.vimPlugins.zk-nvim.overrideAttrs {
|
||||
nvimSkipModules = [
|
||||
"zk.pickers.fzf_lua"
|
||||
];
|
||||
};
|
||||
}
|
||||
12
overlays/python.nix
Normal file
12
overlays/python.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{ ... }:
|
||||
final: prev:
|
||||
let
|
||||
reqPkgs = pyPackages:
|
||||
with pyPackages; [
|
||||
numpy
|
||||
];
|
||||
in
|
||||
{
|
||||
basePythonPackages = reqPkgs;
|
||||
python = prev.python3.withPackages reqPkgs;
|
||||
}
|
||||
46
overlays/r.nix
Normal file
46
overlays/r.nix
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# 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"
|
||||
{rixpkgs, ...}: final: prev: let
|
||||
# R packages from rstats-on-nix for the current system
|
||||
rpkgs = rixpkgs.legacyPackages.${prev.stdenv.hostPlatform.system};
|
||||
|
||||
# Standard R packages used by default in rWrapper and quarto
|
||||
reqPkgs = with rpkgs.rPackages; [
|
||||
languageserver
|
||||
];
|
||||
in {
|
||||
inherit rpkgs;
|
||||
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; };
|
||||
}
|
||||
183
plugin/00_options.lua
Normal file
183
plugin/00_options.lua
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
--stylua: ignore start
|
||||
local later = MiniDeps.later
|
||||
local now = MiniDeps.now
|
||||
local nix = require('config.nix')
|
||||
|
||||
|
||||
if not Config.isNixCats then
|
||||
now(function()
|
||||
MiniDeps.add({ name = "mini.nvim" })
|
||||
end)
|
||||
end
|
||||
|
||||
-- Leader key =================================================================
|
||||
vim.g.mapleader = ' '
|
||||
vim.g.maplocalleader = ','
|
||||
-- General ====================================================================
|
||||
vim.o.backup = true -- Don't store backup
|
||||
vim.opt.backupdir = vim.fn.stdpath('data') .. '/backups'
|
||||
vim.o.mouse = 'a' -- Enable mouse
|
||||
vim.o.mousescroll = 'ver:25,hor:6' -- Customize mouse scroll
|
||||
vim.o.scrolloff = 8 -- Lines above and below cursor
|
||||
vim.o.switchbuf = 'usetab' -- Use already opened buffers when switching
|
||||
vim.o.writebackup = true -- Don't store backup (better performance)
|
||||
vim.o.undofile = true -- Enable persistent undo
|
||||
vim.o.wildmenu = true -- Enable wildmenu
|
||||
vim.o.wildmode = 'full' -- Show all matches in command line completion
|
||||
|
||||
vim.o.shada = "'100,<50,s10,:1000,/100,@100,h" -- Limit what is stored in ShaDa file
|
||||
|
||||
vim.cmd('filetype plugin indent on') -- Enable all filetype plugins
|
||||
|
||||
-- UI =========================================================================
|
||||
vim.o.breakindent = true -- Indent wrapped lines to match line start
|
||||
vim.o.colorcolumn = '+1' -- Draw colored column one step to the right of desired maximum width
|
||||
vim.o.cursorline = false -- Enable highlighting of the current line
|
||||
vim.o.foldenable = false -- Enable folding
|
||||
vim.o.linebreak = true -- Wrap long lines at 'breakat' (if 'wrap' is set)
|
||||
vim.o.list = true -- Show helpful character indicators
|
||||
vim.o.number = true -- Show line numbers
|
||||
vim.o.pumheight = 10 -- Make popup menu smaller
|
||||
vim.o.relativenumber = true -- Show relative line numbers
|
||||
vim.o.ruler = false -- Don't show cursor position
|
||||
vim.o.shortmess = 'FOSWaco' -- Disable certain messages from |ins-completion-menu|
|
||||
vim.o.showmode = false -- Don't show mode in command line
|
||||
vim.o.signcolumn = 'yes' -- Always show signcolumn or it would frequently shift
|
||||
vim.o.splitbelow = true -- Horizontal splits will be below
|
||||
vim.o.splitright = true -- Vertical splits will be to the right
|
||||
vim.o.wrap = true -- Display long lines as just one line
|
||||
vim.o.background = nix.get_setting('dark', "background") --'light' -- Set background
|
||||
|
||||
vim.o.listchars = table.concat({ 'extends:…', 'nbsp:␣', 'precedes:…', 'tab:> ', 'trail:·' }, ',') -- Special text symbols
|
||||
vim.o.cursorlineopt = 'screenline,number' -- Show cursor line only screen line when wrapped
|
||||
vim.o.breakindentopt = 'list:-1' -- Add padding for lists when 'wrap' is on
|
||||
|
||||
if vim.fn.has('nvim-0.9') == 1 then
|
||||
vim.o.shortmess = 'CFOSWaco' -- Don't show "Scanning..." messages
|
||||
vim.o.splitkeep = 'screen' -- Reduce scroll during window split
|
||||
end
|
||||
|
||||
if vim.fn.has('nvim-0.10') == 0 then
|
||||
vim.o.termguicolors = true -- Enable gui colors (Neovim>=0.10 does this automatically)
|
||||
end
|
||||
|
||||
if vim.fn.has('nvim-0.11') == 1 then
|
||||
-- vim.o.completeopt = 'menuone,fuzzy' -- Use fuzzy matching for built-in completion noselect,
|
||||
vim.o.winborder = 'rounded' -- Use double-line as default border
|
||||
end
|
||||
if vim.fn.has('nvim-0.12') == 1 then
|
||||
vim.o.pummaxwidth = 100 -- Limit maximum width of popup menu
|
||||
vim.o.completefuzzycollect = 'keyword,files,whole_line' -- Use fuzzy matching when collecting candidates
|
||||
end
|
||||
|
||||
vim.o.complete = '.,w,b,kspell' -- Use spell check and don't use tags for completion
|
||||
-- Colors =====================================================================
|
||||
-- Enable syntax highlighing if it wasn't already (as it is time consuming)
|
||||
-- Don't use defer it because it affects start screen appearance
|
||||
if vim.fn.exists('syntax_on') ~= 1 then vim.cmd('syntax enable') end
|
||||
|
||||
-- Editing ====================================================================
|
||||
vim.o.autoindent = true -- Use auto indent
|
||||
vim.o.expandtab = true -- Convert tabs to spaces
|
||||
vim.o.formatoptions = 'qnl1j' -- Improve comment editing
|
||||
vim.o.ignorecase = true -- Ignore case when searching (use `\C` to force not doing that)
|
||||
vim.o.incsearch = true -- Show search results while typing
|
||||
vim.o.infercase = true -- Infer letter cases for a richer built-in keyword completion
|
||||
vim.o.shiftwidth = 2 -- Use this number of spaces for indentation
|
||||
vim.o.smartcase = true -- Don't ignore case when searching if pattern has upper case
|
||||
vim.o.smartindent = true -- Make indenting smart
|
||||
vim.o.tabstop = 2 -- Insert 2 spaces for a tab
|
||||
vim.o.virtualedit = 'block' -- Allow going past the end of line in visual block mode
|
||||
|
||||
vim.o.iskeyword = '@,48-57,_,192-255,-' -- Treat dash separated words as a word text object
|
||||
|
||||
-- Define pattern for a start of 'numbered' list. This is responsible for
|
||||
-- correct formatting of lists when using `gw`. This basically reads as 'at
|
||||
-- least one special character (digit, -, +, *) possibly followed some
|
||||
-- punctuation (. or `)`) followed by at least one space is a start of list
|
||||
-- item'
|
||||
vim.o.formatlistpat = [[^\s*[0-9\-\+\*]\+[\.\)]*\s\+]]
|
||||
|
||||
-- Spelling ===================================================================
|
||||
vim.o.spelllang = 'en_us,de' -- Define spelling dictionaries
|
||||
vim.o.spelloptions = 'camel' -- Treat parts of camelCase words as seprate words
|
||||
|
||||
-- vim.o.dictionary = vim.fn.stdpath('config') .. '/misc/dict/english.txt' -- Use specific dictionaries
|
||||
|
||||
-- Folds ======================================================================
|
||||
vim.o.foldmethod = 'indent' -- Set 'indent' folding method
|
||||
vim.o.foldlevel = 1 -- Display all folds except top ones
|
||||
vim.o.foldnestmax = 10 -- Create folds only for some number of nested levels
|
||||
vim.g.markdown_folding = 1 -- Use folding by heading in markdown files
|
||||
|
||||
if vim.fn.has('nvim-0.10') == 1 then
|
||||
vim.o.foldtext = '' -- Use underlying text with its highlighting
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- Diagnostics ================================================================
|
||||
local diagnostic_opts = {
|
||||
-- Define how diagnostic entries should be shown
|
||||
signs = { priority = 9999, severity = { min = 'HINT', max = 'ERROR' } },
|
||||
virtual_lines = false,
|
||||
virtual_text = { current_line = false, severity = { min = 'WARN', max = 'ERROR' } },
|
||||
jump = { float = false },
|
||||
underline = false,
|
||||
-- Don't update diagnostics when typing
|
||||
update_in_insert = false,
|
||||
}
|
||||
later(function() vim.diagnostic.config(diagnostic_opts) end)
|
||||
|
||||
|
||||
-- Custom autocommands ========================================================
|
||||
local augroup = vim.api.nvim_create_augroup('CustomSettings', {})
|
||||
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = { 'markdown' },
|
||||
group = augroup,
|
||||
callback = function()
|
||||
vim.diagnostic.config({
|
||||
signs = {
|
||||
severity = { min = 'WARN', max = 'ERROR' }
|
||||
},
|
||||
virtual_text = {
|
||||
current_line = false,
|
||||
severity = { min = 'HINT', max = 'ERROR' }
|
||||
}
|
||||
})
|
||||
end
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
desc = "remove formatoptions",
|
||||
callback = function()
|
||||
vim.opt.formatoptions:remove({ "r", "o" }) -- Don't continue comments on enter or o
|
||||
vim.b.minitrailspace_disable = true -- Don't highlight trailing space by default
|
||||
end,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
group = augroup,
|
||||
callback = function()
|
||||
-- Don't auto-wrap comments and don't insert comment leader after hitting 'o'
|
||||
-- If don't do this on `FileType`, this keeps reappearing due to being set in
|
||||
-- filetype plugins.
|
||||
vim.cmd('setlocal formatoptions-=r formatoptions-=o')
|
||||
end,
|
||||
desc = [[Ensure proper 'formatoptions']],
|
||||
})
|
||||
-- Neovide ==============================================
|
||||
if vim.g.neovide then
|
||||
vim.g.neovide_cursor_vfx_mode = "pixiedust"
|
||||
vim.g.neovide_cursor_smooth_blink = true
|
||||
vim.g.neovide_cursor_animation_length = 0.02
|
||||
vim.g.neovide_cursor_short_animation_length = 0
|
||||
vim.g.neovide_font_hinting = 'none'
|
||||
vim.g.neovide_font_edging = 'subpixelantialias'
|
||||
vim.o.guifont = 'Iosevka Nerd Font,Symbols Nerd Font:h14:#e-subpixelantialias:#h-none'
|
||||
vim.g.neovide_floating_corner_radius = 0.35
|
||||
vim.keymap.set("n", "<leader>nf", "<cmd>NeovideFullscreen<CR>", { desc = "Toggle Neovide Fullscreen" })
|
||||
end
|
||||
|
||||
--stylua: ignore end
|
||||
119
plugin/01_lib.lua
Normal file
119
plugin/01_lib.lua
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
-- Global Functions
|
||||
Config.new_scratch_buffer = function() vim.api.nvim_win_set_buf(0, vim.api.nvim_create_buf(true, true)) end
|
||||
|
||||
-- Toggle quickfix window
|
||||
Config.toggle_quickfix = function()
|
||||
local cur_tabnr = vim.fn.tabpagenr()
|
||||
for _, wininfo in ipairs(vim.fn.getwininfo()) do
|
||||
if wininfo.quickfix == 1 and wininfo.tabnr == cur_tabnr then return vim.cmd('cclose') end
|
||||
end
|
||||
vim.cmd('copen')
|
||||
end
|
||||
|
||||
Config.log = {}
|
||||
Config.log_buf_id = Config.log_buf_id or nil
|
||||
Config.start_hrtime = Config.start_hrtime or vim.loop.hrtime()
|
||||
|
||||
Config.log_print = function()
|
||||
if Config.log_buf_id == nil or not vim.api.nvim_buf_is_valid(Config.log_buf_id) then
|
||||
Config.log_buf_id = vim.api.nvim_create_buf(true, true)
|
||||
end
|
||||
vim.api.nvim_win_set_buf(0, Config.log_buf_id)
|
||||
vim.api.nvim_buf_set_lines(Config.log_buf_id, 0, -1, false, vim.split(vim.inspect(Config.log), '\n'))
|
||||
end
|
||||
|
||||
Config.log_clear = function()
|
||||
Config.log = {}
|
||||
Config.start_hrtime = vim.loop.hrtime()
|
||||
vim.cmd('echo "Cleared log"')
|
||||
end
|
||||
|
||||
-- Execute current line with `lua`
|
||||
Config.execute_lua_line = function()
|
||||
local line = 'lua ' .. vim.api.nvim_get_current_line()
|
||||
vim.api.nvim_command(line)
|
||||
print(line)
|
||||
vim.api.nvim_input('<Down>')
|
||||
end
|
||||
|
||||
-- Try opening current file's dir with fallback to cwd
|
||||
Config.try_opendir = function()
|
||||
local buff = vim.api.nvim_buf_get_name(0)
|
||||
local ok, err = pcall(MiniFiles.open, buff)
|
||||
if ok then return end
|
||||
vim.notify(err)
|
||||
MiniFiles.open()
|
||||
end
|
||||
|
||||
-- For mini.start
|
||||
--- Edit a file in the specified window, with smart buffer reuse
|
||||
--- @param path string: File path to edit
|
||||
--- @param win_id number|nil: Window ID (defaults to current window)
|
||||
--- @return number|nil: Buffer ID on success, nil on failure
|
||||
Config.edit = function(path, win_id)
|
||||
-- Validate inputs
|
||||
if type(path) ~= 'string' or path == '' then
|
||||
return nil
|
||||
end
|
||||
|
||||
win_id = win_id or 0
|
||||
if not vim.api.nvim_win_is_valid(win_id == 0 and vim.api.nvim_get_current_win() or win_id) then
|
||||
return nil
|
||||
end
|
||||
|
||||
local current_buf = vim.api.nvim_win_get_buf(win_id)
|
||||
|
||||
-- Check if current buffer can be reused (empty, unmodified, single window)
|
||||
local is_empty_buffer = vim.fn.bufname(current_buf) == ''
|
||||
local is_regular_buffer = vim.bo[current_buf].buftype ~= 'quickfix'
|
||||
local is_unmodified = not vim.bo[current_buf].modified
|
||||
local is_single_window = #vim.fn.win_findbuf(current_buf) == 1
|
||||
local has_only_empty_line = vim.deep_equal(vim.fn.getbufline(current_buf, 1, '$'), { '' })
|
||||
|
||||
local can_reuse_buffer = is_empty_buffer and is_regular_buffer and is_unmodified
|
||||
and is_single_window and has_only_empty_line
|
||||
|
||||
-- Create or get buffer for the file
|
||||
local normalized_path = vim.fn.fnamemodify(path, ':.')
|
||||
local target_buf = vim.fn.bufadd(normalized_path)
|
||||
|
||||
-- Set buffer in window (use pcall to handle swap file messages gracefully)
|
||||
local success = pcall(vim.api.nvim_win_set_buf, win_id, target_buf)
|
||||
if not success then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Ensure buffer is listed
|
||||
vim.bo[target_buf].buflisted = true
|
||||
|
||||
-- Clean up old buffer if it was reused
|
||||
if can_reuse_buffer then
|
||||
pcall(vim.api.nvim_buf_delete, current_buf, { unload = false })
|
||||
end
|
||||
|
||||
return target_buf
|
||||
end
|
||||
|
||||
-- Load library
|
||||
local packdir = nixCats.vimPackDir or MiniDeps.config.path.package
|
||||
|
||||
-- See https://github.com/echasnovski/mini.deps/blob/2953b2089591a49a70e0a88194dbb47fb0e4635c/lua/mini/deps.lua#L518C5-L518C39
|
||||
Config.source_path = function(path)
|
||||
pcall(function() vim.cmd('source ' .. vim.fn.fnameescape(path)) end)
|
||||
end
|
||||
|
||||
Config.add = (function(pkg)
|
||||
vim.cmd.packadd(pkg)
|
||||
local should_load_after_dir = vim.v.vim_did_enter == 1 and vim.o.loadplugins
|
||||
if not should_load_after_dir then return end
|
||||
local after_paths = vim.fn.glob(
|
||||
packdir .. '/pack/myNeovimPackages/opt/' .. pkg .. '/after/plugin/**/*.{vim,lua}',
|
||||
false,
|
||||
true
|
||||
)
|
||||
vim.iter(after_paths):map(function(p)
|
||||
Config.source_path(p)
|
||||
end)
|
||||
end)
|
||||
|
||||
Config.now_if_args = vim.fn.argc(-1) > 0 and MiniDeps.now or MiniDeps.later
|
||||
130
plugin/02_startup.lua
Normal file
130
plugin/02_startup.lua
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
local M = {}
|
||||
|
||||
-- Helper function to normalize input to a list
|
||||
local function normalize_filetypes_input(input)
|
||||
if type(input) == "string" then
|
||||
return { input }
|
||||
elseif type(input) == "table" then
|
||||
return input
|
||||
else
|
||||
vim.notify("get_recent_files_by_ft_or_ext: Invalid input type for filetypes", vim.log.levels.ERROR)
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Helper function to check if a file matches any target filetype
|
||||
local function matches_target_filetype(file_path, file_ext, detected_ft, target_ft_map)
|
||||
for target_ft in pairs(target_ft_map) do
|
||||
if file_ext:lower() == target_ft:lower() or
|
||||
(detected_ft and detected_ft == target_ft) then
|
||||
return target_ft
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Helper function to safely detect filetype
|
||||
local function detect_filetype(file_path)
|
||||
local success, ft_match_fn = pcall(function() return vim.filetype.match end)
|
||||
if not (success and type(ft_match_fn) == "function") then
|
||||
return nil
|
||||
end
|
||||
|
||||
local ok, result = pcall(ft_match_fn, { filename = file_path })
|
||||
return ok and type(result) == "string" and result ~= "" and result or nil
|
||||
end
|
||||
|
||||
-- Helper function to capitalize first letter
|
||||
local function capitalize_first(str)
|
||||
return str:sub(1, 1):upper() .. str:sub(2)
|
||||
end
|
||||
|
||||
function M.get_recent_files_by_ft_or_ext(target_filetypes_input)
|
||||
local target_filetypes_list = normalize_filetypes_input(target_filetypes_input)
|
||||
if not target_filetypes_list or #target_filetypes_list == 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
-- Create lookup map for O(1) filetype checking
|
||||
local target_ft_map = {}
|
||||
for _, ft in ipairs(target_filetypes_list) do
|
||||
target_ft_map[ft] = true
|
||||
end
|
||||
|
||||
local oldfiles = vim.v.oldfiles
|
||||
if not oldfiles or #oldfiles == 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local cwd = vim.fn.getcwd()
|
||||
local fnamemodify = vim.fn.fnamemodify
|
||||
local filereadable = vim.fn.filereadable
|
||||
local getftime = vim.fn.getftime
|
||||
|
||||
-- Track most recent file for each target filetype
|
||||
local most_recent_files = {}
|
||||
for _, ft in ipairs(target_filetypes_list) do
|
||||
most_recent_files[ft] = { file = nil, time = 0 }
|
||||
end
|
||||
|
||||
local processed_paths = {}
|
||||
|
||||
for _, file_path in ipairs(oldfiles) do
|
||||
local full_path = fnamemodify(file_path, ':p')
|
||||
|
||||
-- Skip if already processed or invalid
|
||||
if processed_paths[full_path] or
|
||||
filereadable(full_path) ~= 1 or
|
||||
not full_path:find(cwd, 1, true) then
|
||||
goto continue
|
||||
end
|
||||
|
||||
processed_paths[full_path] = true
|
||||
|
||||
local file_ext = fnamemodify(full_path, ':e')
|
||||
local detected_ft = detect_filetype(full_path)
|
||||
local matched_ft = matches_target_filetype(full_path, file_ext, detected_ft, target_ft_map)
|
||||
|
||||
if matched_ft then
|
||||
local mod_time = getftime(full_path)
|
||||
if mod_time > most_recent_files[matched_ft].time then
|
||||
most_recent_files[matched_ft] = { file = full_path, time = mod_time }
|
||||
end
|
||||
end
|
||||
|
||||
::continue::
|
||||
end
|
||||
|
||||
-- Build result items
|
||||
local result_items = {}
|
||||
for ft, data in pairs(most_recent_files) do
|
||||
if data.file then
|
||||
local filename = fnamemodify(data.file, ':t')
|
||||
local relative_path = fnamemodify(data.file, ':~:.')
|
||||
|
||||
table.insert(result_items, {
|
||||
action = function() Config.edit(data.file) end,
|
||||
name = string.format('%s (%s)', filename, relative_path),
|
||||
section = 'Recent ' .. capitalize_first(ft),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
return result_items
|
||||
end
|
||||
|
||||
M.footer_text = (function()
|
||||
return [[
|
||||
$$$$$$$\ $$\ $$\ $$\ $$\ $$\ $$$$$$$\ $$\ $$\ $$\ $$\
|
||||
$$ __$$\ \__| $$ |$ | $$ |$$ |$$ __$$\ $$ | $$ | $$ |\__|
|
||||
$$ | $$ | $$$$$$\ $$$$$$$\ $$\ $$$$$$\ $$ |\_/$$$$$$$\ $$ /$$ / $$ | $$ | $$$$$$\ $$$$$$\ $$$$$$\ $$ | $$ |$$\ $$$$$$\$$$$\
|
||||
$$ | $$ | \____$$\ $$ __$$\ $$ |$$ __$$\ $$ | $$ _____| $$ /$$ / $$ | $$ | \____$$\\_$$ _| \____$$\\$$\ $$ |$$ |$$ _$$ _$$\
|
||||
$$ | $$ | $$$$$$$ |$$ | $$ |$$ |$$$$$$$$ |$$ | \$$$$$$\ $$ /$$ / $$ | $$ | $$$$$$$ | $$ | $$$$$$$ |\$$\$$ / $$ |$$ / $$ / $$ |
|
||||
$$ | $$ |$$ __$$ |$$ | $$ |$$ |$$ ____|$$ | \____$$\ $$ /$$ / $$ | $$ |$$ __$$ | $$ |$$\ $$ __$$ | \$$$ / $$ |$$ | $$ | $$ |
|
||||
$$$$$$$ |\$$$$$$$ |$$ | $$ |$$ |\$$$$$$$\ $$ | $$$$$$$ |$$ /$$ / $$$$$$$ |\$$$$$$$ | \$$$$ |\$$$$$$$ | \$ / $$ |$$ | $$ | $$ |
|
||||
\_______/ \_______|\__| \__|\__| \_______|\__| \_______/ \__/ \__/ \_______/ \_______| \____/ \_______| \_/ \__|\__| \__| \__|
|
||||
]]
|
||||
end
|
||||
)
|
||||
|
||||
Config.startup = M
|
||||
78
plugin/03_terminal.lua
Normal file
78
plugin/03_terminal.lua
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
local M = {}
|
||||
|
||||
-- Configuration
|
||||
Config.opt_bracket = true
|
||||
M.opt_term = nil
|
||||
|
||||
-- Default terminal commands
|
||||
-- Users can override this via Config.terminal_commands in their setup
|
||||
local defaults = {
|
||||
clickhouse_client = "clickhouse client -m",
|
||||
clickhouse_local = "clickhouse local -m",
|
||||
duckdb = "duckdb",
|
||||
julia = "julia",
|
||||
python = "ipython",
|
||||
shell = "echo 'Hello " .. vim.env.USER .. "!'",
|
||||
}
|
||||
|
||||
-- Registry of terminal commands
|
||||
M.commands = vim.tbl_deep_extend("force", defaults, Config.terminal_commands or {})
|
||||
|
||||
-- Bracket paste control
|
||||
function M.toggle_bracket()
|
||||
Config.opt_bracket = not Config.opt_bracket
|
||||
vim.g.slime_bracketed_paste = Config.opt_bracket
|
||||
return Config.opt_bracket
|
||||
end
|
||||
|
||||
-- Terminal management
|
||||
function M.split_and_open_terminal()
|
||||
vim.cmd("below terminal")
|
||||
vim.cmd("resize " .. math.floor(vim.fn.winheight(0) * 0.9))
|
||||
local term_buf = vim.api.nvim_win_get_buf(vim.api.nvim_get_current_win())
|
||||
M.opt_term = term_buf
|
||||
|
||||
-- Set buffer-local variables for vim-slime
|
||||
local job_id = vim.b[term_buf].terminal_job_id
|
||||
vim.b[term_buf].slime_config = { jobid = job_id }
|
||||
|
||||
return M.opt_term
|
||||
end
|
||||
|
||||
-- Public functions
|
||||
function M.open_in_terminal(cmd)
|
||||
local command = cmd or ""
|
||||
local current_window = vim.api.nvim_get_current_win()
|
||||
local code_buf = vim.api.nvim_get_current_buf()
|
||||
|
||||
-- Open terminal and get buffer
|
||||
local term_buf = M.split_and_open_terminal()
|
||||
|
||||
-- Send command if provided
|
||||
if command ~= "" then
|
||||
-- We can use standard slime sending if needed, or direct chan_send for initialization
|
||||
local job_id = vim.b[term_buf].terminal_job_id
|
||||
if job_id then
|
||||
vim.api.nvim_chan_send(job_id, command .. "\r")
|
||||
end
|
||||
end
|
||||
|
||||
-- Configure slime for the ORIGINAL code buffer to point to this new terminal
|
||||
-- This makes "Send to Terminal" work immediately
|
||||
local slime_config = { jobid = vim.b[term_buf].terminal_job_id }
|
||||
|
||||
-- Fix: Set the variable on the captured code buffer, not the current (terminal) buffer
|
||||
vim.api.nvim_buf_set_var(code_buf, "slime_config", slime_config)
|
||||
|
||||
-- Switch back to code buffer
|
||||
vim.api.nvim_set_current_win(current_window)
|
||||
end
|
||||
|
||||
-- Predefined terminal commands
|
||||
for name, command in pairs(M.commands) do
|
||||
M["open_" .. name] = function()
|
||||
M.open_in_terminal(command)
|
||||
end
|
||||
end
|
||||
|
||||
Config.terminal = M
|
||||
147
plugin/04_treesitter.lua
Normal file
147
plugin/04_treesitter.lua
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
local M = {}
|
||||
|
||||
-- Default parsers list moved from startup config
|
||||
M.default_parsers = {
|
||||
"bash", "bibtex", "c", "caddy", "cmake", "comment", "commonlisp", "cpp", "css", "csv",
|
||||
"cuda", "desktop", "diff", "dockerfile", "doxygen", "editorconfig", "fortran", "git_config", "git_rebase",
|
||||
"gitattributes", "gitcommit", "gitignore", "gnuplot", "go", "gpg", "html", "javascript", "jq", "json", "json5",
|
||||
"julia", "just", "latex", "ledger", "lua", "luadoc", "luap", "luau", "make", "markdown", "markdown_inline",
|
||||
"matlab", "meson", "muttrc", "nix", "nu", "passwd", "powershell", "prql", "python", "r", "query", "readline", "regex",
|
||||
"requirements", "rnoweb", "rust", "sql", "ssh_config", "swift", "tmux", "toml", "tsv", "tsx", "typescript", "typst",
|
||||
"vala", "vim", "vimdoc", "yaml", "zig",
|
||||
}
|
||||
|
||||
-- Cache treesitter utils to avoid repeated requires
|
||||
local smart_send = require('nix_smart_send')
|
||||
|
||||
-- Helper function to check if value exists in list (optimized with early return)
|
||||
local function is_in_list(list, value)
|
||||
if not list or not value then
|
||||
return false
|
||||
end
|
||||
|
||||
for _, v in ipairs(list) do
|
||||
if v == value then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function M.add_global_node(nodes)
|
||||
if not nodes then
|
||||
return nil
|
||||
end
|
||||
|
||||
local node_type = M.get_type()
|
||||
if not node_type then
|
||||
return nodes
|
||||
end
|
||||
|
||||
-- Create a copy to avoid modifying the original
|
||||
local global_nodes = vim.deepcopy(nodes)
|
||||
|
||||
-- Check if node type already exists to avoid duplicates
|
||||
if not is_in_list(global_nodes, node_type) then
|
||||
table.insert(global_nodes, node_type)
|
||||
end
|
||||
|
||||
return global_nodes
|
||||
end
|
||||
|
||||
function M.remove_global_node(nodes)
|
||||
if not nodes then
|
||||
return nil
|
||||
end
|
||||
|
||||
local node_type = M.get_type()
|
||||
if not node_type then
|
||||
return nodes
|
||||
end
|
||||
|
||||
local global_nodes = vim.deepcopy(nodes)
|
||||
|
||||
-- Remove all occurrences (iterate backwards to avoid index issues)
|
||||
for i = #global_nodes, 1, -1 do
|
||||
if global_nodes[i] == node_type then
|
||||
table.remove(global_nodes, i)
|
||||
end
|
||||
end
|
||||
|
||||
return global_nodes
|
||||
end
|
||||
|
||||
function M.set_global_nodes()
|
||||
local input = vim.fn.input("Enter root nodes: ")
|
||||
if input == "" then
|
||||
return {}
|
||||
end
|
||||
|
||||
local nodes_in = {}
|
||||
-- Trim whitespace from each node name
|
||||
for node in string.gmatch(input, '([^,]+)') do
|
||||
local trimmed = vim.trim(node)
|
||||
if trimmed ~= "" then
|
||||
table.insert(nodes_in, trimmed)
|
||||
end
|
||||
end
|
||||
|
||||
return nodes_in
|
||||
end
|
||||
|
||||
function M.get_type()
|
||||
local cur_node = smart_send.get_current_node()
|
||||
if not cur_node then
|
||||
print("Not a node")
|
||||
return nil
|
||||
end
|
||||
|
||||
local node_type = cur_node:type()
|
||||
print("Node type: " .. node_type)
|
||||
return node_type
|
||||
end
|
||||
|
||||
|
||||
function M.setup_keybindings(global_nodes)
|
||||
local current_global_nodes = global_nodes
|
||||
|
||||
vim.keymap.set({ 'n' }, '<localleader>r', function()
|
||||
current_global_nodes = M.set_global_nodes()
|
||||
end,
|
||||
{ noremap = true, silent = true, desc = "set global_nodes", buffer = true })
|
||||
|
||||
vim.keymap.set({ 'n', 'v' }, '<localleader>v', function()
|
||||
smart_send.move_to_next_non_empty_line(); smart_send.select_until_global(current_global_nodes)
|
||||
end,
|
||||
{ noremap = true, silent = true, desc = "Visual select next node after WS", buffer = true })
|
||||
|
||||
vim.keymap.set('n', '<localleader>a', function() smart_send.send_repl(current_global_nodes) end,
|
||||
{ noremap = true, silent = true, desc = "Send node to REPL", buffer = true })
|
||||
|
||||
vim.keymap.set({ 'n', 'i' }, '<S-CR>', function() smart_send.send_repl(current_global_nodes) end,
|
||||
{ noremap = true, silent = true, desc = "Send node to REPL", buffer = true })
|
||||
|
||||
vim.keymap.set('n', '<CR>', function() smart_send.send_repl(current_global_nodes) end,
|
||||
{ noremap = true, silent = true, desc = "Send node to REPL", buffer = true })
|
||||
|
||||
vim.keymap.set('n', '<localleader>n',
|
||||
function() current_global_nodes = M.add_global_node(current_global_nodes) end,
|
||||
{ noremap = true, silent = true, desc = "Add node under cursor to globals", buffer = true })
|
||||
|
||||
vim.keymap.set('n', '<localleader>x',
|
||||
function() current_global_nodes = M.remove_global_node(current_global_nodes) end,
|
||||
{ noremap = true, silent = true, desc = "Remove node under cursor from globals", buffer = true })
|
||||
|
||||
vim.keymap.set('n', '<localleader>o', function()
|
||||
pout = table.concat(global_nodes, ', ') .. ""
|
||||
print(pout)
|
||||
end, { noremap = true, silent = true, desc = "Print globals", buffer = true })
|
||||
|
||||
vim.keymap.set('n', '<localleader>p', function() M.get_type() end,
|
||||
{ noremap = true, silent = true, desc = "Print node type", buffer = true })
|
||||
end
|
||||
|
||||
Config.treesitter_helpers = M
|
||||
|
||||
return M
|
||||
318
plugin/10_keymap.lua
Normal file
318
plugin/10_keymap.lua
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
-- Basic mappings =============================================================
|
||||
-- NOTE: Most basic mappings come from 'mini.basics'
|
||||
-- Shorter version of the most frequent way of going outside of terminal window
|
||||
vim.keymap.set('t', '<C-h>', [[<C-\><C-N><C-w>h]])
|
||||
-- Select all
|
||||
-- vim.keymap.set({ "n", "v", "x" }, "<C-a>", "gg3vG$", { noremap = true, silent = true, desc = "Select all" })
|
||||
-- Escape deletes highlights
|
||||
vim.keymap.set("n", "<Esc>", "<cmd>nohlsearch<CR>")
|
||||
-- Paste before/after linewise
|
||||
local cmd = vim.fn.has('nvim-0.12') == 1 and 'iput' or 'put'
|
||||
vim.keymap.set({ 'n', 'x' }, '[p', '<Cmd>exe "' .. cmd .. '! " . v:register<CR>', { desc = 'Paste Above' })
|
||||
vim.keymap.set({ 'n', 'x' }, ']p', '<Cmd>exe "' .. cmd .. ' " . v:register<CR>', { desc = 'Paste Below' })
|
||||
|
||||
vim.keymap.set({ "n", "v", "x" }, "<leader>p", '"+p', { noremap = true, silent = true, desc = "Paste from clipboard" })
|
||||
vim.keymap.set({ "n", "v", "x" }, "<leader>y", '"+y', { noremap = true, silent = true, desc = "Copy toclipboard" })
|
||||
-- Leader mappings ============================================================
|
||||
-- stylua: ignore start
|
||||
|
||||
-- Create global tables with information about clue groups in certain modes
|
||||
-- Structure of tables is taken to be compatible with 'mini.clue'.
|
||||
_G.Config.leader_group_clues = {
|
||||
{ mode = 'n', keys = '<Leader>a', desc = '+AI' },
|
||||
{ mode = 'n', keys = '<Leader>b', desc = '+Buffer' },
|
||||
{ mode = 'n', keys = '<Leader>e', desc = '+Explore' },
|
||||
{ mode = 'n', keys = '<Leader>f', desc = '+Find' },
|
||||
{ mode = 'n', keys = '<Leader>fl', desc = '+LSP' },
|
||||
{ mode = 'n', keys = '<Leader>fa', desc = '+Git' },
|
||||
{ mode = 'n', keys = '<Leader>g', desc = '+Git' },
|
||||
{ mode = 'n', keys = '<Leader>l', desc = '+LSP' },
|
||||
{ mode = 'n', keys = '<Leader>L', desc = '+Lua/Log' },
|
||||
{ mode = 'n', keys = '<Leader>o', desc = '+Other' },
|
||||
{ mode = 'n', keys = '<Leader>r', desc = '+R' },
|
||||
{ mode = 'n', keys = '<Leader>t', desc = '+Terminal' },
|
||||
{ mode = 'n', keys = '<Leader>u', desc = '+UI' },
|
||||
{ mode = 'n', keys = '<Leader>v', desc = '+Visits' },
|
||||
{ mode = 'n', keys = '<Leader>w', desc = '+Windows' },
|
||||
{ mode = 'x', keys = '<Leader>l', desc = '+LSP' },
|
||||
{ mode = 'x', keys = '<Leader>r', desc = '+R' },
|
||||
{ mode = 'n', keys = '<Leader>z', desc = '+ZK' },
|
||||
{ mode = 'n', keys = '<Leader>zr', desc = '+Reviews' },
|
||||
{ mode = 'x', keys = '<leader>a', desc = '+AI' },
|
||||
}
|
||||
|
||||
-- Create `<Leader>` mappings
|
||||
local nmap_leader = function(suffix, rhs, desc, opts)
|
||||
opts = opts or {}
|
||||
opts.desc = desc
|
||||
vim.keymap.set('n', '<Leader>' .. suffix, rhs, opts)
|
||||
end
|
||||
local xmap_leader = function(suffix, rhs, desc, opts)
|
||||
opts = opts or {}
|
||||
opts.desc = desc
|
||||
vim.keymap.set('x', '<Leader>' .. suffix, rhs, opts)
|
||||
end
|
||||
-- Other mappings
|
||||
local nmap_lsp = function(keys, func, desc)
|
||||
if desc then
|
||||
desc = desc .. "(LSP)"
|
||||
end
|
||||
|
||||
vim.keymap.set("n", keys, func, { desc = desc })
|
||||
end
|
||||
|
||||
-- Switch buffers
|
||||
nmap_leader('<Tab>', '<Cmd>bnext<CR>', 'Next buffer')
|
||||
nmap_leader('<S-Tab>', '<Cmd>bprev<CR>', 'Prev buffer')
|
||||
|
||||
-- a is for 'AI'
|
||||
nmap_leader("ac", "<cmd>CodeCompanionChat Toggle<CR>", "Chat Toggle")
|
||||
nmap_leader("ae", "<cmd>CodeCompanion /explain<CR>", "Explain Code")
|
||||
nmap_leader("af", "<cmd>CodeCompanion /fix<CR>", "Fix Code")
|
||||
nmap_leader("ag", "<cmd>CodeCompanion /commit<CR>", "Generate commit message")
|
||||
nmap_leader("ai", "<cmd>CodeCompanionActions<CR>", "Chat Action")
|
||||
nmap_leader("al", "<cmd>CodeCompanion /lsp<CR>", "Explain LSP Diagnostics")
|
||||
nmap_leader("an", "<cmd>CodeCompanionChat Add<CR>", "Chat New")
|
||||
nmap_leader("as", "<cmd>CodeCompanion /suggest<CR>", "Suggest Improvements")
|
||||
nmap_leader("ax", "<cmd>CodeCompanion /fixer<CR>", "Code Fixer")
|
||||
nmap_leader("ax", "<cmd>CodeCompanion /fixer<CR>", "Code Fixer")
|
||||
xmap_leader("ae", "<cmd>CodeCompanion /explain<CR>", "Explain Code")
|
||||
xmap_leader("af", "<cmd>CodeCompanion /fix<CR>", "Fix Code")
|
||||
xmap_leader("ap", "<cmd>CodeCompanion /expert<CR>", "Code Fixer")
|
||||
xmap_leader("ap", "<cmd>CodeCompanion /expert<CR>", "Code Fixer")
|
||||
xmap_leader("as", "<cmd>CodeCompanion /suggest<CR>", "Suggest Improvements")
|
||||
|
||||
-- b is for 'buffer'
|
||||
nmap_leader('bb', '<Cmd>b#<CR>', 'Alternate')
|
||||
nmap_leader('bd', '<Cmd>lua MiniBufremove.delete()<CR>', 'Delete')
|
||||
nmap_leader('bD', '<Cmd>lua MiniBufremove.delete(0, true)<CR>', 'Delete!')
|
||||
nmap_leader('bs', '<Cmd>lua Config.new_scratch_buffer()<CR>', 'Scratch')
|
||||
nmap_leader('bw', '<Cmd>lua MiniBufremove.wipeout()<CR>', 'Wipeout')
|
||||
nmap_leader('bW', '<Cmd>lua MiniBufremove.wipeout(0, true)<CR>', 'Wipeout!')
|
||||
nmap_leader('bq', '<Cmd>qall<CR>', 'Quit all')
|
||||
|
||||
-- e is for 'explore' and 'edit'
|
||||
nmap_leader('ed', '<Cmd>lua MiniFiles.open()<CR>', 'Directory')
|
||||
nmap_leader('ef', '<Cmd>lua Config.try_opendir()<CR>', 'File directory')
|
||||
nmap_leader('es', '<Cmd>lua MiniSessions.select()<CR>', 'Sessions')
|
||||
nmap_leader('eq', '<Cmd>lua Config.toggle_quickfix()<CR>', 'Quickfix')
|
||||
nmap_leader('ez', '<Cmd>lua MiniFiles.open(os.getenv("ZK_NOTEBOOK_DIR"))<CR>', 'Notes directory')
|
||||
|
||||
-- f is for 'fuzzy find'
|
||||
nmap_leader('f/', '<Cmd>Pick history scope="/"<CR>', '"/" history')
|
||||
nmap_leader('f:', '<Cmd>Pick history scope=":"<CR>', '":" history')
|
||||
nmap_leader('f,', '<Cmd>Pick visit_labels<CR>', 'Visit labels')
|
||||
nmap_leader('faa', '<Cmd>Pick git_hunks scope="staged"<CR>', 'Added hunks (all)')
|
||||
nmap_leader('faA', '<Cmd>Pick git_hunks path="%" scope="staged"<CR>', 'Added hunks (current)')
|
||||
nmap_leader('fb', '<Cmd>Pick buffers<CR>', 'Buffers')
|
||||
nmap_leader(',', '<Cmd>Pick buffers<CR>', 'Buffers')
|
||||
nmap_leader('fac', '<Cmd>Pick git_commits<CR>', 'Commits (all)')
|
||||
nmap_leader('faC', '<Cmd>Pick git_commits path="%"<CR>', 'Commits (current)')
|
||||
nmap_leader('fd', '<Cmd>Pick diagnostic scope="all"<CR>', 'Diagnostic workspace')
|
||||
nmap_leader('fD', '<Cmd>Pick diagnostic scope="current"<CR>', 'Diagnostic buffer')
|
||||
nmap_leader('ff', '<Cmd>Pick files<CR>', 'Files')
|
||||
nmap_leader('fg', '<Cmd>Pick grep_live<CR>', 'Grep live')
|
||||
nmap_leader('fG', '<Cmd>Pick grep pattern="<cword>"<CR>', 'Grep current word')
|
||||
nmap_leader('fh', '<Cmd>Pick help<CR>', 'Help tags')
|
||||
nmap_leader('fH', '<Cmd>Pick hl_groups<CR>', 'Highlight groups')
|
||||
nmap_leader('fj', '<Cmd>Pick buf_lines scope="all"<CR>', 'Lines (all)')
|
||||
nmap_leader('fJ', '<Cmd>Pick buf_lines scope="current"<CR>', 'Lines (current)')
|
||||
nmap_leader('fam', '<Cmd>Pick git_hunks<CR>', 'Modified hunks (all)')
|
||||
nmap_leader('faM', '<Cmd>Pick git_hunks path="%"<CR>', 'Modified hunks (current)')
|
||||
nmap_leader('fm', '<Cmd>Pick marks<CR>', 'Marks')
|
||||
nmap_leader('fn', '<cmd>ZkNotes<CR>', "Notes")
|
||||
nmap_leader('fk', '<Cmd>Pick keymaps<CR>', 'Keymaps')
|
||||
nmap_leader('fR', '<Cmd>Pick resume<CR>', 'Resume')
|
||||
nmap_leader('fp', '<Cmd>Pick projects<CR>', 'Projects')
|
||||
nmap_leader('fq', '<Cmd>Pick list scope="quickfix"<CR>', 'Quickfix')
|
||||
nmap_leader('fr', '<Cmd>Pick lsp scope="references"<CR>', 'References (LSP)')
|
||||
nmap_leader('flr', '<Cmd>Pick lsp scope="references"<CR>', 'References (LSP)')
|
||||
nmap_leader('fS', '<Cmd>Pick lsp scope="workspace_symbol"<CR>', 'Symbols workspace (LSP)')
|
||||
nmap_leader('flS', '<Cmd>Pick lsp scope="workspace_symbol"<CR>', 'Symbols workspace (LSP)')
|
||||
nmap_leader('fs', '<Cmd>Pick lsp scope="document_symbol"<CR>', 'Symbols buffer (LSP)')
|
||||
nmap_leader('fls', '<Cmd>Pick lsp scope="document_symbol"<CR>', 'Symbols buffer (LSP)')
|
||||
nmap_leader('fld', '<Cmd>Pick lsp scope="definition"<CR>', 'Definition (LSP)')
|
||||
nmap_leader('flD', '<Cmd>Pick lsp scope="declaration"<CR>', 'Declaration (LSP)')
|
||||
nmap_leader('flt', '<Cmd>Pick lsp scope="type_definition"<CR>', 'Type Definition (LSP)')
|
||||
nmap_leader('fv', '<Cmd>Pick visit_paths cwd=""<CR>', 'Visit paths (all)')
|
||||
nmap_leader('fV', '<Cmd>Pick visit_paths<CR>', 'Visit paths (cwd)')
|
||||
|
||||
-- g is for git
|
||||
local git_log_cmd = [[Git log --pretty=format:\%h\ \%as\ │\ \%s --topo-order]]
|
||||
|
||||
nmap_leader('gc', '<Cmd>Git commit<CR>', 'Commit')
|
||||
nmap_leader('gC', '<Cmd>Git commit --amend<CR>', 'Commit amend')
|
||||
nmap_leader('gd', '<Cmd>Git diff<CR>', 'Diff')
|
||||
nmap_leader('gD', '<Cmd>Git diff -- %<CR>', 'Diff buffer')
|
||||
nmap_leader('gg', '<Cmd>lua require("neogit").open()<CR>', 'Git tab')
|
||||
nmap_leader('gl', '<Cmd>' .. git_log_cmd .. '<CR>', 'Log')
|
||||
nmap_leader('gL', '<Cmd>' .. git_log_cmd .. ' --follow -- %<CR>', 'Log buffer')
|
||||
nmap_leader('go', '<Cmd>lua MiniDiff.toggle_overlay()<CR>', 'Toggle overlay')
|
||||
nmap_leader('gp', '<Cmd>Git pull<CR>', 'Pull')
|
||||
nmap_leader('gP', '<Cmd>Git push<CR>', 'Push')
|
||||
nmap_leader('gs', '<Cmd>lua MiniGit.show_at_cursor()<CR>', 'Show at cursor')
|
||||
|
||||
xmap_leader('gs', '<Cmd>lua MiniGit.show_at_cursor()<CR>', 'Show at selection')
|
||||
|
||||
-- j/k navigate quickfix
|
||||
nmap_leader("j", '<cmd>cnext<CR>zz', "Quickfix next")
|
||||
nmap_leader("k", '<cmd>cprev<CR>zz', "Quickfix prev")
|
||||
|
||||
-- l is for 'LSP' (Language Server Protocol)
|
||||
vim.keymap.set({ 'n' }, 'grd', '<Cmd>lua vim.lsp.buf.definition()<CR>', { desc = 'Definition' })
|
||||
vim.keymap.set({ 'n' }, 'grk', '<Cmd>lua vim.lsp.buf.hover()<CR>', { desc = 'Documentation' })
|
||||
vim.keymap.set({ 'n' }, 'gre', '<Cmd>lua vim.diagnostic.open_float()<CR>', { desc = 'Diagnostics' })
|
||||
|
||||
nmap_lsp("K", '<Cmd>lua vim.lsp.buf.hover()<CR>', "Documentation")
|
||||
local formatting_cmd = '<Cmd>lua require("conform").format({ lsp_fallback = true })<CR>'
|
||||
nmap_leader('la', '<Cmd>lua vim.lsp.buf.code_action()<CR>', 'Actions')
|
||||
nmap_leader('le', '<Cmd>lua vim.diagnostic.open_float()<CR>', 'Diagnostics popup')
|
||||
nmap_leader('lf', formatting_cmd, 'Format')
|
||||
nmap_leader('lk', '<Cmd>lua vim.lsp.buf.hover()<CR>', 'Documentation')
|
||||
nmap_leader('li', '<Cmd>lua vim.lsp.buf.implementation()<CR>', 'Information')
|
||||
-- use ]d and [d
|
||||
--nmap_leader('lj', '<Cmd>lua vim.diagnostic.goto_next()<CR>', 'Next diagnostic')
|
||||
--nmap_leader('lk', '<Cmd>lua vim.diagnostic.goto_prev()<CR>', 'Prev diagnostic')
|
||||
nmap_leader('lR', '<Cmd>lua vim.lsp.buf.references()<CR>', 'References')
|
||||
nmap_leader('lr', '<Cmd>lua vim.lsp.buf.rename()<CR>', 'Rename')
|
||||
nmap_leader('ls', '<Cmd>lua vim.lsp.buf.definition()<CR>', 'Source definition')
|
||||
|
||||
xmap_leader('lf', formatting_cmd, 'Format selection')
|
||||
|
||||
-- L is for 'Lua'
|
||||
nmap_leader('Lc', '<Cmd>lua Config.log_clear()<CR>', 'Clear log')
|
||||
nmap_leader('LL', '<Cmd>luafile %<CR><Cmd>echo "Sourced lua"<CR>', 'Source buffer')
|
||||
nmap_leader('Ls', '<Cmd>lua Config.log_print()<CR>', 'Show log')
|
||||
nmap_leader('Lx', '<Cmd>lua Config.execute_lua_line()<CR>', 'Execute `lua` line')
|
||||
|
||||
-- m is free
|
||||
|
||||
-- o is for 'other'
|
||||
local trailspace_toggle_command = '<Cmd>lua vim.b.minitrailspace_disable = not vim.b.minitrailspace_disable<CR>'
|
||||
nmap_leader('od', '<Cmd>Neogen<CR>', 'Document')
|
||||
nmap_leader('oh', '<Cmd>normal gxiagxila<CR>', 'Move arg left')
|
||||
nmap_leader('ol', '<Cmd>normal gxiagxina<CR>', 'Move arg right')
|
||||
nmap_leader('or', '<Cmd>lua MiniMisc.resize_window()<CR>', 'Resize to default width')
|
||||
nmap_leader('oS', '<Cmd>lua Config.insert_section()<CR>', 'Section insert')
|
||||
nmap_leader('ot', '<Cmd>lua MiniTrailspace.trim()<CR>', 'Trim trailspace')
|
||||
nmap_leader('oT', trailspace_toggle_command, 'Trailspace hl toggle')
|
||||
nmap_leader('oz', '<Cmd>lua MiniMisc.zoom()<CR>', 'Zoom toggle')
|
||||
nmap_leader('ow',
|
||||
"<Cmd>lua MiniSessions.write(vim.fn.input('Session name: ', string.match(vim.fn.getcwd(), \"[^/]+$\") .. '-session.vim'))<CR>",
|
||||
'Write session')
|
||||
|
||||
-- r is for 'R'
|
||||
nmap_leader('rc', '<Cmd>RSend devtools::check()<CR>', 'Check')
|
||||
nmap_leader('rC', '<Cmd>RSend devtools::test_coverage()<CR>', 'Coverage')
|
||||
nmap_leader('rd', '<Cmd>RSend devtools::document()<CR>', 'Document')
|
||||
nmap_leader('ri', '<Cmd>RSend devtools::install(keep_source=TRUE)<CR>', 'Install')
|
||||
nmap_leader('rk', '<Cmd>RSend quarto::quarto_preview("%")<CR>', 'Knit file')
|
||||
nmap_leader('rl', '<Cmd>RSend devtools::load_all()<CR>', 'Load all')
|
||||
nmap_leader('rL', '<Cmd>RSend devtools::load_all(recompile=TRUE)<CR>', 'Load all recompile')
|
||||
nmap_leader('rm', '<Cmd>RSend Rcpp::compileAttributes()<CR>', 'Run examples')
|
||||
nmap_leader('rT', '<Cmd>RSend testthat::test_file("%")<CR>', 'Test file')
|
||||
nmap_leader('rt', '<Cmd>RSend devtools::test()<CR>', 'Test')
|
||||
|
||||
-- - Copy to clipboard and make reprex (which itself is loaded to clipboard)
|
||||
xmap_leader('rx', '"+y :RSend reprex::reprex()<CR>', 'Reprex selection')
|
||||
|
||||
-- s is for 'send' (Send text to neoterm buffer)
|
||||
nmap_leader('s', '<Cmd>SlimeSendCurrentLine<CR>j', 'Send to terminal')
|
||||
|
||||
-- - In simple visual mode send text and move to the last character in
|
||||
-- selection and move to the right. Otherwise (like in line or block visual
|
||||
-- mode) send text and move one line down from bottom of selection.
|
||||
xmap_leader('s', '<Plug>SlimeRegionSend<CR>', 'Send to terminal')
|
||||
|
||||
-- t is for 'terminal'
|
||||
vim.keymap.set("t", "<Esc>", [[<C-\><C-n>]], { desc = "Exit terminal mode" })
|
||||
vim.keymap.set("n", "<leader>tc", '<Cmd>lua Config.terminal.open_clickhouse_client()<CR>',
|
||||
{ desc = "Open Clickhouse client" })
|
||||
vim.keymap.set("n", "<leader>tl", '<Cmd>lua Config.terminal.open_clickhouse_local()<CR>',
|
||||
{ desc = "Open Clickhouse local" })
|
||||
vim.keymap.set("n", "<leader>tp", '<Cmd>lua Config.terminal.open_python()<CR>', { desc = "Open Python" })
|
||||
vim.keymap.set("n", "<leader>tj", '<Cmd>lua Config.terminal.open_julia()<CR>', { desc = "Open Julia" })
|
||||
vim.keymap.set("n", "<leader>td", '<Cmd>lua Config.terminal.open_duckdb();Config.terminal.toggle_bracket()<CR>',
|
||||
{ desc = "Open DuckDB" })
|
||||
vim.keymap.set("n", "<leader>tx", '<Cmd>lua Config.terminal.open_in_terminal()<CR>', { desc = "Terminal Command" })
|
||||
vim.keymap.set("n", "<leader>tt", '<Cmd>lua Config.terminal.open_shell()<CR>', { desc = "Terminal" })
|
||||
nmap_leader("tb", '<Cmd>lua Config.terminal.toggle_bracket()<CR>', "Toggle bracketed paste")
|
||||
nmap_leader("up", '<Cmd>lua Config.terminal.toggle_bracket()<CR>', "Toggle bracketed paste")
|
||||
|
||||
-- u is for UI
|
||||
nmap_leader('ut', '<Cmd>TSContext toggle<CR>', 'Toggle TScontext')
|
||||
nmap_leader('ua', '<Cmd>Copilot toggle<CR>', 'Toggle AI completion')
|
||||
|
||||
-- v is for 'visits'
|
||||
nmap_leader('vv', '<Cmd>lua MiniVisits.add_label("core")<CR>', 'Add "core" label')
|
||||
nmap_leader('vV', '<Cmd>lua MiniVisits.remove_label("core")<CR>', 'Remove "core" label')
|
||||
nmap_leader('vl', '<Cmd>lua MiniVisits.add_label()<CR>', 'Add label')
|
||||
nmap_leader('vL', '<Cmd>lua MiniVisits.remove_label()<CR>', 'Remove label')
|
||||
|
||||
local map_pick_core = function(keys, cwd, desc)
|
||||
local rhs = function()
|
||||
local sort_latest = MiniVisits.gen_sort.default({ recency_weight = 1 })
|
||||
MiniExtra.pickers.visit_paths({
|
||||
cwd = cwd,
|
||||
filter = 'core',
|
||||
sort = sort_latest
|
||||
}, { source = { name = desc } })
|
||||
end
|
||||
nmap_leader(keys, rhs, desc)
|
||||
end
|
||||
map_pick_core('vc', '', 'Core visits (all)')
|
||||
map_pick_core('vC', nil, 'Core visits (cwd)')
|
||||
|
||||
-- w is for 'windows'
|
||||
nmap_leader("wh", "<C-w>h", "Go to Left Window", { remap = true })
|
||||
nmap_leader("wj", "<C-w>j", "Go to Lower Window", { remap = true })
|
||||
nmap_leader("wk", "<C-w>k", "Go to Upper Window", { remap = true })
|
||||
nmap_leader("wl", "<C-w>l", "Go to Right Window", { remap = true })
|
||||
|
||||
nmap_leader("_", "<C-W>s", "Split Window Below", { remap = true })
|
||||
nmap_leader("|", "<C-W>v", "Split Window Right", { remap = true })
|
||||
nmap_leader("wd", "<C-W>c", "Delete Window", { remap = true })
|
||||
nmap_leader("wo", "<C-W>o", "Delete Other Windows", { remap = true })
|
||||
|
||||
-- z is for 'ZettelKasten'
|
||||
nmap_leader("zo", '<Cmd>ZkNotes<CR>', "Notes")
|
||||
nmap_leader("zt", '<Cmd>ZkTags<cr>', "Tags")
|
||||
|
||||
nmap_leader(
|
||||
"zrd",
|
||||
'<Cmd>ZkNew { group = "dreviews" }<CR>',
|
||||
"Daily Review"
|
||||
)
|
||||
nmap_leader(
|
||||
"zrw",
|
||||
'<Cmd>ZkNew { group = "wreviews" }<CR>',
|
||||
"Weekly Review"
|
||||
)
|
||||
nmap_leader(
|
||||
"zn",
|
||||
'<Cmd>ZkNew { group = "inbox", title = vim.fn.input("Title: ") }<CR>',
|
||||
"New"
|
||||
)
|
||||
nmap_leader(
|
||||
"zp",
|
||||
"<Cmd>ZkNew { group = 'permanent', title = vim.fn.input('Title: ') }<CR>",
|
||||
"Permanent"
|
||||
)
|
||||
|
||||
nmap_leader(
|
||||
"zl",
|
||||
"<Cmd>ZkNew { group = 'literature', title = vim.fn.input('Title: '), extra.author = vim.fn.input('Author: '), extra.year = vim.fn.input('Year: ') }<CR>",
|
||||
"Literature"
|
||||
)
|
||||
|
||||
nmap_leader(
|
||||
"zd",
|
||||
"<Cmd>ZkNew { group = 'dashboard', title = vim.fn.input('Title: ') }<CR>",
|
||||
"Dashboard"
|
||||
)
|
||||
nmap_leader(
|
||||
"zP",
|
||||
"<Cmd>ZkNew { group = 'project', title = vim.fn.input('Title: ')}<CR>",
|
||||
"Project"
|
||||
)
|
||||
-- stylua: ignore end
|
||||
314
plugin/20_startup.lua
Normal file
314
plugin/20_startup.lua
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
local now = MiniDeps.now
|
||||
local later = MiniDeps.later
|
||||
local now_if_args = Config.now_if_args
|
||||
local nix = require('config.nix')
|
||||
|
||||
if not Config.isNixCats then
|
||||
local add = MiniDeps.add
|
||||
now_if_args(function()
|
||||
add({
|
||||
source = "nvim-treesitter/nvim-treesitter",
|
||||
checkout = "master",
|
||||
monitor = "main",
|
||||
hooks = {
|
||||
post_checkout = function()
|
||||
vim.cmd("TSUpdate")
|
||||
end,
|
||||
},
|
||||
})
|
||||
add({
|
||||
source = "nvim-treesitter/nvim-treesitter-textobjects",
|
||||
checkout = "main",
|
||||
})
|
||||
add({ source = "zk-org/zk-nvim" })
|
||||
end)
|
||||
end
|
||||
|
||||
-- Mini.nvim
|
||||
now(function()
|
||||
local colorschemeName = nix.get_setting("onedark_dark", "colorscheme")
|
||||
if colorschemeName == 'light' then
|
||||
local palette = require('mini.hues').make_palette({
|
||||
background = '#fefcf5',
|
||||
foreground = '#657b83',
|
||||
accent = 'bg',
|
||||
saturation = 'high',
|
||||
n_hues = 8
|
||||
})
|
||||
palette.fg_mid2 = "#586e75"
|
||||
palette.fg_mid = "#073642"
|
||||
palette.bg_edge = "#fdf6e3"
|
||||
palette.accent_bg = "#eee8d5"
|
||||
require('mini.hues').apply_palette(palette)
|
||||
else
|
||||
if colorschemeName == "cyberdream" and vim.o.background == 'light' then
|
||||
colorschemeName = colorschemeName .. '-light'
|
||||
end
|
||||
vim.cmd.colorscheme(colorschemeName)
|
||||
end
|
||||
end)
|
||||
|
||||
now(function()
|
||||
require("mini.basics").setup({
|
||||
options = {
|
||||
basic = true,
|
||||
extra_ui = true
|
||||
},
|
||||
mappings = {
|
||||
-- jk linewise, gy/gp system clipboard, gV select last change/yank
|
||||
basic = true,
|
||||
-- <C-hjkl> move between windows, <C-arrow> resize
|
||||
windows = true,
|
||||
move_with_alt = true,
|
||||
option_toggle_prefix = "<leader>u"
|
||||
},
|
||||
autocommands = {
|
||||
basic = true,
|
||||
relnum_in_visual_mode = true
|
||||
},
|
||||
})
|
||||
end)
|
||||
|
||||
now(function()
|
||||
require("mini.icons").setup({
|
||||
use_file_extension = function(ext, _)
|
||||
local suf3, suf4 = ext:sub(-3), ext:sub(-4)
|
||||
return suf3 ~= "scm" and suf3 ~= "txt" and suf3 ~= "yml" and suf4 ~= "json" and suf4 ~= "yaml"
|
||||
end,
|
||||
})
|
||||
later(MiniIcons.mock_nvim_web_devicons)
|
||||
later(MiniIcons.tweak_lsp_kind)
|
||||
end)
|
||||
|
||||
now(function()
|
||||
local predicate = function(notif)
|
||||
if not (notif.data.source == "lsp_progress" and notif.data.client_name == "lua_ls") then
|
||||
return true
|
||||
end
|
||||
-- Filter out some LSP progress notifications from 'lua_ls'
|
||||
return notif.msg:find("Diagnosing") == nil and notif.msg:find("semantic tokens") == nil
|
||||
end
|
||||
local custom_sort = function(notif_arr)
|
||||
return MiniNotify.default_sort(vim.tbl_filter(predicate, notif_arr))
|
||||
end
|
||||
|
||||
require("mini.notify").setup({ content = { sort = custom_sort } })
|
||||
vim.notify = MiniNotify.make_notify()
|
||||
end)
|
||||
|
||||
now(function()
|
||||
require("mini.sessions").setup()
|
||||
end)
|
||||
|
||||
now(function()
|
||||
local starter = require("mini.starter")
|
||||
starter.setup({
|
||||
evaluate_single = true,
|
||||
items = {
|
||||
starter.sections.recent_files(5, true),
|
||||
function()
|
||||
local section = Config.startup.get_recent_files_by_ft_or_ext({
|
||||
"r",
|
||||
"sql",
|
||||
"julia",
|
||||
"python",
|
||||
"lua",
|
||||
})
|
||||
return section
|
||||
end,
|
||||
starter.sections.pick(),
|
||||
starter.sections.sessions(5, true),
|
||||
starter.sections.builtin_actions(),
|
||||
starter.sections.recent_files(3, false),
|
||||
},
|
||||
footer = Config.startup.footer_text,
|
||||
content_hooks = {
|
||||
starter.gen_hook.adding_bullet(),
|
||||
starter.gen_hook.indexing(
|
||||
"all",
|
||||
{ "Builtin actions", "Recent files (current directory)", "Recent files", }
|
||||
),
|
||||
starter.gen_hook.aligning("center", "center"),
|
||||
starter.gen_hook.padding(3, 2),
|
||||
},
|
||||
})
|
||||
end)
|
||||
|
||||
now(function()
|
||||
require("mini.statusline").setup()
|
||||
end)
|
||||
|
||||
now(function()
|
||||
require("mini.tabline").setup()
|
||||
end)
|
||||
|
||||
now(function()
|
||||
local miniclue = require("mini.clue")
|
||||
--stylua: ignore
|
||||
miniclue.setup({
|
||||
window = {
|
||||
config = {
|
||||
width = 'auto'
|
||||
},
|
||||
delay = 100,
|
||||
},
|
||||
clues = {
|
||||
Config.leader_group_clues,
|
||||
miniclue.gen_clues.builtin_completion(),
|
||||
miniclue.gen_clues.g(),
|
||||
miniclue.gen_clues.marks(),
|
||||
miniclue.gen_clues.registers(),
|
||||
miniclue.gen_clues.windows({ submode_resize = true, submode_move = true }),
|
||||
miniclue.gen_clues.z(),
|
||||
},
|
||||
triggers = {
|
||||
{ mode = 'n', keys = '<Leader>' }, -- Leader triggers
|
||||
{ mode = 'n', keys = '<LocalLeader>' }, -- LocalLeader triggers
|
||||
{ mode = 'x', keys = '<Leader>' },
|
||||
{ mode = 'x', keys = '<LocalLeader>' },
|
||||
{ mode = 'n', keys = [[\]] }, -- mini.basics
|
||||
{ mode = 'n', keys = '[' }, -- mini.bracketed
|
||||
{ mode = 'n', keys = ']' },
|
||||
{ mode = 'x', keys = '[' },
|
||||
{ mode = 'x', keys = ']' },
|
||||
{ mode = 'i', keys = '<C-x>' }, -- Built-in completion
|
||||
{ mode = 'n', keys = 'g' }, -- `g` key
|
||||
{ mode = 'x', keys = 'g' },
|
||||
{ mode = 'n', keys = '`' },
|
||||
{ mode = 'x', keys = '`' },
|
||||
{ mode = 'n', keys = '"' }, -- Registers
|
||||
{ mode = 'x', keys = '"' },
|
||||
{ mode = 'i', keys = '<C-r>' },
|
||||
{ mode = 'c', keys = '<C-r>' },
|
||||
{ mode = 'n', keys = '<C-w>' }, -- Window commands
|
||||
{ mode = 'n', keys = 'z' }, -- `z` key
|
||||
{ mode = 'x', keys = 'z' },
|
||||
},
|
||||
})
|
||||
end)
|
||||
|
||||
-- Treesitter
|
||||
|
||||
now_if_args(function()
|
||||
vim.treesitter.language.register("markdown", { "markdown", "codecompanion" })
|
||||
|
||||
-- Base configuration
|
||||
local opts = {
|
||||
highlight = { enable = true },
|
||||
indent = { enable = false },
|
||||
textobjects = {
|
||||
move = {
|
||||
enable = true,
|
||||
set_jumps = true, -- whether to set jumps in the jumplist
|
||||
goto_next_start = {
|
||||
["]a"] = "@paramter.inner",
|
||||
["]f"] = "@function.outer",
|
||||
["]o"] = "@loop.*",
|
||||
["]s"] = { query = "@local.scope", desc = "Next scope" },
|
||||
["]z"] = { query = "@fold", desc = "Next fold" },
|
||||
},
|
||||
goto_next_end = {
|
||||
["]M"] = "@function.outer",
|
||||
["]["] = "@class.outer",
|
||||
},
|
||||
goto_previous_start = {
|
||||
["[a"] = "@parameter.inner",
|
||||
["[f"] = "@function.outer",
|
||||
["[o"] = "@loop.*",
|
||||
["[s"] = { query = "@local.scope", query_group = "locals", desc = "Prev. scope" },
|
||||
["[z"] = { query = "@fold", query_group = "folds", desc = "Prev. fold" },
|
||||
},
|
||||
goto_previous_end = {
|
||||
["[M"] = "@function.outer",
|
||||
["[]"] = "@class.outer",
|
||||
},
|
||||
goto_next = {
|
||||
["]e"] = "@conditional.outer",
|
||||
},
|
||||
goto_previous = {
|
||||
["[e"] = "@conditional.outer",
|
||||
}
|
||||
},
|
||||
swap = {
|
||||
enable = true,
|
||||
swap_next = {
|
||||
["<leader>x"] = "@parameter.inner",
|
||||
},
|
||||
swap_previous = {
|
||||
["<leader>X"] = "@parameter.inner",
|
||||
},
|
||||
},
|
||||
lsp_interop = {
|
||||
enable = true,
|
||||
border = 'none',
|
||||
floating_preview_opts = {},
|
||||
peek_definition_code = {
|
||||
["<leader>lm"] = "@function.outer",
|
||||
["<leader>lM"] = "@class.outer",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
-- Environment-specific Overrides
|
||||
if not Config.isNixCats then
|
||||
opts.auto_install = true
|
||||
opts.ensure_installed = Config.treesitter_helpers.default_parsers
|
||||
else
|
||||
opts.auto_install = false
|
||||
-- Nix handles installation, so ensure_installed is skipped/empty
|
||||
end
|
||||
|
||||
-- Manual parser check for non-Nix users
|
||||
if not Config.isNixCats then
|
||||
local installed_check = function(lang)
|
||||
return #vim.api.nvim_get_runtime_file("parser/" .. lang .. ".*", false) == 0
|
||||
end
|
||||
local to_install = vim.tbl_filter(installed_check, opts.ensure_installed)
|
||||
if #to_install > 0 then
|
||||
require("nvim-treesitter").install(to_install)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local configs = require("nvim-treesitter.configs")
|
||||
configs.setup(opts)
|
||||
require 'treesitter-context'.setup {
|
||||
enable = true,
|
||||
multiwindow = false, -- Enable multiwindow support.
|
||||
max_lines = 30, -- How many lines the window should span. Values <= 0 mean no limit.
|
||||
min_window_height = 70, -- Minimum editor window height to enable context. Values <= 0 mean no limit.
|
||||
line_numbers = true,
|
||||
multiline_threshold = 10, -- Maximum number of lines to show for a single context
|
||||
trim_scope = 'outer', -- Which context lines to discard if `max_lines` is exceeded. Choices: 'inner', 'outer'
|
||||
mode = 'cursor', -- Line used to calculate context. Choices: 'cursor', 'topline'
|
||||
-- Separator between context and content. Should be a single character string, like '-'.
|
||||
-- When separator is set, the context will only show up when there are at least 2 lines above cursorline.
|
||||
separator = '-',
|
||||
zindex = 20, -- The Z-index of the context window
|
||||
on_attach = nil, -- (fun(buf: integer): boolean) return false to disable attaching
|
||||
}
|
||||
end)
|
||||
|
||||
-- zk
|
||||
now_if_args(function()
|
||||
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" },
|
||||
},
|
||||
|
||||
},
|
||||
})
|
||||
end)
|
||||
104
plugin/21_datascience.lua
Normal file
104
plugin/21_datascience.lua
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
local now = MiniDeps.now
|
||||
local now_if_args = Config.now_if_args
|
||||
local later = MiniDeps.later
|
||||
local add = Config.add
|
||||
local nix = require('config.nix')
|
||||
|
||||
if not Config.isNixCats then
|
||||
local m_add = MiniDeps.add
|
||||
|
||||
now(function()
|
||||
m_add({ source = "R-nvim/R.nvim" })
|
||||
end)
|
||||
|
||||
now_if_args(function()
|
||||
m_add({ source = "jmbuhr/otter.nvim" })
|
||||
end)
|
||||
|
||||
later(function()
|
||||
m_add({ source = "jpalardy/vim-slime" })
|
||||
end)
|
||||
end
|
||||
|
||||
-- terminal
|
||||
later(function()
|
||||
vim.g.slime_target = "neovim"
|
||||
vim.g.slime_no_mappings = true
|
||||
add("vim-slime")
|
||||
vim.g.slime_cell_delimiter = vim.g.slime_cell_delimiter or "# %%"
|
||||
vim.g.slime_bracketed_paste = Config.opt_bracket
|
||||
vim.g.slime_input_pid = false
|
||||
vim.g.slime_suggest_default = true
|
||||
vim.g.slime_menu_config = false
|
||||
vim.g.slime_neovim_ignore_unlisted = false
|
||||
|
||||
-- Define standard slime mappings
|
||||
vim.keymap.set("v", "<CR>", "<Plug>SlimeRegionSend", { noremap = true })
|
||||
vim.keymap.set("v", "<localleader><localleader>", "<Plug>SlimeRegionSend", { noremap = true })
|
||||
vim.keymap.set("n", "<localleader><localleader>", "<Plug>SlimeLineSend", { noremap = true })
|
||||
-- Standardize on C-c C-c as well (common convention)
|
||||
vim.keymap.set("v", "<C-c><C-c>", "<Plug>SlimeRegionSend", { noremap = true })
|
||||
vim.keymap.set("n", "<C-c><C-c>", "<Plug>SlimeParagraphSend", { noremap = true })
|
||||
end)
|
||||
|
||||
-- r
|
||||
now(function()
|
||||
if nix.get_cat("r", false) then
|
||||
vim.g.rout_follow_colorscheme = true
|
||||
require("r").setup({
|
||||
-- Create a table with the options to be passed to setup()
|
||||
R_args = { "--quiet", "--no-save" },
|
||||
auto_start = "no",
|
||||
objbr_auto_start = false,
|
||||
objbr_place = 'console,below',
|
||||
rconsole_width = 120,
|
||||
min_editor_width = 80,
|
||||
rconsole_height = 20,
|
||||
nvimpager = "split_h",
|
||||
pdfviewer = "zathura",
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
-- Quarto
|
||||
now(function()
|
||||
vim.treesitter.language.register("markdown", { "quarto", "rmd" })
|
||||
|
||||
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)
|
||||
|
||||
later(function()
|
||||
require("quarto").setup({
|
||||
lspFeatures = {
|
||||
enabled = true,
|
||||
languages = { "r", "python", "julia" },
|
||||
diagnostics = {
|
||||
enabled = true,
|
||||
triggers = { "BufWrite" },
|
||||
},
|
||||
completion = {
|
||||
enabled = true,
|
||||
},
|
||||
},
|
||||
codeRunner = {
|
||||
enabled = true,
|
||||
default_method = "slime",
|
||||
},
|
||||
})
|
||||
end)
|
||||
53
plugin/22_languages.lua
Normal file
53
plugin/22_languages.lua
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
local add = Config.add
|
||||
local now_if_args = Config.now_if_args
|
||||
local later = MiniDeps.later
|
||||
|
||||
if not Config.isNixCats then
|
||||
local m_add = MiniDeps.add
|
||||
later(function()
|
||||
m_add({ source = "Bilal2453/luvit-meta" })
|
||||
m_add({ source = "folke/lazydev.nvim" })
|
||||
end)
|
||||
end
|
||||
|
||||
-- lua
|
||||
later(function()
|
||||
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
|
||||
now_if_args(function()
|
||||
add("render-markdown.nvim")
|
||||
require('render-markdown').setup({
|
||||
-- completions = { blink = { enabled = true } },
|
||||
file_types = { 'markdown', 'quarto', 'rmd', 'codecompanion', },
|
||||
link = {
|
||||
wiki = {
|
||||
body = function(ctx)
|
||||
local diagnostics = vim.diagnostic.get(ctx.buf, {
|
||||
lnum = ctx.row,
|
||||
severity = vim.diagnostic.severity.HINT,
|
||||
})
|
||||
for _, diagnostic in ipairs(diagnostics) do
|
||||
if diagnostic.source == 'marksman' then
|
||||
return diagnostic.message
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
},
|
||||
},
|
||||
})
|
||||
end)
|
||||
348
plugin/23_editor.lua
Normal file
348
plugin/23_editor.lua
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
local later = MiniDeps.later
|
||||
local add = Config.add
|
||||
|
||||
if not Config.isNixCats then
|
||||
local m_add = MiniDeps.add
|
||||
|
||||
later(function()
|
||||
m_add("stevearc/conform.nvim")
|
||||
end)
|
||||
end
|
||||
|
||||
-- Formatting
|
||||
later(function()
|
||||
add("conform.nvim")
|
||||
require("conform").setup({
|
||||
-- Map of filetype to formatters
|
||||
formatters_by_ft = {
|
||||
javascript = { "prettier" },
|
||||
json = { "prettier" },
|
||||
python = { "black" },
|
||||
nix = { "alejandra" },
|
||||
-- r = { "my_styler" },
|
||||
rmd = { "injected" },
|
||||
quarto = { "injected" },
|
||||
},
|
||||
|
||||
lsp_format = "fallback",
|
||||
|
||||
formatters = {
|
||||
my_styler = {
|
||||
command = "R",
|
||||
-- A list of strings, or a function that returns a list of strings
|
||||
-- Return a single string instead of a list to run the command in a shell
|
||||
args = { "-s", "-e", "styler::style_file(commandArgs(TRUE)[1])", "--args", "$FILENAME" },
|
||||
stdin = false,
|
||||
},
|
||||
},
|
||||
})
|
||||
end)
|
||||
|
||||
-- Edit
|
||||
later(function()
|
||||
local ai = require("mini.ai")
|
||||
local spec_treesitter = ai.gen_spec.treesitter
|
||||
ai.setup({
|
||||
search_method = "cover",
|
||||
n_lines = 1000,
|
||||
})
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.align").setup()
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.animate").setup({ scroll = { enable = false } })
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.bracketed").setup({
|
||||
diagnostic = {
|
||||
options = {
|
||||
float = false,
|
||||
},
|
||||
},
|
||||
})
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.bufremove").setup()
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.comment").setup()
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.cursorword").setup({ delay = 1000 })
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.diff").setup({
|
||||
view = {
|
||||
style = "sign",
|
||||
},
|
||||
mappings = {
|
||||
apply = "<leader>ga",
|
||||
reset = "<leader>gr",
|
||||
textobject = "o",
|
||||
},
|
||||
options = {
|
||||
linematch = 1000,
|
||||
algorithm = 'myers',
|
||||
},
|
||||
})
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.files").setup({
|
||||
windows = {
|
||||
preview = true,
|
||||
width_focus = 80,
|
||||
width_preview = 90,
|
||||
},
|
||||
mappings = {
|
||||
mark_goto = "'",
|
||||
synchronize = ':',
|
||||
}
|
||||
})
|
||||
local minifiles_augroup = vim.api.nvim_create_augroup("ec-mini-files", {})
|
||||
vim.api.nvim_create_autocmd("User", {
|
||||
group = minifiles_augroup,
|
||||
pattern = "MiniFilesExplorerOpen",
|
||||
callback = function()
|
||||
MiniFiles.set_bookmark("h", os.getenv("HOME") or vim.env.HOME, { desc = "Home" })
|
||||
MiniFiles.set_bookmark("c", vim.fn.stdpath("config"), { desc = "Config" })
|
||||
MiniFiles.set_bookmark("w", vim.fn.getcwd, { desc = "Working directory" })
|
||||
MiniFiles.set_bookmark("z", os.getenv("ZK_NOTEBOOK_DIR") or vim.env.HOME, { desc = "ZK" })
|
||||
end,
|
||||
})
|
||||
|
||||
-- Set focused directory as current working directory
|
||||
local function remove_string(string1, string2)
|
||||
return string2:gsub(string1, "", 1)
|
||||
end
|
||||
local set_cwd = function()
|
||||
local path = (MiniFiles.get_fs_entry() or {}).path
|
||||
if path == nil then
|
||||
return vim.notify("Cursor is not on valid entry")
|
||||
end
|
||||
|
||||
local pwd = vim.fs.dirname(path)
|
||||
vim.notify("PWD: " .. '.' .. vim.fn.pathshorten(pwd, 6))
|
||||
vim.fn.chdir(pwd)
|
||||
end
|
||||
|
||||
-- Yank in register full path of entry under cursor
|
||||
local yank_path = function()
|
||||
local path = (MiniFiles.get_fs_entry() or {}).path
|
||||
if path == nil then
|
||||
return vim.notify("Cursor is not on valid entry")
|
||||
end
|
||||
vim.notify("Yanked: " .. path)
|
||||
vim.fn.setreg(vim.v.register, path)
|
||||
end
|
||||
|
||||
-- Yank in register relative path of entry under cursor
|
||||
local yank_relpath = function()
|
||||
local path = (MiniFiles.get_fs_entry() or {}).path
|
||||
local cwd = vim.fn.getcwd() .. '/'
|
||||
local relpath = remove_string(cwd, path)
|
||||
if path == nil then
|
||||
return vim.notify("Cursor is not on valid entry")
|
||||
end
|
||||
vim.notify("Yanked: " .. relpath)
|
||||
vim.fn.setreg(vim.v.register, relpath)
|
||||
end
|
||||
|
||||
local ui_open = function()
|
||||
vim.ui.open(MiniFiles.get_fs_entry().path)
|
||||
end
|
||||
vim.api.nvim_create_autocmd("User", {
|
||||
pattern = "MiniFilesBufferCreate",
|
||||
callback = function(args)
|
||||
local b = args.data.buf_id
|
||||
vim.keymap.set("n", "g~", set_cwd, { buffer = b, desc = "Set cwd" })
|
||||
vim.keymap.set("n", "gX", ui_open, { buffer = b, desc = "Open UI" })
|
||||
vim.keymap.set("n", "gY", yank_path, { buffer = b, desc = "Yank path" })
|
||||
vim.keymap.set("n", "gy", yank_relpath, { buffer = b, desc = "Yank relpath" })
|
||||
end,
|
||||
})
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.git").setup()
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.extra").setup()
|
||||
end)
|
||||
|
||||
later(function()
|
||||
local hipatterns = require("mini.hipatterns")
|
||||
local hi_words = MiniExtra.gen_highlighter.words
|
||||
hipatterns.setup({
|
||||
highlighters = {
|
||||
fixme = hi_words({ "FIXME", "Fixme", "fixme" }, "MiniHipatternsFixme"),
|
||||
hack = hi_words({ "HACK", "Hack", "hack" }, "MiniHipatternsHack"),
|
||||
todo = hi_words({ "TODO", "Todo", "todo" }, "MiniHipatternsTodo"),
|
||||
note = hi_words({ "NOTE", "Note", "note" }, "MiniHipatternsNote"),
|
||||
|
||||
hex_color = hipatterns.gen_highlighter.hex_color(),
|
||||
},
|
||||
})
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.indentscope").setup()
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.jump").setup()
|
||||
end)
|
||||
|
||||
later(function()
|
||||
local jump2d = require("mini.jump2d")
|
||||
jump2d.setup({
|
||||
spotter = jump2d.gen_spotter.pattern("[^%s%p]+"),
|
||||
allowed_lines = {
|
||||
blank = false,
|
||||
cursor_at = false
|
||||
},
|
||||
labels = "asdfghjklweruiopzxcnm,;",
|
||||
view = { dim = true, n_steps_ahead = 2 },
|
||||
mappings = {
|
||||
start_jumping = "sj",
|
||||
},
|
||||
})
|
||||
vim.keymap.set({ "n", "x", "o" }, "<leader><CR>", function()
|
||||
MiniJump2d.start(MiniJump2d.builtin_opts.single_character)
|
||||
end)
|
||||
end)
|
||||
|
||||
later(function()
|
||||
local minikeymap = require("mini.keymap")
|
||||
minikeymap.setup()
|
||||
local map_multistep = minikeymap.map_multistep
|
||||
local tab_steps = {
|
||||
"blink_next",
|
||||
"pmenu_next",
|
||||
"increase_indent",
|
||||
"jump_after_close",
|
||||
}
|
||||
map_multistep("i", "<Tab>", tab_steps)
|
||||
local shifttab_steps = {
|
||||
"blink_prev",
|
||||
"pmenu_prev",
|
||||
"decrease_indent",
|
||||
"jump_before_open",
|
||||
}
|
||||
map_multistep("i", "<S-Tab>", shifttab_steps)
|
||||
map_multistep("i", "<CR>", {
|
||||
"blink_accept",
|
||||
"pmenu_accept",
|
||||
"minipairs_cr",
|
||||
})
|
||||
map_multistep("i", "<BS>", { "hungry_bs", "minipairs_bs" })
|
||||
|
||||
local tab_steps_n = {
|
||||
"minisnippets_next",
|
||||
"jump_after_tsnode",
|
||||
"jump_after_close",
|
||||
}
|
||||
map_multistep("n", "<Tab>", tab_steps_n)
|
||||
|
||||
local shifttab_steps_n = {
|
||||
"minisnippets_prev",
|
||||
"jump_before_tsnode",
|
||||
"jump_before_open",
|
||||
}
|
||||
map_multistep("n", "<S-Tab>", shifttab_steps_n)
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.move").setup({ options = { reindent_linewise = false } })
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.operators").setup({
|
||||
replace = {
|
||||
prefix = "gl"
|
||||
},
|
||||
})
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.pairs").setup({
|
||||
mappings = {
|
||||
['"'] = { neigh_pattern = '[^%a\\"].' },
|
||||
["'"] = { neigh_pattern = "[^%a\\'#]." },
|
||||
},
|
||||
modes = {
|
||||
insert = true,
|
||||
command = true,
|
||||
terminal = true
|
||||
}
|
||||
})
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.misc").setup({ make_global = { "put", "put_text", "stat_summary", "bench_time" } })
|
||||
-- MiniMisc.setup_auto_root()
|
||||
MiniMisc.setup_termbg_sync()
|
||||
MiniMisc.setup_restore_cursor()
|
||||
end)
|
||||
|
||||
later(function()
|
||||
local choose_all = function()
|
||||
local mappings = MiniPick.get_picker_opts().mappings
|
||||
vim.api.nvim_input(mappings.mark_all .. mappings.choose_marked)
|
||||
end
|
||||
require("mini.pick").setup({
|
||||
mappings = {
|
||||
choose_marked = '<C-CR>',
|
||||
choose_all = { char = '<C-q>', func = choose_all },
|
||||
}
|
||||
})
|
||||
|
||||
vim.ui.select = MiniPick.ui_select
|
||||
-- vim.api.nvim_set_hl(0, "MiniPickMatchCurrent", { bg = "#fe640b", bold = true })
|
||||
end)
|
||||
|
||||
later(function()
|
||||
local snippets = require("mini.snippets")
|
||||
local gen_loader = snippets.gen_loader
|
||||
local lang_patterns = {
|
||||
markdown_inline = { "quarto.json" },
|
||||
}
|
||||
snippets.setup({
|
||||
snippets = {
|
||||
-- Load custom file with global snippets first (adjust for Windows)
|
||||
gen_loader.from_file(vim.fn.stdpath('config') .. "/snippets/global.json"),
|
||||
|
||||
-- Load snippets based on current language by reading files from
|
||||
-- "snippets/" subdirectories from 'runtimepath' directories.
|
||||
gen_loader.from_lang({ lang_patterns = lang_patterns }),
|
||||
},
|
||||
-- expand = { match = match_strict },
|
||||
})
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.splitjoin").setup()
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.surround").setup()
|
||||
-- Disable `s` shortcut (use `cl` instead) for safer usage of 'mini.surround'
|
||||
vim.keymap.set({ "n", "x" }, "s", "<Nop>")
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.trailspace").setup()
|
||||
end)
|
||||
|
||||
later(function()
|
||||
require("mini.visits").setup()
|
||||
end)
|
||||
351
plugin/24_completion.lua
Normal file
351
plugin/24_completion.lua
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
local add = Config.add
|
||||
local later = MiniDeps.later
|
||||
local now_if_args = Config.now_if_args
|
||||
|
||||
-- Constants
|
||||
local BLINK_VERSION = "v1.4.1"
|
||||
|
||||
-- Plugin sources configuration
|
||||
local PLUGIN_SOURCES = {
|
||||
"hrsh7th/cmp-cmdline",
|
||||
"xzbdmw/colorful-menu.nvim",
|
||||
"zbirenbaum/copilot.lua",
|
||||
"jmbuhr/cmp-pandoc-references",
|
||||
"fang2hou/blink-copilot",
|
||||
"olimorris/codecompanion.nvim"
|
||||
}
|
||||
|
||||
local PLUGIN_ADDS = {
|
||||
"cmp-cmdline",
|
||||
"blink.compat",
|
||||
"colorful-menu.nvim",
|
||||
"cmp-pandoc-references",
|
||||
}
|
||||
|
||||
-- Helper functions
|
||||
local function create_system_prompt(role_description)
|
||||
return function(context)
|
||||
return "I want you to act as a senior " .. context.filetype .. " developer. " .. role_description
|
||||
end
|
||||
end
|
||||
|
||||
local function get_code_block(context)
|
||||
local text = require("codecompanion.helpers.actions").get_code(context.start_line, context.end_line)
|
||||
return "```" .. context.filetype .. "\n" .. text .. "\n```"
|
||||
end
|
||||
|
||||
local function create_common_opts(mapping, short_name)
|
||||
return {
|
||||
mapping = mapping,
|
||||
modes = { "v" },
|
||||
short_name = short_name,
|
||||
auto_submit = true,
|
||||
stop_context_insertion = true,
|
||||
user_prompt = true,
|
||||
}
|
||||
end
|
||||
|
||||
local function get_mini_icons_highlight(ctx)
|
||||
local _, hl, _ = require("mini.icons").get("lsp", ctx.kind)
|
||||
return hl
|
||||
end
|
||||
|
||||
local function get_blink_fuzzy_setting()
|
||||
local setting = {
|
||||
sorts = { "exact", "score", "sort_text" }
|
||||
}
|
||||
|
||||
if not Config.isNixCats then
|
||||
setting.prebuilt_binary = { force_version = BLINK_VERSION }
|
||||
end
|
||||
|
||||
return setting
|
||||
end
|
||||
|
||||
-- Plugin loading
|
||||
if not Config.isNixCats then
|
||||
local m_add = MiniDeps.add
|
||||
|
||||
now_if_args(function()
|
||||
m_add({
|
||||
source = "saghen/blink.cmp",
|
||||
depends = { "rafamadriz/friendly-snippets" },
|
||||
checkout = BLINK_VERSION,
|
||||
})
|
||||
end)
|
||||
|
||||
later(function()
|
||||
for _, source in ipairs(PLUGIN_SOURCES) do
|
||||
m_add({ source = source })
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function get_codecompanion_config()
|
||||
return {
|
||||
adapters = {
|
||||
http = {
|
||||
copilot = function()
|
||||
return require("codecompanion.adapters").extend("copilot", {
|
||||
schema = {
|
||||
model = { default = "gemini-3-pro-preview" }
|
||||
}
|
||||
})
|
||||
end,
|
||||
}
|
||||
},
|
||||
display = {
|
||||
chat = {
|
||||
show_settings = false,
|
||||
window = {
|
||||
layout = "horizontal",
|
||||
position = "bottom",
|
||||
height = 0.33,
|
||||
},
|
||||
},
|
||||
},
|
||||
prompt_library = {
|
||||
["Code Expert"] = {
|
||||
strategy = "chat",
|
||||
description = "Get expert advice from an LLM",
|
||||
opts = create_common_opts("<localleader>ae", "expert"),
|
||||
prompts = {
|
||||
{
|
||||
role = "system",
|
||||
content = create_system_prompt(
|
||||
"I will ask you specific questions and I want you to return concise explanations and codeblock examples."
|
||||
),
|
||||
},
|
||||
{
|
||||
role = "user",
|
||||
content = function(context)
|
||||
return "I have the following code:\n\n" .. get_code_block(context) .. "\n\n"
|
||||
end,
|
||||
opts = { contains_code = true },
|
||||
},
|
||||
},
|
||||
},
|
||||
["Code Fixer"] = {
|
||||
strategy = "chat",
|
||||
description = "Fix code errors with expert guidance",
|
||||
opts = create_common_opts("<localleader>af", "afixer"),
|
||||
prompts = {
|
||||
{
|
||||
role = "system",
|
||||
content = create_system_prompt(
|
||||
"I have a block of code that is not working and will give you a hint about the error. I want you to return the corrected code and a concise explanation of the corrections."
|
||||
),
|
||||
},
|
||||
{
|
||||
role = "user",
|
||||
content = function(context)
|
||||
return "The following code has an error:\n\n" .. get_code_block(context) .. "\n\nThe error is:"
|
||||
end,
|
||||
opts = { contains_code = true },
|
||||
},
|
||||
},
|
||||
},
|
||||
["Suggest"] = {
|
||||
strategy = "chat",
|
||||
description = "Suggest improvements to the buffer",
|
||||
opts = {
|
||||
mapping = "<localleader>as",
|
||||
modes = { "v" },
|
||||
short_name = "suggest",
|
||||
auto_submit = true,
|
||||
user_prompt = false,
|
||||
stop_context_insertion = false,
|
||||
},
|
||||
prompts = {
|
||||
{
|
||||
role = "system",
|
||||
content = create_system_prompt(
|
||||
"When asked to improve code, follow these steps:\n" ..
|
||||
"1. Identify the programming language.\n" ..
|
||||
"2. Think separately for each function or significant block of code and think about possible improvements (e.g., for better readability or speed) in the context of the language.\n" ..
|
||||
"3. Think about the whole document and think about possible improvements.\n" ..
|
||||
"4. Provide the improved code.\n" ..
|
||||
"5. Provide a concise explanation of the improvements."
|
||||
),
|
||||
},
|
||||
{
|
||||
role = "user",
|
||||
content = function(context)
|
||||
return "Please improve the following code:\n\n" .. get_code_block(context)
|
||||
end,
|
||||
opts = { contains_code = true },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
-- Batch add simple plugins
|
||||
later(function()
|
||||
for _, plugin in ipairs(PLUGIN_ADDS) do
|
||||
add(plugin)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Configure plugins with setup
|
||||
later(function()
|
||||
add("copilot.lua")
|
||||
require("copilot").setup({
|
||||
suggestion = { enabled = false },
|
||||
panel = { enabled = false },
|
||||
filetypes = {
|
||||
help = true,
|
||||
julia = true,
|
||||
lua = true,
|
||||
markdown = true,
|
||||
nix = true,
|
||||
python = true,
|
||||
r = true,
|
||||
sh = function()
|
||||
if string.match(vim.fs.basename(vim.api.nvim_buf_get_name(0)), '^%.env.*') then
|
||||
-- disable for .env files
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end,
|
||||
["."] = false
|
||||
},
|
||||
server_opts_overrides = {
|
||||
settings = {
|
||||
telemetry = { telemetryLevel = 'off' }
|
||||
}
|
||||
},
|
||||
should_attach = function(_, bufname)
|
||||
if string.match(bufname, "env") then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
})
|
||||
end)
|
||||
|
||||
later(function()
|
||||
add("blink-copilot")
|
||||
require("blink-copilot").setup({
|
||||
max_completions = 1,
|
||||
})
|
||||
end)
|
||||
|
||||
|
||||
later(function()
|
||||
add("codecompanion.nvim")
|
||||
|
||||
-- now use function
|
||||
require("codecompanion").setup(get_codecompanion_config())
|
||||
vim.cmd([[cab cc CodeCompanion]])
|
||||
end)
|
||||
|
||||
now_if_args(function()
|
||||
add("blink.cmp")
|
||||
|
||||
require("blink.cmp").setup({
|
||||
keymap = {
|
||||
preset = "default",
|
||||
["<C-space>"] = { "show", "select_next" },
|
||||
["<C-l>"] = { "accept" },
|
||||
},
|
||||
cmdline = {
|
||||
enabled = true,
|
||||
keymap = {
|
||||
preset = "inherit",
|
||||
["<Tab>"] = { "show", "select_next" },
|
||||
["<S-Tab>"] = { "show", "select_prev" },
|
||||
["<C-l>"] = { "accept" },
|
||||
},
|
||||
completion = {
|
||||
menu = { auto_show = true },
|
||||
list = {
|
||||
selection = { preselect = false, auto_insert = true }
|
||||
},
|
||||
},
|
||||
sources = function()
|
||||
local cmd_type = vim.fn.getcmdtype()
|
||||
if cmd_type == "/" or cmd_type == "?" then
|
||||
return { "buffer" }
|
||||
elseif cmd_type == ":" or cmd_type == "@" then
|
||||
return { "cmdline", "cmp_cmdline" }
|
||||
end
|
||||
return {}
|
||||
end,
|
||||
},
|
||||
fuzzy = get_blink_fuzzy_setting(),
|
||||
signature = {
|
||||
enabled = true,
|
||||
window = { show_documentation = true }
|
||||
},
|
||||
completion = {
|
||||
menu = {
|
||||
draw = {
|
||||
treesitter = { "lsp" },
|
||||
components = {
|
||||
label = {
|
||||
text = function(ctx)
|
||||
return require("colorful-menu").blink_components_text(ctx)
|
||||
end,
|
||||
highlight = function(ctx)
|
||||
return require("colorful-menu").blink_components_highlight(ctx)
|
||||
end,
|
||||
},
|
||||
kind_icon = { highlight = get_mini_icons_highlight },
|
||||
kind = { highlight = get_mini_icons_highlight },
|
||||
},
|
||||
},
|
||||
},
|
||||
list = {
|
||||
selection = { preselect = false, auto_insert = true }
|
||||
},
|
||||
documentation = { auto_show = true },
|
||||
trigger = { show_in_snippet = false },
|
||||
},
|
||||
snippets = { preset = "mini_snippets" },
|
||||
sources = {
|
||||
default = { "references", "lsp", "path", "snippets", "buffer", "omni", "copilot", "codecompanion" },
|
||||
providers = {
|
||||
path = {
|
||||
score_offset = 50,
|
||||
opts = {
|
||||
get_cwd = function(_)
|
||||
return vim.fn.getcwd()
|
||||
end,
|
||||
},
|
||||
},
|
||||
lsp = { score_offset = 40 },
|
||||
snippets = { score_offset = 0 },
|
||||
cmp_cmdline = {
|
||||
name = "cmp_cmdline",
|
||||
module = "blink.compat.source",
|
||||
enabled = false,
|
||||
score_offset = 10,
|
||||
opts = { cmp_name = "cmdline" }
|
||||
},
|
||||
cmp_r = {
|
||||
name = "cmp_r",
|
||||
module = "blink.compat.source",
|
||||
},
|
||||
copilot = {
|
||||
name = "copilot",
|
||||
module = "blink-copilot",
|
||||
score_offset = 45,
|
||||
async = true,
|
||||
},
|
||||
codecompanion = {
|
||||
name = "CodeCompanion",
|
||||
module = "codecompanion.providers.completion.blink",
|
||||
score_offset = 45,
|
||||
async = true,
|
||||
},
|
||||
references = {
|
||||
name = "pandoc_references",
|
||||
module = "cmp-pandoc-references.blink",
|
||||
score_offset = 50,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
end)
|
||||
89
plugin/25_lsp.lua
Normal file
89
plugin/25_lsp.lua
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
local now_if_args = Config.now_if_args
|
||||
|
||||
if not Config.isNixCats then
|
||||
local m_add = MiniDeps.add
|
||||
now_if_args(function()
|
||||
m_add("neovim/nvim-lspconfig")
|
||||
end)
|
||||
end
|
||||
|
||||
now_if_args(function()
|
||||
local servers = {
|
||||
clangd = {},
|
||||
basedpyright = {},
|
||||
ruff = {},
|
||||
marksman = {
|
||||
filetypes = { "markdown", "markdown_inline", "codecompanion" },
|
||||
},
|
||||
r_language_server = {
|
||||
filetypes = { 'r', 'rmd', 'rmarkdown' },
|
||||
settings = {
|
||||
['r_language_server'] = {
|
||||
lsp = {
|
||||
rich_documentation = true,
|
||||
enable = true,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
julials = {
|
||||
settings = {
|
||||
julia = {
|
||||
format = {
|
||||
indent = 2,
|
||||
},
|
||||
lsp = {
|
||||
autoStart = true,
|
||||
provideFormatter = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
lua_ls = {
|
||||
settings = {
|
||||
Lua = {
|
||||
completion = {
|
||||
callSnippet = "Replace",
|
||||
},
|
||||
runtime = {
|
||||
version = "LuaJIT",
|
||||
},
|
||||
diagnostics = {
|
||||
disable = { "trailing-space" },
|
||||
},
|
||||
workspace = {
|
||||
checkThirdParty = false,
|
||||
},
|
||||
doc = {
|
||||
privateName = { "^_" },
|
||||
},
|
||||
telemetry = {
|
||||
enable = false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
local lsp_flags = {
|
||||
allow_incremental_sync = true,
|
||||
}
|
||||
|
||||
if vim.fn.has("nvim-0.11") == 1 then
|
||||
-- Neovim 0.11+ Native LSP Configuration
|
||||
for name, config in pairs(servers) do
|
||||
vim.lsp.config(name, config)
|
||||
end
|
||||
vim.lsp.config('*', { flags = lsp_flags })
|
||||
|
||||
-- Enable all defined servers
|
||||
vim.lsp.enable(vim.tbl_keys(servers))
|
||||
else
|
||||
-- Fallback for Neovim < 0.11 (using nvim-lspconfig)
|
||||
local lspconfig = require('lspconfig')
|
||||
for name, config in pairs(servers) do
|
||||
local final_config = vim.tbl_extend("force", { flags = lsp_flags }, config)
|
||||
lspconfig[name].setup(final_config)
|
||||
end
|
||||
end
|
||||
end)
|
||||
14
scripts/updater.nix
Normal file
14
scripts/updater.nix
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{pkgs}:
|
||||
pkgs.writeShellApplication {
|
||||
name = "updateR";
|
||||
|
||||
# Tools your script needs at runtime
|
||||
runtimeInputs = [
|
||||
pkgs.wget
|
||||
pkgs.gnused
|
||||
pkgs.coreutils
|
||||
];
|
||||
|
||||
# Keep script in separate file, but embed contents
|
||||
text = builtins.readFile ./updater.sh;
|
||||
}
|
||||
22
scripts/updater.sh
Normal file
22
scripts/updater.sh
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
echo "📡 Fetching latest R version from rstats-on-nix..."
|
||||
RVER=$( wget -qO- 'https://raw.githubusercontent.com/ropensci/rix/refs/heads/main/inst/extdata/available_df.csv' | tail -n 1 | head -n 1 | cut -d',' -f4 | tr -d '"' )
|
||||
|
||||
# Validate RVER matches YYYY-MM-DD format
|
||||
if [[ ! "$RVER" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
|
||||
echo "❌ Error: Failed to fetch valid R version date. Got: '$RVER'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ R date is $RVER"
|
||||
|
||||
# Create backup of flake.nix before modifying
|
||||
cp flake.nix flake.nix.backup
|
||||
|
||||
# Update rixpkgs date in flake.nix
|
||||
if sed -i "s|rixpkgs.url = \"github:rstats-on-nix/nixpkgs/[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\";|rixpkgs.url = \"github:rstats-on-nix/nixpkgs/$RVER\";|" flake.nix; then
|
||||
echo "✅ Updated rixpkgs date in flake.nix"
|
||||
rm flake.nix.backup
|
||||
else
|
||||
echo "⚠️ Warning: Failed to update flake.nix, restoring backup"
|
||||
mv flake.nix.backup flake.nix
|
||||
fi
|
||||
BIN
spell/de.utf-8.spl
Normal file
BIN
spell/de.utf-8.spl
Normal file
Binary file not shown.
BIN
spell/de.utf-8.sug
Normal file
BIN
spell/de.utf-8.sug
Normal file
Binary file not shown.
28
tests/init.lua
Normal file
28
tests/init.lua
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
local function assert_ok(value, message)
|
||||
if not value then
|
||||
error(message or "assertion failed")
|
||||
end
|
||||
end
|
||||
|
||||
local ok, nix = pcall(require, "config.nix")
|
||||
assert_ok(ok, "Failed to require config.nix")
|
||||
|
||||
local init_ok, helper = pcall(function()
|
||||
return nix.init({ non_nix_value = true })
|
||||
end)
|
||||
assert_ok(init_ok and helper, "Failed to initialize config.nix helper")
|
||||
|
||||
-- Basic shape checks
|
||||
assert_ok(type(helper.is_nix) == "boolean", "Expected helper.is_nix to be boolean")
|
||||
|
||||
-- Cat/setting access should return defaults without errors
|
||||
local cat_value = helper.get_cat("general", true)
|
||||
assert_ok(type(cat_value) == "boolean", "Expected get_cat to return boolean")
|
||||
|
||||
local background = helper.get_setting("dark", "background")
|
||||
assert_ok(type(background) == "string", "Expected get_setting to return string")
|
||||
|
||||
local info_value = helper.get_info("nvim", "nixCats_configDirName")
|
||||
assert_ok(type(info_value) == "string", "Expected get_info to return string")
|
||||
|
||||
print("[tests/init.lua] nix helper smoke test passed")
|
||||
Loading…
Add table
Add a link
Reference in a new issue