diff options
Diffstat (limited to 'src/nvim/normal.c')
-rw-r--r-- | src/nvim/normal.c | 98 |
1 files changed, 57 insertions, 41 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 382c4943ff..b17b4c584e 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -36,7 +36,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/mouse.h" @@ -460,7 +459,7 @@ void normal_enter(bool cmdwin, bool noexmode) normal_state_init(&state); state.cmdwin = cmdwin; state.noexmode = noexmode; - state.toplevel = !cmdwin && !noexmode; + state.toplevel = (!cmdwin || cmdwin_result == 0) && !noexmode; state_enter(&state.state); } @@ -974,7 +973,7 @@ static int normal_execute(VimState *state, int key) s->old_col = curwin->w_curswant; s->c = key; - LANGMAP_ADJUST(s->c, true); + LANGMAP_ADJUST(s->c, get_real_state() != SELECTMODE); // If a mapping was started in Visual or Select mode, remember the length // of the mapping. This is used below to not return to Insert mode for as @@ -1131,6 +1130,7 @@ static int normal_execute(VimState *state, int key) start_selection(); unshift_special(&s->ca); s->idx = find_command(s->ca.cmdchar); + assert(s->idx >= 0); } else if ((nv_cmds[s->idx].cmd_flags & NV_SSS) && (mod_mask & MOD_MASK_SHIFT)) { start_selection(); @@ -1361,7 +1361,7 @@ static int normal_check(VimState *state) // Dict internally somewhere. // "may_garbage_collect" is reset in vgetc() which is invoked through // do_exmode() and normal_cmd(). - may_garbage_collect = s->toplevel; + may_garbage_collect = !s->cmdwin && !s->noexmode; // Update w_curswant if w_set_curswant has been set. // Postponed until here to avoid computing w_virtcol too often. @@ -1518,10 +1518,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) coladvance(curwin->w_curswant); } cap->count0 = redo_VIsual_count; - if (redo_VIsual_count != 0) - cap->count1 = redo_VIsual_count; - else - cap->count1 = 1; + cap->count1 = (cap->count0 == 0 ? 1 : cap->count0); } else if (VIsual_active) { if (!gui_yank) { /* Save the current VIsual area for '< and '> marks, and "gv" */ @@ -1795,10 +1792,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) if (oap->line_count < 2) oap->line_count = 2; if (curwin->w_cursor.lnum + oap->line_count - 1 > - curbuf->b_ml.ml_line_count) + curbuf->b_ml.ml_line_count) { beep_flush(); - else { - do_join(oap->line_count, oap->op_type == OP_JOIN, true, true, true); + } else { + do_join((size_t)oap->line_count, oap->op_type == OP_JOIN, + true, true, true); auto_format(false, true); } break; @@ -2109,6 +2107,20 @@ static void op_function(oparg_T *oap) } } +// Move the current tab to tab in same column as mouse or to end of the +// tabline if there is no tab there. +static void move_tab_to_mouse(void) +{ + int tabnr = tab_page_click_defs[mouse_col].tabnr; + if (tabnr <= 0) { + tabpage_move(9999); + } else if (tabnr < tabpage_index(curtab)) { + tabpage_move(tabnr - 1); + } else { + tabpage_move(tabnr); + } +} + /* * Do the appropriate action for the current mouse click in the current mode. * Not used for Command-line mode. @@ -2345,12 +2357,7 @@ do_mouse ( if (mouse_row == 0 && firstwin->w_winrow > 0) { if (is_drag) { if (in_tab_line) { - if (tab_page_click_defs[mouse_col].type == kStlClickTabClose) { - tabpage_move(9999); - } else { - int tabnr = tab_page_click_defs[mouse_col].tabnr; - tabpage_move(tabnr < tabpage_index(curtab) ? tabnr - 1 : tabnr); - } + move_tab_to_mouse(); } return false; } @@ -2457,7 +2464,7 @@ do_mouse ( (int) strlen(tab_page_click_defs[mouse_col].func), &rettv, ARRAY_SIZE(argv), argv, curwin->w_cursor.lnum, curwin->w_cursor.lnum, - &doesrange, true, NULL); + &doesrange, true, NULL, NULL); clear_tv(&rettv); break; } @@ -2465,10 +2472,7 @@ do_mouse ( } return true; } else if (is_drag && in_tab_line) { - tabpage_move(tab_page_click_defs[mouse_col].type == kStlClickTabClose - ? 9999 - : tab_page_click_defs[mouse_col].tabnr - 1); - in_tab_line = false; + move_tab_to_mouse(); return false; } @@ -3640,10 +3644,11 @@ nv_gd ( size_t len; char_u *ptr; if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0 - || !find_decl(ptr, len, nchar == 'd', thisblock, 0)) + || !find_decl(ptr, len, nchar == 'd', thisblock, SEARCH_START)) { clearopbeep(oap); - else if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP) + } else if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP) { foldOpenCursor(); + } } /* @@ -3659,7 +3664,7 @@ find_decl ( size_t len, bool locally, bool thisblock, - int searchflags /* flags passed to searchit() */ + int flags_arg // flags passed to searchit() ) { char_u *pat; @@ -3671,6 +3676,7 @@ find_decl ( bool save_p_scs; bool retval = true; bool incll; + int searchflags = flags_arg; pat = xmalloc(len + 7); @@ -3744,10 +3750,12 @@ find_decl ( break; } - /* For finding a local variable and the match is before the "{" search - * to find a later match. For K&R style function declarations this - * skips the function header without types. */ + // For finding a local variable and the match is before the "{" search + // to find a later match. For K&R style function declarations this + // skips the function header without types. Remove SEARCH_START from + // flags to avoid getting stuck at one position. found_pos = curwin->w_cursor; + searchflags &= ~SEARCH_START; } if (t == false) { @@ -5918,6 +5926,8 @@ static void nv_replace(cmdarg_T *cap) curwin->w_set_curswant = true; set_last_insert(cap->nchar); } + + foldUpdateAfterInsert(); } /* @@ -7666,7 +7676,7 @@ static void nv_join(cmdarg_T *cap) prep_redo(cap->oap->regname, cap->count0, NUL, cap->cmdchar, NUL, NUL, cap->nchar); - do_join(cap->count0, cap->nchar == NUL, true, true, true); + do_join((size_t)cap->count0, cap->nchar == NUL, true, true, true); } } @@ -7715,16 +7725,22 @@ static void nv_put(cmdarg_T *cap) savereg = copy_register(regname); } - /* Now delete the selected text. */ - cap->cmdchar = 'd'; - cap->nchar = NUL; - cap->oap->regname = NUL; - nv_operator(cap); - do_pending_operator(cap, 0, false); - empty = (curbuf->b_ml.ml_flags & ML_EMPTY); + // To place the cursor correctly after a blockwise put, and to leave the + // text in the correct position when putting over a selection with + // 'virtualedit' and past the end of the line, we use the 'c' operator in + // do_put(), which requires the visual selection to still be active. + if (!VIsual_active || VIsual_mode == 'V' || regname != '.') { + // Now delete the selected text. + cap->cmdchar = 'd'; + cap->nchar = NUL; + cap->oap->regname = NUL; + nv_operator(cap); + do_pending_operator(cap, 0, false); + empty = (curbuf->b_ml.ml_flags & ML_EMPTY); - /* delete PUT_LINE_BACKWARD; */ - cap->oap->regname = regname; + // delete PUT_LINE_BACKWARD; + cap->oap->regname = regname; + } /* When deleted a linewise Visual area, put the register as * lines to avoid it joined with the next line. When deletion was @@ -7871,15 +7887,15 @@ static void nv_event(cmdarg_T *cap) { // Garbage collection should have been executed before blocking for events in // the `os_inchar` in `state_enter`, but we also disable it here in case the - // `os_inchar` branch was not executed(!queue_empty(loop.events), which could - // have `may_garbage_collect` set to true in `normal_check`). + // `os_inchar` branch was not executed (!multiqueue_empty(loop.events), which + // could have `may_garbage_collect` set to true in `normal_check`). // // That is because here we may run code that calls `os_inchar` // later(`f_confirm` or `get_keystroke` for example), but in these cases it is // not safe to perform garbage collection because there could be unreferenced // lists or dicts being used. may_garbage_collect = false; - queue_process_events(loop.events); + multiqueue_process_events(main_loop.events); cap->retval |= CA_COMMAND_BUSY; // don't call edit() now } |