@@ -92,14 +92,21 @@ function M.setup(_server)
9292		end 
9393
9494		if  bindings .accept  and  bindings .accept  ~=  " "  then 
95- 			vim .keymap .set (" i"  , bindings .accept , M .accept , { silent  =  true , expr  =  true , script  =  true , nowait  =  true  })
95+ 			vim .keymap .set (" i"  , bindings .accept , function ()
96+ 					if  not  M .has_suggestions () then  return  bindings .accept  end 
97+ 					M .accept_suggestion ()
98+ 				end ,
99+ 				{ silent  =  true , expr  =  true , script  =  true , nowait  =  true  })
96100		end 
97101
98102		if  bindings .accept_word  and  bindings .accept_word  ~=  " "  then 
99103			vim .keymap .set (
100104				" i"  ,
101105				bindings .accept_word ,
102- 				M .accept_next_word ,
106+ 				function ()
107+ 					if  not  M .has_suggestions () then  return  bindings .accept_word  end 
108+ 					M .accept_word ()
109+ 				end ,
103110				{ silent  =  true , expr  =  true , script  =  true , nowait  =  true  }
104111			)
105112		end 
@@ -108,7 +115,10 @@ function M.setup(_server)
108115			vim .keymap .set (
109116				" i"  ,
110117				bindings .accept_line ,
111- 				M .accept_next_line ,
118+ 				function ()
119+ 					if  not  M .has_suggestions () then  return  bindings .accept_line  end 
120+ 					M .accept_line ()
121+ 				end ,
112122				{ silent  =  true , expr  =  true , script  =  true , nowait  =  true  }
113123			)
114124		end 
@@ -122,6 +132,18 @@ function M.setup(_server)
122132	})
123133end 
124134
135+ M .accept_suggestion  =  vim .schedule_wrap (function ()
136+ 	M .accept ()
137+ end )
138+ 
139+ M .accept_line  =  vim .schedule_wrap (function ()
140+ 	M .accept_next_line ()
141+ end )
142+ 
143+ M .accept_word  =  vim .schedule_wrap (function ()
144+ 	M .accept_next_word ()
145+ end )
146+ 
125147function  M .set_style ()
126148	if  vim .fn .has (" termguicolors"  ) ==  1  and  vim .o .termguicolors  then 
127149		vim .api .nvim_set_hl (0 , hlgroup , { fg  =  " #808080"  , default  =  true  })
@@ -136,15 +158,64 @@ function M.get_completion_text()
136158	return  completion_text  or  " " 
137159end 
138160
139- local  function  completion_inserter (current_completion , insert_text )
140- 	local  default  =  config .options .virtual_text .accept_fallback  or  (vim .fn .pumvisible () ==  1  and  " <C-N>"  or  " \t "  )
161+ local  function  str_to_lines (str )
162+ 	return  vim .fn .split (str , " \n "  )
163+ end 
164+ 
165+ local  function  move_cursor (offset )
166+ 	local  row , col  =  unpack (vim .api .nvim_win_get_cursor (0 ))
167+ 	local  target_row , target_col  =  row , col  +  offset 
168+ 	while  target_col  <  0  and  target_row  >  1  do 
169+ 		target_row  =  target_row  -  1 
170+ 		local  prev_line  =  vim .api .nvim_buf_get_lines (0 , target_row  -  1 , target_row , false )[1 ]
171+ 		target_col  =  # prev_line  +  target_col  +  1 
172+ 	end 
173+ 
174+ 	if  target_col  <  0  then 
175+ 		target_col  =  0 
176+ 	end 
177+ 
178+ 	vim .api .nvim_win_set_cursor (0 , { target_row , target_col  })
179+ end 
180+ 
181+ 
182+ local  function  delete_file_range (start_offset , end_offset )
183+ 	if  end_offset  <=  start_offset  then 
184+ 		return 
185+ 	end 
186+ 
187+ 	local  start_line  =  vim .fn .byte2line (start_offset  +  1 )
188+ 	local  end_line  =  vim .fn .byte2line (end_offset )
189+ 
190+ 	local  start_col  =  start_offset  -  vim .fn .line2byte (start_line ) +  1 
191+ 	local  end_col  =  end_offset  -  vim .fn .line2byte (end_line ) +  1 
192+ 
193+ 	local  start_line_content  =  vim .fn .getline (start_line )
194+ 	local  updated_start_line  =  start_line_content :sub (1 , start_col )
141195
196+ 	local  end_line_content  =  vim .fn .getline (end_line )
197+ 	local  updated_end_line  =  end_line_content :sub (end_col  +  1 )
198+ 
199+ 	if  start_line  ==  end_line  then 
200+ 		local  updated_line  =  updated_start_line  ..  updated_end_line 
201+ 		vim .fn .setline (start_line , updated_line )
202+ 	else 
203+ 		vim .fn .setline (start_line , updated_start_line )
204+ 		vim .fn .setline (end_line , updated_end_line )
205+ 		vim .api .nvim_buf_set_lines (0 , start_line , end_line  -  1 , false , {})
206+ 	end 
207+ 
208+ 	vim .api .nvim_win_set_cursor (0 , { start_line , start_col  })
209+ end 
210+ 
211+ 
212+ local  function  completion_inserter (current_completion , insert_text )
142213	if  not  (vim .fn .mode ():match (" ^[iR]"  )) then 
143- 		return   default 
214+ 		return 
144215	end 
145216
146217	if  current_completion  ==  nil  then 
147- 		return   default 
218+ 		return 
148219	end 
149220
150221	local  range  =  current_completion .range 
@@ -156,29 +227,24 @@ local function completion_inserter(current_completion, insert_text)
156227
157228	local  text  =  insert_text  ..  suffix_text 
158229	if  text  ==  " "  then 
159- 		return   default 
230+ 		return 
160231	end 
161232
162- 	local  delete_range  =  " " 
163- 	if  end_offset  -  start_offset  >  0  then 
164- 		local  delete_bytes  =  end_offset  -  start_offset 
165- 		local  delete_chars  =  vim .fn .strchars (vim .fn .strpart (vim .fn .getline (" ."  ), 0 , delete_bytes ))
166- 		delete_range  =  '  <Esc>"_x0"_d'  ..  delete_chars  ..  " li" 
167- 	end 
233+ 	delete_file_range (start_offset , end_offset )
168234
169- 	local  insert_text  =  ' <C-R><C-O>=v:lua.require("codeium.virtual_text").get_completion_text()<CR>' 
170235	M .completion_text  =  text 
171236
172- 	local  cursor_text  =  delta  ==  0  and  " "  or  ' <C-O>:exe "go" line2byte(line("."))+col(".")+('  ..  delta  ..  " )<CR>" 
173- 
174237	server .accept_completion (current_completion .completion .completionId )
238+ 	local  lines  =  str_to_lines (text )
175239
176- 	return  ' <C-g>u'  ..  delete_range  ..  insert_text  ..  cursor_text 
240+ 	vim .api .nvim_put (lines , " c"  , false , true )
241+ 
242+ 	move_cursor (delta )
177243end 
178244
179245function  M .accept ()
180246	local  current_completion  =  M .get_current_completion_item ()
181- 	return   completion_inserter (current_completion , current_completion  and  current_completion .completion .text  or  " "  )
247+ 	completion_inserter (current_completion , current_completion  and  current_completion .completion .text  or  " "  )
182248end 
183249
184250function  M .accept_next_word ()
@@ -190,13 +256,20 @@ function M.accept_next_word()
190256	local  prefix_text  =  completion_parts [1 ].prefix  or  " " 
191257	local  completion_text  =  completion_parts [1 ].text  or  " " 
192258	local  next_word  =  completion_text :match (" ^%W*%w*"  )
193- 	return   completion_inserter (current_completion , prefix_text  ..  next_word )
259+ 	completion_inserter (current_completion , prefix_text  ..  next_word )
194260end 
195261
196262function  M .accept_next_line ()
197263	local  current_completion  =  M .get_current_completion_item ()
198264	local  text  =  current_completion  and  current_completion .completion .text :gsub (" \n .*$"  , " "  ) or  " " 
199- 	return  completion_inserter (current_completion , text )
265+ 	completion_inserter (current_completion , text )
266+ end 
267+ 
268+ function  M .has_suggestions ()
269+ 	local  current_completion  =  M .get_current_completion_item ()
270+ 	local  suffix  =  current_completion  and  current_completion .suffix  or  {}
271+ 	local  suffix_text  =  suffix  and  suffix .text  or  " " 
272+ 	return  current_completion  and  current_completion .completion .text  ..  suffix_text 
200273end 
201274
202275function  M .get_current_completion_item ()
0 commit comments