Skip to content

Commit edccb60

Browse files
committed
feat: add line range support to ClaudeCodeAdd command
- Add optional start-line and end-line arguments to ClaudeCodeAdd command - Convert 1-indexed user input to 0-indexed for Claude compatibility - Add comprehensive validation for line numbers (positive, start <= end) - Ignore line numbers for directories with debug logging - Remove redundant vim.notify calls (logger handles notifications) - Update README with line range syntax and examples - Add extensive test coverage for all line range scenarios - Clean up chatty comments that describe obvious operations Change-Id: Ied866de821628c6f274faac3c82e527a0eaf46e1 Signed-off-by: Thomas Kosiewski <[email protected]>
1 parent f5a87a9 commit edccb60

File tree

3 files changed

+266
-37
lines changed

3 files changed

+266
-37
lines changed

README.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ That's it! For more configuration options, see [Advanced Setup](#advanced-setup)
8181
- `:ClaudeCode` - Toggle the Claude Code terminal window
8282
- `:ClaudeCodeSend` - Send current visual selection to Claude, or add files from tree explorer
8383
- `:ClaudeCodeTreeAdd` - Add selected file(s) from tree explorer to Claude context (also available via ClaudeCodeSend)
84-
- `:ClaudeCodeAdd <file-path>` - Add a specific file or directory to Claude context by path
84+
- `:ClaudeCodeAdd <file-path> [start-line] [end-line]` - Add a specific file or directory to Claude context by path with optional line range
8585

8686
### Tree Integration
8787

@@ -101,35 +101,44 @@ This allows you to quickly add entire files to Claude's context for review, refa
101101

102102
### Direct File Addition
103103

104-
The `:ClaudeCodeAdd` command allows you to add files or directories directly by path:
104+
The `:ClaudeCodeAdd` command allows you to add files or directories directly by path, with optional line range specification:
105105

106106
```vim
107107
:ClaudeCodeAdd src/main.lua
108108
:ClaudeCodeAdd ~/projects/myproject/
109109
:ClaudeCodeAdd ./README.md
110+
:ClaudeCodeAdd src/main.lua 50 100 " Lines 50-100 only
111+
:ClaudeCodeAdd config.lua 25 " From line 25 to end of file
110112
```
111113

112114
#### Features
113115

114116
- **Path completion**: Tab completion for file and directory paths
115117
- **Path expansion**: Supports `~` for home directory and relative paths
116-
- **Validation**: Checks that files and directories exist before adding
118+
- **Line range support**: Optionally specify start and end lines for files (ignored for directories)
119+
- **Validation**: Checks that files and directories exist before adding, validates line numbers
117120
- **Flexible**: Works with both individual files and entire directories
118121

119122
#### Examples
120123

121124
```vim
122-
" Add a specific file
125+
" Add entire files
123126
:ClaudeCodeAdd src/components/Header.tsx
127+
:ClaudeCodeAdd ~/.config/nvim/init.lua
124128
125-
" Add an entire directory
129+
" Add entire directories (line numbers ignored)
126130
:ClaudeCodeAdd tests/
131+
:ClaudeCodeAdd ../other-project/
127132
128-
" Add file in home directory
129-
:ClaudeCodeAdd ~/.config/nvim/init.lua
133+
" Add specific line ranges
134+
:ClaudeCodeAdd src/main.lua 50 100 " Lines 50 through 100
135+
:ClaudeCodeAdd config.lua 25 " From line 25 to end of file
136+
:ClaudeCodeAdd utils.py 1 50 " First 50 lines
137+
:ClaudeCodeAdd README.md 10 20 " Just lines 10-20
130138
131-
" Add relative path
132-
:ClaudeCodeAdd ../other-project/package.json
139+
" Path expansion works with line ranges
140+
:ClaudeCodeAdd ~/project/src/app.js 100 200
141+
:ClaudeCodeAdd ./relative/path.lua 30
133142
```
134143

135144
## How It Works

lua/claudecode/init.lua

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -273,25 +273,38 @@ function M._create_commands()
273273
---@param file_path string The file path to broadcast
274274
---@return boolean success Whether the broadcast was successful
275275
---@return string|nil error Error message if broadcast failed
276-
local function broadcast_at_mention(file_path)
276+
local function broadcast_at_mention(file_path, start_line, end_line)
277277
if not M.state.server then
278278
return false, "Claude Code integration is not running"
279279
end
280280

281281
local formatted_path, is_directory = format_path_for_at_mention(file_path)
282282

283+
if is_directory and (start_line or end_line) then
284+
logger.debug("command", "Line numbers ignored for directory: " .. formatted_path)
285+
start_line = nil
286+
end_line = nil
287+
end
288+
283289
local params = {
284290
filePath = formatted_path,
285-
lineStart = nil,
286-
lineEnd = nil,
291+
lineStart = start_line,
292+
lineEnd = end_line,
287293
}
288294

289295
local broadcast_success = M.state.server.broadcast("at_mentioned", params)
290296
if broadcast_success then
291-
logger.debug(
292-
"command",
293-
"Broadcast success: Added " .. (is_directory and "directory" or "file") .. " " .. formatted_path
294-
)
297+
local message = "Broadcast success: Added " .. (is_directory and "directory" or "file") .. " " .. formatted_path
298+
if not is_directory and (start_line or end_line) then
299+
local range_info = ""
300+
if start_line and end_line then
301+
range_info = " (lines " .. start_line .. "-" .. end_line .. ")"
302+
elseif start_line then
303+
range_info = " (from line " .. start_line .. ")"
304+
end
305+
message = message .. range_info
306+
end
307+
logger.debug("command", message)
295308
return true, nil
296309
else
297310
local error_msg = "Failed to broadcast " .. (is_directory and "directory" or "file") .. " " .. formatted_path
@@ -545,35 +558,83 @@ function M._create_commands()
545558
vim.api.nvim_create_user_command("ClaudeCodeAdd", function(opts)
546559
if not M.state.server then
547560
logger.error("command", "ClaudeCodeAdd: Claude Code integration is not running.")
548-
vim.notify("Claude Code integration is not running", vim.log.levels.ERROR)
549561
return
550562
end
551563

552-
local file_path = opts.args
553-
if not file_path or file_path == "" then
564+
if not opts.args or opts.args == "" then
554565
logger.error("command", "ClaudeCodeAdd: No file path provided")
555-
vim.notify("ClaudeCodeAdd: Please provide a file path", vim.log.levels.ERROR)
566+
return
567+
end
568+
569+
local args = vim.split(opts.args, "%s+")
570+
local file_path = args[1]
571+
local start_line = args[2] and tonumber(args[2]) or nil
572+
local end_line = args[3] and tonumber(args[3]) or nil
573+
574+
if #args > 3 then
575+
logger.error(
576+
"command",
577+
"ClaudeCodeAdd: Too many arguments. Usage: ClaudeCodeAdd <file-path> [start-line] [end-line]"
578+
)
579+
return
580+
end
581+
582+
if args[2] and not start_line then
583+
logger.error("command", "ClaudeCodeAdd: Invalid start line number: " .. args[2])
584+
return
585+
end
586+
587+
if args[3] and not end_line then
588+
logger.error("command", "ClaudeCodeAdd: Invalid end line number: " .. args[3])
589+
return
590+
end
591+
592+
if start_line and start_line < 1 then
593+
logger.error("command", "ClaudeCodeAdd: Start line must be positive: " .. start_line)
594+
return
595+
end
596+
597+
if end_line and end_line < 1 then
598+
logger.error("command", "ClaudeCodeAdd: End line must be positive: " .. end_line)
599+
return
600+
end
601+
602+
if start_line and end_line and start_line > end_line then
603+
logger.error(
604+
"command",
605+
"ClaudeCodeAdd: Start line (" .. start_line .. ") must be <= end line (" .. end_line .. ")"
606+
)
556607
return
557608
end
558609

559610
file_path = vim.fn.expand(file_path)
560611
if vim.fn.filereadable(file_path) == 0 and vim.fn.isdirectory(file_path) == 0 then
561612
logger.error("command", "ClaudeCodeAdd: File or directory does not exist: " .. file_path)
562-
vim.notify("ClaudeCodeAdd: File or directory does not exist: " .. file_path, vim.log.levels.ERROR)
563613
return
564614
end
565615

566-
local success, error_msg = broadcast_at_mention(file_path)
616+
-- Convert 1-indexed user input to 0-indexed for Claude
617+
local claude_start_line = start_line and (start_line - 1) or nil
618+
local claude_end_line = end_line and (end_line - 1) or nil
619+
620+
local success, error_msg = broadcast_at_mention(file_path, claude_start_line, claude_end_line)
567621
if not success then
568622
logger.error("command", "ClaudeCodeAdd: " .. (error_msg or "Failed to add file"))
569-
vim.notify("ClaudeCodeAdd: " .. (error_msg or "Failed to add file"), vim.log.levels.ERROR)
570623
else
571-
logger.debug("command", "ClaudeCodeAdd: Successfully added " .. file_path)
624+
local message = "ClaudeCodeAdd: Successfully added " .. file_path
625+
if start_line or end_line then
626+
if start_line and end_line then
627+
message = message .. " (lines " .. start_line .. "-" .. end_line .. ")"
628+
elseif start_line then
629+
message = message .. " (from line " .. start_line .. ")"
630+
end
631+
end
632+
logger.debug("command", message)
572633
end
573634
end, {
574-
nargs = 1,
635+
nargs = "+",
575636
complete = "file",
576-
desc = "Add specified file or directory to Claude Code context",
637+
desc = "Add specified file or directory to Claude Code context with optional line range",
577638
})
578639

579640
local terminal_ok, terminal = pcall(require, "claudecode.terminal")

0 commit comments

Comments
 (0)