Skip to content

Commit 725400e

Browse files
committed
docs: update keymap to <leader>ck for ClaudeCodeSend command
Change-Id: I209a1d283ac927f3c5bd6c390108d77820ce3e2f Signed-off-by: Thomas Kosiewski <[email protected]>
1 parent 7428bfa commit 725400e

File tree

2 files changed

+61
-54
lines changed

2 files changed

+61
-54
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ return {
9393
config = true, -- or function(_, opts) require("claudecode").setup(opts) end
9494
keys = {
9595
{ "<leader>cc", "<cmd>ClaudeCode<cr>", desc = "Toggle Claude Terminal" },
96-
{ "<leader>cs", "<cmd>ClaudeCodeSend<cr>", desc = "Send to Claude Code" },
96+
{ "<leader>ck", "<cmd>ClaudeCodeSend<cr>", desc = "Send to Claude Code" },
9797
{ "<leader>co", "<cmd>ClaudeCodeOpen<cr>", desc = "Open Claude Terminal" },
9898
{ "<leader>cx", "<cmd>ClaudeCodeClose<cr>", desc = "Close Claude Terminal" },
9999
},
@@ -131,7 +131,7 @@ return {
131131
config = true,
132132
keys = {
133133
{ "<leader>cc", "<cmd>ClaudeCode<cr>", desc = "Toggle Claude Terminal" },
134-
{ "<leader>cs", "<cmd>ClaudeCodeSend<cr>", desc = "Send to Claude Code" },
134+
{ "<leader>ck", "<cmd>ClaudeCodeSend<cr>", desc = "Send to Claude Code" },
135135
{ "<leader>co", "<cmd>ClaudeCodeOpen<cr>", desc = "Open Claude Terminal" },
136136
{ "<leader>cx", "<cmd>ClaudeCodeClose<cr>", desc = "Close Claude Terminal" },
137137
},
@@ -220,7 +220,7 @@ No default keymaps are provided. Add your own in your configuration:
220220

221221
```lua
222222
vim.keymap.set("n", "<leader>cc", "<cmd>ClaudeCode<cr>", { desc = "Toggle Claude Terminal" })
223-
vim.keymap.set({"n", "v"}, "<leader>cs", "<cmd>ClaudeCodeSend<cr>", { desc = "Send to Claude Code" })
223+
vim.keymap.set({"n", "v"}, "<leader>ck", "<cmd>ClaudeCodeSend<cr>", { desc = "Send to Claude Code" })
224224

225225
-- Or more specific maps:
226226
vim.keymap.set("n", "<leader>co", "<cmd>ClaudeCodeOpen<cr>", { desc = "Open Claude Terminal" })

lua/claudecode/selection.lua

Lines changed: 58 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
-- Selection tracking for Claude Code Neovim integration
1+
---
2+
-- Manages selection tracking and communication with the Claude server.
3+
-- This module handles enabling/disabling selection tracking, debouncing updates,
4+
-- determining the current selection (visual or cursor position), and sending
5+
-- updates to the Claude server.
6+
-- @module claudecode.selection
27
local M = {}
38

49
-- Selection state
@@ -9,7 +14,9 @@ M.state = {
914
debounce_ms = 300, -- Default debounce time in milliseconds
1015
}
1116

12-
-- Enable selection tracking
17+
--- Enables selection tracking.
18+
-- Sets up autocommands to monitor cursor movements, mode changes, and text changes.
19+
-- @param server table The server object to use for communication.
1320
function M.enable(server)
1421
if M.state.tracking_enabled then
1522
return
@@ -18,53 +25,49 @@ function M.enable(server)
1825
M.state.tracking_enabled = true
1926
M.server = server
2027

21-
-- Set up autocommands for tracking selections
2228
M._create_autocommands()
2329
end
2430

25-
-- Disable selection tracking
31+
--- Disables selection tracking.
32+
-- Clears autocommands, resets internal state, and stops any active debounce timers.
2633
function M.disable()
2734
if not M.state.tracking_enabled then
2835
return
2936
end
3037

3138
M.state.tracking_enabled = false
3239

33-
-- Remove autocommands
3440
M._clear_autocommands()
3541

36-
-- Clear state
3742
M.state.latest_selection = nil
3843
M.server = nil
3944

40-
-- Clear debounce timer if active
4145
if M.state.debounce_timer then
4246
vim.loop.timer_stop(M.state.debounce_timer)
4347
M.state.debounce_timer = nil
4448
end
4549
end
4650

47-
-- Create autocommands for tracking selections
51+
--- Creates autocommands for tracking selections.
52+
-- Sets up listeners for CursorMoved, CursorMovedI, ModeChanged, and TextChanged events.
53+
-- @local
4854
function M._create_autocommands()
4955
local group = vim.api.nvim_create_augroup("ClaudeCodeSelection", { clear = true })
5056

51-
-- Track selection changes in various modes
5257
vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI" }, {
5358
group = group,
5459
callback = function()
5560
M.on_cursor_moved()
5661
end,
5762
})
5863

59-
-- Track mode changes
6064
vim.api.nvim_create_autocmd("ModeChanged", {
6165
group = group,
6266
callback = function()
6367
M.on_mode_changed()
6468
end,
6569
})
6670

67-
-- Track buffer content changes
6871
vim.api.nvim_create_autocmd("TextChanged", {
6972
group = group,
7073
callback = function()
@@ -73,74 +76,75 @@ function M._create_autocommands()
7376
})
7477
end
7578

76-
-- Clear autocommands
79+
--- Clears the autocommands related to selection tracking.
80+
-- @local
7781
function M._clear_autocommands()
7882
vim.api.nvim_clear_autocmds({ group = "ClaudeCodeSelection" })
7983
end
8084

81-
-- Handle cursor movement events
85+
--- Handles cursor movement events.
86+
-- Triggers a debounced update of the selection.
8287
function M.on_cursor_moved()
8388
-- Debounce the update to avoid sending too many updates
8489
M.debounce_update()
8590
end
8691

87-
-- Handle mode change events
92+
--- Handles mode change events.
93+
-- Triggers an immediate update of the selection.
8894
function M.on_mode_changed()
8995
-- Update selection immediately on mode change
9096
M.update_selection()
9197
end
9298

93-
-- Handle text change events
99+
--- Handles text change events.
100+
-- Triggers a debounced update of the selection.
94101
function M.on_text_changed()
95-
-- Debounce the update
96102
M.debounce_update()
97103
end
98104

99-
-- Debounce selection updates
105+
--- Debounces selection updates.
106+
-- Ensures that `update_selection` is not called too frequently by deferring
107+
-- its execution.
100108
function M.debounce_update()
101-
-- Cancel existing timer if active
102109
if M.state.debounce_timer then
103110
vim.loop.timer_stop(M.state.debounce_timer)
104111
end
105112

106-
-- Create new timer for debounced update
107113
M.state.debounce_timer = vim.defer_fn(function()
108114
M.update_selection()
109115
M.state.debounce_timer = nil
110116
end, M.state.debounce_ms)
111117
end
112118

113-
-- Update the current selection
119+
--- Updates the current selection state.
120+
-- Determines the current selection based on the editor mode (visual or normal)
121+
-- and sends an update to the server if the selection has changed.
114122
function M.update_selection()
115123
if not M.state.tracking_enabled then
116124
return
117125
end
118126

119127
local current_mode = vim.api.nvim_get_mode().mode
120128

121-
-- Get selection based on mode
122129
local current_selection
123130
if current_mode == "v" or current_mode == "V" or current_mode == "\022" then
124-
-- Visual mode selection
125131
current_selection = M.get_visual_selection()
126132
else
127-
-- Normal mode - no selection, just track cursor position
128133
current_selection = M.get_cursor_position()
129134
end
130135

131-
-- Check if selection has changed
132136
if M.has_selection_changed(current_selection) then
133-
-- Store latest selection
134137
M.state.latest_selection = current_selection
135138

136-
-- Send selection update if connected to Claude
137139
if M.server then
138140
M.send_selection_update(current_selection)
139141
end
140142
end
141143
end
142144

143-
-- Get the current visual selection
145+
--- Gets the current visual selection details.
146+
-- @return table|nil A table containing selection text, file path, URL, and
147+
-- start/end positions, or nil if no visual selection exists.
144148
function M.get_visual_selection()
145149
local start_pos = vim.fn.getpos("'<")
146150
local end_pos = vim.fn.getpos("'>")
@@ -153,23 +157,20 @@ function M.get_visual_selection()
153157
local current_buf = vim.api.nvim_get_current_buf()
154158
local file_path = vim.api.nvim_buf_get_name(current_buf)
155159

156-
-- Get selection text
157160
local lines = vim.api.nvim_buf_get_lines(
158161
current_buf,
159162
start_pos[2] - 1, -- 0-indexed line
160163
end_pos[2], -- end line is exclusive
161164
false
162165
)
163166

164-
-- Adjust for column positions
165167
if #lines == 1 then
166168
lines[1] = string.sub(lines[1], start_pos[3], end_pos[3])
167169
else
168170
lines[1] = string.sub(lines[1], start_pos[3])
169171
lines[#lines] = string.sub(lines[#lines], 1, end_pos[3])
170172
end
171173

172-
-- Combine lines
173174
local text = table.concat(lines, "\n")
174175

175176
return {
@@ -184,7 +185,9 @@ function M.get_visual_selection()
184185
}
185186
end
186187

187-
-- Get the current cursor position (no selection)
188+
--- Gets the current cursor position when no visual selection is active.
189+
-- @return table A table containing an empty text, file path, URL, and cursor
190+
-- position as start/end, with isEmpty set to true.
188191
function M.get_cursor_position()
189192
local cursor_pos = vim.api.nvim_win_get_cursor(0)
190193
local current_buf = vim.api.nvim_get_current_buf()
@@ -202,67 +205,71 @@ function M.get_cursor_position()
202205
}
203206
end
204207

205-
-- Check if selection has changed
208+
--- Checks if the selection has changed compared to the latest stored selection.
209+
-- @param new_selection table|nil The new selection object to compare.
210+
-- @return boolean true if the selection has changed, false otherwise.
206211
function M.has_selection_changed(new_selection)
207-
if not M.state.latest_selection then
208-
return true
212+
local old_selection = M.state.latest_selection
213+
214+
if not new_selection then
215+
-- If old selection was also nil, no change. Otherwise (old selection existed), it's a change.
216+
return old_selection ~= nil
209217
end
210218

211-
local current = M.state.latest_selection
219+
if not old_selection then
220+
return true
221+
end
212222

213-
-- Compare file paths
214-
if current.filePath ~= new_selection.filePath then
223+
if old_selection.filePath ~= new_selection.filePath then
215224
return true
216225
end
217226

218-
-- Compare text content
219-
if current.text ~= new_selection.text then
227+
if old_selection.text ~= new_selection.text then
220228
return true
221229
end
222230

223-
-- Compare selection positions
224231
if
225-
current.selection.start.line ~= new_selection.selection.start.line
226-
or current.selection.start.character ~= new_selection.selection.start.character
227-
or current.selection["end"].line ~= new_selection.selection["end"].line
228-
or current.selection["end"].character ~= new_selection.selection["end"].character
232+
old_selection.selection.start.line ~= new_selection.selection.start.line
233+
or old_selection.selection.start.character ~= new_selection.selection.start.character
234+
or old_selection.selection["end"].line ~= new_selection.selection["end"].line
235+
or old_selection.selection["end"].character ~= new_selection.selection["end"].character
229236
then
230237
return true
231238
end
232239

233240
return false
234241
end
235242

236-
-- Send selection update to Claude
243+
--- Sends the selection update to the Claude server.
244+
-- @param selection table The selection object to send.
237245
function M.send_selection_update(selection)
238-
-- Send via WebSocket
239246
M.server.broadcast("selection_changed", selection)
240247
end
241248

242-
-- Get the latest selection
249+
--- Gets the latest recorded selection.
250+
-- @return table|nil The latest selection object, or nil if none recorded.
243251
function M.get_latest_selection()
244252
return M.state.latest_selection
245253
end
246254

247-
-- Send current selection to Claude (user command)
255+
--- Sends the current selection to Claude.
256+
-- This function is typically invoked by a user command. It forces an immediate
257+
-- update and sends the latest selection.
248258
function M.send_current_selection()
249259
if not M.state.tracking_enabled or not M.server then
250260
vim.api.nvim_err_writeln("Claude Code is not running")
251261
return
252262
end
253263

254-
-- Force an immediate selection update
255264
M.update_selection()
256265

257-
-- Get the latest selection
258266
local selection = M.state.latest_selection
259267

260268
if not selection then
261269
vim.api.nvim_err_writeln("No selection available")
262270
return
263271
end
264272

265-
-- Send it to Claude
266273
M.send_selection_update(selection)
267274

268275
vim.api.nvim_echo({ { "Selection sent to Claude", "Normal" } }, false, {})

0 commit comments

Comments
 (0)