aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/edit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/edit.c')
-rw-r--r--src/nvim/edit.c178
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)) {