diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/buffer.c | 9 | ||||
| -rw-r--r-- | src/nvim/edit.c | 2 | ||||
| -rw-r--r-- | src/nvim/indent.c | 3 | ||||
| -rw-r--r-- | src/nvim/mark.c | 2 | ||||
| -rw-r--r-- | src/nvim/mark_defs.h | 3 | ||||
| -rw-r--r-- | src/nvim/normal.c | 25 | ||||
| -rw-r--r-- | src/nvim/ops.c | 92 | ||||
| -rw-r--r-- | src/nvim/spell.c | 5 | ||||
| -rw-r--r-- | src/nvim/testdir/setup.vim | 4 | ||||
| -rw-r--r-- | src/nvim/testdir/test_autocmd.vim | 7 | ||||
| -rw-r--r-- | src/nvim/testdir/test_cindent.vim | 11 | ||||
| -rw-r--r-- | src/nvim/testdir/test_cmdline.vim | 10 | ||||
| -rw-r--r-- | src/nvim/testdir/test_edit.vim | 4 | ||||
| -rw-r--r-- | src/nvim/testdir/test_indent.vim | 155 | ||||
| -rw-r--r-- | src/nvim/testdir/test_normal.vim | 241 | ||||
| -rw-r--r-- | src/nvim/testdir/test_spell.vim | 12 | ||||
| -rw-r--r-- | src/nvim/testdir/test_substitute.vim | 2 | ||||
| -rw-r--r-- | src/nvim/testdir/test_timers.vim | 2 | ||||
| -rw-r--r-- | src/nvim/testdir/test_virtualedit.vim | 3 | ||||
| -rw-r--r-- | src/nvim/testdir/test_visual.vim | 77 | ||||
| -rw-r--r-- | src/nvim/tui/tui.c | 25 | 
21 files changed, 604 insertions, 90 deletions
| diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 7bdb905dfa..411705cfa3 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -89,6 +89,7 @@  static char *msg_loclist = N_("[Location List]");  static char *msg_qflist = N_("[Quickfix List]");  static char *e_auabort = N_("E855: Autocommands caused command to abort"); +static char *e_buflocked = N_("E937: Attempt to delete a buffer that is in use");  // Number of times free_buffer() was called.  static int buf_free_count = 0; @@ -438,7 +439,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i    // Disallow deleting the buffer when it is locked (already being closed or    // halfway a command that relies on it). Unloading is allowed.    if (buf->b_locked > 0 && (del_buf || wipe_buf)) { -    emsg(_("E937: Attempt to delete a buffer that is in use")); +    emsg(_(e_buflocked));      return false;    } @@ -529,7 +530,9 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i    }    if (buf->terminal) { +    buf->b_locked++;      terminal_close(&buf->terminal, -1); +    buf->b_locked--;    }    // Always remove the buffer when there is no file name. @@ -1182,6 +1185,10 @@ int do_buffer(int action, int start, int dir, int count, int forceit)    if (unload) {      int forward;      bufref_T bufref; +    if (buf->b_locked) { +      emsg(_(e_buflocked)); +      return FAIL; +    }      set_bufref(&bufref, buf);      // When unloading or deleting a buffer that's already unloaded and diff --git a/src/nvim/edit.c b/src/nvim/edit.c index d21583e951..e3c80505c8 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -7330,7 +7330,7 @@ static void replace_do_bs(int limit_col)  }  /// Check that C-indenting is on. -static bool cindent_on(void) +bool cindent_on(void)    FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT  {    return !p_paste && (curbuf->b_p_cin || *curbuf->b_p_inde != NUL); diff --git a/src/nvim/indent.c b/src/nvim/indent.c index 9d60cf9dfe..271498d41a 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -656,6 +656,9 @@ int get_lisp_indent(void)                }              }            } +          if (*that == NUL) { +            break; +          }          }          if ((*that == '(') || (*that == '[')) {            parencount++; diff --git a/src/nvim/mark.c b/src/nvim/mark.c index 2402ea3035..0bf5875269 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -607,6 +607,8 @@ void mark_view_restore(fmark_T *fm)  {    if (fm != NULL && fm->view.topline_offset >= 0) {      linenr_T topline = fm->mark.lnum - fm->view.topline_offset; +    // If the mark does not have a view, topline_offset is MAXLNUM, +    // and this check can prevent restoring mark view in that case.      if (topline >= 1) {        set_topline(curwin, topline);      } diff --git a/src/nvim/mark_defs.h b/src/nvim/mark_defs.h index 16d85a6e51..a78056c5f9 100644 --- a/src/nvim/mark_defs.h +++ b/src/nvim/mark_defs.h @@ -64,9 +64,10 @@ typedef enum {  /// Represents view in which the mark was created  typedef struct fmarkv {    linenr_T topline_offset;  ///< Amount of lines from the mark lnum to the top of the window. +                            ///< Use MAXLNUM to indicate that the mark does not have a view.  } fmarkv_T; -#define INIT_FMARKV { 0 } +#define INIT_FMARKV { MAXLNUM }  /// Structure defining single local mark  typedef struct filemark { diff --git a/src/nvim/normal.c b/src/nvim/normal.c index c7f7b569e7..ed624c0c9f 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -2494,21 +2494,30 @@ static void prep_redo_cmd(cmdarg_T *cap)  /// Note that only the last argument can be a multi-byte char.  void prep_redo(int regname, long num, int cmd1, int cmd2, int cmd3, int cmd4, int cmd5)  { +  prep_redo_num2(regname, num, cmd1, cmd2, 0L, cmd3, cmd4, cmd5); +} + +/// Prepare for redo of any command with extra count after "cmd2". +void prep_redo_num2(int regname, long num1, int cmd1, int cmd2, long num2, int cmd3, int cmd4, +                    int cmd5) +{    ResetRedobuff();    if (regname != 0) {   // yank from specified buffer      AppendCharToRedobuff('"');      AppendCharToRedobuff(regname);    } -  if (num) { -    AppendNumberToRedobuff(num); +  if (num1 != 0) { +    AppendNumberToRedobuff(num1);    } -    if (cmd1 != NUL) {      AppendCharToRedobuff(cmd1);    }    if (cmd2 != NUL) {      AppendCharToRedobuff(cmd2);    } +  if (num2 != 0) { +    AppendNumberToRedobuff(num2); +  }    if (cmd3 != NUL) {      AppendCharToRedobuff(cmd3);    } @@ -6157,6 +6166,16 @@ static void nv_g_cmd(cmdarg_T *cap)        i = curwin->w_leftcol + curwin->w_width_inner - col_off - 1;        coladvance((colnr_T)i); +      // if the character doesn't fit move one back +      if (curwin->w_cursor.col > 0 && utf_ptr2cells((const char *)get_cursor_pos_ptr()) > 1) { +        colnr_T vcol; + +        getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &vcol); +        if (vcol >= curwin->w_leftcol + curwin->w_width - col_off) { +          curwin->w_cursor.col--; +        } +      } +        // Make sure we stick in this column.        validate_virtcol();        curwin->w_curswant = curwin->w_virtcol; diff --git a/src/nvim/ops.c b/src/nvim/ops.c index a8198cfce9..2f29e94ff1 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -4421,6 +4421,7 @@ void format_lines(linenr_T line_count, int avoid_fex)    int smd_save;    long count;    bool need_set_indent = true;      // set indent of next paragraph +  linenr_T first_line = curwin->w_cursor.lnum;    bool force_format = false;    const int old_State = State; @@ -4547,9 +4548,24 @@ void format_lines(linenr_T line_count, int avoid_fex)         */        if (is_end_par || force_format) {          if (need_set_indent) { -          // replace indent in first line with minimal number of -          // tabs and spaces, according to current options -          (void)set_indent(get_indent(), SIN_CHANGED); +          int indent = 0;  // amount of indent needed + +          // Replace indent in first line of a paragraph with minimal +          // number of tabs and spaces, according to current options. +          // For the very first formatted line keep the current +          // indent. +          if (curwin->w_cursor.lnum == first_line) { +            indent = get_indent(); +          } else if (curbuf->b_p_lisp) { +            indent = get_lisp_indent(); +          } else { +            if (cindent_on()) { +              indent = *curbuf->b_p_inde != NUL ? get_expr_indent() : get_c_indent(); +            } else { +              indent = get_indent(); +            } +          } +          (void)set_indent(indent, SIN_CHANGED);          }          // put cursor on last non-space @@ -6218,6 +6234,15 @@ static void get_op_vcol(oparg_T *oap, colnr_T redo_VIsual_vcol, bool initial)    oap->start = curwin->w_cursor;  } +/// Information for redoing the previous Visual selection. +typedef struct { +  int rv_mode;             ///< 'v', 'V', or Ctrl-V +  linenr_T rv_line_count;  ///< number of lines +  colnr_T rv_vcol;         ///< number of cols or end column +  long rv_count;           ///< count for Visual operator +  int rv_arg;              ///< extra argument +} redo_VIsual_T; +  /// Handle an operator after Visual mode or when the movement is finished.  /// "gui_yank" is true when yanking text for the clipboard.  void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) @@ -6229,11 +6254,8 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)    int lbr_saved = curwin->w_p_lbr;    // The visual area is remembered for redo -  static int redo_VIsual_mode = NUL;        // 'v', 'V', or Ctrl-V -  static linenr_T redo_VIsual_line_count;   // number of lines -  static colnr_T redo_VIsual_vcol;          // number of cols or end column -  static long redo_VIsual_count;            // count for Visual operator -  static int redo_VIsual_arg;               // extra argument +  static redo_VIsual_T redo_VIsual = { NUL, 0, 0, 0, 0 }; +    bool include_line_break = false;    old_cursor = curwin->w_cursor; @@ -6316,28 +6338,27 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)      if (redo_VIsual_busy) {        // Redo of an operation on a Visual area. Use the same size from -      // redo_VIsual_line_count and redo_VIsual_vcol. +      // redo_VIsual.rv_line_count and redo_VIsual.rv_vcol.        oap->start = curwin->w_cursor; -      curwin->w_cursor.lnum += redo_VIsual_line_count - 1; +      curwin->w_cursor.lnum += redo_VIsual.rv_line_count - 1;        if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {          curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;        } -      VIsual_mode = redo_VIsual_mode; -      if (redo_VIsual_vcol == MAXCOL || VIsual_mode == 'v') { +      VIsual_mode = redo_VIsual.rv_mode; +      if (redo_VIsual.rv_vcol == MAXCOL || VIsual_mode == 'v') {          if (VIsual_mode == 'v') { -          if (redo_VIsual_line_count <= 1) { +          if (redo_VIsual.rv_line_count <= 1) {              validate_virtcol(); -            curwin->w_curswant = -              curwin->w_virtcol + redo_VIsual_vcol - 1; +            curwin->w_curswant = curwin->w_virtcol + redo_VIsual.rv_vcol - 1;            } else { -            curwin->w_curswant = redo_VIsual_vcol; +            curwin->w_curswant = redo_VIsual.rv_vcol;            }          } else {            curwin->w_curswant = MAXCOL;          }          coladvance(curwin->w_curswant);        } -      cap->count0 = redo_VIsual_count; +      cap->count0 = redo_VIsual.rv_count;        cap->count1 = (cap->count0 == 0 ? 1 : cap->count0);      } else if (VIsual_active) {        if (!gui_yank) { @@ -6424,7 +6445,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)      virtual_op = virtual_active();      if (VIsual_active || redo_VIsual_busy) { -      get_op_vcol(oap, redo_VIsual_vcol, true); +      get_op_vcol(oap, redo_VIsual.rv_vcol, true);        if (!redo_VIsual_busy && !gui_yank) {          // Prepare to reselect and redo Visual: this is based on the @@ -6469,6 +6490,8 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)                      get_op_char(oap->op_type), get_extra_op_char(oap->op_type),                      oap->motion_force, cap->cmdchar, cap->nchar);          } else if (cap->cmdchar != ':' && cap->cmdchar != K_COMMAND) { +          int opchar = get_op_char(oap->op_type); +          int extra_opchar = get_extra_op_char(oap->op_type);            int nchar = oap->op_type == OP_REPLACE ? cap->nchar : NUL;            // reverse what nv_replace() did @@ -6477,15 +6500,20 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)            } else if (nchar == REPLACE_NL_NCHAR) {              nchar = NL;            } -          prep_redo(oap->regname, 0L, NUL, 'v', get_op_char(oap->op_type), -                    get_extra_op_char(oap->op_type), nchar); + +          if (opchar == 'g' && extra_opchar == '@') { +            // also repeat the count for 'operatorfunc' +            prep_redo_num2(oap->regname, 0L, NUL, 'v', cap->count0, opchar, extra_opchar, nchar); +          } else { +            prep_redo(oap->regname, 0L, NUL, 'v', opchar, extra_opchar, nchar); +          }          }          if (!redo_VIsual_busy) { -          redo_VIsual_mode = resel_VIsual_mode; -          redo_VIsual_vcol = resel_VIsual_vcol; -          redo_VIsual_line_count = resel_VIsual_line_count; -          redo_VIsual_count = cap->count0; -          redo_VIsual_arg = cap->arg; +          redo_VIsual.rv_mode = resel_VIsual_mode; +          redo_VIsual.rv_vcol = resel_VIsual_vcol; +          redo_VIsual.rv_line_count = resel_VIsual_line_count; +          redo_VIsual.rv_count = cap->count0; +          redo_VIsual.rv_arg = cap->arg;          }        } @@ -6735,12 +6763,20 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)        op_format(oap, true);             // use internal function        break; -    case OP_FUNCTION: +    case OP_FUNCTION: { +      redo_VIsual_T save_redo_VIsual = redo_VIsual; +        // Restore linebreak, so that when the user edits it looks as        // before.        curwin->w_p_lbr = lbr_saved; -      op_function(oap);                 // call 'operatorfunc' +      // call 'operatorfunc' +      op_function(oap); + +      // Restore the info for redoing Visual mode, the function may +      // invoke another operator and unintentionally change it. +      redo_VIsual = save_redo_VIsual;        break; +    }      case OP_INSERT:      case OP_APPEND: @@ -6821,7 +6857,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)        } else {          VIsual_active = true;          curwin->w_p_lbr = lbr_saved; -        op_addsub(oap, (linenr_T)cap->count1, redo_VIsual_arg); +        op_addsub(oap, (linenr_T)cap->count1, redo_VIsual.rv_arg);          VIsual_active = false;        }        check_cursor_col(); diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 0fedd27037..2aadc2258e 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -7023,8 +7023,9 @@ void spell_dump_compl(char_u *pat, int ic, Direction *dir, int dumpflags_arg)            n = arridx[depth] + curi[depth];            ++curi[depth];            c = byts[n]; -          if (c == 0) { -            // End of word, deal with the word. +          if (c == 0 || depth >= MAXWLEN - 1) { +            // End of word or reached maximum length, deal with the +            // word.              // Don't use keep-case words in the fold-case tree,              // they will appear in the keep-case tree.              // Only use the word when the region matches. diff --git a/src/nvim/testdir/setup.vim b/src/nvim/testdir/setup.vim index f1092af358..dfcde37f62 100644 --- a/src/nvim/testdir/setup.vim +++ b/src/nvim/testdir/setup.vim @@ -30,6 +30,10 @@ set switchbuf=  mapclear  mapclear! +" Make "Q" switch to Ex mode. +" This does not work for all tests. +nnoremap Q gQ +  " Prevent Nvim log from writing to stderr.  let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log' diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 660801d575..fcef57e47a 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -169,7 +169,9 @@ func Test_autocmd_bufunload_avoiding_SEGV_01()      exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'    augroup END -  call assert_fails('edit bb.txt', 'E937:') +  " Todo: check for E937 generated first +  " call assert_fails('edit bb.txt', 'E937:') +  call assert_fails('edit bb.txt', 'E517:')    autocmd! test_autocmd_bufunload    augroup! test_autocmd_bufunload @@ -540,7 +542,7 @@ func Test_three_windows()    e Xtestje2    sp Xtestje1    call assert_fails('e', 'E937:') -  call assert_equal('Xtestje2', expand('%')) +  call assert_equal('Xtestje1', expand('%'))    " Test changing buffers in a BufWipeout autocommand.  If this goes wrong    " there are ml_line errors and/or a Crash. @@ -563,7 +565,6 @@ func Test_three_windows()    au!    enew -  bwipe! Xtestje1    call delete('Xtestje1')    call delete('Xtestje2')    call delete('Xtestje3') diff --git a/src/nvim/testdir/test_cindent.vim b/src/nvim/testdir/test_cindent.vim index 7ba8ef3397..ccc8168c09 100644 --- a/src/nvim/testdir/test_cindent.vim +++ b/src/nvim/testdir/test_cindent.vim @@ -5306,11 +5306,20 @@ func Test_cindent_case()    set cindent    norm! f:a:    call assert_equal('case x:: // x', getline(1)) -    set cindent&    bwipe!  endfunc +" Test for changing multiple lines (using c) with cindent +func Test_cindent_change_multline() +  new +  setlocal cindent +  call setline(1, ['if (a)', '{', '    i = 1;', '}']) +  normal! jc3jm = 2; +  call assert_equal("\tm = 2;", getline(2)) +  close! +endfunc +  " This was reading past the end of the line  func Test_cindent_check_funcdecl()    new diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index aedcad5296..8ee894c35f 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -1226,6 +1226,16 @@ func Test_cmdline_expand_home()    call delete('Xdir', 'rf')  endfunc +" Test for normal mode commands not supported in the cmd window +func Test_cmdwin_blocked_commands() +  call assert_fails('call feedkeys("q:\<C-T>\<CR>", "xt")', 'E11:') +  call assert_fails('call feedkeys("q:\<C-]>\<CR>", "xt")', 'E11:') +  call assert_fails('call feedkeys("q:\<C-^>\<CR>", "xt")', 'E11:') +  call assert_fails('call feedkeys("q:Q\<CR>", "xt")', 'E11:') +  call assert_fails('call feedkeys("q:Z\<CR>", "xt")', 'E11:') +  call assert_fails('call feedkeys("q:\<F1>\<CR>", "xt")', 'E11:') +endfunc +  " test that ";" works to find a match at the start of the first line  func Test_zero_line_search()    new diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim index 275c8f7a15..c14afbe5b9 100644 --- a/src/nvim/testdir/test_edit.vim +++ b/src/nvim/testdir/test_edit.vim @@ -270,6 +270,10 @@ func Test_edit_10()    call cursor(1, 4)    call feedkeys("A\<s-home>start\<esc>", 'txin')    call assert_equal(['startdef', 'ghi'], getline(1, '$')) +  " start select mode again with gv +  set selectmode=cmd +  call feedkeys('gvabc', 'xt') +  call assert_equal('abctdef', getline(1))    set selectmode= keymodel=    bw!  endfunc diff --git a/src/nvim/testdir/test_indent.vim b/src/nvim/testdir/test_indent.vim index 516b3fbdd1..3b5b643177 100644 --- a/src/nvim/testdir/test_indent.vim +++ b/src/nvim/testdir/test_indent.vim @@ -121,4 +121,159 @@ func Test_copyindent()    close!  endfunc +" Test for changing multiple lines with lisp indent +func Test_lisp_indent_change_multiline() +  new +  setlocal lisp autoindent +  call setline(1, ['(if a', '  (if b', '    (return 5)))']) +  normal! jc2j(return 4)) +  call assert_equal('  (return 4))', getline(2)) +  close! +endfunc + +func Test_lisp_indent() +  new +  setlocal lisp autoindent +  call setline(1, ['(if a', '  ;; comment', '  \ abc', '', '  " str1\', '  " st\b', '  (return 5)']) +  normal! jo;; comment +  normal! jo\ abc +  normal! jo;; ret +  normal! jostr1" +  normal! jostr2" +  call assert_equal(['  ;; comment', '  ;; comment', '  \ abc', '  \ abc', '', '  ;; ret', '  " str1\', '  str1"', '  " st\b', '  str2"'], getline(2, 11)) +  close! +endfunc + +func Test_lisp_indent_quoted() +  " This was going past the end of the line +  new +  setlocal lisp autoindent +  call setline(1, ['"[', '=']) +  normal Gvk= + +  bwipe! +endfunc + +" Test for setting the 'indentexpr' from a modeline +func Test_modeline_indent_expr() +  let modeline = &modeline +  set modeline +  func GetIndent() +    return line('.') * 2 +  endfunc +  call writefile(['# vim: indentexpr=GetIndent()'], 'Xfile.txt') +  set modelineexpr +  new Xfile.txt +  call assert_equal('GetIndent()', &indentexpr) +  exe "normal Oa\nb\n" +  call assert_equal(['  a', '    b'], getline(1, 2)) + +  set modelineexpr& +  delfunc GetIndent +  let &modeline = modeline +  close! +  call delete('Xfile.txt') +endfunc + +func Test_indent_func_with_gq() +   +  function GetTeXIndent() +    " Sample indent expression for TeX files +    let lnum = prevnonblank(v:lnum - 1) +    " At the start of the file use zero indent. +    if lnum == 0 +      return 0 +    endif +    let line = getline(lnum) +    let ind = indent(lnum) +    " Add a 'shiftwidth' after beginning of environments. +    if line =~ '\\begin{center}'  +      let ind = ind + shiftwidth() +    endif +    return ind +  endfunction + +  new +  setl et sw=2 sts=2 ts=2 tw=50 indentexpr=GetTeXIndent() +  put =[  '\documentclass{article}', '', '\begin{document}', '', +        \ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce ut enim non', +        \ 'libero efficitur aliquet. Maecenas metus justo, facilisis convallis blandit', +        \ 'non, semper eu urna. Suspendisse diam diam, iaculis faucibus lorem eu,', +        \ 'fringilla condimentum lectus. Quisque euismod diam at convallis vulputate.', +        \ 'Pellentesque laoreet tortor sit amet mauris euismod ornare. Sed varius', +        \ 'bibendum orci vel vehicula. Pellentesque tempor, ipsum et auctor accumsan,', +        \ 'metus lectus ultrices odio, sed elementum mi ante at arcu.', '', '\begin{center}', '', +        \ 'Proin nec risus consequat nunc dapibus consectetur. Mauris lacinia est a augue', +        \ 'tristique accumsan. Morbi pretium, felis molestie eleifend condimentum, arcu', +        \ 'ipsum congue nisl, quis euismod purus libero in ante.', '', +        \ 'Donec id semper purus.', +        \ 'Suspendisse eget aliquam nunc. Maecenas fringilla mauris vitae maximus', +        \ 'condimentum. Cras a quam in mi dictum eleifend at a lorem. Sed convallis', +        \ 'ante a commodo facilisis. Nam suscipit vulputate odio, vel dapibus nisl', +        \ 'dignissim facilisis. Vestibulum ante ipsum primis in faucibus orci luctus et', +        \ 'ultrices posuere cubilia curae;', '', ''] +  1d_ +  call cursor(5, 1) +  ka +  call cursor(14, 1) +  kb +  norm! 'agqap +  norm! 'bgqG +  let expected = [ '\documentclass{article}', '', '\begin{document}', '', +        \ 'Lorem ipsum dolor sit amet, consectetur adipiscing', +        \ 'elit. Fusce ut enim non libero efficitur aliquet.', +        \ 'Maecenas metus justo, facilisis convallis blandit', +        \ 'non, semper eu urna. Suspendisse diam diam,', +        \ 'iaculis faucibus lorem eu, fringilla condimentum', +        \ 'lectus. Quisque euismod diam at convallis', +        \ 'vulputate.  Pellentesque laoreet tortor sit amet', +        \ 'mauris euismod ornare. Sed varius bibendum orci', +        \ 'vel vehicula. Pellentesque tempor, ipsum et auctor', +        \ 'accumsan, metus lectus ultrices odio, sed', +        \ 'elementum mi ante at arcu.', '', '\begin{center}', '', +        \ '  Proin nec risus consequat nunc dapibus', +        \ '  consectetur. Mauris lacinia est a augue', +        \ '  tristique accumsan. Morbi pretium, felis', +        \ '  molestie eleifend condimentum, arcu ipsum congue', +        \ '  nisl, quis euismod purus libero in ante.', +        \ '', +        \ '  Donec id semper purus.  Suspendisse eget aliquam', +        \ '  nunc. Maecenas fringilla mauris vitae maximus', +        \ '  condimentum. Cras a quam in mi dictum eleifend', +        \ '  at a lorem. Sed convallis ante a commodo', +        \ '  facilisis. Nam suscipit vulputate odio, vel', +        \ '  dapibus nisl dignissim facilisis. Vestibulum', +        \ '  ante ipsum primis in faucibus orci luctus et', +        \ '  ultrices posuere cubilia curae;', '', ''] +  call assert_equal(expected, getline(1, '$')) + +  bwipe! +  delmark ab +  delfunction GetTeXIndent  +endfu + +func Test_formatting_keeps_first_line_indent() +  let lines =<< trim END +      foo() +      { +          int x;         // manually positioned +                         // more text that will be formatted +                         // but not reindented +  END +  new +  call setline(1, lines) +  setlocal sw=4 cindent tw=45 et +  normal! 4Ggqj +  let expected =<< trim END +      foo() +      { +          int x;         // manually positioned +                         // more text that will be +                         // formatted but not +                         // reindented +  END +  call assert_equal(expected, getline(1, '$')) +  bwipe! +endfunc +  " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index b44d65c2a4..82ba2cfd48 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -115,8 +115,8 @@ func Test_normal01_keymodel()    bw!  endfunc +" Test for select mode  func Test_normal02_selectmode() -  " some basic select mode tests    call Setup_NewWindow()    50    norm! gHy @@ -345,7 +345,7 @@ func Test_normal08_fold()    bw!  endfunc -func Test_normal09_operatorfunc() +func Test_normal09a_operatorfunc()    " Test operatorfunc    call Setup_NewWindow()    " Add some spaces for counting @@ -375,7 +375,7 @@ func Test_normal09_operatorfunc()    bw!  endfunc -func Test_normal09a_operatorfunc() +func Test_normal09b_operatorfunc()    " Test operatorfunc    call Setup_NewWindow()    " Add some spaces for counting @@ -397,10 +397,45 @@ func Test_normal09a_operatorfunc()    " clean up    unmap <buffer> ,,    set opfunc= +  call assert_fails('normal Vg@', 'E774:')    bw!    unlet! g:opt  endfunc +func OperatorfuncRedo(_) +  let g:opfunc_count = v:count +endfunc + +func Underscorize(_) +  normal! '[V']r_ +endfunc + +func Test_normal09c_operatorfunc() +  " Test redoing operatorfunc +  new +  call setline(1, 'some text') +  set operatorfunc=OperatorfuncRedo +  normal v3g@ +  call assert_equal(3, g:opfunc_count) +  let g:opfunc_count = 0 +  normal . +  call assert_equal(3, g:opfunc_count) + +  bw! +  unlet g:opfunc_count + +  " Test redoing Visual mode +  set operatorfunc=Underscorize +  new +  call setline(1, ['first', 'first', 'third', 'third', 'second']) +  normal! 1GVjg@ +  normal! 5G. +  normal! 3G. +  call assert_equal(['_____', '_____', '_____', '_____', '______'], getline(1, '$')) +  bwipe! +  set operatorfunc= +endfunc +  func Test_normal10_expand()    " Test for expand()    10new @@ -456,8 +491,12 @@ func Test_normal12_nv_error()    10new    call setline(1, range(1,5))    " should not do anything, just beep -  exe "norm! <c-k>" +  call assert_beeps('exe "norm! <c-k>"')    call assert_equal(map(range(1,5), 'string(v:val)'), getline(1,'$')) +  call assert_beeps('normal! G2dd') +  call assert_beeps("normal! g\<C-A>") +  call assert_beeps("normal! g\<C-X>") +  call assert_beeps("normal! g\<C-B>")    bw!  endfunc @@ -1654,6 +1693,14 @@ fun! Test_normal30_changecase()      throw 'Skipped: Turkish locale not available'    endtry +  call setline(1, ['aaaaaa', 'aaaaaa']) +  normal! gg10~ +  call assert_equal(['AAAAAA', 'aaaaaa'], getline(1, 2)) +  set whichwrap+=~ +  normal! gg10~ +  call assert_equal(['aaaaaa', 'AAAAaa'], getline(1, 2)) +  set whichwrap& +    " clean up    bw!  endfunc @@ -1683,8 +1730,8 @@ fun! Test_normal31_r_cmd()    bw!  endfunc +" Test for g*, g#  func Test_normal32_g_cmd1() -  " Test for g*, g#    new    call append(0, ['abc.x_foo', 'x_foobar.abc'])    1 @@ -1699,11 +1746,12 @@ func Test_normal32_g_cmd1()    bw!  endfunc +" Test for g`, g;, g,, g&, gv, gk, gj, gJ, g0, g^, g_, gm, g$, gM, g CTRL-G, +" gi and gI commands  fun! Test_normal33_g_cmd2()    if !has("jumplist")      return    endif -  " Tests for g cmds    call Setup_NewWindow()    " Test for g`    clearjumps @@ -1715,6 +1763,10 @@ fun! Test_normal33_g_cmd2()    call assert_equal('>', a[-1:])    call assert_equal(1, line('.'))    call assert_equal('1', getline('.')) +  call cursor(10, 1) +  norm! g'a +  call assert_equal('>', a[-1:]) +  call assert_equal(1, line('.'))    " Test for g; and g,    norm! g; @@ -1756,14 +1808,20 @@ fun! Test_normal33_g_cmd2()    exe "norm! G0\<c-v>4k4ly"    exe "norm! gvood"    call assert_equal(['', 'abfgh', 'abfgh', 'abfgh', 'fgh', 'fgh', 'fgh', 'fgh', 'fgh'], getline(1,'$')) +  " gv cannot be used  in operator pending mode +  call assert_beeps('normal! cgv') +  " gv should beep without a previously selected visual area +  new +  call assert_beeps('normal! gv') +  close    " Test for gk/gj    %d    15vsp    set wrap listchars= sbr= -  let lineA='abcdefghijklmnopqrstuvwxyz' -  let lineB='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' -  let lineC='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' +  let lineA = 'abcdefghijklmnopqrstuvwxyz' +  let lineB = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' +  let lineC = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'    $put =lineA    $put =lineB @@ -1796,8 +1854,39 @@ fun! Test_normal33_g_cmd2()    norm! g^yl    call assert_equal(15, col('.'))    call assert_equal('l', getreg(0)) +  call assert_beeps('normal 5g$') + +  " Test for g$ with double-width character half displayed +  vsplit +  9wincmd | +  setlocal nowrap nonumber +  call setline(2, 'asdfasdfヨ') +  2 +  normal 0g$ +  call assert_equal(8, col('.')) +  10wincmd | +  normal 0g$ +  call assert_equal(9, col('.')) + +  setlocal signcolumn=yes +  11wincmd | +  normal 0g$ +  call assert_equal(8, col('.')) +  12wincmd | +  normal 0g$ +  call assert_equal(9, col('.')) -  norm! 2ggdd +  close + +  " Test for g_ +  call assert_beeps('normal! 100g_') +  call setline(2, ['  foo  ', '  foobar  ']) +  normal! 2ggg_ +  call assert_equal(5, col('.')) +  normal! 2g_ +  call assert_equal(8, col('.')) + +  norm! 2ggdG    $put =lineC    " Test for gM @@ -1839,6 +1928,17 @@ fun! Test_normal33_g_cmd2()    $put ='third line'    norm! gi another word    call assert_equal(['foobar next word another word', 'new line', 'third line'], getline(1,'$')) +  call setline(1, 'foobar') +  normal! Ggifirst line +  call assert_equal('foobarfirst line', getline(1)) +  " Test gi in 'virtualedit' mode with cursor after the end of the line +  set virtualedit=all +  call setline(1, 'foo') +  exe "normal! Abar\<Right>\<Right>\<Right>\<Right>" +  call setline(1, 'foo') +  normal! Ggifirst line +  call assert_equal('foo       first line', getline(1)) +  set virtualedit&    " clean up    bw! @@ -1927,8 +2027,8 @@ func Test_g_ctrl_g()    bwipe!  endfunc +" Test for g8  fun! Test_normal34_g_cmd3() -  " Test for g8    new    let a=execute(':norm! 1G0g8')    call assert_equal("\nNUL", a) @@ -1945,11 +2045,10 @@ fun! Test_normal34_g_cmd3()    bw!  endfunc +" Test 8g8 which finds invalid utf8 at or after the cursor.  func Test_normal_8g8()    new -  " Test 8g8 which finds invalid utf8 at or after the cursor. -    " With invalid byte.    call setline(1, "___\xff___")    norm! 1G08g8g @@ -1978,8 +2077,8 @@ func Test_normal_8g8()    bw!  endfunc +" Test for g<  fun! Test_normal35_g_cmd4() -  " Test for g<    " Cannot capture its output,    " probably a bug, therefore, test disabled:    throw "Skipped: output of g< can't be tested currently" @@ -1988,6 +2087,7 @@ fun! Test_normal35_g_cmd4()    call assert_true(!empty(b), 'failed `execute(g<)`')  endfunc +" Test for gp gP go  fun! Test_normal36_g_cmd5()    new    call append(0, 'abcdefghijklmnopqrstuvwxyz') @@ -2026,8 +2126,8 @@ fun! Test_normal36_g_cmd5()    bw!  endfunc +" Test for gt and gT  fun! Test_normal37_g_cmd6() -  " basic test for gt and gT    tabnew 1.txt    tabnew 2.txt    tabnew 3.txt @@ -2050,11 +2150,11 @@ fun! Test_normal37_g_cmd6()      tabclose    endfor    " clean up -  call assert_fails(':tabclose', 'E784') +  call assert_fails(':tabclose', 'E784:')  endfunc +" Test for <Home> and <C-Home> key  fun! Test_normal38_nvhome() -  " Test for <Home> and <C-Home> key    new    call setline(1, range(10))    $ @@ -2069,11 +2169,14 @@ fun! Test_normal38_nvhome()    call assert_equal([0, 5, 1, 0, 1], getcurpos())    exe "norm! \<c-home>"    call assert_equal([0, 1, 1, 0, 1], getcurpos()) +  exe "norm! G\<c-kHome>" +  call assert_equal([0, 1, 1, 0, 1], getcurpos())    " clean up    bw!  endfunc +" Test for cw cW ce  fun! Test_normal39_cw()    " Test for cw and cW on whitespace    " and cpo+=w setting @@ -2095,12 +2198,27 @@ fun! Test_normal39_cw()    norm! 2gg0cwfoo    call assert_equal('foo', getline('.')) +  call setline(1, 'one; two') +  call cursor(1, 1) +  call feedkeys('cwvim', 'xt') +  call assert_equal('vim; two', getline(1)) +  call feedkeys('0cWone', 'xt') +  call assert_equal('one two', getline(1)) +  "When cursor is at the end of a word 'ce' will change until the end of the +  "next word, but 'cw' will change only one character +  call setline(1, 'one two') +  call feedkeys('0ecwce', 'xt') +  call assert_equal('once two', getline(1)) +  call setline(1, 'one two') +  call feedkeys('0ecely', 'xt') +  call assert_equal('only', getline(1)) +    " clean up    bw!  endfunc +" Test for CTRL-\ commands  fun! Test_normal40_ctrl_bsl() -  " Basic test for CTRL-\ commands    new    call append(0, 'here      are   some words')    exe "norm! 1gg0a\<C-\>\<C-N>" @@ -2124,9 +2242,8 @@ fun! Test_normal40_ctrl_bsl()    bw!  endfunc +" Test for <c-r>=, <c-r><c-r>= and <c-r><c-o>= in insert mode  fun! Test_normal41_insert_reg() -  " Test for <c-r>=, <c-r><c-r>= and <c-r><c-o>= -  " in insert mode    new    set sts=2 sw=2 ts=8 tw=0    call append(0, ["aaa\tbbb\tccc", '', '', '']) @@ -2144,8 +2261,8 @@ fun! Test_normal41_insert_reg()    bw!  endfunc +" Test for Ctrl-D and Ctrl-U  func Test_normal42_halfpage() -  " basic test for Ctrl-D and Ctrl-U    call Setup_NewWindow()    call assert_equal(5, &scroll)    exe "norm! \<c-d>" @@ -2181,8 +2298,8 @@ func Test_normal42_halfpage()    bw!  endfunc +" Tests for text object aw  fun! Test_normal43_textobject1() -  " basic tests for text object aw    new    call append(0, ['foobar,eins,foobar', 'foo,zwei,foo    '])    " diw @@ -2212,8 +2329,8 @@ fun! Test_normal43_textobject1()    bw!  endfunc +" Test for is and as text objects  func Test_normal44_textobjects2() -  " basic testing for is and as text objects    new    call append(0, ['This is a test. With some sentences!', '', 'Even with a question? And one more. And no sentence here'])    " Test for dis - does not remove trailing whitespace @@ -2504,6 +2621,18 @@ func Test_gr_command()    normal 4gro    call assert_equal('ooooecond line', getline(2))    let &cpo = save_cpo +  normal! ggvegrx +  call assert_equal('xxxxx line', getline(1)) +  exe "normal! gggr\<C-V>122" +  call assert_equal('zxxxx line', getline(1)) +  set virtualedit=all +  normal! 15|grl +  call assert_equal('zxxxx line    l', getline(1)) +  set virtualedit& +  set nomodifiable +  call assert_fails('normal! grx', 'E21:') +  call assert_fails('normal! gRx', 'E21:') +  set modifiable&    enew!  endfunc @@ -2701,10 +2830,11 @@ fun! Test_normal_gdollar_cmd()    bw!  endfunc -func Test_normal_gk() +func Test_normal_gk_gj()    " needs 80 column new window    new    vert 80new +  call assert_beeps('normal gk')    put =[repeat('x',90)..' {{{1', 'x {{{1']    norm! gk    " In a 80 column wide terminal the window will be only 78 char @@ -2719,12 +2849,12 @@ func Test_normal_gk()    norm! gk    call assert_equal(95, col('.'))    call assert_equal(95, virtcol('.')) -  bw! -  bw! +  %bw!    " needs 80 column new window    new    vert 80new +  call assert_beeps('normal gj')    set number    set numberwidth=10    set cpoptions+=n @@ -2743,9 +2873,14 @@ func Test_normal_gk()    call assert_equal(1, col('.'))    norm! gj    call assert_equal(76, col('.')) -  bw! -  bw! -  set cpoptions& number& numberwidth& +  " When 'nowrap' is set, gk and gj behave like k and j +  set nowrap +  normal! gk +  call assert_equal([2, 76], [line('.'), col('.')]) +  normal! gj +  call assert_equal([3, 76], [line('.'), col('.')]) +  %bw! +  set cpoptions& number& numberwidth& wrap&  endfunc  " Test for cursor movement with '-' in 'cpoptions' @@ -2765,6 +2900,54 @@ func Test_normal_cpo_minus()    close!  endfunc +" Test for using : to run a multi-line Ex command in operator pending mode +func Test_normal_yank_with_excmd() +  new +  call setline(1, ['foo', 'bar', 'baz']) +  let @a = '' +  call feedkeys("\"ay:if v:true\<CR>normal l\<CR>endif\<CR>", 'xt') +  call assert_equal('f', @a) +  close! +endfunc + +" Test for supplying a count to a normal-mode command across a cursorhold call +func Test_normal_cursorhold_with_count() +  throw 'Skipped: Nvim removed <CursorHold> key' +  func s:cHold() +    let g:cHold_Called += 1 +  endfunc +  new +  augroup normalcHoldTest +    au! +    au CursorHold <buffer> call s:cHold() +  augroup END +  let g:cHold_Called = 0 +  call feedkeys("3\<CursorHold>2ix", 'xt') +  call assert_equal(1, g:cHold_Called) +  call assert_equal(repeat('x', 32), getline(1)) +  augroup normalcHoldTest +    au! +  augroup END +  au! normalcHoldTest +  close! +  delfunc s:cHold +endfunc + +" Test for using a count and a command with CTRL-W +func Test_wincmd_with_count() +  call feedkeys("\<C-W>12n", 'xt') +  call assert_equal(12, winheight(0)) +endfunc + +" Test for 'b', 'B' 'ge' and 'gE' commands +func Test_backward_motion() +  normal! gg +  call assert_beeps('normal! b') +  call assert_beeps('normal! B') +  call assert_beeps('normal! gE') +  call assert_beeps('normal! ge') +endfunc +  " Some commands like yy, cc, dd, >>, << and !! accept a count after  " typing the first letter of the command.  func Test_normal_count_after_operator() diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim index 1db0a01bd8..5099818384 100644 --- a/src/nvim/testdir/test_spell.vim +++ b/src/nvim/testdir/test_spell.vim @@ -287,6 +287,18 @@ func Test_spellreall()    bwipe!  endfunc +func Test_spell_dump_word_length() +  " this was running over MAXWLEN +  new +  noremap 0 0a0zW0000000 +  sil! norm 0z=0 +  sil norm 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +  sil! norm 0z=0 + +  bwipe! +  nunmap 0 +endfunc +  " Test spellsuggest({word} [, {max} [, {capital}]])  func Test_spellsuggest()    " Verify suggestions are given even when spell checking is not enabled. diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim index 8483435062..bd44079882 100644 --- a/src/nvim/testdir/test_substitute.vim +++ b/src/nvim/testdir/test_substitute.vim @@ -140,7 +140,7 @@ func Test_substitute_repeat()    " This caused an invalid memory access.    split Xfile    s/^/x -  call feedkeys("gQsc\<CR>y", 'tx') +  call feedkeys("Qsc\<CR>y", 'tx')    bwipe!  endfunc diff --git a/src/nvim/testdir/test_timers.vim b/src/nvim/testdir/test_timers.vim index 09eed4e10d..5c67efb831 100644 --- a/src/nvim/testdir/test_timers.vim +++ b/src/nvim/testdir/test_timers.vim @@ -279,7 +279,7 @@ func Test_ex_mode()    endfunc    let timer = timer_start(40, function('g:Foo'), {'repeat':-1})    " This used to throw error E749. -  exe "normal gQsleep 100m\rvi\r" +  exe "normal Qsleep 100m\rvi\r"    call timer_stop(timer)  endfunc diff --git a/src/nvim/testdir/test_virtualedit.vim b/src/nvim/testdir/test_virtualedit.vim index 250b896532..522ca17675 100644 --- a/src/nvim/testdir/test_virtualedit.vim +++ b/src/nvim/testdir/test_virtualedit.vim @@ -301,6 +301,9 @@ func Test_replace_on_tab()    call append(0, "'r'\t")    normal gg^5lrxAy    call assert_equal("'r'  x  y", getline(1)) +  call setline(1, 'aaaaaaaaaaaa') +  exe "normal! gg2lgR\<Tab>" +  call assert_equal("aa\taaaa", getline(1))    bwipe!    set virtualedit=  endfunc diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim index 492750fa66..349c4fde50 100644 --- a/src/nvim/testdir/test_visual.vim +++ b/src/nvim/testdir/test_visual.vim @@ -700,7 +700,6 @@ func Test_linewise_select_mode()    exe "normal GkkgH\<Del>"    call assert_equal(['', 'b', 'c'], getline(1, '$')) -    " linewise select mode: delete middle two lines    call deletebufline('', 1, '$')    call append('$', ['a', 'b', 'c']) @@ -722,6 +721,15 @@ func Test_linewise_select_mode()    bwipe!  endfunc +" Test for blockwise select mode (g CTRL-H) +func Test_blockwise_select_mode() +  new +  call setline(1, ['foo', 'bar']) +  call feedkeys("g\<BS>\<Right>\<Down>mm", 'xt') +  call assert_equal(['mmo', 'mmr'], getline(1, '$')) +  close! +endfunc +  func Test_visual_mode_put()    new @@ -1105,6 +1113,73 @@ func Test_block_insert_replace_tabs()    bwipe!  endfunc +" Test for * register in : +func Test_star_register() +  call assert_fails('*bfirst', 'E16:') +  new +  call setline(1, ['foo', 'bar', 'baz', 'qux']) +  exe "normal jVj\<ESC>" +  *yank r +  call assert_equal("bar\nbaz\n", @r) + +  delmarks < > +  call assert_fails('*yank', 'E20:') +  close! +endfunc + +" Test for using visual mode maps in select mode +func Test_select_mode_map() +  new +  vmap <buffer> <F2> 3l +  call setline(1, 'Test line') +  call feedkeys("gh\<F2>map", 'xt') +  call assert_equal('map line', getline(1)) + +  vmap <buffer> <F2> ygV +  call feedkeys("0gh\<Right>\<Right>\<F2>cwabc", 'xt') +  call assert_equal('abc line', getline(1)) + +  vmap <buffer> <F2> :<C-U>let v=100<CR> +  call feedkeys("gggh\<Right>\<Right>\<F2>foo", 'xt') +  call assert_equal('foo line', getline(1)) + +  " reselect the select mode using gv from a visual mode map +  vmap <buffer> <F2> gv +  set selectmode=cmd +  call feedkeys("0gh\<F2>map", 'xt') +  call assert_equal('map line', getline(1)) +  set selectmode& + +  close! +endfunc + +" Test for changing text in visual mode with 'exclusive' selection +func Test_exclusive_selection() +  new +  call setline(1, ['one', 'two']) +  set selection=exclusive +  call feedkeys("vwcabc", 'xt') +  call assert_equal('abctwo', getline(1)) +  call setline(1, ["\tone"]) +  set virtualedit=all +  call feedkeys('0v2lcl', 'xt') +  call assert_equal('l      one', getline(1)) +  set virtualedit& +  set selection& +  close! +endfunc + +" Test for starting visual mode with a count +" This test should be run withou any previous visual modes. So this should be +" run as a first test. +func Test_AAA_start_visual_mode_with_count() +  new +  call setline(1, ['aaaaaaa', 'aaaaaaa', 'aaaaaaa', 'aaaaaaa']) +  normal! gg2Vy +  call assert_equal("aaaaaaa\naaaaaaa\n", @") +  close! +endfunc +  func Test_visual_put_in_block()    new    call setline(1, ['xxxx', 'y∞yy', 'zzzz']) diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index bd66260457..68df5819e2 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -137,8 +137,7 @@ struct TUIData {    char *space_buf;  }; -static bool got_winch = false; -static bool did_user_set_dimensions = false; +static int got_winch = 0;  static bool cursor_style_enabled = false;  #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -535,7 +534,7 @@ static void sigcont_cb(SignalWatcher *watcher, int signum, void *data)  static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data)  { -  got_winch = true; +  got_winch++;    UI *ui = data;    if (tui_is_stopped(ui)) {      return; @@ -987,7 +986,7 @@ static void tui_grid_resize(UI *ui, Integer g, Integer width, Integer height)      r->right = MIN(r->right, grid->width);    } -  if (!got_winch && (!data->is_starting || did_user_set_dimensions)) { +  if (!got_winch && !data->is_starting) {      // Resize the _host_ terminal.      UNIBI_SET_NUM_VAR(data->params[0], (int)height);      UNIBI_SET_NUM_VAR(data->params[1], (int)width); @@ -997,7 +996,7 @@ static void tui_grid_resize(UI *ui, Integer g, Integer width, Integer height)        reset_scroll_region(ui, ui->width == grid->width);      }    } else {  // Already handled the SIGWINCH signal; avoid double-resize. -    got_winch = false; +    got_winch = got_winch > 0 ? got_winch - 1 : 0;      grid->row = -1;    }  } @@ -1504,23 +1503,13 @@ static void tui_guess_size(UI *ui)    TUIData *data = ui->data;    int width = 0, height = 0; -  // 1 - look for non-default 'columns' and 'lines' options during startup -  if (data->is_starting && (Columns != DFLT_COLS || Rows != DFLT_ROWS)) { -    did_user_set_dimensions = true; -    assert(Columns >= 0); -    assert(Rows >= 0); -    width = Columns; -    height = Rows; -    goto end; -  } - -  // 2 - try from a system call(ioctl/TIOCGWINSZ on unix) +  // 1 - try from a system call(ioctl/TIOCGWINSZ on unix)    if (data->out_isatty        && !uv_tty_get_winsize(&data->output_handle.tty, &width, &height)) {      goto end;    } -  // 3 - use $LINES/$COLUMNS if available +  // 2 - use $LINES/$COLUMNS if available    const char *val;    int advance;    if ((val = os_getenv("LINES")) @@ -1530,7 +1519,7 @@ static void tui_guess_size(UI *ui)      goto end;    } -  // 4 - read from terminfo if available +  // 3 - read from terminfo if available    height = unibi_get_num(data->ut, unibi_lines);    width = unibi_get_num(data->ut, unibi_columns); | 
