popup_settext({id}, {text}) none set the text of popup window {id}
popup_show({id}) Number unhide popup window {id}
pow({x}, {y}) Float {x} to the power of {y}
+preinserted() Number whether text is inserted after cursor
prevnonblank({lnum}) Number line nr of non-blank line <= {lnum}
printf({fmt}, {expr1}...) String format text
prompt_getprompt({buf}) String get prompt text
Return type: |Number|
+preinserted() *preinserted()*
+ Returns non-zero if text has been inserted after the cursor
+ because "preinsert" is present in 'completeopt', or if
+ "longest" is present in 'completeopt' while 'autocomplete'
+ is enabled. Otherwise returns zero.
+
+ Return type: |Number|
+
+
prevnonblank({lnum}) *prevnonblank()*
Return the line number of the first line at or above {lnum}
that is not blank. Example: >
-*options.txt* For Vim version 9.1. Last change: 2025 Sep 22
+*options.txt* For Vim version 9.1. Last change: 2025 Sep 26
VIM REFERENCE MANUAL by Bram Moolenaar
to gather more alternatives for your candidate list,
see 'completefuzzycollect'.
- longest Only insert the longest common text of the matches. If
- the menu is displayed you can use CTRL-L to add more
- characters. Whether case is ignored depends on the kind
- of completion. For buffer text the 'ignorecase' option is
- used.
+ longest
+ When 'autocomplete' is not active, only the longest
+ common prefix of the matches is inserted. If the popup
+ menu is displayed, you can use CTRL-L to add more
+ characters. Whether case is ignored depends on the type
+ of completion. For buffer text the 'ignorecase' option
+ applies.
+
+ When 'autocomplete' is active and no completion item is
+ selected, the longest common prefix of the matches is
+ inserted after the cursor. The prefix is taken either
+ from all displayed items or only from items in the current
+ buffer. The inserted text is highlighted with
+ |hl-PreInsert|, and the cursor position does not change
+ (similar to `"preinsert"`). Press CTRL-Y to accept.
+ See also |preinserted()|.
menu Use a popup menu to show the possible completions. The
menu is only shown when there is more than one match and
{only works when compiled with the |+textprop| feature}
preinsert
- When 'autocomplete' is not active, inserts the part of the
- first candidate word beyond the current completion leader,
- highlighted with |hl-PreInsert|. The cursor doesn't move.
- Requires "fuzzy" unset and "menuone" in 'completeopt'.
-
- When 'autocomplete' is active, inserts the longest common
- prefix of matches (from all shown items or from the
- current buffer items). This occurs only when no menu item
- is selected. Press CTRL-Y to accept.
+ Inserts the text of the first completion candidate
+ beyond the current leader, highlighted with |hl-PreInsert|.
+ The cursor does not move.
+ Requires "fuzzy" to be unset, and either "menuone" in
+ 'completeopt' or 'autocomplete' enabled. When
+ 'autocomplete' is enabled, this does not work if
+ 'ignorecase' is set without 'infercase'.
+ See also |preinserted()|.
preview Show extra information about the currently selected
completion in the preview window. Only works in
combination with "menu" or "menuone".
- Only "fuzzy", "popup", "popuphidden", "preinsert" and "preview" have
- an effect when 'autocomplete' is enabled.
+ Only "fuzzy", "longest", "popup", "popuphidden", "preinsert" and
+ "preview" have an effect when 'autocomplete' is enabled.
This option does not apply to |cmdline-completion|. See 'wildoptions'
for that.
postscript-printing print.txt /*postscript-printing*
pow() builtin.txt /*pow()*
ppwiz.vim syntax.txt /*ppwiz.vim*
+preinserted() builtin.txt /*preinserted()*
press-enter message.txt /*press-enter*
press-return message.txt /*press-return*
prevcount-variable eval.txt /*prevcount-variable*
-*usr_41.txt* For Vim version 9.1. Last change: 2025 Aug 23
+*usr_41.txt* For Vim version 9.1. Last change: 2025 Sep 26
VIM USER MANUAL - by Bram Moolenaar
complete_info() get current completion information
complete_match() get insert completion start match col and
trigger text
+ preinserted() check if text is inserted after cursor
pumvisible() check if the popup menu is displayed
pum_getpos() position and size of popup menu if visible
-*version9.txt* For Vim version 9.1. Last change: 2025 Sep 22
+*version9.txt* For Vim version 9.1. Last change: 2025 Sep 26
VIM REFERENCE MANUAL by Bram Moolenaar
|matchstrlist()| all the matches of a pattern in a List of strings
|ngettext()| lookup single/plural message translation
|popup_setbuf()| switch to a different buffer in a popup
+|preinserted()| whether preinserted text has been inserted during
+ completion (see 'completeopt')
|str2blob()| convert a List of strings into a blob
|test_null_tuple()| return a null tuple
|tuple2list()| turn a Tuple of items into a List
syn keyword vimFuncName contained char2nr charclass charcol charidx chdir cindent clearmatches cmdcomplete_info col complete complete_add complete_check complete_info complete_match confirm copy cos cosh count cscope_connection cursor debugbreak deepcopy delete deletebufline did_filetype diff diff_filler diff_hlID digraph_get digraph_getlist digraph_set digraph_setlist echoraw empty environ err_teapot escape eval eventhandler executable execute exepath exists exists_compiled exp expand expandcmd extend extendnew feedkeys filecopy filereadable filewritable filter finddir findfile flatten flattennew float2nr floor fmod fnameescape fnamemodify foldclosed foldclosedend foldlevel foldtext foldtextresult foreach foreground fullcommand funcref function garbagecollect
syn keyword vimFuncName contained get getbufinfo getbufline getbufoneline getbufvar getcellpixels getcellwidths getchangelist getchar getcharmod getcharpos getcharsearch getcharstr getcmdcomplpat getcmdcompltype getcmdline getcmdpos getcmdprompt getcmdscreenpos getcmdtype getcmdwintype getcompletion getcompletiontype getcurpos getcursorcharpos getcwd getenv getfontname getfperm getfsize getftime getftype getimstatus getjumplist getline getloclist getmarklist getmatches getmousepos getmouseshape getpid getpos getqflist getreg getreginfo getregion getregionpos getregtype getscriptinfo getstacktrace gettabinfo gettabvar gettabwinvar gettagstack gettext getwininfo getwinpos getwinposx getwinposy getwinvar glob glob2regpat globpath has has_key haslocaldir hasmapto
syn keyword vimFuncName contained histadd histdel histget histnr hlID hlexists hlget hlset hostname iconv id indent index indexof input inputdialog inputlist inputrestore inputsave inputsecret insert instanceof interrupt invert isabsolutepath isdirectory isinf islocked isnan items job_getchannel job_info job_setoptions job_start job_status job_stop join js_decode js_encode json_decode json_encode keys keytrans len libcall libcallnr line line2byte lispindent list2blob list2str list2tuple listener_add listener_flush listener_remove localtime log log10 luaeval map maparg mapcheck maplist mapnew mapset match matchadd matchaddpos matcharg matchbufline matchdelete matchend matchfuzzy matchfuzzypos matchlist matchstr matchstrlist matchstrpos max menu_info min mkdir mode
-syn keyword vimFuncName contained mzeval nextnonblank ngettext nr2char or pathshorten perleval popup_atcursor popup_beval popup_clear popup_close popup_create popup_dialog popup_filter_menu popup_filter_yesno popup_findecho popup_findinfo popup_findpreview popup_getoptions popup_getpos popup_hide popup_list popup_locate popup_menu popup_move popup_notification popup_setbuf popup_setoptions popup_settext popup_show pow prevnonblank printf prompt_getprompt prompt_setcallback prompt_setinterrupt prompt_setprompt prop_add prop_add_list prop_clear prop_find prop_list prop_remove prop_type_add prop_type_change prop_type_delete prop_type_get prop_type_list pum_getpos pumvisible py3eval pyeval pyxeval rand range readblob readdir readdirex readfile reduce reg_executing
+syn keyword vimFuncName contained mzeval nextnonblank ngettext nr2char or pathshorten perleval popup_atcursor popup_beval popup_clear popup_close popup_create popup_dialog popup_filter_menu popup_filter_yesno popup_findecho popup_findinfo popup_findpreview popup_getoptions popup_getpos popup_hide popup_list popup_locate popup_menu popup_move popup_notification popup_setbuf popup_setoptions popup_settext popup_show pow preinserted prevnonblank printf prompt_getprompt prompt_setcallback prompt_setinterrupt prompt_setprompt prop_add prop_add_list prop_clear prop_find prop_list prop_remove prop_type_add prop_type_change prop_type_delete prop_type_get prop_type_list pum_getpos pumvisible py3eval pyeval pyxeval rand range readblob readdir readdirex readfile reduce reg_executing
syn keyword vimFuncName contained reg_recording reltime reltimefloat reltimestr remote_expr remote_foreground remote_peek remote_read remote_send remote_startserver remove rename repeat resolve reverse round rubyeval screenattr screenchar screenchars screencol screenpos screenrow screenstring search searchcount searchdecl searchpair searchpairpos searchpos server2client serverlist setbufline setbufvar setcellwidths setcharpos setcharsearch setcmdline setcmdpos setcursorcharpos setenv setfperm setline setloclist setmatches setpos setqflist setreg settabvar settabwinvar settagstack setwinvar sha256 shellescape shiftwidth sign_define sign_getdefined sign_getplaced sign_jump sign_place sign_placelist sign_undefine sign_unplace sign_unplacelist simplify sin sinh slice
syn keyword vimFuncName contained sort sound_clear sound_playevent sound_playfile sound_stop soundfold spellbadword spellsuggest split sqrt srand state str2blob str2float str2list str2nr strcharlen strcharpart strchars strdisplaywidth strftime strgetchar stridx string strlen strpart strptime strridx strtrans strutf16len strwidth submatch substitute swapfilelist swapinfo swapname synID synIDattr synIDtrans synconcealed synstack system systemlist tabpagebuflist tabpagenr tabpagewinnr tagfiles taglist tan tanh tempname term_dumpdiff term_dumpload term_dumpwrite term_getaltscreen term_getansicolors term_getattr term_getcursor term_getjob term_getline term_getscrolled term_getsize term_getstatus term_gettitle term_gettty term_list term_scrape term_sendkeys term_setansicolors
syn keyword vimFuncName contained term_setapi term_setkill term_setrestore term_setsize term_start term_wait terminalprops test_alloc_fail test_autochdir test_feedinput test_garbagecollect_now test_garbagecollect_soon test_getvalue test_gui_event test_ignore_error test_mswin_event test_null_blob test_null_channel test_null_dict test_null_function test_null_job test_null_list test_null_partial test_null_string test_null_tuple test_option_not_set test_override test_refcount test_setmouse test_settime test_srand_seed test_unknown test_void timer_info timer_pause timer_start timer_stop timer_stopall tolower toupper tr trim trunc tuple2list type typename undofile undotree uniq uri_decode uri_encode utf16idx values virtcol virtcol2col visualmode wildmenumode wildtrigger
&& stop_arrow() == OK)
{
ins_compl_delete();
- if (ins_compl_has_preinsert()
- && ins_compl_autocomplete_enabled())
- (void)ins_compl_insert(FALSE, TRUE);
- else
- (void)ins_compl_insert(FALSE, FALSE);
+ ins_compl_insert(FALSE, !ins_compl_has_preinsert());
+ if (ins_compl_preinsert_longest())
+ {
+ ins_compl_init_get_longest();
+ continue;
+ }
}
// Delete preinserted text when typing special chars
else if (IS_WHITE_NL_OR_NUL(c) && ins_compl_preinsert_effect())
ret_number, PROP_FUNC(f_popup_show)},
{"pow", 2, 2, FEARG_1, arg2_float_or_nr,
ret_float, f_pow},
+ {"preinserted", 0, 0, 0, NULL,
+ ret_number_bool, f_preinserted},
{"prevnonblank", 1, 1, FEARG_1, arg1_lnum,
ret_number, f_prevnonblank},
{"printf", 1, 19, FEARG_2, arg119_printf,
static int compl_timeout_ms = COMPL_INITIAL_TIMEOUT_MS;
static int compl_time_slice_expired = FALSE; // time budget exceeded for current source
static int compl_from_nonkeyword = FALSE; // completion started from non-keyword
-static int compl_autocomplete_preinsert = FALSE; // apply preinsert highlight
+static int compl_hi_on_autocompl_longest = FALSE; // apply "PreInsert" highlight
// Halve the current completion timeout, simulating exponential decay.
#define COMPL_MIN_TIMEOUT_MS 5
&& !(flags & COT_FUZZY);
}
+/*
+ * Returns TRUE if autocomplete is active and the pre-insert effect targets the
+ * longest prefix.
+ */
+ int
+ins_compl_preinsert_longest(void)
+{
+ return compl_autocomplete
+ && (get_cot_flags() & (COT_LONGEST | COT_PREINSERT | COT_FUZZY))
+ == COT_LONGEST;
+}
+
/*
* Add a match to the list of matches. The arguments are:
* str - text of the match to add
compl_curr_match = match;
// Find the longest common string if still doing that.
- if (compl_get_longest && (flags & CP_ORIGINAL_TEXT) == 0 && !cfc_has_mode())
+ if (compl_get_longest && (flags & CP_ORIGINAL_TEXT) == 0 && !cfc_has_mode()
+ && !ins_compl_preinsert_longest())
ins_compl_longest_match(match);
return OK;
ins_compl_col_range_attr(linenr_T lnum, int col)
{
int start_col;
+ int has_preinsert = ins_compl_has_preinsert()
+ || ins_compl_preinsert_longest();
int attr;
- int has_preinsert = ins_compl_has_preinsert();
if ((get_cot_flags() & COT_FUZZY)
- || (!has_preinsert
- && (attr = syn_name2attr((char_u *)"ComplMatchIns")) == 0)
- || (!compl_autocomplete && has_preinsert
- && (attr = syn_name2attr((char_u *)"PreInsert")) == 0)
- || (compl_autocomplete
- && (!compl_autocomplete_preinsert
- || (attr = syn_name2attr((char_u *)"PreInsert")) == 0)))
+ || (!compl_hi_on_autocompl_longest && ins_compl_preinsert_longest())
+ || (attr = syn_name2attr(has_preinsert
+ ? (char_u *)"PreInsert" : (char_u *)"ComplMatchIns")) == 0)
return -1;
start_col = compl_col + (int)ins_compl_leader_len();
int cur = -1;
unsigned int cur_cot_flags = get_cot_flags();
int compl_no_select = (cur_cot_flags & COT_NOSELECT) != 0
- || compl_autocomplete;
+ || (compl_autocomplete && !ins_compl_has_preinsert());
int fuzzy_filter = (cur_cot_flags & COT_FUZZY) != 0;
compl_T *match_head = NULL;
compl_T *match_tail = NULL;
ins_compl_has_preinsert(void)
{
int cur_cot_flags = get_cot_flags();
+ if (compl_autocomplete && p_ic && !p_inf)
+ return FALSE;
return !compl_autocomplete
? (cur_cot_flags & (COT_PREINSERT | COT_FUZZY | COT_MENUONE))
== (COT_PREINSERT | COT_MENUONE)
int
ins_compl_preinsert_effect(void)
{
- if (!ins_compl_has_preinsert())
+ if (!ins_compl_has_preinsert() && !ins_compl_preinsert_longest())
return FALSE;
return curwin->w_cursor.col < compl_ins_end_col;
}
-/*
- * Returns TRUE if autocompletion is active.
- */
- int
-ins_compl_autocomplete_enabled(void)
-{
- return compl_autocomplete;
-}
-
/*
* Delete one character before the cursor and show the subset of the matches
* that match the word that is now before the cursor.
}
// Clear selection if a menu item is currently selected in autocompletion
- if (compl_autocomplete && compl_first_match)
+ if (compl_autocomplete && compl_first_match && !ins_compl_has_preinsert())
compl_shown_match = compl_first_match;
ins_compl_new_leader();
if (!compl_interrupted)
show_pum(save_w_wrow, save_w_leftcol);
- compl_autocomplete_preinsert = FALSE;
// Don't let Enter select the original text when there is no popup menu.
if (compl_match_array == NULL)
compl_enter_selects = FALSE;
else if (ins_compl_has_preinsert() && compl_leader.length > 0)
- {
- if (compl_started && compl_autocomplete
- && !ins_compl_preinsert_effect())
- {
- if (ins_compl_insert(TRUE, TRUE) == OK)
- compl_autocomplete_preinsert = TRUE;
- }
- else
- (void)ins_compl_insert(TRUE, FALSE);
- }
+ ins_compl_insert(TRUE, FALSE);
+ else if (compl_started && ins_compl_preinsert_longest()
+ && compl_leader.length > 0 && !ins_compl_preinsert_effect())
+ ins_compl_insert(TRUE, TRUE);
}
/*
ins_compl_restart();
// When 'always' is set, don't reset compl_leader. While completing,
- // cursor doesn't point original position, changing compl_leader would
- // break redo.
+ // cursor doesn't point to the original position, changing compl_leader
+ // would break redo.
if (!compl_opt_refresh_always)
{
VIM_CLEAR_STRING(compl_leader);
compl_leader.length = (size_t)(curwin->w_cursor.col - compl_col);
compl_leader.string = vim_strnsave(ml_get_curline() + compl_col,
- compl_leader.length);
+ compl_leader.length);
if (compl_leader.string == NULL)
{
compl_leader.length = 0;
if (!in_fuzzy_collect)
ptr = ins_compl_get_next_word_or_line(st->ins_buf,
st->cur_match_pos, &len, &cont_s_ipos);
- if (ptr == NULL || (!compl_autocomplete && ins_compl_has_preinsert()
+ if (ptr == NULL || (ins_compl_has_preinsert()
&& STRCMP(ptr, compl_pattern.string) == 0))
continue;
}
may_trigger_modechanged();
- if (is_nearest_active())
+ if (is_nearest_active() && !ins_compl_has_preinsert())
sort_compl_match_list(cp_compare_nearest);
return match_count;
if (len > (int)ins_compl_leader_len())
{
+ // Avoid inserting text that duplicates the text already present
+ // after the cursor.
+ if (len == (int)STRLEN(first))
+ {
+ char_u *line = ml_get_curline();
+ char_u *p = line + curwin->w_cursor.col;
+ if (p && !IS_WHITE_OR_NUL(*p))
+ {
+ char_u *end = find_word_end(p);
+ int text_len = end - p;
+ if (text_len > 0
+ && text_len < (len - (int)ins_compl_leader_len())
+ && STRNCMP(first + len - text_len, p, text_len) == 0)
+ len -= text_len;
+ }
+ }
*prefix_len = (size_t)len;
return first;
}
* Insert the new text being completed.
* "move_cursor" is used when 'completeopt' includes "preinsert" and when TRUE
* cursor needs to move back from the inserted text to the compl_leader.
- * When "preinsert_prefix" is TRUE the longest common prefix is inserted
- * instead of shown match.
+ * When "insert_prefix" is TRUE the longest common prefix is inserted instead
+ * of shown match.
*/
- int
-ins_compl_insert(int move_cursor, int preinsert_prefix)
+ void
+ins_compl_insert(int move_cursor, int insert_prefix)
{
int compl_len = get_compl_len();
int preinsert = ins_compl_has_preinsert();
size_t leader_len = ins_compl_leader_len();
char_u *has_multiple = vim_strchr(cp_str, '\n');
- if (preinsert_prefix)
+ if (insert_prefix)
{
cp_str = find_common_prefix(&cp_str_len, FALSE);
if (cp_str == NULL)
{
cp_str = find_common_prefix(&cp_str_len, TRUE);
if (cp_str == NULL)
- return FAIL;
+ {
+ cp_str = compl_shown_match->cp_str.string;
+ cp_str_len = compl_shown_match->cp_str.length;
+ }
}
}
// Since completion sources may provide matches with varying start
else
{
ins_compl_insert_bytes(cp_str + compl_len,
- preinsert_prefix ? (int)cp_str_len - compl_len : -1);
- if (preinsert && move_cursor)
+ insert_prefix ? (int)cp_str_len - compl_len : -1);
+ if ((preinsert || insert_prefix) && move_cursor)
curwin->w_cursor.col -= (colnr_T)(cp_str_len - leader_len);
}
}
if (match_at_original_text(compl_shown_match)
- || (preinsert && !compl_autocomplete))
+ || (preinsert && !insert_prefix))
compl_used_match = FALSE;
else
compl_used_match = TRUE;
set_vim_var_dict(VV_COMPLETED_ITEM, dict);
}
#endif
- return OK;
+ compl_hi_on_autocompl_longest = insert_prefix && move_cursor;
}
/*
compl_T *found_compl = NULL;
unsigned int cur_cot_flags = get_cot_flags();
int compl_no_select = (cur_cot_flags & COT_NOSELECT) != 0
- || compl_autocomplete;
+ || (compl_autocomplete && !ins_compl_has_preinsert());
int compl_fuzzy_match = (cur_cot_flags & COT_FUZZY) != 0;
string_T *leader;
buf_T *orig_curbuf = curbuf;
unsigned int cur_cot_flags = get_cot_flags();
int compl_no_insert = (cur_cot_flags & COT_NOINSERT) != 0
- || compl_autocomplete;
+ || (compl_autocomplete && !ins_compl_has_preinsert());
int compl_fuzzy_match = (cur_cot_flags & COT_FUZZY) != 0;
int compl_preinsert = ins_compl_has_preinsert();
return -1;
}
- compl_autocomplete_preinsert = FALSE;
-
// Insert the text of the new completion, or the compl_leader.
- if (compl_no_insert && !started)
+ if (!started && ins_compl_preinsert_longest())
+ ins_compl_insert(TRUE, TRUE);
+ else if (compl_no_insert && !started && !compl_preinsert)
{
- int insert_orig = !compl_preinsert;
- if (compl_preinsert && compl_autocomplete)
- {
- if (ins_compl_insert(TRUE, TRUE) == OK)
- compl_autocomplete_preinsert = TRUE;
- else
- insert_orig = TRUE;
- }
- if (insert_orig)
- ins_compl_insert_bytes(compl_orig_text.string + get_compl_len(), -1);
+ ins_compl_insert_bytes(compl_orig_text.string + get_compl_len(), -1);
compl_used_match = FALSE;
}
else if (insert_match)
{
if (!compl_get_longest || compl_used_match)
{
- int none_selected = match_at_original_text(compl_shown_match);
- if (compl_preinsert && compl_autocomplete
- && none_selected)
- {
- if (ins_compl_insert(none_selected, TRUE) == OK)
- compl_autocomplete_preinsert = none_selected;
- else
- (void)ins_compl_insert(FALSE, FALSE);
- }
- else
- (void)ins_compl_insert(!compl_autocomplete, FALSE);
+ int preinsert_longest = ins_compl_preinsert_longest()
+ && match_at_original_text(compl_shown_match); // none selected
+ ins_compl_insert(compl_preinsert || preinsert_longest,
+ preinsert_longest);
}
else
ins_compl_insert_bytes(compl_leader.string + get_compl_len(), -1);
check_elapsed_time();
}
- if (compl_pending != 0 && !got_int && !(cot_flags & COT_NOINSERT)
- && !compl_autocomplete)
+ if (compl_pending && !got_int && !(cot_flags & COT_NOINSERT)
+ && (!compl_autocomplete || ins_compl_has_preinsert()))
{
// Insert the first match immediately and advance compl_shown_match,
// before finding other matches.
compl_matches = ins_compl_make_cyclic();
#endif
}
+
+/*
+ * "preinserted()" function
+ */
+ void
+f_preinserted(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
+{
+ if (ins_compl_preinsert_effect())
+ rettv->vval.v_number = 1;
+}
int ins_compl_len(void);
int ins_compl_has_preinsert(void);
int ins_compl_preinsert_effect(void);
-int ins_compl_autocomplete_enabled(void);
int ins_compl_bs(void);
void ins_compl_addleader(int c);
void ins_compl_addfrommatch(void);
void f_complete_match(typval_T *argvars, typval_T *rettv);
void f_complete_info(typval_T *argvars, typval_T *rettv);
void ins_compl_delete(void);
-int ins_compl_insert(int move_cursor, int preinsert_prefix);
+void ins_compl_insert(int move_cursor, int insert_longest);
void ins_compl_check_keys(int frequency, int in_compl_func);
int ins_complete(int c, int enable_pum);
void ins_compl_enable_autocomplete(void);
void free_insexpand_stuff(void);
int ins_compl_has_autocomplete(void);
+int ins_compl_preinsert_longest(void);
+void f_preinserted(typval_T *argvars UNUSED, typval_T *rettv UNUSED);
/* vim: set ft=c : */
|f+0&#ffffff0|o@1| @71
|f|o@1|b|a|r| @68
|f|o@1|b|a|r|b|a|z| @65
-|f>o+0#00e0003&@1| +0#0000000&@71
-|f+0#0000001#e0e0e08|o@1| @11| +0#4040ff13#ffffff0@59
+|f|o@1> @71
+|f+0#0000001#ffd7ff255|o@1| @11| +0#4040ff13#ffffff0@59
|f+0#0000001#ffd7ff255|o@1|b|a|r| @8| +0#4040ff13#ffffff0@59
|f+0#0000001#ffd7ff255|o@1|b|a|r|b|a|z| @5| +0#4040ff13#ffffff0@59
|~| @73
|~| @73
-|-+2#0000000&@1| |K|e|y|w|o|r|d| |c|o|m|p|l|e|t|i|o|n| |(|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |3| +0#0000000&@33
+|-+2#0000000&@1| |K|e|y|w|o|r|d| |c|o|m|p|l|e|t|i|o|n| |(|^|N|^|P|)| |B+0#e000002&|a|c|k| |a|t| |o|r|i|g|i|n|a|l| +0#0000000&@29
func Test_omni_dash()
func Omni(findstart, base)
if a:findstart
- return 5
+ return 5
else
- echom a:base
- return ['-help', '-v']
+ return ['-help', '-v']
endif
endfunc
set omnifunc=Omni
delfunc Omni_test
endfunc
+func Test_autocomplete_completeopt_preinsert()
+ func Omni_test(findstart, base)
+ if a:findstart
+ return col(".") - 1
+ endif
+ return [#{word: "fobar"}, #{word: "foobar"}]
+ endfunc
+ set omnifunc=Omni_test complete+=o
+ set completeopt=preinsert autocomplete
+ " set completeopt=preinsert,menuone autocomplete
+ func GetLine()
+ let g:line = getline('.')
+ let g:col = col('.')
+ endfunc
+
+ call test_override("char_avail", 1)
+ new
+ inoremap <buffer><F5> <C-R>=GetLine()<CR>
+ call feedkeys("Sfo\<F5>\<ESC>", 'tx')
+ call assert_equal("fobar", g:line)
+ call assert_equal(3, g:col)
+
+ call feedkeys("Sfoo\<F5>\<ESC>", 'tx')
+ call assert_equal("foobar", g:line)
+
+ call feedkeys("Sfoo\<BS>\<BS>\<BS>", 'tx')
+ call assert_equal("", getline('.'))
+
+ " delete a character
+ call feedkeys("Sfoo\<BS>b\<F5>\<ESC>", 'tx')
+ call assert_equal("fobar", g:line)
+ call assert_equal(4, g:col)
+
+ set complete&
+ %d
+ call setline(1, ['fobar', 'foobar'])
+
+ call feedkeys("Gofoo\<BS>\<BS>\<F5>\<ESC>", 'tx')
+ call assert_equal("fobar", g:line)
+ call assert_equal(2, g:col)
+
+ call feedkeys("Shello wo\<Left>\<Left>\<Left>f\<F5>\<ESC>", 'tx')
+ call assert_equal("hello fobar wo", g:line)
+ call assert_equal(9, g:col)
+
+ call feedkeys("Shello wo\<Left>\<Left>\<Left>f\<BS>\<F5>\<ESC>", 'tx')
+ call assert_equal("hello wo", g:line)
+ call assert_equal(8, g:col)
+
+ call feedkeys("Shello wo\<Left>\<Left>\<Left>foo\<F5>\<ESC>", 'tx')
+ call assert_equal("hello foobar wo", g:line)
+ call assert_equal(11, g:col)
+
+ call feedkeys("Shello wo\<Left>\<Left>\<Left>foo\<BS>b\<F5>\<ESC>", 'tx')
+ call assert_equal("hello fobar wo", g:line)
+ call assert_equal(11, g:col)
+
+ " confirm
+ call feedkeys("Sf\<C-Y>", 'tx')
+ call assert_equal("fobar", getline('.'))
+ call assert_equal(5, col('.'))
+
+ " cancel
+ call feedkeys("Sfo\<C-E>", 'tx')
+ call assert_equal("fo", getline('.'))
+ call assert_equal(2, col('.'))
+
+ " delete preinsert part
+ call feedkeys("Sfo ", 'tx')
+ call assert_equal("fo ", getline('.'))
+ call assert_equal(3, col('.'))
+
+ " can not work with fuzzy
+ set cot+=fuzzy
+ call feedkeys("Sf", 'tx')
+ call assert_equal("f", getline('.'))
+ set cot-=fuzzy
+
+ " does not work with 'ignorecase' unless 'infercase' is also enabled
+ %d
+ call setline(1, ['FIX', 'fobar', 'foobar'])
+ set ignorecase
+ call feedkeys("Gof\<F5>\<ESC>", 'tx')
+ call assert_equal("f", g:line) " should not produce 'FIX'
+ set infercase
+ call feedkeys("Gof\<F5>\<ESC>", 'tx')
+ call assert_equal("fix", g:line)
+ set ignorecase& infercase&
+
+ %delete _
+ let &l:undolevels = &l:undolevels
+ normal! ifoo
+ let &l:undolevels = &l:undolevels
+ normal! obar
+ let &l:undolevels = &l:undolevels
+ normal! obaz
+ let &l:undolevels = &l:undolevels
+
+ func CheckUndo()
+ let g:errmsg = ''
+ call assert_equal(['foo', 'bar', 'baz'], getline(1, '$'))
+ undo
+ call assert_equal(['foo', 'bar'], getline(1, '$'))
+ undo
+ call assert_equal(['foo'], getline(1, '$'))
+ undo
+ call assert_equal([''], getline(1, '$'))
+ later 3
+ call assert_equal(['foo', 'bar', 'baz'], getline(1, '$'))
+ call assert_equal('', v:errmsg)
+ endfunc
+
+ " Check that switching buffer with "preinsert" doesn't corrupt undo.
+ new
+ setlocal bufhidden=wipe
+ inoremap <buffer> <F2> <Cmd>enew!<CR>
+ call feedkeys("if\<F2>\<Esc>", 'tx')
+ bwipe!
+ call CheckUndo()
+
+ " Check that closing window with "preinsert" doesn't corrupt undo.
+ new
+ setlocal bufhidden=wipe
+ inoremap <buffer> <F2> <Cmd>close!<CR>
+ call feedkeys("if\<F2>\<Esc>", 'tx')
+ call CheckUndo()
+
+ %delete _
+ delfunc CheckUndo
+
+ bw!
+ set cot&
+ set omnifunc&
+ set autocomplete&
+ call test_override("char_avail", 0)
+ delfunc Omni_test
+ delfunc GetLine
+endfunc
+
" Check that mark positions are correct after triggering multiline completion.
func Test_complete_multiline_marks()
func Omni_test(findstart, base)
call VerifyScreenDump(buf, 'Test_autocompletedelay_6', {})
" During delay wait, user can open menu using CTRL_N completion
- call term_sendkeys(buf, "\<Esc>:set completeopt=menuone,preinsert\<CR>")
+ call term_sendkeys(buf, "\<Esc>:set completeopt=menuone,longest\<CR>")
call term_sendkeys(buf, "Sf\<C-N>")
call VerifyScreenDump(buf, 'Test_autocompletedelay_7', {})
call StopVimInTerminal(buf)
endfunc
-func Test_autocomplete_completeopt_preinsert()
+" Preinsert longest prefix when autocomplete
+func Test_autocomplete_longest()
func GetLine()
let g:line = getline('.')
let g:col = col('.')
+ let g:preinserted = preinserted()
endfunc
call test_override("char_avail", 1)
new
inoremap <buffer><F5> <C-R>=GetLine()<CR>
- set completeopt=preinsert autocomplete
+ set completeopt=longest autocomplete
call setline(1, ["foobar", "foozbar"])
call feedkeys("Go\<ESC>", 'tx')
call DoTest("f\<C-P>", 'foobar', 7)
call DoTest("fo\<BS>\<C-P>", 'foobar', 7)
+ " <C-Y> to accept preinserted text
+ inoremap <buffer><F6> <C-R>=pumvisible()<CR>
call DoTest("zar\<C-O>0f", 'foozar', 2)
call DoTest("zar\<C-O>0f\<C-Y>", 'foozar', 4)
+ call DoTest("zar\<C-O>0f\<C-Y>\<F6>", 'foo1zar', 5)
call DoTest("zar\<C-O>0f\<C-Y>\<BS>", 'foozar', 3)
+ call DoTest("zar\<C-O>0f\<C-Y>\<BS>\<F6>", 'fo1zar', 4)
+ " Select items in menu
call DoTest("zar\<C-O>0f\<C-N>", 'foozbarzar', 8)
call DoTest("zar\<C-O>0f\<C-N>\<C-N>", 'foobarzar', 7)
call DoTest("zar\<C-O>0f\<C-N>\<C-N>\<C-N>", 'foozar', 2)
call DoTest("f", 'f', 2)
set cot-=fuzzy
+ " preinserted()
+ call DoTest("f", 'foo', 2)
+ call assert_equal(1, g:preinserted)
+ call assert_equal(0, preinserted())
+ call DoTest("f\<BS>", '', 1)
+ call assert_equal(0, g:preinserted)
+ call DoTest("f ", 'f ', 3)
+ call assert_equal(0, g:preinserted)
+ call DoTest("foob", 'foobar', 5)
+ call assert_equal(1, g:preinserted)
+ call DoTest("foob\<BS>\<BS>x", 'fox', 4)
+ call assert_equal(0, g:preinserted)
+
+ " Complete non-keyword
+ func Omni(findstart, base)
+ if a:findstart
+ return 5
+ else
+ return ['xyz:']
+ endif
+ endfunc
+ set omnifunc=Omni
+ set cpt+=o
+ call DoTest("xyz:", "xyz:xyz:", 5)
+ call DoTest("xyz:\<BS>\<BS>", "xyz:", 3)
+ set omnifunc& cpt&
+ delfunc Omni
+
" leader should match prefix of inserted word
%delete
set smartcase ignorecase
call assert_equal('FOO', g:line)
set smartcase& ignorecase&
+ " avoid repeating text that is already present after the cursor
+ %delete
+ call setline(1, ["foobarbaz", ""])
+ call feedkeys($"G", 'tx')
+ call DoTest("baz\<C-O>0f", "foobarbaz", 2)
+ call feedkeys($"Sxfoozar\<CR>\<Esc>", 'tx')
+ call DoTest("baz\<C-O>0f", "foobarbaz", 2)
+ call feedkeys($"Sfoozar\<CR>\<Esc>", 'tx')
+ call DoTest("baz\<C-O>0f", "foobaz", 2)
+
" Verify that redo (dot) works
%delete
call setline(1, ["foobar", "foozbar", "foobaz", "changed", "change"])
call assert_equal('', v:errmsg)
endfunc
- " Check that switching buffer with "preinsert" doesn't corrupt undo.
+ " Check that switching buffer with "longest" doesn't corrupt undo.
new
setlocal bufhidden=wipe
inoremap <buffer> <F2> <Cmd>enew!<CR>
bwipe!
call CheckUndo()
- " Check that closing window with "preinsert" doesn't corrupt undo.
+ " Check that closing window with "longest" doesn't corrupt undo.
new
setlocal bufhidden=wipe
inoremap <buffer> <F2> <Cmd>close!<CR>
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1797,
/**/
1796,
/**/