@@ -573,25 +573,91 @@ function M.send_current_selection()
573
573
vim .api .nvim_echo ({ { " Selection sent to Claude" , " Normal" } }, false , {})
574
574
end
575
575
576
+ --- Gets selection from range marks (e.g., when using :'<,'> commands)
577
+ -- @param line1 number The start line (1-indexed)
578
+ -- @param line2 number The end line (1-indexed)
579
+ -- @return table|nil A table containing selection text, file path, URL, and
580
+ -- start/end positions, or nil if invalid range
581
+ function M .get_range_selection (line1 , line2 )
582
+ if not line1 or not line2 or line1 < 1 or line2 < 1 or line1 > line2 then
583
+ return nil
584
+ end
585
+
586
+ local current_buf = vim .api .nvim_get_current_buf ()
587
+ local file_path = vim .api .nvim_buf_get_name (current_buf )
588
+
589
+ -- Get the total number of lines in the buffer
590
+ local total_lines = vim .api .nvim_buf_line_count (current_buf )
591
+
592
+ -- Ensure line2 doesn't exceed buffer bounds
593
+ if line2 > total_lines then
594
+ line2 = total_lines
595
+ end
596
+
597
+ local lines_content = vim .api .nvim_buf_get_lines (
598
+ current_buf ,
599
+ line1 - 1 , -- Convert to 0-indexed
600
+ line2 , -- nvim_buf_get_lines end is exclusive
601
+ false
602
+ )
603
+
604
+ if # lines_content == 0 then
605
+ return nil
606
+ end
607
+
608
+ local final_text = table.concat (lines_content , " \n " )
609
+
610
+ -- For range selections, we treat them as linewise
611
+ local lsp_start_line = line1 - 1 -- Convert to 0-indexed
612
+ local lsp_end_line = line2 - 1
613
+ local lsp_start_char = 0
614
+ local lsp_end_char = # lines_content [# lines_content ]
615
+
616
+ return {
617
+ text = final_text or " " ,
618
+ filePath = file_path ,
619
+ fileUrl = " file://" .. file_path ,
620
+ selection = {
621
+ start = { line = lsp_start_line , character = lsp_start_char },
622
+ [" end" ] = { line = lsp_end_line , character = lsp_end_char },
623
+ isEmpty = (not final_text or # final_text == 0 ),
624
+ },
625
+ }
626
+ end
627
+
576
628
--- Sends an at_mentioned notification for the current visual selection.
577
- function M .send_at_mention_for_visual_selection ()
629
+ -- @param line1 number|nil Optional start line for range-based selection
630
+ -- @param line2 number|nil Optional end line for range-based selection
631
+ function M .send_at_mention_for_visual_selection (line1 , line2 )
578
632
if not M .state .tracking_enabled or not M .server then
579
633
logger .error (" selection" , " Claude Code is not running or server not available for send_at_mention." )
580
634
return false
581
635
end
582
636
583
- local sel_to_send = M . state . latest_selection
637
+ local sel_to_send
584
638
585
- if not sel_to_send or sel_to_send .selection .isEmpty then
586
- -- Fallback: try to get current visual selection directly.
587
- -- This helps if latest_selection was demoted or command was too fast.
588
- local current_visual = M .get_visual_selection ()
589
- if current_visual and not current_visual .selection .isEmpty then
590
- sel_to_send = current_visual
591
- else
592
- logger .warn (" selection" , " No visual selection to send as at-mention." )
639
+ -- If range parameters are provided, use them (for :'<,'> commands)
640
+ if line1 and line2 then
641
+ sel_to_send = M .get_range_selection (line1 , line2 )
642
+ if not sel_to_send or sel_to_send .selection .isEmpty then
643
+ logger .warn (" selection" , " Invalid range selection to send as at-mention." )
593
644
return false
594
645
end
646
+ else
647
+ -- Use existing logic for visual mode or tracked selection
648
+ sel_to_send = M .state .latest_selection
649
+
650
+ if not sel_to_send or sel_to_send .selection .isEmpty then
651
+ -- Fallback: try to get current visual selection directly.
652
+ -- This helps if latest_selection was demoted or command was too fast.
653
+ local current_visual = M .get_visual_selection ()
654
+ if current_visual and not current_visual .selection .isEmpty then
655
+ sel_to_send = current_visual
656
+ else
657
+ logger .warn (" selection" , " No visual selection to send as at-mention." )
658
+ return false
659
+ end
660
+ end
595
661
end
596
662
597
663
-- Sanity check: ensure the selection is for the current buffer
0 commit comments