blob: 0d5a6e56872b1a58124f208083688ef5d49aa4f9 [file] [log] [blame]
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001/* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * insexpand.c: functions for Insert mode completion
12 */
13
14#include "vim.h"
15
Bram Moolenaar7591bb32019-03-30 13:53:47 +010016/*
17 * Definitions used for CTRL-X submode.
18 * Note: If you change CTRL-X submode, you must also maintain ctrl_x_msgs[] and
19 * ctrl_x_mode_names[] below.
20 */
21# define CTRL_X_WANT_IDENT 0x100
22
Bram Moolenaaraa2f0ee2019-12-21 18:47:26 +010023# define CTRL_X_NORMAL 0 // CTRL-N CTRL-P completion, default
Bram Moolenaar7591bb32019-03-30 13:53:47 +010024# define CTRL_X_NOT_DEFINED_YET 1
25# define CTRL_X_SCROLL 2
26# define CTRL_X_WHOLE_LINE 3
27# define CTRL_X_FILES 4
28# define CTRL_X_TAGS (5 + CTRL_X_WANT_IDENT)
29# define CTRL_X_PATH_PATTERNS (6 + CTRL_X_WANT_IDENT)
30# define CTRL_X_PATH_DEFINES (7 + CTRL_X_WANT_IDENT)
31# define CTRL_X_FINISHED 8
32# define CTRL_X_DICTIONARY (9 + CTRL_X_WANT_IDENT)
33# define CTRL_X_THESAURUS (10 + CTRL_X_WANT_IDENT)
34# define CTRL_X_CMDLINE 11
Bram Moolenaar9810cfb2019-12-11 21:23:00 +010035# define CTRL_X_FUNCTION 12
Bram Moolenaar7591bb32019-03-30 13:53:47 +010036# define CTRL_X_OMNI 13
37# define CTRL_X_SPELL 14
Bram Moolenaaraa2f0ee2019-12-21 18:47:26 +010038# define CTRL_X_LOCAL_MSG 15 // only used in "ctrl_x_msgs"
39# define CTRL_X_EVAL 16 // for builtin function complete()
zeertzjqdca29d92021-08-31 19:12:51 +020040# define CTRL_X_CMDLINE_CTRL_X 17 // CTRL-X typed in CTRL_X_CMDLINE
Bram Moolenaar7591bb32019-03-30 13:53:47 +010041
42# define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT]
43
44// Message for CTRL-X mode, index is ctrl_x_mode.
45static char *ctrl_x_msgs[] =
46{
47 N_(" Keyword completion (^N^P)"), // CTRL_X_NORMAL, ^P/^N compl.
48 N_(" ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)"),
49 NULL, // CTRL_X_SCROLL: depends on state
50 N_(" Whole line completion (^L^N^P)"),
51 N_(" File name completion (^F^N^P)"),
52 N_(" Tag completion (^]^N^P)"),
53 N_(" Path pattern completion (^N^P)"),
54 N_(" Definition completion (^D^N^P)"),
55 NULL, // CTRL_X_FINISHED
56 N_(" Dictionary completion (^K^N^P)"),
57 N_(" Thesaurus completion (^T^N^P)"),
58 N_(" Command-line completion (^V^N^P)"),
59 N_(" User defined completion (^U^N^P)"),
60 N_(" Omni completion (^O^N^P)"),
61 N_(" Spelling suggestion (s^N^P)"),
62 N_(" Keyword Local completion (^N^P)"),
63 NULL, // CTRL_X_EVAL doesn't use msg.
zeertzjqdca29d92021-08-31 19:12:51 +020064 N_(" Command-line completion (^V^N^P)"),
Bram Moolenaar7591bb32019-03-30 13:53:47 +010065};
66
Bram Moolenaar9cb698d2019-08-21 15:30:45 +020067#if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL)
Bram Moolenaar7591bb32019-03-30 13:53:47 +010068static char *ctrl_x_mode_names[] = {
69 "keyword",
70 "ctrl_x",
zeertzjq27fef592021-10-03 12:01:27 +010071 "scroll",
Bram Moolenaar7591bb32019-03-30 13:53:47 +010072 "whole_line",
73 "files",
74 "tags",
75 "path_patterns",
76 "path_defines",
77 "unknown", // CTRL_X_FINISHED
78 "dictionary",
79 "thesaurus",
80 "cmdline",
81 "function",
82 "omni",
83 "spell",
84 NULL, // CTRL_X_LOCAL_MSG only used in "ctrl_x_msgs"
zeertzjqdca29d92021-08-31 19:12:51 +020085 "eval",
86 "cmdline",
Bram Moolenaar7591bb32019-03-30 13:53:47 +010087};
Bram Moolenaar9cb698d2019-08-21 15:30:45 +020088#endif
Bram Moolenaar7591bb32019-03-30 13:53:47 +010089
90/*
91 * Array indexes used for cp_text[].
92 */
93#define CPT_ABBR 0 // "abbr"
94#define CPT_MENU 1 // "menu"
95#define CPT_KIND 2 // "kind"
96#define CPT_INFO 3 // "info"
Bram Moolenaar08928322020-01-04 14:32:48 +010097#define CPT_COUNT 4 // Number of entries
Bram Moolenaar7591bb32019-03-30 13:53:47 +010098
99/*
100 * Structure used to store one match for insert completion.
101 */
102typedef struct compl_S compl_T;
103struct compl_S
104{
105 compl_T *cp_next;
106 compl_T *cp_prev;
Bram Moolenaar73655cf2019-04-06 13:45:55 +0200107 char_u *cp_str; // matched text
Bram Moolenaar73655cf2019-04-06 13:45:55 +0200108 char_u *(cp_text[CPT_COUNT]); // text for the menu
Bram Moolenaarab782c52020-01-04 19:00:11 +0100109#ifdef FEAT_EVAL
Bram Moolenaar08928322020-01-04 14:32:48 +0100110 typval_T cp_user_data;
Bram Moolenaarab782c52020-01-04 19:00:11 +0100111#endif
Bram Moolenaar73655cf2019-04-06 13:45:55 +0200112 char_u *cp_fname; // file containing the match, allocated when
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200113 // cp_flags has CP_FREE_FNAME
114 int cp_flags; // CP_ values
Bram Moolenaar73655cf2019-04-06 13:45:55 +0200115 int cp_number; // sequence number
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100116};
117
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200118// values for cp_flags
119# define CP_ORIGINAL_TEXT 1 // the original text when the expansion begun
120# define CP_FREE_FNAME 2 // cp_fname is allocated
121# define CP_CONT_S_IPOS 4 // use CONT_S_IPOS for compl_cont_status
122# define CP_EQUAL 8 // ins_compl_equal() always returns TRUE
123# define CP_ICASE 16 // ins_compl_equal() ignores case
Bram Moolenaar440cf092021-04-03 20:13:30 +0200124# define CP_FAST 32 // use fast_breakcheck instead of ui_breakcheck
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100125
126static char e_hitend[] = N_("Hit end of paragraph");
127# ifdef FEAT_COMPL_FUNC
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100128static char e_compldel[] = N_("E840: Completion function deleted text");
129# endif
130
131/*
132 * All the current matches are stored in a list.
133 * "compl_first_match" points to the start of the list.
134 * "compl_curr_match" points to the currently selected entry.
135 * "compl_shown_match" is different from compl_curr_match during
136 * ins_compl_get_exp().
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000137 * "compl_old_match" points to previous "compl_curr_match".
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100138 */
139static compl_T *compl_first_match = NULL;
140static compl_T *compl_curr_match = NULL;
141static compl_T *compl_shown_match = NULL;
142static compl_T *compl_old_match = NULL;
143
144// After using a cursor key <Enter> selects a match in the popup menu,
145// otherwise it inserts a line break.
146static int compl_enter_selects = FALSE;
147
148// When "compl_leader" is not NULL only matches that start with this string
149// are used.
150static char_u *compl_leader = NULL;
151
152static int compl_get_longest = FALSE; // put longest common string
153 // in compl_leader
154
155static int compl_no_insert = FALSE; // FALSE: select & insert
156 // TRUE: noinsert
157static int compl_no_select = FALSE; // FALSE: select & insert
158 // TRUE: noselect
159
160// Selected one of the matches. When FALSE the match was edited or using the
161// longest common string.
162static int compl_used_match;
163
164// didn't finish finding completions.
165static int compl_was_interrupted = FALSE;
166
167// Set when character typed while looking for matches and it means we should
168// stop looking for matches.
169static int compl_interrupted = FALSE;
170
171static int compl_restarting = FALSE; // don't insert match
172
173// When the first completion is done "compl_started" is set. When it's
174// FALSE the word to be completed must be located.
175static int compl_started = FALSE;
176
177// Which Ctrl-X mode are we in?
178static int ctrl_x_mode = CTRL_X_NORMAL;
179
180static int compl_matches = 0;
181static char_u *compl_pattern = NULL;
182static int compl_direction = FORWARD;
183static int compl_shows_dir = FORWARD;
184static int compl_pending = 0; // > 1 for postponed CTRL-N
185static pos_T compl_startpos;
186static colnr_T compl_col = 0; // column where the text starts
187 // that is being completed
188static char_u *compl_orig_text = NULL; // text as it was before
189 // completion started
190static int compl_cont_mode = 0;
191static expand_T compl_xp;
192
193static int compl_opt_refresh_always = FALSE;
194static int compl_opt_suppress_empty = FALSE;
195
Bram Moolenaar08928322020-01-04 14:32:48 +0100196static int ins_compl_add(char_u *str, int len, char_u *fname, char_u **cptext, typval_T *user_data, int cdir, int flags, int adup);
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100197static void ins_compl_longest_match(compl_T *match);
198static void ins_compl_del_pum(void);
199static void ins_compl_files(int count, char_u **files, int thesaurus, int flags, regmatch_T *regmatch, char_u *buf, int *dir);
200static char_u *find_line_end(char_u *ptr);
201static void ins_compl_free(void);
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100202static int ins_compl_need_restart(void);
203static void ins_compl_new_leader(void);
204static int ins_compl_len(void);
205static void ins_compl_restart(void);
206static void ins_compl_set_original_text(char_u *str);
207static void ins_compl_fixRedoBufForLeader(char_u *ptr_arg);
208# if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL)
209static void ins_compl_add_list(list_T *list);
210static void ins_compl_add_dict(dict_T *dict);
211# endif
212static int ins_compl_key2dir(int c);
213static int ins_compl_pum_key(int c);
214static int ins_compl_key2count(int c);
215static void show_pum(int prev_w_wrow, int prev_w_leftcol);
216static unsigned quote_meta(char_u *dest, char_u *str, int len);
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100217
218#ifdef FEAT_SPELL
219static void spell_back_to_badword(void);
220static int spell_bad_len = 0; // length of located bad word
221#endif
222
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100223/*
224 * CTRL-X pressed in Insert mode.
225 */
226 void
227ins_ctrl_x(void)
228{
zeertzjqdca29d92021-08-31 19:12:51 +0200229 if (!ctrl_x_mode_cmdline())
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100230 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000231 // if the next ^X<> won't ADD nothing, then reset compl_cont_status
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100232 if (compl_cont_status & CONT_N_ADDS)
233 compl_cont_status |= CONT_INTRPT;
234 else
235 compl_cont_status = 0;
236 // We're not sure which CTRL-X mode it will be yet
237 ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
238 edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
239 edit_submode_pre = NULL;
240 showmode();
241 }
zeertzjqdca29d92021-08-31 19:12:51 +0200242 else
243 // CTRL-X in CTRL-X CTRL-V mode behaves differently to make CTRL-X
244 // CTRL-V look like CTRL-N
245 ctrl_x_mode = CTRL_X_CMDLINE_CTRL_X;
=?UTF-8?q?Magnus=20Gro=C3=9F?=25def2c2021-10-22 18:56:39 +0100246
247 trigger_modechanged();
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100248}
249
250/*
251 * Functions to check the current CTRL-X mode.
252 */
253int ctrl_x_mode_none(void) { return ctrl_x_mode == 0; }
254int ctrl_x_mode_normal(void) { return ctrl_x_mode == CTRL_X_NORMAL; }
255int ctrl_x_mode_scroll(void) { return ctrl_x_mode == CTRL_X_SCROLL; }
256int ctrl_x_mode_whole_line(void) { return ctrl_x_mode == CTRL_X_WHOLE_LINE; }
257int ctrl_x_mode_files(void) { return ctrl_x_mode == CTRL_X_FILES; }
258int ctrl_x_mode_tags(void) { return ctrl_x_mode == CTRL_X_TAGS; }
259int ctrl_x_mode_path_patterns(void) {
260 return ctrl_x_mode == CTRL_X_PATH_PATTERNS; }
261int ctrl_x_mode_path_defines(void) {
262 return ctrl_x_mode == CTRL_X_PATH_DEFINES; }
263int ctrl_x_mode_dictionary(void) { return ctrl_x_mode == CTRL_X_DICTIONARY; }
264int ctrl_x_mode_thesaurus(void) { return ctrl_x_mode == CTRL_X_THESAURUS; }
zeertzjqdca29d92021-08-31 19:12:51 +0200265int ctrl_x_mode_cmdline(void) {
266 return ctrl_x_mode == CTRL_X_CMDLINE
267 || ctrl_x_mode == CTRL_X_CMDLINE_CTRL_X; }
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100268int ctrl_x_mode_function(void) { return ctrl_x_mode == CTRL_X_FUNCTION; }
269int ctrl_x_mode_omni(void) { return ctrl_x_mode == CTRL_X_OMNI; }
270int ctrl_x_mode_spell(void) { return ctrl_x_mode == CTRL_X_SPELL; }
271int ctrl_x_mode_line_or_eval(void) {
272 return ctrl_x_mode == CTRL_X_WHOLE_LINE || ctrl_x_mode == CTRL_X_EVAL; }
273
274/*
275 * Whether other than default completion has been selected.
276 */
277 int
278ctrl_x_mode_not_default(void)
279{
280 return ctrl_x_mode != CTRL_X_NORMAL;
281}
282
283/*
zeertzjqdca29d92021-08-31 19:12:51 +0200284 * Whether CTRL-X was typed without a following character,
285 * not including when in CTRL-X CTRL-V mode.
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100286 */
287 int
288ctrl_x_mode_not_defined_yet(void)
289{
290 return ctrl_x_mode == CTRL_X_NOT_DEFINED_YET;
291}
292
293/*
294 * Return TRUE if the 'dict' or 'tsr' option can be used.
295 */
296 int
297has_compl_option(int dict_opt)
298{
299 if (dict_opt ? (*curbuf->b_p_dict == NUL && *p_dict == NUL
Bram Moolenaare2c453d2019-08-21 14:37:09 +0200300#ifdef FEAT_SPELL
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100301 && !curwin->w_p_spell
Bram Moolenaare2c453d2019-08-21 14:37:09 +0200302#endif
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100303 )
Yegappan Lakshmanan160e9942021-10-16 15:41:29 +0100304 : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL
305#ifdef FEAT_COMPL_FUNC
Bram Moolenaarf4d8b762021-10-17 14:13:09 +0100306 && *curbuf->b_p_tsrfu == NUL && *p_tsrfu == NUL
Yegappan Lakshmanan160e9942021-10-16 15:41:29 +0100307#endif
308 ))
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100309 {
310 ctrl_x_mode = CTRL_X_NORMAL;
311 edit_submode = NULL;
312 msg_attr(dict_opt ? _("'dictionary' option is empty")
313 : _("'thesaurus' option is empty"),
314 HL_ATTR(HLF_E));
Bram Moolenaar28ee8922020-10-28 20:20:00 +0100315 if (emsg_silent == 0 && !in_assert_fails)
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100316 {
317 vim_beep(BO_COMPL);
318 setcursor();
319 out_flush();
320#ifdef FEAT_EVAL
321 if (!get_vim_var_nr(VV_TESTING))
322#endif
Bram Moolenaareda1da02019-11-17 17:06:33 +0100323 ui_delay(2004L, FALSE);
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100324 }
325 return FALSE;
326 }
327 return TRUE;
328}
329
330/*
331 * Is the character 'c' a valid key to go to or keep us in CTRL-X mode?
332 * This depends on the current mode.
333 */
334 int
335vim_is_ctrl_x_key(int c)
336{
337 // Always allow ^R - let its results then be checked
338 if (c == Ctrl_R)
339 return TRUE;
340
341 // Accept <PageUp> and <PageDown> if the popup menu is visible.
342 if (ins_compl_pum_key(c))
343 return TRUE;
344
345 switch (ctrl_x_mode)
346 {
347 case 0: // Not in any CTRL-X mode
348 return (c == Ctrl_N || c == Ctrl_P || c == Ctrl_X);
349 case CTRL_X_NOT_DEFINED_YET:
zeertzjqdca29d92021-08-31 19:12:51 +0200350 case CTRL_X_CMDLINE_CTRL_X:
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100351 return ( c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E
352 || c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB
353 || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P
354 || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V
355 || c == Ctrl_Q || c == Ctrl_U || c == Ctrl_O
zeertzjqdca29d92021-08-31 19:12:51 +0200356 || c == Ctrl_S || c == Ctrl_K || c == 's'
357 || c == Ctrl_Z);
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100358 case CTRL_X_SCROLL:
359 return (c == Ctrl_Y || c == Ctrl_E);
360 case CTRL_X_WHOLE_LINE:
361 return (c == Ctrl_L || c == Ctrl_P || c == Ctrl_N);
362 case CTRL_X_FILES:
363 return (c == Ctrl_F || c == Ctrl_P || c == Ctrl_N);
364 case CTRL_X_DICTIONARY:
365 return (c == Ctrl_K || c == Ctrl_P || c == Ctrl_N);
366 case CTRL_X_THESAURUS:
367 return (c == Ctrl_T || c == Ctrl_P || c == Ctrl_N);
368 case CTRL_X_TAGS:
369 return (c == Ctrl_RSB || c == Ctrl_P || c == Ctrl_N);
370#ifdef FEAT_FIND_ID
371 case CTRL_X_PATH_PATTERNS:
372 return (c == Ctrl_P || c == Ctrl_N);
373 case CTRL_X_PATH_DEFINES:
374 return (c == Ctrl_D || c == Ctrl_P || c == Ctrl_N);
375#endif
376 case CTRL_X_CMDLINE:
377 return (c == Ctrl_V || c == Ctrl_Q || c == Ctrl_P || c == Ctrl_N
378 || c == Ctrl_X);
379#ifdef FEAT_COMPL_FUNC
380 case CTRL_X_FUNCTION:
381 return (c == Ctrl_U || c == Ctrl_P || c == Ctrl_N);
382 case CTRL_X_OMNI:
383 return (c == Ctrl_O || c == Ctrl_P || c == Ctrl_N);
384#endif
385 case CTRL_X_SPELL:
386 return (c == Ctrl_S || c == Ctrl_P || c == Ctrl_N);
387 case CTRL_X_EVAL:
388 return (c == Ctrl_P || c == Ctrl_N);
389 }
390 internal_error("vim_is_ctrl_x_key()");
391 return FALSE;
392}
393
394/*
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000395 * Returns TRUE if the currently shown text is the original text when the
396 * completion began.
397 */
398 static int
399ins_compl_at_original_text(compl_T *match)
400{
401 return match->cp_flags & CP_ORIGINAL_TEXT;
402}
403
404/*
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100405 * Return TRUE when character "c" is part of the item currently being
406 * completed. Used to decide whether to abandon complete mode when the menu
407 * is visible.
408 */
409 int
410ins_compl_accept_char(int c)
411{
412 if (ctrl_x_mode & CTRL_X_WANT_IDENT)
413 // When expanding an identifier only accept identifier chars.
414 return vim_isIDc(c);
415
416 switch (ctrl_x_mode)
417 {
418 case CTRL_X_FILES:
419 // When expanding file name only accept file name chars. But not
420 // path separators, so that "proto/<Tab>" expands files in
421 // "proto", not "proto/" as a whole
422 return vim_isfilec(c) && !vim_ispathsep(c);
423
424 case CTRL_X_CMDLINE:
zeertzjqdca29d92021-08-31 19:12:51 +0200425 case CTRL_X_CMDLINE_CTRL_X:
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100426 case CTRL_X_OMNI:
427 // Command line and Omni completion can work with just about any
428 // printable character, but do stop at white space.
429 return vim_isprintc(c) && !VIM_ISWHITE(c);
430
431 case CTRL_X_WHOLE_LINE:
432 // For while line completion a space can be part of the line.
433 return vim_isprintc(c);
434 }
435 return vim_iswordc(c);
436}
437
438/*
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000439 * Get the completed text by inferring the case of the originally typed text.
440 */
441 static char_u *
442ins_compl_infercase_gettext(
443 char_u *str,
444 int actual_len,
445 int actual_compl_length,
446 int min_len)
447{
448 int *wca; // Wide character array.
449 char_u *p;
450 int i, c;
451 int has_lower = FALSE;
452 int was_letter = FALSE;
453
454 IObuff[0] = NUL;
455
456 // Allocate wide character array for the completion and fill it.
457 wca = ALLOC_MULT(int, actual_len);
458 if (wca == NULL)
459 return IObuff;
460
461 p = str;
462 for (i = 0; i < actual_len; ++i)
463 if (has_mbyte)
464 wca[i] = mb_ptr2char_adv(&p);
465 else
466 wca[i] = *(p++);
467
468 // Rule 1: Were any chars converted to lower?
469 p = compl_orig_text;
470 for (i = 0; i < min_len; ++i)
471 {
472 if (has_mbyte)
473 c = mb_ptr2char_adv(&p);
474 else
475 c = *(p++);
476 if (MB_ISLOWER(c))
477 {
478 has_lower = TRUE;
479 if (MB_ISUPPER(wca[i]))
480 {
481 // Rule 1 is satisfied.
482 for (i = actual_compl_length; i < actual_len; ++i)
483 wca[i] = MB_TOLOWER(wca[i]);
484 break;
485 }
486 }
487 }
488
489 // Rule 2: No lower case, 2nd consecutive letter converted to
490 // upper case.
491 if (!has_lower)
492 {
493 p = compl_orig_text;
494 for (i = 0; i < min_len; ++i)
495 {
496 if (has_mbyte)
497 c = mb_ptr2char_adv(&p);
498 else
499 c = *(p++);
500 if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
501 {
502 // Rule 2 is satisfied.
503 for (i = actual_compl_length; i < actual_len; ++i)
504 wca[i] = MB_TOUPPER(wca[i]);
505 break;
506 }
507 was_letter = MB_ISLOWER(c) || MB_ISUPPER(c);
508 }
509 }
510
511 // Copy the original case of the part we typed.
512 p = compl_orig_text;
513 for (i = 0; i < min_len; ++i)
514 {
515 if (has_mbyte)
516 c = mb_ptr2char_adv(&p);
517 else
518 c = *(p++);
519 if (MB_ISLOWER(c))
520 wca[i] = MB_TOLOWER(wca[i]);
521 else if (MB_ISUPPER(c))
522 wca[i] = MB_TOUPPER(wca[i]);
523 }
524
525 // Generate encoding specific output from wide character array.
526 // Multi-byte characters can occupy up to five bytes more than
527 // ASCII characters, and we also need one byte for NUL, so stay
528 // six bytes away from the edge of IObuff.
529 p = IObuff;
530 i = 0;
531 while (i < actual_len && (p - IObuff + 6) < IOSIZE)
532 if (has_mbyte)
533 p += (*mb_char2bytes)(wca[i++], p);
534 else
535 *(p++) = wca[i++];
536 *p = NUL;
537
538 vim_free(wca);
539
540 return IObuff;
541}
542
543/*
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100544 * This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
545 * case of the originally typed text is used, and the case of the completed
546 * text is inferred, ie this tries to work out what case you probably wanted
547 * the rest of the word to be in -- webb
548 */
549 int
550ins_compl_add_infercase(
Bram Moolenaar73655cf2019-04-06 13:45:55 +0200551 char_u *str_arg,
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100552 int len,
553 int icase,
554 char_u *fname,
555 int dir,
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200556 int cont_s_ipos) // next ^X<> will set initial_pos
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100557{
Bram Moolenaar73655cf2019-04-06 13:45:55 +0200558 char_u *str = str_arg;
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100559 char_u *p;
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100560 int actual_len; // Take multi-byte characters
561 int actual_compl_length; // into account.
562 int min_len;
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200563 int flags = 0;
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100564
565 if (p_ic && curbuf->b_p_inf && len > 0)
566 {
567 // Infer case of completed part.
568
569 // Find actual length of completion.
570 if (has_mbyte)
571 {
572 p = str;
573 actual_len = 0;
574 while (*p != NUL)
575 {
576 MB_PTR_ADV(p);
577 ++actual_len;
578 }
579 }
580 else
581 actual_len = len;
582
583 // Find actual length of original text.
584 if (has_mbyte)
585 {
586 p = compl_orig_text;
587 actual_compl_length = 0;
588 while (*p != NUL)
589 {
590 MB_PTR_ADV(p);
591 ++actual_compl_length;
592 }
593 }
594 else
595 actual_compl_length = compl_length;
596
597 // "actual_len" may be smaller than "actual_compl_length" when using
598 // thesaurus, only use the minimum when comparing.
599 min_len = actual_len < actual_compl_length
600 ? actual_len : actual_compl_length;
601
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000602 str = ins_compl_infercase_gettext(str, actual_len, actual_compl_length,
603 min_len);
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100604 }
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200605 if (cont_s_ipos)
606 flags |= CP_CONT_S_IPOS;
607 if (icase)
608 flags |= CP_ICASE;
Bram Moolenaar73655cf2019-04-06 13:45:55 +0200609
Bram Moolenaar08928322020-01-04 14:32:48 +0100610 return ins_compl_add(str, len, fname, NULL, NULL, dir, flags, FALSE);
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100611}
612
613/*
614 * Add a match to the list of matches.
615 * If the given string is already in the list of completions, then return
616 * NOTDONE, otherwise add it to the list and return OK. If there is an error,
617 * maybe because alloc() returns NULL, then FAIL is returned.
618 */
619 static int
620ins_compl_add(
621 char_u *str,
622 int len,
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100623 char_u *fname,
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100624 char_u **cptext, // extra text for popup menu or NULL
625 typval_T *user_data UNUSED, // "user_data" entry or NULL
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100626 int cdir,
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200627 int flags_arg,
Bram Moolenaar08928322020-01-04 14:32:48 +0100628 int adup) // accept duplicate match
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100629{
630 compl_T *match;
631 int dir = (cdir == 0 ? compl_direction : cdir);
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200632 int flags = flags_arg;
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100633
Bram Moolenaarceb06192021-04-04 15:05:22 +0200634 if (flags & CP_FAST)
635 fast_breakcheck();
636 else
637 ui_breakcheck();
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100638 if (got_int)
639 return FAIL;
640 if (len < 0)
641 len = (int)STRLEN(str);
642
643 // If the same match is already present, don't add it.
644 if (compl_first_match != NULL && !adup)
645 {
646 match = compl_first_match;
647 do
648 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000649 if (!ins_compl_at_original_text(match)
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100650 && STRNCMP(match->cp_str, str, len) == 0
651 && match->cp_str[len] == NUL)
652 return NOTDONE;
653 match = match->cp_next;
654 } while (match != NULL && match != compl_first_match);
655 }
656
657 // Remove any popup menu before changing the list of matches.
658 ins_compl_del_pum();
659
660 // Allocate a new match structure.
661 // Copy the values to the new match structure.
Bram Moolenaarc799fe22019-05-28 23:08:19 +0200662 match = ALLOC_CLEAR_ONE(compl_T);
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100663 if (match == NULL)
664 return FAIL;
665 match->cp_number = -1;
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200666 if (flags & CP_ORIGINAL_TEXT)
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100667 match->cp_number = 0;
668 if ((match->cp_str = vim_strnsave(str, len)) == NULL)
669 {
670 vim_free(match);
671 return FAIL;
672 }
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100673
674 // match-fname is:
675 // - compl_curr_match->cp_fname if it is a string equal to fname.
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200676 // - a copy of fname, CP_FREE_FNAME is set to free later THE allocated mem.
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100677 // - NULL otherwise. --Acevedo
678 if (fname != NULL
679 && compl_curr_match != NULL
680 && compl_curr_match->cp_fname != NULL
681 && STRCMP(fname, compl_curr_match->cp_fname) == 0)
682 match->cp_fname = compl_curr_match->cp_fname;
683 else if (fname != NULL)
684 {
685 match->cp_fname = vim_strsave(fname);
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200686 flags |= CP_FREE_FNAME;
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100687 }
688 else
689 match->cp_fname = NULL;
690 match->cp_flags = flags;
691
692 if (cptext != NULL)
693 {
694 int i;
695
696 for (i = 0; i < CPT_COUNT; ++i)
697 if (cptext[i] != NULL && *cptext[i] != NUL)
698 match->cp_text[i] = vim_strsave(cptext[i]);
699 }
Bram Moolenaarab782c52020-01-04 19:00:11 +0100700#ifdef FEAT_EVAL
Bram Moolenaar08928322020-01-04 14:32:48 +0100701 if (user_data != NULL)
702 match->cp_user_data = *user_data;
Bram Moolenaarab782c52020-01-04 19:00:11 +0100703#endif
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100704
705 // Link the new match structure in the list of matches.
706 if (compl_first_match == NULL)
707 match->cp_next = match->cp_prev = NULL;
708 else if (dir == FORWARD)
709 {
710 match->cp_next = compl_curr_match->cp_next;
711 match->cp_prev = compl_curr_match;
712 }
713 else // BACKWARD
714 {
715 match->cp_next = compl_curr_match;
716 match->cp_prev = compl_curr_match->cp_prev;
717 }
718 if (match->cp_next)
719 match->cp_next->cp_prev = match;
720 if (match->cp_prev)
721 match->cp_prev->cp_next = match;
722 else // if there's nothing before, it is the first match
723 compl_first_match = match;
724 compl_curr_match = match;
725
726 // Find the longest common string if still doing that.
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200727 if (compl_get_longest && (flags & CP_ORIGINAL_TEXT) == 0)
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100728 ins_compl_longest_match(match);
729
730 return OK;
731}
732
733/*
734 * Return TRUE if "str[len]" matches with match->cp_str, considering
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200735 * match->cp_flags.
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100736 */
737 static int
738ins_compl_equal(compl_T *match, char_u *str, int len)
739{
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200740 if (match->cp_flags & CP_EQUAL)
Bram Moolenaar73655cf2019-04-06 13:45:55 +0200741 return TRUE;
Bram Moolenaard9eefe32019-04-06 14:22:21 +0200742 if (match->cp_flags & CP_ICASE)
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100743 return STRNICMP(match->cp_str, str, (size_t)len) == 0;
744 return STRNCMP(match->cp_str, str, (size_t)len) == 0;
745}
746
747/*
748 * Reduce the longest common string for match "match".
749 */
750 static void
751ins_compl_longest_match(compl_T *match)
752{
753 char_u *p, *s;
754 int c1, c2;
755 int had_match;
756
757 if (compl_leader == NULL)
758 {
759 // First match, use it as a whole.
760 compl_leader = vim_strsave(match->cp_str);
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000761 if (compl_leader == NULL)
762 return;
763
764 had_match = (curwin->w_cursor.col > compl_col);
765 ins_compl_delete();
766 ins_bytes(compl_leader + ins_compl_len());
767 ins_redraw(FALSE);
768
769 // When the match isn't there (to avoid matching itself) remove it
770 // again after redrawing.
771 if (!had_match)
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100772 ins_compl_delete();
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100773 compl_used_match = FALSE;
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000774
775 return;
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100776 }
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000777
778 // Reduce the text if this match differs from compl_leader.
779 p = compl_leader;
780 s = match->cp_str;
781 while (*p != NUL)
782 {
783 if (has_mbyte)
784 {
785 c1 = mb_ptr2char(p);
786 c2 = mb_ptr2char(s);
787 }
788 else
789 {
790 c1 = *p;
791 c2 = *s;
792 }
793 if ((match->cp_flags & CP_ICASE)
794 ? (MB_TOLOWER(c1) != MB_TOLOWER(c2)) : (c1 != c2))
795 break;
796 if (has_mbyte)
797 {
798 MB_PTR_ADV(p);
799 MB_PTR_ADV(s);
800 }
801 else
802 {
803 ++p;
804 ++s;
805 }
806 }
807
808 if (*p != NUL)
809 {
810 // Leader was shortened, need to change the inserted text.
811 *p = NUL;
812 had_match = (curwin->w_cursor.col > compl_col);
813 ins_compl_delete();
814 ins_bytes(compl_leader + ins_compl_len());
815 ins_redraw(FALSE);
816
817 // When the match isn't there (to avoid matching itself) remove it
818 // again after redrawing.
819 if (!had_match)
820 ins_compl_delete();
821 }
822
823 compl_used_match = FALSE;
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100824}
825
826/*
827 * Add an array of matches to the list of matches.
828 * Frees matches[].
829 */
830 static void
831ins_compl_add_matches(
832 int num_matches,
833 char_u **matches,
834 int icase)
835{
836 int i;
837 int add_r = OK;
838 int dir = compl_direction;
839
840 for (i = 0; i < num_matches && add_r != FAIL; i++)
Bram Moolenaar08928322020-01-04 14:32:48 +0100841 if ((add_r = ins_compl_add(matches[i], -1, NULL, NULL, NULL, dir,
Bram Moolenaar440cf092021-04-03 20:13:30 +0200842 CP_FAST | (icase ? CP_ICASE : 0), FALSE)) == OK)
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100843 // if dir was BACKWARD then honor it just once
844 dir = FORWARD;
845 FreeWild(num_matches, matches);
846}
847
848/*
849 * Make the completion list cyclic.
850 * Return the number of matches (excluding the original).
851 */
852 static int
853ins_compl_make_cyclic(void)
854{
855 compl_T *match;
856 int count = 0;
857
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000858 if (compl_first_match == NULL)
859 return 0;
860
861 // Find the end of the list.
862 match = compl_first_match;
863 // there's always an entry for the compl_orig_text, it doesn't count.
864 while (match->cp_next != NULL && match->cp_next != compl_first_match)
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100865 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000866 match = match->cp_next;
867 ++count;
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100868 }
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000869 match->cp_next = compl_first_match;
870 compl_first_match->cp_prev = match;
871
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100872 return count;
873}
874
875/*
876 * Return whether there currently is a shown match.
877 */
878 int
879ins_compl_has_shown_match(void)
880{
881 return compl_shown_match == NULL
882 || compl_shown_match != compl_shown_match->cp_next;
883}
884
885/*
886 * Return whether the shown match is long enough.
887 */
888 int
889ins_compl_long_shown_match(void)
890{
891 return (int)STRLEN(compl_shown_match->cp_str)
892 > curwin->w_cursor.col - compl_col;
893}
894
895/*
896 * Set variables that store noselect and noinsert behavior from the
897 * 'completeopt' value.
898 */
899 void
900completeopt_was_set(void)
901{
902 compl_no_insert = FALSE;
903 compl_no_select = FALSE;
904 if (strstr((char *)p_cot, "noselect") != NULL)
905 compl_no_select = TRUE;
906 if (strstr((char *)p_cot, "noinsert") != NULL)
907 compl_no_insert = TRUE;
908}
909
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100910
911// "compl_match_array" points the currently displayed list of entries in the
912// popup menu. It is NULL when there is no popup menu.
913static pumitem_T *compl_match_array = NULL;
914static int compl_match_arraysize;
915
916/*
917 * Update the screen and when there is any scrolling remove the popup menu.
918 */
919 static void
920ins_compl_upd_pum(void)
921{
922 int h;
923
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000924 if (compl_match_array == NULL)
925 return;
926
927 h = curwin->w_cline_height;
928 // Update the screen later, before drawing the popup menu over it.
929 pum_call_update_screen();
930 if (h != curwin->w_cline_height)
931 ins_compl_del_pum();
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100932}
933
934/*
935 * Remove any popup menu.
936 */
937 static void
938ins_compl_del_pum(void)
939{
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000940 if (compl_match_array == NULL)
941 return;
942
943 pum_undisplay();
944 VIM_CLEAR(compl_match_array);
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100945}
946
947/*
948 * Return TRUE if the popup menu should be displayed.
949 */
950 int
951pum_wanted(void)
952{
953 // 'completeopt' must contain "menu" or "menuone"
954 if (vim_strchr(p_cot, 'm') == NULL)
955 return FALSE;
956
957 // The display looks bad on a B&W display.
958 if (t_colors < 8
959#ifdef FEAT_GUI
960 && !gui.in_use
961#endif
962 )
963 return FALSE;
964 return TRUE;
965}
966
967/*
968 * Return TRUE if there are two or more matches to be shown in the popup menu.
969 * One if 'completopt' contains "menuone".
970 */
971 static int
972pum_enough_matches(void)
973{
974 compl_T *compl;
975 int i;
976
977 // Don't display the popup menu if there are no matches or there is only
978 // one (ignoring the original text).
979 compl = compl_first_match;
980 i = 0;
981 do
982 {
983 if (compl == NULL
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +0000984 || (!ins_compl_at_original_text(compl) && ++i == 2))
Bram Moolenaar7591bb32019-03-30 13:53:47 +0100985 break;
986 compl = compl->cp_next;
987 } while (compl != compl_first_match);
988
989 if (strstr((char *)p_cot, "menuone") != NULL)
990 return (i >= 1);
991 return (i >= 2);
992}
993
Bram Moolenaar3075a452021-11-17 15:51:52 +0000994#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar9cb698d2019-08-21 15:30:45 +0200995/*
996 * Allocate Dict for the completed item.
997 * { word, abbr, menu, kind, info }
998 */
999 static dict_T *
1000ins_compl_dict_alloc(compl_T *match)
1001{
1002 dict_T *dict = dict_alloc_lock(VAR_FIXED);
1003
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001004 if (dict == NULL)
1005 return NULL;
1006
1007 dict_add_string(dict, "word", match->cp_str);
1008 dict_add_string(dict, "abbr", match->cp_text[CPT_ABBR]);
1009 dict_add_string(dict, "menu", match->cp_text[CPT_MENU]);
1010 dict_add_string(dict, "kind", match->cp_text[CPT_KIND]);
1011 dict_add_string(dict, "info", match->cp_text[CPT_INFO]);
1012 if (match->cp_user_data.v_type == VAR_UNKNOWN)
1013 dict_add_string(dict, "user_data", (char_u *)"");
1014 else
1015 dict_add_tv(dict, "user_data", &match->cp_user_data);
1016
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02001017 return dict;
1018}
1019
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001020/*
1021 * Trigger the CompleteChanged autocmd event. Invoked each time the Insert mode
1022 * completion menu is changed.
1023 */
Bram Moolenaard7f246c2019-04-08 18:15:41 +02001024 static void
1025trigger_complete_changed_event(int cur)
1026{
1027 dict_T *v_event;
1028 dict_T *item;
1029 static int recursive = FALSE;
Bram Moolenaar3075a452021-11-17 15:51:52 +00001030 save_v_event_T save_v_event;
Bram Moolenaard7f246c2019-04-08 18:15:41 +02001031
1032 if (recursive)
1033 return;
1034
Bram Moolenaard7f246c2019-04-08 18:15:41 +02001035 if (cur < 0)
1036 item = dict_alloc();
1037 else
1038 item = ins_compl_dict_alloc(compl_curr_match);
1039 if (item == NULL)
1040 return;
Bram Moolenaar3075a452021-11-17 15:51:52 +00001041 v_event = get_v_event(&save_v_event);
Bram Moolenaard7f246c2019-04-08 18:15:41 +02001042 dict_add_dict(v_event, "completed_item", item);
1043 pum_set_event_info(v_event);
1044 dict_set_items_ro(v_event);
1045
1046 recursive = TRUE;
Bram Moolenaar6adb9ea2020-04-30 22:31:18 +02001047 textwinlock++;
Bram Moolenaard7f246c2019-04-08 18:15:41 +02001048 apply_autocmds(EVENT_COMPLETECHANGED, NULL, NULL, FALSE, curbuf);
Bram Moolenaar6adb9ea2020-04-30 22:31:18 +02001049 textwinlock--;
Bram Moolenaard7f246c2019-04-08 18:15:41 +02001050 recursive = FALSE;
1051
Bram Moolenaar3075a452021-11-17 15:51:52 +00001052 restore_v_event(v_event, &save_v_event);
Bram Moolenaard7f246c2019-04-08 18:15:41 +02001053}
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02001054#endif
Bram Moolenaard7f246c2019-04-08 18:15:41 +02001055
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001056/*
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001057 * Build a popup menu to show the completion matches.
1058 * Returns the popup menu entry that should be selected. Returns -1 if nothing
1059 * should be selected.
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001060 */
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001061 static int
1062ins_compl_build_pum(void)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001063{
1064 compl_T *compl;
1065 compl_T *shown_compl = NULL;
1066 int did_find_shown_match = FALSE;
1067 int shown_match_ok = FALSE;
1068 int i;
1069 int cur = -1;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001070 int lead_len = 0;
1071
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001072 // Need to build the popup menu list.
1073 compl_match_arraysize = 0;
1074 compl = compl_first_match;
1075 if (compl_leader != NULL)
1076 lead_len = (int)STRLEN(compl_leader);
1077
1078 do
1079 {
1080 if (!ins_compl_at_original_text(compl)
1081 && (compl_leader == NULL
1082 || ins_compl_equal(compl, compl_leader, lead_len)))
1083 ++compl_match_arraysize;
1084 compl = compl->cp_next;
1085 } while (compl != NULL && compl != compl_first_match);
1086
1087 if (compl_match_arraysize == 0)
1088 return -1;
1089
1090 compl_match_array = ALLOC_CLEAR_MULT(pumitem_T, compl_match_arraysize);
1091 if (compl_match_array == NULL)
1092 return -1;
1093
1094 // If the current match is the original text don't find the first
1095 // match after it, don't highlight anything.
1096 if (ins_compl_at_original_text(compl_shown_match))
1097 shown_match_ok = TRUE;
1098
1099 i = 0;
1100 compl = compl_first_match;
1101 do
1102 {
1103 if (!ins_compl_at_original_text(compl)
1104 && (compl_leader == NULL
1105 || ins_compl_equal(compl, compl_leader, lead_len)))
1106 {
1107 if (!shown_match_ok)
1108 {
1109 if (compl == compl_shown_match || did_find_shown_match)
1110 {
1111 // This item is the shown match or this is the
1112 // first displayed item after the shown match.
1113 compl_shown_match = compl;
1114 did_find_shown_match = TRUE;
1115 shown_match_ok = TRUE;
1116 }
1117 else
1118 // Remember this displayed match for when the
1119 // shown match is just below it.
1120 shown_compl = compl;
1121 cur = i;
1122 }
1123
1124 if (compl->cp_text[CPT_ABBR] != NULL)
1125 compl_match_array[i].pum_text =
1126 compl->cp_text[CPT_ABBR];
1127 else
1128 compl_match_array[i].pum_text = compl->cp_str;
1129 compl_match_array[i].pum_kind = compl->cp_text[CPT_KIND];
1130 compl_match_array[i].pum_info = compl->cp_text[CPT_INFO];
1131 if (compl->cp_text[CPT_MENU] != NULL)
1132 compl_match_array[i++].pum_extra =
1133 compl->cp_text[CPT_MENU];
1134 else
1135 compl_match_array[i++].pum_extra = compl->cp_fname;
1136 }
1137
1138 if (compl == compl_shown_match)
1139 {
1140 did_find_shown_match = TRUE;
1141
1142 // When the original text is the shown match don't set
1143 // compl_shown_match.
1144 if (ins_compl_at_original_text(compl))
1145 shown_match_ok = TRUE;
1146
1147 if (!shown_match_ok && shown_compl != NULL)
1148 {
1149 // The shown match isn't displayed, set it to the
1150 // previously displayed match.
1151 compl_shown_match = shown_compl;
1152 shown_match_ok = TRUE;
1153 }
1154 }
1155 compl = compl->cp_next;
1156 } while (compl != NULL && compl != compl_first_match);
1157
1158 if (!shown_match_ok) // no displayed match at all
1159 cur = -1;
1160
1161 return cur;
1162}
1163
1164/*
1165 * Show the popup menu for the list of matches.
1166 * Also adjusts "compl_shown_match" to an entry that is actually displayed.
1167 */
1168 void
1169ins_compl_show_pum(void)
1170{
1171 int i;
1172 int cur = -1;
1173 colnr_T col;
1174
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001175 if (!pum_wanted() || !pum_enough_matches())
1176 return;
1177
1178#if defined(FEAT_EVAL)
1179 // Dirty hard-coded hack: remove any matchparen highlighting.
Bram Moolenaar179eb562020-12-27 18:03:22 +01001180 do_cmdline_cmd((char_u *)"if exists('g:loaded_matchparen')|:3match none|endif");
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001181#endif
1182
1183 // Update the screen later, before drawing the popup menu over it.
1184 pum_call_update_screen();
1185
1186 if (compl_match_array == NULL)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001187 // Need to build the popup menu list.
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001188 cur = ins_compl_build_pum();
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001189 else
1190 {
1191 // popup menu already exists, only need to find the current item.
1192 for (i = 0; i < compl_match_arraysize; ++i)
1193 if (compl_match_array[i].pum_text == compl_shown_match->cp_str
1194 || compl_match_array[i].pum_text
1195 == compl_shown_match->cp_text[CPT_ABBR])
1196 {
1197 cur = i;
1198 break;
1199 }
1200 }
1201
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001202 if (compl_match_array == NULL)
1203 return;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001204
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001205 // In Replace mode when a $ is displayed at the end of the line only
1206 // part of the screen would be updated. We do need to redraw here.
1207 dollar_vcol = -1;
1208
1209 // Compute the screen column of the start of the completed text.
1210 // Use the cursor to get all wrapping and other settings right.
1211 col = curwin->w_cursor.col;
1212 curwin->w_cursor.col = compl_col;
1213 pum_display(compl_match_array, compl_match_arraysize, cur);
1214 curwin->w_cursor.col = col;
Bram Moolenaard7f246c2019-04-08 18:15:41 +02001215
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02001216#ifdef FEAT_EVAL
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001217 if (has_completechanged())
1218 trigger_complete_changed_event(cur);
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02001219#endif
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001220}
1221
1222#define DICT_FIRST (1) // use just first element in "dict"
1223#define DICT_EXACT (2) // "dict" is the exact name of a file
1224
1225/*
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001226 * Add any identifiers that match the given pattern "pat" in the list of
1227 * dictionary files "dict_start" to the list of completions.
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001228 */
1229 static void
1230ins_compl_dictionaries(
1231 char_u *dict_start,
1232 char_u *pat,
1233 int flags, // DICT_FIRST and/or DICT_EXACT
1234 int thesaurus) // Thesaurus completion
1235{
1236 char_u *dict = dict_start;
1237 char_u *ptr;
1238 char_u *buf;
1239 regmatch_T regmatch;
1240 char_u **files;
1241 int count;
1242 int save_p_scs;
1243 int dir = compl_direction;
1244
1245 if (*dict == NUL)
1246 {
1247#ifdef FEAT_SPELL
1248 // When 'dictionary' is empty and spell checking is enabled use
1249 // "spell".
1250 if (!thesaurus && curwin->w_p_spell)
1251 dict = (char_u *)"spell";
1252 else
1253#endif
1254 return;
1255 }
1256
1257 buf = alloc(LSIZE);
1258 if (buf == NULL)
1259 return;
1260 regmatch.regprog = NULL; // so that we can goto theend
1261
1262 // If 'infercase' is set, don't use 'smartcase' here
1263 save_p_scs = p_scs;
1264 if (curbuf->b_p_inf)
1265 p_scs = FALSE;
1266
1267 // When invoked to match whole lines for CTRL-X CTRL-L adjust the pattern
1268 // to only match at the start of a line. Otherwise just match the
1269 // pattern. Also need to double backslashes.
1270 if (ctrl_x_mode_line_or_eval())
1271 {
1272 char_u *pat_esc = vim_strsave_escaped(pat, (char_u *)"\\");
1273 size_t len;
1274
1275 if (pat_esc == NULL)
1276 goto theend;
1277 len = STRLEN(pat_esc) + 10;
Bram Moolenaar964b3742019-05-24 18:54:09 +02001278 ptr = alloc(len);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001279 if (ptr == NULL)
1280 {
1281 vim_free(pat_esc);
1282 goto theend;
1283 }
1284 vim_snprintf((char *)ptr, len, "^\\s*\\zs\\V%s", pat_esc);
1285 regmatch.regprog = vim_regcomp(ptr, RE_MAGIC);
1286 vim_free(pat_esc);
1287 vim_free(ptr);
1288 }
1289 else
1290 {
Bram Moolenaarf4e20992020-12-21 19:59:08 +01001291 regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001292 if (regmatch.regprog == NULL)
1293 goto theend;
1294 }
1295
1296 // ignore case depends on 'ignorecase', 'smartcase' and "pat"
1297 regmatch.rm_ic = ignorecase(pat);
1298 while (*dict != NUL && !got_int && !compl_interrupted)
1299 {
1300 // copy one dictionary file name into buf
1301 if (flags == DICT_EXACT)
1302 {
1303 count = 1;
1304 files = &dict;
1305 }
1306 else
1307 {
1308 // Expand wildcards in the dictionary name, but do not allow
1309 // backticks (for security, the 'dict' option may have been set in
1310 // a modeline).
1311 copy_option_part(&dict, buf, LSIZE, ",");
1312# ifdef FEAT_SPELL
1313 if (!thesaurus && STRCMP(buf, "spell") == 0)
1314 count = -1;
1315 else
1316# endif
1317 if (vim_strchr(buf, '`') != NULL
1318 || expand_wildcards(1, &buf, &count, &files,
1319 EW_FILE|EW_SILENT) != OK)
1320 count = 0;
1321 }
1322
1323# ifdef FEAT_SPELL
1324 if (count == -1)
1325 {
1326 // Complete from active spelling. Skip "\<" in the pattern, we
1327 // don't use it as a RE.
1328 if (pat[0] == '\\' && pat[1] == '<')
1329 ptr = pat + 2;
1330 else
1331 ptr = pat;
1332 spell_dump_compl(ptr, regmatch.rm_ic, &dir, 0);
1333 }
1334 else
1335# endif
1336 if (count > 0) // avoid warning for using "files" uninit
1337 {
1338 ins_compl_files(count, files, thesaurus, flags,
1339 &regmatch, buf, &dir);
1340 if (flags != DICT_EXACT)
1341 FreeWild(count, files);
1342 }
1343 if (flags != 0)
1344 break;
1345 }
1346
1347theend:
1348 p_scs = save_p_scs;
1349 vim_regfree(regmatch.regprog);
1350 vim_free(buf);
1351}
1352
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001353/*
1354 * Add all the words in the line "*buf_arg" from the thesaurus file "fname"
1355 * skipping the word at 'skip_word'. Returns OK on success.
1356 */
1357 static int
1358thesarurs_add_words_in_line(
1359 char_u *fname,
1360 char_u **buf_arg,
1361 int dir,
1362 char_u *skip_word)
1363{
1364 int status = OK;
1365 char_u *ptr;
1366 char_u *wstart;
1367
1368 // Add the other matches on the line
1369 ptr = *buf_arg;
1370 while (!got_int)
1371 {
1372 // Find start of the next word. Skip white
1373 // space and punctuation.
1374 ptr = find_word_start(ptr);
1375 if (*ptr == NUL || *ptr == NL)
1376 break;
1377 wstart = ptr;
1378
1379 // Find end of the word.
1380 if (has_mbyte)
1381 // Japanese words may have characters in
1382 // different classes, only separate words
1383 // with single-byte non-word characters.
1384 while (*ptr != NUL)
1385 {
1386 int l = (*mb_ptr2len)(ptr);
1387
1388 if (l < 2 && !vim_iswordc(*ptr))
1389 break;
1390 ptr += l;
1391 }
1392 else
1393 ptr = find_word_end(ptr);
1394
1395 // Add the word. Skip the regexp match.
1396 if (wstart != skip_word)
1397 {
1398 status = ins_compl_add_infercase(wstart, (int)(ptr - wstart), p_ic,
1399 fname, dir, FALSE);
1400 if (status == FAIL)
1401 break;
1402 }
1403 }
1404
1405 *buf_arg = ptr;
1406 return status;
1407}
1408
1409/*
1410 * Process "count" dictionary/thesaurus "files" and add the text matching
1411 * "regmatch".
1412 */
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001413 static void
1414ins_compl_files(
1415 int count,
1416 char_u **files,
1417 int thesaurus,
1418 int flags,
1419 regmatch_T *regmatch,
1420 char_u *buf,
1421 int *dir)
1422{
1423 char_u *ptr;
1424 int i;
1425 FILE *fp;
1426 int add_r;
1427
1428 for (i = 0; i < count && !got_int && !compl_interrupted; i++)
1429 {
1430 fp = mch_fopen((char *)files[i], "r"); // open dictionary file
1431 if (flags != DICT_EXACT)
1432 {
Bram Moolenaarcc233582020-12-12 13:32:07 +01001433 msg_hist_off = TRUE; // reset in msg_trunc_attr()
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001434 vim_snprintf((char *)IObuff, IOSIZE,
1435 _("Scanning dictionary: %s"), (char *)files[i]);
1436 (void)msg_trunc_attr((char *)IObuff, TRUE, HL_ATTR(HLF_R));
1437 }
1438
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001439 if (fp == NULL)
1440 continue;
1441
1442 // Read dictionary file line by line.
1443 // Check each line for a match.
1444 while (!got_int && !compl_interrupted && !vim_fgets(buf, LSIZE, fp))
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001445 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001446 ptr = buf;
1447 while (vim_regexec(regmatch, buf, (colnr_T)(ptr - buf)))
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001448 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001449 ptr = regmatch->startp[0];
1450 if (ctrl_x_mode_line_or_eval())
1451 ptr = find_line_end(ptr);
1452 else
1453 ptr = find_word_end(ptr);
1454 add_r = ins_compl_add_infercase(regmatch->startp[0],
1455 (int)(ptr - regmatch->startp[0]),
1456 p_ic, files[i], *dir, FALSE);
1457 if (thesaurus)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001458 {
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001459 // For a thesaurus, add all the words in the line
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001460 ptr = buf;
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001461 add_r = thesarurs_add_words_in_line(files[i], &ptr, *dir,
1462 regmatch->startp[0]);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001463 }
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001464 if (add_r == OK)
1465 // if dir was BACKWARD then honor it just once
1466 *dir = FORWARD;
1467 else if (add_r == FAIL)
1468 break;
1469 // avoid expensive call to vim_regexec() when at end
1470 // of line
1471 if (*ptr == '\n' || got_int)
1472 break;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001473 }
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001474 line_breakcheck();
1475 ins_compl_check_keys(50, FALSE);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001476 }
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001477 fclose(fp);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001478 }
1479}
1480
1481/*
1482 * Find the start of the next word.
1483 * Returns a pointer to the first char of the word. Also stops at a NUL.
1484 */
1485 char_u *
1486find_word_start(char_u *ptr)
1487{
1488 if (has_mbyte)
1489 while (*ptr != NUL && *ptr != '\n' && mb_get_class(ptr) <= 1)
1490 ptr += (*mb_ptr2len)(ptr);
1491 else
1492 while (*ptr != NUL && *ptr != '\n' && !vim_iswordc(*ptr))
1493 ++ptr;
1494 return ptr;
1495}
1496
1497/*
1498 * Find the end of the word. Assumes it starts inside a word.
1499 * Returns a pointer to just after the word.
1500 */
1501 char_u *
1502find_word_end(char_u *ptr)
1503{
1504 int start_class;
1505
1506 if (has_mbyte)
1507 {
1508 start_class = mb_get_class(ptr);
1509 if (start_class > 1)
1510 while (*ptr != NUL)
1511 {
1512 ptr += (*mb_ptr2len)(ptr);
1513 if (mb_get_class(ptr) != start_class)
1514 break;
1515 }
1516 }
1517 else
1518 while (vim_iswordc(*ptr))
1519 ++ptr;
1520 return ptr;
1521}
1522
1523/*
1524 * Find the end of the line, omitting CR and NL at the end.
1525 * Returns a pointer to just after the line.
1526 */
1527 static char_u *
1528find_line_end(char_u *ptr)
1529{
1530 char_u *s;
1531
1532 s = ptr + STRLEN(ptr);
1533 while (s > ptr && (s[-1] == CAR || s[-1] == NL))
1534 --s;
1535 return s;
1536}
1537
1538/*
1539 * Free the list of completions
1540 */
1541 static void
1542ins_compl_free(void)
1543{
1544 compl_T *match;
1545 int i;
1546
1547 VIM_CLEAR(compl_pattern);
1548 VIM_CLEAR(compl_leader);
1549
1550 if (compl_first_match == NULL)
1551 return;
1552
1553 ins_compl_del_pum();
1554 pum_clear();
1555
1556 compl_curr_match = compl_first_match;
1557 do
1558 {
1559 match = compl_curr_match;
1560 compl_curr_match = compl_curr_match->cp_next;
1561 vim_free(match->cp_str);
1562 // several entries may use the same fname, free it just once.
Bram Moolenaard9eefe32019-04-06 14:22:21 +02001563 if (match->cp_flags & CP_FREE_FNAME)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001564 vim_free(match->cp_fname);
1565 for (i = 0; i < CPT_COUNT; ++i)
1566 vim_free(match->cp_text[i]);
Bram Moolenaarab782c52020-01-04 19:00:11 +01001567#ifdef FEAT_EVAL
Bram Moolenaar08928322020-01-04 14:32:48 +01001568 clear_tv(&match->cp_user_data);
Bram Moolenaarab782c52020-01-04 19:00:11 +01001569#endif
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001570 vim_free(match);
1571 } while (compl_curr_match != NULL && compl_curr_match != compl_first_match);
1572 compl_first_match = compl_curr_match = NULL;
1573 compl_shown_match = NULL;
1574 compl_old_match = NULL;
1575}
1576
1577 void
1578ins_compl_clear(void)
1579{
1580 compl_cont_status = 0;
1581 compl_started = FALSE;
1582 compl_matches = 0;
1583 VIM_CLEAR(compl_pattern);
1584 VIM_CLEAR(compl_leader);
1585 edit_submode_extra = NULL;
1586 VIM_CLEAR(compl_orig_text);
1587 compl_enter_selects = FALSE;
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02001588#ifdef FEAT_EVAL
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001589 // clear v:completed_item
1590 set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02001591#endif
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001592}
1593
1594/*
1595 * Return TRUE when Insert completion is active.
1596 */
1597 int
1598ins_compl_active(void)
1599{
1600 return compl_started;
1601}
1602
1603/*
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001604 * Selected one of the matches. When FALSE the match was edited or using the
1605 * longest common string.
1606 */
1607 int
1608ins_compl_used_match(void)
1609{
1610 return compl_used_match;
1611}
1612
1613/*
1614 * Initialize get longest common string.
1615 */
1616 void
1617ins_compl_init_get_longest(void)
1618{
1619 compl_get_longest = FALSE;
1620}
1621
1622/*
1623 * Returns TRUE when insert completion is interrupted.
1624 */
1625 int
1626ins_compl_interrupted(void)
1627{
1628 return compl_interrupted;
1629}
1630
1631/*
1632 * Returns TRUE if the <Enter> key selects a match in the completion popup
1633 * menu.
1634 */
1635 int
1636ins_compl_enter_selects(void)
1637{
1638 return compl_enter_selects;
1639}
1640
1641/*
1642 * Return the column where the text starts that is being completed
1643 */
1644 colnr_T
1645ins_compl_col(void)
1646{
1647 return compl_col;
1648}
1649
1650/*
1651 * Delete one character before the cursor and show the subset of the matches
1652 * that match the word that is now before the cursor.
1653 * Returns the character to be used, NUL if the work is done and another char
1654 * to be got from the user.
1655 */
1656 int
1657ins_compl_bs(void)
1658{
1659 char_u *line;
1660 char_u *p;
1661
1662 line = ml_get_curline();
1663 p = line + curwin->w_cursor.col;
1664 MB_PTR_BACK(line, p);
1665
1666 // Stop completion when the whole word was deleted. For Omni completion
1667 // allow the word to be deleted, we won't match everything.
1668 // Respect the 'backspace' option.
1669 if ((int)(p - line) - (int)compl_col < 0
1670 || ((int)(p - line) - (int)compl_col == 0
Bram Moolenaar440cf092021-04-03 20:13:30 +02001671 && ctrl_x_mode != CTRL_X_OMNI)
1672 || ctrl_x_mode == CTRL_X_EVAL
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001673 || (!can_bs(BS_START) && (int)(p - line) - (int)compl_col
1674 - compl_length < 0))
1675 return K_BS;
1676
1677 // Deleted more than what was used to find matches or didn't finish
1678 // finding all matches: need to look for matches all over again.
1679 if (curwin->w_cursor.col <= compl_col + compl_length
1680 || ins_compl_need_restart())
1681 ins_compl_restart();
1682
1683 vim_free(compl_leader);
Bram Moolenaar71ccd032020-06-12 22:59:11 +02001684 compl_leader = vim_strnsave(line + compl_col, (p - line) - compl_col);
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00001685 if (compl_leader == NULL)
1686 return K_BS;
1687
1688 ins_compl_new_leader();
1689 if (compl_shown_match != NULL)
1690 // Make sure current match is not a hidden item.
1691 compl_curr_match = compl_shown_match;
1692 return NUL;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001693}
1694
1695/*
1696 * Return TRUE when we need to find matches again, ins_compl_restart() is to
1697 * be called.
1698 */
1699 static int
1700ins_compl_need_restart(void)
1701{
1702 // Return TRUE if we didn't complete finding matches or when the
1703 // 'completefunc' returned "always" in the "refresh" dictionary item.
1704 return compl_was_interrupted
1705 || ((ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI)
1706 && compl_opt_refresh_always);
1707}
1708
1709/*
1710 * Called after changing "compl_leader".
1711 * Show the popup menu with a different set of matches.
1712 * May also search for matches again if the previous search was interrupted.
1713 */
1714 static void
1715ins_compl_new_leader(void)
1716{
1717 ins_compl_del_pum();
1718 ins_compl_delete();
1719 ins_bytes(compl_leader + ins_compl_len());
1720 compl_used_match = FALSE;
1721
1722 if (compl_started)
1723 ins_compl_set_original_text(compl_leader);
1724 else
1725 {
1726#ifdef FEAT_SPELL
1727 spell_bad_len = 0; // need to redetect bad word
1728#endif
Bram Moolenaar32aa1022019-11-02 22:54:41 +01001729 // Matches were cleared, need to search for them now. Before drawing
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001730 // the popup menu display the changed text before the cursor. Set
1731 // "compl_restarting" to avoid that the first match is inserted.
1732 pum_call_update_screen();
1733#ifdef FEAT_GUI
1734 if (gui.in_use)
1735 {
1736 // Show the cursor after the match, not after the redrawn text.
1737 setcursor();
1738 out_flush_cursor(FALSE, FALSE);
1739 }
1740#endif
1741 compl_restarting = TRUE;
1742 if (ins_complete(Ctrl_N, TRUE) == FAIL)
1743 compl_cont_status = 0;
1744 compl_restarting = FALSE;
1745 }
1746
1747 compl_enter_selects = !compl_used_match;
1748
1749 // Show the popup menu with a different set of matches.
1750 ins_compl_show_pum();
1751
1752 // Don't let Enter select the original text when there is no popup menu.
1753 if (compl_match_array == NULL)
1754 compl_enter_selects = FALSE;
1755}
1756
1757/*
1758 * Return the length of the completion, from the completion start column to
1759 * the cursor column. Making sure it never goes below zero.
1760 */
1761 static int
1762ins_compl_len(void)
1763{
1764 int off = (int)curwin->w_cursor.col - (int)compl_col;
1765
1766 if (off < 0)
1767 return 0;
1768 return off;
1769}
1770
1771/*
1772 * Append one character to the match leader. May reduce the number of
1773 * matches.
1774 */
1775 void
1776ins_compl_addleader(int c)
1777{
1778 int cc;
1779
1780 if (stop_arrow() == FAIL)
1781 return;
1782 if (has_mbyte && (cc = (*mb_char2len)(c)) > 1)
1783 {
1784 char_u buf[MB_MAXBYTES + 1];
1785
1786 (*mb_char2bytes)(c, buf);
1787 buf[cc] = NUL;
1788 ins_char_bytes(buf, cc);
1789 if (compl_opt_refresh_always)
1790 AppendToRedobuff(buf);
1791 }
1792 else
1793 {
1794 ins_char(c);
1795 if (compl_opt_refresh_always)
1796 AppendCharToRedobuff(c);
1797 }
1798
1799 // If we didn't complete finding matches we must search again.
1800 if (ins_compl_need_restart())
1801 ins_compl_restart();
1802
1803 // When 'always' is set, don't reset compl_leader. While completing,
1804 // cursor doesn't point original position, changing compl_leader would
1805 // break redo.
1806 if (!compl_opt_refresh_always)
1807 {
1808 vim_free(compl_leader);
1809 compl_leader = vim_strnsave(ml_get_curline() + compl_col,
Bram Moolenaar71ccd032020-06-12 22:59:11 +02001810 curwin->w_cursor.col - compl_col);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001811 if (compl_leader != NULL)
1812 ins_compl_new_leader();
1813 }
1814}
1815
1816/*
1817 * Setup for finding completions again without leaving CTRL-X mode. Used when
1818 * BS or a key was typed while still searching for matches.
1819 */
1820 static void
1821ins_compl_restart(void)
1822{
1823 ins_compl_free();
1824 compl_started = FALSE;
1825 compl_matches = 0;
1826 compl_cont_status = 0;
1827 compl_cont_mode = 0;
1828}
1829
1830/*
1831 * Set the first match, the original text.
1832 */
1833 static void
1834ins_compl_set_original_text(char_u *str)
1835{
1836 char_u *p;
1837
1838 // Replace the original text entry.
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001839 // The CP_ORIGINAL_TEXT flag is either at the first item or might possibly
1840 // be at the last item for backward completion
1841 if (ins_compl_at_original_text(compl_first_match)) // safety check
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001842 {
1843 p = vim_strsave(str);
1844 if (p != NULL)
1845 {
1846 vim_free(compl_first_match->cp_str);
1847 compl_first_match->cp_str = p;
1848 }
1849 }
1850 else if (compl_first_match->cp_prev != NULL
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001851 && ins_compl_at_original_text(compl_first_match->cp_prev))
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001852 {
1853 p = vim_strsave(str);
1854 if (p != NULL)
1855 {
1856 vim_free(compl_first_match->cp_prev->cp_str);
1857 compl_first_match->cp_prev->cp_str = p;
1858 }
1859 }
1860}
1861
1862/*
1863 * Append one character to the match leader. May reduce the number of
1864 * matches.
1865 */
1866 void
1867ins_compl_addfrommatch(void)
1868{
1869 char_u *p;
1870 int len = (int)curwin->w_cursor.col - (int)compl_col;
1871 int c;
1872 compl_T *cp;
1873
1874 p = compl_shown_match->cp_str;
1875 if ((int)STRLEN(p) <= len) // the match is too short
1876 {
1877 // When still at the original match use the first entry that matches
1878 // the leader.
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001879 if (!ins_compl_at_original_text(compl_shown_match))
1880 return;
1881
1882 p = NULL;
1883 for (cp = compl_shown_match->cp_next; cp != NULL
1884 && cp != compl_first_match; cp = cp->cp_next)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001885 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001886 if (compl_leader == NULL
1887 || ins_compl_equal(cp, compl_leader,
1888 (int)STRLEN(compl_leader)))
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001889 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001890 p = cp->cp_str;
1891 break;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001892 }
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001893 }
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00001894 if (p == NULL || (int)STRLEN(p) <= len)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01001895 return;
1896 }
1897 p += len;
1898 c = PTR2CHAR(p);
1899 ins_compl_addleader(c);
1900}
1901
1902/*
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00001903 * Set the CTRL-X completion mode based on the key 'c' typed after a CTRL-X.
1904 * Uses the global variables: ctrl_x_mode, edit_submode, edit_submode_pre,
1905 * compl_cont_mode and compl_cont_status.
1906 * Returns TRUE when the character is not to be inserted.
1907 */
1908 static int
1909set_ctrl_x_mode(int c)
1910{
1911 int retval = FALSE;
1912
1913 switch (c)
1914 {
1915 case Ctrl_E:
1916 case Ctrl_Y:
1917 // scroll the window one line up or down
1918 ctrl_x_mode = CTRL_X_SCROLL;
1919 if (!(State & REPLACE_FLAG))
1920 edit_submode = (char_u *)_(" (insert) Scroll (^E/^Y)");
1921 else
1922 edit_submode = (char_u *)_(" (replace) Scroll (^E/^Y)");
1923 edit_submode_pre = NULL;
1924 showmode();
1925 break;
1926 case Ctrl_L:
1927 // complete whole line
1928 ctrl_x_mode = CTRL_X_WHOLE_LINE;
1929 break;
1930 case Ctrl_F:
1931 // complete filenames
1932 ctrl_x_mode = CTRL_X_FILES;
1933 break;
1934 case Ctrl_K:
1935 // complete words from a dictinoary
1936 ctrl_x_mode = CTRL_X_DICTIONARY;
1937 break;
1938 case Ctrl_R:
1939 // Register insertion without exiting CTRL-X mode
1940 // Simply allow ^R to happen without affecting ^X mode
1941 break;
1942 case Ctrl_T:
1943 // complete words from a thesaurus
1944 ctrl_x_mode = CTRL_X_THESAURUS;
1945 break;
1946#ifdef FEAT_COMPL_FUNC
1947 case Ctrl_U:
1948 // user defined completion
1949 ctrl_x_mode = CTRL_X_FUNCTION;
1950 break;
1951 case Ctrl_O:
1952 // omni completion
1953 ctrl_x_mode = CTRL_X_OMNI;
1954 break;
1955#endif
1956 case 's':
1957 case Ctrl_S:
1958 // complete spelling suggestions
1959 ctrl_x_mode = CTRL_X_SPELL;
1960#ifdef FEAT_SPELL
1961 ++emsg_off; // Avoid getting the E756 error twice.
1962 spell_back_to_badword();
1963 --emsg_off;
1964#endif
1965 break;
1966 case Ctrl_RSB:
1967 // complete tag names
1968 ctrl_x_mode = CTRL_X_TAGS;
1969 break;
1970#ifdef FEAT_FIND_ID
1971 case Ctrl_I:
1972 case K_S_TAB:
1973 // complete keywords from included files
1974 ctrl_x_mode = CTRL_X_PATH_PATTERNS;
1975 break;
1976 case Ctrl_D:
1977 // complete definitions from included files
1978 ctrl_x_mode = CTRL_X_PATH_DEFINES;
1979 break;
1980#endif
1981 case Ctrl_V:
1982 case Ctrl_Q:
1983 // complete vim commands
1984 ctrl_x_mode = CTRL_X_CMDLINE;
1985 break;
1986 case Ctrl_Z:
1987 // stop completion
1988 ctrl_x_mode = CTRL_X_NORMAL;
1989 edit_submode = NULL;
1990 showmode();
1991 retval = TRUE;
1992 break;
1993 case Ctrl_P:
1994 case Ctrl_N:
1995 // ^X^P means LOCAL expansion if nothing interrupted (eg we
1996 // just started ^X mode, or there were enough ^X's to cancel
1997 // the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below)
1998 // do normal expansion when interrupting a different mode (say
1999 // ^X^F^X^P or ^P^X^X^P, see below)
2000 // nothing changes if interrupting mode 0, (eg, the flag
2001 // doesn't change when going to ADDING mode -- Acevedo
2002 if (!(compl_cont_status & CONT_INTRPT))
2003 compl_cont_status |= CONT_LOCAL;
2004 else if (compl_cont_mode != 0)
2005 compl_cont_status &= ~CONT_LOCAL;
2006 // FALLTHROUGH
2007 default:
2008 // If we have typed at least 2 ^X's... for modes != 0, we set
2009 // compl_cont_status = 0 (eg, as if we had just started ^X
2010 // mode).
2011 // For mode 0, we set "compl_cont_mode" to an impossible
2012 // value, in both cases ^X^X can be used to restart the same
2013 // mode (avoiding ADDING mode).
2014 // Undocumented feature: In a mode != 0 ^X^P and ^X^X^P start
2015 // 'complete' and local ^P expansions respectively.
2016 // In mode 0 an extra ^X is needed since ^X^P goes to ADDING
2017 // mode -- Acevedo
2018 if (c == Ctrl_X)
2019 {
2020 if (compl_cont_mode != 0)
2021 compl_cont_status = 0;
2022 else
2023 compl_cont_mode = CTRL_X_NOT_DEFINED_YET;
2024 }
2025 ctrl_x_mode = CTRL_X_NORMAL;
2026 edit_submode = NULL;
2027 showmode();
2028 break;
2029 }
2030
2031 return retval;
2032}
2033
2034/*
2035 * Stop insert completion mode
2036 */
2037 static int
2038ins_compl_stop(int c, int prev_mode, int retval)
2039{
2040 char_u *ptr;
2041#ifdef FEAT_CINDENT
2042 int want_cindent;
2043#endif
2044
2045 // Get here when we have finished typing a sequence of ^N and
2046 // ^P or other completion characters in CTRL-X mode. Free up
2047 // memory that was used, and make sure we can redo the insert.
2048 if (compl_curr_match != NULL || compl_leader != NULL || c == Ctrl_E)
2049 {
2050 // If any of the original typed text has been changed, eg when
2051 // ignorecase is set, we must add back-spaces to the redo
2052 // buffer. We add as few as necessary to delete just the part
2053 // of the original text that has changed.
2054 // When using the longest match, edited the match or used
2055 // CTRL-E then don't use the current match.
2056 if (compl_curr_match != NULL && compl_used_match && c != Ctrl_E)
2057 ptr = compl_curr_match->cp_str;
2058 else
2059 ptr = NULL;
2060 ins_compl_fixRedoBufForLeader(ptr);
2061 }
2062
2063#ifdef FEAT_CINDENT
2064 want_cindent = (get_can_cindent() && cindent_on());
2065#endif
2066 // When completing whole lines: fix indent for 'cindent'.
2067 // Otherwise, break line if it's too long.
2068 if (compl_cont_mode == CTRL_X_WHOLE_LINE)
2069 {
2070#ifdef FEAT_CINDENT
2071 // re-indent the current line
2072 if (want_cindent)
2073 {
2074 do_c_expr_indent();
2075 want_cindent = FALSE; // don't do it again
2076 }
2077#endif
2078 }
2079 else
2080 {
2081 int prev_col = curwin->w_cursor.col;
2082
2083 // put the cursor on the last char, for 'tw' formatting
2084 if (prev_col > 0)
2085 dec_cursor();
2086 // only format when something was inserted
2087 if (!arrow_used && !ins_need_undo_get() && c != Ctrl_E)
2088 insertchar(NUL, 0, -1);
2089 if (prev_col > 0
2090 && ml_get_curline()[curwin->w_cursor.col] != NUL)
2091 inc_cursor();
2092 }
2093
2094 // If the popup menu is displayed pressing CTRL-Y means accepting
2095 // the selection without inserting anything. When
2096 // compl_enter_selects is set the Enter key does the same.
2097 if ((c == Ctrl_Y || (compl_enter_selects
2098 && (c == CAR || c == K_KENTER || c == NL)))
2099 && pum_visible())
2100 retval = TRUE;
2101
2102 // CTRL-E means completion is Ended, go back to the typed text.
2103 // but only do this, if the Popup is still visible
2104 if (c == Ctrl_E)
2105 {
2106 ins_compl_delete();
2107 if (compl_leader != NULL)
2108 ins_bytes(compl_leader + ins_compl_len());
2109 else if (compl_first_match != NULL)
2110 ins_bytes(compl_orig_text + ins_compl_len());
2111 retval = TRUE;
2112 }
2113
2114 auto_format(FALSE, TRUE);
2115
2116 // Trigger the CompleteDonePre event to give scripts a chance to
2117 // act upon the completion before clearing the info, and restore
2118 // ctrl_x_mode, so that complete_info() can be used.
2119 ctrl_x_mode = prev_mode;
2120 ins_apply_autocmds(EVENT_COMPLETEDONEPRE);
2121
2122 ins_compl_free();
2123 compl_started = FALSE;
2124 compl_matches = 0;
2125 if (!shortmess(SHM_COMPLETIONMENU))
2126 msg_clr_cmdline(); // necessary for "noshowmode"
2127 ctrl_x_mode = CTRL_X_NORMAL;
2128 compl_enter_selects = FALSE;
2129 if (edit_submode != NULL)
2130 {
2131 edit_submode = NULL;
2132 showmode();
2133 }
2134
2135#ifdef FEAT_CMDWIN
2136 if (c == Ctrl_C && cmdwin_type != 0)
2137 // Avoid the popup menu remains displayed when leaving the
2138 // command line window.
2139 update_screen(0);
2140#endif
2141#ifdef FEAT_CINDENT
2142 // Indent now if a key was typed that is in 'cinkeys'.
2143 if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0)))
2144 do_c_expr_indent();
2145#endif
2146 // Trigger the CompleteDone event to give scripts a chance to act
2147 // upon the end of completion.
2148 ins_apply_autocmds(EVENT_COMPLETEDONE);
2149
2150 return retval;
2151}
2152
2153/*
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002154 * Prepare for Insert mode completion, or stop it.
2155 * Called just after typing a character in Insert mode.
2156 * Returns TRUE when the character is not to be inserted;
2157 */
2158 int
2159ins_compl_prep(int c)
2160{
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002161 int retval = FALSE;
Bram Moolenaar17e04782020-01-17 18:58:59 +01002162 int prev_mode = ctrl_x_mode;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002163
2164 // Forget any previous 'special' messages if this is actually
2165 // a ^X mode key - bar ^R, in which case we wait to see what it gives us.
2166 if (c != Ctrl_R && vim_is_ctrl_x_key(c))
2167 edit_submode_extra = NULL;
2168
2169 // Ignore end of Select mode mapping and mouse scroll buttons.
2170 if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP
Bram Moolenaar957cf672020-11-12 14:21:06 +01002171 || c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_COMMAND)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002172 return retval;
2173
Bram Moolenaar05ad5ff2019-11-30 22:48:27 +01002174#ifdef FEAT_PROP_POPUP
Bram Moolenaarf0bc15c2019-08-18 19:23:45 +02002175 // Ignore mouse events in a popup window
2176 if (is_mouse_key(c))
2177 {
2178 // Ignore drag and release events, the position does not need to be in
2179 // the popup and it may have just closed.
2180 if (c == K_LEFTRELEASE
2181 || c == K_LEFTRELEASE_NM
2182 || c == K_MIDDLERELEASE
2183 || c == K_RIGHTRELEASE
2184 || c == K_X1RELEASE
2185 || c == K_X2RELEASE
2186 || c == K_LEFTDRAG
2187 || c == K_MIDDLEDRAG
2188 || c == K_RIGHTDRAG
2189 || c == K_X1DRAG
2190 || c == K_X2DRAG)
2191 return retval;
2192 if (popup_visible)
2193 {
2194 int row = mouse_row;
2195 int col = mouse_col;
2196 win_T *wp = mouse_find_win(&row, &col, FIND_POPUP);
2197
2198 if (wp != NULL && WIN_IS_POPUP(wp))
2199 return retval;
2200 }
2201 }
2202#endif
2203
zeertzjqdca29d92021-08-31 19:12:51 +02002204 if (ctrl_x_mode == CTRL_X_CMDLINE_CTRL_X && c != Ctrl_X)
2205 {
2206 if (c == Ctrl_V || c == Ctrl_Q || c == Ctrl_Z || ins_compl_pum_key(c)
2207 || !vim_is_ctrl_x_key(c))
2208 {
2209 // Not starting another completion mode.
2210 ctrl_x_mode = CTRL_X_CMDLINE;
2211
2212 // CTRL-X CTRL-Z should stop completion without inserting anything
2213 if (c == Ctrl_Z)
2214 retval = TRUE;
2215 }
2216 else
2217 {
2218 ctrl_x_mode = CTRL_X_CMDLINE;
2219
2220 // Other CTRL-X keys first stop completion, then start another
2221 // completion mode.
2222 ins_compl_prep(' ');
2223 ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
2224 }
2225 }
2226
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002227 // Set "compl_get_longest" when finding the first matches.
2228 if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET
2229 || (ctrl_x_mode == CTRL_X_NORMAL && !compl_started))
2230 {
2231 compl_get_longest = (strstr((char *)p_cot, "longest") != NULL);
2232 compl_used_match = TRUE;
2233
2234 }
2235
2236 if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002237 // We have just typed CTRL-X and aren't quite sure which CTRL-X mode
2238 // it will be yet. Now we decide.
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00002239 retval = set_ctrl_x_mode(c);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002240 else if (ctrl_x_mode != CTRL_X_NORMAL)
2241 {
2242 // We're already in CTRL-X mode, do we stay in it?
2243 if (!vim_is_ctrl_x_key(c))
2244 {
2245 if (ctrl_x_mode == CTRL_X_SCROLL)
2246 ctrl_x_mode = CTRL_X_NORMAL;
2247 else
2248 ctrl_x_mode = CTRL_X_FINISHED;
2249 edit_submode = NULL;
2250 }
2251 showmode();
2252 }
2253
2254 if (compl_started || ctrl_x_mode == CTRL_X_FINISHED)
2255 {
2256 // Show error message from attempted keyword completion (probably
2257 // 'Pattern not found') until another key is hit, then go back to
2258 // showing what mode we are in.
2259 showmode();
2260 if ((ctrl_x_mode == CTRL_X_NORMAL && c != Ctrl_N && c != Ctrl_P
2261 && c != Ctrl_R && !ins_compl_pum_key(c))
2262 || ctrl_x_mode == CTRL_X_FINISHED)
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00002263 retval = ins_compl_stop(c, prev_mode, retval);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002264 }
2265 else if (ctrl_x_mode == CTRL_X_LOCAL_MSG)
2266 // Trigger the CompleteDone event to give scripts a chance to act
2267 // upon the (possibly failed) completion.
2268 ins_apply_autocmds(EVENT_COMPLETEDONE);
2269
=?UTF-8?q?Magnus=20Gro=C3=9F?=25def2c2021-10-22 18:56:39 +01002270 trigger_modechanged();
2271
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002272 // reset continue_* if we left expansion-mode, if we stay they'll be
2273 // (re)set properly in ins_complete()
2274 if (!vim_is_ctrl_x_key(c))
2275 {
2276 compl_cont_status = 0;
2277 compl_cont_mode = 0;
2278 }
2279
2280 return retval;
2281}
2282
2283/*
2284 * Fix the redo buffer for the completion leader replacing some of the typed
2285 * text. This inserts backspaces and appends the changed text.
2286 * "ptr" is the known leader text or NUL.
2287 */
2288 static void
2289ins_compl_fixRedoBufForLeader(char_u *ptr_arg)
2290{
2291 int len;
2292 char_u *p;
2293 char_u *ptr = ptr_arg;
2294
2295 if (ptr == NULL)
2296 {
2297 if (compl_leader != NULL)
2298 ptr = compl_leader;
2299 else
2300 return; // nothing to do
2301 }
2302 if (compl_orig_text != NULL)
2303 {
2304 p = compl_orig_text;
2305 for (len = 0; p[len] != NUL && p[len] == ptr[len]; ++len)
2306 ;
2307 if (len > 0)
2308 len -= (*mb_head_off)(p, p + len);
2309 for (p += len; *p != NUL; MB_PTR_ADV(p))
2310 AppendCharToRedobuff(K_BS);
2311 }
2312 else
2313 len = 0;
2314 if (ptr != NULL)
2315 AppendToRedobuffLit(ptr + len, -1);
2316}
2317
2318/*
2319 * Loops through the list of windows, loaded-buffers or non-loaded-buffers
2320 * (depending on flag) starting from buf and looking for a non-scanned
2321 * buffer (other than curbuf). curbuf is special, if it is called with
2322 * buf=curbuf then it has to be the first call for a given flag/expansion.
2323 *
2324 * Returns the buffer to scan, if any, otherwise returns curbuf -- Acevedo
2325 */
2326 static buf_T *
2327ins_compl_next_buf(buf_T *buf, int flag)
2328{
2329 static win_T *wp = NULL;
2330
2331 if (flag == 'w') // just windows
2332 {
2333 if (buf == curbuf || wp == NULL) // first call for this flag/expansion
2334 wp = curwin;
2335 while ((wp = (wp->w_next != NULL ? wp->w_next : firstwin)) != curwin
2336 && wp->w_buffer->b_scanned)
2337 ;
2338 buf = wp->w_buffer;
2339 }
2340 else
2341 // 'b' (just loaded buffers), 'u' (just non-loaded buffers) or 'U'
2342 // (unlisted buffers)
2343 // When completing whole lines skip unloaded buffers.
2344 while ((buf = (buf->b_next != NULL ? buf->b_next : firstbuf)) != curbuf
2345 && ((flag == 'U'
2346 ? buf->b_p_bl
2347 : (!buf->b_p_bl
2348 || (buf->b_ml.ml_mfp == NULL) != (flag == 'u')))
2349 || buf->b_scanned))
2350 ;
2351 return buf;
2352}
2353
2354#ifdef FEAT_COMPL_FUNC
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002355
2356# ifdef FEAT_EVAL
2357static callback_T cfu_cb; // 'completefunc' callback function
2358static callback_T ofu_cb; // 'omnifunc' callback function
2359static callback_T tsrfu_cb; // 'thesaurusfunc' callback function
2360# endif
2361
2362/*
2363 * Copy a global callback function to a buffer local callback.
2364 */
2365 static void
2366copy_global_to_buflocal_cb(callback_T *globcb, callback_T *bufcb)
2367{
2368 free_callback(bufcb);
2369 if (globcb->cb_name != NULL && *globcb->cb_name != NUL)
2370 copy_callback(bufcb, globcb);
2371}
2372
2373/*
2374 * Parse the 'completefunc' option value and set the callback function.
2375 * Invoked when the 'completefunc' option is set. The option value can be a
2376 * name of a function (string), or function(<name>) or funcref(<name>) or a
2377 * lambda expression.
2378 */
2379 int
2380set_completefunc_option(void)
2381{
2382 int retval;
2383
2384 retval = option_set_callback_func(curbuf->b_p_cfu, &cfu_cb);
2385 if (retval == OK)
2386 set_buflocal_cfu_callback(curbuf);
2387
2388 return retval;
2389}
2390
2391/*
2392 * Copy the global 'completefunc' callback function to the buffer-local
2393 * 'completefunc' callback for 'buf'.
2394 */
2395 void
2396set_buflocal_cfu_callback(buf_T *buf UNUSED)
2397{
2398# ifdef FEAT_EVAL
2399 copy_global_to_buflocal_cb(&cfu_cb, &buf->b_cfu_cb);
2400# endif
2401}
2402
2403/*
2404 * Parse the 'omnifunc' option value and set the callback function.
2405 * Invoked when the 'omnifunc' option is set. The option value can be a
2406 * name of a function (string), or function(<name>) or funcref(<name>) or a
2407 * lambda expression.
2408 */
2409 int
2410set_omnifunc_option(void)
2411{
2412 int retval;
2413
2414 retval = option_set_callback_func(curbuf->b_p_ofu, &ofu_cb);
2415 if (retval == OK)
2416 set_buflocal_ofu_callback(curbuf);
2417
2418 return retval;
2419}
2420
2421/*
2422 * Copy the global 'omnifunc' callback function to the buffer-local 'omnifunc'
2423 * callback for 'buf'.
2424 */
2425 void
2426set_buflocal_ofu_callback(buf_T *buf UNUSED)
2427{
2428# ifdef FEAT_EVAL
2429 copy_global_to_buflocal_cb(&ofu_cb, &buf->b_ofu_cb);
2430# endif
2431}
2432
2433/*
2434 * Parse the 'thesaurusfunc' option value and set the callback function.
2435 * Invoked when the 'thesaurusfunc' option is set. The option value can be a
2436 * name of a function (string), or function(<name>) or funcref(<name>) or a
2437 * lambda expression.
2438 */
2439 int
2440set_thesaurusfunc_option(void)
2441{
2442 int retval;
2443
2444 if (*curbuf->b_p_tsrfu != NUL)
2445 {
2446 // buffer-local option set
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002447 retval = option_set_callback_func(curbuf->b_p_tsrfu,
2448 &curbuf->b_tsrfu_cb);
2449 }
2450 else
2451 {
2452 // global option set
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002453 retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
2454 }
2455
2456 return retval;
2457}
2458
Yegappan Lakshmanan6ae8fae2021-12-12 16:26:44 +00002459/*
2460 * Mark the global 'completefunc' 'omnifunc' and 'thesaurusfunc' callbacks with
2461 * 'copyID' so that they are not garbage collected.
2462 */
2463 int
2464set_ref_in_insexpand_funcs(int copyID)
2465{
2466 int abort = FALSE;
2467
2468 abort = set_ref_in_callback(&cfu_cb, copyID);
2469 abort = abort || set_ref_in_callback(&ofu_cb, copyID);
2470 abort = abort || set_ref_in_callback(&tsrfu_cb, copyID);
2471
2472 return abort;
2473}
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002474
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002475/*
Yegappan Lakshmanan160e9942021-10-16 15:41:29 +01002476 * Get the user-defined completion function name for completion 'type'
2477 */
2478 static char_u *
2479get_complete_funcname(int type)
2480{
2481 switch (type)
2482 {
2483 case CTRL_X_FUNCTION:
2484 return curbuf->b_p_cfu;
2485 case CTRL_X_OMNI:
2486 return curbuf->b_p_ofu;
2487 case CTRL_X_THESAURUS:
Bram Moolenaarf4d8b762021-10-17 14:13:09 +01002488 return *curbuf->b_p_tsrfu == NUL ? p_tsrfu : curbuf->b_p_tsrfu;
Yegappan Lakshmanan160e9942021-10-16 15:41:29 +01002489 default:
2490 return (char_u *)"";
2491 }
2492}
2493
2494/*
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002495 * Get the callback to use for insert mode completion.
2496 */
2497 callback_T *
2498get_insert_callback(int type)
2499{
2500 if (type == CTRL_X_FUNCTION)
2501 return &curbuf->b_cfu_cb;
2502 if (type == CTRL_X_OMNI)
2503 return &curbuf->b_ofu_cb;
2504 // CTRL_X_THESAURUS
2505 return (*curbuf->b_p_tsrfu != NUL) ? &curbuf->b_tsrfu_cb : &tsrfu_cb;
2506}
2507
2508/*
Yegappan Lakshmanan05e59e32021-12-01 10:30:07 +00002509 * Execute user defined complete function 'completefunc', 'omnifunc' or
2510 * 'thesaurusfunc', and get matches in "matches".
2511 * "type" is either CTRL_X_OMNI or CTRL_X_FUNCTION or CTRL_X_THESAURUS.
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002512 */
2513 static void
Yegappan Lakshmanan05e59e32021-12-01 10:30:07 +00002514expand_by_function(int type, char_u *base)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002515{
2516 list_T *matchlist = NULL;
2517 dict_T *matchdict = NULL;
2518 typval_T args[3];
2519 char_u *funcname;
2520 pos_T pos;
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002521 callback_T *cb;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002522 typval_T rettv;
2523 int save_State = State;
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002524 int retval;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002525
Yegappan Lakshmanan160e9942021-10-16 15:41:29 +01002526 funcname = get_complete_funcname(type);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002527 if (*funcname == NUL)
2528 return;
2529
2530 // Call 'completefunc' to obtain the list of matches.
2531 args[0].v_type = VAR_NUMBER;
2532 args[0].vval.v_number = 0;
2533 args[1].v_type = VAR_STRING;
2534 args[1].vval.v_string = base != NULL ? base : (char_u *)"";
2535 args[2].v_type = VAR_UNKNOWN;
2536
2537 pos = curwin->w_cursor;
Bram Moolenaar28976e22021-01-29 21:07:07 +01002538 // Lock the text to avoid weird things from happening. Also disallow
2539 // switching to another window, it should not be needed and may end up in
2540 // Insert mode in another buffer.
2541 ++textwinlock;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002542
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002543 cb = get_insert_callback(type);
2544 retval = call_callback(cb, 0, &rettv, 2, args);
2545
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002546 // Call a function, which returns a list or dict.
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00002547 if (retval == OK)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002548 {
2549 switch (rettv.v_type)
2550 {
2551 case VAR_LIST:
2552 matchlist = rettv.vval.v_list;
2553 break;
2554 case VAR_DICT:
2555 matchdict = rettv.vval.v_dict;
2556 break;
2557 case VAR_SPECIAL:
2558 if (rettv.vval.v_number == VVAL_NONE)
2559 compl_opt_suppress_empty = TRUE;
2560 // FALLTHROUGH
2561 default:
2562 // TODO: Give error message?
2563 clear_tv(&rettv);
2564 break;
2565 }
2566 }
Bram Moolenaar28976e22021-01-29 21:07:07 +01002567 --textwinlock;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002568
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002569 curwin->w_cursor = pos; // restore the cursor position
2570 validate_cursor();
2571 if (!EQUAL_POS(curwin->w_cursor, pos))
2572 {
2573 emsg(_(e_compldel));
2574 goto theend;
2575 }
2576
2577 if (matchlist != NULL)
2578 ins_compl_add_list(matchlist);
2579 else if (matchdict != NULL)
2580 ins_compl_add_dict(matchdict);
2581
2582theend:
2583 // Restore State, it might have been changed.
2584 State = save_State;
2585
2586 if (matchdict != NULL)
2587 dict_unref(matchdict);
2588 if (matchlist != NULL)
2589 list_unref(matchlist);
2590}
2591#endif // FEAT_COMPL_FUNC
2592
2593#if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL) || defined(PROTO)
2594/*
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002595 * Add a match to the list of matches from a typeval_T.
2596 * If the given string is already in the list of completions, then return
2597 * NOTDONE, otherwise add it to the list and return OK. If there is an error,
2598 * maybe because alloc() returns NULL, then FAIL is returned.
Bram Moolenaar440cf092021-04-03 20:13:30 +02002599 * When "fast" is TRUE use fast_breakcheck() instead of ui_breakcheck().
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002600 */
2601 static int
Bram Moolenaar440cf092021-04-03 20:13:30 +02002602ins_compl_add_tv(typval_T *tv, int dir, int fast)
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002603{
2604 char_u *word;
2605 int dup = FALSE;
2606 int empty = FALSE;
Bram Moolenaar440cf092021-04-03 20:13:30 +02002607 int flags = fast ? CP_FAST : 0;
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002608 char_u *(cptext[CPT_COUNT]);
Bram Moolenaar08928322020-01-04 14:32:48 +01002609 typval_T user_data;
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002610
Bram Moolenaar08928322020-01-04 14:32:48 +01002611 user_data.v_type = VAR_UNKNOWN;
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002612 if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL)
2613 {
2614 word = dict_get_string(tv->vval.v_dict, (char_u *)"word", FALSE);
2615 cptext[CPT_ABBR] = dict_get_string(tv->vval.v_dict,
2616 (char_u *)"abbr", FALSE);
2617 cptext[CPT_MENU] = dict_get_string(tv->vval.v_dict,
2618 (char_u *)"menu", FALSE);
2619 cptext[CPT_KIND] = dict_get_string(tv->vval.v_dict,
2620 (char_u *)"kind", FALSE);
2621 cptext[CPT_INFO] = dict_get_string(tv->vval.v_dict,
2622 (char_u *)"info", FALSE);
Bram Moolenaar08928322020-01-04 14:32:48 +01002623 dict_get_tv(tv->vval.v_dict, (char_u *)"user_data", &user_data);
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002624 if (dict_get_string(tv->vval.v_dict, (char_u *)"icase", FALSE) != NULL
2625 && dict_get_number(tv->vval.v_dict, (char_u *)"icase"))
2626 flags |= CP_ICASE;
2627 if (dict_get_string(tv->vval.v_dict, (char_u *)"dup", FALSE) != NULL)
2628 dup = dict_get_number(tv->vval.v_dict, (char_u *)"dup");
2629 if (dict_get_string(tv->vval.v_dict, (char_u *)"empty", FALSE) != NULL)
2630 empty = dict_get_number(tv->vval.v_dict, (char_u *)"empty");
2631 if (dict_get_string(tv->vval.v_dict, (char_u *)"equal", FALSE) != NULL
2632 && dict_get_number(tv->vval.v_dict, (char_u *)"equal"))
2633 flags |= CP_EQUAL;
2634 }
2635 else
2636 {
2637 word = tv_get_string_chk(tv);
Bram Moolenaara80faa82020-04-12 19:37:17 +02002638 CLEAR_FIELD(cptext);
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002639 }
2640 if (word == NULL || (!empty && *word == NUL))
2641 return FAIL;
Bram Moolenaar08928322020-01-04 14:32:48 +01002642 return ins_compl_add(word, -1, NULL, cptext, &user_data, dir, flags, dup);
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002643}
2644
2645/*
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002646 * Add completions from a list.
2647 */
2648 static void
2649ins_compl_add_list(list_T *list)
2650{
2651 listitem_T *li;
2652 int dir = compl_direction;
2653
2654 // Go through the List with matches and add each of them.
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02002655 CHECK_LIST_MATERIALIZE(list);
Bram Moolenaaraeea7212020-04-02 18:50:46 +02002656 FOR_ALL_LIST_ITEMS(list, li)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002657 {
Bram Moolenaar440cf092021-04-03 20:13:30 +02002658 if (ins_compl_add_tv(&li->li_tv, dir, TRUE) == OK)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002659 // if dir was BACKWARD then honor it just once
2660 dir = FORWARD;
2661 else if (did_emsg)
2662 break;
2663 }
2664}
2665
2666/*
2667 * Add completions from a dict.
2668 */
2669 static void
2670ins_compl_add_dict(dict_T *dict)
2671{
2672 dictitem_T *di_refresh;
2673 dictitem_T *di_words;
2674
2675 // Check for optional "refresh" item.
2676 compl_opt_refresh_always = FALSE;
2677 di_refresh = dict_find(dict, (char_u *)"refresh", 7);
2678 if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING)
2679 {
2680 char_u *v = di_refresh->di_tv.vval.v_string;
2681
2682 if (v != NULL && STRCMP(v, (char_u *)"always") == 0)
2683 compl_opt_refresh_always = TRUE;
2684 }
2685
2686 // Add completions from a "words" list.
2687 di_words = dict_find(dict, (char_u *)"words", 5);
2688 if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST)
2689 ins_compl_add_list(di_words->di_tv.vval.v_list);
2690}
2691
2692/*
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02002693 * Start completion for the complete() function.
2694 * "startcol" is where the matched text starts (1 is first column).
2695 * "list" is the list of matches.
2696 */
2697 static void
2698set_completion(colnr_T startcol, list_T *list)
2699{
2700 int save_w_wrow = curwin->w_wrow;
2701 int save_w_leftcol = curwin->w_leftcol;
2702 int flags = CP_ORIGINAL_TEXT;
2703
2704 // If already doing completions stop it.
2705 if (ctrl_x_mode != CTRL_X_NORMAL)
2706 ins_compl_prep(' ');
2707 ins_compl_clear();
2708 ins_compl_free();
2709
2710 compl_direction = FORWARD;
2711 if (startcol > curwin->w_cursor.col)
2712 startcol = curwin->w_cursor.col;
2713 compl_col = startcol;
2714 compl_length = (int)curwin->w_cursor.col - (int)startcol;
2715 // compl_pattern doesn't need to be set
2716 compl_orig_text = vim_strnsave(ml_get_curline() + compl_col, compl_length);
2717 if (p_ic)
2718 flags |= CP_ICASE;
2719 if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
Bram Moolenaar440cf092021-04-03 20:13:30 +02002720 -1, NULL, NULL, NULL, 0,
2721 flags | CP_FAST, FALSE) != OK)
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02002722 return;
2723
2724 ctrl_x_mode = CTRL_X_EVAL;
2725
2726 ins_compl_add_list(list);
2727 compl_matches = ins_compl_make_cyclic();
2728 compl_started = TRUE;
2729 compl_used_match = TRUE;
2730 compl_cont_status = 0;
2731
2732 compl_curr_match = compl_first_match;
2733 if (compl_no_insert || compl_no_select)
2734 {
2735 ins_complete(K_DOWN, FALSE);
2736 if (compl_no_select)
2737 // Down/Up has no real effect.
2738 ins_complete(K_UP, FALSE);
2739 }
2740 else
2741 ins_complete(Ctrl_N, FALSE);
2742 compl_enter_selects = compl_no_insert;
2743
2744 // Lazily show the popup menu, unless we got interrupted.
2745 if (!compl_interrupted)
2746 show_pum(save_w_wrow, save_w_leftcol);
=?UTF-8?q?Magnus=20Gro=C3=9F?=25def2c2021-10-22 18:56:39 +01002747 trigger_modechanged();
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02002748 out_flush();
2749}
2750
2751/*
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002752 * "complete()" function
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002753 */
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002754 void
2755f_complete(typval_T *argvars, typval_T *rettv UNUSED)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002756{
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002757 int startcol;
Bram Moolenaarff06f282020-04-21 22:01:14 +02002758 int save_textlock = textlock;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002759
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002760 if (in_vim9script()
2761 && (check_for_number_arg(argvars, 0) == FAIL
2762 || check_for_list_arg(argvars, 1) == FAIL))
2763 return;
2764
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002765 if ((State & INSERT) == 0)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002766 {
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002767 emsg(_("E785: complete() can only be used in Insert mode"));
2768 return;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002769 }
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002770
Bram Moolenaar6adb9ea2020-04-30 22:31:18 +02002771 // "textlock" is set when evaluating 'completefunc' but we can change
2772 // text here.
Bram Moolenaarff06f282020-04-21 22:01:14 +02002773 textlock = 0;
2774
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002775 // Check for undo allowed here, because if something was already inserted
2776 // the line was already saved for undo and this check isn't done.
2777 if (!undo_allowed())
2778 return;
2779
2780 if (argvars[1].v_type != VAR_LIST || argvars[1].vval.v_list == NULL)
Bram Moolenaar436b5ad2021-12-31 22:49:24 +00002781 emsg(_(e_invalid_argument));
Bram Moolenaarff06f282020-04-21 22:01:14 +02002782 else
2783 {
2784 startcol = (int)tv_get_number_chk(&argvars[0], NULL);
2785 if (startcol > 0)
2786 set_completion(startcol - 1, argvars[1].vval.v_list);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01002787 }
Bram Moolenaarff06f282020-04-21 22:01:14 +02002788 textlock = save_textlock;
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002789}
2790
2791/*
2792 * "complete_add()" function
2793 */
2794 void
2795f_complete_add(typval_T *argvars, typval_T *rettv)
2796{
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02002797 if (in_vim9script() && check_for_string_or_dict_arg(argvars, 0) == FAIL)
Yegappan Lakshmanan83494b42021-07-20 17:51:51 +02002798 return;
2799
Bram Moolenaar440cf092021-04-03 20:13:30 +02002800 rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0, FALSE);
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002801}
2802
2803/*
2804 * "complete_check()" function
2805 */
2806 void
2807f_complete_check(typval_T *argvars UNUSED, typval_T *rettv)
2808{
2809 int saved = RedrawingDisabled;
2810
2811 RedrawingDisabled = 0;
2812 ins_compl_check_keys(0, TRUE);
2813 rettv->vval.v_number = ins_compl_interrupted();
2814 RedrawingDisabled = saved;
2815}
2816
2817/*
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02002818 * Return Insert completion mode name string
2819 */
2820 static char_u *
2821ins_compl_mode(void)
2822{
zeertzjq27fef592021-10-03 12:01:27 +01002823 if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET || ctrl_x_mode == CTRL_X_SCROLL
2824 || compl_started)
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02002825 return (char_u *)ctrl_x_mode_names[ctrl_x_mode & ~CTRL_X_WANT_IDENT];
2826
2827 return (char_u *)"";
2828}
2829
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00002830/*
2831 * Assign the sequence number to all the completion matches which don't have
2832 * one assigned yet.
2833 */
Bram Moolenaarf9d51352020-10-26 19:22:42 +01002834 static void
2835ins_compl_update_sequence_numbers()
2836{
2837 int number = 0;
2838 compl_T *match;
2839
2840 if (compl_direction == FORWARD)
2841 {
2842 // search backwards for the first valid (!= -1) number.
2843 // This should normally succeed already at the first loop
2844 // cycle, so it's fast!
2845 for (match = compl_curr_match->cp_prev; match != NULL
2846 && match != compl_first_match;
2847 match = match->cp_prev)
2848 if (match->cp_number != -1)
2849 {
2850 number = match->cp_number;
2851 break;
2852 }
2853 if (match != NULL)
2854 // go up and assign all numbers which are not assigned
2855 // yet
2856 for (match = match->cp_next;
2857 match != NULL && match->cp_number == -1;
2858 match = match->cp_next)
2859 match->cp_number = ++number;
2860 }
2861 else // BACKWARD
2862 {
2863 // search forwards (upwards) for the first valid (!= -1)
2864 // number. This should normally succeed already at the
2865 // first loop cycle, so it's fast!
2866 for (match = compl_curr_match->cp_next; match != NULL
2867 && match != compl_first_match;
2868 match = match->cp_next)
2869 if (match->cp_number != -1)
2870 {
2871 number = match->cp_number;
2872 break;
2873 }
2874 if (match != NULL)
2875 // go down and assign all numbers which are not
2876 // assigned yet
2877 for (match = match->cp_prev; match
2878 && match->cp_number == -1;
2879 match = match->cp_prev)
2880 match->cp_number = ++number;
2881 }
2882}
2883
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02002884/*
2885 * Get complete information
2886 */
2887 static void
2888get_complete_info(list_T *what_list, dict_T *retdict)
2889{
2890 int ret = OK;
2891 listitem_T *item;
2892#define CI_WHAT_MODE 0x01
2893#define CI_WHAT_PUM_VISIBLE 0x02
2894#define CI_WHAT_ITEMS 0x04
2895#define CI_WHAT_SELECTED 0x08
2896#define CI_WHAT_INSERTED 0x10
2897#define CI_WHAT_ALL 0xff
2898 int what_flag;
2899
2900 if (what_list == NULL)
2901 what_flag = CI_WHAT_ALL;
2902 else
2903 {
2904 what_flag = 0;
Bram Moolenaar7e9f3512020-05-13 22:44:22 +02002905 CHECK_LIST_MATERIALIZE(what_list);
Bram Moolenaaraeea7212020-04-02 18:50:46 +02002906 FOR_ALL_LIST_ITEMS(what_list, item)
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02002907 {
2908 char_u *what = tv_get_string(&item->li_tv);
2909
2910 if (STRCMP(what, "mode") == 0)
2911 what_flag |= CI_WHAT_MODE;
2912 else if (STRCMP(what, "pum_visible") == 0)
2913 what_flag |= CI_WHAT_PUM_VISIBLE;
2914 else if (STRCMP(what, "items") == 0)
2915 what_flag |= CI_WHAT_ITEMS;
2916 else if (STRCMP(what, "selected") == 0)
2917 what_flag |= CI_WHAT_SELECTED;
2918 else if (STRCMP(what, "inserted") == 0)
2919 what_flag |= CI_WHAT_INSERTED;
2920 }
2921 }
2922
2923 if (ret == OK && (what_flag & CI_WHAT_MODE))
2924 ret = dict_add_string(retdict, "mode", ins_compl_mode());
2925
2926 if (ret == OK && (what_flag & CI_WHAT_PUM_VISIBLE))
2927 ret = dict_add_number(retdict, "pum_visible", pum_visible());
2928
2929 if (ret == OK && (what_flag & CI_WHAT_ITEMS))
2930 {
2931 list_T *li;
2932 dict_T *di;
2933 compl_T *match;
2934
2935 li = list_alloc();
2936 if (li == NULL)
2937 return;
2938 ret = dict_add_list(retdict, "items", li);
2939 if (ret == OK && compl_first_match != NULL)
2940 {
2941 match = compl_first_match;
2942 do
2943 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00002944 if (!ins_compl_at_original_text(match))
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02002945 {
2946 di = dict_alloc();
2947 if (di == NULL)
2948 return;
2949 ret = list_append_dict(li, di);
2950 if (ret != OK)
2951 return;
2952 dict_add_string(di, "word", match->cp_str);
2953 dict_add_string(di, "abbr", match->cp_text[CPT_ABBR]);
2954 dict_add_string(di, "menu", match->cp_text[CPT_MENU]);
2955 dict_add_string(di, "kind", match->cp_text[CPT_KIND]);
2956 dict_add_string(di, "info", match->cp_text[CPT_INFO]);
Bram Moolenaar08928322020-01-04 14:32:48 +01002957 if (match->cp_user_data.v_type == VAR_UNKNOWN)
2958 // Add an empty string for backwards compatibility
2959 dict_add_string(di, "user_data", (char_u *)"");
2960 else
2961 dict_add_tv(di, "user_data", &match->cp_user_data);
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02002962 }
2963 match = match->cp_next;
2964 }
2965 while (match != NULL && match != compl_first_match);
2966 }
2967 }
2968
2969 if (ret == OK && (what_flag & CI_WHAT_SELECTED))
Bram Moolenaarf9d51352020-10-26 19:22:42 +01002970 {
2971 if (compl_curr_match != NULL && compl_curr_match->cp_number == -1)
2972 ins_compl_update_sequence_numbers();
2973 ret = dict_add_number(retdict, "selected", compl_curr_match != NULL
2974 ? compl_curr_match->cp_number - 1 : -1);
2975 }
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02002976
2977 // TODO
2978 // if (ret == OK && (what_flag & CI_WHAT_INSERTED))
2979}
2980
2981/*
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002982 * "complete_info()" function
2983 */
2984 void
2985f_complete_info(typval_T *argvars, typval_T *rettv)
2986{
2987 list_T *what_list = NULL;
2988
2989 if (rettv_dict_alloc(rettv) != OK)
2990 return;
2991
Yegappan Lakshmanan4490ec42021-07-27 22:00:44 +02002992 if (in_vim9script() && check_for_opt_list_arg(argvars, 0) == FAIL)
2993 return;
2994
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02002995 if (argvars[0].v_type != VAR_UNKNOWN)
2996 {
2997 if (argvars[0].v_type != VAR_LIST)
2998 {
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00002999 emsg(_(e_list_required));
Bram Moolenaar9bca58f2019-08-15 21:31:52 +02003000 return;
3001 }
3002 what_list = argvars[0].vval.v_list;
3003 }
3004 get_complete_info(what_list, rettv->vval.v_dict);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003005}
3006#endif
3007
3008/*
Yegappan Lakshmanan160e9942021-10-16 15:41:29 +01003009 * Returns TRUE when using a user-defined function for thesaurus completion.
3010 */
3011 static int
3012thesaurus_func_complete(int type UNUSED)
3013{
3014#ifdef FEAT_COMPL_FUNC
Bram Moolenaarf4d8b762021-10-17 14:13:09 +01003015 return type == CTRL_X_THESAURUS
3016 && (*curbuf->b_p_tsrfu != NUL || *p_tsrfu != NUL);
Yegappan Lakshmanan160e9942021-10-16 15:41:29 +01003017#else
3018 return FALSE;
3019#endif
3020}
3021
3022/*
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003023 * Return value of process_next_cpt_value()
3024 */
3025enum
3026{
3027 INS_COMPL_CPT_OK = 1,
3028 INS_COMPL_CPT_CONT,
3029 INS_COMPL_CPT_END
3030};
3031
3032/*
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003033 * state information used for getting the next set of insert completion
3034 * matches.
3035 */
3036typedef struct
3037{
3038 char_u *e_cpt; // current entry in 'complete'
3039 buf_T *ins_buf; // buffer being scanned
3040 pos_T *cur_match_pos; // current match position
3041 pos_T prev_match_pos; // previous match position
3042 int set_match_pos; // save first_match_pos/last_match_pos
3043 pos_T first_match_pos; // first match position
3044 pos_T last_match_pos; // last match position
3045 int found_all; // found all matches of a certain type.
3046 char_u *dict; // dictionary file to search
3047 int dict_f; // "dict" is an exact file name or not
3048} ins_compl_next_state_T;
3049
3050/*
3051 * Process the next 'complete' option value in st->e_cpt.
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003052 *
3053 * If successful, the arguments are set as below:
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003054 * st->cpt - pointer to the next option value in "st->cpt"
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003055 * compl_type_arg - type of insert mode completion to use
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003056 * st->found_all - all matches of this type are found
3057 * st->ins_buf - search for completions in this buffer
3058 * st->first_match_pos - position of the first completion match
3059 * st->last_match_pos - position of the last completion match
3060 * st->set_match_pos - TRUE if the first match position should be saved to
3061 * avoid loops after the search wraps around.
3062 * st->dict - name of the dictionary or thesaurus file to search
3063 * st->dict_f - flag specifying whether "dict" is an exact file name or not
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003064 *
3065 * Returns INS_COMPL_CPT_OK if the next value is processed successfully.
3066 * Returns INS_COMPL_CPT_CONT to skip the current value and process the next
3067 * option value.
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003068 * Returns INS_COMPL_CPT_END if all the values in "st->e_cpt" are processed.
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003069 */
3070 static int
3071process_next_cpt_value(
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003072 ins_compl_next_state_T *st,
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003073 int *compl_type_arg,
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003074 pos_T *start_match_pos)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003075{
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003076 int compl_type = -1;
3077 int status = INS_COMPL_CPT_OK;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003078
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003079 st->found_all = FALSE;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003080
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003081 while (*st->e_cpt == ',' || *st->e_cpt == ' ')
3082 st->e_cpt++;
3083
3084 if (*st->e_cpt == '.' && !curbuf->b_scanned)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003085 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003086 st->ins_buf = curbuf;
3087 st->first_match_pos = *start_match_pos;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003088 // Move the cursor back one character so that ^N can match the
3089 // word immediately after the cursor.
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003090 if (ctrl_x_mode == CTRL_X_NORMAL && dec(&st->first_match_pos) < 0)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003091 {
3092 // Move the cursor to after the last character in the
3093 // buffer, so that word at start of buffer is found
3094 // correctly.
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003095 st->first_match_pos.lnum = st->ins_buf->b_ml.ml_line_count;
3096 st->first_match_pos.col =
3097 (colnr_T)STRLEN(ml_get(st->first_match_pos.lnum));
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003098 }
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003099 st->last_match_pos = st->first_match_pos;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003100 compl_type = 0;
3101
3102 // Remember the first match so that the loop stops when we
3103 // wrap and come back there a second time.
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003104 st->set_match_pos = TRUE;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003105 }
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003106 else if (vim_strchr((char_u *)"buwU", *st->e_cpt) != NULL
3107 && (st->ins_buf = ins_compl_next_buf(st->ins_buf, *st->e_cpt)) != curbuf)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003108 {
3109 // Scan a buffer, but not the current one.
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003110 if (st->ins_buf->b_ml.ml_mfp != NULL) // loaded buffer
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003111 {
3112 compl_started = TRUE;
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003113 st->first_match_pos.col = st->last_match_pos.col = 0;
3114 st->first_match_pos.lnum = st->ins_buf->b_ml.ml_line_count + 1;
3115 st->last_match_pos.lnum = 0;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003116 compl_type = 0;
3117 }
3118 else // unloaded buffer, scan like dictionary
3119 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003120 st->found_all = TRUE;
3121 if (st->ins_buf->b_fname == NULL)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003122 {
3123 status = INS_COMPL_CPT_CONT;
3124 goto done;
3125 }
3126 compl_type = CTRL_X_DICTIONARY;
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003127 st->dict = st->ins_buf->b_fname;
3128 st->dict_f = DICT_EXACT;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003129 }
3130 msg_hist_off = TRUE; // reset in msg_trunc_attr()
3131 vim_snprintf((char *)IObuff, IOSIZE, _("Scanning: %s"),
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003132 st->ins_buf->b_fname == NULL
3133 ? buf_spname(st->ins_buf)
3134 : st->ins_buf->b_sfname == NULL
3135 ? st->ins_buf->b_fname
3136 : st->ins_buf->b_sfname);
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003137 (void)msg_trunc_attr((char *)IObuff, TRUE, HL_ATTR(HLF_R));
3138 }
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003139 else if (*st->e_cpt == NUL)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003140 status = INS_COMPL_CPT_END;
3141 else
3142 {
3143 if (ctrl_x_mode_line_or_eval())
3144 compl_type = -1;
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003145 else if (*st->e_cpt == 'k' || *st->e_cpt == 's')
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003146 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003147 if (*st->e_cpt == 'k')
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003148 compl_type = CTRL_X_DICTIONARY;
3149 else
3150 compl_type = CTRL_X_THESAURUS;
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003151 if (*++st->e_cpt != ',' && *st->e_cpt != NUL)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003152 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003153 st->dict = st->e_cpt;
3154 st->dict_f = DICT_FIRST;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003155 }
3156 }
3157#ifdef FEAT_FIND_ID
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003158 else if (*st->e_cpt == 'i')
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003159 compl_type = CTRL_X_PATH_PATTERNS;
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003160 else if (*st->e_cpt == 'd')
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003161 compl_type = CTRL_X_PATH_DEFINES;
3162#endif
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003163 else if (*st->e_cpt == ']' || *st->e_cpt == 't')
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003164 {
3165 msg_hist_off = TRUE; // reset in msg_trunc_attr()
3166 compl_type = CTRL_X_TAGS;
3167 vim_snprintf((char *)IObuff, IOSIZE, _("Scanning tags."));
3168 (void)msg_trunc_attr((char *)IObuff, TRUE, HL_ATTR(HLF_R));
3169 }
3170 else
3171 compl_type = -1;
3172
3173 // in any case e_cpt is advanced to the next entry
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003174 (void)copy_option_part(&st->e_cpt, IObuff, IOSIZE, ",");
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003175
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003176 st->found_all = TRUE;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003177 if (compl_type == -1)
3178 status = INS_COMPL_CPT_CONT;
3179 }
3180
3181done:
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003182 *compl_type_arg = compl_type;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003183 return status;
3184}
3185
3186#ifdef FEAT_FIND_ID
3187/*
3188 * Get the next set of identifiers or defines matching "compl_pattern" in
3189 * included files.
3190 */
3191 static void
3192get_next_include_file_completion(int compl_type)
3193{
3194 find_pattern_in_path(compl_pattern, compl_direction,
3195 (int)STRLEN(compl_pattern), FALSE, FALSE,
3196 (compl_type == CTRL_X_PATH_DEFINES
3197 && !(compl_cont_status & CONT_SOL))
3198 ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
3199 (linenr_T)1, (linenr_T)MAXLNUM);
3200}
3201#endif
3202
3203/*
3204 * Get the next set of words matching "compl_pattern" in dictionary or
3205 * thesaurus files.
3206 */
3207 static void
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003208get_next_dict_tsr_completion(int compl_type, char_u *dict, int dict_f)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003209{
3210#ifdef FEAT_COMPL_FUNC
3211 if (thesaurus_func_complete(compl_type))
3212 expand_by_function(compl_type, compl_pattern);
3213 else
3214#endif
3215 ins_compl_dictionaries(
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003216 dict != NULL ? dict
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003217 : (compl_type == CTRL_X_THESAURUS
3218 ? (*curbuf->b_p_tsr == NUL ? p_tsr : curbuf->b_p_tsr)
3219 : (*curbuf->b_p_dict == NUL ? p_dict : curbuf->b_p_dict)),
3220 compl_pattern,
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003221 dict != NULL ? dict_f : 0,
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003222 compl_type == CTRL_X_THESAURUS);
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003223}
3224
3225/*
3226 * Get the next set of tag names matching "compl_pattern".
3227 */
3228 static void
3229get_next_tag_completion(void)
3230{
3231 int save_p_ic;
3232 char_u **matches;
3233 int num_matches;
3234
3235 // set p_ic according to p_ic, p_scs and pat for find_tags().
3236 save_p_ic = p_ic;
3237 p_ic = ignorecase(compl_pattern);
3238
3239 // Find up to TAG_MANY matches. Avoids that an enormous number
3240 // of matches is found when compl_pattern is empty
3241 g_tag_at_cursor = TRUE;
3242 if (find_tags(compl_pattern, &num_matches, &matches,
3243 TAG_REGEXP | TAG_NAMES | TAG_NOIC | TAG_INS_COMP
3244 | (ctrl_x_mode != CTRL_X_NORMAL ? TAG_VERBOSE : 0),
3245 TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0)
3246 ins_compl_add_matches(num_matches, matches, p_ic);
3247 g_tag_at_cursor = FALSE;
3248 p_ic = save_p_ic;
3249}
3250
3251/*
3252 * Get the next set of filename matching "compl_pattern".
3253 */
3254 static void
3255get_next_filename_completion(void)
3256{
3257 char_u **matches;
3258 int num_matches;
3259
3260 if (expand_wildcards(1, &compl_pattern, &num_matches, &matches,
3261 EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) != OK)
3262 return;
3263
3264 // May change home directory back to "~".
3265 tilde_replace(compl_pattern, num_matches, matches);
3266#ifdef BACKSLASH_IN_FILENAME
3267 if (curbuf->b_p_csl[0] != NUL)
3268 {
3269 int i;
3270
3271 for (i = 0; i < num_matches; ++i)
3272 {
3273 char_u *ptr = matches[i];
3274
3275 while (*ptr != NUL)
3276 {
3277 if (curbuf->b_p_csl[0] == 's' && *ptr == '\\')
3278 *ptr = '/';
3279 else if (curbuf->b_p_csl[0] == 'b' && *ptr == '/')
3280 *ptr = '\\';
3281 ptr += (*mb_ptr2len)(ptr);
3282 }
3283 }
3284 }
3285#endif
3286 ins_compl_add_matches(num_matches, matches, p_fic || p_wic);
3287}
3288
3289/*
3290 * Get the next set of command-line completions matching "compl_pattern".
3291 */
3292 static void
3293get_next_cmdline_completion()
3294{
3295 char_u **matches;
3296 int num_matches;
3297
3298 if (expand_cmdline(&compl_xp, compl_pattern,
3299 (int)STRLEN(compl_pattern),
3300 &num_matches, &matches) == EXPAND_OK)
3301 ins_compl_add_matches(num_matches, matches, FALSE);
3302}
3303
3304/*
3305 * Get the next set of spell suggestions matching "compl_pattern".
3306 */
3307 static void
3308get_next_spell_completion(linenr_T lnum UNUSED)
3309{
3310#ifdef FEAT_SPELL
3311 char_u **matches;
3312 int num_matches;
3313
3314 num_matches = expand_spelling(lnum, compl_pattern, &matches);
3315 if (num_matches > 0)
3316 ins_compl_add_matches(num_matches, matches, p_ic);
Bram Moolenaar8e7cc6b2021-12-30 10:32:25 +00003317 else
3318 vim_free(matches);
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003319#endif
3320}
3321
3322/*
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003323 * Return the next word or line from buffer "ins_buf" at position
3324 * "cur_match_pos" for completion. The length of the match is set in "len".
3325 */
3326 static char_u *
3327ins_comp_get_next_word_or_line(
3328 buf_T *ins_buf, // buffer being scanned
3329 pos_T *cur_match_pos, // current match position
3330 int *match_len,
3331 int *cont_s_ipos) // next ^X<> will set initial_pos
3332{
3333 char_u *ptr;
3334 int len;
3335
3336 *match_len = 0;
3337 ptr = ml_get_buf(ins_buf, cur_match_pos->lnum, FALSE) +
3338 cur_match_pos->col;
3339 if (ctrl_x_mode_line_or_eval())
3340 {
3341 if (compl_cont_status & CONT_ADDING)
3342 {
3343 if (cur_match_pos->lnum >= ins_buf->b_ml.ml_line_count)
3344 return NULL;
3345 ptr = ml_get_buf(ins_buf, cur_match_pos->lnum + 1, FALSE);
3346 if (!p_paste)
3347 ptr = skipwhite(ptr);
3348 }
3349 len = (int)STRLEN(ptr);
3350 }
3351 else
3352 {
3353 char_u *tmp_ptr = ptr;
3354
3355 if (compl_cont_status & CONT_ADDING)
3356 {
3357 tmp_ptr += compl_length;
3358 // Skip if already inside a word.
3359 if (vim_iswordp(tmp_ptr))
3360 return NULL;
3361 // Find start of next word.
3362 tmp_ptr = find_word_start(tmp_ptr);
3363 }
3364 // Find end of this word.
3365 tmp_ptr = find_word_end(tmp_ptr);
3366 len = (int)(tmp_ptr - ptr);
3367
3368 if ((compl_cont_status & CONT_ADDING) && len == compl_length)
3369 {
3370 if (cur_match_pos->lnum < ins_buf->b_ml.ml_line_count)
3371 {
3372 // Try next line, if any. the new word will be
3373 // "join" as if the normal command "J" was used.
3374 // IOSIZE is always greater than
3375 // compl_length, so the next STRNCPY always
3376 // works -- Acevedo
3377 STRNCPY(IObuff, ptr, len);
3378 ptr = ml_get_buf(ins_buf, cur_match_pos->lnum + 1, FALSE);
3379 tmp_ptr = ptr = skipwhite(ptr);
3380 // Find start of next word.
3381 tmp_ptr = find_word_start(tmp_ptr);
3382 // Find end of next word.
3383 tmp_ptr = find_word_end(tmp_ptr);
3384 if (tmp_ptr > ptr)
3385 {
3386 if (*ptr != ')' && IObuff[len - 1] != TAB)
3387 {
3388 if (IObuff[len - 1] != ' ')
3389 IObuff[len++] = ' ';
3390 // IObuf =~ "\k.* ", thus len >= 2
3391 if (p_js
3392 && (IObuff[len - 2] == '.'
3393 || (vim_strchr(p_cpo, CPO_JOINSP)
3394 == NULL
3395 && (IObuff[len - 2] == '?'
3396 || IObuff[len - 2] == '!'))))
3397 IObuff[len++] = ' ';
3398 }
3399 // copy as much as possible of the new word
3400 if (tmp_ptr - ptr >= IOSIZE - len)
3401 tmp_ptr = ptr + IOSIZE - len - 1;
3402 STRNCPY(IObuff + len, ptr, tmp_ptr - ptr);
3403 len += (int)(tmp_ptr - ptr);
3404 *cont_s_ipos = TRUE;
3405 }
3406 IObuff[len] = NUL;
3407 ptr = IObuff;
3408 }
3409 if (len == compl_length)
3410 return NULL;
3411 }
3412 }
3413
3414 *match_len = len;
3415 return ptr;
3416}
3417
3418/*
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003419 * Get the next set of words matching "compl_pattern" for default completion(s)
3420 * (normal ^P/^N and ^X^L).
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003421 * Search for "compl_pattern" in the buffer "st->ins_buf" starting from the
3422 * position "st->start_pos" in the "compl_direction" direction. If
3423 * "st->set_match_pos" is TRUE, then set the "st->first_match_pos" and
3424 * "st->last_match_pos".
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003425 * Returns OK if a new next match is found, otherwise returns FAIL.
3426 */
3427 static int
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003428get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_pos)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003429{
3430 int found_new_match = FAIL;
3431 int save_p_scs;
3432 int save_p_ws;
3433 int looped_around = FALSE;
3434 char_u *ptr;
3435 int len;
3436
3437 // If 'infercase' is set, don't use 'smartcase' here
3438 save_p_scs = p_scs;
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003439 if (st->ins_buf->b_p_inf)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003440 p_scs = FALSE;
3441
3442 // Buffers other than curbuf are scanned from the beginning or the
3443 // end but never from the middle, thus setting nowrapscan in this
3444 // buffer is a good idea, on the other hand, we always set
3445 // wrapscan for curbuf to avoid missing matches -- Acevedo,Webb
3446 save_p_ws = p_ws;
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003447 if (st->ins_buf != curbuf)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003448 p_ws = FALSE;
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003449 else if (*st->e_cpt == '.')
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003450 p_ws = TRUE;
3451 looped_around = FALSE;
3452 for (;;)
3453 {
3454 int cont_s_ipos = FALSE;
3455
3456 ++msg_silent; // Don't want messages for wrapscan.
3457
3458 // ctrl_x_mode_line_or_eval() || word-wise search that
3459 // has added a word that was at the beginning of the line
3460 if (ctrl_x_mode_line_or_eval()
3461 || (compl_cont_status & CONT_SOL))
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003462 found_new_match = search_for_exact_line(st->ins_buf,
3463 st->cur_match_pos, compl_direction, compl_pattern);
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003464 else
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003465 found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos,
3466 NULL, compl_direction, compl_pattern, 1L,
3467 SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003468 --msg_silent;
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003469 if (!compl_started || st->set_match_pos)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003470 {
3471 // set "compl_started" even on fail
3472 compl_started = TRUE;
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003473 st->first_match_pos = *st->cur_match_pos;
3474 st->last_match_pos = *st->cur_match_pos;
3475 st->set_match_pos = FALSE;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003476 }
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003477 else if (st->first_match_pos.lnum == st->last_match_pos.lnum
3478 && st->first_match_pos.col == st->last_match_pos.col)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003479 {
3480 found_new_match = FAIL;
3481 }
3482 else if ((compl_direction == FORWARD)
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003483 && (st->prev_match_pos.lnum > st->cur_match_pos->lnum
3484 || (st->prev_match_pos.lnum == st->cur_match_pos->lnum
3485 && st->prev_match_pos.col >= st->cur_match_pos->col)))
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003486 {
3487 if (looped_around)
3488 found_new_match = FAIL;
3489 else
3490 looped_around = TRUE;
3491 }
3492 else if ((compl_direction != FORWARD)
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003493 && (st->prev_match_pos.lnum < st->cur_match_pos->lnum
3494 || (st->prev_match_pos.lnum == st->cur_match_pos->lnum
3495 && st->prev_match_pos.col <= st->cur_match_pos->col)))
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003496 {
3497 if (looped_around)
3498 found_new_match = FAIL;
3499 else
3500 looped_around = TRUE;
3501 }
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003502 st->prev_match_pos = *st->cur_match_pos;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003503 if (found_new_match == FAIL)
3504 break;
3505
3506 // when ADDING, the text before the cursor matches, skip it
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003507 if ((compl_cont_status & CONT_ADDING) && st->ins_buf == curbuf
3508 && start_pos->lnum == st->cur_match_pos->lnum
3509 && start_pos->col == st->cur_match_pos->col)
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003510 continue;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003511
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003512 ptr = ins_comp_get_next_word_or_line(st->ins_buf, st->cur_match_pos,
3513 &len, &cont_s_ipos);
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003514 if (ptr == NULL)
3515 continue;
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003516
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003517 if (ins_compl_add_infercase(ptr, len, p_ic,
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003518 st->ins_buf == curbuf ? NULL : st->ins_buf->b_sfname,
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003519 0, cont_s_ipos) != NOTDONE)
3520 {
3521 found_new_match = OK;
3522 break;
3523 }
3524 }
3525 p_scs = save_p_scs;
3526 p_ws = save_p_ws;
3527
3528 return found_new_match;
3529}
3530
3531/*
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003532 * get the next set of completion matches for 'type'.
3533 * Returns TRUE if a new match is found. Otherwise returns FALSE.
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003534 */
3535 static int
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003536get_next_completion_match(int type, ins_compl_next_state_T *st, pos_T *ini)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003537{
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003538 int found_new_match = FALSE;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003539
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003540 switch (type)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003541 {
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003542 case -1:
3543 break;
3544#ifdef FEAT_FIND_ID
3545 case CTRL_X_PATH_PATTERNS:
3546 case CTRL_X_PATH_DEFINES:
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003547 get_next_include_file_completion(type);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003548 break;
3549#endif
3550
3551 case CTRL_X_DICTIONARY:
3552 case CTRL_X_THESAURUS:
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003553 get_next_dict_tsr_completion(type, st->dict, st->dict_f);
3554 st->dict = NULL;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003555 break;
3556
3557 case CTRL_X_TAGS:
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003558 get_next_tag_completion();
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003559 break;
3560
3561 case CTRL_X_FILES:
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003562 get_next_filename_completion();
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003563 break;
3564
3565 case CTRL_X_CMDLINE:
zeertzjqdca29d92021-08-31 19:12:51 +02003566 case CTRL_X_CMDLINE_CTRL_X:
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00003567 get_next_cmdline_completion();
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003568 break;
3569
3570#ifdef FEAT_COMPL_FUNC
3571 case CTRL_X_FUNCTION:
3572 case CTRL_X_OMNI:
3573 expand_by_function(type, compl_pattern);
3574 break;
3575#endif
3576
3577 case CTRL_X_SPELL:
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003578 get_next_spell_completion(st->first_match_pos.lnum);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003579 break;
3580
3581 default: // normal ^P/^N and ^X^L
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003582 found_new_match = get_next_default_completion(st, ini);
3583 if (found_new_match == FAIL && st->ins_buf == curbuf)
3584 st->found_all = TRUE;
3585 }
3586
3587 // check if compl_curr_match has changed, (e.g. other type of
3588 // expansion added something)
3589 if (type != 0 && compl_curr_match != compl_old_match)
3590 found_new_match = OK;
3591
3592 return found_new_match;
3593}
3594
3595/*
3596 * Get the next expansion(s), using "compl_pattern".
3597 * The search starts at position "ini" in curbuf and in the direction
3598 * compl_direction.
3599 * When "compl_started" is FALSE start at that position, otherwise continue
3600 * where we stopped searching before.
3601 * This may return before finding all the matches.
3602 * Return the total number of matches or -1 if still unknown -- Acevedo
3603 */
3604 static int
3605ins_compl_get_exp(pos_T *ini)
3606{
3607 static ins_compl_next_state_T st;
3608 int i;
3609 int found_new_match;
3610 int type = ctrl_x_mode;
3611
3612 if (!compl_started)
3613 {
3614 FOR_ALL_BUFFERS(st.ins_buf)
3615 st.ins_buf->b_scanned = 0;
3616 st.found_all = FALSE;
3617 st.ins_buf = curbuf;
3618 st.e_cpt = (compl_cont_status & CONT_LOCAL)
3619 ? (char_u *)"." : curbuf->b_p_cpt;
3620 st.last_match_pos = st.first_match_pos = *ini;
3621 }
3622 else if (st.ins_buf != curbuf && !buf_valid(st.ins_buf))
3623 st.ins_buf = curbuf; // In case the buffer was wiped out.
3624
3625 compl_old_match = compl_curr_match; // remember the last current match
3626 st.cur_match_pos = (compl_direction == FORWARD)
3627 ? &st.last_match_pos : &st.first_match_pos;
3628
3629 // For ^N/^P loop over all the flags/windows/buffers in 'complete'.
3630 for (;;)
3631 {
3632 found_new_match = FAIL;
3633 st.set_match_pos = FALSE;
3634
3635 // For ^N/^P pick a new entry from e_cpt if compl_started is off,
3636 // or if found_all says this entry is done. For ^X^L only use the
3637 // entries from 'complete' that look in loaded buffers.
3638 if ((ctrl_x_mode == CTRL_X_NORMAL
3639 || ctrl_x_mode_line_or_eval())
3640 && (!compl_started || st.found_all))
3641 {
3642 int status = process_next_cpt_value(&st, &type, ini);
3643
3644 if (status == INS_COMPL_CPT_END)
3645 break;
3646 if (status == INS_COMPL_CPT_CONT)
3647 continue;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003648 }
3649
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003650 // If complete() was called then compl_pattern has been reset. The
3651 // following won't work then, bail out.
3652 if (compl_pattern == NULL)
3653 break;
3654
3655 // get the next set of completion matches
3656 found_new_match = get_next_completion_match(type, &st, ini);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003657
3658 // break the loop for specialized modes (use 'complete' just for the
3659 // generic ctrl_x_mode == CTRL_X_NORMAL) or when we've found a new
3660 // match
3661 if ((ctrl_x_mode != CTRL_X_NORMAL
3662 && !ctrl_x_mode_line_or_eval()) || found_new_match != FAIL)
3663 {
3664 if (got_int)
3665 break;
3666 // Fill the popup menu as soon as possible.
3667 if (type != -1)
3668 ins_compl_check_keys(0, FALSE);
3669
3670 if ((ctrl_x_mode != CTRL_X_NORMAL
3671 && !ctrl_x_mode_line_or_eval()) || compl_interrupted)
3672 break;
3673 compl_started = TRUE;
3674 }
3675 else
3676 {
3677 // Mark a buffer scanned when it has been scanned completely
3678 if (type == 0 || type == CTRL_X_PATH_PATTERNS)
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003679 st.ins_buf->b_scanned = TRUE;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003680
3681 compl_started = FALSE;
3682 }
3683 }
3684 compl_started = TRUE;
3685
3686 if ((ctrl_x_mode == CTRL_X_NORMAL || ctrl_x_mode_line_or_eval())
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003687 && *st.e_cpt == NUL) // Got to end of 'complete'
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003688 found_new_match = FAIL;
3689
3690 i = -1; // total of matches, unknown
3691 if (found_new_match == FAIL || (ctrl_x_mode != CTRL_X_NORMAL
3692 && !ctrl_x_mode_line_or_eval()))
3693 i = ins_compl_make_cyclic();
3694
3695 if (compl_old_match != NULL)
3696 {
3697 // If several matches were added (FORWARD) or the search failed and has
3698 // just been made cyclic then we have to move compl_curr_match to the
3699 // next or previous entry (if any) -- Acevedo
3700 compl_curr_match = compl_direction == FORWARD ? compl_old_match->cp_next
3701 : compl_old_match->cp_prev;
3702 if (compl_curr_match == NULL)
3703 compl_curr_match = compl_old_match;
3704 }
=?UTF-8?q?Magnus=20Gro=C3=9F?=25def2c2021-10-22 18:56:39 +01003705 trigger_modechanged();
3706
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003707 return i;
3708}
3709
3710/*
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003711 * Update "compl_shown_match" to the actually shown match, it may differ when
3712 * "compl_leader" is used to omit some of the matches.
3713 */
3714 static void
3715ins_compl_update_shown_match(void)
3716{
3717 while (!ins_compl_equal(compl_shown_match,
3718 compl_leader, (int)STRLEN(compl_leader))
3719 && compl_shown_match->cp_next != NULL
3720 && compl_shown_match->cp_next != compl_first_match)
3721 compl_shown_match = compl_shown_match->cp_next;
3722
3723 // If we didn't find it searching forward, and compl_shows_dir is
3724 // backward, find the last match.
3725 if (compl_shows_dir == BACKWARD
3726 && !ins_compl_equal(compl_shown_match,
3727 compl_leader, (int)STRLEN(compl_leader))
3728 && (compl_shown_match->cp_next == NULL
3729 || compl_shown_match->cp_next == compl_first_match))
3730 {
3731 while (!ins_compl_equal(compl_shown_match,
3732 compl_leader, (int)STRLEN(compl_leader))
3733 && compl_shown_match->cp_prev != NULL
3734 && compl_shown_match->cp_prev != compl_first_match)
3735 compl_shown_match = compl_shown_match->cp_prev;
3736 }
3737}
3738
3739/*
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003740 * Delete the old text being completed.
3741 */
3742 void
3743ins_compl_delete(void)
3744{
3745 int col;
3746
3747 // In insert mode: Delete the typed part.
3748 // In replace mode: Put the old characters back, if any.
3749 col = compl_col + (compl_cont_status & CONT_ADDING ? compl_length : 0);
3750 if ((int)curwin->w_cursor.col > col)
3751 {
3752 if (stop_arrow() == FAIL)
3753 return;
3754 backspace_until_column(col);
3755 }
3756
3757 // TODO: is this sufficient for redrawing? Redrawing everything causes
3758 // flicker, thus we can't do that.
3759 changed_cline_bef_curs();
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02003760#ifdef FEAT_EVAL
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003761 // clear v:completed_item
3762 set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED));
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02003763#endif
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003764}
3765
3766/*
3767 * Insert the new text being completed.
3768 * "in_compl_func" is TRUE when called from complete_check().
3769 */
3770 void
3771ins_compl_insert(int in_compl_func)
3772{
Bram Moolenaar4b28ba32021-12-27 19:28:37 +00003773 int compl_len = ins_compl_len();
3774
3775 // Make sure we don't go over the end of the string, this can happen with
3776 // illegal bytes.
3777 if (compl_len < (int)STRLEN(compl_shown_match->cp_str))
3778 ins_bytes(compl_shown_match->cp_str + compl_len);
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003779 if (ins_compl_at_original_text(compl_shown_match))
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003780 compl_used_match = FALSE;
3781 else
3782 compl_used_match = TRUE;
Bram Moolenaar9cb698d2019-08-21 15:30:45 +02003783#ifdef FEAT_EVAL
3784 {
3785 dict_T *dict = ins_compl_dict_alloc(compl_shown_match);
3786
3787 set_vim_var_dict(VV_COMPLETED_ITEM, dict);
3788 }
3789#endif
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003790 if (!in_compl_func)
3791 compl_curr_match = compl_shown_match;
3792}
3793
3794/*
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003795 * show the file name for the completion match (if any). Truncate the file
3796 * name to avoid a wait for return.
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003797 */
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003798 static void
3799ins_compl_show_filename(void)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003800{
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003801 char *lead = _("match in file");
3802 int space = sc_col - vim_strsize((char_u *)lead) - 2;
3803 char_u *s;
3804 char_u *e;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003805
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003806 if (space <= 0)
3807 return;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003808
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003809 // We need the tail that fits. With double-byte encoding going
3810 // back from the end is very slow, thus go from the start and keep
3811 // the text that fits in "space" between "s" and "e".
3812 for (s = e = compl_shown_match->cp_fname; *e != NUL; MB_PTR_ADV(e))
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003813 {
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003814 space -= ptr2cells(e);
3815 while (space < 0)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003816 {
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003817 space += ptr2cells(s);
3818 MB_PTR_ADV(s);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003819 }
3820 }
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003821 msg_hist_off = TRUE;
3822 vim_snprintf((char *)IObuff, IOSIZE, "%s %s%s", lead,
3823 s > compl_shown_match->cp_fname ? "<" : "", s);
3824 msg((char *)IObuff);
3825 msg_hist_off = FALSE;
3826 redraw_cmdline = FALSE; // don't overwrite!
3827}
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003828
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003829/*
3830 * Find the next set of matches for completion. Repeat the completion 'todo'
3831 * times. The number of matches found is returned in 'num_matches'.
3832 *
3833 * If "allow_get_expansion" is TRUE, then ins_compl_get_exp() may be called to
3834 * get more completions. If it is FALSE, then do nothing when there are no more
3835 * completions in the given direction.
3836 *
3837 * If "advance" is TRUE, then completion will move to the first match.
3838 * Otherwise, the original text will be shown.
3839 *
3840 * Returns OK on success and -1 if the number of matches are unknown.
3841 */
3842 static int
3843find_next_completion_match(
3844 int allow_get_expansion,
3845 int todo, // repeat completion this many times
3846 int advance,
3847 int *num_matches)
3848{
3849 int found_end = FALSE;
3850 compl_T *found_compl = NULL;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003851
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003852 while (--todo >= 0)
3853 {
3854 if (compl_shows_dir == FORWARD && compl_shown_match->cp_next != NULL)
3855 {
3856 compl_shown_match = compl_shown_match->cp_next;
3857 found_end = (compl_first_match != NULL
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003858 && (compl_shown_match->cp_next == compl_first_match
3859 || compl_shown_match == compl_first_match));
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003860 }
3861 else if (compl_shows_dir == BACKWARD
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003862 && compl_shown_match->cp_prev != NULL)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003863 {
3864 found_end = (compl_shown_match == compl_first_match);
3865 compl_shown_match = compl_shown_match->cp_prev;
3866 found_end |= (compl_shown_match == compl_first_match);
3867 }
3868 else
3869 {
3870 if (!allow_get_expansion)
3871 {
3872 if (advance)
3873 {
3874 if (compl_shows_dir == BACKWARD)
3875 compl_pending -= todo + 1;
3876 else
3877 compl_pending += todo + 1;
3878 }
3879 return -1;
3880 }
3881
3882 if (!compl_no_select && advance)
3883 {
3884 if (compl_shows_dir == BACKWARD)
3885 --compl_pending;
3886 else
3887 ++compl_pending;
3888 }
3889
3890 // Find matches.
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003891 *num_matches = ins_compl_get_exp(&compl_startpos);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003892
3893 // handle any pending completions
3894 while (compl_pending != 0 && compl_direction == compl_shows_dir
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003895 && advance)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003896 {
3897 if (compl_pending > 0 && compl_shown_match->cp_next != NULL)
3898 {
3899 compl_shown_match = compl_shown_match->cp_next;
3900 --compl_pending;
3901 }
3902 if (compl_pending < 0 && compl_shown_match->cp_prev != NULL)
3903 {
3904 compl_shown_match = compl_shown_match->cp_prev;
3905 ++compl_pending;
3906 }
3907 else
3908 break;
3909 }
3910 found_end = FALSE;
3911 }
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003912 if (!ins_compl_at_original_text(compl_shown_match)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003913 && compl_leader != NULL
3914 && !ins_compl_equal(compl_shown_match,
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003915 compl_leader, (int)STRLEN(compl_leader)))
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003916 ++todo;
3917 else
3918 // Remember a matching item.
3919 found_compl = compl_shown_match;
3920
3921 // Stop at the end of the list when we found a usable match.
3922 if (found_end)
3923 {
3924 if (found_compl != NULL)
3925 {
3926 compl_shown_match = found_compl;
3927 break;
3928 }
3929 todo = 1; // use first usable match after wrapping around
3930 }
3931 }
3932
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003933 return OK;
3934}
3935
3936/*
3937 * Fill in the next completion in the current direction.
3938 * If "allow_get_expansion" is TRUE, then we may call ins_compl_get_exp() to
3939 * get more completions. If it is FALSE, then we just do nothing when there
3940 * are no more completions in a given direction. The latter case is used when
3941 * we are still in the middle of finding completions, to allow browsing
3942 * through the ones found so far.
3943 * Return the total number of matches, or -1 if still unknown -- webb.
3944 *
3945 * compl_curr_match is currently being used by ins_compl_get_exp(), so we use
3946 * compl_shown_match here.
3947 *
3948 * Note that this function may be called recursively once only. First with
3949 * "allow_get_expansion" TRUE, which calls ins_compl_get_exp(), which in turn
3950 * calls this function with "allow_get_expansion" FALSE.
3951 */
3952 static int
3953ins_compl_next(
3954 int allow_get_expansion,
3955 int count, // repeat completion this many times; should
3956 // be at least 1
3957 int insert_match, // Insert the newly selected match
3958 int in_compl_func) // called from complete_check()
3959{
3960 int num_matches = -1;
3961 int todo = count;
3962 int advance;
3963 int started = compl_started;
3964
3965 // When user complete function return -1 for findstart which is next
3966 // time of 'always', compl_shown_match become NULL.
3967 if (compl_shown_match == NULL)
3968 return -1;
3969
3970 if (compl_leader != NULL
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00003971 && !ins_compl_at_original_text(compl_shown_match))
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00003972 // Update "compl_shown_match" to the actually shown match
3973 ins_compl_update_shown_match();
3974
3975 if (allow_get_expansion && insert_match
3976 && (!(compl_get_longest || compl_restarting) || compl_used_match))
3977 // Delete old text to be replaced
3978 ins_compl_delete();
3979
3980 // When finding the longest common text we stick at the original text,
3981 // don't let CTRL-N or CTRL-P move to the first match.
3982 advance = count != 1 || !allow_get_expansion || !compl_get_longest;
3983
3984 // When restarting the search don't insert the first match either.
3985 if (compl_restarting)
3986 {
3987 advance = FALSE;
3988 compl_restarting = FALSE;
3989 }
3990
3991 // Repeat this for when <PageUp> or <PageDown> is typed. But don't wrap
3992 // around.
3993 if (find_next_completion_match(allow_get_expansion, todo, advance,
3994 &num_matches) == -1)
3995 return -1;
3996
Bram Moolenaar7591bb32019-03-30 13:53:47 +01003997 // Insert the text of the new completion, or the compl_leader.
3998 if (compl_no_insert && !started)
3999 {
4000 ins_bytes(compl_orig_text + ins_compl_len());
4001 compl_used_match = FALSE;
4002 }
4003 else if (insert_match)
4004 {
4005 if (!compl_get_longest || compl_used_match)
4006 ins_compl_insert(in_compl_func);
4007 else
4008 ins_bytes(compl_leader + ins_compl_len());
4009 }
4010 else
4011 compl_used_match = FALSE;
4012
4013 if (!allow_get_expansion)
4014 {
4015 // may undisplay the popup menu first
4016 ins_compl_upd_pum();
4017
4018 if (pum_enough_matches())
4019 // Will display the popup menu, don't redraw yet to avoid flicker.
4020 pum_call_update_screen();
4021 else
4022 // Not showing the popup menu yet, redraw to show the user what was
4023 // inserted.
4024 update_screen(0);
4025
4026 // display the updated popup menu
4027 ins_compl_show_pum();
4028#ifdef FEAT_GUI
4029 if (gui.in_use)
4030 {
4031 // Show the cursor after the match, not after the redrawn text.
4032 setcursor();
4033 out_flush_cursor(FALSE, FALSE);
4034 }
4035#endif
4036
4037 // Delete old text to be replaced, since we're still searching and
4038 // don't want to match ourselves!
4039 ins_compl_delete();
4040 }
4041
4042 // Enter will select a match when the match wasn't inserted and the popup
4043 // menu is visible.
4044 if (compl_no_insert && !started)
4045 compl_enter_selects = TRUE;
4046 else
4047 compl_enter_selects = !insert_match && compl_match_array != NULL;
4048
4049 // Show the file name for the match (if any)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004050 if (compl_shown_match->cp_fname != NULL)
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004051 ins_compl_show_filename();
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004052
4053 return num_matches;
4054}
4055
4056/*
4057 * Call this while finding completions, to check whether the user has hit a key
4058 * that should change the currently displayed completion, or exit completion
4059 * mode. Also, when compl_pending is not zero, show a completion as soon as
4060 * possible. -- webb
4061 * "frequency" specifies out of how many calls we actually check.
4062 * "in_compl_func" is TRUE when called from complete_check(), don't set
4063 * compl_curr_match.
4064 */
4065 void
4066ins_compl_check_keys(int frequency, int in_compl_func)
4067{
4068 static int count = 0;
4069 int c;
4070
4071 // Don't check when reading keys from a script, :normal or feedkeys().
4072 // That would break the test scripts. But do check for keys when called
4073 // from complete_check().
4074 if (!in_compl_func && (using_script() || ex_normal_busy))
4075 return;
4076
4077 // Only do this at regular intervals
4078 if (++count < frequency)
4079 return;
4080 count = 0;
4081
4082 // Check for a typed key. Do use mappings, otherwise vim_is_ctrl_x_key()
4083 // can't do its work correctly.
4084 c = vpeekc_any();
4085 if (c != NUL)
4086 {
4087 if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R)
4088 {
4089 c = safe_vgetc(); // Eat the character
4090 compl_shows_dir = ins_compl_key2dir(c);
4091 (void)ins_compl_next(FALSE, ins_compl_key2count(c),
4092 c != K_UP && c != K_DOWN, in_compl_func);
4093 }
4094 else
4095 {
4096 // Need to get the character to have KeyTyped set. We'll put it
4097 // back with vungetc() below. But skip K_IGNORE.
4098 c = safe_vgetc();
4099 if (c != K_IGNORE)
4100 {
4101 // Don't interrupt completion when the character wasn't typed,
4102 // e.g., when doing @q to replay keys.
4103 if (c != Ctrl_R && KeyTyped)
4104 compl_interrupted = TRUE;
4105
4106 vungetc(c);
4107 }
4108 }
4109 }
4110 if (compl_pending != 0 && !got_int && !compl_no_insert)
4111 {
4112 int todo = compl_pending > 0 ? compl_pending : -compl_pending;
4113
4114 compl_pending = 0;
4115 (void)ins_compl_next(FALSE, todo, TRUE, in_compl_func);
4116 }
4117}
4118
4119/*
4120 * Decide the direction of Insert mode complete from the key typed.
4121 * Returns BACKWARD or FORWARD.
4122 */
4123 static int
4124ins_compl_key2dir(int c)
4125{
4126 if (c == Ctrl_P || c == Ctrl_L
4127 || c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP || c == K_UP)
4128 return BACKWARD;
4129 return FORWARD;
4130}
4131
4132/*
4133 * Return TRUE for keys that are used for completion only when the popup menu
4134 * is visible.
4135 */
4136 static int
4137ins_compl_pum_key(int c)
4138{
4139 return pum_visible() && (c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP
4140 || c == K_PAGEDOWN || c == K_KPAGEDOWN || c == K_S_DOWN
4141 || c == K_UP || c == K_DOWN);
4142}
4143
4144/*
4145 * Decide the number of completions to move forward.
4146 * Returns 1 for most keys, height of the popup menu for page-up/down keys.
4147 */
4148 static int
4149ins_compl_key2count(int c)
4150{
4151 int h;
4152
4153 if (ins_compl_pum_key(c) && c != K_UP && c != K_DOWN)
4154 {
4155 h = pum_get_height();
4156 if (h > 3)
4157 h -= 2; // keep some context
4158 return h;
4159 }
4160 return 1;
4161}
4162
4163/*
4164 * Return TRUE if completion with "c" should insert the match, FALSE if only
4165 * to change the currently selected completion.
4166 */
4167 static int
4168ins_compl_use_match(int c)
4169{
4170 switch (c)
4171 {
4172 case K_UP:
4173 case K_DOWN:
4174 case K_PAGEDOWN:
4175 case K_KPAGEDOWN:
4176 case K_S_DOWN:
4177 case K_PAGEUP:
4178 case K_KPAGEUP:
4179 case K_S_UP:
4180 return FALSE;
4181 }
4182 return TRUE;
4183}
4184
4185/*
Bram Moolenaarbf7ff612021-12-27 12:52:07 +00004186 * Get the pattern, column and length for normal completion (CTRL-N CTRL-P
4187 * completion)
4188 * Sets the global variables: compl_col, compl_length and compl_pattern.
4189 * Uses the global variables: compl_cont_status and ctrl_x_mode
4190 */
4191 static int
4192get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col)
4193{
Yegappan Lakshmananedc6f102021-12-29 17:38:46 +00004194 if ((compl_cont_status & CONT_SOL) || ctrl_x_mode == CTRL_X_PATH_DEFINES)
Bram Moolenaarbf7ff612021-12-27 12:52:07 +00004195 {
4196 if (!(compl_cont_status & CONT_ADDING))
4197 {
4198 while (--startcol >= 0 && vim_isIDc(line[startcol]))
4199 ;
4200 compl_col += ++startcol;
4201 compl_length = curs_col - startcol;
4202 }
4203 if (p_ic)
4204 compl_pattern = str_foldcase(line + compl_col,
4205 compl_length, NULL, 0);
4206 else
4207 compl_pattern = vim_strnsave(line + compl_col, compl_length);
4208 if (compl_pattern == NULL)
4209 return FAIL;
4210 }
4211 else if (compl_cont_status & CONT_ADDING)
4212 {
4213 char_u *prefix = (char_u *)"\\<";
4214
4215 // we need up to 2 extra chars for the prefix
4216 compl_pattern = alloc(quote_meta(NULL, line + compl_col,
4217 compl_length) + 2);
4218 if (compl_pattern == NULL)
4219 return FAIL;
4220 if (!vim_iswordp(line + compl_col)
4221 || (compl_col > 0
4222 && (vim_iswordp(mb_prevptr(line, line + compl_col)))))
4223 prefix = (char_u *)"";
4224 STRCPY((char *)compl_pattern, prefix);
4225 (void)quote_meta(compl_pattern + STRLEN(prefix),
4226 line + compl_col, compl_length);
4227 }
4228 else if (--startcol < 0
4229 || !vim_iswordp(mb_prevptr(line, line + startcol + 1)))
4230 {
4231 // Match any word of at least two chars
4232 compl_pattern = vim_strsave((char_u *)"\\<\\k\\k");
4233 if (compl_pattern == NULL)
4234 return FAIL;
4235 compl_col += curs_col;
4236 compl_length = 0;
4237 }
4238 else
4239 {
4240 // Search the point of change class of multibyte character
4241 // or not a word single byte character backward.
4242 if (has_mbyte)
4243 {
4244 int base_class;
4245 int head_off;
4246
4247 startcol -= (*mb_head_off)(line, line + startcol);
4248 base_class = mb_get_class(line + startcol);
4249 while (--startcol >= 0)
4250 {
4251 head_off = (*mb_head_off)(line, line + startcol);
4252 if (base_class != mb_get_class(line + startcol
4253 - head_off))
4254 break;
4255 startcol -= head_off;
4256 }
4257 }
4258 else
4259 while (--startcol >= 0 && vim_iswordc(line[startcol]))
4260 ;
4261 compl_col += ++startcol;
4262 compl_length = (int)curs_col - startcol;
4263 if (compl_length == 1)
4264 {
4265 // Only match word with at least two chars -- webb
4266 // there's no need to call quote_meta,
4267 // alloc(7) is enough -- Acevedo
4268 compl_pattern = alloc(7);
4269 if (compl_pattern == NULL)
4270 return FAIL;
4271 STRCPY((char *)compl_pattern, "\\<");
4272 (void)quote_meta(compl_pattern + 2, line + compl_col, 1);
4273 STRCAT((char *)compl_pattern, "\\k");
4274 }
4275 else
4276 {
4277 compl_pattern = alloc(quote_meta(NULL, line + compl_col,
4278 compl_length) + 2);
4279 if (compl_pattern == NULL)
4280 return FAIL;
4281 STRCPY((char *)compl_pattern, "\\<");
4282 (void)quote_meta(compl_pattern + 2, line + compl_col,
4283 compl_length);
4284 }
4285 }
4286
4287 return OK;
4288}
4289
4290/*
4291 * Get the pattern, column and length for whole line completion or for the
4292 * complete() function.
4293 * Sets the global variables: compl_col, compl_length and compl_pattern.
4294 */
4295 static int
4296get_wholeline_compl_info(char_u *line, colnr_T curs_col)
4297{
4298 compl_col = (colnr_T)getwhitecols(line);
4299 compl_length = (int)curs_col - (int)compl_col;
4300 if (compl_length < 0) // cursor in indent: empty pattern
4301 compl_length = 0;
4302 if (p_ic)
4303 compl_pattern = str_foldcase(line + compl_col, compl_length,
4304 NULL, 0);
4305 else
4306 compl_pattern = vim_strnsave(line + compl_col, compl_length);
4307 if (compl_pattern == NULL)
4308 return FAIL;
4309
4310 return OK;
4311}
4312
4313/*
4314 * Get the pattern, column and length for filename completion.
4315 * Sets the global variables: compl_col, compl_length and compl_pattern.
4316 */
4317 static int
4318get_filename_compl_info(char_u *line, int startcol, colnr_T curs_col)
4319{
4320 // Go back to just before the first filename character.
4321 if (startcol > 0)
4322 {
4323 char_u *p = line + startcol;
4324
4325 MB_PTR_BACK(line, p);
4326 while (p > line && vim_isfilec(PTR2CHAR(p)))
4327 MB_PTR_BACK(line, p);
4328 if (p == line && vim_isfilec(PTR2CHAR(p)))
4329 startcol = 0;
4330 else
4331 startcol = (int)(p - line) + 1;
4332 }
4333
4334 compl_col += startcol;
4335 compl_length = (int)curs_col - startcol;
4336 compl_pattern = addstar(line + compl_col, compl_length, EXPAND_FILES);
4337 if (compl_pattern == NULL)
4338 return FAIL;
4339
4340 return OK;
4341}
4342
4343/*
4344 * Get the pattern, column and length for command-line completion.
4345 * Sets the global variables: compl_col, compl_length and compl_pattern.
4346 */
4347 static int
4348get_cmdline_compl_info(char_u *line, colnr_T curs_col)
4349{
4350 compl_pattern = vim_strnsave(line, curs_col);
4351 if (compl_pattern == NULL)
4352 return FAIL;
4353 set_cmd_context(&compl_xp, compl_pattern,
4354 (int)STRLEN(compl_pattern), curs_col, FALSE);
4355 if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL
4356 || compl_xp.xp_context == EXPAND_NOTHING)
4357 // No completion possible, use an empty pattern to get a
4358 // "pattern not found" message.
4359 compl_col = curs_col;
4360 else
4361 compl_col = (int)(compl_xp.xp_pattern - compl_pattern);
4362 compl_length = curs_col - compl_col;
4363
4364 return OK;
4365}
4366
4367/*
4368 * Get the pattern, column and length for user defined completion ('omnifunc',
4369 * 'completefunc' and 'thesaurusfunc')
4370 * Sets the global variables: compl_col, compl_length and compl_pattern.
4371 * Uses the global variable: spell_bad_len
4372 */
4373 static int
4374get_userdefined_compl_info(colnr_T curs_col UNUSED)
4375{
4376 int ret = FAIL;
4377
4378#ifdef FEAT_COMPL_FUNC
4379 // Call user defined function 'completefunc' with "a:findstart"
4380 // set to 1 to obtain the length of text to use for completion.
4381 char_u *line;
4382 typval_T args[3];
4383 int col;
4384 char_u *funcname;
4385 pos_T pos;
4386 int save_State = State;
4387 callback_T *cb;
4388
4389 // Call 'completefunc' or 'omnifunc' or 'thesaurusfunc' and get pattern
4390 // length as a string
4391 funcname = get_complete_funcname(ctrl_x_mode);
4392 if (*funcname == NUL)
4393 {
Bram Moolenaar74409f62022-01-01 15:58:22 +00004394 semsg(_(e_option_str_is_not_set), ctrl_x_mode == CTRL_X_FUNCTION
Bram Moolenaarbf7ff612021-12-27 12:52:07 +00004395 ? "completefunc" : "omnifunc");
4396 return FAIL;
4397 }
4398
4399 args[0].v_type = VAR_NUMBER;
4400 args[0].vval.v_number = 1;
4401 args[1].v_type = VAR_STRING;
4402 args[1].vval.v_string = (char_u *)"";
4403 args[2].v_type = VAR_UNKNOWN;
4404 pos = curwin->w_cursor;
4405 ++textwinlock;
4406 cb = get_insert_callback(ctrl_x_mode);
4407 col = call_callback_retnr(cb, 2, args);
4408 --textwinlock;
4409
4410 State = save_State;
4411 curwin->w_cursor = pos; // restore the cursor position
4412 validate_cursor();
4413 if (!EQUAL_POS(curwin->w_cursor, pos))
4414 {
4415 emsg(_(e_compldel));
4416 return FAIL;
4417 }
4418
4419 // Return value -2 means the user complete function wants to
4420 // cancel the complete without an error.
4421 // Return value -3 does the same as -2 and leaves CTRL-X mode.
4422 if (col == -2)
4423 return FAIL;
4424 if (col == -3)
4425 {
4426 ctrl_x_mode = CTRL_X_NORMAL;
4427 edit_submode = NULL;
4428 if (!shortmess(SHM_COMPLETIONMENU))
4429 msg_clr_cmdline();
4430 return FAIL;
4431 }
4432
4433 // Reset extended parameters of completion, when start new
4434 // completion.
4435 compl_opt_refresh_always = FALSE;
4436 compl_opt_suppress_empty = FALSE;
4437
4438 if (col < 0)
4439 col = curs_col;
4440 compl_col = col;
4441 if (compl_col > curs_col)
4442 compl_col = curs_col;
4443
4444 // Setup variables for completion. Need to obtain "line" again,
4445 // it may have become invalid.
4446 line = ml_get(curwin->w_cursor.lnum);
4447 compl_length = curs_col - compl_col;
4448 compl_pattern = vim_strnsave(line + compl_col, compl_length);
4449 if (compl_pattern == NULL)
4450 return FAIL;
4451
4452 ret = OK;
4453#endif
4454
4455 return ret;
4456}
4457
4458/*
4459 * Get the pattern, column and length for spell completion.
4460 * Sets the global variables: compl_col, compl_length and compl_pattern.
4461 * Uses the global variable: spell_bad_len
4462 */
4463 static int
4464get_spell_compl_info(int startcol UNUSED, colnr_T curs_col UNUSED)
4465{
4466 int ret = FAIL;
4467#ifdef FEAT_SPELL
4468 char_u *line;
4469
4470 if (spell_bad_len > 0)
4471 compl_col = curs_col - spell_bad_len;
4472 else
4473 compl_col = spell_word_start(startcol);
4474 if (compl_col >= (colnr_T)startcol)
4475 {
4476 compl_length = 0;
4477 compl_col = curs_col;
4478 }
4479 else
4480 {
4481 spell_expand_check_cap(compl_col);
4482 compl_length = (int)curs_col - compl_col;
4483 }
4484 // Need to obtain "line" again, it may have become invalid.
4485 line = ml_get(curwin->w_cursor.lnum);
4486 compl_pattern = vim_strnsave(line + compl_col, compl_length);
4487 if (compl_pattern == NULL)
4488 return FAIL;
4489
4490 ret = OK;
4491#endif
4492
4493 return ret;
4494}
4495
4496/*
4497 * Get the completion pattern, column and length.
4498 */
4499 static int
4500compl_get_info(char_u *line, int startcol, colnr_T curs_col, int *line_invalid)
4501{
4502 if (ctrl_x_mode == CTRL_X_NORMAL
4503 || (ctrl_x_mode & CTRL_X_WANT_IDENT
4504 && !thesaurus_func_complete(ctrl_x_mode)))
4505 {
4506 return get_normal_compl_info(line, startcol, curs_col);
4507 }
4508 else if (ctrl_x_mode_line_or_eval())
4509 {
4510 return get_wholeline_compl_info(line, curs_col);
4511 }
4512 else if (ctrl_x_mode == CTRL_X_FILES)
4513 {
4514 return get_filename_compl_info(line, startcol, curs_col);
4515 }
4516 else if (ctrl_x_mode == CTRL_X_CMDLINE)
4517 {
4518 return get_cmdline_compl_info(line, curs_col);
4519 }
4520 else if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI
4521 || thesaurus_func_complete(ctrl_x_mode))
4522 {
4523 if (get_userdefined_compl_info(curs_col) == FAIL)
4524 return FAIL;
4525 *line_invalid = TRUE; // 'line' may have become invalid
4526 }
4527 else if (ctrl_x_mode == CTRL_X_SPELL)
4528 {
4529 if (get_spell_compl_info(startcol, curs_col) == FAIL)
4530 return FAIL;
4531 *line_invalid = TRUE; // 'line' may have become invalid
4532 }
4533 else
4534 {
4535 internal_error("ins_complete()");
4536 return FAIL;
4537 }
4538
4539 return OK;
4540}
4541
4542/*
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004543 * Continue an interrupted completion mode search in "line".
4544 *
4545 * If this same ctrl_x_mode has been interrupted use the text from
4546 * "compl_startpos" to the cursor as a pattern to add a new word instead of
4547 * expand the one before the cursor, in word-wise if "compl_startpos" is not in
4548 * the same line as the cursor then fix it (the line has been split because it
4549 * was longer than 'tw'). if SOL is set then skip the previous pattern, a word
4550 * at the beginning of the line has been inserted, we'll look for that.
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004551 */
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004552 static void
4553ins_compl_continue_search(char_u *line)
4554{
4555 // it is a continued search
4556 compl_cont_status &= ~CONT_INTRPT; // remove INTRPT
4557 if (ctrl_x_mode == CTRL_X_NORMAL
4558 || ctrl_x_mode == CTRL_X_PATH_PATTERNS
4559 || ctrl_x_mode == CTRL_X_PATH_DEFINES)
4560 {
4561 if (compl_startpos.lnum != curwin->w_cursor.lnum)
4562 {
4563 // line (probably) wrapped, set compl_startpos to the
4564 // first non_blank in the line, if it is not a wordchar
4565 // include it to get a better pattern, but then we don't
4566 // want the "\\<" prefix, check it below
4567 compl_col = (colnr_T)getwhitecols(line);
4568 compl_startpos.col = compl_col;
4569 compl_startpos.lnum = curwin->w_cursor.lnum;
4570 compl_cont_status &= ~CONT_SOL; // clear SOL if present
4571 }
4572 else
4573 {
4574 // S_IPOS was set when we inserted a word that was at the
4575 // beginning of the line, which means that we'll go to SOL
4576 // mode but first we need to redefine compl_startpos
4577 if (compl_cont_status & CONT_S_IPOS)
4578 {
4579 compl_cont_status |= CONT_SOL;
4580 compl_startpos.col = (colnr_T)(skipwhite(
4581 line + compl_length
4582 + compl_startpos.col) - line);
4583 }
4584 compl_col = compl_startpos.col;
4585 }
4586 compl_length = curwin->w_cursor.col - (int)compl_col;
4587 // IObuff is used to add a "word from the next line" would we
4588 // have enough space? just being paranoid
4589#define MIN_SPACE 75
4590 if (compl_length > (IOSIZE - MIN_SPACE))
4591 {
4592 compl_cont_status &= ~CONT_SOL;
4593 compl_length = (IOSIZE - MIN_SPACE);
4594 compl_col = curwin->w_cursor.col - compl_length;
4595 }
4596 compl_cont_status |= CONT_ADDING | CONT_N_ADDS;
4597 if (compl_length < 1)
4598 compl_cont_status &= CONT_LOCAL;
4599 }
4600 else if (ctrl_x_mode_line_or_eval())
4601 compl_cont_status = CONT_ADDING | CONT_N_ADDS;
4602 else
4603 compl_cont_status = 0;
4604}
4605
4606/*
4607 * start insert mode completion
4608 */
4609 static int
4610ins_compl_start(void)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004611{
4612 char_u *line;
4613 int startcol = 0; // column where searched text starts
4614 colnr_T curs_col; // cursor column
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004615 int line_invalid = FALSE;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004616 int save_did_ai = did_ai;
Bram Moolenaard9eefe32019-04-06 14:22:21 +02004617 int flags = CP_ORIGINAL_TEXT;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004618
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004619 // First time we hit ^N or ^P (in a row, I mean)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004620
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004621 did_ai = FALSE;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004622#ifdef FEAT_SMARTINDENT
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004623 did_si = FALSE;
4624 can_si = FALSE;
4625 can_si_back = FALSE;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004626#endif
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004627 if (stop_arrow() == FAIL)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004628 return FAIL;
4629
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004630 line = ml_get(curwin->w_cursor.lnum);
4631 curs_col = curwin->w_cursor.col;
4632 compl_pending = 0;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004633
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004634 if ((compl_cont_status & CONT_INTRPT) == CONT_INTRPT
4635 && compl_cont_mode == ctrl_x_mode)
4636 // this same ctrl-x_mode was interrupted previously. Continue the
4637 // completion.
4638 ins_compl_continue_search(line);
4639 else
4640 compl_cont_status &= CONT_LOCAL;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004641
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004642 if (!(compl_cont_status & CONT_ADDING)) // normal expansion
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004643 {
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004644 compl_cont_mode = ctrl_x_mode;
4645 if (ctrl_x_mode != CTRL_X_NORMAL)
4646 // Remove LOCAL if ctrl_x_mode != CTRL_X_NORMAL
4647 compl_cont_status = 0;
4648 compl_cont_status |= CONT_N_ADDS;
4649 compl_startpos = curwin->w_cursor;
4650 startcol = (int)curs_col;
4651 compl_col = 0;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004652 }
4653
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004654 // Work out completion pattern and original text -- webb
4655 if (compl_get_info(line, startcol, curs_col, &line_invalid) == FAIL)
4656 {
4657 if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI
4658 || thesaurus_func_complete(ctrl_x_mode))
4659 // restore did_ai, so that adding comment leader works
4660 did_ai = save_did_ai;
4661 return FAIL;
4662 }
4663 // If "line" was changed while getting completion info get it again.
4664 if (line_invalid)
4665 line = ml_get(curwin->w_cursor.lnum);
4666
4667 if (compl_cont_status & CONT_ADDING)
4668 {
4669 edit_submode_pre = (char_u *)_(" Adding");
4670 if (ctrl_x_mode_line_or_eval())
4671 {
4672 // Insert a new line, keep indentation but ignore 'comments'.
4673 char_u *old = curbuf->b_p_com;
4674
4675 curbuf->b_p_com = (char_u *)"";
4676 compl_startpos.lnum = curwin->w_cursor.lnum;
4677 compl_startpos.col = compl_col;
4678 ins_eol('\r');
4679 curbuf->b_p_com = old;
4680 compl_length = 0;
4681 compl_col = curwin->w_cursor.col;
4682 }
4683 }
4684 else
4685 {
4686 edit_submode_pre = NULL;
4687 compl_startpos.col = compl_col;
4688 }
4689
4690 if (compl_cont_status & CONT_LOCAL)
4691 edit_submode = (char_u *)_(ctrl_x_msgs[CTRL_X_LOCAL_MSG]);
4692 else
4693 edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
4694
4695 // If any of the original typed text has been changed we need to fix
4696 // the redo buffer.
4697 ins_compl_fixRedoBufForLeader(NULL);
4698
4699 // Always add completion for the original text.
4700 vim_free(compl_orig_text);
4701 compl_orig_text = vim_strnsave(line + compl_col, compl_length);
4702 if (p_ic)
4703 flags |= CP_ICASE;
4704 if (compl_orig_text == NULL || ins_compl_add(compl_orig_text,
4705 -1, NULL, NULL, NULL, 0, flags, FALSE) != OK)
4706 {
4707 VIM_CLEAR(compl_pattern);
4708 VIM_CLEAR(compl_orig_text);
4709 return FAIL;
4710 }
4711
4712 // showmode might reset the internal line pointers, so it must
4713 // be called before line = ml_get(), or when this address is no
4714 // longer needed. -- Acevedo.
4715 edit_submode_extra = (char_u *)_("-- Searching...");
4716 edit_submode_highl = HLF_COUNT;
4717 showmode();
4718 edit_submode_extra = NULL;
4719 out_flush();
4720
4721 return OK;
4722}
4723
4724/*
4725 * display the completion status message
4726 */
4727 static void
4728ins_compl_show_statusmsg(void)
4729{
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004730 // we found no match if the list has only the "compl_orig_text"-entry
4731 if (compl_first_match == compl_first_match->cp_next)
4732 {
4733 edit_submode_extra = (compl_cont_status & CONT_ADDING)
4734 && compl_length > 1
Bram Moolenaar460ae5d2022-01-01 14:19:49 +00004735 ? (char_u *)_(e_hitend)
4736 : (char_u *)_(e_pattern_not_found);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004737 edit_submode_highl = HLF_E;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004738 }
4739
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004740 if (edit_submode_extra == NULL)
4741 {
Yegappan Lakshmanan6ad84ab2021-12-31 12:59:53 +00004742 if (ins_compl_at_original_text(compl_curr_match))
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004743 {
4744 edit_submode_extra = (char_u *)_("Back at original");
4745 edit_submode_highl = HLF_W;
4746 }
4747 else if (compl_cont_status & CONT_S_IPOS)
4748 {
4749 edit_submode_extra = (char_u *)_("Word from other line");
4750 edit_submode_highl = HLF_COUNT;
4751 }
4752 else if (compl_curr_match->cp_next == compl_curr_match->cp_prev)
4753 {
4754 edit_submode_extra = (char_u *)_("The only match");
4755 edit_submode_highl = HLF_COUNT;
Bram Moolenaarf9d51352020-10-26 19:22:42 +01004756 compl_curr_match->cp_number = 1;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004757 }
4758 else
4759 {
Bram Moolenaar977fd0b2020-10-27 09:12:45 +01004760#if defined(FEAT_COMPL_FUNC) || defined(FEAT_EVAL)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004761 // Update completion sequence number when needed.
4762 if (compl_curr_match->cp_number == -1)
Bram Moolenaarf9d51352020-10-26 19:22:42 +01004763 ins_compl_update_sequence_numbers();
Bram Moolenaar977fd0b2020-10-27 09:12:45 +01004764#endif
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004765 // The match should always have a sequence number now, this is
4766 // just a safety check.
4767 if (compl_curr_match->cp_number != -1)
4768 {
4769 // Space for 10 text chars. + 2x10-digit no.s = 31.
4770 // Translations may need more than twice that.
4771 static char_u match_ref[81];
4772
4773 if (compl_matches > 0)
4774 vim_snprintf((char *)match_ref, sizeof(match_ref),
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004775 _("match %d of %d"),
4776 compl_curr_match->cp_number, compl_matches);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004777 else
4778 vim_snprintf((char *)match_ref, sizeof(match_ref),
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004779 _("match %d"),
4780 compl_curr_match->cp_number);
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004781 edit_submode_extra = match_ref;
4782 edit_submode_highl = HLF_R;
4783 if (dollar_vcol >= 0)
4784 curs_columns(FALSE);
4785 }
4786 }
4787 }
4788
4789 // Show a message about what (completion) mode we're in.
4790 if (!compl_opt_suppress_empty)
4791 {
4792 showmode();
4793 if (!shortmess(SHM_COMPLETIONMENU))
4794 {
4795 if (edit_submode_extra != NULL)
4796 {
4797 if (!p_smd)
Bram Moolenaarcc233582020-12-12 13:32:07 +01004798 {
4799 msg_hist_off = TRUE;
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004800 msg_attr((char *)edit_submode_extra,
4801 edit_submode_highl < HLF_COUNT
4802 ? HL_ATTR(edit_submode_highl) : 0);
Bram Moolenaarcc233582020-12-12 13:32:07 +01004803 msg_hist_off = FALSE;
4804 }
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004805 }
4806 else
4807 msg_clr_cmdline(); // necessary for "noshowmode"
4808 }
4809 }
Yegappan Lakshmanan5d2e0072021-12-30 11:40:53 +00004810}
4811
4812/*
4813 * Do Insert mode completion.
4814 * Called when character "c" was typed, which has a meaning for completion.
4815 * Returns OK if completion was done, FAIL if something failed (out of mem).
4816 */
4817 int
4818ins_complete(int c, int enable_pum)
4819{
4820 int n;
4821 int save_w_wrow;
4822 int save_w_leftcol;
4823 int insert_match;
4824
4825 compl_direction = ins_compl_key2dir(c);
4826 insert_match = ins_compl_use_match(c);
4827
4828 if (!compl_started)
4829 {
4830 if (ins_compl_start() == FAIL)
4831 return FAIL;
4832 }
4833 else if (insert_match && stop_arrow() == FAIL)
4834 return FAIL;
4835
4836 compl_shown_match = compl_curr_match;
4837 compl_shows_dir = compl_direction;
4838
4839 // Find next match (and following matches).
4840 save_w_wrow = curwin->w_wrow;
4841 save_w_leftcol = curwin->w_leftcol;
4842 n = ins_compl_next(TRUE, ins_compl_key2count(c), insert_match, FALSE);
4843
4844 // may undisplay the popup menu
4845 ins_compl_upd_pum();
4846
4847 if (n > 1) // all matches have been found
4848 compl_matches = n;
4849 compl_curr_match = compl_shown_match;
4850 compl_direction = compl_shows_dir;
4851
4852 // Eat the ESC that vgetc() returns after a CTRL-C to avoid leaving Insert
4853 // mode.
4854 if (got_int && !global_busy)
4855 {
4856 (void)vgetc();
4857 got_int = FALSE;
4858 }
4859
4860 // we found no match if the list has only the "compl_orig_text"-entry
4861 if (compl_first_match == compl_first_match->cp_next)
4862 {
4863 // remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
4864 // because we couldn't expand anything at first place, but if we used
4865 // ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
4866 // (such as M in M'exico) if not tried already. -- Acevedo
4867 if (compl_length > 1
4868 || (compl_cont_status & CONT_ADDING)
4869 || (ctrl_x_mode != CTRL_X_NORMAL
4870 && ctrl_x_mode != CTRL_X_PATH_PATTERNS
4871 && ctrl_x_mode != CTRL_X_PATH_DEFINES))
4872 compl_cont_status &= ~CONT_N_ADDS;
4873 }
4874
4875 if (compl_curr_match->cp_flags & CP_CONT_S_IPOS)
4876 compl_cont_status |= CONT_S_IPOS;
4877 else
4878 compl_cont_status &= ~CONT_S_IPOS;
4879
4880 ins_compl_show_statusmsg();
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004881
4882 // Show the popup menu, unless we got interrupted.
4883 if (enable_pum && !compl_interrupted)
4884 show_pum(save_w_wrow, save_w_leftcol);
4885
4886 compl_was_interrupted = compl_interrupted;
4887 compl_interrupted = FALSE;
4888
4889 return OK;
4890}
4891
Yegappan Lakshmanane9825862022-01-03 11:03:48 +00004892/*
4893 * Remove (if needed) and show the popup menu
4894 */
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004895 static void
4896show_pum(int prev_w_wrow, int prev_w_leftcol)
4897{
4898 // RedrawingDisabled may be set when invoked through complete().
4899 int n = RedrawingDisabled;
4900
4901 RedrawingDisabled = 0;
4902
4903 // If the cursor moved or the display scrolled we need to remove the pum
4904 // first.
4905 setcursor();
4906 if (prev_w_wrow != curwin->w_wrow || prev_w_leftcol != curwin->w_leftcol)
4907 ins_compl_del_pum();
4908
4909 ins_compl_show_pum();
4910 setcursor();
4911 RedrawingDisabled = n;
4912}
4913
4914/*
4915 * Looks in the first "len" chars. of "src" for search-metachars.
4916 * If dest is not NULL the chars. are copied there quoting (with
4917 * a backslash) the metachars, and dest would be NUL terminated.
4918 * Returns the length (needed) of dest
4919 */
4920 static unsigned
4921quote_meta(char_u *dest, char_u *src, int len)
4922{
4923 unsigned m = (unsigned)len + 1; // one extra for the NUL
4924
4925 for ( ; --len >= 0; src++)
4926 {
4927 switch (*src)
4928 {
4929 case '.':
4930 case '*':
4931 case '[':
4932 if (ctrl_x_mode == CTRL_X_DICTIONARY
4933 || ctrl_x_mode == CTRL_X_THESAURUS)
4934 break;
4935 // FALLTHROUGH
4936 case '~':
Bram Moolenaarf4e20992020-12-21 19:59:08 +01004937 if (!magic_isset()) // quote these only if magic is set
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004938 break;
4939 // FALLTHROUGH
4940 case '\\':
4941 if (ctrl_x_mode == CTRL_X_DICTIONARY
4942 || ctrl_x_mode == CTRL_X_THESAURUS)
4943 break;
4944 // FALLTHROUGH
4945 case '^': // currently it's not needed.
4946 case '$':
4947 m++;
4948 if (dest != NULL)
4949 *dest++ = '\\';
4950 break;
4951 }
4952 if (dest != NULL)
4953 *dest++ = *src;
4954 // Copy remaining bytes of a multibyte character.
4955 if (has_mbyte)
4956 {
4957 int i, mb_len;
4958
4959 mb_len = (*mb_ptr2len)(src) - 1;
4960 if (mb_len > 0 && len >= mb_len)
4961 for (i = 0; i < mb_len; ++i)
4962 {
4963 --len;
4964 ++src;
4965 if (dest != NULL)
4966 *dest++ = *src;
4967 }
4968 }
4969 }
4970 if (dest != NULL)
4971 *dest = NUL;
4972
4973 return m;
4974}
4975
Bram Moolenaare2c453d2019-08-21 14:37:09 +02004976#if defined(EXITFREE) || defined(PROTO)
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004977 void
4978free_insexpand_stuff(void)
4979{
4980 VIM_CLEAR(compl_orig_text);
Yegappan Lakshmanan8658c752021-12-03 11:09:29 +00004981# ifdef FEAT_EVAL
4982 free_callback(&cfu_cb);
4983 free_callback(&ofu_cb);
4984 free_callback(&tsrfu_cb);
4985# endif
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004986}
Bram Moolenaare2c453d2019-08-21 14:37:09 +02004987#endif
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004988
Bram Moolenaare2c453d2019-08-21 14:37:09 +02004989#ifdef FEAT_SPELL
Bram Moolenaar7591bb32019-03-30 13:53:47 +01004990/*
4991 * Called when starting CTRL_X_SPELL mode: Move backwards to a previous badly
4992 * spelled word, if there is one.
4993 */
4994 static void
4995spell_back_to_badword(void)
4996{
4997 pos_T tpos = curwin->w_cursor;
4998
4999 spell_bad_len = spell_move_to(curwin, BACKWARD, TRUE, TRUE, NULL);
5000 if (curwin->w_cursor.col != tpos.col)
5001 start_arrow(&tpos);
5002}
Bram Moolenaare2c453d2019-08-21 14:37:09 +02005003#endif