@@ -172,6 +172,7 @@ static pos_T compl_startpos;
172172// Length in bytes of the text being completed (this is deleted to be replaced
173173// by the match.)
174174static int compl_length = 0 ;
175+ static linenr_T compl_lnum = 0 ; // lnum where the completion start
175176static colnr_T compl_col = 0 ; // column where the text starts
176177 // that is being completed
177178static colnr_T compl_ins_end_col = 0 ;
@@ -226,6 +227,8 @@ static int ins_compl_pum_key(int c);
226227static int ins_compl_key2count (int c );
227228static void show_pum (int prev_w_wrow , int prev_w_leftcol );
228229static 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 );
229232
230233#ifdef FEAT_SPELL
231234static void spell_back_to_badword (void );
@@ -919,20 +922,54 @@ ins_compl_insert_bytes(char_u *p, int len)
919922/*
920923 * Checks if the column is within the currently inserted completion text
921924 * column range. If it is, it returns a special highlight attribute.
922- * -1 mean normal item.
925+ * -1 means normal item.
923926 */
924927 int
925- ins_compl_col_range_attr (int col )
928+ ins_compl_col_range_attr (linenr_T lnum , int col )
926929{
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 )
928935 return -1 ;
929936
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 ;
932946
933947 return -1 ;
934948}
935949
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+
936973/*
937974 * Reduce the longest common string for match "match".
938975 */
@@ -3123,6 +3160,7 @@ set_completion(colnr_T startcol, list_T *list)
31233160 if (startcol > curwin -> w_cursor .col )
31243161 startcol = curwin -> w_cursor .col ;
31253162 compl_col = startcol ;
3163+ compl_lnum = curwin -> w_cursor .lnum ;
31263164 compl_length = (int )curwin -> w_cursor .col - (int )startcol ;
31273165 // compl_pattern doesn't need to be set
31283166 compl_orig_text .string = vim_strnsave (ml_get_curline () + compl_col ,
@@ -4342,13 +4380,39 @@ ins_compl_delete(void)
43424380 // In insert mode: Delete the typed part.
43434381 // In replace mode: Put the old characters back, if any.
43444382 int col = compl_col + (compl_status_adding () ? compl_length : 0 );
4383+ char_u * remaining = NULL ;
4384+ int orig_col ;
43454385 int has_preinsert = ins_compl_preinsert_effect ();
43464386 if (has_preinsert )
43474387 {
43484388 col += ins_compl_leader_len ();
43494389 curwin -> w_cursor .col = compl_ins_end_col ;
43504390 }
43514391
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+
43524416 if ((int )curwin -> w_cursor .col > col )
43534417 {
43544418 if (stop_arrow () == FAIL )
@@ -4357,6 +4421,13 @@ ins_compl_delete(void)
43574421 compl_ins_end_col = curwin -> w_cursor .col ;
43584422 }
43594423
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+ }
43604431 // TODO: is this sufficient for redrawing? Redrawing everything causes
43614432 // flicker, thus we can't do that.
43624433 changed_cline_bef_curs ();
@@ -4366,6 +4437,38 @@ ins_compl_delete(void)
43664437#endif
43674438}
43684439
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+
43694472/*
43704473 * Insert the new text being completed.
43714474 * "in_compl_func" is TRUE when called from complete_check().
@@ -4375,19 +4478,25 @@ ins_compl_delete(void)
43754478 void
43764479ins_compl_insert (int in_compl_func , int move_cursor )
43774480{
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' );
43834487
43844488 // Make sure we don't go over the end of the string, this can happen with
43854489 // illegal bytes.
43864490 if (compl_len < (int )cp_str_len )
43874491 {
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+ }
43914500 }
43924501 if (match_at_original_text (compl_shown_match ) || preinsert )
43934502 compl_used_match = FALSE;
@@ -5373,6 +5482,7 @@ ins_compl_start(void)
53735482 line = ml_get (curwin -> w_cursor .lnum );
53745483 curs_col = curwin -> w_cursor .col ;
53755484 compl_pending = 0 ;
5485+ compl_lnum = curwin -> w_cursor .lnum ;
53765486
53775487 if ((compl_cont_status & CONT_INTRPT ) == CONT_INTRPT
53785488 && compl_cont_mode == ctrl_x_mode )
@@ -5423,6 +5533,7 @@ ins_compl_start(void)
54235533 curbuf -> b_p_com = old ;
54245534 compl_length = 0 ;
54255535 compl_col = curwin -> w_cursor .col ;
5536+ compl_lnum = curwin -> w_cursor .lnum ;
54265537 }
54275538 else if (ctrl_x_mode_normal () && in_fuzzy )
54285539 {
0 commit comments