My nvim configuration
feat(claude): cancel prompt leadercc
3 files changed, +56 -6
+1-0claude-nvim/lua/claude/init.lua
| @@ -31,6 +31,7 @@ function M.setup(opts) | ||
| 31 | 31 | |
| 32 | 32 | vim.keymap.set("n", "<leader>c", "", { desc = "Claude" }) |
| 33 | 33 | |
| 34 | + vim.keymap.set("n", "<leader>cc", ui.cancel_current, { desc = "Claude: Cancel current prompt" }) | |
| 34 | 35 | vim.keymap.set("n", "<leader>ct", ui.toggle, { desc = "Claude: Toggle panel" }) |
| 35 | 36 | vim.keymap.set("n", "<leader>cn", ui.start_new, { desc = "Claude: New session" }) |
| 36 | 37 | vim.keymap.set("n", "<leader>cr", ui.resume_last, { desc = "Claude: Resume last session" }) |
+35-6claude-nvim/lua/claude/runner.lua
| @@ -332,15 +332,25 @@ function M.send(sid, prompt_text, opts) | ||
| 332 | 332 | log("EXIT", code) |
| 333 | 333 | flush_line_buf(sid) |
| 334 | 334 | st.job = nil |
| 335 | - if st.current_prompt then | |
| 336 | - flush_prompt(sid) | |
| 337 | - end | |
| 338 | - persist_pointer(st) | |
| 339 | - if code ~= 0 then | |
| 335 | + local was_cancelled = st.cancelled | |
| 336 | + st.cancelled = false | |
| 337 | + if was_cancelled then | |
| 338 | + st.current_prompt = nil | |
| 339 | + st.before_files = {} | |
| 340 | 340 | vim.schedule(function() |
| 341 | - vim.notify("claude exited " .. tostring(code), vim.log.levels.ERROR) | |
| 341 | + if ok_u then ui.append_cancelled(sid) end | |
| 342 | 342 | end) |
| 343 | + else | |
| 344 | + if st.current_prompt then | |
| 345 | + flush_prompt(sid) | |
| 346 | + end | |
| 347 | + if code ~= 0 then | |
| 348 | + vim.schedule(function() | |
| 349 | + vim.notify("claude exited " .. tostring(code), vim.log.levels.ERROR) | |
| 350 | + end) | |
| 351 | + end | |
| 343 | 352 | end |
| 353 | + persist_pointer(st) | |
| 344 | 354 | end, |
| 345 | 355 | }) |
| 346 | 356 | if st.job <= 0 then |
| @@ -357,4 +367,23 @@ function M.get_session(sid) | ||
| 357 | 367 | return st and st.session or nil |
| 358 | 368 | end |
| 359 | 369 | |
| 370 | +function M.cancel(sid) | |
| 371 | + local st = active[sid] | |
| 372 | + if not st or not st.job then return false end | |
| 373 | + st.cancelled = true | |
| 374 | + pcall(vim.fn.jobstop, st.job) | |
| 375 | + return true | |
| 376 | +end | |
| 377 | + | |
| 378 | +function M.cancel_active() | |
| 379 | + for sid, st in pairs(active) do | |
| 380 | + if st.job then | |
| 381 | + st.cancelled = true | |
| 382 | + pcall(vim.fn.jobstop, st.job) | |
| 383 | + return sid | |
| 384 | + end | |
| 385 | + end | |
| 386 | + return nil | |
| 387 | +end | |
| 388 | + | |
| 360 | 389 | return M |
+20-0claude-nvim/lua/claude/ui.lua
| @@ -594,6 +594,26 @@ function M.append_separator(sid) | ||
| 594 | 594 | end) |
| 595 | 595 | end |
| 596 | 596 | |
| 597 | +function M.append_cancelled(sid) | |
| 598 | + if sid ~= panel.sid then return end | |
| 599 | + vim.schedule(function() | |
| 600 | + spinner_stop() | |
| 601 | + append_lines({ "", "_— cancelled —_", "", "---", "" }) | |
| 602 | + end) | |
| 603 | +end | |
| 604 | + | |
| 605 | +function M.cancel_current() | |
| 606 | + local runner = require("claude.runner") | |
| 607 | + local sid = panel.sid | |
| 608 | + if not sid then | |
| 609 | + vim.notify("claude: no active session", vim.log.levels.WARN) | |
| 610 | + return | |
| 611 | + end | |
| 612 | + if not runner.cancel(sid) then | |
| 613 | + vim.notify("claude: nothing to cancel", vim.log.levels.WARN) | |
| 614 | + end | |
| 615 | +end | |
| 616 | + | |
| 597 | 617 | function M.append_stderr(sid, line) |
| 598 | 618 | if sid ~= panel.sid then return end |
| 599 | 619 | vim.schedule(function() append_lines({ "_stderr: " .. line .. "_" }) end) |