@@ -172,6 +172,7 @@ static pos_T compl_startpos;
172
172
// Length in bytes of the text being completed (this is deleted to be replaced
173
173
// by the match.)
174
174
static int compl_length = 0 ;
175
+ static linenr_T compl_lnum = 0 ; // lnum where the completion start
175
176
static colnr_T compl_col = 0 ; // column where the text starts
176
177
// that is being completed
177
178
static colnr_T compl_ins_end_col = 0 ;
@@ -226,6 +227,8 @@ static int ins_compl_pum_key(int c);
226
227
static int ins_compl_key2count (int c );
227
228
static void show_pum (int prev_w_wrow , int prev_w_leftcol );
228
229
static unsigned quote_meta (char_u * dest , char_u * str , int len );
230
+ static int ins_compl_has_multiple (void );
231
+ static void ins_compl_expand_multiple (char_u * str );
229
232
230
233
#ifdef FEAT_SPELL
231
234
static void spell_back_to_badword (void );
@@ -919,20 +922,54 @@ ins_compl_insert_bytes(char_u *p, int len)
919
922
/*
920
923
* Checks if the column is within the currently inserted completion text
921
924
* column range. If it is, it returns a special highlight attribute.
922
- * -1 mean normal item.
925
+ * -1 means normal item.
923
926
*/
924
927
int
925
- ins_compl_col_range_attr (int col )
928
+ ins_compl_col_range_attr (linenr_T lnum , int col )
926
929
{
927
- if ((get_cot_flags () & COT_FUZZY ))
930
+ int start_col ;
931
+ int attr ;
932
+
933
+ if ((get_cot_flags () & COT_FUZZY )
934
+ || (attr = syn_name2attr ((char_u * )"ComplMatchIns" )) == 0 )
928
935
return -1 ;
929
936
930
- if (col >= (compl_col + (int )ins_compl_leader_len ()) && col < compl_ins_end_col )
931
- return syn_name2attr ((char_u * )"ComplMatchIns" );
937
+ start_col = compl_col + (int )ins_compl_leader_len ();
938
+ if (!ins_compl_has_multiple ())
939
+ return (col >= start_col && col < compl_ins_end_col ) ? attr : -1 ;
940
+
941
+ // Multiple lines
942
+ if ((lnum == compl_lnum && col >= start_col && col < MAXCOL ) ||
943
+ (lnum > compl_lnum && lnum < curwin -> w_cursor .lnum ) ||
944
+ (lnum == curwin -> w_cursor .lnum && col <= compl_ins_end_col ))
945
+ return attr ;
932
946
933
947
return -1 ;
934
948
}
935
949
950
+ /*
951
+ * Returns TRUE if the current completion string contains newline characters,
952
+ * indicating it's a multi-line completion.
953
+ */
954
+ static int
955
+ ins_compl_has_multiple (void )
956
+ {
957
+ return vim_strchr (compl_shown_match -> cp_str .string , '\n' ) != NULL ;
958
+ }
959
+
960
+ /*
961
+ * Returns TRUE if the given line number falls within the range of a multi-line
962
+ * completion, i.e. between the starting line (compl_lnum) and current cursor
963
+ * line. Always returns FALSE for single-line completions.
964
+ */
965
+ int
966
+ ins_compl_lnum_in_range (linenr_T lnum )
967
+ {
968
+ if (!ins_compl_has_multiple ())
969
+ return FALSE;
970
+ return lnum >= compl_lnum && lnum <= curwin -> w_cursor .lnum ;
971
+ }
972
+
936
973
/*
937
974
* Reduce the longest common string for match "match".
938
975
*/
@@ -3123,6 +3160,7 @@ set_completion(colnr_T startcol, list_T *list)
3123
3160
if (startcol > curwin -> w_cursor .col )
3124
3161
startcol = curwin -> w_cursor .col ;
3125
3162
compl_col = startcol ;
3163
+ compl_lnum = curwin -> w_cursor .lnum ;
3126
3164
compl_length = (int )curwin -> w_cursor .col - (int )startcol ;
3127
3165
// compl_pattern doesn't need to be set
3128
3166
compl_orig_text .string = vim_strnsave (ml_get_curline () + compl_col ,
@@ -4342,13 +4380,39 @@ ins_compl_delete(void)
4342
4380
// In insert mode: Delete the typed part.
4343
4381
// In replace mode: Put the old characters back, if any.
4344
4382
int col = compl_col + (compl_status_adding () ? compl_length : 0 );
4383
+ char_u * remaining = NULL ;
4384
+ int orig_col ;
4345
4385
int has_preinsert = ins_compl_preinsert_effect ();
4346
4386
if (has_preinsert )
4347
4387
{
4348
4388
col += ins_compl_leader_len ();
4349
4389
curwin -> w_cursor .col = compl_ins_end_col ;
4350
4390
}
4351
4391
4392
+ if (curwin -> w_cursor .lnum > compl_lnum )
4393
+ {
4394
+ if (curwin -> w_cursor .col < ml_get_curline_len ())
4395
+ {
4396
+ char_u * line = ml_get_curline ();
4397
+ remaining = vim_strnsave (line + curwin -> w_cursor .col ,
4398
+ (size_t )STRLEN (line + curwin -> w_cursor .col ));
4399
+ if (remaining == NULL )
4400
+ return ;
4401
+ }
4402
+ while (curwin -> w_cursor .lnum > compl_lnum )
4403
+ {
4404
+ if (ml_delete (curwin -> w_cursor .lnum ) == FAIL )
4405
+ {
4406
+ if (remaining )
4407
+ VIM_CLEAR (remaining );
4408
+ return ;
4409
+ }
4410
+ curwin -> w_cursor .lnum -- ;
4411
+ }
4412
+ // move cursor to end of line
4413
+ curwin -> w_cursor .col = ml_get_curline_len ();
4414
+ }
4415
+
4352
4416
if ((int )curwin -> w_cursor .col > col )
4353
4417
{
4354
4418
if (stop_arrow () == FAIL )
@@ -4357,6 +4421,13 @@ ins_compl_delete(void)
4357
4421
compl_ins_end_col = curwin -> w_cursor .col ;
4358
4422
}
4359
4423
4424
+ if (remaining != NULL )
4425
+ {
4426
+ orig_col = curwin -> w_cursor .col ;
4427
+ ins_str (remaining );
4428
+ curwin -> w_cursor .col = orig_col ;
4429
+ vim_free (remaining );
4430
+ }
4360
4431
// TODO: is this sufficient for redrawing? Redrawing everything causes
4361
4432
// flicker, thus we can't do that.
4362
4433
changed_cline_bef_curs ();
@@ -4366,6 +4437,38 @@ ins_compl_delete(void)
4366
4437
#endif
4367
4438
}
4368
4439
4440
+ /*
4441
+ * Insert a completion string that contains newlines.
4442
+ * The string is split and inserted line by line.
4443
+ */
4444
+ static void
4445
+ ins_compl_expand_multiple (char_u * str )
4446
+ {
4447
+ char_u * start = str ;
4448
+ char_u * curr = str ;
4449
+
4450
+ while (* curr != NUL )
4451
+ {
4452
+ if (* curr == '\n' )
4453
+ {
4454
+ // Insert the text chunk before newline
4455
+ if (curr > start )
4456
+ ins_char_bytes (start , (int )(curr - start ));
4457
+
4458
+ // Handle newline
4459
+ open_line (FORWARD , OPENLINE_KEEPTRAIL , FALSE, NULL );
4460
+ start = curr + 1 ;
4461
+ }
4462
+ curr ++ ;
4463
+ }
4464
+
4465
+ // Handle remaining text after last newline (if any)
4466
+ if (curr > start )
4467
+ ins_char_bytes (start , (int )(curr - start ));
4468
+
4469
+ compl_ins_end_col = curwin -> w_cursor .col ;
4470
+ }
4471
+
4369
4472
/*
4370
4473
* Insert the new text being completed.
4371
4474
* "in_compl_func" is TRUE when called from complete_check().
@@ -4375,19 +4478,25 @@ ins_compl_delete(void)
4375
4478
void
4376
4479
ins_compl_insert (int in_compl_func , int move_cursor )
4377
4480
{
4378
- int compl_len = get_compl_len ();
4379
- int preinsert = ins_compl_has_preinsert ();
4380
- char_u * cp_str = compl_shown_match -> cp_str .string ;
4381
- size_t cp_str_len = compl_shown_match -> cp_str .length ;
4382
- size_t leader_len = ins_compl_leader_len ();
4481
+ int compl_len = get_compl_len ();
4482
+ int preinsert = ins_compl_has_preinsert ();
4483
+ char_u * cp_str = compl_shown_match -> cp_str .string ;
4484
+ size_t cp_str_len = compl_shown_match -> cp_str .length ;
4485
+ size_t leader_len = ins_compl_leader_len ();
4486
+ char_u * has_multiple = vim_strchr (cp_str , '\n' );
4383
4487
4384
4488
// Make sure we don't go over the end of the string, this can happen with
4385
4489
// illegal bytes.
4386
4490
if (compl_len < (int )cp_str_len )
4387
4491
{
4388
- ins_compl_insert_bytes (cp_str + compl_len , -1 );
4389
- if (preinsert && move_cursor )
4390
- curwin -> w_cursor .col -= (colnr_T )(cp_str_len - leader_len );
4492
+ if (has_multiple )
4493
+ ins_compl_expand_multiple (cp_str + compl_len );
4494
+ else
4495
+ {
4496
+ ins_compl_insert_bytes (cp_str + compl_len , -1 );
4497
+ if (preinsert && move_cursor )
4498
+ curwin -> w_cursor .col -= (colnr_T )(cp_str_len - leader_len );
4499
+ }
4391
4500
}
4392
4501
if (match_at_original_text (compl_shown_match ) || preinsert )
4393
4502
compl_used_match = FALSE;
@@ -5373,6 +5482,7 @@ ins_compl_start(void)
5373
5482
line = ml_get (curwin -> w_cursor .lnum );
5374
5483
curs_col = curwin -> w_cursor .col ;
5375
5484
compl_pending = 0 ;
5485
+ compl_lnum = curwin -> w_cursor .lnum ;
5376
5486
5377
5487
if ((compl_cont_status & CONT_INTRPT ) == CONT_INTRPT
5378
5488
&& compl_cont_mode == ctrl_x_mode )
@@ -5423,6 +5533,7 @@ ins_compl_start(void)
5423
5533
curbuf -> b_p_com = old ;
5424
5534
compl_length = 0 ;
5425
5535
compl_col = curwin -> w_cursor .col ;
5536
+ compl_lnum = curwin -> w_cursor .lnum ;
5426
5537
}
5427
5538
else if (ctrl_x_mode_normal () && in_fuzzy )
5428
5539
{
0 commit comments