My nvim configuration
refactor(claude): leadercp resumes session rather than starting a new one
2 files changed, +63 -13
+4-0claude-nvim/lua/claude/init.lua
| @@ -41,6 +41,10 @@ function M.setup(opts) | ||
| 41 | 41 | vim.keymap.set("v", "<leader>c", function() |
| 42 | 42 | edit.prompt_visual() |
| 43 | 43 | end, { desc = "Claude: Edit selection with prompt" }) |
| 44 | + | |
| 45 | + vim.keymap.set("v", "<leader>p", function() | |
| 46 | + ui.prompt_visual_chat() | |
| 47 | + end, { desc = "Claude: Chat with selection as context" }) | |
| 44 | 48 | end |
| 45 | 49 | |
| 46 | 50 | return M |
+59-13claude-nvim/lua/claude/ui.lua
| @@ -270,6 +270,7 @@ function M.open_input(opts) | ||
| 270 | 270 | end |
| 271 | 271 | local sid = panel.sid |
| 272 | 272 | local return_to = opts.return_to |
| 273 | + local context = opts.context | |
| 273 | 274 | local input_buf = vim.api.nvim_create_buf(false, true) |
| 274 | 275 | vim.bo[input_buf].bufhidden = "wipe" |
| 275 | 276 | vim.bo[input_buf].filetype = "markdown" |
| @@ -284,7 +285,8 @@ function M.open_input(opts) | ||
| 284 | 285 | height = height, |
| 285 | 286 | style = "minimal", |
| 286 | 287 | border = "rounded", |
| 287 | - title = " Claude prompt — <C-s> send <C-c> cancel ", | |
| 288 | + title = context and " Claude prompt (with context) — <C-s> send <C-c> cancel " | |
| 289 | + or " Claude prompt — <C-s> send <C-c> cancel ", | |
| 288 | 290 | title_pos = "center", |
| 289 | 291 | }) |
| 290 | 292 | vim.cmd("startinsert") |
| @@ -307,6 +309,9 @@ function M.open_input(opts) | ||
| 307 | 309 | local text = table.concat(lines, "\n") |
| 308 | 310 | close() |
| 309 | 311 | if text:match("^%s*$") then return end |
| 312 | + if context and context ~= "" then | |
| 313 | + text = context .. "\n\n" .. text | |
| 314 | + end | |
| 310 | 315 | local runner = require("claude.runner") |
| 311 | 316 | local ok, err = runner.send(sid, text) |
| 312 | 317 | if not ok then |
| @@ -320,13 +325,55 @@ function M.open_input(opts) | ||
| 320 | 325 | vim.keymap.set("n", "<Esc>", close, km) |
| 321 | 326 | end |
| 322 | 327 | |
| 328 | +local function capture_visual_selection() | |
| 329 | + local old_reg = vim.fn.getreg('"') | |
| 330 | + local old_regtype = vim.fn.getregtype('"') | |
| 331 | + vim.cmd('noautocmd normal! gv"vy') | |
| 332 | + local sel = vim.fn.getreg("v") | |
| 333 | + vim.fn.setreg('"', old_reg, old_regtype) | |
| 334 | + return sel or "" | |
| 335 | +end | |
| 336 | + | |
| 337 | +function M.prompt_visual_chat() | |
| 338 | + local origin_buf = vim.api.nvim_get_current_buf() | |
| 339 | + local origin_win = vim.api.nvim_get_current_win() | |
| 340 | + local sel = capture_visual_selection() | |
| 341 | + if sel == "" then | |
| 342 | + vim.notify("claude: empty selection", vim.log.levels.WARN) | |
| 343 | + return | |
| 344 | + end | |
| 345 | + local s = vim.fn.getpos("'<") | |
| 346 | + local e = vim.fn.getpos("'>") | |
| 347 | + local fname = vim.api.nvim_buf_get_name(origin_buf) | |
| 348 | + local rel = fname ~= "" and vim.fn.fnamemodify(fname, ":.") or "[No Name]" | |
| 349 | + local ft = vim.bo[origin_buf].filetype or "" | |
| 350 | + local context = string.format( | |
| 351 | + "<context>\n%s:%d-%d\n```%s\n%s\n```\n</context>", | |
| 352 | + rel, s[2], e[2], ft, sel | |
| 353 | + ) | |
| 354 | + | |
| 355 | + if not M.is_open() then | |
| 356 | + if panel.sid then | |
| 357 | + M.open_panel() | |
| 358 | + else | |
| 359 | + M.start_new() | |
| 360 | + end | |
| 361 | + end | |
| 362 | + M.open_input({ return_to = origin_win, context = context }) | |
| 363 | +end | |
| 364 | + | |
| 323 | 365 | function M.open_prompt_keep_focus() |
| 324 | 366 | local origin = vim.api.nvim_get_current_win() |
| 325 | 367 | if not M.is_open() then |
| 326 | 368 | if panel.sid then |
| 327 | 369 | M.open_panel() |
| 328 | 370 | else |
| 329 | - M.start_new() | |
| 371 | + local store = require("claude.store") | |
| 372 | + if store.read_pointer() then | |
| 373 | + M.resume_last() | |
| 374 | + else | |
| 375 | + M.start_new() | |
| 376 | + end | |
| 330 | 377 | end |
| 331 | 378 | end |
| 332 | 379 | M.open_input({ return_to = origin }) |
| @@ -336,17 +383,16 @@ end | ||
| 336 | 383 | |
| 337 | 384 | function M.append_user_prompt(sid, text) |
| 338 | 385 | if sid ~= panel.sid then return end |
| 339 | - vim.schedule(function() | |
| 340 | - local lines = { "## You", "" } | |
| 341 | - for _, l in ipairs(vim.split(text, "\n", { plain = true })) do | |
| 342 | - table.insert(lines, l) | |
| 343 | - end | |
| 344 | - table.insert(lines, "") | |
| 345 | - table.insert(lines, "## Claude") | |
| 346 | - table.insert(lines, "") | |
| 347 | - append_lines(lines) | |
| 348 | - spinner_start() | |
| 349 | - end) | |
| 386 | + local lines = { "## You", "" } | |
| 387 | + for _, l in ipairs(vim.split(text, "\n", { plain = true })) do | |
| 388 | + table.insert(lines, l) | |
| 389 | + end | |
| 390 | + table.insert(lines, "") | |
| 391 | + table.insert(lines, "## Claude") | |
| 392 | + table.insert(lines, "") | |
| 393 | + append_lines(lines) | |
| 394 | + spinner_start() | |
| 395 | + vim.cmd("redraw") | |
| 350 | 396 | end |
| 351 | 397 | |
| 352 | 398 | function M.append_assistant_text(sid, text) |