Merge pull request #10 from harivansh-afk/phase-3

phase 3
This commit is contained in:
Hari 2026-03-31 00:25:22 -04:00 committed by GitHub
commit 03302eaf08
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 4940 additions and 860 deletions

1
.gitignore vendored
View file

@ -4,3 +4,4 @@ result
.bw-session
config/karabiner/assets/
config/karabiner/automatic_backups/
tmp/

View file

@ -1,34 +1,25 @@
local lsp = require('config.lsp')
pcall(vim.cmd.packadd, "blink.cmp")
vim.lsp.config('*', {
capabilities = lsp.capabilities(),
local lsp = require "config.lsp"
vim.lsp.config("*", {
on_attach = lsp.on_attach,
capabilities = lsp.capabilities(),
})
vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('UserLspConfig', {}),
callback = function(ev)
local client = vim.lsp.get_client_by_id(ev.data.client_id)
if client then
lsp.on_attach(client, ev.buf)
end
end,
})
for _, server in ipairs({
'lua_ls',
'pyright',
'ts_ls',
'rust_analyzer',
'gopls',
'clangd',
'bashls',
'jsonls',
'html',
'cssls',
}) do
local ok, config = pcall(require, 'lsp.' .. server)
if ok then
vim.lsp.config(server, config)
end
vim.lsp.enable(server)
for _, server in ipairs {
"lua_ls",
"pyright",
"ts_ls",
"rust_analyzer",
"gopls",
"clangd",
"bashls",
"jsonls",
"html",
"cssls",
} do
local ok, config = pcall(require, "lsp." .. server)
if ok and config then vim.lsp.config(server, config) end
vim.lsp.enable(server)
end

View file

@ -1,68 +1,56 @@
vim.g.mapleader = ' '
vim.g.maplocalleader = ','
vim.g.mapleader = " "
vim.g.maplocalleader = ","
local home = os.getenv('HOME') or ''
local local_bin = home .. '/.local/bin'
if not (os.getenv('PATH') or ''):find(local_bin, 1, true) then
local new_path = local_bin .. ':' .. (os.getenv('PATH') or '')
vim.env.PATH = new_path
vim.uv.os_setenv('PATH', new_path)
local home = os.getenv "HOME" or ""
local local_bin = home .. "/.local/bin"
if not (os.getenv "PATH" or ""):find(local_bin, 1, true) then
local new_path = local_bin .. ":" .. (os.getenv "PATH" or "")
vim.env.PATH = new_path
vim.uv.os_setenv("PATH", new_path)
end
function _G.map(mode, lhs, rhs, opts)
vim.keymap.set(mode, lhs, rhs, vim.tbl_extend('keep', opts or {}, { silent = true }))
vim.keymap.set(mode, lhs, rhs, vim.tbl_extend("keep", opts or {}, { silent = true }))
end
function _G.bmap(mode, lhs, rhs, opts)
_G.map(mode, lhs, rhs, vim.tbl_extend('force', opts or {}, { buffer = 0 }))
end
function _G.bmap(mode, lhs, rhs, opts) _G.map(mode, lhs, rhs, vim.tbl_extend("force", opts or {}, { buffer = 0 })) end
local disabled_plugins = {
'2html_plugin',
'bugreport',
'getscript',
'getscriptPlugin',
'gzip',
'logipat',
'matchit',
'netrw',
'netrwFileHandlers',
'netrwPlugin',
'netrwSettings',
'optwin',
'rplugin',
'rrhelper',
'synmenu',
'tar',
'tarPlugin',
'tohtml',
'tutor',
'vimball',
'vimballPlugin',
'zip',
'zipPlugin',
"2html_plugin",
"bugreport",
"getscript",
"getscriptPlugin",
"gzip",
"logipat",
"matchit",
"netrw",
"netrwFileHandlers",
"netrwPlugin",
"netrwSettings",
"optwin",
"rplugin",
"rrhelper",
"synmenu",
"tar",
"tarPlugin",
"tohtml",
"tutor",
"vimball",
"vimballPlugin",
"zip",
"zipPlugin",
}
for _, plugin in ipairs(disabled_plugins) do
vim.g['loaded_' .. plugin] = 1
vim.g["loaded_" .. plugin] = 1
end
local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim'
local lazylock = vim.fn.stdpath('state') .. '/lazy-lock.json'
if not vim.uv.fs_stat(lazypath) then
vim.fn.system({
'git',
'clone',
'--filter=blob:none',
'--branch=stable',
'https://github.com/folke/lazy.nvim.git',
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
vim.g.lz_n = {
load = function(name) vim.cmd.packadd(name:match "[^/]+$" or name) end,
}
require('lazy').setup('plugins', {
defaults = { lazy = false },
change_detection = { enabled = false },
lockfile = lazylock,
})
vim.pack.add {
"https://github.com/lumen-oss/lz.n",
}
require("lz.n").load "plugins"

View file

@ -1,28 +1,45 @@
local M = {}
local cached_capabilities
local function load_blink()
pcall(vim.cmd.packadd, "blink.cmp")
local ok_blink, blink = pcall(require, "blink.cmp")
if ok_blink then return blink end
local ok_lz, lz = pcall(require, "lz.n")
if ok_lz then
pcall(lz.trigger_load, "saghen/blink.cmp")
ok_blink, blink = pcall(require, "blink.cmp")
if ok_blink then return blink end
end
end
function M.on_attach(_, bufnr)
local function buf(mode, lhs, rhs)
bmap(mode, lhs, rhs, { buffer = bufnr })
end
local function buf(mode, lhs, rhs) bmap(mode, lhs, rhs, { buffer = bufnr }) end
buf('n', 'gd', vim.lsp.buf.definition)
buf('n', 'gD', vim.lsp.buf.declaration)
buf('n', '<C-]>', vim.lsp.buf.definition)
buf('n', 'gi', vim.lsp.buf.implementation)
buf('n', 'gr', vim.lsp.buf.references)
buf('n', 'K', vim.lsp.buf.hover)
buf('n', '<leader>rn', vim.lsp.buf.rename)
buf({ 'n', 'v' }, '<leader>ca', vim.lsp.buf.code_action)
buf('n', '<leader>f', function() vim.lsp.buf.format({ async = true }) end)
buf("n", "gd", vim.lsp.buf.definition)
buf("n", "gD", vim.lsp.buf.declaration)
buf("n", "<C-]>", vim.lsp.buf.definition)
buf("n", "gi", vim.lsp.buf.implementation)
buf("n", "gr", vim.lsp.buf.references)
buf("n", "K", vim.lsp.buf.hover)
buf("n", "<leader>rn", vim.lsp.buf.rename)
buf({ "n", "v" }, "<leader>ca", vim.lsp.buf.code_action)
buf("n", "<leader>f", function() vim.lsp.buf.format { async = true } end)
end
function M.capabilities()
local caps = vim.lsp.protocol.make_client_capabilities()
local ok, blink = pcall(require, 'blink.cmp')
if ok then
caps = blink.get_lsp_capabilities(caps)
end
return caps
if cached_capabilities then return vim.deepcopy(cached_capabilities) end
local capabilities = vim.lsp.protocol.make_client_capabilities()
local blink = load_blink()
if blink and blink.get_lsp_capabilities then
capabilities = vim.tbl_deep_extend("force", capabilities, blink.get_lsp_capabilities({}, false))
end
cached_capabilities = capabilities
return vim.deepcopy(cached_capabilities)
end
return M

View file

@ -1,48 +1,54 @@
vim.pack.add({
"https://github.com/saghen/blink.cmp",
}, { load = function() end })
return {
'saghen/blink.cmp',
version = '*',
event = { 'InsertEnter', 'LspAttach' },
opts = {
keymap = {
['<Tab>'] = { 'select_and_accept', 'snippet_forward', 'fallback' },
['<S-Tab>'] = { 'snippet_backward', 'fallback' },
['<c-p>'] = { 'select_prev', 'fallback' },
['<c-n>'] = { 'show', 'select_next', 'fallback' },
['<c-y>'] = { 'select_and_accept', 'fallback' },
['<c-e>'] = { 'cancel', 'fallback' },
['<c-u>'] = { 'scroll_documentation_up', 'fallback' },
['<c-d>'] = { 'scroll_documentation_down', 'fallback' },
"saghen/blink.cmp",
event = { "InsertEnter", "LspAttach" },
keys = { { "<c-n>", mode = "i" } },
after = function()
require("blink.cmp").setup {
keymap = {
["<Tab>"] = { "select_and_accept", "snippet_forward", "fallback" },
["<S-Tab>"] = { "snippet_backward", "fallback" },
["<c-p>"] = { "select_prev", "fallback" },
["<c-n>"] = { "show", "select_next", "fallback" },
["<c-y>"] = { "select_and_accept", "fallback" },
["<c-e>"] = { "cancel", "fallback" },
["<c-u>"] = { "scroll_documentation_up", "fallback" },
["<c-d>"] = { "scroll_documentation_down", "fallback" },
},
cmdline = { enabled = false },
completion = {
accept = {
auto_brackets = { enabled = true },
},
cmdline = { enabled = false },
completion = {
accept = {
auto_brackets = { enabled = true },
},
documentation = {
auto_show = true,
window = {
border = 'single',
scrollbar = false,
winhighlight = 'Normal:BlinkCmpDoc,FloatBorder:BlinkCmpDocBorder',
},
},
menu = {
auto_show = true,
border = 'single',
scrollbar = false,
winhighlight = 'Normal:BlinkCmpMenu,FloatBorder:BlinkCmpMenuBorder,CursorLine:BlinkCmpMenuSelection',
draw = {
treesitter = { 'lsp' },
columns = {
{ 'kind_icon', gap = 1 },
{ 'label', 'label_description', gap = 1 },
},
},
},
ghost_text = { enabled = true },
documentation = {
auto_show = true,
window = {
border = "single",
scrollbar = false,
winhighlight = "Normal:BlinkCmpDoc,FloatBorder:BlinkCmpDocBorder",
},
},
sources = {
default = { 'lsp', 'path', 'buffer', 'snippets' },
menu = {
auto_show = true,
border = "single",
scrollbar = false,
winhighlight = "Normal:BlinkCmpMenu,FloatBorder:BlinkCmpMenuBorder,CursorLine:BlinkCmpMenuSelection",
draw = {
treesitter = { "lsp" },
columns = {
{ "kind_icon", gap = 1 },
{ "label", "label_description", gap = 1 },
},
},
},
},
ghost_text = { enabled = true },
},
sources = {
default = { "lsp", "path", "buffer", "snippets" },
},
}
end,
}

View file

@ -1,171 +1,108 @@
vim.pack.add({
"https://github.com/windwp/nvim-autopairs",
"https://github.com/folke/flash.nvim",
"https://github.com/kylechui/nvim-surround",
"https://github.com/kevinhwang91/nvim-ufo",
"https://github.com/kevinhwang91/promise-async",
"https://github.com/barrettruth/pending.nvim",
"https://github.com/barrettruth/preview.nvim",
}, { load = function() end })
return {
{
'windwp/nvim-autopairs',
config = true,
},
{
'folke/flash.nvim',
opts = {
modes = { search = { enabled = true } },
},
config = function(_, opts)
require('flash').setup(opts)
map({ 'n', 'x', 'o' }, 's', function() require('flash').jump() end)
map({ 'n', 'x', 'o' }, 'S', function() require('flash').treesitter() end)
map('o', 'r', function() require('flash').remote() end)
map({ 'o', 'x' }, 'R', function() require('flash').treesitter_search() end)
map('c', '<c-s>', function() require('flash').toggle() end)
end,
},
{
'kylechui/nvim-surround',
config = true,
},
{
'kevinhwang91/nvim-ufo',
dependencies = { 'kevinhwang91/promise-async' },
opts = {
provider_selector = function()
return { 'treesitter', 'indent' }
end,
},
config = function(_, opts)
require('ufo').setup(opts)
map('n', 'zR', require('ufo').openAllFolds)
map('n', 'zM', require('ufo').closeAllFolds)
end,
},
{
enabled = false,
'barrettruth/cp.nvim',
dependencies = { 'ibhagwan/fzf-lua' },
init = function()
-- Keep uv cache in-project so cp.nvim scraping works in restricted environments.
if vim.env.UV_CACHE_DIR == nil or vim.env.UV_CACHE_DIR == '' then
local uv_cache_dir = vim.fn.getcwd() .. '/.uv-cache'
vim.fn.mkdir(uv_cache_dir, 'p')
vim.env.UV_CACHE_DIR = uv_cache_dir
end
vim.g.cp = {
languages = {
python = {
extension = 'py',
commands = {
run = { 'python3', '{source}' },
debug = { 'python3', '{source}' },
},
},
},
platforms = {
codeforces = {
enabled_languages = { 'python' },
default_language = 'python',
},
atcoder = {
enabled_languages = { 'python' },
default_language = 'python',
},
cses = {
enabled_languages = { 'python' },
default_language = 'python',
},
},
open_url = true,
ui = {
picker = 'fzf-lua',
},
}
end,
config = function()
local function open_url(url)
local ok_ui_open, opened = pcall(vim.ui.open, url)
if ok_ui_open and opened ~= false then
return
end
local opener = nil
if vim.fn.has('macunix') == 1 then
opener = 'open'
elseif vim.fn.has('unix') == 1 then
opener = 'xdg-open'
end
if opener then
vim.fn.jobstart({ opener, url }, { detach = true })
end
end
local function open_current_cp_problem_url()
local ok_state, state = pcall(require, 'cp.state')
local ok_cache, cache = pcall(require, 'cp.cache')
if not (ok_state and ok_cache) then
return
end
local platform = state.get_platform()
local contest_id = state.get_contest_id()
local problem_id = state.get_problem_id()
if not (platform and contest_id and problem_id) then
return
end
cache.load()
local contest = cache.get_contest_data(platform, contest_id)
if contest and contest.url then
open_url(contest.url:format(problem_id))
end
end
-- cp.nvim only opens URLs when first entering a contest; extend this locally for next/prev.
local ok_setup, setup = pcall(require, 'cp.setup')
local ok_config, cp_config = pcall(require, 'cp.config')
if ok_setup and ok_config and not setup._url_open_patch_applied then
local original_navigate_problem = setup.navigate_problem
setup.navigate_problem = function(direction, language)
local ok_state, state = pcall(require, 'cp.state')
local old_problem_id = ok_state and state.get_problem_id() or nil
original_navigate_problem(direction, language)
local cfg = cp_config.get_config()
local new_problem_id = ok_state and state.get_problem_id() or nil
local moved = old_problem_id ~= nil and new_problem_id ~= nil and old_problem_id ~= new_problem_id
if cfg and cfg.open_url and moved then
vim.schedule(open_current_cp_problem_url)
end
end
setup._url_open_patch_applied = true
end
map('n', '<leader>cr', '<cmd>CP run<cr>', { desc = 'CP run' })
map('n', '<leader>cp', '<cmd>CP panel<cr>', { desc = 'CP panel' })
map('n', '<leader>ce', '<cmd>CP edit<cr>', { desc = 'CP edit tests' })
map('n', '<leader>cn', '<cmd>CP next<cr>', { desc = 'CP next problem' })
map('n', '<leader>cN', '<cmd>CP prev<cr>', { desc = 'CP previous problem' })
map('n', '<leader>cc', '<cmd>CP pick<cr>', { desc = 'CP contest picker' })
map('n', '<leader>ci', '<cmd>CP interact<cr>', { desc = 'CP interact' })
map('n', '<leader>co', open_current_cp_problem_url, { desc = 'CP open problem url' })
end,
},
{
'barrettruth/pending.nvim',
init = function()
map('n', '<leader>p', '<cmd>Pending<cr><cmd>only<cr>')
end,
},
{
'barrettruth/preview.nvim',
init = function()
vim.g.preview = {
typst = true,
latex = true,
github = {
output = function(ctx)
return '/tmp/' .. vim.fn.fnamemodify(ctx.file, ':t:r') .. '.html'
end,
{
"windwp/nvim-autopairs",
event = "InsertEnter",
after = function() require("nvim-autopairs").setup() end,
},
{
"folke/flash.nvim",
after = function()
require("flash").setup {
modes = { search = { enabled = true } },
}
end,
keys = {
{
"s",
function() require("flash").jump() end,
mode = { "n", "x", "o" },
},
mermaid = true,
}
end,
},
{
"S",
function() require("flash").treesitter() end,
mode = { "n", "x", "o" },
},
{
"r",
function() require("flash").remote() end,
mode = "o",
},
{
"R",
function() require("flash").treesitter_search() end,
mode = { "o", "x" },
},
{
"<c-s>",
function() require("flash").toggle() end,
mode = "c",
},
},
},
{
"kylechui/nvim-surround",
after = function() require("nvim-surround").setup() end,
keys = {
{ "cs", mode = "n" },
{ "ds", mode = "n" },
{ "ys", mode = "n" },
{ "yS", mode = "n" },
{ "yss", mode = "n" },
{ "ySs", mode = "n" },
},
},
{
"kevinhwang91/nvim-ufo",
event = "BufReadPost",
before = function() vim.cmd.packadd "promise-async" end,
after = function()
require("ufo").setup {
provider_selector = function() return { "treesitter", "indent" } end,
}
end,
keys = {
{
"zR",
function() require("ufo").openAllFolds() end,
mode = "n",
},
{
"zM",
function() require("ufo").closeAllFolds() end,
mode = "n",
},
},
},
{
"barrettruth/pending.nvim",
cmd = "Pending",
keys = {
{ "<leader>p", "<cmd>Pending<cr><cmd>only<cr>" },
},
},
{
"barrettruth/preview.nvim",
cmd = "Preview",
ft = { "markdown", "tex", "typst" },
before = function()
vim.g.preview = {
typst = true,
latex = true,
github = {
output = function(ctx) return "/tmp/" .. vim.fn.fnamemodify(ctx.file, ":t:r") .. ".html" end,
},
mermaid = true,
}
end,
},
}

View file

@ -1,3 +1,7 @@
vim.pack.add({
"https://github.com/ibhagwan/fzf-lua",
}, { load = function() end })
---@param kind 'issue'|'pr'
---@param state 'all'|'open'|'closed'
local function gh_picker(kind, state)
@ -5,8 +9,10 @@ local function gh_picker(kind, state)
vim.notify("gh CLI not found", vim.log.levels.WARN)
return
end
local next_state = ({ all = "open", open = "closed", closed = "all" })[state]
local label = kind == "pr" and "PRs" or "Issues"
require("fzf-lua").fzf_exec(("gh %s list --limit 100 --state %s"):format(kind, state), {
prompt = ("%s (%s)> "):format(label, state),
header = ":: <c-o> to toggle all/open/closed",
@ -22,9 +28,27 @@ end
return {
"ibhagwan/fzf-lua",
dependencies = { "nvim-tree/nvim-web-devicons" },
config = function(_, opts)
cmd = "FzfLua",
before = function()
pcall(vim.cmd.packadd, "nvim-web-devicons")
pcall(vim.cmd.packadd, "nonicons.nvim")
end,
after = function()
local fzf = require "fzf-lua"
local opts = {
"default-title",
winopts = {
border = "single",
preview = {
layout = "vertical",
vertical = "down:50%",
},
},
fzf_opts = {
["--layout"] = "reverse",
},
}
fzf.setup(opts)
local ok, fzf_reload = pcall(require, "config.fzf_reload")
@ -32,45 +56,43 @@ return {
fzf_reload.setup(opts)
fzf_reload.reload()
end
map("n", "<C-f>", function()
local git_dir = vim.fn.system("git rev-parse --git-dir 2>/dev/null"):gsub("\n", "")
if vim.v.shell_error == 0 and git_dir ~= "" then
fzf.git_files()
else
fzf.files()
end
end)
map("n", "<leader>ff", "<cmd>FzfLua files<cr>")
map("n", "<leader>fg", "<cmd>FzfLua live_grep<cr>")
map("n", "<leader>fb", "<cmd>FzfLua buffers<cr>")
map("n", "<leader>fh", "<cmd>FzfLua help_tags<cr>")
map("n", "<leader>fr", "<cmd>FzfLua resume<cr>")
map("n", "<leader>fo", "<cmd>FzfLua oldfiles<cr>")
map("n", "<leader>fc", "<cmd>FzfLua commands<cr>")
map("n", "<leader>fk", "<cmd>FzfLua keymaps<cr>")
map("n", "<leader>f/", "<cmd>FzfLua search_history<cr>")
map("n", "<leader>f:", "<cmd>FzfLua command_history<cr>")
map("n", "<leader>fe", "<cmd>FzfLua files cwd=~/.config<cr>")
map("n", "gq", "<cmd>FzfLua quickfix<cr>")
map("n", "gl", "<cmd>FzfLua loclist<cr>")
map("n", "<leader>GB", "<cmd>FzfLua git_branches<cr>")
map("n", "<leader>Gc", "<cmd>FzfLua git_commits<cr>")
map("n", "<leader>Gs", "<cmd>FzfLua git_status<cr>")
map("n", "<leader>Gp", function() gh_picker("pr", "open") end)
map("n", "<leader>Gi", function() gh_picker("issue", "open") end)
end,
opts = {
"default-title",
winopts = {
border = "single",
preview = {
layout = "vertical",
vertical = "down:50%",
},
keys = {
{
"<C-f>",
function()
local fzf = require "fzf-lua"
local git_dir = vim.fn.system("git rev-parse --git-dir 2>/dev/null"):gsub("\n", "")
if vim.v.shell_error == 0 and git_dir ~= "" then
fzf.git_files()
else
fzf.files()
end
end,
},
fzf_opts = {
["--layout"] = "reverse",
{ "<leader>ff", "<cmd>FzfLua files<cr>" },
{ "<leader>fg", "<cmd>FzfLua live_grep<cr>" },
{ "<leader>fb", "<cmd>FzfLua buffers<cr>" },
{ "<leader>fh", "<cmd>FzfLua help_tags<cr>" },
{ "<leader>fr", "<cmd>FzfLua resume<cr>" },
{ "<leader>fo", "<cmd>FzfLua oldfiles<cr>" },
{ "<leader>fc", "<cmd>FzfLua commands<cr>" },
{ "<leader>fk", "<cmd>FzfLua keymaps<cr>" },
{ "<leader>f/", "<cmd>FzfLua search_history<cr>" },
{ "<leader>f:", "<cmd>FzfLua command_history<cr>" },
{ "<leader>fe", "<cmd>FzfLua files cwd=~/.config<cr>" },
{ "gq", "<cmd>FzfLua quickfix<cr>" },
{ "gl", "<cmd>FzfLua loclist<cr>" },
{ "<leader>GB", "<cmd>FzfLua git_branches<cr>" },
{ "<leader>Gc", "<cmd>FzfLua git_commits<cr>" },
{ "<leader>Gs", "<cmd>FzfLua git_status<cr>" },
{
"<leader>Gp",
function() gh_picker("pr", "open") end,
},
{
"<leader>Gi",
function() gh_picker("issue", "open") end,
},
},
}

View file

@ -1,102 +1,68 @@
local function file_loc()
local root = vim.trim(vim.fn.system('git rev-parse --show-toplevel'))
if vim.v.shell_error ~= 0 or root == '' then
return nil
end
local path = vim.api.nvim_buf_get_name(0)
if path == '' or path:sub(1, #root + 1) ~= root .. '/' then
return nil
end
return ('%s:%d'):format(path:sub(#root + 2), vim.fn.line('.'))
end
local function gh_browse()
if vim.fn.executable('gh') ~= 1 then
vim.notify('gh CLI not found', vim.log.levels.WARN)
return
end
local loc = file_loc()
if loc then
vim.system({ 'gh', 'browse', loc })
else
vim.system({ 'gh', 'browse' })
end
end
vim.pack.add({
"https://github.com/lewis6991/gitsigns.nvim",
"https://github.com/barrettruth/forge.nvim",
"https://github.com/barrettruth/diffs.nvim",
}, { load = function() end })
return {
{
'tpope/vim-fugitive',
config = function()
map('n', '<leader>gg', '<cmd>Git<cr><cmd>only<cr>')
map('n', '<leader>gc', '<cmd>Git commit<cr>')
map('n', '<leader>gp', '<cmd>Git push<cr>')
map('n', '<leader>gl', '<cmd>Git pull<cr>')
map('n', '<leader>gb', '<cmd>Git blame<cr>')
map('n', '<leader>gd', '<cmd>Gvdiffsplit<cr>')
map('n', '<leader>gr', '<cmd>Gread<cr>')
map('n', '<leader>gw', '<cmd>Gwrite<cr>')
map({ 'n', 'v' }, '<leader>go', gh_browse)
end,
},
{
'lewis6991/gitsigns.nvim',
opts = {
signs = {
add = { text = '██' },
change = { text = '██' },
delete = { text = '▄▄' },
topdelete = { text = '▀▀' },
changedelete = { text = '██' },
},
signs_staged = {
add = { text = '▓▓' },
change = { text = '▓▓' },
delete = { text = '▄▄' },
topdelete = { text = '▀▀' },
changedelete = { text = '▓▓' },
},
signs_staged_enable = true,
{
"lewis6991/gitsigns.nvim",
event = "BufReadPre",
after = function()
require("gitsigns").setup {
signs = {
add = { text = "██" },
change = { text = "██" },
delete = { text = "▄▄" },
topdelete = { text = "▀▀" },
changedelete = { text = "██" },
},
config = function(_, opts)
require('gitsigns').setup(opts)
map('n', ']g', '<cmd>Gitsigns next_hunk<cr>')
map('n', '[g', '<cmd>Gitsigns prev_hunk<cr>')
map('n', '<leader>ghs', '<cmd>Gitsigns stage_hunk<cr>')
map('n', '<leader>ghr', '<cmd>Gitsigns reset_hunk<cr>')
map('n', '<leader>ghp', '<cmd>Gitsigns preview_hunk<cr>')
map('n', '<leader>gB', '<cmd>Gitsigns toggle_current_line_blame<cr>')
end,
},
{
'barrettruth/forge.nvim',
dependencies = { 'ibhagwan/fzf-lua' },
init = function()
vim.g.forge = vim.g.forge or {}
end,
config = function()
map('n', '<c-t>', '<cmd>Forge<cr>', { desc = 'Forge picker' })
end,
},
{
'barrettruth/diffs.nvim',
enabled = true,
init = function()
vim.g.diffs = {
integrations = {
fugitive = {
enabled = true,
horizontal = false,
vertical = false,
},
},
hide_prefix = true,
highlights = {
warn_max_lines = false,
gutter = true,
blend_alpha = 0.5,
intra = { enabled = true },
},
}
end,
signs_staged = {
add = { text = "▓▓" },
change = { text = "▓▓" },
delete = { text = "▄▄" },
topdelete = { text = "▀▀" },
changedelete = { text = "▓▓" },
},
signs_staged_enable = true,
}
map("n", "]g", "<cmd>Gitsigns next_hunk<cr>")
map("n", "[g", "<cmd>Gitsigns prev_hunk<cr>")
map("n", "<leader>ghs", "<cmd>Gitsigns stage_hunk<cr>")
map("n", "<leader>ghr", "<cmd>Gitsigns reset_hunk<cr>")
map("n", "<leader>ghp", "<cmd>Gitsigns preview_hunk<cr>")
map("n", "<leader>gB", "<cmd>Gitsigns toggle_current_line_blame<cr>")
end,
},
{
"barrettruth/forge.nvim",
cmd = "Forge",
before = function() vim.g.forge = vim.g.forge or {} end,
after = function() pcall(vim.cmd.packadd, "fzf-lua") end,
keys = {
{ "<c-t>", "<cmd>Forge<cr>", desc = "Forge picker" },
},
},
{
"barrettruth/diffs.nvim",
before = function()
vim.g.diffs = {
integrations = {
fugitive = {
enabled = true,
horizontal = false,
vertical = false,
},
},
hide_prefix = true,
highlights = {
warn_max_lines = false,
gutter = true,
blend_alpha = 0.5,
intra = { enabled = true },
},
}
end,
},
}

View file

@ -1,4 +1,9 @@
vim.pack.add({
"https://github.com/neovim/nvim-lspconfig",
}, { load = function() end })
return {
'neovim/nvim-lspconfig',
lazy = false,
{
"neovim/nvim-lspconfig",
},
}

View file

@ -1,87 +1,144 @@
return {
{
'barrettruth/canola.nvim',
branch = 'canola',
dependencies = { 'nvim-tree/nvim-web-devicons' },
init = function()
vim.g.canola = {
columns = { 'icon' },
delete = { wipe = false, recursive = true },
hidden = { enabled = false },
keymaps = {
['g?'] = { callback = 'actions.show_help', mode = 'n' },
['<CR>'] = 'actions.select',
['<C-v>'] = { callback = 'actions.select', opts = { vertical = true } },
['<C-x>'] = { callback = 'actions.select', opts = { horizontal = true } },
['<C-p>'] = 'actions.preview',
['<C-c>'] = { callback = 'actions.close', mode = 'n' },
['-'] = { callback = 'actions.parent', mode = 'n' },
['g.'] = { callback = 'actions.toggle_hidden', mode = 'n' },
['<C-t>'] = false,
},
}
map('n', '-', '<cmd>Canola<cr>')
map('n', '<leader>e', '<cmd>Canola<cr>')
vim.pack.add({
"https://github.com/barrettruth/canola.nvim",
"https://github.com/barrettruth/canola-collection",
}, { load = function() end })
local ns = vim.api.nvim_create_namespace('canola_git_trailing')
local symbols = {
M = { 'M', 'DiagnosticWarn' },
A = { 'A', 'DiagnosticOk' },
D = { 'D', 'DiagnosticError' },
R = { 'R', 'DiagnosticWarn' },
['?'] = { '?', 'DiagnosticInfo' },
['!'] = { '!', 'Comment' },
}
local function apply_git_status(buf)
if not vim.api.nvim_buf_is_valid(buf) then return end
vim.api.nvim_buf_clear_namespace(buf, ns, 0, -1)
local ok, canola = pcall(require, 'canola')
if not ok then return end
local dir = canola.get_current_dir(buf)
if not dir then return end
local git_ok, git = pcall(require, 'canola-git')
if not git_ok then return end
local dir_cache = git._cache[dir]
if not dir_cache or not dir_cache.status then return end
local lines = vim.api.nvim_buf_line_count(buf)
for lnum = 0, lines - 1 do
local entry = canola.get_entry_on_line(buf, lnum + 1)
if entry then
local status = dir_cache.status[entry.name]
if status then
local ch = status:sub(1, 1)
if ch == ' ' then ch = status:sub(2, 2) end
local sym = symbols[ch]
if sym then
vim.api.nvim_buf_set_extmark(buf, ns, lnum, 0, {
virt_text = { { ' ' .. sym[1], sym[2] } },
virt_text_pos = 'eol',
invalidate = true,
})
end
end
end
end
end
vim.api.nvim_create_autocmd('User', {
pattern = 'CanolaReadPost',
callback = function(args)
local buf = args.buf
apply_git_status(buf)
vim.defer_fn(function() apply_git_status(buf) end, 500)
end,
})
end,
},
{
'barrettruth/canola-collection',
dependencies = { 'barrettruth/canola.nvim' },
},
local ns = vim.api.nvim_create_namespace("canola_git_trailing")
local symbols = {
M = { "M", "DiagnosticWarn" },
A = { "A", "DiagnosticOk" },
D = { "D", "DiagnosticError" },
R = { "R", "DiagnosticWarn" },
["?"] = { "?", "DiagnosticInfo" },
["!"] = { "!", "Comment" },
}
local function apply_git_status(buf)
if not vim.api.nvim_buf_is_valid(buf) then return end
vim.api.nvim_buf_clear_namespace(buf, ns, 0, -1)
local ok, canola = pcall(require, "canola")
if not ok then return end
local dir = canola.get_current_dir(buf)
if not dir then return end
local git_ok, git = pcall(require, "canola-git")
if not git_ok then return end
local dir_cache = git._cache[dir]
if not dir_cache or not dir_cache.status then return end
local lines = vim.api.nvim_buf_line_count(buf)
for lnum = 0, lines - 1 do
local entry = canola.get_entry_on_line(buf, lnum + 1)
if entry then
local status = dir_cache.status[entry.name]
if status then
local ch = status:sub(1, 1)
if ch == " " then ch = status:sub(2, 2) end
local sym = symbols[ch]
if sym then
vim.api.nvim_buf_set_extmark(buf, ns, lnum, 0, {
virt_text = { { " " .. sym[1], sym[2] } },
virt_text_pos = "eol",
invalidate = true,
})
end
end
end
end
end
return {
{
"barrettruth/canola.nvim",
cmd = "Canola",
before = function()
pcall(vim.cmd.packadd, "nvim-web-devicons")
pcall(vim.cmd.packadd, "nonicons.nvim")
vim.g.canola = {
columns = { "icon" },
hidden = { enabled = false },
highlights = { filename = {}, columns = true },
save = "auto",
extglob = true,
delete = { wipe = false, recursive = true },
float = { border = "single" },
keymaps = {
["g?"] = { callback = "actions.show_help", mode = "n" },
["<CR>"] = "actions.select",
["<C-v>"] = { callback = "actions.select", opts = { vertical = true } },
["<C-x>"] = { callback = "actions.select", opts = { horizontal = true } },
["<C-p>"] = "actions.preview",
["<C-c>"] = { callback = "actions.close", mode = "n" },
["-"] = { callback = "actions.parent", mode = "n" },
["g."] = { callback = "actions.toggle_hidden", mode = "n" },
["<C-t>"] = false,
},
}
end,
after = function()
vim.cmd.packadd("canola-collection")
local augroup = vim.api.nvim_create_augroup("UserCanolaConfig", { clear = true })
local detail_columns = { "git_status", "permissions", "owner", "size", "mtime" }
local base_columns = vim.deepcopy(vim.g.canola.columns or {})
local show_all = false
vim.api.nvim_create_autocmd("FileType", {
group = augroup,
pattern = "canola",
callback = function(args)
local bufnr = args.buf
vim.keymap.set("n", "gC", function()
show_all = not show_all
require("canola").set_columns(show_all and detail_columns or base_columns)
end, {
buffer = bufnr,
desc = "toggle canola columns",
})
vim.keymap.set("n", "gX", function()
local canola = require("canola")
local entry = canola.get_cursor_entry()
local dir = canola.get_current_dir()
if not entry or not dir then return end
vim.ui.input({ prompt = "chmod: ", default = "755" }, function(mode)
if not mode then return end
vim.uv.fs_chmod(dir .. entry.name, tonumber(mode, 8), function(err)
if err then
vim.schedule(function() vim.notify(err, vim.log.levels.ERROR) end)
return
end
vim.schedule(function() require("canola.actions").refresh.callback() end)
end)
end)
end, {
buffer = bufnr,
desc = "chmod entry",
})
end,
})
vim.api.nvim_create_autocmd("User", {
group = augroup,
pattern = "CanolaReadPost",
callback = function(args)
local buf = args.buf
apply_git_status(buf)
vim.defer_fn(function() apply_git_status(buf) end, 500)
end,
})
end,
keys = {
{ "-", "<cmd>Canola<cr>" },
{ "<leader>e", "<cmd>Canola<cr>" },
},
},
}

View file

@ -1,56 +1,71 @@
vim.pack.add({
"https://github.com/nvim-treesitter/nvim-treesitter",
"https://github.com/nvim-treesitter/nvim-treesitter-textobjects",
}, { load = function() end })
vim.api.nvim_create_autocmd("PackChanged", {
callback = function(ev)
local name, kind = ev.data.spec.name, ev.data.kind
if kind == "delete" then return end
if name == "nvim-treesitter" then vim.schedule(function() vim.cmd "TSUpdate all" end) end
end,
})
return {
{
'nvim-treesitter/nvim-treesitter',
build = ':TSUpdate',
dependencies = { 'nvim-treesitter/nvim-treesitter-textobjects' },
config = function()
require('nvim-treesitter-textobjects').setup({
select = {
enable = true,
lookahead = true,
keymaps = {
['af'] = '@function.outer',
['if'] = '@function.inner',
['ac'] = '@class.outer',
['ic'] = '@class.inner',
['aa'] = '@parameter.outer',
['ia'] = '@parameter.inner',
['ai'] = '@conditional.outer',
['ii'] = '@conditional.inner',
['al'] = '@loop.outer',
['il'] = '@loop.inner',
['ab'] = '@block.outer',
['ib'] = '@block.inner',
},
},
move = {
enable = true,
set_jumps = true,
goto_next_start = {
[']f'] = '@function.outer',
[']c'] = '@class.outer',
[']a'] = '@parameter.inner',
},
goto_next_end = {
[']F'] = '@function.outer',
[']C'] = '@class.outer',
},
goto_previous_start = {
['[f'] = '@function.outer',
['[c'] = '@class.outer',
['[a'] = '@parameter.inner',
},
goto_previous_end = {
['[F'] = '@function.outer',
['[C'] = '@class.outer',
},
},
swap = {
enable = true,
swap_next = { ['<leader>sn'] = '@parameter.inner' },
swap_previous = { ['<leader>sp'] = '@parameter.inner' },
},
})
end,
},
{
"nvim-treesitter/nvim-treesitter",
after = function() require("nvim-treesitter").setup { auto_install = true } end,
},
{
"nvim-treesitter/nvim-treesitter-textobjects",
after = function()
require("nvim-treesitter-textobjects").setup {
select = {
enable = true,
lookahead = true,
keymaps = {
["af"] = "@function.outer",
["if"] = "@function.inner",
["ac"] = "@class.outer",
["ic"] = "@class.inner",
["aa"] = "@parameter.outer",
["ia"] = "@parameter.inner",
["ai"] = "@conditional.outer",
["ii"] = "@conditional.inner",
["al"] = "@loop.outer",
["il"] = "@loop.inner",
["ab"] = "@block.outer",
["ib"] = "@block.inner",
},
},
move = {
enable = true,
set_jumps = true,
goto_next_start = {
["]f"] = "@function.outer",
["]c"] = "@class.outer",
["]a"] = "@parameter.inner",
},
goto_next_end = {
["]F"] = "@function.outer",
["]C"] = "@class.outer",
},
goto_previous_start = {
["[f"] = "@function.outer",
["[c"] = "@class.outer",
["[a"] = "@parameter.inner",
},
goto_previous_end = {
["[F"] = "@function.outer",
["[C"] = "@class.outer",
},
},
swap = {
enable = true,
swap_next = { ["<leader>sn"] = "@parameter.inner" },
swap_previous = { ["<leader>sp"] = "@parameter.inner" },
},
}
end,
},
}

View file

@ -1,15 +1,29 @@
vim.pack.add({
"https://github.com/harivansh-afk/cozybox.nvim",
"https://github.com/nvim-lualine/lualine.nvim",
"https://github.com/barrettruth/nonicons.nvim",
"https://github.com/nvim-tree/nvim-web-devicons",
}, { load = function() end })
return {
{
"harivansh-afk/cozybox.nvim",
lazy = false,
priority = 1000,
config = function() require("theme").setup() end,
after = function() require("theme").setup() end,
},
{
"nvim-tree/nvim-web-devicons",
},
{
"barrettruth/nonicons.nvim",
before = function() vim.cmd.packadd "nvim-web-devicons" end,
},
{
"nvim-lualine/lualine.nvim",
dependencies = { "nvim-tree/nvim-web-devicons" },
config = function()
local theme_status = function() return require("theme").statusline_label() end
before = function()
vim.cmd.packadd "nvim-web-devicons"
pcall(vim.cmd.packadd, "nonicons.nvim")
end,
after = function()
local theme = {
normal = {
a = { gui = "bold" },
@ -24,6 +38,7 @@ return {
a = { gui = "bold" },
},
}
require("lualine").setup {
options = {
icons_enabled = false,
@ -42,8 +57,4 @@ return {
}
end,
},
{
"barrettruth/nonicons.nvim",
dependencies = { "nvim-tree/nvim-web-devicons" },
},
}

View file

@ -0,0 +1,96 @@
{
"plugins": {
"blink.cmp": {
"rev": "451168851e8e2466bc97ee3e026c3dcb9141ce07",
"src": "https://github.com/saghen/blink.cmp"
},
"canola-collection": {
"rev": "888ee61c54873e0c57df07d35e38284e23bb978c",
"src": "https://github.com/barrettruth/canola-collection"
},
"canola.nvim": {
"rev": "4a0dd41ca39793342177b2cdb8e784243da5a936",
"src": "https://github.com/barrettruth/canola.nvim"
},
"cozybox.nvim": {
"rev": "be246810d74e3030cc5790685db3b9b8aacda5e3",
"src": "https://github.com/harivansh-afk/cozybox.nvim"
},
"diffs.nvim": {
"rev": "0cb16a0e2384f1d3dd6330f6ea517de8e07aa8e8",
"src": "https://github.com/barrettruth/diffs.nvim"
},
"flash.nvim": {
"rev": "fcea7ff883235d9024dc41e638f164a450c14ca2",
"src": "https://github.com/folke/flash.nvim"
},
"forge.nvim": {
"rev": "0dc433a32c1dac7bdfc313cf73070f03f27b2ef2",
"src": "https://github.com/barrettruth/forge.nvim"
},
"fzf-lua": {
"rev": "bde73a6886b607246095aa59f396de5e0d036890",
"src": "https://github.com/ibhagwan/fzf-lua"
},
"gitsigns.nvim": {
"rev": "50c205548d8b037b7ff6378fca6d21146f0b6161",
"src": "https://github.com/lewis6991/gitsigns.nvim"
},
"lualine.nvim": {
"rev": "47f91c416daef12db467145e16bed5bbfe00add8",
"src": "https://github.com/nvim-lualine/lualine.nvim"
},
"lz.n": {
"rev": "3a696418821fa8e4963a0a59dd1f8d40fedb6824",
"src": "https://github.com/lumen-oss/lz.n"
},
"nonicons.nvim": {
"rev": "2c5fad40a79d80338b49e6fbd3db9b2c1141a4ed",
"src": "https://github.com/barrettruth/nonicons.nvim"
},
"nvim-autopairs": {
"rev": "59bce2eef357189c3305e25bc6dd2d138c1683f5",
"src": "https://github.com/windwp/nvim-autopairs"
},
"nvim-lspconfig": {
"rev": "16812abf0e8d8175155f26143a8504e8253e92b0",
"src": "https://github.com/neovim/nvim-lspconfig"
},
"nvim-surround": {
"rev": "61319d4bd1c5e336e197defa15bd104c51f0fb29",
"src": "https://github.com/kylechui/nvim-surround"
},
"nvim-treesitter": {
"rev": "cf12346a3414fa1b06af75c79faebe7f76df080a",
"src": "https://github.com/nvim-treesitter/nvim-treesitter"
},
"nvim-treesitter-textobjects": {
"rev": "93d60a475f0b08a8eceb99255863977d3a25f310",
"src": "https://github.com/nvim-treesitter/nvim-treesitter-textobjects"
},
"nvim-ufo": {
"rev": "ab3eb124062422d276fae49e0dd63b3ad1062cfc",
"src": "https://github.com/kevinhwang91/nvim-ufo"
},
"nvim-web-devicons": {
"rev": "d7462543c9e366c0d196c7f67a945eaaf5d99414",
"src": "https://github.com/nvim-tree/nvim-web-devicons"
},
"pending.nvim": {
"rev": "e58cf6665b2d12cc63e1fd7a87169a9d2c20f7b5",
"src": "https://github.com/barrettruth/pending.nvim"
},
"preview.nvim": {
"rev": "ddf9b14c7f0fe00bb47833304625b648a97018a6",
"src": "https://github.com/barrettruth/preview.nvim"
},
"promise-async": {
"rev": "119e8961014c9bfaf1487bf3c2a393d254f337e2",
"src": "https://github.com/kevinhwang91/promise-async"
},
"vim-fugitive": {
"rev": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0",
"src": "https://github.com/tpope/vim-fugitive"
}
}
}

View file

@ -1,31 +1,47 @@
local api = vim.api
local augroup = api.nvim_create_augroup('UserAutocmds', { clear = true })
local augroup = api.nvim_create_augroup("UserAutocmds", { clear = true })
api.nvim_create_autocmd('TextYankPost', {
group = augroup,
callback = function()
vim.highlight.on_yank({ higroup = 'Visual', timeout = 200 })
end,
local function maybe_load_canola(bufnr)
local name = api.nvim_buf_get_name(bufnr)
if name == "" or vim.bo[bufnr].filetype == "canola" or vim.fn.isdirectory(name) == 0 then return end
pcall(vim.cmd.packadd, "canola.nvim")
pcall(vim.cmd, "silent keepalt Canola " .. vim.fn.fnameescape(name))
end
api.nvim_create_autocmd("TextYankPost", {
group = augroup,
callback = function() vim.highlight.on_yank { higroup = "Visual", timeout = 200 } end,
})
api.nvim_create_autocmd('BufReadPost', {
group = augroup,
callback = function()
if ({ gitcommit = true, gitrebase = true })[vim.bo.filetype] then
return
end
local mark = api.nvim_buf_get_mark(0, '"')
if mark[1] > 0 and mark[1] <= api.nvim_buf_line_count(0) then
pcall(api.nvim_win_set_cursor, 0, mark)
end
end,
api.nvim_create_autocmd("BufReadPost", {
group = augroup,
callback = function()
if ({ gitcommit = true, gitrebase = true })[vim.bo.filetype] then return end
local mark = api.nvim_buf_get_mark(0, '"')
if mark[1] > 0 and mark[1] <= api.nvim_buf_line_count(0) then pcall(api.nvim_win_set_cursor, 0, mark) end
end,
})
api.nvim_create_autocmd('VimResized', {
group = augroup,
callback = function()
local tab = vim.fn.tabpagenr()
vim.cmd('tabdo wincmd =')
vim.cmd('tabnext ' .. tab)
end,
api.nvim_create_autocmd("BufEnter", {
group = augroup,
nested = true,
callback = function(args)
if vim.v.vim_did_enter == 1 then maybe_load_canola(args.buf) end
end,
})
api.nvim_create_autocmd("VimEnter", {
group = augroup,
nested = true,
callback = function() maybe_load_canola(0) end,
})
api.nvim_create_autocmd("VimResized", {
group = augroup,
callback = function()
local tab = vim.fn.tabpagenr()
vim.cmd "tabdo wincmd ="
vim.cmd("tabnext " .. tab)
end,
})

View file

@ -0,0 +1,42 @@
vim.pack.add({
'https://github.com/tpope/vim-fugitive',
})
local function file_loc()
local root = vim.trim(vim.fn.system('git rev-parse --show-toplevel'))
if vim.v.shell_error ~= 0 or root == '' then
return nil
end
local path = vim.api.nvim_buf_get_name(0)
if path == '' or path:sub(1, #root + 1) ~= root .. '/' then
return nil
end
return ('%s:%d'):format(path:sub(#root + 2), vim.fn.line('.'))
end
local function gh_browse()
if vim.fn.executable('gh') ~= 1 then
vim.notify('gh CLI not found', vim.log.levels.WARN)
return
end
local loc = file_loc()
if loc then
vim.system({ 'gh', 'browse', loc })
else
vim.system({ 'gh', 'browse' })
end
end
map('n', '<C-g>', '<cmd>Git<cr><cmd>only<cr>')
map('n', '<leader>gg', '<cmd>Git<cr><cmd>only<cr>')
map('n', '<leader>gc', '<cmd>Git commit<cr>')
map('n', '<leader>gp', '<cmd>Git push<cr>')
map('n', '<leader>gl', '<cmd>Git pull<cr>')
map('n', '<leader>gb', '<cmd>Git blame<cr>')
map('n', '<leader>gd', '<cmd>Gvdiffsplit<cr>')
map('n', '<leader>gr', '<cmd>Gread<cr>')
map('n', '<leader>gw', '<cmd>Gwrite<cr>')
map({ 'n', 'v' }, '<leader>go', gh_browse)

View file

@ -1,21 +1,20 @@
map('n', '<leader>w', '<cmd>w<cr>')
map('n', '<leader>q', '<cmd>q<cr>')
map('n', '<C-g>', '<cmd>Git<cr><cmd>only<cr>')
map("n", "<leader>w", "<cmd>w<cr>")
map("n", "<leader>q", "<cmd>q<cr>")
map('n', '<Tab>', '<cmd>bnext<cr>')
map('n', '<S-Tab>', '<cmd>bprev<cr>')
map('n', '<leader>x', '<cmd>bdelete<cr>')
map('n', '<leader>b', '<cmd>enew<cr>')
map("n", "<Tab>", "<cmd>bnext<cr>")
map("n", "<S-Tab>", "<cmd>bprev<cr>")
map("n", "<leader>x", "<cmd>bdelete<cr>")
map("n", "<leader>b", "<cmd>enew<cr>")
map('n', '<C-h>', '<C-w>h')
map('n', '<C-j>', '<C-w>j')
map('n', '<C-k>', '<C-w>k')
map('n', '<C-l>', '<C-w>l')
map("n", "<C-h>", "<C-w>h")
map("n", "<C-j>", "<C-w>j")
map("n", "<C-k>", "<C-w>k")
map("n", "<C-l>", "<C-w>l")
map('n', 'J', 'mzJ`z')
map('x', 'x', '"_x')
map('x', 'p', '"_dP')
map('n', '<Esc>', '<cmd>nohlsearch<cr>')
map('n', '<leader>t', '<cmd>setlocal wrap!<cr>')
map("n", "J", "mzJ`z")
map("x", "x", '"_x')
map("x", "p", '"_dP')
map("n", "<Esc>", "<cmd>nohlsearch<cr>")
map("n", "<leader>t", "<cmd>setlocal wrap!<cr>")
map('t', '<Esc>', '<C-\\><C-n>')
map("t", "<Esc>", "<C-\\><C-n>")

60
flake.lock generated
View file

@ -76,6 +76,27 @@
"type": "github"
}
},
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": [
"neovim-nightly",
"nixpkgs"
]
},
"locked": {
"lastModified": 1772408722,
"narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
@ -153,6 +174,44 @@
"type": "github"
}
},
"neovim-nightly": {
"inputs": {
"flake-parts": "flake-parts_2",
"neovim-src": "neovim-src",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1774915815,
"narHash": "sha256-LocQzkSjVS4G0AKMBiEIVdBKCNTMZXQFjQMWFId4Jpg=",
"owner": "nix-community",
"repo": "neovim-nightly-overlay",
"rev": "9001416dc5d0ca24c8e4b5a44bfe7cd6fbeb1dd1",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "neovim-nightly-overlay",
"type": "github"
}
},
"neovim-src": {
"flake": false,
"locked": {
"lastModified": 1774915197,
"narHash": "sha256-yor+eo8CVi7wBp7CjAMQnVoK+m197gsl7MvUzaqicns=",
"owner": "neovim",
"repo": "neovim",
"rev": "dbc4800dda2b0dc3290dc79955f857256e0694e2",
"type": "github"
},
"original": {
"owner": "neovim",
"repo": "neovim",
"type": "github"
}
},
"nix-darwin": {
"inputs": {
"nixpkgs": [
@ -264,6 +323,7 @@
"flake-parts": "flake-parts",
"googleworkspace-cli": "googleworkspace-cli",
"home-manager": "home-manager",
"neovim-nightly": "neovim-nightly",
"nix-darwin": "nix-darwin",
"nix-homebrew": "nix-homebrew",
"nixpkgs": "nixpkgs",

View file

@ -37,6 +37,11 @@
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
neovim-nightly = {
url = "github:nix-community/neovim-nightly-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =

View file

@ -8,10 +8,14 @@ let
nvimConfig = lib.cleanSourceWith {
src = ../config/nvim;
filter =
path: type: builtins.baseNameOf path != ".git" && builtins.baseNameOf path != "lazy-lock.json";
path: type:
let
baseName = builtins.baseNameOf path;
in
baseName != ".git" && baseName != "lazy-lock.json" && baseName != "nvim-pack-lock.json";
};
lazyLockSeed = ../config/nvim/lazy-lock.json;
lazyLockPath = "${config.xdg.stateHome}/nvim/lazy-lock.json";
packLockSeed = ../config/nvim/nvim-pack-lock.json;
packLockPath = "${config.xdg.stateHome}/nvim/nvim-pack-lock.json";
python = pkgs.writeShellScriptBin "python" ''
exec ${pkgs.python3}/bin/python3 "$@"
'';
@ -60,13 +64,15 @@ in
recursive = true;
};
home.activation.seedNvimLazyLock = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
xdg.configFile."nvim/nvim-pack-lock.json".source = config.lib.file.mkOutOfStoreSymlink packLockPath;
home.activation.seedNvimPackLock = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
state_dir="${config.xdg.stateHome}/nvim"
lockfile="${lazyLockPath}"
lockfile="${packLockPath}"
if [ ! -e "$lockfile" ]; then
mkdir -p "$state_dir"
cp ${lazyLockSeed} "$lockfile"
cp ${packLockSeed} "$lockfile"
chmod u+w "$lockfile"
fi
'';

View file

@ -32,6 +32,10 @@
setopt localoptions noshwordsplit
unset prompt_pure_async_render_requested
prompt_pure_set_colors
_codex_pure_default_arrow=$prompt_pure_colors[git:arrow]
_codex_pure_default_success=$prompt_pure_colors[prompt:success]
typeset -g prompt_pure_git_branch_color=$prompt_pure_colors[git:branch]
[[ -n ''${prompt_pure_git_last_dirty_check_timestamp+x} ]] && prompt_pure_git_branch_color=$prompt_pure_colors[git:branch:cached]

View file

@ -9,6 +9,89 @@
}:
let
packageSets = import ../../lib/package-sets.nix { inherit inputs lib pkgs; };
sandboxDomain = "netty.harivan.sh";
forgejoDomain = "git.harivan.sh";
forgejoApiUrl = "http://127.0.0.1:3000";
sandboxAgentPackage = pkgs.callPackage ../../pkgs/sandbox-agent { };
sandboxAgentDir = "/home/${username}/.config/sandbox-agent";
sandboxAgentPath =
packageSets.core
++ packageSets.extras
++ [
pkgs.bubblewrap
pkgs.git
pkgs.nodejs
pkgs.pnpm
sandboxAgentPackage
];
sandboxAgentEnvCheck = pkgs.writeShellScript "sandbox-agent-env-check" ''
[ -f "${sandboxAgentDir}/agent.env" ] && [ -f "${sandboxAgentDir}/public.env" ]
'';
sandboxAgentWrapper = pkgs.writeShellScript "sandbox-agent-public" ''
set -euo pipefail
set -a
. "${sandboxAgentDir}/public.env"
. "${sandboxAgentDir}/agent.env"
set +a
exec sandbox-agent server \
--host 127.0.0.1 \
--port "''${SANDBOX_AGENT_PORT}" \
--token "''${SANDBOX_AGENT_TOKEN}"
'';
sandboxCorsProxy = pkgs.writeText "sandbox-agent-cors-proxy.mjs" ''
import http from "node:http";
const listenHost = "127.0.0.1";
const listenPort = 2468;
const targetHost = "127.0.0.1";
const targetPort = 2470;
function setCorsHeaders(headers, req) {
headers["access-control-allow-origin"] = "*";
headers["access-control-allow-methods"] = "GET,POST,PUT,PATCH,DELETE,OPTIONS";
headers["access-control-allow-headers"] =
req.headers["access-control-request-headers"] || "authorization,content-type";
headers["access-control-max-age"] = "86400";
return headers;
}
const server = http.createServer((req, res) => {
if (req.method === "OPTIONS") {
res.writeHead(204, setCorsHeaders({}, req));
res.end();
return;
}
const proxyReq = http.request(
{
host: targetHost,
port: targetPort,
method: req.method,
path: req.url,
headers: {
...req.headers,
host: `''${targetHost}:''${targetPort}`,
},
},
(proxyRes) => {
res.writeHead(
proxyRes.statusCode || 502,
setCorsHeaders({ ...proxyRes.headers }, req),
);
proxyRes.pipe(res);
},
);
proxyReq.on("error", () => {
res.writeHead(502, setCorsHeaders({ "content-type": "text/plain" }, req));
res.end("Upstream request failed");
});
req.pipe(proxyReq);
});
server.listen(listenPort, listenHost);
'';
in
{
imports = [
@ -103,6 +186,7 @@ in
pkgs.bubblewrap
pkgs.pnpm
pkgs.nodejs
sandboxAgentPackage
];
systemd.tmpfiles.rules = [
@ -122,13 +206,13 @@ in
recommendedTlsSettings = true;
clientMaxBodySize = "512m";
virtualHosts."sandbox.example.dev" = {
virtualHosts.${sandboxDomain} = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://127.0.0.1:2470";
};
virtualHosts."git.example.dev" = {
virtualHosts.${forgejoDomain} = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://127.0.0.1:3000";
@ -150,10 +234,10 @@ in
group = "git";
settings = {
server = {
DOMAIN = "git.example.dev";
ROOT_URL = "https://git.example.dev/";
DOMAIN = forgejoDomain;
ROOT_URL = "https://${forgejoDomain}/";
HTTP_PORT = 3000;
SSH_DOMAIN = "git.example.dev";
SSH_DOMAIN = forgejoDomain;
};
service.DISABLE_REGISTRATION = true;
session.COOKIE_SECURE = true;
@ -177,53 +261,87 @@ in
pkgs.curl
pkgs.jq
pkgs.coreutils
pkgs.gnused
];
script = ''
set -euo pipefail
# Fetch all GitHub repos
api_call() {
local response http_code body
response=$(curl -sS -w "\n%{http_code}" "$@")
http_code=$(printf '%s\n' "$response" | tail -n1)
body=$(printf '%s\n' "$response" | sed '$d')
if [ "$http_code" -ge 400 ]; then
printf '[forgejo-mirror-sync] HTTP %s\n' "$http_code" >&2
printf '%s\n' "$body" >&2
return 1
fi
printf '%s' "$body"
}
gh_user=$(api_call -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/user" | jq -r '.login')
repos_file=$(mktemp)
trap 'rm -f "$repos_file"' EXIT
page=1
repos=""
while true; do
batch=$(curl -sf -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/user/repos?per_page=100&page=$page&affiliation=owner")
count=$(echo "$batch" | jq length)
batch=$(api_call -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/user/repos?per_page=100&page=$page&visibility=all&affiliation=owner,organization_member")
count=$(printf '%s' "$batch" | jq length)
[ "$count" -eq 0 ] && break
repos="$repos$batch"
printf '%s' "$batch" | jq -r '.[] | [.full_name, .clone_url] | @tsv' >> "$repos_file"
page=$((page + 1))
done
echo "$repos" | jq -r '.[].clone_url' | while read -r clone_url; do
repo_name=$(basename "$clone_url" .git)
sort -u "$repos_file" -o "$repos_file"
# Check if mirror already exists in Forgejo
status=$(curl -sf -o /dev/null -w '%{http_code}' \
while IFS=$'\t' read -r full_name clone_url; do
repo_owner="''${full_name%%/*}"
repo_name="''${full_name#*/}"
if [ "$repo_owner" = "$gh_user" ]; then
forgejo_repo_name="$repo_name"
else
forgejo_repo_name="$repo_owner--$repo_name"
fi
status=$(curl -sS -o /dev/null -w '%{http_code}' \
-H "Authorization: token $FORGEJO_TOKEN" \
"$FORGEJO_URL/api/v1/repos/$FORGEJO_OWNER/$repo_name")
"${forgejoApiUrl}/api/v1/repos/$FORGEJO_OWNER/$forgejo_repo_name" || true)
if [ "$status" = "404" ]; then
# Create mirror
curl -sf -X POST \
api_call -X POST \
-H "Authorization: token $FORGEJO_TOKEN" \
-H "Content-Type: application/json" \
"$FORGEJO_URL/api/v1/repos/migrate" \
-d "{
\"clone_addr\": \"$clone_url\",
\"auth_token\": \"$GITHUB_TOKEN\",
\"uid\": $(curl -sf -H "Authorization: token $FORGEJO_TOKEN" "$FORGEJO_URL/api/v1/user" | jq .id),
\"repo_name\": \"$repo_name\",
\"mirror\": true,
\"service\": \"github\"
}"
echo "Created mirror: $repo_name"
"${forgejoApiUrl}/api/v1/repos/migrate" \
-d "$(jq -n \
--arg addr "$clone_url" \
--arg name "$forgejo_repo_name" \
--arg owner "$FORGEJO_OWNER" \
--arg token "$GITHUB_TOKEN" \
'{
clone_addr: $addr,
repo_name: $name,
repo_owner: $owner,
mirror: true,
auth_token: $token,
service: "github"
}')" \
> /dev/null
echo "Created mirror: $full_name -> $FORGEJO_OWNER/$forgejo_repo_name"
else
# Trigger sync on existing mirror
curl -sf -X POST \
if ! api_call -X POST \
-H "Authorization: token $FORGEJO_TOKEN" \
"$FORGEJO_URL/api/v1/repos/$FORGEJO_OWNER/$repo_name/mirror-sync" || true
echo "Synced mirror: $repo_name"
"${forgejoApiUrl}/api/v1/repos/$FORGEJO_OWNER/$forgejo_repo_name/mirror-sync" \
> /dev/null; then
echo "Failed mirror sync: $full_name -> $FORGEJO_OWNER/$forgejo_repo_name" >&2
continue
fi
echo "Synced mirror: $full_name -> $FORGEJO_OWNER/$forgejo_repo_name"
fi
done
done < "$repos_file"
'';
};
@ -239,14 +357,17 @@ in
# --- Sandbox Agent (declarative systemd services) ---
systemd.services.sandbox-agent = {
description = "Sandbox Agent";
after = [ "network.target" ];
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
path = sandboxAgentPath;
serviceConfig = {
Type = "simple";
User = username;
Group = "users";
EnvironmentFile = "/home/${username}/.config/sandbox-agent/agent.env";
ExecStart = "/home/${username}/.local/bin/sandbox-agent";
WorkingDirectory = "/home/${username}";
ExecCondition = sandboxAgentEnvCheck;
ExecStart = sandboxAgentWrapper;
Restart = "on-failure";
RestartSec = 5;
};
@ -255,12 +376,15 @@ in
systemd.services.sandbox-cors-proxy = {
description = "Sandbox CORS Proxy";
after = [ "sandbox-agent.service" ];
requires = [ "sandbox-agent.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
User = username;
Group = "users";
ExecStart = "${pkgs.nodejs}/bin/node /home/${username}/.config/sandbox-agent/cors-proxy.js";
WorkingDirectory = "/home/${username}";
ExecCondition = sandboxAgentEnvCheck;
ExecStart = "${pkgs.nodejs}/bin/node ${sandboxCorsProxy}";
Restart = "on-failure";
RestartSec = 5;
};

17
leverage.md Normal file
View file

@ -0,0 +1,17 @@
# Nix Leveraging
[flake.nix](./flake.nix) is the root lever: one flake, one lockfile, one graph for both macOS and Linux. [modules/hosts/darwin.nix](./modules/hosts/darwin.nix) composes `nix-darwin`, `home-manager`, and `nix-homebrew`; [modules/hosts/netty.nix](./modules/hosts/netty.nix) composes `nixosSystem`, `disko`, and `home-manager`. The point is not “using Nix”; it is collapsing laptop state and VPS state into one reproducible interface.
[modules/nixpkgs.nix](./modules/nixpkgs.nix) and [lib/hosts.nix](./lib/hosts.nix) are the next leverage layer. They define the global `username`, per-host metadata, feature flags, and the `specialArgs` boundary. That removes random `isDarwin` checks from leaf modules and turns host differences into data.
[lib/package-sets.nix](./lib/package-sets.nix), [modules/base.nix](./modules/base.nix), [modules/packages.nix](./modules/packages.nix), and [modules/homebrew.nix](./modules/homebrew.nix) are the package policy. `core`, `extras`, and `fonts` give one place to reason about the machine surface; custom inputs like `googleworkspace-cli`, `claude-code-nix`, `OpenSpec`, `neovim-nightly`, `nix-homebrew`, and `disko` are pinned in [flake.nix](./flake.nix) instead of installed ad hoc.
[home/default.nix](./home/default.nix) and [home/common.nix](./home/common.nix) turn Home Manager into the userland control plane. [home/xdg.nix](./home/xdg.nix) pushes Rust, Go, Node, Python, AWS, Claude, npm, wget, psql, and sqlite into XDG paths; [home/security.nix](./home/security.nix) fixes SSH and GPG permissions on activation; [home/migration.nix](./home/migration.nix) cleans legacy `~/dots` links during the cutover instead of relying on manual cleanup.
[lib/theme.nix](./lib/theme.nix), [home/ghostty.nix](./home/ghostty.nix), [home/tmux.nix](./home/tmux.nix), [home/zsh.nix](./home/zsh.nix), and [home/scripts.nix](./home/scripts.nix) are the ergonomic leverage. One palette renders Ghostty, tmux, fzf, zsh highlights, bat, and delta. The generated `theme` script hot-swaps light/dark across those surfaces. tmux gets session restore, directory-based window names, and a generated session list; zsh gets vi mode, cursor-shape switching, XDG history, prompt theming, and deterministic PATH assembly.
[home/nvim.nix](./home/nvim.nix), [home/codex.nix](./home/codex.nix), [home/claude.nix](./home/claude.nix), and [home/skills.nix](./home/skills.nix) are the agent/editor layer. Neovim is pinned with the nightly overlay and seeded lockfile state; Codex and Claude configs are repo-owned; global skills are installed declaratively via `npx skills add -g` and hash-stamped so the activation only resyncs when the manifest changes.
[scripts/default.nix](./scripts/default.nix), [justfile](./justfile), [scripts/render-bw-shell-secrets.sh](./scripts/render-bw-shell-secrets.sh), and [scripts/restore-bw-files.sh](./scripts/restore-bw-files.sh) are the operational leverage. `writeShellApplication` turns local scripts into managed tools (`ga`, `ghpr`, `gpr`, `ni`, `theme`, `wt`, `wtc`); Bitwarden stays the secret source of truth; `just switch`, `just switch-netty`, and `nixos-anywhere` keep deployment small.
Finally, [hosts/netty/configuration.nix](./hosts/netty/configuration.nix) turns the VPS into a declarative service bundle: static networking, nginx + ACME, Forgejo with GitHub mirror sync, sandbox-agent plus its CORS proxy, bounded GC/journald retention, and a machine that can be rebuilt instead of repaired.

View file

@ -46,6 +46,7 @@ in
);
nixpkgs.config.allowUnfree = true;
nixpkgs.overlays = [ inputs.neovim-nightly.overlays.default ];
programs.zsh.enable = true;
environment.shells = [ pkgs.zsh ];

View file

@ -11,19 +11,16 @@
taps = [
"humanlayer/humanlayer"
"gromgit/fuse"
"mutagen-io/mutagen"
];
brews = [
"gromgit/fuse/sshfs-mac"
"mutagen-io/mutagen/mutagen"
];
casks = [
"cap"
"karabiner-elements"
"macfuse"
"rectangle"
"raycast"
"riptide-beta"

View file

@ -1,173 +0,0 @@
Nix Config - Architecture and Operations Guide
================================================
1. STATIC IP
----------------------------
DHCP on a VPS is dangerous. If the DHCP lease expires or the server
reboots while the DHCP server is unreachable, the machine loses its IP
and becomes inaccessible via SSH.
Static config in hosts/netty/configuration.nix:
- IP: 152.53.195.59/22
- Gateway: 152.53.192.1
- Interface: ens3
- DNS: 1.1.1.1, 8.8.8.8
Always verify the interface name with `ip link show` before changing
network config. Keep VNC console access available as a fallback.
2. HOST ABSTRACTION (hostConfig)
---------------------------------
lib/hosts.nix defines each machine with:
- isDarwin / isLinux / isNixOS booleans
- features map (rust, go, node, python, aws, claude, docker, tex)
modules/nixpkgs.nix passes hostConfig via specialArgs so all home-manager
modules can use it. This replaces scattered `pkgs.stdenv.isDarwin` checks.
To add a new host:
1. Add entry to lib/hosts.nix with all fields
2. Create hosts/<name>/configuration.nix (NixOS) or add darwin case
3. Add host output in modules/hosts/<name>.nix
4. home/default.nix auto-selects modules based on hostConfig flags
home/default.nix is the unified entry point - no separate per-host home
modules needed.
3. XDG COMPLIANCE
------------------
home/xdg.nix sets environment variables so tools respect XDG dirs:
CARGO_HOME -> $XDG_DATA_HOME/cargo
RUSTUP_HOME -> $XDG_DATA_HOME/rustup
GOPATH -> $XDG_DATA_HOME/go
GOMODCACHE -> $XDG_CACHE_HOME/go/mod
NPM_CONFIG_USERCONFIG -> $XDG_CONFIG_HOME/npm/npmrc
NODE_REPL_HISTORY -> $XDG_STATE_HOME/node_repl_history
PYTHON_HISTORY -> $XDG_STATE_HOME/python_history
AWS_CONFIG_FILE -> $XDG_CONFIG_HOME/aws/config
DOCKER_CONFIG -> $XDG_CONFIG_HOME/docker
CLAUDE_CONFIG_DIR -> $XDG_CONFIG_HOME/claude
PSQL_HISTORY -> $XDG_STATE_HOME/psql_history
SQLITE_HISTORY -> $XDG_STATE_HOME/sqlite_history
LESSHISTFILE -> "-" (disabled)
All gated by hostConfig.features so tools only get configured when
the feature flag is set for that host.
4. SECURITY MODULE
-------------------
home/security.nix runs activation scripts on every `home-manager switch`:
- ~/.ssh/ dir: 700, private keys: 600, pub/known_hosts/config: 644
- ~/.gnupg/ dirs: 700, files: 600
No manual chmod needed after restoring keys from Bitwarden.
5. THEME SYSTEM
----------------
lib/theme.nix is the single source of truth for colors.
Shared palette (gruvbox-inspired) used across:
- Ghostty terminal (renderGhostty)
- Tmux status bar (renderTmux)
- fzf color scheme (renderFzf)
- Zsh syntax highlighting (renderZshHighlights)
- Bat (batTheme)
- Git delta (deltaTheme)
Runtime toggle: `theme toggle` writes "light" or "dark" to
$XDG_STATE_HOME/theme/current, then updates Ghostty, tmux, fzf,
and Neovim (via RPC) live. Bat and delta are static at build time.
6. SHELL SETUP
---------------
Pure prompt with gruvbox-colored git integration. Async git status
(no blocking on large repos). Colors defined in lib/theme.nix via
renderPurePrompt - adapts to light/dark mode at runtime.
Vim mode via defaultKeymap = "viins" with cursor shape switching
(beam for insert, block for normal).
History: 50k entries, dedup, ignoreSpace, extended format, stored at
$XDG_STATE_HOME/zsh_history.
zoxide: declarative via programs.zoxide (no manual eval).
PATH: managed via home.sessionPath in xdg.nix + initContent block
in zsh.nix for entries that need conditional logic.
7. SERVER SERVICES (netty)
---------------------------
All in hosts/netty/configuration.nix:
Nginx reverse proxy with ACME SSL:
- sandbox.example.dev -> 127.0.0.1:2470 (sandbox agent)
- git.example.dev -> 127.0.0.1:3000 (forgejo)
Forgejo:
- Self-hosted git, registration disabled
- Runs as git user on port 3000
- GitHub mirror sync via hourly systemd timer
- Requires /etc/forgejo-mirror.env with GITHUB_TOKEN, FORGEJO_TOKEN,
FORGEJO_URL, FORGEJO_OWNER
Sandbox Agent:
- System-level systemd services (not user units)
- sandbox-agent on :2470, env from ~/.config/sandbox-agent/agent.env
- sandbox-cors-proxy on :2468 (Node.js)
- No cloudflared - nginx handles SSL termination
Garbage collection: 3-day retention (vs 14-day on darwin).
Disk guards: min-free 100MB, max-free 1GB.
Journald: 1-week retention.
8. DEPLOY COMMANDS
-------------------
Darwin (local):
just switch
Netty (from mac):
just switch-netty
First-time netty install:
nix run github:nix-community/nixos-anywhere -- \
--flake .#netty --target-host netty --build-on-remote
9. ROLLBACK
-------------
Each phase is a separate git commit.
NixOS rollback:
ssh netty "nixos-rebuild switch --rollback"
Or boot previous generation from GRUB (3 kept).
Darwin rollback:
git revert <commit> && just switch
Home Manager rollback:
home-manager generations # list
home-manager switch --flake .#<host> # after git revert
10. FEATURE FLAGS REFERENCE
-----------------------------
| Feature | darwin | netty |
|---------|--------|-------|
| rust | yes | yes |
| go | yes | yes |
| node | yes | yes |
| python | yes | yes |
| aws | yes | yes |
| claude | yes | yes |
| docker | yes | no |
| tex | yes | no |
Set in lib/hosts.nix, consumed by home/xdg.nix and lib/package-sets.nix.

3832
pkgs/sandbox-agent/Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,38 @@
{
lib,
fetchFromGitHub,
rustPlatform,
}:
rustPlatform.buildRustPackage {
pname = "sandbox-agent";
version = "0.5.0-rc.1";
src = fetchFromGitHub {
owner = "rivet-dev";
repo = "sandbox-agent";
rev = "v0.5.0-rc.1";
hash = "sha256-oeOpWjaQlQZZzwQGts4yJgL3STDCd3Hz2qbOJ4N2HBM=";
};
cargoLock.lockFile = ./Cargo.lock;
prePatch = ''
cp ${./Cargo.lock} Cargo.lock
'';
cargoBuildFlags = [
"-p"
"sandbox-agent"
];
env.SANDBOX_AGENT_SKIP_INSPECTOR = "1";
doCheck = false;
meta = with lib; {
description = "Universal API for coding agents in sandboxes";
homepage = "https://sandboxagent.dev";
license = licenses.asl20;
mainProgram = "sandbox-agent";
platforms = platforms.unix;
};
}