62
62
63
63
local function find_lines_between_separator (
64
64
lines ,
65
- start_line ,
65
+ current_line ,
66
66
start_pattern ,
67
67
end_pattern ,
68
68
allow_end_of_file
@@ -72,7 +72,6 @@ local function find_lines_between_separator(
72
72
end
73
73
74
74
local line_count = # lines
75
- local current_line = vim .api .nvim_win_get_cursor (0 )[1 ] - start_line
76
75
local separator_line_start = 1
77
76
local separator_line_finish = line_count
78
77
local found_one = false
@@ -385,14 +384,20 @@ end
385
384
386
385
--- Open the chat window.
387
386
--- @param config CopilotChat.config | CopilotChat.config.prompt | nil
388
- --- @param source CopilotChat.config.source ?
389
- function M .open (config , source )
387
+ function M .open (config )
388
+ -- If we are already in chat window, do nothing
389
+ if state .chat :active () then
390
+ return
391
+ end
392
+
390
393
config = vim .tbl_deep_extend (' force' , M .config , config or {})
391
394
state .config = config
392
- state .source = vim .tbl_extend (' keep' , source or {}, {
395
+
396
+ -- Save the source buffer and window (e.g the buffer we are currently asking about)
397
+ state .source = {
393
398
bufnr = vim .api .nvim_get_current_buf (),
394
399
winnr = vim .api .nvim_get_current_win (),
395
- })
400
+ }
396
401
397
402
utils .return_to_normal_mode ()
398
403
state .chat :open (config )
@@ -407,12 +412,11 @@ end
407
412
408
413
--- Toggle the chat window.
409
414
--- @param config CopilotChat.config | nil
410
- --- @param source CopilotChat.config.source ?
411
- function M .toggle (config , source )
415
+ function M .toggle (config )
412
416
if state .chat :visible () then
413
417
M .close ()
414
418
else
415
- M .open (config , source )
419
+ M .open (config )
416
420
end
417
421
end
418
422
@@ -472,11 +476,10 @@ end
472
476
--- Ask a question to the Copilot model.
473
477
--- @param prompt string
474
478
--- @param config CopilotChat.config | CopilotChat.config.prompt | nil
475
- --- @param source CopilotChat.config.source ?
476
- function M .ask (prompt , config , source )
479
+ function M .ask (prompt , config )
477
480
config = vim .tbl_deep_extend (' force' , M .config , config or {})
478
481
vim .diagnostic .reset (vim .api .nvim_create_namespace (' copilot_diagnostics' ))
479
- M .open (config , source )
482
+ M .open (config )
480
483
481
484
prompt = vim .trim (prompt or ' ' )
482
485
if prompt == ' ' then
@@ -489,6 +492,14 @@ function M.ask(prompt, config, source)
489
492
finish (config , nil , true )
490
493
end
491
494
495
+ -- Clear the current input prompt before asking a new question
496
+ local chat_lines = vim .api .nvim_buf_get_lines (state .chat .bufnr , 0 , - 1 , false )
497
+ local _ , start_line , end_line =
498
+ find_lines_between_separator (chat_lines , # chat_lines , M .config .separator .. ' $' , nil , true )
499
+ if # chat_lines == end_line then
500
+ vim .api .nvim_buf_set_lines (state .chat .bufnr , start_line , end_line , false , { ' ' })
501
+ end
502
+
492
503
state .chat :append (prompt )
493
504
state .chat :append (' \n\n ' .. config .answer_header .. config .separator .. ' \n\n ' )
494
505
@@ -884,17 +895,15 @@ function M.setup(config)
884
895
885
896
map_key (M .config .mappings .submit_prompt , bufnr , function ()
886
897
local chat_lines = vim .api .nvim_buf_get_lines (bufnr , 0 , - 1 , false )
887
- local lines , start_line , end_line =
888
- find_lines_between_separator (chat_lines , 0 , M .config .separator .. ' $' , nil , true )
889
- local input = vim .trim (table.concat (lines , ' \n ' ))
890
- if input ~= ' ' then
891
- -- If we are entering the input at the end, replace it
892
- if # chat_lines == end_line then
893
- vim .api .nvim_buf_set_lines (bufnr , start_line , end_line , false , { ' ' })
894
- end
895
-
896
- M .ask (input , state .config , state .source )
897
- end
898
+ local current_line = vim .api .nvim_win_get_cursor (0 )[1 ]
899
+ local lines = find_lines_between_separator (
900
+ chat_lines ,
901
+ current_line ,
902
+ M .config .separator .. ' $' ,
903
+ nil ,
904
+ true
905
+ )
906
+ M .ask (vim .trim (table.concat (lines , ' \n ' )), state .config )
898
907
end )
899
908
900
909
map_key (M .config .mappings .toggle_sticky , bufnr , function ()
@@ -909,7 +918,7 @@ function M.setup(config)
909
918
910
919
local chat_lines = vim .api .nvim_buf_get_lines (bufnr , 0 , - 1 , false )
911
920
local _ , start_line , end_line =
912
- find_lines_between_separator (chat_lines , 0 , M .config .separator .. ' $' , nil , true )
921
+ find_lines_between_separator (chat_lines , cur_line , M .config .separator .. ' $' , nil , true )
913
922
914
923
if vim .startswith (current_line , ' > ' ) then
915
924
return
@@ -942,15 +951,20 @@ function M.setup(config)
942
951
943
952
map_key (M .config .mappings .accept_diff , bufnr , function ()
944
953
local selection = get_selection ()
945
- if not selection .start_row or not selection .end_row then
954
+ if not selection or not selection .start_row or not selection .end_row then
946
955
return
947
956
end
948
957
949
958
local chat_lines = vim .api .nvim_buf_get_lines (bufnr , 0 , - 1 , false )
959
+ local current_line = vim .api .nvim_win_get_cursor (0 )[1 ]
950
960
local section_lines , start_line =
951
- find_lines_between_separator (chat_lines , 0 , M .config .separator .. ' $' )
952
- local lines =
953
- find_lines_between_separator (section_lines , start_line - 1 , ' ^```%w+$' , ' ^```$' )
961
+ find_lines_between_separator (chat_lines , current_line , M .config .separator .. ' $' )
962
+ local lines = find_lines_between_separator (
963
+ section_lines ,
964
+ current_line - start_line - 1 ,
965
+ ' ^```%w+$' ,
966
+ ' ^```$'
967
+ )
954
968
if # lines > 0 then
955
969
vim .api .nvim_buf_set_text (
956
970
state .source .bufnr ,
@@ -965,15 +979,20 @@ function M.setup(config)
965
979
966
980
map_key (M .config .mappings .yank_diff , bufnr , function ()
967
981
local selection = get_selection ()
968
- if not selection . start_row or not selection .end_row then
982
+ if not selection or not selection .lines then
969
983
return
970
984
end
971
985
972
986
local chat_lines = vim .api .nvim_buf_get_lines (bufnr , 0 , - 1 , false )
987
+ local current_line = vim .api .nvim_win_get_cursor (0 )[1 ]
973
988
local section_lines , start_line =
974
- find_lines_between_separator (chat_lines , 0 , M .config .separator .. ' $' )
975
- local lines =
976
- find_lines_between_separator (section_lines , start_line - 1 , ' ^```%w+$' , ' ^```$' )
989
+ find_lines_between_separator (chat_lines , current_line , M .config .separator .. ' $' )
990
+ local lines = find_lines_between_separator (
991
+ section_lines ,
992
+ current_line - start_line - 1 ,
993
+ ' ^```%w+$' ,
994
+ ' ^```$'
995
+ )
977
996
if # lines > 0 then
978
997
local content = table.concat (lines , ' \n ' )
979
998
vim .fn .setreg (M .config .mappings .yank_diff .register , content )
@@ -982,15 +1001,21 @@ function M.setup(config)
982
1001
983
1002
map_key (M .config .mappings .show_diff , bufnr , function ()
984
1003
local selection = get_selection ()
985
- if not selection or not selection .start_row or not selection . end_row then
1004
+ if not selection or not selection .lines then
986
1005
return
987
1006
end
988
1007
989
1008
local chat_lines = vim .api .nvim_buf_get_lines (state .chat .bufnr , 0 , - 1 , false )
1009
+ local current_line = vim .api .nvim_win_get_cursor (0 )[1 ]
990
1010
local section_lines , start_line =
991
- find_lines_between_separator (chat_lines , 0 , M .config .separator .. ' $' )
1011
+ find_lines_between_separator (chat_lines , current_line , M .config .separator .. ' $' )
992
1012
local lines = table.concat (
993
- find_lines_between_separator (section_lines , start_line - 1 , ' ^```%w+$' , ' ^```$' ),
1013
+ find_lines_between_separator (
1014
+ section_lines ,
1015
+ current_line - start_line - 1 ,
1016
+ ' ^```%w+$' ,
1017
+ ' ^```$'
1018
+ ),
994
1019
' \n '
995
1020
)
996
1021
if vim .trim (lines ) ~= ' ' then
@@ -1026,7 +1051,7 @@ function M.setup(config)
1026
1051
1027
1052
map_key (M .config .mappings .show_user_selection , bufnr , function ()
1028
1053
local selection = get_selection ()
1029
- if not selection . start_row or not selection .end_row then
1054
+ if not selection or not selection .lines then
1030
1055
return
1031
1056
end
1032
1057
0 commit comments