diff --git a/modules/cli/home.nix b/modules/cli/home.nix index be55f6f..7d575a0 100644 --- a/modules/cli/home.nix +++ b/modules/cli/home.nix @@ -120,6 +120,7 @@ - NEVER EVER commit ; don't talk about commiting we do not care. Do not run `git commit` (or `jj commit`) and never push changes under any circumstances unless the user explicitly asks you to commit in that message. - Do not edit run git commands to write/checkout/fetch/whatever. Use `jj` if you need but you should not touch the git/jj state in most cases. - when fetching github content/pr/issues/wha, use the `gh` cli. + - NEVER ever create issues/pr/write on github. ''; xdg.configFile."claude/keybindings.json".text = builtins.toJSON { diff --git a/nvim/default.nix b/nvim/default.nix index cb4b6ce..97a916b 100644 --- a/nvim/default.nix +++ b/nvim/default.nix @@ -84,7 +84,7 @@ in oil-nvim harpoon2 - gitsigns-nvim + mini-diff jj-nvim vim-fugitive vim-rhubarb diff --git a/nvim/lua/jj-diff.lua b/nvim/lua/jj-diff.lua new file mode 100644 index 0000000..c43e7eb --- /dev/null +++ b/nvim/lua/jj-diff.lua @@ -0,0 +1,102 @@ +-- mini.diff source backed by jj. + +local M = {} + +local function resolve(buf_id) + local name = vim.api.nvim_buf_get_name(buf_id) + if name == "" then + return nil + end + + local change_id, rel = name:match("^jj://([^/]+)/(.+)$") + if change_id then + -- The path in the uri is repo-relative; jj resolves it from anywhere in + -- the repo, so run from the current working directory. + return { rev = change_id .. "-", file = rel, cwd = vim.fn.getcwd() } + end + + local path = vim.uv.fs_realpath(name) + if path == nil then + return nil + end + return { rev = "@-", file = path, cwd = vim.fs.dirname(path) } +end + +local function set_ref_text(buf_id) + if not vim.api.nvim_buf_is_valid(buf_id) then + return + end + local target = resolve(buf_id) + if target == nil then + return + end + vim.system( + { "jj", "file", "show", "--ignore-working-copy", "-r", target.rev, target.file }, + { cwd = target.cwd, text = true }, + vim.schedule_wrap(function(obj) + if not vim.api.nvim_buf_is_valid(buf_id) then + return + end + local text = obj.code == 0 and obj.stdout or "" + pcall(MiniDiff.set_ref_text, buf_id, text) + end) + ) +end + +local function group_name(buf_id) + return "MiniDiffSourceJj" .. buf_id +end + +local function attach(buf_id) + local target = resolve(buf_id) + if target == nil then + return false + end + + if vim.fs.root(target.cwd, ".jj") == nil then + return false + end + + local group = vim.api.nvim_create_augroup(group_name(buf_id), { clear = true }) + vim.api.nvim_create_autocmd({ "BufWritePost", "BufReadPost", "BufEnter", "FocusGained", "FileChangedShellPost" }, { + group = group, + buffer = buf_id, + desc = "Refresh jj diff reference", + callback = function() + set_ref_text(buf_id) + end, + }) + + set_ref_text(buf_id) +end + +local function detach(buf_id) + pcall(vim.api.nvim_del_augroup_by_name, group_name(buf_id)) +end + +M.source = { + name = "jj", + attach = attach, + detach = detach, +} + +-- support jj:// buffers +function M.setup() + local group = vim.api.nvim_create_augroup("MiniDiffJjRevisionBuffers", { clear = true }) + vim.api.nvim_create_autocmd({ "BufWinEnter", "BufReadPost" }, { + group = group, + desc = "Enable mini.diff on jj revision buffers", + callback = function(ev) + vim.schedule(function() + if not vim.api.nvim_buf_is_valid(ev.buf) then + return + end + if vim.api.nvim_buf_get_name(ev.buf):match("^jj://") then + pcall(require("mini.diff").enable, ev.buf) + end + end) + end, + }) +end + +return M diff --git a/nvim/lua/plugins/git.lua b/nvim/lua/plugins/git.lua index a27d20f..eb19e0c 100644 --- a/nvim/lua/plugins/git.lua +++ b/nvim/lua/plugins/git.lua @@ -24,43 +24,46 @@ vim.api.nvim_create_autocmd("FileType", { return { { - "gitsigns.nvim", + "mini.diff", event = { "BufReadPost", "BufWritePost", "BufNewFile" }, opts = { - signs = { - add = { text = "▕" }, - change = { text = "▕" }, - changedelete = { text = "▕" }, - untracked = { text = "▕" }, + view = { + style = "sign", + signs = { add = "▕", change = "▕", delete = "▕" }, }, - signs_staged = { - add = { text = "▕" }, - change = { text = "▕" }, - changedelete = { text = "▕" }, - untracked = { text = "▕" }, + source = { + require("jj-diff").source, + require("mini.diff").gen_source.git(), + }, + mappings = { + apply = "", + reset = "gH", + textobject = "ih", + goto_first = "[H", + goto_prev = "[h", + goto_next = "]h", + goto_last = "]H", }, - on_attach = function(buffer) - local gs = require("gitsigns") - local function map(mode, l, r, desc) - vim.keymap.set(mode, l, r, { buffer = buffer, desc = desc }) - end - - map('n', ']h', function() gs.nav_hunk("next", { target = "all" }) end, "Next Hunk") - map('n', '[h', function() gs.nav_hunk("prev", { target = "all" }) end, "Prev Hunk") - - map({ "n", "v" }, "ha", gs.stage_hunk, "Add Hunk") - map({ "n", "v" }, "hr", gs.reset_hunk, "Reset Hunk") - map("n", "hp", gs.preview_hunk, "Preview Hunk") - - map("n", "ga", gs.stage_buffer, "Add buffer") - map("n", "gR", gs.reset_buffer, "Reset Buffer") - - map({ "o", "x" }, "ih", gs.select_hunk, "Git Select Hunk") - map({ "o", "x" }, "ah", gs.select_hunk, "Git Select Hunk") - end, }, after = function(plug) - require("gitsigns").setup(plug.opts) + local diff = require("mini.diff") + diff.setup(plug.opts) + require("jj-diff").setup() + + local function map(mode, l, r, desc) + vim.keymap.set(mode, l, r, { desc = desc }) + end + + map("n", "hr", function() + local line = vim.fn.line(".") + diff.do_hunks(0, "reset", { line_start = line, line_end = line }) + end, "Reset Hunk") + map("x", "hr", function() + diff.do_hunks(0, "reset", { line_start = vim.fn.line("v"), line_end = vim.fn.line(".") }) + end, "Reset Hunk") + + map("n", "hp", function() diff.toggle_overlay(0) end, "Preview Hunk (overlay)") + map("n", "gR", function() diff.do_hunks(0, "reset") end, "Reset Buffer") end, }, diff --git a/nvim/lua/plugins/statuscol.lua b/nvim/lua/plugins/statuscol.lua index 3622330..447b3c3 100644 --- a/nvim/lua/plugins/statuscol.lua +++ b/nvim/lua/plugins/statuscol.lua @@ -17,7 +17,7 @@ return { }, { text = { builtin.lnumfunc }, click = "v:lua.ScLa", }, { - sign = { namespace = { "gitsign" }, maxwidth = 1, colwidth = 1 }, + sign = { namespace = { "MiniDiffViz" }, maxwidth = 1, colwidth = 1 }, click = "v:lua.ScSa" }, }