diff options
Diffstat (limited to 'src/nvim/normal.c')
-rw-r--r-- | src/nvim/normal.c | 237 |
1 files changed, 139 insertions, 98 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 570368991a..f87de52a82 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1269,7 +1269,8 @@ static void normal_redraw(NormalState *s) xfree(p); } - if (need_fileinfo) { // show file info after redraw + // show fileinfo after redraw + if (need_fileinfo && !shortmess(SHM_FILEINFO)) { fileinfo(false, true, false); need_fileinfo = false; } @@ -1867,7 +1868,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) } else { bangredo = true; // do_bang() will put cmd in redo buffer. } - // fallthrough + FALLTHROUGH; case OP_INDENT: case OP_COLON: @@ -2015,7 +2016,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) default: clearopbeep(oap); } - virtual_op = MAYBE; + virtual_op = kNone; if (!gui_yank) { /* * if 'sol' not set, go back to old column for some commands @@ -2090,7 +2091,7 @@ static void op_colon(oparg_T *oap) */ static void op_function(oparg_T *oap) { - int save_virtual_op = virtual_op; + const TriState save_virtual_op = virtual_op; if (*p_opfunc == NUL) EMSG(_("E774: 'operatorfunc' is empty")); @@ -2113,7 +2114,7 @@ static void op_function(oparg_T *oap) // Reset virtual_op so that 'virtualedit' can be changed in the // function. - virtual_op = MAYBE; + virtual_op = kNone; (void)call_func_retnr(p_opfunc, 1, argv, false); @@ -2858,9 +2859,10 @@ static void find_start_of_word(pos_T *pos) while (pos->col > 0) { col = pos->col - 1; - col -= (*mb_head_off)(line, line + col); - if (get_mouse_class(line + col) != cclass) + col -= utf_head_off(line, line + col); + if (get_mouse_class(line + col) != cclass) { break; + } pos->col = col; } } @@ -2877,8 +2879,8 @@ static void find_end_of_word(pos_T *pos) line = ml_get(pos->lnum); if (*p_sel == 'e' && pos->col > 0) { - --pos->col; - pos->col -= (*mb_head_off)(line, line + pos->col); + pos->col--; + pos->col -= utf_head_off(line, line + pos->col); } cclass = get_mouse_class(line + pos->col); while (line[pos->col] != NUL) { @@ -2990,6 +2992,43 @@ void reset_VIsual(void) } } +// Check for a balloon-eval special item to include when searching for an +// identifier. When "dir" is BACKWARD "ptr[-1]" must be valid! +// Returns true if the character at "*ptr" should be included. +// "dir" is FORWARD or BACKWARD, the direction of searching. +// "*colp" is in/decremented if "ptr[-dir]" should also be included. +// "bnp" points to a counter for square brackets. +static bool find_is_eval_item( + const char_u *const ptr, + int *const colp, + int *const bnp, + const int dir) +{ + // Accept everything inside []. + if ((*ptr == ']' && dir == BACKWARD) || (*ptr == '[' && dir == FORWARD)) { + *bnp += 1; + } + if (*bnp > 0) { + if ((*ptr == '[' && dir == BACKWARD) || (*ptr == ']' && dir == FORWARD)) { + *bnp -= 1; + } + return true; + } + + // skip over "s.var" + if (*ptr == '.') { + return true; + } + + // two-character item: s->var + if (ptr[dir == BACKWARD ? 0 : 1] == '>' + && ptr[dir == BACKWARD ? -1 : 0] == '-') { + *colp += dir; + return true; + } + return false; +} + /* * Find the identifier under or to the right of the cursor. * "find_type" can have one of three values: @@ -3030,6 +3069,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, int this_class = 0; int prev_class; int prevcol; + int bn = 0; // bracket nesting /* * if i == 0: try to find an identifier @@ -3041,71 +3081,62 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, * 1. skip to start of identifier/string */ col = startcol; - if (has_mbyte) { - while (ptr[col] != NUL) { - this_class = mb_get_class(ptr + col); - if (this_class != 0 && (i == 1 || this_class != 1)) - break; - col += (*mb_ptr2len)(ptr + col); + while (ptr[col] != NUL) { + // Stop at a ']' to evaluate "a[x]". + if ((find_type & FIND_EVAL) && ptr[col] == ']') { + break; } - } else - while (ptr[col] != NUL - && (i == 0 ? !vim_iswordc(ptr[col]) : ascii_iswhite(ptr[col])) - ) - ++col; - - - /* - * 2. Back up to start of identifier/string. - */ - if (has_mbyte) { - /* Remember class of character under cursor. */ this_class = mb_get_class(ptr + col); - while (col > 0 && this_class != 0) { - prevcol = col - 1 - (*mb_head_off)(ptr, ptr + col - 1); - prev_class = mb_get_class(ptr + prevcol); - if (this_class != prev_class - && (i == 0 - || prev_class == 0 - || (find_type & FIND_IDENT)) - ) - break; - col = prevcol; + if (this_class != 0 && (i == 1 || this_class != 1)) { + break; } + col += utfc_ptr2len(ptr + col); + } - /* If we don't want just any old string, or we've found an - * identifier, stop searching. */ - if (this_class > 2) - this_class = 2; - if (!(find_type & FIND_STRING) || this_class == 2) - break; - } else { - while (col > 0 - && ((i == 0 - ? vim_iswordc(ptr[col - 1]) - : (!ascii_iswhite(ptr[col - 1]) - && (!(find_type & FIND_IDENT) - || !vim_iswordc(ptr[col - 1])))) - )) - --col; + // When starting on a ']' count it, so that we include the '['. + bn = ptr[col] == ']'; - /* If we don't want just any old string, or we've found an - * identifier, stop searching. */ - if (!(find_type & FIND_STRING) || vim_iswordc(ptr[col])) + // + // 2. Back up to start of identifier/string. + // + // Remember class of character under cursor. + if ((find_type & FIND_EVAL) && ptr[col] == ']') { + this_class = mb_get_class((char_u *)"a"); + } else { + this_class = mb_get_class(ptr + col); + } + while (col > 0 && this_class != 0) { + prevcol = col - 1 - utf_head_off(ptr, ptr + col - 1); + prev_class = mb_get_class(ptr + prevcol); + if (this_class != prev_class + && (i == 0 + || prev_class == 0 + || (find_type & FIND_IDENT)) + && (!(find_type & FIND_EVAL) + || prevcol == 0 + || !find_is_eval_item(ptr + prevcol, &prevcol, &bn, BACKWARD))) { break; + } + col = prevcol; + } + + // If we don't want just any old string, or we've found an + // identifier, stop searching. + if (this_class > 2) { + this_class = 2; + } + if (!(find_type & FIND_STRING) || this_class == 2) { + break; } } - if (ptr[col] == NUL || (i == 0 && ( - has_mbyte ? this_class != 2 : - !vim_iswordc(ptr[col])))) { - /* - * didn't find an identifier or string - */ - if (find_type & FIND_STRING) + if (ptr[col] == NUL || (i == 0 && this_class != 2)) { + // Didn't find an identifier or string. + if (find_type & FIND_STRING) { EMSG(_("E348: No string under cursor")); - else + } else { EMSG(_(e_noident)); + } return 0; } ptr += col; @@ -3114,21 +3145,20 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, /* * 3. Find the end if the identifier/string. */ + bn = 0; + startcol -= col; col = 0; - if (has_mbyte) { - /* Search for point of changing multibyte character class. */ - this_class = mb_get_class(ptr); - while (ptr[col] != NUL - && ((i == 0 ? mb_get_class(ptr + col) == this_class - : mb_get_class(ptr + col) != 0) - )) - col += (*mb_ptr2len)(ptr + col); - } else - while ((i == 0 ? vim_iswordc(ptr[col]) - : (ptr[col] != NUL && !ascii_iswhite(ptr[col]))) - ) { - ++col; - } + // Search for point of changing multibyte character class. + this_class = mb_get_class(ptr); + while (ptr[col] != NUL + && ((i == 0 + ? mb_get_class(ptr + col) == this_class + : mb_get_class(ptr + col) != 0) + || ((find_type & FIND_EVAL) + && col <= (int)startcol + && find_is_eval_item(ptr + col, &col, &bn, FORWARD)))) { + col += utfc_ptr2len(ptr + col); + } assert(col >= 0); return (size_t)col; @@ -3994,8 +4024,12 @@ static void nv_mousescroll(cmdarg_T *cap) row = mouse_row; col = mouse_col; - /* find the window at the pointer coordinates */ - curwin = mouse_find_win(&row, &col); + // find the window at the pointer coordinates + win_T *const wp = mouse_find_win(&row, &col); + if (wp == NULL) { + return; + } + curwin = wp; curbuf = curwin->w_buffer; } @@ -4169,12 +4203,12 @@ dozet: else curwin->w_cursor.lnum = curwin->w_botline; } - /* FALLTHROUGH */ + FALLTHROUGH; case NL: case CAR: case K_KENTER: beginline(BL_WHITE | BL_FIX); - /* FALLTHROUGH */ + FALLTHROUGH; case 't': scroll_cursor_top(0, true); redraw_later(VALID); @@ -4183,7 +4217,7 @@ dozet: /* "z." and "zz": put cursor in middle of screen */ case '.': beginline(BL_WHITE | BL_FIX); - /* FALLTHROUGH */ + FALLTHROUGH; case 'z': scroll_cursor_halfway(true); redraw_later(VALID); @@ -4201,10 +4235,10 @@ dozet: curwin->w_cursor.lnum = 1; else curwin->w_cursor.lnum = curwin->w_topline - 1; - /* FALLTHROUGH */ + FALLTHROUGH; case '-': beginline(BL_WHITE | BL_FIX); - /* FALLTHROUGH */ + FALLTHROUGH; case 'b': scroll_cursor_bot(0, true); redraw_later(VALID); @@ -4214,7 +4248,7 @@ dozet: /* "zH" - scroll screen right half-page */ case 'H': cap->count1 *= curwin->w_width / 2; - /* FALLTHROUGH */ + FALLTHROUGH; /* "zh" - scroll screen to the right */ case 'h': @@ -4230,7 +4264,7 @@ dozet: /* "zL" - scroll screen left half-page */ case 'L': cap->count1 *= curwin->w_width / 2; - /* FALLTHROUGH */ + FALLTHROUGH; /* "zl" - scroll screen to the left */ case 'l': @@ -4447,7 +4481,7 @@ dozet: break; } undo = true; - /*FALLTHROUGH*/ + FALLTHROUGH; case 'g': /* "zg": add good word to word list */ case 'w': /* "zw": add wrong word to word list */ @@ -4738,6 +4772,10 @@ static void nv_ident(cmdarg_T *cap) assert(*kp != NUL); // option.c:do_set() should default to ":help" if empty. bool kp_ex = (*kp == ':'); // 'keywordprg' is an ex command bool kp_help = (STRCMP(kp, ":he") == 0 || STRCMP(kp, ":help") == 0); + if (kp_help && *skipwhite(ptr) == NUL) { + EMSG(_(e_noident)); // found white space only + return; + } size_t buf_size = n * 2 + 30 + STRLEN(kp); char *buf = xmalloc(buf_size); buf[0] = NUL; @@ -5005,7 +5043,10 @@ static void nv_scroll(cmdarg_T *cap) curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; } - cursor_correct(); /* correct for 'so' */ + // Correct for 'so', except when an operator is pending. + if (cap->oap->op_type == OP_NOP) { + cursor_correct(); + } beginline(BL_SOL | BL_FIX); } @@ -6257,7 +6298,7 @@ static void nv_gomark(cmdarg_T *cap) pos_T *pos; int c; pos_T old_cursor = curwin->w_cursor; - int old_KeyTyped = KeyTyped; /* getting file may reset it */ + const bool old_KeyTyped = KeyTyped; // getting file may reset it if (cap->cmdchar == 'g') c = cap->extra_char; @@ -6294,7 +6335,7 @@ static void nv_pcmark(cmdarg_T *cap) { pos_T *pos; linenr_T lnum = curwin->w_cursor.lnum; - int old_KeyTyped = KeyTyped; /* getting file may reset it */ + const bool old_KeyTyped = KeyTyped; // getting file may reset it if (!checkclearopq(cap->oap)) { if (cap->cmdchar == 'g') @@ -6459,8 +6500,8 @@ void may_start_select(int c) */ static void n_start_visual_mode(int c) { - /* Check for redraw before changing the state. */ - conceal_check_cursur_line(); + // Check for redraw before changing the state. + conceal_check_cursor_line(); VIsual_mode = c; VIsual_active = true; @@ -6477,8 +6518,8 @@ static void n_start_visual_mode(int c) foldAdjustVisual(); setmouse(); - /* Check for redraw after changing the state. */ - conceal_check_cursur_line(); + // Check for redraw after changing the state. + conceal_check_cursor_line(); if (p_smd && msg_silent == 0) redraw_cmdline = true; /* show visual mode later */ @@ -6623,7 +6664,7 @@ static void nv_g_cmd(cmdarg_T *cap) */ case K_BS: cap->nchar = Ctrl_H; - /* FALLTHROUGH */ + FALLTHROUGH; case 'h': case 'H': case Ctrl_H: @@ -6689,7 +6730,7 @@ static void nv_g_cmd(cmdarg_T *cap) */ case '^': flag = true; - /* FALLTHROUGH */ + FALLTHROUGH; case '0': case 'm': @@ -6867,7 +6908,7 @@ static void nv_g_cmd(cmdarg_T *cap) /* "g'm" and "g`m": jump to mark without setting pcmark */ case '\'': cap->arg = true; - /*FALLTHROUGH*/ + FALLTHROUGH; case '`': nv_gomark(cap); break; @@ -6925,7 +6966,7 @@ static void nv_g_cmd(cmdarg_T *cap) case 'q': case 'w': oap->cursor_start = curwin->w_cursor; - /*FALLTHROUGH*/ + FALLTHROUGH; case '~': case 'u': case 'U': |