diff options
Diffstat (limited to 'src/nvim/edit.c')
-rw-r--r-- | src/nvim/edit.c | 178 |
1 files changed, 96 insertions, 82 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c index e131da8fe0..95c33916f1 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -29,7 +29,6 @@ #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/misc1.h" -#include "nvim/misc2.h" #include "nvim/keymap.h" #include "nvim/move.h" #include "nvim/normal.h" @@ -463,6 +462,7 @@ static void insert_enter(InsertState *s) o_lnum = curwin->w_cursor.lnum; } + foldUpdateAfterInsert(); if (s->cmdchar != 'r' && s->cmdchar != 'v') { apply_autocmds(EVENT_INSERTLEAVE, NULL, NULL, false, curbuf); } @@ -474,7 +474,9 @@ static int insert_check(VimState *state) InsertState *s = (InsertState *)state; // If typed something may trigger CursorHoldI again. - if (s->c != K_EVENT) { + if (s->c != K_EVENT + // but not in CTRL-X mode, a script can't restore the state + && ctrl_x_mode == 0) { did_cursorhold = false; } @@ -501,7 +503,7 @@ static int insert_check(VimState *state) Insstart_orig = Insstart; } - if (stop_insert_mode) { + if (stop_insert_mode && !pum_visible()) { // ":stopinsert" used or 'insertmode' reset s->count = 0; return 0; // exit insert mode @@ -664,11 +666,12 @@ static int insert_execute(VimState *state, int key) // Pressing CTRL-Y selects the current match. When // compl_enter_selects is set the Enter key does the same. - if (s->c == Ctrl_Y - || (compl_enter_selects - && (s->c == CAR || s->c == K_KENTER || s->c == NL))) { + if ((s->c == Ctrl_Y + || (compl_enter_selects + && (s->c == CAR || s->c == K_KENTER || s->c == NL))) + && stop_arrow() == OK) { ins_compl_delete(); - ins_compl_insert(); + ins_compl_insert(false); } } } @@ -961,7 +964,7 @@ static int insert_handle_key(InsertState *s) break; case K_EVENT: // some event - queue_process_events(loop.events); + multiqueue_process_events(main_loop.events); break; case K_FOCUSGAINED: // Neovim has been given focus @@ -1285,10 +1288,9 @@ bool edit(int cmdchar, bool startln, long count) { if (curbuf->terminal) { if (ex_normal_busy) { - // don't enter terminal mode from `ex_normal`, which can result in all - // kinds of havoc(such as terminal mode recursiveness). Instead, set a - // flag that allow us to force-set the value of `restart_edit` before - // `ex_normal` returns + // Do not enter terminal mode from ex_normal(), which would cause havoc + // (such as terminal-mode recursiveness). Instead set a flag to force-set + // the value of `restart_edit` before `ex_normal` returns. restart_edit = 'i'; force_restart_edit = true; } else { @@ -2322,7 +2324,6 @@ static int ins_compl_make_cyclic(void) return count; } - // Set variables that store noselect and noinsert behavior from the // 'completeopt' value. void completeopt_was_set(void) @@ -2351,9 +2352,6 @@ void set_completion(colnr_T startcol, list_T *list) } ins_compl_clear(); - if (stop_arrow() == FAIL) - return; - compl_direction = FORWARD; if (startcol > curwin->w_cursor.col) startcol = curwin->w_cursor.col; @@ -2385,6 +2383,7 @@ void set_completion(colnr_T startcol, list_T *list) } else { ins_complete(Ctrl_N, false); } + compl_enter_selects = compl_no_insert; // Lazily show the popup menu, unless we got interrupted. if (!compl_interrupted) { @@ -2471,6 +2470,7 @@ void ins_compl_show_pum(void) int cur = -1; colnr_T col; int lead_len = 0; + bool array_changed = false; if (!pum_wanted() || !pum_enough_matches()) return; @@ -2482,7 +2482,8 @@ void ins_compl_show_pum(void) update_screen(0); if (compl_match_array == NULL) { - /* Need to build the popup menu list. */ + array_changed = true; + // Need to build the popup menu list. compl_match_arraysize = 0; compl = compl_first_match; /* @@ -2585,7 +2586,7 @@ void ins_compl_show_pum(void) // Use the cursor to get all wrapping and other settings right. col = curwin->w_cursor.col; curwin->w_cursor.col = compl_col; - pum_display(compl_match_array, compl_match_arraysize, cur); + pum_display(compl_match_array, compl_match_arraysize, cur, array_changed); curwin->w_cursor.col = col; } @@ -2775,7 +2776,7 @@ static void ins_compl_files(int count, char_u **files, int thesaurus, int flags, break; } line_breakcheck(); - ins_compl_check_keys(50); + ins_compl_check_keys(50, false); } fclose(fp); } @@ -3261,14 +3262,19 @@ static bool ins_compl_prep(int c) } else { int prev_col = curwin->w_cursor.col; - /* put the cursor on the last char, for 'tw' formatting */ - if (prev_col > 0) + // put the cursor on the last char, for 'tw' formatting + if (prev_col > 0) { dec_cursor(); - if (stop_arrow() == OK) + } + + if (!arrow_used && !ins_need_undo && c != Ctrl_E) { insertchar(NUL, 0, -1); + } + if (prev_col > 0 - && get_cursor_line_ptr()[curwin->w_cursor.col] != NUL) + && get_cursor_line_ptr()[curwin->w_cursor.col] != NUL) { inc_cursor(); + } } // If the popup menu is displayed pressing CTRL-Y means accepting @@ -3280,7 +3286,8 @@ static bool ins_compl_prep(int c) retval = true; } - /* CTRL-E means completion is Ended, go back to the typed text. */ + // CTRL-E means completion is Ended, go back to the typed text. + // but only do this, if the Popup is still visible if (c == Ctrl_E) { ins_compl_delete(); if (compl_leader != NULL) { @@ -3529,21 +3536,15 @@ int ins_compl_add_tv(typval_T *tv, int dir) char_u *(cptext[CPT_COUNT]); if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) { - word = get_dict_string(tv->vval.v_dict, (char_u *)"word", FALSE); - cptext[CPT_ABBR] = get_dict_string(tv->vval.v_dict, - (char_u *)"abbr", FALSE); - cptext[CPT_MENU] = get_dict_string(tv->vval.v_dict, - (char_u *)"menu", FALSE); - cptext[CPT_KIND] = get_dict_string(tv->vval.v_dict, - (char_u *)"kind", FALSE); - cptext[CPT_INFO] = get_dict_string(tv->vval.v_dict, - (char_u *)"info", FALSE); - if (get_dict_string(tv->vval.v_dict, (char_u *)"icase", FALSE) != NULL) - icase = get_dict_number(tv->vval.v_dict, (char_u *)"icase"); - if (get_dict_string(tv->vval.v_dict, (char_u *)"dup", FALSE) != NULL) - adup = get_dict_number(tv->vval.v_dict, (char_u *)"dup"); - if (get_dict_string(tv->vval.v_dict, (char_u *)"empty", FALSE) != NULL) - aempty = get_dict_number(tv->vval.v_dict, (char_u *)"empty"); + word = get_dict_string(tv->vval.v_dict, "word", false); + cptext[CPT_ABBR] = get_dict_string(tv->vval.v_dict, "abbr", false); + cptext[CPT_MENU] = get_dict_string(tv->vval.v_dict, "menu", false); + cptext[CPT_KIND] = get_dict_string(tv->vval.v_dict, "kind", false); + cptext[CPT_INFO] = get_dict_string(tv->vval.v_dict, "info", false); + + icase = get_dict_number(tv->vval.v_dict, "icase"); + adup = get_dict_number(tv->vval.v_dict, "dup"); + aempty = get_dict_number(tv->vval.v_dict, "empty"); } else { word = get_tv_string_chk(tv); memset(cptext, 0, sizeof(cptext)); @@ -3846,13 +3847,11 @@ static int ins_compl_get_exp(pos_T *ini) if ((compl_cont_status & CONT_ADDING) && len == compl_length) { if (pos->lnum < ins_buf->b_ml.ml_line_count) { - /* Try next line, if any. the new word will be - * "join" as if the normal command "J" was used. - * IOSIZE is always greater than - * compl_length, so the next STRNCPY always - * works -- Acevedo */ + // Try next line, if any. the new word will be "join" as if the + // normal command "J" was used. IOSIZE is always greater than + // compl_length, so the next STRNCPY always works -- Acevedo STRNCPY(IObuff, ptr, len); - ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE); + ptr = ml_get_buf(ins_buf, pos->lnum + 1, false); tmp_ptr = ptr = skipwhite(ptr); /* Find start of next word. */ tmp_ptr = find_word_start(tmp_ptr); @@ -3908,7 +3907,7 @@ static int ins_compl_get_exp(pos_T *ini) break; /* Fill the popup menu as soon as possible. */ if (type != -1) - ins_compl_check_keys(0); + ins_compl_check_keys(0, false); if ((l_ctrl_x_mode != 0 && !CTRL_X_MODE_LINE_OR_EVAL(l_ctrl_x_mode)) || compl_interrupted) { @@ -3951,23 +3950,28 @@ static int ins_compl_get_exp(pos_T *ini) /* Delete the old text being completed. */ static void ins_compl_delete(void) { - int i; + int col; - /* - * In insert mode: Delete the typed part. - * In replace mode: Put the old characters back, if any. - */ - i = compl_col + (compl_cont_status & CONT_ADDING ? compl_length : 0); - backspace_until_column(i); - // TODO: is this sufficient for redrawing? Redrawing everything causes - // flicker, thus we can't do that. + // In insert mode: Delete the typed part. + // In replace mode: Put the old characters back, if any. + col = compl_col + (compl_cont_status & CONT_ADDING ? compl_length : 0); + if ((int)curwin->w_cursor.col > col) { + if (stop_arrow() == FAIL) { + return; + } + backspace_until_column(col); + } + + // TODO(vim): is this sufficient for redrawing? Redrawing everything + // causes flicker, thus we can't do that. changed_cline_bef_curs(); // clear v:completed_item set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); } -/* Insert the new text being completed. */ -static void ins_compl_insert(void) +// Insert the new text being completed. +// "in_compl_func" is TRUE when called from complete_check(). +static void ins_compl_insert(int in_compl_func) { ins_bytes(compl_shown_match->cp_str + ins_compl_len()); if (compl_shown_match->cp_flags & ORIGINAL_TEXT) @@ -3989,6 +3993,9 @@ static void ins_compl_insert(void) dict_add_nr_str(dict, "info", 0L, EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO])); set_vim_var_dict(VV_COMPLETED_ITEM, dict); + if (!in_compl_func) { + compl_curr_match = compl_shown_match; + } } /* @@ -4010,9 +4017,10 @@ static void ins_compl_insert(void) static int ins_compl_next ( int allow_get_expansion, - int count, /* repeat completion this many times; should - be at least 1 */ - int insert_match /* Insert the newly selected match */ + int count, // Repeat completion this many times; should + // be at least 1 + int insert_match, // Insert the newly selected match + int in_compl_func // Called from complete_check() ) { int num_matches = -1; @@ -4142,7 +4150,7 @@ ins_compl_next ( compl_used_match = FALSE; } else if (insert_match) { if (!compl_get_longest || compl_used_match) { - ins_compl_insert(); + ins_compl_insert(in_compl_func); } else { ins_bytes(compl_leader + ins_compl_len()); } @@ -4192,14 +4200,14 @@ ins_compl_next ( return num_matches; } -/* - * Call this while finding completions, to check whether the user has hit a key - * that should change the currently displayed completion, or exit completion - * mode. Also, when compl_pending is not zero, show a completion as soon as - * possible. -- webb - * "frequency" specifies out of how many calls we actually check. - */ -void ins_compl_check_keys(int frequency) +// Call this while finding completions, to check whether the user has hit a key +// that should change the currently displayed completion, or exit completion +// mode. Also, when compl_pending is not zero, show a completion as soon as +// possible. -- webb +// "frequency" specifies out of how many calls we actually check. +// "in_compl_func" is TRUE when called from complete_check(), don't set +// compl_curr_match. +void ins_compl_check_keys(int frequency, int in_compl_func) { static int count = 0; @@ -4222,8 +4230,8 @@ void ins_compl_check_keys(int frequency) if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R) { c = safe_vgetc(); /* Eat the character */ compl_shows_dir = ins_compl_key2dir(c); - (void)ins_compl_next(FALSE, ins_compl_key2count(c), - c != K_UP && c != K_DOWN); + (void)ins_compl_next(false, ins_compl_key2count(c), + c != K_UP && c != K_DOWN, in_compl_func); } else { /* Need to get the character to have KeyTyped set. We'll put it * back with vungetc() below. But skip K_IGNORE. */ @@ -4242,7 +4250,7 @@ void ins_compl_check_keys(int frequency) int todo = compl_pending > 0 ? compl_pending : -compl_pending; compl_pending = 0; - (void)ins_compl_next(FALSE, todo, TRUE); + (void)ins_compl_next(false, todo, true, in_compl_func); } } @@ -4321,8 +4329,11 @@ static int ins_complete(int c, bool enable_pum) colnr_T curs_col; /* cursor column */ int n; int save_w_wrow; + int insert_match; compl_direction = ins_compl_key2dir(c); + insert_match = ins_compl_use_match(c); + if (!compl_started) { /* First time we hit ^N or ^P (in a row, I mean) */ @@ -4504,14 +4515,15 @@ static int ins_complete(int c, bool enable_pum) } else if (ctrl_x_mode == CTRL_X_CMDLINE) { compl_pattern = vim_strnsave(line, curs_col); set_cmd_context(&compl_xp, compl_pattern, - (int)STRLEN(compl_pattern), curs_col); + (int)STRLEN(compl_pattern), curs_col, false); if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL - || compl_xp.xp_context == EXPAND_NOTHING) - /* No completion possible, use an empty pattern to get a - * "pattern not found" message. */ + || compl_xp.xp_context == EXPAND_NOTHING) { + // No completion possible, use an empty pattern to get a + // "pattern not found" message. compl_col = curs_col; - else + } else { compl_col = (int)(compl_xp.xp_pattern - compl_pattern); + } compl_length = curs_col - compl_col; } else if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI) { @@ -4655,6 +4667,8 @@ static int ins_complete(int c, bool enable_pum) showmode(); edit_submode_extra = NULL; ui_flush(); + } else if (insert_match && stop_arrow() == FAIL) { + return FAIL; } compl_shown_match = compl_curr_match; @@ -4664,7 +4678,7 @@ static int ins_complete(int c, bool enable_pum) * Find next match (and following matches). */ save_w_wrow = curwin->w_wrow; - n = ins_compl_next(TRUE, ins_compl_key2count(c), ins_compl_use_match(c)); + n = ins_compl_next(true, ins_compl_key2count(c), insert_match, false); /* may undisplay the popup menu */ ins_compl_upd_pum(); @@ -5692,7 +5706,7 @@ comp_textwidth ( textwidth -= 1; textwidth -= curwin->w_p_fdc; - if (curwin->w_buffer->b_signlist != NULL) { + if (signcolumn_on(curwin)) { textwidth -= 1; } @@ -6952,8 +6966,8 @@ static void ins_reg(void) AppendCharToRedobuff(literally); AppendCharToRedobuff(regname); - do_put(regname, NULL, BACKWARD, 1L, - (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND); + do_put(regname, NULL, BACKWARD, 1, + (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND); } else if (insert_reg(regname, literally) == FAIL) { vim_beep(BO_REG); need_redraw = true; // remove the '"' @@ -7701,7 +7715,7 @@ static void ins_mouse(int c) undisplay_dollar(); tpos = curwin->w_cursor; - if (do_mouse(NULL, c, BACKWARD, 1L, 0)) { + if (do_mouse(NULL, c, BACKWARD, 1, 0)) { win_T *new_curwin = curwin; if (curwin != old_curwin && win_valid(old_curwin)) { |