From da70c394053e2110aedf5a8ea72cbaba0ccf06d9 Mon Sep 17 00:00:00 2001 From: Liad Oz Date: Wed, 7 Dec 2022 19:07:56 +0200 Subject: fix(extmarks): adjust extmarks when inserting prompt prefix --- src/nvim/edit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 36a8674730..b83e732cec 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1484,7 +1484,7 @@ static void init_prompt(int cmdchar_todo) } curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; coladvance(MAXCOL); - changed_bytes(curbuf->b_ml.ml_line_count, 0); + inserted_bytes(curbuf->b_ml.ml_line_count, 0, 0, (colnr_T)strlen(prompt)); } // Insert always starts after the prompt, allow editing text after it. -- cgit From c94d8e7f13bbe6aa0d195eeac115695e0d95e7f3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 07:31:32 +0800 Subject: vim-patch:9.0.1244: cursor displayed in wrong position when leaving Insert mode (#21996) Problem: Cursor briefly displayed in a wrong position when pressing Esc in Insert mode after autoindent was used. Solution: Do not adjust the cursor position for assumed deleted white space if text is following. (closes vim/vim#11877) https://github.com/vim/vim/commit/0f843ef091eceb470caece1d90fdfe08926fe076 Co-authored-by: Bram Moolenaar --- src/nvim/getchar.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 9c5364e1b1..51554fea22 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2526,10 +2526,12 @@ static int vgetorpeek(bool advance) // move cursor left, if possible if (curwin->w_cursor.col != 0) { if (curwin->w_wcol > 0) { - if (did_ai) { - // We are expecting to truncate the trailing - // white-space, so find the last non-white - // character -- webb + // After auto-indenting and no text is following, + // we are expecting to truncate the trailing + // white-space, so find the last non-white + // character -- webb + if (did_ai + && *skipwhite(get_cursor_line_ptr() + curwin->w_cursor.col) == NUL) { curwin->w_wcol = 0; ptr = (char_u *)get_cursor_line_ptr(); chartabsize_T cts; -- cgit From f15947866ce59589346a4074a1fdc10f941a16b5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 07:46:51 +0800 Subject: vim-patch:9.0.1243: :setglobal cannot use script-local function for "expr" option (#21997) Problem: :setglobal cannot use script-local function for "expr" option. Solution: Use the pointer to the option value properly. (closes vim/vim#11883) https://github.com/vim/vim/commit/01d4efe2e87632aa085897d3d64e27585908f977 --- src/nvim/optionstr.c | 33 ++++++++++------------- src/nvim/testdir/test_edit.vim | 15 +++++++++++ src/nvim/testdir/test_fold.vim | 58 +++++++++++++++++++++++++++++++++++++--- src/nvim/testdir/test_gf.vim | 25 +++++++++++++++++ src/nvim/testdir/test_normal.vim | 46 +++++++++++++++++++++++++++++++ 5 files changed, 155 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index a5a708600f..162d8b691a 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1497,12 +1497,12 @@ static void did_set_vartabstop(buf_T *buf, win_T *win, char **varp, char **errms } } -static void did_set_optexpr(win_T *win, char **p_opt, char **varp, char **gvarp) +static void did_set_optexpr(char **varp) { - char *name = get_scriptlocal_funcname(*p_opt); + char *name = get_scriptlocal_funcname(*varp); if (name != NULL) { - free_string_option(*p_opt); - *p_opt = name; + free_string_option(*varp); + *varp = name; } } @@ -1808,23 +1808,18 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char did_set_varsoftabstop(buf, varp, &errmsg); } else if (varp == &buf->b_p_vts) { // 'vartabstop' did_set_vartabstop(buf, win, varp, &errmsg); - } else if (varp == &p_dex) { // 'diffexpr' - did_set_optexpr(win, &p_dex, varp, gvarp); - } else if (varp == &win->w_p_fde) { // 'foldexpr' - did_set_optexpr(win, &win->w_p_fde, varp, gvarp); - if (foldmethodIsExpr(win)) { + } else if (varp == &p_dex // 'diffexpr' + || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr' + || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext' + || gvarp == &p_fex // 'formatexpr' + || gvarp == &p_inex // 'includeexpr' + || gvarp == &p_inde // 'indentexpr' + || varp == &p_pex // 'patchexpr' + || varp == &p_ccv) { // 'charconvert' + did_set_optexpr(varp); + if (varp == &win->w_p_fde && foldmethodIsExpr(win)) { foldUpdateAll(win); } - } else if (varp == &win->w_p_fdt) { // 'foldtext' - did_set_optexpr(win, &win->w_p_fdt, varp, gvarp); - } else if (varp == &p_pex) { // 'patchexpr' - did_set_optexpr(win, &p_pex, varp, gvarp); - } else if (gvarp == &p_fex) { // 'formatexpr' - did_set_optexpr(win, &buf->b_p_fex, varp, gvarp); - } else if (gvarp == &p_inex) { // 'includeexpr' - did_set_optexpr(win, &buf->b_p_inex, varp, gvarp); - } else if (gvarp == &p_inde) { // 'indentexpr' - did_set_optexpr(win, &buf->b_p_inde, varp, gvarp); } else if (gvarp == &p_cfu) { // 'completefunc' set_completefunc_option(&errmsg); } else if (gvarp == &p_ofu) { // 'omnifunc' diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim index fd54f77ccb..89a9179e60 100644 --- a/src/nvim/testdir/test_edit.vim +++ b/src/nvim/testdir/test_edit.vim @@ -336,8 +336,23 @@ func Test_edit_11_indentexpr() endfunc set indentexpr=s:NewIndentExpr() call assert_equal(expand('') .. 'NewIndentExpr()', &indentexpr) + call assert_equal(expand('') .. 'NewIndentExpr()', &g:indentexpr) set indentexpr=NewIndentExpr() call assert_equal(expand('') .. 'NewIndentExpr()', &indentexpr) + call assert_equal(expand('') .. 'NewIndentExpr()', &g:indentexpr) + setlocal indentexpr= + setglobal indentexpr=s:NewIndentExpr() + call assert_equal(expand('') .. 'NewIndentExpr()', &g:indentexpr) + call assert_equal('', &indentexpr) + new + call assert_equal(expand('') .. 'NewIndentExpr()', &indentexpr) + bw! + setglobal indentexpr=NewIndentExpr() + call assert_equal(expand('') .. 'NewIndentExpr()', &g:indentexpr) + call assert_equal('', &indentexpr) + new + call assert_equal(expand('') .. 'NewIndentExpr()', &indentexpr) + bw! set indentexpr& bw! diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim index 19415286ad..9014948fb4 100644 --- a/src/nvim/testdir/test_fold.vim +++ b/src/nvim/testdir/test_fold.vim @@ -1305,6 +1305,7 @@ func Test_foldexpr_scriptlocal_func() set foldmethod=expr foldexpr=s:FoldFunc() redraw! call assert_equal(expand('') .. 'FoldFunc()', &foldexpr) + call assert_equal(expand('') .. 'FoldFunc()', &g:foldexpr) call assert_equal(1, g:FoldLnum) set foldmethod& foldexpr= bw! @@ -1314,8 +1315,31 @@ func Test_foldexpr_scriptlocal_func() set foldmethod=expr foldexpr=FoldFunc() redraw! call assert_equal(expand('') .. 'FoldFunc()', &foldexpr) + call assert_equal(expand('') .. 'FoldFunc()', &g:foldexpr) call assert_equal(1, g:FoldLnum) - set foldmethod& foldexpr= + bw! + call setline(1, 'abc') + setlocal foldmethod& foldexpr& + setglobal foldmethod=expr foldexpr=s:FoldFunc() + call assert_equal(expand('') .. 'FoldFunc()', &g:foldexpr) + call assert_equal('0', &foldexpr) + enew! + call setline(1, 'abc') + redraw! + call assert_equal(expand('') .. 'FoldFunc()', &foldexpr) + call assert_equal(1, g:FoldLnum) + bw! + call setline(1, 'abc') + setlocal foldmethod& foldexpr& + setglobal foldmethod=expr foldexpr=FoldFunc() + call assert_equal(expand('') .. 'FoldFunc()', &g:foldexpr) + call assert_equal('0', &foldexpr) + enew! + call setline(1, 'abc') + redraw! + call assert_equal(expand('') .. 'FoldFunc()', &foldexpr) + call assert_equal(1, g:FoldLnum) + set foldmethod& foldexpr& delfunc s:FoldFunc bw! endfunc @@ -1329,25 +1353,53 @@ func Test_foldtext_scriptlocal_func() new | only call setline(1, range(50)) let g:FoldTextArgs = [] - set foldmethod=manual set foldtext=s:FoldText() norm! 4Gzf4j redraw! call assert_equal(expand('') .. 'FoldText()', &foldtext) + call assert_equal(expand('') .. 'FoldText()', &g:foldtext) call assert_equal([4, 8], g:FoldTextArgs) set foldtext& bw! new | only call setline(1, range(50)) let g:FoldTextArgs = [] - set foldmethod=manual set foldtext=FoldText() norm! 8Gzf4j redraw! call assert_equal(expand('') .. 'FoldText()', &foldtext) + call assert_equal(expand('') .. 'FoldText()', &g:foldtext) call assert_equal([8, 12], g:FoldTextArgs) set foldtext& bw! + call setline(1, range(50)) + let g:FoldTextArgs = [] + setlocal foldtext& + setglobal foldtext=s:FoldText() + call assert_equal(expand('') .. 'FoldText()', &g:foldtext) + call assert_equal('foldtext()', &foldtext) + enew! + call setline(1, range(50)) + norm! 12Gzf4j + redraw! + call assert_equal(expand('') .. 'FoldText()', &foldtext) + call assert_equal([12, 16], g:FoldTextArgs) + set foldtext& + bw! + call setline(1, range(50)) + let g:FoldTextArgs = [] + setlocal foldtext& + setglobal foldtext=FoldText() + call assert_equal(expand('') .. 'FoldText()', &g:foldtext) + call assert_equal('foldtext()', &foldtext) + enew! + call setline(1, range(50)) + norm! 16Gzf4j + redraw! + call assert_equal(expand('') .. 'FoldText()', &foldtext) + call assert_equal([16, 20], g:FoldTextArgs) + set foldtext& + bw! delfunc s:FoldText endfunc diff --git a/src/nvim/testdir/test_gf.vim b/src/nvim/testdir/test_gf.vim index e369645328..f09dbd72ce 100644 --- a/src/nvim/testdir/test_gf.vim +++ b/src/nvim/testdir/test_gf.vim @@ -234,6 +234,7 @@ func Test_includeexpr_scriptlocal_func() endfunc set includeexpr=s:IncludeFunc() call assert_equal(expand('') .. 'IncludeFunc()', &includeexpr) + call assert_equal(expand('') .. 'IncludeFunc()', &g:includeexpr) new | only call setline(1, 'TestFile1') let g:IncludeFname = '' @@ -242,11 +243,35 @@ func Test_includeexpr_scriptlocal_func() bw! set includeexpr=IncludeFunc() call assert_equal(expand('') .. 'IncludeFunc()', &includeexpr) + call assert_equal(expand('') .. 'IncludeFunc()', &g:includeexpr) new | only call setline(1, 'TestFile2') let g:IncludeFname = '' call assert_fails('normal! gf', 'E447:') call assert_equal('TestFile2', g:IncludeFname) + bw! + setlocal includeexpr= + setglobal includeexpr=s:IncludeFunc() + call assert_equal(expand('') .. 'IncludeFunc()', &g:includeexpr) + call assert_equal('', &includeexpr) + new + call assert_equal(expand('') .. 'IncludeFunc()', &includeexpr) + call setline(1, 'TestFile3') + let g:IncludeFname = '' + call assert_fails('normal! gf', 'E447:') + call assert_equal('TestFile3', g:IncludeFname) + bw! + setlocal includeexpr= + setglobal includeexpr=IncludeFunc() + call assert_equal(expand('') .. 'IncludeFunc()', &g:includeexpr) + call assert_equal('', &includeexpr) + new + call assert_equal(expand('') .. 'IncludeFunc()', &includeexpr) + call setline(1, 'TestFile4') + let g:IncludeFname = '' + call assert_fails('normal! gf', 'E447:') + call assert_equal('TestFile4', g:IncludeFname) + bw! set includeexpr& delfunc s:IncludeFunc bw! diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index 7c90b444e5..2aaa1ff830 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -262,6 +262,7 @@ func Test_formatexpr_scriptlocal_func() endfunc set formatexpr=s:Format() call assert_equal(expand('') .. 'Format()', &formatexpr) + call assert_equal(expand('') .. 'Format()', &g:formatexpr) new | only call setline(1, range(1, 40)) let g:FormatArgs = [] @@ -270,6 +271,7 @@ func Test_formatexpr_scriptlocal_func() bw! set formatexpr=Format() call assert_equal(expand('') .. 'Format()', &formatexpr) + call assert_equal(expand('') .. 'Format()', &g:formatexpr) new | only call setline(1, range(1, 40)) let g:FormatArgs = [] @@ -277,6 +279,7 @@ func Test_formatexpr_scriptlocal_func() call assert_equal([4, 2], g:FormatArgs) bw! let &formatexpr = 's:Format()' + call assert_equal(expand('') .. 'Format()', &g:formatexpr) new | only call setline(1, range(1, 40)) let g:FormatArgs = [] @@ -284,12 +287,55 @@ func Test_formatexpr_scriptlocal_func() call assert_equal([6, 2], g:FormatArgs) bw! let &formatexpr = 'Format()' + call assert_equal(expand('') .. 'Format()', &g:formatexpr) new | only call setline(1, range(1, 40)) let g:FormatArgs = [] normal! 8GVjgq call assert_equal([8, 2], g:FormatArgs) + bw! setlocal formatexpr= + setglobal formatexpr=s:Format() + call assert_equal(expand('') .. 'Format()', &g:formatexpr) + call assert_equal('', &formatexpr) + new + call assert_equal(expand('') .. 'Format()', &formatexpr) + call setline(1, range(1, 40)) + let g:FormatArgs = [] + normal! 10GVjgq + call assert_equal([10, 2], g:FormatArgs) + bw! + setglobal formatexpr=Format() + call assert_equal(expand('') .. 'Format()', &g:formatexpr) + call assert_equal('', &formatexpr) + new + call assert_equal(expand('') .. 'Format()', &formatexpr) + call setline(1, range(1, 40)) + let g:FormatArgs = [] + normal! 12GVjgq + call assert_equal([12, 2], g:FormatArgs) + bw! + let &g:formatexpr = 's:Format()' + call assert_equal(expand('') .. 'Format()', &g:formatexpr) + call assert_equal('', &formatexpr) + new + call assert_equal(expand('') .. 'Format()', &formatexpr) + call setline(1, range(1, 40)) + let g:FormatArgs = [] + normal! 14GVjgq + call assert_equal([14, 2], g:FormatArgs) + bw! + let &g:formatexpr = 'Format()' + call assert_equal(expand('') .. 'Format()', &g:formatexpr) + call assert_equal('', &formatexpr) + new + call assert_equal(expand('') .. 'Format()', &formatexpr) + call setline(1, range(1, 40)) + let g:FormatArgs = [] + normal! 16GVjgq + call assert_equal([16, 2], g:FormatArgs) + bw! + set formatexpr= delfunc s:Format bw! endfunc -- cgit From 88e906d165b5dd57fb13b190ec9cb2d67bc6b223 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 08:52:21 +0800 Subject: vim-patch:9.0.1245: code is indented more than necessary (#21998) Problem: Code is indented more than necessary. Solution: Use an early return where it makes sense. (Yegappan Lakshmanan, closes vim/vim#11879) https://github.com/vim/vim/commit/032713f8299abd92fcfb1e490d1ae5c1ecadde41 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 50 +++++------ src/nvim/eval/typval.c | 80 ++++++++--------- src/nvim/tag.c | 228 +++++++++++++++++++++++++------------------------ src/nvim/testing.c | 49 +++++------ src/nvim/textformat.c | 32 +++---- 5 files changed, 226 insertions(+), 213 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 5a31288ecd..c527b62c8f 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7823,34 +7823,35 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // MSVC returns NULL for an invalid value of seconds. if (curtime_ptr == NULL) { rettv->vval.v_string = xstrdup(_("(Invalid)")); - } else { - vimconv_T conv; + return; + } - conv.vc_type = CONV_NONE; - char *enc = enc_locale(); - convert_setup(&conv, p_enc, enc); - if (conv.vc_type != CONV_NONE) { - p = string_convert(&conv, p, NULL); - } - char result_buf[256]; - if (p == NULL || strftime(result_buf, sizeof(result_buf), p, curtime_ptr) == 0) { - result_buf[0] = NUL; - } + vimconv_T conv; - if (conv.vc_type != CONV_NONE) { - xfree(p); - } - convert_setup(&conv, enc, p_enc); - if (conv.vc_type != CONV_NONE) { - rettv->vval.v_string = string_convert(&conv, result_buf, NULL); - } else { - rettv->vval.v_string = xstrdup(result_buf); - } + conv.vc_type = CONV_NONE; + char *enc = enc_locale(); + convert_setup(&conv, p_enc, enc); + if (conv.vc_type != CONV_NONE) { + p = string_convert(&conv, p, NULL); + } + char result_buf[256]; + if (p == NULL || strftime(result_buf, sizeof(result_buf), p, curtime_ptr) == 0) { + result_buf[0] = NUL; + } - // Release conversion descriptors. - convert_setup(&conv, NULL, NULL); - xfree(enc); + if (conv.vc_type != CONV_NONE) { + xfree(p); } + convert_setup(&conv, enc, p_enc); + if (conv.vc_type != CONV_NONE) { + rettv->vval.v_string = string_convert(&conv, result_buf, NULL); + } else { + rettv->vval.v_string = xstrdup(result_buf); + } + + // Release conversion descriptors. + convert_setup(&conv, NULL, NULL); + xfree(enc); } /// "strgetchar()" function @@ -8654,6 +8655,7 @@ static void f_timer_pause(typval_T *argvars, typval_T *unused, EvalFuncData fptr emsg(_(e_number_exp)); return; } + int paused = (bool)tv_get_number(&argvars[1]); timer_T *timer = find_timer_by_nr(tv_get_number(&argvars[0])); if (timer != NULL) { diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 05b4737206..c298064d86 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -3208,17 +3208,19 @@ static inline void _nothing_conv_dict_end(typval_T *const tv, dict_T **const dic /// @param[in,out] tv Value to free. void tv_clear(typval_T *const tv) { - if (tv != NULL && tv->v_type != VAR_UNKNOWN) { - // WARNING: do not translate the string here, gettext is slow and function - // is used *very* often. At the current state encode_vim_to_nothing() does - // not error out and does not use the argument anywhere. - // - // If situation changes and this argument will be used, translate it in the - // place where it is used. - const int evn_ret = encode_vim_to_nothing(NULL, tv, "tv_clear() argument"); - (void)evn_ret; - assert(evn_ret == OK); + if (tv == NULL || tv->v_type == VAR_UNKNOWN) { + return; } + + // WARNING: do not translate the string here, gettext is slow and function + // is used *very* often. At the current state encode_vim_to_nothing() does + // not error out and does not use the argument anywhere. + // + // If situation changes and this argument will be used, translate it in the + // place where it is used. + const int evn_ret = encode_vim_to_nothing(NULL, tv, "tv_clear() argument"); + (void)evn_ret; + assert(evn_ret == OK); } //{{{3 Free @@ -3228,35 +3230,37 @@ void tv_clear(typval_T *const tv) /// @param tv Object to free. void tv_free(typval_T *tv) { - if (tv != NULL) { - switch (tv->v_type) { - case VAR_PARTIAL: - partial_unref(tv->vval.v_partial); - break; - case VAR_FUNC: - func_unref(tv->vval.v_string); - FALLTHROUGH; - case VAR_STRING: - xfree(tv->vval.v_string); - break; - case VAR_BLOB: - tv_blob_unref(tv->vval.v_blob); - break; - case VAR_LIST: - tv_list_unref(tv->vval.v_list); - break; - case VAR_DICT: - tv_dict_unref(tv->vval.v_dict); - break; - case VAR_BOOL: - case VAR_SPECIAL: - case VAR_NUMBER: - case VAR_FLOAT: - case VAR_UNKNOWN: - break; - } - xfree(tv); + if (tv == NULL) { + return; + } + + switch (tv->v_type) { + case VAR_PARTIAL: + partial_unref(tv->vval.v_partial); + break; + case VAR_FUNC: + func_unref(tv->vval.v_string); + FALLTHROUGH; + case VAR_STRING: + xfree(tv->vval.v_string); + break; + case VAR_BLOB: + tv_blob_unref(tv->vval.v_blob); + break; + case VAR_LIST: + tv_list_unref(tv->vval.v_list); + break; + case VAR_DICT: + tv_dict_unref(tv->vval.v_dict); + break; + case VAR_BOOL: + case VAR_SPECIAL: + case VAR_NUMBER: + case VAR_FLOAT: + case VAR_UNKNOWN: + break; } + xfree(tv); } //{{{3 Copy diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 197184c181..42618e8924 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -2732,55 +2732,57 @@ static int parse_match(char *lbuf, tagptrs_T *tagp) tagp->tagline = 0; tagp->command_end = NULL; - if (retval == OK) { - // Try to find a kind field: "kind:" or just "" - p = tagp->command; - if (find_extra(&p) == OK) { - tagp->command_end = p; - if (p > tagp->command && p[-1] == '|') { - tagp->command_end = p - 1; // drop trailing bar - } - p += 2; // skip ";\"" - if (*p++ == TAB) { - // Accept ASCII alphabetic kind characters and any multi-byte - // character. - while (ASCII_ISALPHA(*p) || utfc_ptr2len(p) > 1) { - if (strncmp(p, "kind:", 5) == 0) { - tagp->tagkind = p + 5; - } else if (strncmp(p, "user_data:", 10) == 0) { - tagp->user_data = p + 10; - } else if (strncmp(p, "line:", 5) == 0) { - tagp->tagline = atoi(p + 5); - } - if (tagp->tagkind != NULL && tagp->user_data != NULL) { - break; - } + if (retval != OK) { + return retval; + } - pc = vim_strchr(p, ':'); - pt = vim_strchr(p, '\t'); - if (pc == NULL || (pt != NULL && pc > pt)) { - tagp->tagkind = p; - } - if (pt == NULL) { - break; - } - p = pt; - MB_PTR_ADV(p); + // Try to find a kind field: "kind:" or just "" + p = tagp->command; + if (find_extra(&p) == OK) { + tagp->command_end = p; + if (p > tagp->command && p[-1] == '|') { + tagp->command_end = p - 1; // drop trailing bar + } + p += 2; // skip ";\"" + if (*p++ == TAB) { + // Accept ASCII alphabetic kind characters and any multi-byte + // character. + while (ASCII_ISALPHA(*p) || utfc_ptr2len(p) > 1) { + if (strncmp(p, "kind:", 5) == 0) { + tagp->tagkind = p + 5; + } else if (strncmp(p, "user_data:", 10) == 0) { + tagp->user_data = p + 10; + } else if (strncmp(p, "line:", 5) == 0) { + tagp->tagline = atoi(p + 5); } + if (tagp->tagkind != NULL && tagp->user_data != NULL) { + break; + } + + pc = vim_strchr(p, ':'); + pt = vim_strchr(p, '\t'); + if (pc == NULL || (pt != NULL && pc > pt)) { + tagp->tagkind = p; + } + if (pt == NULL) { + break; + } + p = pt; + MB_PTR_ADV(p); } } - if (tagp->tagkind != NULL) { - for (p = tagp->tagkind; - *p && *p != '\t' && *p != '\r' && *p != '\n'; - MB_PTR_ADV(p)) {} - tagp->tagkind_end = p; - } - if (tagp->user_data != NULL) { - for (p = tagp->user_data; - *p && *p != '\t' && *p != '\r' && *p != '\n'; - MB_PTR_ADV(p)) {} - tagp->user_data_end = p; - } + } + if (tagp->tagkind != NULL) { + for (p = tagp->tagkind; + *p && *p != '\t' && *p != '\r' && *p != '\n'; + MB_PTR_ADV(p)) {} + tagp->tagkind_end = p; + } + if (tagp->user_data != NULL) { + for (p = tagp->user_data; + *p && *p != '\t' && *p != '\r' && *p != '\n'; + MB_PTR_ADV(p)) {} + tagp->user_data_end = p; } return retval; } @@ -3329,86 +3331,88 @@ int get_tags(list_T *list, char *pat, char *buf_fname) ret = find_tags(pat, &num_matches, &matches, TAG_REGEXP | TAG_NOIC, MAXCOL, buf_fname); - if (ret == OK && num_matches > 0) { - for (i = 0; i < num_matches; i++) { - int parse_result = parse_match(matches[i], &tp); + if (ret != OK || num_matches <= 0) { + return ret; + } - // Avoid an unused variable warning in release builds. - (void)parse_result; - assert(parse_result == OK); + for (i = 0; i < num_matches; i++) { + int parse_result = parse_match(matches[i], &tp); - is_static = test_for_static(&tp); + // Avoid an unused variable warning in release builds. + (void)parse_result; + assert(parse_result == OK); - // Skip pseudo-tag lines. - if (strncmp(tp.tagname, "!_TAG_", 6) == 0) { - xfree(matches[i]); - continue; - } + is_static = test_for_static(&tp); + + // Skip pseudo-tag lines. + if (strncmp(tp.tagname, "!_TAG_", 6) == 0) { + xfree(matches[i]); + continue; + } - dict = tv_dict_alloc(); - tv_list_append_dict(list, dict); - - full_fname = tag_full_fname(&tp); - if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL - || add_tag_field(dict, "filename", full_fname, NULL) == FAIL - || add_tag_field(dict, "cmd", tp.command, tp.command_end) == FAIL - || add_tag_field(dict, "kind", tp.tagkind, - tp.tagkind ? tp.tagkind_end : NULL) == FAIL - || tv_dict_add_nr(dict, S_LEN("static"), is_static) == FAIL) { - ret = FAIL; - } - - xfree(full_fname); - - if (tp.command_end != NULL) { - for (char *p = tp.command_end + 3; - *p != NUL && *p != '\n' && *p != '\r'; - MB_PTR_ADV(p)) { - if (p == tp.tagkind - || (p + 5 == tp.tagkind && strncmp(p, "kind:", 5) == 0)) { - // skip "kind:" and "" - p = tp.tagkind_end - 1; - } else if (strncmp(p, "file:", 5) == 0) { - // skip "file:" (static tag) - p += 4; - } else if (!ascii_iswhite(*p)) { - char *s, *n; - int len; - - // Add extra field as a dict entry. Fields are - // separated by Tabs. - n = p; - while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':') { + dict = tv_dict_alloc(); + tv_list_append_dict(list, dict); + + full_fname = tag_full_fname(&tp); + if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL + || add_tag_field(dict, "filename", full_fname, NULL) == FAIL + || add_tag_field(dict, "cmd", tp.command, tp.command_end) == FAIL + || add_tag_field(dict, "kind", tp.tagkind, + tp.tagkind ? tp.tagkind_end : NULL) == FAIL + || tv_dict_add_nr(dict, S_LEN("static"), is_static) == FAIL) { + ret = FAIL; + } + + xfree(full_fname); + + if (tp.command_end != NULL) { + for (char *p = tp.command_end + 3; + *p != NUL && *p != '\n' && *p != '\r'; + MB_PTR_ADV(p)) { + if (p == tp.tagkind + || (p + 5 == tp.tagkind && strncmp(p, "kind:", 5) == 0)) { + // skip "kind:" and "" + p = tp.tagkind_end - 1; + } else if (strncmp(p, "file:", 5) == 0) { + // skip "file:" (static tag) + p += 4; + } else if (!ascii_iswhite(*p)) { + char *s, *n; + int len; + + // Add extra field as a dict entry. Fields are + // separated by Tabs. + n = p; + while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':') { + p++; + } + len = (int)(p - n); + if (*p == ':' && len > 0) { + s = ++p; + while (*p != NUL && (uint8_t)(*p) >= ' ') { p++; } - len = (int)(p - n); - if (*p == ':' && len > 0) { - s = ++p; - while (*p != NUL && (uint8_t)(*p) >= ' ') { - p++; - } - n[len] = NUL; - if (add_tag_field(dict, n, s, p) == FAIL) { - ret = FAIL; - } - n[len] = ':'; - } else { - // Skip field without colon. - while (*p != NUL && (uint8_t)(*p) >= ' ') { - p++; - } + n[len] = NUL; + if (add_tag_field(dict, n, s, p) == FAIL) { + ret = FAIL; } - if (*p == NUL) { - break; + n[len] = ':'; + } else { + // Skip field without colon. + while (*p != NUL && (uint8_t)(*p) >= ' ') { + p++; } } + if (*p == NUL) { + break; + } } } - - xfree(matches[i]); } - xfree(matches); + + xfree(matches[i]); } + xfree(matches); return ret; } diff --git a/src/nvim/testing.c b/src/nvim/testing.c index edf92c78ac..b5921b3445 100644 --- a/src/nvim/testing.c +++ b/src/nvim/testing.c @@ -77,31 +77,32 @@ static void ga_concat_esc(garray_T *gap, const char *p, int clen) memmove(buf, p, (size_t)clen); buf[clen] = NUL; ga_concat(gap, buf); - } else { - switch (*p) { - case BS: - ga_concat(gap, "\\b"); break; - case ESC: - ga_concat(gap, "\\e"); break; - case FF: - ga_concat(gap, "\\f"); break; - case NL: - ga_concat(gap, "\\n"); break; - case TAB: - ga_concat(gap, "\\t"); break; - case CAR: - ga_concat(gap, "\\r"); break; - case '\\': - ga_concat(gap, "\\\\"); break; - default: - if ((uint8_t)(*p) < ' ' || *p == 0x7f) { - vim_snprintf(buf, NUMBUFLEN, "\\x%02x", *p); - ga_concat(gap, buf); - } else { - ga_append(gap, (uint8_t)(*p)); - } - break; + return; + } + + switch (*p) { + case BS: + ga_concat(gap, "\\b"); break; + case ESC: + ga_concat(gap, "\\e"); break; + case FF: + ga_concat(gap, "\\f"); break; + case NL: + ga_concat(gap, "\\n"); break; + case TAB: + ga_concat(gap, "\\t"); break; + case CAR: + ga_concat(gap, "\\r"); break; + case '\\': + ga_concat(gap, "\\\\"); break; + default: + if ((uint8_t)(*p) < ' ' || *p == 0x7f) { + vim_snprintf(buf, NUMBUFLEN, "\\x%02x", *p); + ga_concat(gap, buf); + } else { + ga_append(gap, (uint8_t)(*p)); } + break; } } diff --git a/src/nvim/textformat.c b/src/nvim/textformat.c index fbea1ccfb7..e30580a748 100644 --- a/src/nvim/textformat.c +++ b/src/nvim/textformat.c @@ -736,22 +736,24 @@ void check_auto_format(bool end_insert) int c = ' '; int cc; - if (did_add_space) { - cc = gchar_cursor(); - if (!WHITECHAR(cc)) { - // Somehow the space was removed already. + if (!did_add_space) { + return; + } + + cc = gchar_cursor(); + if (!WHITECHAR(cc)) { + // Somehow the space was removed already. + did_add_space = false; + } else { + if (!end_insert) { + inc_cursor(); + c = gchar_cursor(); + dec_cursor(); + } + if (c != NUL) { + // The space is no longer at the end of the line, delete it. + del_char(false); did_add_space = false; - } else { - if (!end_insert) { - inc_cursor(); - c = gchar_cursor(); - dec_cursor(); - } - if (c != NUL) { - // The space is no longer at the end of the line, delete it. - del_char(false); - did_add_space = false; - } } } } -- cgit From 116766f243b4ac647f040181334c8001e01aab75 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 09:12:33 +0800 Subject: refactor(options): don't pass negative number to illegal_char() (#21999) This only changes the error messages for an unexpected Unicode char in an option to show its first byte instead of some special keycode. The second argument of vim_strchr() usually doesn't matter, but it may be better to consistently cast to uint8_t. --- src/nvim/optionstr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 162d8b691a..5ebff9ed77 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -615,7 +615,7 @@ char *check_stl_option(char *s) continue; } if (vim_strchr(STL_ALL, (uint8_t)(*s)) == NULL) { - return illegal_char(errbuf, sizeof(errbuf), *s); + return illegal_char(errbuf, sizeof(errbuf), (uint8_t)(*s)); } if (*s == '{') { bool reevaluate = (*++s == '%'); @@ -957,7 +957,7 @@ static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, char * while (*s && *s != ':') { if (vim_strchr(COM_ALL, (uint8_t)(*s)) == NULL && !ascii_isdigit(*s) && *s != '-') { - *errmsg = illegal_char(errbuf, errbuflen, *s); + *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); break; } s++; @@ -1029,7 +1029,7 @@ static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, ch for (char *s = p_shada; *s;) { // Check it's a valid character if (vim_strchr("!\"%'/:<@cfhnrs", (uint8_t)(*s)) == NULL) { - *errmsg = illegal_char(errbuf, errbuflen, *s); + *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); break; } if (*s == 'n') { // name is always last one @@ -1236,7 +1236,7 @@ static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, char * break; } if (vim_strchr(".wbuksid]tU", (uint8_t)(*s)) == NULL) { - *errmsg = illegal_char(errbuf, errbuflen, *s); + *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); break; } if (*++s != NUL && *s != ',' && *s != ' ') { @@ -1511,8 +1511,8 @@ static void did_set_option_listflag(char **varp, char *flags, char *errbuf, size char **errmsg) { for (char *s = *varp; *s; s++) { - if (vim_strchr(flags, *s) == NULL) { - *errmsg = illegal_char(errbuf, errbuflen, *s); + if (vim_strchr(flags, (uint8_t)(*s)) == NULL) { + *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s)); break; } } -- cgit From 5ac34cf55db2b00c044fa95f75766dd89dd36ba9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 09:30:26 +0800 Subject: refactor(intro): avoid Coverity warning (#22000) refactor(intro): avoid coverity warning Problem: Coverity warns about overwriting "mesg" leaking memory. Solution: Make it clear that "mesg" will not be overwritten. --- src/nvim/version.c | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/nvim/version.c b/src/nvim/version.c index 417e5116a5..11f1d6695e 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -2785,13 +2785,6 @@ void maybe_intro_message(void) /// @param colon true for ":intro" void intro_message(int colon) { - int i; - long row; - long blanklines; - int sponsor; - char *p; - char *mesg; - int mesg_size; static char *(lines[]) = { N_(NVIM_VERSION_LONG), "", @@ -2813,7 +2806,7 @@ void intro_message(int colon) size_t lines_size = ARRAY_SIZE(lines); assert(lines_size <= LONG_MAX); - blanklines = Rows - ((long)lines_size - 1L); + long blanklines = Rows - ((long)lines_size - 1L); // Don't overwrite a statusline. Depends on 'cmdheight'. if (p_ls > 1) { @@ -2826,17 +2819,17 @@ void intro_message(int colon) // Show the sponsor and register message one out of four times, the Uganda // message two out of four times. - sponsor = (int)time(NULL); + int sponsor = (int)time(NULL); sponsor = ((sponsor & 2) == 0) - ((sponsor & 4) == 0); // start displaying the message lines after half of the blank lines - row = blanklines / 2; + long row = blanklines / 2; if (((row >= 2) && (Columns >= 50)) || colon) { - for (i = 0; i < (int)ARRAY_SIZE(lines); i++) { - p = lines[i]; - mesg = NULL; - mesg_size = 0; + for (int i = 0; i < (int)ARRAY_SIZE(lines); i++) { + char *p = lines[i]; + char *mesg = NULL; + int mesg_size = 0; if (strstr(p, "news") != NULL) { p = _(p); @@ -2846,18 +2839,15 @@ void intro_message(int colon) mesg = xmallocz((size_t)mesg_size); snprintf(mesg, (size_t)mesg_size + 1, p, STR(NVIM_VERSION_MAJOR), STR(NVIM_VERSION_MINOR)); - } - - if (sponsor != 0) { + } else if (sponsor != 0) { if (strstr(p, "children") != NULL) { - mesg = sponsor < 0 - ? _("Sponsor Vim development!") - : _("Become a registered Vim user!"); - } - if (strstr(p, "iccf") != NULL) { - mesg = sponsor < 0 - ? _("type :help sponsor for information ") - : _("type :help register for information "); + p = sponsor < 0 + ? N_("Sponsor Vim development!") + : N_("Become a registered Vim user!"); + } else if (strstr(p, "iccf") != NULL) { + p = sponsor < 0 + ? N_("type :help sponsor for information ") + : N_("type :help register for information "); } } -- cgit From 6644786db078e019426f90cf85da50e3fa1b6a67 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 09:44:15 +0800 Subject: vim-patch:9.0.1227: no cmdline completion for :runtime Problem: No cmdline completion for :runtime. Solution: Add completion for :runtime. (closes vim/vim#11853, closes vim/vim#11447) Improve the resulting matches. https://github.com/vim/vim/commit/a6759381a590b2d395e05b109ca9ccfc356be5a8 --- src/nvim/cmdexpand.c | 12 +++++++ src/nvim/runtime.c | 70 ++++++++++++++++++++++++++++++++------- src/nvim/runtime.h | 1 + src/nvim/testdir/test_cmdline.vim | 9 +++++ src/nvim/usercmd.c | 1 + src/nvim/vim.h | 1 + 6 files changed, 82 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index be815151ef..3e06814d6a 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -109,6 +109,7 @@ static bool cmdline_fuzzy_completion_supported(const expand_T *const xp) && xp->xp_context != EXPAND_OLD_SETTING && xp->xp_context != EXPAND_OWNSYNTAX && xp->xp_context != EXPAND_PACKADD + && xp->xp_context != EXPAND_RUNTIME && xp->xp_context != EXPAND_SHELLCMD && xp->xp_context != EXPAND_TAGS && xp->xp_context != EXPAND_TAGS_LISTFILES @@ -1211,6 +1212,7 @@ char *addstar(char *fname, size_t len, int context) if (context == EXPAND_HELP || context == EXPAND_CHECKHEALTH || context == EXPAND_COLORS + || context == EXPAND_RUNTIME || context == EXPAND_COMPILER || context == EXPAND_OWNSYNTAX || context == EXPAND_FILETYPE @@ -2072,6 +2074,11 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa xp->xp_pattern = (char *)arg; break; + case CMD_runtime: + xp->xp_context = EXPAND_RUNTIME; + xp->xp_pattern = (char *)arg; + break; + case CMD_compiler: xp->xp_context = EXPAND_COMPILER; xp->xp_pattern = (char *)arg; @@ -2712,6 +2719,11 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM char *directories[] = { "colors", NULL }; return ExpandRTDir(pat, DIP_START + DIP_OPT, numMatches, matches, directories); } + if (xp->xp_context == EXPAND_RUNTIME) { + char *directories[] = { "", NULL }; + return ExpandRTDir(pat, DIP_START + DIP_OPT + DIP_PRNEXT, numMatches, + matches, directories); + } if (xp->xp_context == EXPAND_COMPILER) { char *directories[] = { "compiler", NULL }; return ExpandRTDir(pat, 0, numMatches, matches, directories); diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 24500b80b9..068a43c790 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -1194,11 +1194,22 @@ int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirname // TODO(bfredl): this is bullshit, expandpath should not reinvent path logic. for (int i = 0; dirnames[i] != NULL; i++) { - size_t size = strlen(dirnames[i]) + pat_len + 16; - char *s = xmalloc(size); - snprintf(s, size, "%s/%s*.\\(vim\\|lua\\)", dirnames[i], pat); - globpath(p_rtp, s, &ga, 0); - xfree(s); + size_t size = strlen(dirnames[i]) + pat_len * 2 + 26; + char *buf = xmalloc(size); + if (*dirnames[i] == NUL) { + // empty dir used for :runtime + if (path_tail(pat) == pat) { + // no path separator, match dir names and script files + snprintf(buf, size, "\\(%s*.\\(vim\\|lua\\)\\)\\|\\(%s*\\)", pat, pat); + } else { + // has path separator, match script files + snprintf(buf, size, "%s*.vim", pat); + } + } else { + snprintf(buf, size, "%s/%s*.\\(vim\\|lua\\)", dirnames[i], pat); + } + globpath(p_rtp, buf, &ga, 0); + xfree(buf); } if (flags & DIP_START) { @@ -1241,18 +1252,53 @@ int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirname char *match = ((char **)ga.ga_data)[i]; char *s = match; char *e = s + strlen(s); + char *res_start = s; + if ((flags & DIP_PRNEXT) != 0) { + char *p = strstr(match, pat); + if (p != NULL) { + // Drop what comes before "pat" in the match, so that for + // match "/long/path/syntax/cpp.vim" with pattern + // "syntax/cp" we only keep "syntax/cpp.vim". + res_start = p; + } + } + if (e - s > 4 && (STRNICMP(e - 4, ".vim", 4) == 0 || STRNICMP(e - 4, ".lua", 4) == 0)) { - e -= 4; - for (s = e; s > match; MB_PTR_BACK(match, s)) { - if (vim_ispathsep(*s)) { - break; + if (res_start == s) { + // Only keep the file name. + // Remove file ext only if flag DIP_PRNEXT is not present. + if ((flags & DIP_PRNEXT) == 0) { + e -= 4; + } + for (s = e; s > match; MB_PTR_BACK(match, s)) { + if (s < match) { + break; + } + if (vim_ispathsep(*s)) { + res_start = s + 1; + break; + } } } - s++; + *e = NUL; - assert((e - s) + 1 >= 0); - memmove(match, s, (size_t)(e - s) + 1); + } + + if (res_start > match) { + assert((e - res_start) + 1 >= 0); + memmove(match, res_start, (size_t)(e - res_start) + 1); + } + + // remove entries that look like backup files + if (e > s && e[-1] == '~') { + xfree(match); + char **fnames = (char **)ga.ga_data; + for (int j = i + 1; j < ga.ga_len; ++j) { + fnames[j - 1] = fnames[j]; + } + ga.ga_len--; + i--; } } diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h index 97063b900c..be2663d52a 100644 --- a/src/nvim/runtime.h +++ b/src/nvim/runtime.h @@ -105,6 +105,7 @@ typedef kvec_t(char *) CharVec; #define DIP_NORTP 0x20 // do not use 'runtimepath' #define DIP_NOAFTER 0x40 // skip "after" directories #define DIP_AFTER 0x80 // only use "after" directories +#define DIP_PRNEXT 0x100 // for print also file extension #define DIP_DIRFILE 0x200 // find both files and directories #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index cf1d56ae38..8f79f0d8a0 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -542,6 +542,15 @@ func Test_getcompletion() call assert_true(index(l, '') >= 0) let l = getcompletion('not', 'mapclear') call assert_equal([], l) + + let l = getcompletion('', 'runtime') + call assert_true(index(l, 'defaults.vim') >= 0) + let l = getcompletion('synt', 'runtime') + call assert_true(index(l, 'syntax') >= 0) + let l = getcompletion('syntax/vi', 'runtime') + call assert_true(index(l, 'syntax/vim.vim') >= 0) + let l = getcompletion('notexitsts', 'runtime') + call assert_equal([], l) let l = getcompletion('.', 'shellcmd') call assert_equal(['./', '../'], filter(l, 'v:val =~ "\\./"')) diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c index 31cb1e8936..ef13f67e49 100644 --- a/src/nvim/usercmd.c +++ b/src/nvim/usercmd.c @@ -89,6 +89,7 @@ static const char *command_complete[] = { [EXPAND_SYNTIME] = "syntime", [EXPAND_SETTINGS] = "option", [EXPAND_PACKADD] = "packadd", + [EXPAND_RUNTIME] = "runtime", [EXPAND_SHELLCMD] = "shellcmd", [EXPAND_SIGN] = "sign", [EXPAND_TAGS] = "tag", diff --git a/src/nvim/vim.h b/src/nvim/vim.h index c4baa911f1..3c765f8eb2 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -156,6 +156,7 @@ enum { EXPAND_DIFF_BUFFERS, EXPAND_BREAKPOINT, EXPAND_SCRIPTNAMES, + EXPAND_RUNTIME, EXPAND_CHECKHEALTH, EXPAND_LUA, }; -- cgit From 6320c91c50e4c0ee5c366241f9a413c4edbfdad8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 09:58:27 +0800 Subject: vim-patch:9.0.1231: completion of :runtime does not handle {where} argument Problem: Completion of :runtime does not handle {where} argument. Solution: Parse the {where} argument. (closes vim/vim#11863) https://github.com/vim/vim/commit/3770f4c9cde7b5fcd10b6fa2e665cd0b69450fb2 --- src/nvim/cmdexpand.c | 17 ++-- src/nvim/eval/funcs.c | 2 +- src/nvim/path.c | 2 +- src/nvim/runtime.c | 205 +++++++++++++++++++------------------- src/nvim/runtime.h | 2 +- src/nvim/testdir/test_cmdline.vim | 9 -- src/nvim/testdir/test_packadd.vim | 64 ++++++++++++ 7 files changed, 178 insertions(+), 123 deletions(-) (limited to 'src') diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index 3e06814d6a..21ea8c1ffc 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -2075,8 +2075,7 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa break; case CMD_runtime: - xp->xp_context = EXPAND_RUNTIME; - xp->xp_pattern = (char *)arg; + set_context_in_runtime_cmd(xp, arg); break; case CMD_compiler: @@ -2720,9 +2719,7 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM return ExpandRTDir(pat, DIP_START + DIP_OPT, numMatches, matches, directories); } if (xp->xp_context == EXPAND_RUNTIME) { - char *directories[] = { "", NULL }; - return ExpandRTDir(pat, DIP_START + DIP_OPT + DIP_PRNEXT, numMatches, - matches, directories); + return expand_runtime_cmd(pat, numMatches, matches); } if (xp->xp_context == EXPAND_COMPILER) { char *directories[] = { "compiler", NULL }; @@ -3213,11 +3210,12 @@ static int ExpandUserLua(expand_T *xp, int *num_file, char ***file) /// Expand `file` for all comma-separated directories in `path`. /// Adds matches to `ga`. -void globpath(char *path, char *file, garray_T *ga, int expand_options) +/// If "dirs" is true only expand directory names. +void globpath(char *path, char *file, garray_T *ga, int expand_options, bool dirs) { expand_T xpc; ExpandInit(&xpc); - xpc.xp_context = EXPAND_FILES; + xpc.xp_context = dirs ? EXPAND_DIRECTORIES : EXPAND_FILES; char *buf = xmalloc(MAXPATHL); @@ -3536,11 +3534,14 @@ void f_getcompletion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) set_context_in_menu_cmd(&xpc, "menu", xpc.xp_pattern, false); xpc.xp_pattern_len = strlen(xpc.xp_pattern); } - if (xpc.xp_context == EXPAND_SIGN) { set_context_in_sign_cmd(&xpc, xpc.xp_pattern); xpc.xp_pattern_len = strlen(xpc.xp_pattern); } + if (xpc.xp_context == EXPAND_RUNTIME) { + set_context_in_runtime_cmd(&xpc, xpc.xp_pattern); + xpc.xp_pattern_len = strlen(xpc.xp_pattern); + } theend: if (cmdline_fuzzy_completion_supported(&xpc)) { diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c527b62c8f..938fef9a52 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2983,7 +2983,7 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (file != NULL && !error) { garray_T ga; ga_init(&ga, (int)sizeof(char *), 10); - globpath((char *)tv_get_string(&argvars[0]), (char *)file, &ga, flags); + globpath((char *)tv_get_string(&argvars[0]), (char *)file, &ga, flags, false); if (rettv->v_type == VAR_STRING) { rettv->vval.v_string = ga_concat_strings_sep(&ga, "\n"); diff --git a/src/nvim/path.c b/src/nvim/path.c index 513f366a27..e4c2253357 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -1138,7 +1138,7 @@ static int expand_in_path(garray_T *const gap, char *const pattern, const int fl if (flags & EW_ADDSLASH) { glob_flags |= WILD_ADD_SLASH; } - globpath(paths, pattern, gap, glob_flags); + globpath(paths, pattern, gap, glob_flags, false); xfree(paths); return gap->ga_len; diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 068a43c790..129d41ed22 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -208,31 +208,65 @@ void runtime_init(void) uv_mutex_init(&runtime_search_path_mutex); } +/// Get DIP_ flags from the [what] argument of a :runtime command. +/// "*argp" is advanced to after the [what] argument. +static int get_runtime_cmd_flags(char **argp) +{ + char *arg = *argp; + char *p = skiptowhite(arg); + size_t what_len = (size_t)(p - arg); + + if (what_len == 0) { + return 0; + } + + if (strncmp(arg, "START", what_len) == 0) { + *argp = skipwhite(arg + what_len); + return DIP_START + DIP_NORTP; + } + if (strncmp(arg, "OPT", what_len) == 0) { + *argp = skipwhite(arg + what_len); + return DIP_OPT + DIP_NORTP; + } + if (strncmp(arg, "PACK", what_len) == 0) { + *argp = skipwhite(arg + what_len); + return DIP_START + DIP_OPT + DIP_NORTP; + } + if (strncmp(arg, "ALL", what_len) == 0) { + *argp = skipwhite(arg + what_len); + return DIP_START + DIP_OPT; + } + + return 0; +} + /// ":runtime [what] {name}" void ex_runtime(exarg_T *eap) { char *arg = eap->arg; - char *p = skiptowhite(arg); - size_t len = (size_t)(p - arg); int flags = eap->forceit ? DIP_ALL : 0; - if (strncmp(arg, "START", len) == 0) { - flags += DIP_START + DIP_NORTP; - arg = skipwhite(arg + len); - } else if (strncmp(arg, "OPT", len) == 0) { - flags += DIP_OPT + DIP_NORTP; - arg = skipwhite(arg + len); - } else if (strncmp(arg, "PACK", len) == 0) { - flags += DIP_START + DIP_OPT + DIP_NORTP; - arg = skipwhite(arg + len); - } else if (strncmp(arg, "ALL", len) == 0) { - flags += DIP_START + DIP_OPT; - arg = skipwhite(arg + len); - } - + flags += get_runtime_cmd_flags(&arg); source_runtime(arg, flags); } +static int runtime_expand_flags; + +/// Set the completion context for the :runtime command. +void set_context_in_runtime_cmd(expand_T *xp, const char *arg) +{ + runtime_expand_flags = DIP_KEEPEXT + get_runtime_cmd_flags((char **)&arg); + xp->xp_context = EXPAND_RUNTIME; + xp->xp_pattern = (char *)arg; +} + +/// Handle command line completion for :runtime command. +int expand_runtime_cmd(char *pat, int *numMatches, char ***matches) +{ + char *directories[] = {"", NULL}; + return ExpandRTDir(pat, runtime_expand_flags, numMatches, matches, directories); +} + static void source_callback(char *fname, void *cookie) { (void)do_source(fname, false, DOSO_NONE); @@ -1194,57 +1228,53 @@ int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirname // TODO(bfredl): this is bullshit, expandpath should not reinvent path logic. for (int i = 0; dirnames[i] != NULL; i++) { - size_t size = strlen(dirnames[i]) + pat_len * 2 + 26; - char *buf = xmalloc(size); - if (*dirnames[i] == NUL) { - // empty dir used for :runtime - if (path_tail(pat) == pat) { - // no path separator, match dir names and script files - snprintf(buf, size, "\\(%s*.\\(vim\\|lua\\)\\)\\|\\(%s*\\)", pat, pat); - } else { - // has path separator, match script files - snprintf(buf, size, "%s*.vim", pat); - } + const size_t buf_len = strlen(dirnames[i]) + pat_len + 31; + char *const buf = xmalloc(buf_len); + char *const tail = buf + 15; + const size_t tail_buflen = buf_len - 15; + int glob_flags = 0; + bool expand_dirs = false; + + if (*dirnames[i] == NUL) { // empty dir used for :runtime + snprintf(tail, tail_buflen, "%s*.\\(vim\\|lua\\)", pat); } else { - snprintf(buf, size, "%s/%s*.\\(vim\\|lua\\)", dirnames[i], pat); + snprintf(tail, tail_buflen, "%s/%s*.\\(vim\\|lua\\)", dirnames[i], pat); } - globpath(p_rtp, buf, &ga, 0); - xfree(buf); - } - if (flags & DIP_START) { - for (int i = 0; dirnames[i] != NULL; i++) { - size_t size = strlen(dirnames[i]) + pat_len + 31; - char *s = xmalloc(size); - snprintf(s, size, "pack/*/start/*/%s/%s*.\\(vim\\|lua\\)", dirnames[i], pat); // NOLINT - globpath(p_pp, s, &ga, 0); - xfree(s); +expand: + if ((flags & DIP_NORTP) == 0) { + globpath(p_rtp, tail, &ga, glob_flags, expand_dirs); } - for (int i = 0; dirnames[i] != NULL; i++) { - size_t size = strlen(dirnames[i]) + pat_len + 31; - char *s = xmalloc(size); - snprintf(s, size, "start/*/%s/%s*.\\(vim\\|lua\\)", dirnames[i], pat); // NOLINT - globpath(p_pp, s, &ga, 0); - xfree(s); + if (flags & DIP_START) { + memcpy(tail - 15, "pack/*/start/*/", 15); // NOLINT + globpath(p_pp, tail - 15, &ga, glob_flags, expand_dirs); + memcpy(tail - 8, "start/*/", 8); // NOLINT + globpath(p_pp, tail - 8, &ga, glob_flags, expand_dirs); } - } - if (flags & DIP_OPT) { - for (int i = 0; dirnames[i] != NULL; i++) { - size_t size = strlen(dirnames[i]) + pat_len + 29; - char *s = xmalloc(size); - snprintf(s, size, "pack/*/opt/*/%s/%s*.\\(vim\\|lua\\)", dirnames[i], pat); // NOLINT - globpath(p_pp, s, &ga, 0); - xfree(s); + if (flags & DIP_OPT) { + memcpy(tail - 13, "pack/*/opt/*/", 13); // NOLINT + globpath(p_pp, tail - 13, &ga, glob_flags, expand_dirs); + memcpy(tail - 6, "opt/*/", 6); // NOLINT + globpath(p_pp, tail - 6, &ga, glob_flags, expand_dirs); } - for (int i = 0; dirnames[i] != NULL; i++) { - size_t size = strlen(dirnames[i]) + pat_len + 29; - char *s = xmalloc(size); - snprintf(s, size, "opt/*/%s/%s*.\\(vim\\|lua\\)", dirnames[i], pat); // NOLINT - globpath(p_pp, s, &ga, 0); - xfree(s); + if (*dirnames[i] == NUL && !expand_dirs) { + // expand dir names in another round + snprintf(tail, tail_buflen, "%s*", pat); + glob_flags = WILD_ADD_SLASH; + expand_dirs = true; + goto expand; + } + + xfree(buf); + } + + int pat_pathsep_cnt = 0; + for (size_t i = 0; i < pat_len; i++) { + if (vim_ispathsep(pat[i])) { + pat_pathsep_cnt++; } } @@ -1252,54 +1282,23 @@ int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirname char *match = ((char **)ga.ga_data)[i]; char *s = match; char *e = s + strlen(s); - char *res_start = s; - if ((flags & DIP_PRNEXT) != 0) { - char *p = strstr(match, pat); - if (p != NULL) { - // Drop what comes before "pat" in the match, so that for - // match "/long/path/syntax/cpp.vim" with pattern - // "syntax/cp" we only keep "syntax/cpp.vim". - res_start = p; - } - } - - if (e - s > 4 && (STRNICMP(e - 4, ".vim", 4) == 0 - || STRNICMP(e - 4, ".lua", 4) == 0)) { - if (res_start == s) { - // Only keep the file name. - // Remove file ext only if flag DIP_PRNEXT is not present. - if ((flags & DIP_PRNEXT) == 0) { - e -= 4; - } - for (s = e; s > match; MB_PTR_BACK(match, s)) { - if (s < match) { - break; - } - if (vim_ispathsep(*s)) { - res_start = s + 1; - break; - } - } - } - + if (e - s > 4 && (flags & DIP_KEEPEXT) == 0 + && (STRNICMP(e - 4, ".vim", 4) == 0 + || STRNICMP(e - 4, ".lua", 4) == 0)) { + e -= 4; *e = NUL; } - if (res_start > match) { - assert((e - res_start) + 1 >= 0); - memmove(match, res_start, (size_t)(e - res_start) + 1); - } - - // remove entries that look like backup files - if (e > s && e[-1] == '~') { - xfree(match); - char **fnames = (char **)ga.ga_data; - for (int j = i + 1; j < ga.ga_len; ++j) { - fnames[j - 1] = fnames[j]; + int match_pathsep_cnt = (e > s && e[-1] == '/') ? -1 : 0; + for (s = e; s > match; MB_PTR_BACK(match, s)) { + if (vim_ispathsep(*s) && ++match_pathsep_cnt > pat_pathsep_cnt) { + break; } - ga.ga_len--; - i--; } + s++; + *e = NUL; + assert((e - s) + 1 >= 0); + memmove(match, s, (size_t)(e - s) + 1); } if (GA_EMPTY(&ga)) { @@ -1329,9 +1328,9 @@ int ExpandPackAddDir(char *pat, int *num_file, char ***file) size_t buflen = pat_len + 26; char *s = xmalloc(buflen); snprintf(s, buflen, "pack/*/opt/%s*", pat); // NOLINT - globpath(p_pp, s, &ga, 0); + globpath(p_pp, s, &ga, 0, true); snprintf(s, buflen, "opt/%s*", pat); // NOLINT - globpath(p_pp, s, &ga, 0); + globpath(p_pp, s, &ga, 0, true); xfree(s); for (int i = 0; i < ga.ga_len; i++) { diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h index be2663d52a..3821fc4bbc 100644 --- a/src/nvim/runtime.h +++ b/src/nvim/runtime.h @@ -105,7 +105,7 @@ typedef kvec_t(char *) CharVec; #define DIP_NORTP 0x20 // do not use 'runtimepath' #define DIP_NOAFTER 0x40 // skip "after" directories #define DIP_AFTER 0x80 // only use "after" directories -#define DIP_PRNEXT 0x100 // for print also file extension +#define DIP_KEEPEXT 0x100 // for completion: include file extension #define DIP_DIRFILE 0x200 // find both files and directories #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 8f79f0d8a0..cf1d56ae38 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -542,15 +542,6 @@ func Test_getcompletion() call assert_true(index(l, '') >= 0) let l = getcompletion('not', 'mapclear') call assert_equal([], l) - - let l = getcompletion('', 'runtime') - call assert_true(index(l, 'defaults.vim') >= 0) - let l = getcompletion('synt', 'runtime') - call assert_true(index(l, 'syntax') >= 0) - let l = getcompletion('syntax/vi', 'runtime') - call assert_true(index(l, 'syntax/vim.vim') >= 0) - let l = getcompletion('notexitsts', 'runtime') - call assert_equal([], l) let l = getcompletion('.', 'shellcmd') call assert_equal(['./', '../'], filter(l, 'v:val =~ "\\./"')) diff --git a/src/nvim/testdir/test_packadd.vim b/src/nvim/testdir/test_packadd.vim index fcb8b8033b..3f00548273 100644 --- a/src/nvim/testdir/test_packadd.vim +++ b/src/nvim/testdir/test_packadd.vim @@ -193,8 +193,10 @@ func Test_packadd_completion() call mkdir(optdir1 . '/pluginA', 'p') call mkdir(optdir1 . '/pluginC', 'p') + call writefile([], optdir1 . '/unrelated') call mkdir(optdir2 . '/pluginB', 'p') call mkdir(optdir2 . '/pluginC', 'p') + call writefile([], optdir2 . '/unrelated') let li = [] call feedkeys(":packadd \')\call add(li, '\", 't') @@ -358,4 +360,66 @@ func Test_runtime() call assert_equal('runstartopt', g:sequence) endfunc +func Test_runtime_completion() + let rundir = &packpath . '/runtime/Xextra' + let startdir = &packpath . '/pack/mine/start/foo/Xextra' + let optdir = &packpath . '/pack/mine/opt/bar/Xextra' + call mkdir(rundir . '/Xrunbaz', 'p') + call mkdir(startdir . '/Xstartbaz', 'p') + call mkdir(optdir . '/Xoptbaz', 'p') + call writefile([], rundir . '/../Xrunfoo.vim') + call writefile([], rundir . '/Xrunbar.vim') + call writefile([], rundir . '/Xunrelated') + call writefile([], rundir . '/../Xunrelated') + call writefile([], startdir . '/../Xstartfoo.vim') + call writefile([], startdir . '/Xstartbar.vim') + call writefile([], startdir . '/Xunrelated') + call writefile([], startdir . '/../Xunrelated') + call writefile([], optdir . '/../Xoptfoo.vim') + call writefile([], optdir . '/Xoptbar.vim') + call writefile([], optdir . '/Xunrelated') + call writefile([], optdir . '/../Xunrelated') + exe 'set rtp=' . &packpath . '/runtime' + + func Check_runtime_completion(arg, arg1, res) + call feedkeys(':runtime ' .. a:arg .. "\\\"\", 'xt') + call assert_equal('"runtime ' .. a:arg1 .. join(a:res), @:) + call assert_equal(a:res, getcompletion(a:arg, 'runtime')) + + call feedkeys(':runtime ' .. a:arg .. "X\\\"\", 'xt') + call assert_equal('"runtime ' .. a:arg1 .. join(a:res), @:) + call assert_equal(a:res, getcompletion(a:arg .. 'X', 'runtime')) + endfunc + + call Check_runtime_completion('', '', + \ ['Xextra/', 'Xrunfoo.vim']) + call Check_runtime_completion('Xextra/', '', + \ ['Xextra/Xrunbar.vim', 'Xextra/Xrunbaz/']) + + call Check_runtime_completion('START ', 'START ', + \ ['Xextra/', 'Xstartfoo.vim']) + call Check_runtime_completion('START Xextra/', 'START ', + \ ['Xextra/Xstartbar.vim', 'Xextra/Xstartbaz/']) + + call Check_runtime_completion('OPT ', 'OPT ', + \ ['Xextra/', 'Xoptfoo.vim']) + call Check_runtime_completion('OPT Xextra/', 'OPT ', + \ ['Xextra/Xoptbar.vim', 'Xextra/Xoptbaz/']) + + call Check_runtime_completion('PACK ', 'PACK ', + \ ['Xextra/', 'Xoptfoo.vim', 'Xstartfoo.vim']) + call Check_runtime_completion('PACK Xextra/', 'PACK ', + \ ['Xextra/Xoptbar.vim', 'Xextra/Xoptbaz/', + \ 'Xextra/Xstartbar.vim', 'Xextra/Xstartbaz/']) + + call Check_runtime_completion('ALL ', 'ALL ', + \ ['Xextra/', 'Xoptfoo.vim', 'Xrunfoo.vim', 'Xstartfoo.vim']) + call Check_runtime_completion('ALL Xextra/', 'ALL ', + \ ['Xextra/Xoptbar.vim', 'Xextra/Xoptbaz/', + \ 'Xextra/Xrunbar.vim', 'Xextra/Xrunbaz/', + \ 'Xextra/Xstartbar.vim', 'Xextra/Xstartbaz/']) + + delfunc Check_runtime_completion +endfunc + " vim: shiftwidth=2 sts=2 expandtab -- cgit From f03f6263bb3eb0b28b759292cb6ef4465a05cafe Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 10:38:53 +0800 Subject: vim-patch:9.0.1238: :runtime completion can be further improved Problem: :runtime completion can be further improved. Solution: Also complete the {where} argument values and adjust the completion for that. (closes vim/vim#11874) https://github.com/vim/vim/commit/5c8771bc5a2be123ab8e6325fa60ed524e8efb09 --- src/nvim/cmdexpand.c | 6 +- src/nvim/runtime.c | 151 +++++++++++++++++++++++--------------- src/nvim/runtime.h | 1 - src/nvim/testdir/test_packadd.vim | 92 +++++++++++++---------- 4 files changed, 148 insertions(+), 102 deletions(-) (limited to 'src') diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index 21ea8c1ffc..53d513b319 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -2718,9 +2718,6 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM char *directories[] = { "colors", NULL }; return ExpandRTDir(pat, DIP_START + DIP_OPT, numMatches, matches, directories); } - if (xp->xp_context == EXPAND_RUNTIME) { - return expand_runtime_cmd(pat, numMatches, matches); - } if (xp->xp_context == EXPAND_COMPILER) { char *directories[] = { "compiler", NULL }; return ExpandRTDir(pat, 0, numMatches, matches, directories); @@ -2742,6 +2739,9 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM if (xp->xp_context == EXPAND_PACKADD) { return ExpandPackAddDir(pat, numMatches, matches); } + if (xp->xp_context == EXPAND_RUNTIME) { + return expand_runtime_cmd(pat, numMatches, matches); + } // When expanding a function name starting with s:, match the nr_ // prefix. diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 129d41ed22..b071e10cf9 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -26,6 +26,7 @@ #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" +#include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/gettext.h" #include "nvim/globals.h" @@ -208,45 +209,43 @@ void runtime_init(void) uv_mutex_init(&runtime_search_path_mutex); } -/// Get DIP_ flags from the [what] argument of a :runtime command. -/// "*argp" is advanced to after the [what] argument. -static int get_runtime_cmd_flags(char **argp) +/// Get DIP_ flags from the [where] argument of a :runtime command. +/// "*argp" is advanced to after the [where] argument. +static int get_runtime_cmd_flags(char **argp, size_t where_len) { char *arg = *argp; - char *p = skiptowhite(arg); - size_t what_len = (size_t)(p - arg); - if (what_len == 0) { + if (where_len == 0) { return 0; } - if (strncmp(arg, "START", what_len) == 0) { - *argp = skipwhite(arg + what_len); + if (strncmp(arg, "START", where_len) == 0) { + *argp = skipwhite(arg + where_len); return DIP_START + DIP_NORTP; } - if (strncmp(arg, "OPT", what_len) == 0) { - *argp = skipwhite(arg + what_len); + if (strncmp(arg, "OPT", where_len) == 0) { + *argp = skipwhite(arg + where_len); return DIP_OPT + DIP_NORTP; } - if (strncmp(arg, "PACK", what_len) == 0) { - *argp = skipwhite(arg + what_len); + if (strncmp(arg, "PACK", where_len) == 0) { + *argp = skipwhite(arg + where_len); return DIP_START + DIP_OPT + DIP_NORTP; } - if (strncmp(arg, "ALL", what_len) == 0) { - *argp = skipwhite(arg + what_len); + if (strncmp(arg, "ALL", where_len) == 0) { + *argp = skipwhite(arg + where_len); return DIP_START + DIP_OPT; } return 0; } -/// ":runtime [what] {name}" +/// ":runtime [where] {name}" void ex_runtime(exarg_T *eap) { char *arg = eap->arg; int flags = eap->forceit ? DIP_ALL : 0; - - flags += get_runtime_cmd_flags(&arg); + char *p = skiptowhite(arg); + flags += get_runtime_cmd_flags(&arg, (size_t)(p - arg)); source_runtime(arg, flags); } @@ -255,18 +254,13 @@ static int runtime_expand_flags; /// Set the completion context for the :runtime command. void set_context_in_runtime_cmd(expand_T *xp, const char *arg) { - runtime_expand_flags = DIP_KEEPEXT + get_runtime_cmd_flags((char **)&arg); + char *p = skiptowhite(arg); + runtime_expand_flags + = *p != NUL ? get_runtime_cmd_flags((char **)&arg, (size_t)(p - arg)) : 0; xp->xp_context = EXPAND_RUNTIME; xp->xp_pattern = (char *)arg; } -/// Handle command line completion for :runtime command. -int expand_runtime_cmd(char *pat, int *numMatches, char ***matches) -{ - char *directories[] = {"", NULL}; - return ExpandRTDir(pat, runtime_expand_flags, numMatches, matches, directories); -} - static void source_callback(char *fname, void *cookie) { (void)do_source(fname, false, DOSO_NONE); @@ -1209,23 +1203,9 @@ void ex_packadd(exarg_T *eap) } } -/// Expand color scheme, compiler or filetype names. -/// Search from 'runtimepath': -/// 'runtimepath'/{dirnames}/{pat}.(vim|lua) -/// When "flags" has DIP_START: search also from "start" of 'packpath': -/// 'packpath'/pack/*/start/*/{dirnames}/{pat}.(vim|lua) -/// When "flags" has DIP_OPT: search also from "opt" of 'packpath': -/// 'packpath'/pack/*/opt/*/{dirnames}/{pat}.(vim|lua) -/// "dirnames" is an array with one or more directory names. -int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirnames[]) +static void ExpandRTDir_int(char *pat, size_t pat_len, int flags, bool keep_ext, garray_T *gap, + char *dirnames[]) { - *num_file = 0; - *file = NULL; - size_t pat_len = strlen(pat); - - garray_T ga; - ga_init(&ga, (int)sizeof(char *), 10); - // TODO(bfredl): this is bullshit, expandpath should not reinvent path logic. for (int i = 0; dirnames[i] != NULL; i++) { const size_t buf_len = strlen(dirnames[i]) + pat_len + 31; @@ -1243,21 +1223,21 @@ int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirname expand: if ((flags & DIP_NORTP) == 0) { - globpath(p_rtp, tail, &ga, glob_flags, expand_dirs); + globpath(p_rtp, tail, gap, glob_flags, expand_dirs); } if (flags & DIP_START) { memcpy(tail - 15, "pack/*/start/*/", 15); // NOLINT - globpath(p_pp, tail - 15, &ga, glob_flags, expand_dirs); + globpath(p_pp, tail - 15, gap, glob_flags, expand_dirs); memcpy(tail - 8, "start/*/", 8); // NOLINT - globpath(p_pp, tail - 8, &ga, glob_flags, expand_dirs); + globpath(p_pp, tail - 8, gap, glob_flags, expand_dirs); } if (flags & DIP_OPT) { memcpy(tail - 13, "pack/*/opt/*/", 13); // NOLINT - globpath(p_pp, tail - 13, &ga, glob_flags, expand_dirs); + globpath(p_pp, tail - 13, gap, glob_flags, expand_dirs); memcpy(tail - 6, "opt/*/", 6); // NOLINT - globpath(p_pp, tail - 6, &ga, glob_flags, expand_dirs); + globpath(p_pp, tail - 6, gap, glob_flags, expand_dirs); } if (*dirnames[i] == NUL && !expand_dirs) { @@ -1278,13 +1258,12 @@ expand: } } - for (int i = 0; i < ga.ga_len; i++) { - char *match = ((char **)ga.ga_data)[i]; + for (int i = 0; i < gap->ga_len; i++) { + char *match = ((char **)gap->ga_data)[i]; char *s = match; char *e = s + strlen(s); - if (e - s > 4 && (flags & DIP_KEEPEXT) == 0 - && (STRNICMP(e - 4, ".vim", 4) == 0 - || STRNICMP(e - 4, ".lua", 4) == 0)) { + if (e - s > 4 && !keep_ext && (STRNICMP(e - 4, ".vim", 4) == 0 + || STRNICMP(e - 4, ".lua", 4) == 0)) { e -= 4; *e = NUL; } @@ -1296,26 +1275,82 @@ expand: } } s++; - *e = NUL; - assert((e - s) + 1 >= 0); - memmove(match, s, (size_t)(e - s) + 1); + if (s != match) { + assert((e - s) + 1 >= 0); + memmove(match, s, (size_t)(e - s) + 1); + } } - if (GA_EMPTY(&ga)) { - return FAIL; + if (GA_EMPTY(gap)) { + return; } // Sort and remove duplicates which can happen when specifying multiple // directories in dirnames. - ga_remove_duplicate_strings(&ga); + ga_remove_duplicate_strings(gap); +} + +/// Expand color scheme, compiler or filetype names. +/// Search from 'runtimepath': +/// 'runtimepath'/{dirnames}/{pat}.(vim|lua) +/// When "flags" has DIP_START: search also from "start" of 'packpath': +/// 'packpath'/pack/*/start/*/{dirnames}/{pat}.(vim|lua) +/// When "flags" has DIP_OPT: search also from "opt" of 'packpath': +/// 'packpath'/pack/*/opt/*/{dirnames}/{pat}.(vim|lua) +/// "dirnames" is an array with one or more directory names. +int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirnames[]) +{ + *num_file = 0; + *file = NULL; + + garray_T ga; + ga_init(&ga, (int)sizeof(char *), 10); + + ExpandRTDir_int(pat, strlen(pat), flags, false, &ga, dirnames); + + if (GA_EMPTY(&ga)) { + return FAIL; + } *file = ga.ga_data; *num_file = ga.ga_len; return OK; } +/// Handle command line completion for :runtime command. +int expand_runtime_cmd(char *pat, int *numMatches, char ***matches) +{ + *numMatches = 0; + *matches = NULL; + + garray_T ga; + ga_init(&ga, sizeof(char *), 10); + + const size_t pat_len = strlen(pat); + char *dirnames[] = { "", NULL }; + ExpandRTDir_int(pat, pat_len, runtime_expand_flags, true, &ga, dirnames); + + // Try to complete values for [where] argument when none was found. + if (runtime_expand_flags == 0) { + char *where_values[] = { "START", "OPT", "PACK", "ALL" }; + for (size_t i = 0; i < ARRAY_SIZE(where_values); i++) { + if (strncmp(pat, where_values[i], pat_len) == 0) { + GA_APPEND(char *, &ga, xstrdup(where_values[i])); + } + } + } + + if (GA_EMPTY(&ga)) { + return FAIL; + } + + *matches = ga.ga_data; + *numMatches = ga.ga_len; + return OK; +} + /// Expand loadplugin names: -/// 'packpath'/pack/ * /opt/{pat} +/// 'packpath'/pack/*/opt/{pat} int ExpandPackAddDir(char *pat, int *num_file, char ***file) { garray_T ga; diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h index 3821fc4bbc..97063b900c 100644 --- a/src/nvim/runtime.h +++ b/src/nvim/runtime.h @@ -105,7 +105,6 @@ typedef kvec_t(char *) CharVec; #define DIP_NORTP 0x20 // do not use 'runtimepath' #define DIP_NOAFTER 0x40 // skip "after" directories #define DIP_AFTER 0x80 // only use "after" directories -#define DIP_KEEPEXT 0x100 // for completion: include file extension #define DIP_DIRFILE 0x200 // find both files and directories #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/testdir/test_packadd.vim b/src/nvim/testdir/test_packadd.vim index 3f00548273..d577f32d55 100644 --- a/src/nvim/testdir/test_packadd.vim +++ b/src/nvim/testdir/test_packadd.vim @@ -361,63 +361,75 @@ func Test_runtime() endfunc func Test_runtime_completion() - let rundir = &packpath . '/runtime/Xextra' - let startdir = &packpath . '/pack/mine/start/foo/Xextra' - let optdir = &packpath . '/pack/mine/opt/bar/Xextra' - call mkdir(rundir . '/Xrunbaz', 'p') - call mkdir(startdir . '/Xstartbaz', 'p') - call mkdir(optdir . '/Xoptbaz', 'p') - call writefile([], rundir . '/../Xrunfoo.vim') - call writefile([], rundir . '/Xrunbar.vim') - call writefile([], rundir . '/Xunrelated') - call writefile([], rundir . '/../Xunrelated') - call writefile([], startdir . '/../Xstartfoo.vim') - call writefile([], startdir . '/Xstartbar.vim') - call writefile([], startdir . '/Xunrelated') - call writefile([], startdir . '/../Xunrelated') - call writefile([], optdir . '/../Xoptfoo.vim') - call writefile([], optdir . '/Xoptbar.vim') - call writefile([], optdir . '/Xunrelated') - call writefile([], optdir . '/../Xunrelated') + let rundir = &packpath . '/runtime/Aextra' + let startdir = &packpath . '/pack/mine/start/foo/Aextra' + let optdir = &packpath . '/pack/mine/opt/bar/Aextra' + call mkdir(rundir . '/Arunbaz', 'p') + call mkdir(startdir . '/Astartbaz', 'p') + call mkdir(optdir . '/Aoptbaz', 'p') + call writefile([], rundir . '/../Arunfoo.vim') + call writefile([], rundir . '/Arunbar.vim') + call writefile([], rundir . '/Aunrelated') + call writefile([], rundir . '/../Aunrelated') + call writefile([], startdir . '/../Astartfoo.vim') + call writefile([], startdir . '/Astartbar.vim') + call writefile([], startdir . '/Aunrelated') + call writefile([], startdir . '/../Aunrelated') + call writefile([], optdir . '/../Aoptfoo.vim') + call writefile([], optdir . '/Aoptbar.vim') + call writefile([], optdir . '/Aunrelated') + call writefile([], optdir . '/../Aunrelated') exe 'set rtp=' . &packpath . '/runtime' func Check_runtime_completion(arg, arg1, res) call feedkeys(':runtime ' .. a:arg .. "\\\"\", 'xt') call assert_equal('"runtime ' .. a:arg1 .. join(a:res), @:) call assert_equal(a:res, getcompletion(a:arg, 'runtime')) - - call feedkeys(':runtime ' .. a:arg .. "X\\\"\", 'xt') - call assert_equal('"runtime ' .. a:arg1 .. join(a:res), @:) - call assert_equal(a:res, getcompletion(a:arg .. 'X', 'runtime')) endfunc call Check_runtime_completion('', '', - \ ['Xextra/', 'Xrunfoo.vim']) - call Check_runtime_completion('Xextra/', '', - \ ['Xextra/Xrunbar.vim', 'Xextra/Xrunbaz/']) + \ ['Aextra/', 'Arunfoo.vim', 'START', 'OPT', 'PACK', 'ALL']) + call Check_runtime_completion('S', '', + \ ['START']) + call Check_runtime_completion('O', '', + \ ['OPT']) + call Check_runtime_completion('P', '', + \ ['PACK']) + call Check_runtime_completion('A', '', + \ ['Aextra/', 'Arunfoo.vim', 'ALL']) + call Check_runtime_completion('Aextra/', '', + \ ['Aextra/Arunbar.vim', 'Aextra/Arunbaz/']) call Check_runtime_completion('START ', 'START ', - \ ['Xextra/', 'Xstartfoo.vim']) - call Check_runtime_completion('START Xextra/', 'START ', - \ ['Xextra/Xstartbar.vim', 'Xextra/Xstartbaz/']) + \ ['Aextra/', 'Astartfoo.vim']) + call Check_runtime_completion('START A', 'START ', + \ ['Aextra/', 'Astartfoo.vim']) + call Check_runtime_completion('START Aextra/', 'START ', + \ ['Aextra/Astartbar.vim', 'Aextra/Astartbaz/']) call Check_runtime_completion('OPT ', 'OPT ', - \ ['Xextra/', 'Xoptfoo.vim']) - call Check_runtime_completion('OPT Xextra/', 'OPT ', - \ ['Xextra/Xoptbar.vim', 'Xextra/Xoptbaz/']) + \ ['Aextra/', 'Aoptfoo.vim']) + call Check_runtime_completion('OPT A', 'OPT ', + \ ['Aextra/', 'Aoptfoo.vim']) + call Check_runtime_completion('OPT Aextra/', 'OPT ', + \ ['Aextra/Aoptbar.vim', 'Aextra/Aoptbaz/']) call Check_runtime_completion('PACK ', 'PACK ', - \ ['Xextra/', 'Xoptfoo.vim', 'Xstartfoo.vim']) - call Check_runtime_completion('PACK Xextra/', 'PACK ', - \ ['Xextra/Xoptbar.vim', 'Xextra/Xoptbaz/', - \ 'Xextra/Xstartbar.vim', 'Xextra/Xstartbaz/']) + \ ['Aextra/', 'Aoptfoo.vim', 'Astartfoo.vim']) + call Check_runtime_completion('PACK A', 'PACK ', + \ ['Aextra/', 'Aoptfoo.vim', 'Astartfoo.vim']) + call Check_runtime_completion('PACK Aextra/', 'PACK ', + \ ['Aextra/Aoptbar.vim', 'Aextra/Aoptbaz/', + \ 'Aextra/Astartbar.vim', 'Aextra/Astartbaz/']) call Check_runtime_completion('ALL ', 'ALL ', - \ ['Xextra/', 'Xoptfoo.vim', 'Xrunfoo.vim', 'Xstartfoo.vim']) - call Check_runtime_completion('ALL Xextra/', 'ALL ', - \ ['Xextra/Xoptbar.vim', 'Xextra/Xoptbaz/', - \ 'Xextra/Xrunbar.vim', 'Xextra/Xrunbaz/', - \ 'Xextra/Xstartbar.vim', 'Xextra/Xstartbaz/']) + \ ['Aextra/', 'Aoptfoo.vim', 'Arunfoo.vim', 'Astartfoo.vim']) + call Check_runtime_completion('ALL A', 'ALL ', + \ ['Aextra/', 'Aoptfoo.vim', 'Arunfoo.vim', 'Astartfoo.vim']) + call Check_runtime_completion('ALL Aextra/', 'ALL ', + \ ['Aextra/Aoptbar.vim', 'Aextra/Aoptbaz/', + \ 'Aextra/Arunbar.vim', 'Aextra/Arunbaz/', + \ 'Aextra/Astartbar.vim', 'Aextra/Astartbaz/']) delfunc Check_runtime_completion endfunc -- cgit From ebc80dcded59b3b9de147091395f7570066fb00c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 10:53:32 +0800 Subject: vim-patch:9.0.1242: code for :runtime completion is not consistent Problem: Code for :runtime completion is not consistent. Solution: Make code for cmdline expansion more consistent. (closes vim/vim#11875) https://github.com/vim/vim/commit/b0d45ec67f4976318f199a7929ad3bcf93686fd0 --- src/nvim/cmdexpand.c | 10 +++++----- src/nvim/option.c | 10 +++++----- src/nvim/testdir/test_packadd.vim | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index 53d513b319..5e4b49db24 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -1212,11 +1212,11 @@ char *addstar(char *fname, size_t len, int context) if (context == EXPAND_HELP || context == EXPAND_CHECKHEALTH || context == EXPAND_COLORS - || context == EXPAND_RUNTIME || context == EXPAND_COMPILER || context == EXPAND_OWNSYNTAX || context == EXPAND_FILETYPE || context == EXPAND_PACKADD + || context == EXPAND_RUNTIME || ((context == EXPAND_TAGS_LISTFILES || context == EXPAND_TAGS) && fname[0] == '/')) { retval = xstrnsave(fname, len); @@ -2074,10 +2074,6 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa xp->xp_pattern = (char *)arg; break; - case CMD_runtime: - set_context_in_runtime_cmd(xp, arg); - break; - case CMD_compiler: xp->xp_context = EXPAND_COMPILER; xp->xp_pattern = (char *)arg; @@ -2098,6 +2094,10 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa xp->xp_pattern = (char *)arg; break; + case CMD_runtime: + set_context_in_runtime_cmd(xp, arg); + break; + #ifdef HAVE_WORKING_LIBINTL case CMD_language: return set_context_in_lang_cmd(xp, arg); diff --git a/src/nvim/option.c b/src/nvim/option.c index 01a5c7677f..ce76b99f8c 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -4824,12 +4824,12 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, char *fuzzystr, int *numM return OK; } -void ExpandOldSetting(int *num_file, char ***file) +void ExpandOldSetting(int *numMatches, char ***matches) { char *var = NULL; - *num_file = 0; - *file = xmalloc(sizeof(char_u *)); + *numMatches = 0; + *matches = xmalloc(sizeof(char *)); // For a terminal key code expand_option_idx is < 0. if (expand_option_idx < 0) { @@ -4862,8 +4862,8 @@ void ExpandOldSetting(int *num_file, char ***file) } #endif - *file[0] = buf; - *num_file = 1; + *matches[0] = buf; + *numMatches = 1; } /// Get the value for the numeric or string option///opp in a nice format into diff --git a/src/nvim/testdir/test_packadd.vim b/src/nvim/testdir/test_packadd.vim index d577f32d55..3121b3b4d1 100644 --- a/src/nvim/testdir/test_packadd.vim +++ b/src/nvim/testdir/test_packadd.vim @@ -26,7 +26,7 @@ func Test_packadd() let rtp_entries = split(rtp, ',') for entry in rtp_entries - if entry =~? '\' + if entry =~? '\' let first_after_entry = entry break endif @@ -186,7 +186,7 @@ func Test_packadd_symlink_dir2() exec "silent !rmdir" top2_dir endfunc -" Check command-line completion for 'packadd' +" Check command-line completion for :packadd func Test_packadd_completion() let optdir1 = &packpath . '/pack/mine/opt' let optdir2 = &packpath . '/pack/candidate/opt' @@ -262,9 +262,9 @@ func Test_helptags() helptags ALL - let tags1 = readfile(docdir1 . '/tags') + let tags1 = readfile(docdir1 . '/tags') call assert_match('look-here', tags1[0]) - let tags2 = readfile(docdir2 . '/tags') + let tags2 = readfile(docdir2 . '/tags') call assert_match('look-away', tags2[0]) call assert_fails('helptags abcxyz', 'E150:') -- cgit From 37b44d17727a03e6a2638da4d16ea85e80069d13 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 14:27:42 +0000 Subject: refactor(option.c): add do_set_num --- src/nvim/option.c | 121 +++++++++++++++++++++++++++++------------------------- 1 file changed, 66 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 01a5c7677f..10773fffde 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -726,6 +726,67 @@ void ex_set(exarg_T *eap) (void)do_set(eap->arg, flags); } +static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, const set_op_T op, + const char *varp, char *errbuf, size_t errbuflen, char **errmsg) +{ + varnumber_T value; + char *arg = *argp; + + // Different ways to set a number option: + // & set to default value + // < set to global value + // accept special key codes for 'wildchar' + // c accept any non-digit for 'wildchar' + // [-]0-9 set number + // other error + arg++; + if (nextchar == '&') { + value = (long)(intptr_t)options[opt_idx].def_val; + } else if (nextchar == '<') { + // For 'undolevels' NO_LOCAL_UNDOLEVEL means to + // use the global value. + if ((long *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL) { + value = NO_LOCAL_UNDOLEVEL; + } else { + value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); + } + } else if (((long *)varp == &p_wc + || (long *)varp == &p_wcm) + && (*arg == '<' + || *arg == '^' + || (*arg != NUL && (!arg[1] || ascii_iswhite(arg[1])) + && !ascii_isdigit(*arg)))) { + value = string_to_key(arg); + if (value == 0 && (long *)varp != &p_wcm) { + *errmsg = e_invarg; + return; + } + } else if (*arg == '-' || ascii_isdigit(*arg)) { + int i; + // Allow negative, octal and hex numbers. + vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true); + if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) { + *errmsg = e_number_required_after_equal; + return; + } + } else { + *errmsg = e_number_required_after_equal; + return; + } + + if (op == OP_ADDING) { + value = *(long *)varp + value; + } + if (op == OP_PREPENDING) { + value = *(long *)varp * value; + } + if (op == OP_REMOVING) { + value = *(long *)varp - value; + } + *errmsg = set_num_option(opt_idx, (char_u *)varp, (long)value, + errbuf, errbuflen, opt_flags); +} + /// Part of do_set() for string options. /// @return FAIL on failure, do not process further options. static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, set_op_T op_arg, @@ -1352,61 +1413,12 @@ int do_set(char *arg, int opt_flags) goto skip; } - if (flags & P_NUM) { // numeric - // Different ways to set a number option: - // & set to default value - // < set to global value - // accept special key codes for 'wildchar' - // c accept any non-digit for 'wildchar' - // [-]0-9 set number - // other error - arg++; - if (nextchar == '&') { - value = (long)(intptr_t)options[opt_idx].def_val; - } else if (nextchar == '<') { - // For 'undolevels' NO_LOCAL_UNDOLEVEL means to - // use the global value. - if ((long *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL) { - value = NO_LOCAL_UNDOLEVEL; - } else { - value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); - } - } else if (((long *)varp == &p_wc - || (long *)varp == &p_wcm) - && (*arg == '<' - || *arg == '^' - || (*arg != NUL && (!arg[1] || ascii_iswhite(arg[1])) - && !ascii_isdigit(*arg)))) { - value = string_to_key(arg); - if (value == 0 && (long *)varp != &p_wcm) { - errmsg = e_invarg; - goto skip; - } - } else if (*arg == '-' || ascii_isdigit(*arg)) { - int i; - // Allow negative, octal and hex numbers. - vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true); - if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) { - errmsg = e_number_required_after_equal; - goto skip; - } - } else { - errmsg = e_number_required_after_equal; + if (flags & P_NUM) { // numeric + do_set_num(opt_idx, opt_flags, &arg, nextchar, op, varp, errbuf, sizeof(errbuf), + &errmsg); + if (errmsg != NULL) { goto skip; } - - if (op == OP_ADDING) { - value = *(long *)varp + value; - } - if (op == OP_PREPENDING) { - value = *(long *)varp * value; - } - if (op == OP_REMOVING) { - value = *(long *)varp - value; - } - errmsg = set_num_option(opt_idx, (char_u *)varp, (long)value, - errbuf, sizeof(errbuf), - opt_flags); } else if (opt_idx >= 0) { // String. if (do_set_string(opt_idx, opt_flags, &arg, nextchar, op, flags, varp, errbuf, sizeof(errbuf), @@ -2245,8 +2257,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf, errmsg = e_positive; } } else if (pp == &p_ch) { - int minval = 0; - if (value < minval) { + if (value < 0) { errmsg = e_positive; } else { p_ch_was_zero = value == 0; -- cgit From ca1ad8977c9e1c79666978aef905c2a2a7f5c16e Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 14:33:23 +0000 Subject: refactor(option.c): add do_set_bool --- src/nvim/option.c | 81 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 10773fffde..c02c30c413 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -726,6 +726,49 @@ void ex_set(exarg_T *eap) (void)do_set(eap->arg, flags); } +static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, int afterchar, + const char *varp, char **errmsg) +{ + if (nextchar == '=' || nextchar == ':') { + *errmsg = e_invarg; + return; + } + + varnumber_T value; + + // ":set opt!": invert + // ":set opt&": reset to default value + // ":set opt<": reset to global value + if (nextchar == '!') { + value = *(int *)(varp) ^ 1; + } else if (nextchar == '&') { + value = (int)(intptr_t)options[opt_idx].def_val; + } else if (nextchar == '<') { + // For 'autoread' -1 means to use global value. + if ((int *)varp == &curbuf->b_p_ar + && opt_flags == OPT_LOCAL) { + value = -1; + } else { + value = *(int *)get_varp_scope(&(options[opt_idx]), + OPT_GLOBAL); + } + } else { + // ":set invopt": invert + // ":set opt" or ":set noopt": set or reset + if (nextchar != NUL && !ascii_iswhite(afterchar)) { + *errmsg = e_trailing; + return; + } + if (prefix == 2) { // inv + value = *(int *)(varp) ^ 1; + } else { + value = prefix; + } + } + + *errmsg = set_bool_option(opt_idx, (char_u *)varp, (int)value, opt_flags); +} + static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, const set_op_T op, const char *varp, char *errbuf, size_t errbuflen, char **errmsg) { @@ -1367,45 +1410,11 @@ int do_set(char *arg, int opt_flags) } } else { int value_checked = false; - varnumber_T value; - if (flags & P_BOOL) { // boolean - if (nextchar == '=' || nextchar == ':') { - errmsg = e_invarg; + do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, &errmsg); + if (errmsg != NULL) { goto skip; } - - // ":set opt!": invert - // ":set opt&": reset to default value - // ":set opt<": reset to global value - if (nextchar == '!') { - value = *(int *)(varp) ^ 1; - } else if (nextchar == '&') { - value = (int)(intptr_t)options[opt_idx].def_val; - } else if (nextchar == '<') { - // For 'autoread' -1 means to use global value. - if ((int *)varp == &curbuf->b_p_ar - && opt_flags == OPT_LOCAL) { - value = -1; - } else { - value = *(int *)get_varp_scope(&(options[opt_idx]), - OPT_GLOBAL); - } - } else { - // ":set invopt": invert - // ":set opt" or ":set noopt": set or reset - if (nextchar != NUL && !ascii_iswhite(afterchar)) { - errmsg = e_trailing; - goto skip; - } - if (prefix == 2) { // inv - value = *(int *)(varp) ^ 1; - } else { - value = prefix; - } - } - - errmsg = set_bool_option(opt_idx, (char_u *)varp, (int)value, opt_flags); } else { // Numeric or string. if (vim_strchr("=:&<", (uint8_t)nextchar) == NULL || prefix != 1) { -- cgit From 9679d058d42c22179fe3cf56e97983b2e67fb3f3 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 14:36:46 +0000 Subject: refactor(option.c): simplify do_set_string --- src/nvim/option.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index c02c30c413..84bc72e834 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -831,10 +831,9 @@ static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, co } /// Part of do_set() for string options. -/// @return FAIL on failure, do not process further options. -static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, set_op_T op_arg, - uint32_t flags, char *varp_arg, char *errbuf, size_t errbuflen, - int *value_checked, char **errmsg) +static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, set_op_T op_arg, + uint32_t flags, char *varp_arg, char *errbuf, size_t errbuflen, + int *value_checked, char **errmsg) { char *arg = *argp; set_op_T op = op_arg; @@ -1163,7 +1162,6 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, xfree(saved_newval); *argp = arg; - return *errmsg == NULL ? OK : FAIL; } /// Parse 'arg' for option settings. @@ -1429,13 +1427,10 @@ int do_set(char *arg, int opt_flags) goto skip; } } else if (opt_idx >= 0) { // String. - if (do_set_string(opt_idx, opt_flags, &arg, nextchar, - op, flags, varp, errbuf, sizeof(errbuf), - &value_checked, &errmsg) == FAIL) { - if (errmsg != NULL) { - goto skip; - } - break; + do_set_string(opt_idx, opt_flags, &arg, nextchar, op, flags, varp, errbuf, + sizeof(errbuf), &value_checked, &errmsg); + if (errmsg != NULL) { + goto skip; } } else { // key code option(FIXME(tarruda): Show a warning or something -- cgit From 18c37c616ec521bb79271c0b51fa198d9f664540 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 14:38:07 +0000 Subject: refactor(option.c): factor out common skip check --- src/nvim/option.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 84bc72e834..d1ecfa0dd7 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1410,9 +1410,6 @@ int do_set(char *arg, int opt_flags) int value_checked = false; if (flags & P_BOOL) { // boolean do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, &errmsg); - if (errmsg != NULL) { - goto skip; - } } else { // Numeric or string. if (vim_strchr("=:&<", (uint8_t)nextchar) == NULL || prefix != 1) { @@ -1423,21 +1420,19 @@ int do_set(char *arg, int opt_flags) if (flags & P_NUM) { // numeric do_set_num(opt_idx, opt_flags, &arg, nextchar, op, varp, errbuf, sizeof(errbuf), &errmsg); - if (errmsg != NULL) { - goto skip; - } } else if (opt_idx >= 0) { // String. do_set_string(opt_idx, opt_flags, &arg, nextchar, op, flags, varp, errbuf, sizeof(errbuf), &value_checked, &errmsg); - if (errmsg != NULL) { - goto skip; - } } else { // key code option(FIXME(tarruda): Show a warning or something // similar) } } + if (errmsg != NULL) { + goto skip; + } + if (opt_idx >= 0) { did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); } -- cgit From e368560c80f162a67dd1ef5369ebaf57fb937de6 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 14:50:29 +0000 Subject: refactor(option.c): factor out loop code from do_set() --- src/nvim/option.c | 456 +++++++++++++++++++++++++++--------------------------- 1 file changed, 230 insertions(+), 226 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index d1ecfa0dd7..5326251d2d 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1164,6 +1164,234 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, *argp = arg; } +static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, + size_t errbuflen, char **errmsg) +{ + int prefix = 1; // 1: nothing, 0: "no", 2: "inv" in front of name + + if (strncmp(*argp, "no", 2) == 0) { + prefix = 0; + *argp += 2; + } else if (strncmp(*argp, "inv", 3) == 0) { + prefix = 2; + *argp += 3; + } + + char *arg = *argp; + + // find end of name + int key = 0; + int len; + int opt_idx; + if (*arg == '<') { + opt_idx = -1; + // look out for ;> + if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4]) { + len = 5; + } else { + len = 1; + while (arg[len] != NUL && arg[len] != '>') { + len++; + } + } + if (arg[len] != '>') { + *errmsg = e_invarg; + return; + } + if (arg[1] == 't' && arg[2] == '_') { // could be term code + opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1)); + } + len++; + if (opt_idx == -1) { + key = find_key_option(arg + 1, true); + } + } else { + len = 0; + // The two characters after "t_" may not be alphanumeric. + if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) { + len = 4; + } else { + while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') { + len++; + } + } + opt_idx = findoption_len((const char *)arg, (size_t)len); + if (opt_idx == -1) { + key = find_key_option(arg, false); + } + } + + // remember character after option name + int afterchar = (uint8_t)arg[len]; + + // skip white space, allow ":set ai ?" + while (ascii_iswhite(arg[len])) { + len++; + } + + set_op_T op = OP_NONE; + if (arg[len] != NUL && arg[len + 1] == '=') { + if (arg[len] == '+') { + op = OP_ADDING; // "+=" + len++; + } else if (arg[len] == '^') { + op = OP_PREPENDING; // "^=" + len++; + } else if (arg[len] == '-') { + op = OP_REMOVING; // "-=" + len++; + } + } + char_u nextchar = (uint8_t)arg[len]; // next non-white char after option name + + if (opt_idx == -1 && key == 0) { // found a mismatch: skip + *errmsg = e_unknown_option; + return; + } + + uint32_t flags; // flags for current option + char *varp = NULL; // pointer to variable for current option + + if (opt_idx >= 0) { + if (options[opt_idx].var == NULL) { // hidden option: skip + // Only give an error message when requesting the value of + // a hidden option, ignore setting it. + if (vim_strchr("=:!&<", (uint8_t)nextchar) == NULL + && (!(options[opt_idx].flags & P_BOOL) + || nextchar == '?')) { + *errmsg = e_unsupportedoption; + } + return; + } + + flags = options[opt_idx].flags; + varp = get_varp_scope(&(options[opt_idx]), opt_flags); + } else { + flags = P_STRING; + } + + // Skip all options that are not window-local (used when showing + // an already loaded buffer in a window). + if ((opt_flags & OPT_WINONLY) + && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) { + return; + } + + // Skip all options that are window-local (used for :vimgrep). + if ((opt_flags & OPT_NOWIN) && opt_idx >= 0 + && options[opt_idx].var == VAR_WIN) { + return; + } + + // Disallow changing some options from modelines. + if (opt_flags & OPT_MODELINE) { + if (flags & (P_SECURE | P_NO_ML)) { + *errmsg = e_not_allowed_in_modeline; + return; + } + if ((flags & P_MLE) && !p_mle) { + *errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off; + return; + } + // In diff mode some options are overruled. This avoids that + // 'foldmethod' becomes "marker" instead of "diff" and that + // "wrap" gets set. + if (curwin->w_p_diff + && opt_idx >= 0 // shut up coverity warning + && (options[opt_idx].indir == PV_FDM + || options[opt_idx].indir == PV_WRAP)) { + return; + } + } + + // Disallow changing some options in the sandbox + if (sandbox != 0 && (flags & P_SECURE)) { + *errmsg = e_sandbox; + return; + } + + if (vim_strchr("?=:!&<", (uint8_t)nextchar) != NULL) { + *argp += len; + if (nextchar == '&' && (*argp)[1] == 'v' && (*argp)[2] == 'i') { + if ((*argp)[3] == 'm') { // "opt&vim": set to Vim default + *argp += 3; + } else { // "opt&vi": set to Vi default + *argp += 2; + } + } + if (vim_strchr("?!&<", (uint8_t)nextchar) != NULL + && (*argp)[1] != NUL && !ascii_iswhite((*argp)[1])) { + *errmsg = e_trailing; + return; + } + } + + // + // allow '=' and ':' as MS-DOS command.com allows only one + // '=' character per "set" command line. grrr. (jw) + // + if (nextchar == '?' + || (prefix == 1 + && vim_strchr("=:&<", (uint8_t)nextchar) == NULL + && !(flags & P_BOOL))) { + // print value + if (*did_show) { + msg_putchar('\n'); // cursor below last one + } else { + gotocmdline(true); // cursor at status line + *did_show = true; // remember that we did a line + } + if (opt_idx >= 0) { + showoneopt(&options[opt_idx], opt_flags); + if (p_verbose > 0) { + // Mention where the option was last set. + if (varp == (char *)options[opt_idx].var) { + option_last_set_msg(options[opt_idx].last_set); + } else if ((int)options[opt_idx].indir & PV_WIN) { + option_last_set_msg(curwin->w_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]); + } else if ((int)options[opt_idx].indir & PV_BUF) { + option_last_set_msg(curbuf->b_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]); + } + } + } else { + *errmsg = e_key_code_not_set; + return; + } + if (nextchar != '?' && nextchar != NUL && !ascii_iswhite(afterchar)) { + *errmsg = e_trailing; + } + } else { + int value_checked = false; + if (flags & P_BOOL) { // boolean + do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); + } else { // Numeric or string. + if (vim_strchr("=:&<", (uint8_t)nextchar) == NULL + || prefix != 1) { + *errmsg = e_invarg; + return; + } + + if (flags & P_NUM) { // numeric + do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); + } else if (opt_idx >= 0) { // String. + do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, + errbuflen, &value_checked, errmsg); + } else { + // key code option(FIXME(tarruda): Show a warning or something + // similar) + } + } + + if (*errmsg != NULL) { + return; + } + + if (opt_idx >= 0) { + did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); + } + } +} + /// Parse 'arg' for option settings. /// /// 'arg' may be IObuff, but only when no errors can be present and option @@ -1181,7 +1409,7 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, /// @return FAIL if an error is detected, OK otherwise int do_set(char *arg, int opt_flags) { - int did_show = false; // already showed one value + bool did_show = false; // already showed one value if (*arg == NUL) { showoptions(0, opt_flags); @@ -1213,232 +1441,8 @@ int do_set(char *arg, int opt_flags) did_show = true; } } else { - int prefix = 1; // 1: nothing, 0: "no", 2: "inv" in front of name - if (strncmp(arg, "no", 2) == 0) { - prefix = 0; - arg += 2; - } else if (strncmp(arg, "inv", 3) == 0) { - prefix = 2; - arg += 3; - } - - // find end of name - int key = 0; - int len; - int opt_idx; - if (*arg == '<') { - opt_idx = -1; - // look out for ;> - if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4]) { - len = 5; - } else { - len = 1; - while (arg[len] != NUL && arg[len] != '>') { - len++; - } - } - if (arg[len] != '>') { - errmsg = e_invarg; - goto skip; - } - if (arg[1] == 't' && arg[2] == '_') { // could be term code - opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1)); - } - len++; - if (opt_idx == -1) { - key = find_key_option(arg + 1, true); - } - } else { - len = 0; - // The two characters after "t_" may not be alphanumeric. - if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) { - len = 4; - } else { - while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') { - len++; - } - } - opt_idx = findoption_len((const char *)arg, (size_t)len); - if (opt_idx == -1) { - key = find_key_option(arg, false); - } - } - - // remember character after option name - int afterchar = (uint8_t)arg[len]; - - // skip white space, allow ":set ai ?" - while (ascii_iswhite(arg[len])) { - len++; - } - - set_op_T op = OP_NONE; - if (arg[len] != NUL && arg[len + 1] == '=') { - if (arg[len] == '+') { - op = OP_ADDING; // "+=" - len++; - } else if (arg[len] == '^') { - op = OP_PREPENDING; // "^=" - len++; - } else if (arg[len] == '-') { - op = OP_REMOVING; // "-=" - len++; - } - } - char_u nextchar = (uint8_t)arg[len]; // next non-white char after option name - - if (opt_idx == -1 && key == 0) { // found a mismatch: skip - errmsg = e_unknown_option; - goto skip; - } - - uint32_t flags; // flags for current option - char *varp = NULL; // pointer to variable for current option - - if (opt_idx >= 0) { - if (options[opt_idx].var == NULL) { // hidden option: skip - // Only give an error message when requesting the value of - // a hidden option, ignore setting it. - if (vim_strchr("=:!&<", (uint8_t)nextchar) == NULL - && (!(options[opt_idx].flags & P_BOOL) - || nextchar == '?')) { - errmsg = e_unsupportedoption; - } - goto skip; - } - - flags = options[opt_idx].flags; - varp = get_varp_scope(&(options[opt_idx]), opt_flags); - } else { - flags = P_STRING; - } - - // Skip all options that are not window-local (used when showing - // an already loaded buffer in a window). - if ((opt_flags & OPT_WINONLY) - && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) { - goto skip; - } - - // Skip all options that are window-local (used for :vimgrep). - if ((opt_flags & OPT_NOWIN) && opt_idx >= 0 - && options[opt_idx].var == VAR_WIN) { - goto skip; - } - - // Disallow changing some options from modelines. - if (opt_flags & OPT_MODELINE) { - if (flags & (P_SECURE | P_NO_ML)) { - errmsg = e_not_allowed_in_modeline; - goto skip; - } - if ((flags & P_MLE) && !p_mle) { - errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off; - goto skip; - } - // In diff mode some options are overruled. This avoids that - // 'foldmethod' becomes "marker" instead of "diff" and that - // "wrap" gets set. - if (curwin->w_p_diff - && opt_idx >= 0 // shut up coverity warning - && (options[opt_idx].indir == PV_FDM - || options[opt_idx].indir == PV_WRAP)) { - goto skip; - } - } - - // Disallow changing some options in the sandbox - if (sandbox != 0 && (flags & P_SECURE)) { - errmsg = e_sandbox; - goto skip; - } - - if (vim_strchr("?=:!&<", (uint8_t)nextchar) != NULL) { - arg += len; - if (nextchar == '&' && arg[1] == 'v' && arg[2] == 'i') { - if (arg[3] == 'm') { // "opt&vim": set to Vim default - arg += 3; - } else { // "opt&vi": set to Vi default - arg += 2; - } - } - if (vim_strchr("?!&<", (uint8_t)nextchar) != NULL - && arg[1] != NUL && !ascii_iswhite(arg[1])) { - errmsg = e_trailing; - goto skip; - } - } - - // - // allow '=' and ':' as MS-DOS command.com allows only one - // '=' character per "set" command line. grrr. (jw) - // - if (nextchar == '?' - || (prefix == 1 - && vim_strchr("=:&<", (uint8_t)nextchar) == NULL - && !(flags & P_BOOL))) { - // print value - if (did_show) { - msg_putchar('\n'); // cursor below last one - } else { - gotocmdline(true); // cursor at status line - did_show = true; // remember that we did a line - } - if (opt_idx >= 0) { - showoneopt(&options[opt_idx], opt_flags); - if (p_verbose > 0) { - // Mention where the option was last set. - if (varp == (char *)options[opt_idx].var) { - option_last_set_msg(options[opt_idx].last_set); - } else if ((int)options[opt_idx].indir & PV_WIN) { - option_last_set_msg(curwin->w_p_script_ctx[ - (int)options[opt_idx].indir & PV_MASK]); - } else if ((int)options[opt_idx].indir & PV_BUF) { - option_last_set_msg(curbuf->b_p_script_ctx[ - (int)options[opt_idx].indir & PV_MASK]); - } - } - } else { - errmsg = e_key_code_not_set; - goto skip; - } - if (nextchar != '?' - && nextchar != NUL && !ascii_iswhite(afterchar)) { - errmsg = e_trailing; - } - } else { - int value_checked = false; - if (flags & P_BOOL) { // boolean - do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, &errmsg); - } else { // Numeric or string. - if (vim_strchr("=:&<", (uint8_t)nextchar) == NULL - || prefix != 1) { - errmsg = e_invarg; - goto skip; - } - - if (flags & P_NUM) { // numeric - do_set_num(opt_idx, opt_flags, &arg, nextchar, op, varp, errbuf, sizeof(errbuf), - &errmsg); - } else if (opt_idx >= 0) { // String. - do_set_string(opt_idx, opt_flags, &arg, nextchar, op, flags, varp, errbuf, - sizeof(errbuf), &value_checked, &errmsg); - } else { - // key code option(FIXME(tarruda): Show a warning or something - // similar) - } - } - - if (errmsg != NULL) { - goto skip; - } - - if (opt_idx >= 0) { - did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); - } - } + do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg); -skip: // Advance to next argument. // - skip until a blank found, taking care of backslashes // - skip blanks -- cgit From 3ae3e47d541db6e2cbf7c42b1ccce9cf48b0e4c9 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 14:53:42 +0000 Subject: refactor(option.c): reduce scope or errmsg --- src/nvim/option.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 5326251d2d..f19d1d1517 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1420,7 +1420,6 @@ int do_set(char *arg, int opt_flags) char errbuf[80]; while (*arg != NUL) { // loop to process all options - char *errmsg = NULL; char *startarg = arg; // remember for error message if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3]) @@ -1441,6 +1440,7 @@ int do_set(char *arg, int opt_flags) did_show = true; } } else { + char *errmsg = NULL; do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg); // Advance to next argument. @@ -1458,26 +1458,26 @@ int do_set(char *arg, int opt_flags) break; } } - } - if (errmsg != NULL) { - xstrlcpy(IObuff, _(errmsg), IOSIZE); - int i = (int)strlen(IObuff) + 2; - if (i + (arg - startarg) < IOSIZE) { - // append the argument with the error - STRCAT(IObuff, ": "); - assert(arg >= startarg); - memmove(IObuff + i, startarg, (size_t)(arg - startarg)); - IObuff[i + (arg - startarg)] = NUL; - } - // make sure all characters are printable - trans_characters(IObuff, IOSIZE); + if (errmsg != NULL) { + xstrlcpy(IObuff, _(errmsg), IOSIZE); + int i = (int)strlen(IObuff) + 2; + if (i + (arg - startarg) < IOSIZE) { + // append the argument with the error + STRCAT(IObuff, ": "); + assert(arg >= startarg); + memmove(IObuff + i, startarg, (size_t)(arg - startarg)); + IObuff[i + (arg - startarg)] = NUL; + } + // make sure all characters are printable + trans_characters(IObuff, IOSIZE); - no_wait_return++; // wait_return() done later - emsg(IObuff); // show error highlighted - no_wait_return--; + no_wait_return++; // wait_return() done later + emsg(IObuff); // show error highlighted + no_wait_return--; - return FAIL; + return FAIL; + } } arg = skipwhite(arg); -- cgit From b93bec68bcd681e06df4f977f4fef3b4ecff2555 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 15:06:32 +0000 Subject: refactor(option.c): reduce scope or errbuf --- src/nvim/option.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index f19d1d1517..535e162e91 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1417,8 +1417,6 @@ int do_set(char *arg, int opt_flags) goto theend; } - char errbuf[80]; - while (*arg != NUL) { // loop to process all options char *startarg = arg; // remember for error message @@ -1441,6 +1439,8 @@ int do_set(char *arg, int opt_flags) } } else { char *errmsg = NULL; + char errbuf[80]; + do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg); // Advance to next argument. -- cgit From bb1efa85aa245b9d21f85fc541530be9f8d6dda4 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 15:12:33 +0000 Subject: refactor(option.c): reduce scope or startarg --- src/nvim/option.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 535e162e91..490ce07c44 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1418,8 +1418,6 @@ int do_set(char *arg, int opt_flags) } while (*arg != NUL) { // loop to process all options - char *startarg = arg; // remember for error message - if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3]) && !(opt_flags & OPT_MODELINE)) { // ":set all" show all options. @@ -1438,6 +1436,7 @@ int do_set(char *arg, int opt_flags) did_show = true; } } else { + char *startarg = arg; // remember for error message char *errmsg = NULL; char errbuf[80]; -- cgit From a13e97ece52a4b6dccda08ec88c035306fd6d24a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 15:19:11 +0000 Subject: refactor(option.c): int -> bool --- src/nvim/option.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 490ce07c44..8df3063fec 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1412,7 +1412,7 @@ int do_set(char *arg, int opt_flags) bool did_show = false; // already showed one value if (*arg == NUL) { - showoptions(0, opt_flags); + showoptions(false, opt_flags); did_show = true; goto theend; } @@ -1432,7 +1432,7 @@ int do_set(char *arg, int opt_flags) ui_refresh_options(); redraw_all_later(UPD_CLEAR); } else { - showoptions(1, opt_flags); + showoptions(true, opt_flags); did_show = true; } } else { @@ -3124,11 +3124,11 @@ static int find_key_option(const char *arg, bool has_lt) return find_key_option_len(arg, strlen(arg), has_lt); } -/// if 'all' == 0: show changed options -/// if 'all' == 1: show all normal options +/// if 'all' == false: show changed options +/// if 'all' == true: show all normal options /// /// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL -static void showoptions(int all, int opt_flags) +static void showoptions(bool all, int opt_flags) { #define INC 20 #define GAP 3 -- cgit From ef85238fde4560ae931dc98ac052a2b5564327fd Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 15:22:31 +0000 Subject: refactor(option.c): remove goto --- src/nvim/option.c | 116 +++++++++++++++++++++++++++--------------------------- 1 file changed, 57 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 8df3063fec..ecec421e90 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1414,75 +1414,73 @@ int do_set(char *arg, int opt_flags) if (*arg == NUL) { showoptions(false, opt_flags); did_show = true; - goto theend; - } - - while (*arg != NUL) { // loop to process all options - if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3]) - && !(opt_flags & OPT_MODELINE)) { - // ":set all" show all options. - // ":set all&" set all options to their default value. - arg += 3; - if (*arg == '&') { - arg++; - // Only for :set command set global value of local options. - set_options_default(OPT_FREE | opt_flags); - didset_options(); - didset_options2(); - ui_refresh_options(); - redraw_all_later(UPD_CLEAR); + } else { + while (*arg != NUL) { // loop to process all options + if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3]) + && !(opt_flags & OPT_MODELINE)) { + // ":set all" show all options. + // ":set all&" set all options to their default value. + arg += 3; + if (*arg == '&') { + arg++; + // Only for :set command set global value of local options. + set_options_default(OPT_FREE | opt_flags); + didset_options(); + didset_options2(); + ui_refresh_options(); + redraw_all_later(UPD_CLEAR); + } else { + showoptions(true, opt_flags); + did_show = true; + } } else { - showoptions(true, opt_flags); - did_show = true; - } - } else { - char *startarg = arg; // remember for error message - char *errmsg = NULL; - char errbuf[80]; - - do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg); - - // Advance to next argument. - // - skip until a blank found, taking care of backslashes - // - skip blanks - // - skip one "=val" argument (for hidden options ":set gfn =xx") - for (int i = 0; i < 2; i++) { - while (*arg != NUL && !ascii_iswhite(*arg)) { - if (*arg++ == '\\' && *arg != NUL) { - arg++; + char *startarg = arg; // remember for error message + char *errmsg = NULL; + char errbuf[80]; + + do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg); + + // Advance to next argument. + // - skip until a blank found, taking care of backslashes + // - skip blanks + // - skip one "=val" argument (for hidden options ":set gfn =xx") + for (int i = 0; i < 2; i++) { + while (*arg != NUL && !ascii_iswhite(*arg)) { + if (*arg++ == '\\' && *arg != NUL) { + arg++; + } + } + arg = skipwhite(arg); + if (*arg != '=') { + break; } } - arg = skipwhite(arg); - if (*arg != '=') { - break; - } - } - if (errmsg != NULL) { - xstrlcpy(IObuff, _(errmsg), IOSIZE); - int i = (int)strlen(IObuff) + 2; - if (i + (arg - startarg) < IOSIZE) { - // append the argument with the error - STRCAT(IObuff, ": "); - assert(arg >= startarg); - memmove(IObuff + i, startarg, (size_t)(arg - startarg)); - IObuff[i + (arg - startarg)] = NUL; - } - // make sure all characters are printable - trans_characters(IObuff, IOSIZE); + if (errmsg != NULL) { + xstrlcpy(IObuff, _(errmsg), IOSIZE); + int i = (int)strlen(IObuff) + 2; + if (i + (arg - startarg) < IOSIZE) { + // append the argument with the error + STRCAT(IObuff, ": "); + assert(arg >= startarg); + memmove(IObuff + i, startarg, (size_t)(arg - startarg)); + IObuff[i + (arg - startarg)] = NUL; + } + // make sure all characters are printable + trans_characters(IObuff, IOSIZE); - no_wait_return++; // wait_return() done later - emsg(IObuff); // show error highlighted - no_wait_return--; + no_wait_return++; // wait_return() done later + emsg(IObuff); // show error highlighted + no_wait_return--; - return FAIL; + return FAIL; + } } - } - arg = skipwhite(arg); + arg = skipwhite(arg); + } } -theend: if (silent_mode && did_show) { // After displaying option values in silent mode. silent_mode = false; -- cgit From 334f5382677b3bcf91e74bb8502d38c7d2bd4281 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 15:41:55 +0000 Subject: refactor(option.c): change nextchar to uint8_t --- src/nvim/option.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index ecec421e90..ac889f2451 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1242,7 +1242,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb len++; } } - char_u nextchar = (uint8_t)arg[len]; // next non-white char after option name + uint8_t nextchar = (uint8_t)arg[len]; // next non-white char after option name if (opt_idx == -1 && key == 0) { // found a mismatch: skip *errmsg = e_unknown_option; @@ -1256,7 +1256,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb if (options[opt_idx].var == NULL) { // hidden option: skip // Only give an error message when requesting the value of // a hidden option, ignore setting it. - if (vim_strchr("=:!&<", (uint8_t)nextchar) == NULL + if (vim_strchr("=:!&<", nextchar) == NULL && (!(options[opt_idx].flags & P_BOOL) || nextchar == '?')) { *errmsg = e_unsupportedoption; @@ -1310,7 +1310,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb return; } - if (vim_strchr("?=:!&<", (uint8_t)nextchar) != NULL) { + if (vim_strchr("?=:!&<", nextchar) != NULL) { *argp += len; if (nextchar == '&' && (*argp)[1] == 'v' && (*argp)[2] == 'i') { if ((*argp)[3] == 'm') { // "opt&vim": set to Vim default @@ -1319,7 +1319,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb *argp += 2; } } - if (vim_strchr("?!&<", (uint8_t)nextchar) != NULL + if (vim_strchr("?!&<", nextchar) != NULL && (*argp)[1] != NUL && !ascii_iswhite((*argp)[1])) { *errmsg = e_trailing; return; @@ -1332,7 +1332,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb // if (nextchar == '?' || (prefix == 1 - && vim_strchr("=:&<", (uint8_t)nextchar) == NULL + && vim_strchr("=:&<", nextchar) == NULL && !(flags & P_BOOL))) { // print value if (*did_show) { @@ -1365,8 +1365,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb if (flags & P_BOOL) { // boolean do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); } else { // Numeric or string. - if (vim_strchr("=:&<", (uint8_t)nextchar) == NULL - || prefix != 1) { + if (vim_strchr("=:&<", nextchar) == NULL || prefix != 1) { *errmsg = e_invarg; return; } -- cgit From 25310af06085c243c2b72a6a0f21cc45ce86a283 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 17:03:15 +0000 Subject: refactor(option.c): use skiptowhite_esc --- src/nvim/option.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index ac889f2451..a4e48f9c02 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1444,11 +1444,7 @@ int do_set(char *arg, int opt_flags) // - skip blanks // - skip one "=val" argument (for hidden options ":set gfn =xx") for (int i = 0; i < 2; i++) { - while (*arg != NUL && !ascii_iswhite(*arg)) { - if (*arg++ == '\\' && *arg != NUL) { - arg++; - } - } + arg = skiptowhite_esc(arg); arg = skipwhite(arg); if (*arg != '=') { break; -- cgit From 0f3fa5a30a6433ab32cfb3aaed946f858f7113a1 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 17:12:21 +0000 Subject: refactor(option.c): factor out set op parsing --- src/nvim/option.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index a4e48f9c02..c511a8e622 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1164,6 +1164,21 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, *argp = arg; } +static set_op_T get_op(const char *arg) +{ + set_op_T op = OP_NONE; + if (*arg != NUL && *(arg + 1) == '=') { + if (*arg == '+') { + op = OP_ADDING; // "+=" + } else if (*arg == '^') { + op = OP_PREPENDING; // "^=" + } else if (*arg == '-') { + op = OP_REMOVING; // "-=" + } + } + return op; +} + static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, size_t errbuflen, char **errmsg) { @@ -1229,19 +1244,11 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb len++; } - set_op_T op = OP_NONE; - if (arg[len] != NUL && arg[len + 1] == '=') { - if (arg[len] == '+') { - op = OP_ADDING; // "+=" - len++; - } else if (arg[len] == '^') { - op = OP_PREPENDING; // "^=" - len++; - } else if (arg[len] == '-') { - op = OP_REMOVING; // "-=" - len++; - } + set_op_T op = get_op(arg + len); + if (op != OP_NONE) { + len++; } + uint8_t nextchar = (uint8_t)arg[len]; // next non-white char after option name if (opt_idx == -1 && key == 0) { // found a mismatch: skip -- cgit From 9a9129c60b76cdfae5752071ec4c998c2f873c7c Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 17:28:21 +0000 Subject: refactor(option.c): factor out option prefix parsing --- src/nvim/option.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index c511a8e622..a54dd4d877 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1179,19 +1179,25 @@ static set_op_T get_op(const char *arg) return op; } -static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, - size_t errbuflen, char **errmsg) +static int get_option_prefix(char **argp) { - int prefix = 1; // 1: nothing, 0: "no", 2: "inv" in front of name - if (strncmp(*argp, "no", 2) == 0) { - prefix = 0; *argp += 2; + return 0; } else if (strncmp(*argp, "inv", 3) == 0) { - prefix = 2; *argp += 3; + return 2; } + return 1; +} + +static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, + size_t errbuflen, char **errmsg) +{ + // 1: nothing, 0: "no", 2: "inv" in front of name + int prefix = get_option_prefix(argp); + char *arg = *argp; // find end of name @@ -1221,11 +1227,11 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb key = find_key_option(arg + 1, true); } } else { - len = 0; // The two characters after "t_" may not be alphanumeric. if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) { len = 4; } else { + len = 0; while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') { len++; } -- cgit From 2c601787ab2fead995fdecce08d0bd21d23eb284 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 25 Jan 2023 17:33:09 +0000 Subject: refactor(option.c): factor out option name parsing --- src/nvim/option.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index a54dd4d877..babbe7e1b3 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1192,18 +1192,18 @@ static int get_option_prefix(char **argp) return 1; } -static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, - size_t errbuflen, char **errmsg) +/// @param[in] arg Pointer to start option name +/// @param[out] opt_idxp Option index in options[] table. +/// @param[out] keyp +/// @param[out] len Length of option name +/// @return FAIL if an error is detected, OK otherwise +static int parse_option_name(char *arg, int *keyp, int *lenp, int *opt_idxp) { - // 1: nothing, 0: "no", 2: "inv" in front of name - int prefix = get_option_prefix(argp); - - char *arg = *argp; - // find end of name int key = 0; int len; int opt_idx; + if (*arg == '<') { opt_idx = -1; // look out for ;> @@ -1216,8 +1216,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb } } if (arg[len] != '>') { - *errmsg = e_invarg; - return; + return FAIL; } if (arg[1] == 't' && arg[2] == '_') { // could be term code opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1)); @@ -1242,6 +1241,30 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb } } + *keyp = key; + *lenp = len; + *opt_idxp = opt_idx; + + return OK; +} + +static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, + size_t errbuflen, char **errmsg) +{ + // 1: nothing, 0: "no", 2: "inv" in front of name + int prefix = get_option_prefix(argp); + + char *arg = *argp; + + // find end of name + int key = 0; + int len; + int opt_idx; + if (parse_option_name(arg, &key, &len, &opt_idx) == FAIL) { + *errmsg = e_invarg; + return; + } + // remember character after option name int afterchar = (uint8_t)arg[len]; -- cgit From e49ae04caf52ac848d090940a36393e4255726c8 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 09:43:11 +0000 Subject: refactor(option.c): factor out opt_idx validation --- src/nvim/option.c | 83 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index babbe7e1b3..4c83eb2a1a 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1248,6 +1248,51 @@ static int parse_option_name(char *arg, int *keyp, int *lenp, int *opt_idxp) return OK; } +static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t flags, char **errmsg) +{ + // Skip all options that are not window-local (used when showing + // an already loaded buffer in a window). + if ((opt_flags & OPT_WINONLY) + && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) { + return FAIL; + } + + // Skip all options that are window-local (used for :vimgrep). + if ((opt_flags & OPT_NOWIN) && opt_idx >= 0 + && options[opt_idx].var == VAR_WIN) { + return FAIL; + } + + // Disallow changing some options from modelines. + if (opt_flags & OPT_MODELINE) { + if (flags & (P_SECURE | P_NO_ML)) { + *errmsg = e_not_allowed_in_modeline; + return FAIL; + } + if ((flags & P_MLE) && !p_mle) { + *errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off; + return FAIL; + } + // In diff mode some options are overruled. This avoids that + // 'foldmethod' becomes "marker" instead of "diff" and that + // "wrap" gets set. + if (win->w_p_diff + && opt_idx >= 0 // shut up coverity warning + && (options[opt_idx].indir == PV_FDM + || options[opt_idx].indir == PV_WRAP)) { + return FAIL; + } + } + + // Disallow changing some options in the sandbox + if (sandbox != 0 && (flags & P_SECURE)) { + *errmsg = e_sandbox; + return FAIL; + } + + return OK; +} + static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, size_t errbuflen, char **errmsg) { @@ -1306,43 +1351,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb flags = P_STRING; } - // Skip all options that are not window-local (used when showing - // an already loaded buffer in a window). - if ((opt_flags & OPT_WINONLY) - && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) { - return; - } - - // Skip all options that are window-local (used for :vimgrep). - if ((opt_flags & OPT_NOWIN) && opt_idx >= 0 - && options[opt_idx].var == VAR_WIN) { - return; - } - - // Disallow changing some options from modelines. - if (opt_flags & OPT_MODELINE) { - if (flags & (P_SECURE | P_NO_ML)) { - *errmsg = e_not_allowed_in_modeline; - return; - } - if ((flags & P_MLE) && !p_mle) { - *errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off; - return; - } - // In diff mode some options are overruled. This avoids that - // 'foldmethod' becomes "marker" instead of "diff" and that - // "wrap" gets set. - if (curwin->w_p_diff - && opt_idx >= 0 // shut up coverity warning - && (options[opt_idx].indir == PV_FDM - || options[opt_idx].indir == PV_WRAP)) { - return; - } - } - - // Disallow changing some options in the sandbox - if (sandbox != 0 && (flags & P_SECURE)) { - *errmsg = e_sandbox; + if (validate_opt_idx(curwin, opt_idx, opt_flags, flags, errmsg) == FAIL) { return; } -- cgit From c6907ea895694ea675ba8c912c3d8e9f67f5c7d4 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 09:47:50 +0000 Subject: refactor(option.c): de-nest code in do_set_option --- src/nvim/option.c | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 4c83eb2a1a..1d5ceb70e6 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1405,35 +1405,36 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb if (nextchar != '?' && nextchar != NUL && !ascii_iswhite(afterchar)) { *errmsg = e_trailing; } - } else { - int value_checked = false; - if (flags & P_BOOL) { // boolean - do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); - } else { // Numeric or string. - if (vim_strchr("=:&<", nextchar) == NULL || prefix != 1) { - *errmsg = e_invarg; - return; - } - - if (flags & P_NUM) { // numeric - do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); - } else if (opt_idx >= 0) { // String. - do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, - errbuflen, &value_checked, errmsg); - } else { - // key code option(FIXME(tarruda): Show a warning or something - // similar) - } - } + return; + } - if (*errmsg != NULL) { + int value_checked = false; + if (flags & P_BOOL) { // boolean + do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); + } else { // Numeric or string. + if (vim_strchr("=:&<", nextchar) == NULL || prefix != 1) { + *errmsg = e_invarg; return; } - if (opt_idx >= 0) { - did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); + if (flags & P_NUM) { // numeric + do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); + } else if (opt_idx >= 0) { // String. + do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, + errbuflen, &value_checked, errmsg); + } else { + // key code option(FIXME(tarruda): Show a warning or something + // similar) } } + + if (*errmsg != NULL) { + return; + } + + if (opt_idx >= 0) { + did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); + } } /// Parse 'arg' for option settings. -- cgit From 0170219e92ce211d935b78895825000f074c4cff Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 09:59:37 +0000 Subject: refactor(option.c): move bool prefix check --- src/nvim/option.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 1d5ceb70e6..50ccf9d302 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1248,8 +1248,15 @@ static int parse_option_name(char *arg, int *keyp, int *lenp, int *opt_idxp) return OK; } -static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t flags, char **errmsg) +static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t flags, int prefix, + char **errmsg) { + // Only bools can have a prefix of 'inv' or 'no' + if (!(flags & P_BOOL) && prefix != 1) { + *errmsg = e_invarg; + return FAIL; + } + // Skip all options that are not window-local (used when showing // an already loaded buffer in a window). if ((opt_flags & OPT_WINONLY) @@ -1351,7 +1358,7 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb flags = P_STRING; } - if (validate_opt_idx(curwin, opt_idx, opt_flags, flags, errmsg) == FAIL) { + if (validate_opt_idx(curwin, opt_idx, opt_flags, flags, prefix, errmsg) == FAIL) { return; } @@ -1408,24 +1415,22 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb return; } + if (!(flags & P_BOOL) && vim_strchr("=:&<", nextchar) == NULL) { + *errmsg = e_invarg; + return; + } + int value_checked = false; - if (flags & P_BOOL) { // boolean + if (flags & P_BOOL) { // boolean do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); - } else { // Numeric or string. - if (vim_strchr("=:&<", nextchar) == NULL || prefix != 1) { - *errmsg = e_invarg; - return; - } - - if (flags & P_NUM) { // numeric - do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); - } else if (opt_idx >= 0) { // String. - do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, - errbuflen, &value_checked, errmsg); - } else { - // key code option(FIXME(tarruda): Show a warning or something - // similar) - } + } else if (flags & P_NUM) { // numeric + do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); + } else if (opt_idx >= 0) { // string. + do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, + errbuflen, &value_checked, errmsg); + } else { + // key code option(FIXME(tarruda): Show a warning or something + // similar) } if (*errmsg != NULL) { -- cgit From 8f2d3537b49846f6e0d27ae5957b57a7ea57e232 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 10:37:05 +0000 Subject: refactor(option.c): add do_set_option_value --- src/nvim/option.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 50ccf9d302..641f07d70b 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1300,6 +1300,32 @@ static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t fla return OK; } +static void do_set_option_value(int opt_idx, int opt_flags, char **argp, int prefix, int nextchar, + int afterchar, set_op_T op, uint32_t flags, char *varp, + char *errbuf, size_t errbuflen, char **errmsg) +{ + int value_checked = false; + if (flags & P_BOOL) { // boolean + do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); + } else if (flags & P_NUM) { // numeric + do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); + } else if (opt_idx >= 0) { // string. + do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, + errbuflen, &value_checked, errmsg); + } else { + // key code option(FIXME(tarruda): Show a warning or something + // similar) + } + + if (*errmsg != NULL) { + return; + } + + if (opt_idx >= 0) { + did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); + } +} + static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf, size_t errbuflen, char **errmsg) { @@ -1420,26 +1446,8 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb return; } - int value_checked = false; - if (flags & P_BOOL) { // boolean - do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); - } else if (flags & P_NUM) { // numeric - do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); - } else if (opt_idx >= 0) { // string. - do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf, - errbuflen, &value_checked, errmsg); - } else { - // key code option(FIXME(tarruda): Show a warning or something - // similar) - } - - if (*errmsg != NULL) { - return; - } - - if (opt_idx >= 0) { - did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked); - } + do_set_option_value(opt_idx, opt_flags, argp, prefix, nextchar, afterchar, op, flags, varp, + errbuf, errbuflen, errmsg); } /// Parse 'arg' for option settings. -- cgit From 41aa5ce3eb49705d26137ac2b34f5ad7cd43f2cf Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 21:05:34 +0800 Subject: vim-patch:9.0.1246: code is indented more than necessary (#22006) Problem: Code is indented more than necessary. Solution: Use an early return where it makes sense. (Yegappan Lakshmanan, closes vim/vim#11887) https://github.com/vim/vim/commit/142ed77898facf8f423fee2717efee1749c55f9a Omit function_using_block_scopes(): only affects Vim9 script. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/userfunc.c | 9 ++++----- src/nvim/undo.c | 8 +++++--- src/nvim/window.c | 30 +++++++++++++++++------------- 3 files changed, 26 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 22c5b1954d..6c6dc3fa43 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -760,13 +760,12 @@ static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force) static bool func_remove(ufunc_T *fp) { hashitem_T *hi = hash_find(&func_hashtab, (char *)UF2HIKEY(fp)); - - if (!HASHITEM_EMPTY(hi)) { - hash_remove(&func_hashtab, hi); - return true; + if (HASHITEM_EMPTY(hi)) { + return false; } - return false; + hash_remove(&func_hashtab, hi); + return true; } static void func_clear_items(ufunc_T *fp) diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 2b0bb1d243..0f12c00f15 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -2985,10 +2985,12 @@ void u_saveline(linenr_T lnum) /// (this is used externally for crossing a line while in insert mode) void u_clearline(void) { - if (curbuf->b_u_line_ptr != NULL) { - XFREE_CLEAR(curbuf->b_u_line_ptr); - curbuf->b_u_line_lnum = 0; + if (curbuf->b_u_line_ptr == NULL) { + return; } + + XFREE_CLEAR(curbuf->b_u_line_ptr); + curbuf->b_u_line_lnum = 0; } /// Implementation of the "U" command. diff --git a/src/nvim/window.c b/src/nvim/window.c index 05f84b5a91..6b40ccdb84 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2599,6 +2599,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev if (!ONE_WINDOW) { return false; } + buf_T *old_curbuf = curbuf; Terminal *term = win->w_buffer ? win->w_buffer->terminal : NULL; @@ -4144,12 +4145,13 @@ int may_open_tabpage(void) { int n = (cmdmod.cmod_tab == 0) ? postponed_split_tab : cmdmod.cmod_tab; - if (n != 0) { - cmdmod.cmod_tab = 0; // reset it to avoid doing it twice - postponed_split_tab = 0; - return win_new_tabpage(n, NULL); + if (n == 0) { + return FAIL; } - return FAIL; + + cmdmod.cmod_tab = 0; // reset it to avoid doing it twice + postponed_split_tab = 0; + return win_new_tabpage(n, NULL); } // Create up to "maxcount" tabpages with empty windows. @@ -4494,11 +4496,12 @@ void goto_tabpage_tp(tabpage_T *tp, bool trigger_enter_autocmds, bool trigger_le /// @return true if the tab page is valid, false otherwise. bool goto_tabpage_lastused(void) { - if (valid_tabpage(lastused_tabpage)) { - goto_tabpage_tp(lastused_tabpage, true, true); - return true; + if (!valid_tabpage(lastused_tabpage)) { + return false; } - return false; + + goto_tabpage_tp(lastused_tabpage, true, true); + return true; } // Enter window "wp" in tab page "tp". @@ -7250,11 +7253,12 @@ static void clear_snapshot(tabpage_T *tp, int idx) static void clear_snapshot_rec(frame_T *fr) { - if (fr != NULL) { - clear_snapshot_rec(fr->fr_next); - clear_snapshot_rec(fr->fr_child); - xfree(fr); + if (fr == NULL) { + return; } + clear_snapshot_rec(fr->fr_next); + clear_snapshot_rec(fr->fr_child); + xfree(fr); } /// Traverse a snapshot to find the previous curwin. -- cgit From 3c2bb1b2bec993cbcd6d65572c531aafbefa25a1 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 15:17:23 +0000 Subject: refactor(fileio.c): reduce scope of locals --- src/nvim/fileio.c | 184 +++++++++++++++++++----------------------------------- 1 file changed, 63 insertions(+), 121 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 9da9d6199e..6b3e7dddb5 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -968,13 +968,11 @@ retry: if (read_buf_lnum > from) { size = 0; } else { - int n, ni; - long tlen; - - tlen = 0; + int ni; + long tlen = 0; for (;;) { p = (char_u *)ml_get(read_buf_lnum) + read_buf_col; - n = (int)strlen((char *)p); + int n = (int)strlen((char *)p); if ((int)tlen + n + 1 > size) { // Filled up to "size", append partial line. // Change NL to NUL to reverse the effect done @@ -2126,7 +2124,6 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en bool errmsg_allocated = false; char *buffer; char smallbuf[SMBUFSIZE]; - char *backup_ext; int bufsize; long perm; // file permissions int retval = OK; @@ -2555,8 +2552,6 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en if ((bkc & BKC_YES) || append) { // "yes" backup_copy = true; } else if ((bkc & BKC_AUTO)) { // "auto" - int i; - // Don't rename the file when: // - it's a hard link // - it's a symbolic link @@ -2571,7 +2566,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en // First find a file name that doesn't exist yet (use some // arbitrary numbers). STRCPY(IObuff, fname); - for (i = 4913;; i += 123) { + for (int i = 4913;; i += 123) { char *tail = path_tail(IObuff); size_t size = (size_t)(tail - IObuff); snprintf(tail, IOSIZE - size, "%d", i); @@ -2624,18 +2619,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en } // make sure we have a valid backup extension to use - if (*p_bex == NUL) { - backup_ext = ".bak"; - } else { - backup_ext = p_bex; - } + char *backup_ext = *p_bex == NUL ? ".bak" : p_bex; if (backup_copy) { - char *wp; int some_error = false; - char *dirp; - char *rootname; - char *p; // Try to make the backup in each directory in the 'bdir' option. // @@ -2647,11 +2634,11 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en // // For these reasons, the existing writable file must be truncated // and reused. Creation of a backup COPY will be attempted. - dirp = p_bdir; + char *dirp = p_bdir; while (*dirp) { // Isolate one directory name, using an entry in 'bdir'. size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ","); - p = IObuff + dir_len; + char *p = IObuff + dir_len; bool trailing_pathseps = after_pathsep(IObuff, p) && p[-1] == p[-2]; if (trailing_pathseps) { IObuff[dir_len - 2] = NUL; @@ -2674,7 +2661,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en } } - rootname = get_file_in_dir(fname, IObuff); + char *rootname = get_file_in_dir(fname, IObuff); if (rootname == NULL) { some_error = true; // out of memory goto nobackup; @@ -2710,7 +2697,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en // delete an existing one, and try to use another name instead. // Change one character, just before the extension. // - wp = backup + strlen(backup) - 1 - strlen(backup_ext); + char *wp = backup + strlen(backup) - 1 - strlen(backup_ext); if (wp < backup) { // empty file name ??? wp = backup; } @@ -2781,10 +2768,6 @@ nobackup: } SET_ERRMSG(NULL); } else { - char *dirp; - char *p; - char *rootname; - // Make a backup by renaming the original file. // If 'cpoptions' includes the "W" flag, we don't want to @@ -2798,11 +2781,11 @@ nobackup: // Form the backup file name - change path/fo.o.h to // path/fo.o.h.bak Try all directories in 'backupdir', first one // that works is used. - dirp = p_bdir; + char *dirp = p_bdir; while (*dirp) { // Isolate one directory name and make the backup file name. size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ","); - p = IObuff + dir_len; + char *p = IObuff + dir_len; bool trailing_pathseps = after_pathsep(IObuff, p) && p[-1] == p[-2]; if (trailing_pathseps) { IObuff[dir_len - 2] = NUL; @@ -2826,7 +2809,7 @@ nobackup: } if (backup == NULL) { - rootname = get_file_in_dir(fname, IObuff); + char *rootname = get_file_in_dir(fname, IObuff); if (rootname == NULL) { backup = NULL; } else { @@ -3690,9 +3673,7 @@ static bool msg_add_fileformat(int eol_type) /// Append line and character count to IObuff. void msg_add_lines(int insert_space, long lnum, off_T nchars) { - char *p; - - p = IObuff + strlen(IObuff); + char *p = IObuff + strlen(IObuff); if (insert_space) { *p++ = ' '; @@ -3758,46 +3739,35 @@ static bool time_differs(const FileInfo *file_info, long mtime, long mtime_ns) F /// @return FAIL for failure, OK otherwise. static int buf_write_bytes(struct bw_info *ip) { - int wlen; - char *buf = ip->bw_buf; // data to write - int len = ip->bw_len; // length of data + char *buf = ip->bw_buf; // data to write + int len = ip->bw_len; // length of data #ifdef HAS_BW_FLAGS - int flags = ip->bw_flags; // extra flags + int flags = ip->bw_flags; // extra flags #endif // Skip conversion when writing the BOM. if (!(flags & FIO_NOCONVERT)) { - char *p; - unsigned c; - int n; - if (flags & FIO_UTF8) { // Convert latin1 in the buffer to UTF-8 in the file. - p = ip->bw_conv_buf; // translate to buffer - for (wlen = 0; wlen < len; wlen++) { + char *p = ip->bw_conv_buf; // translate to buffer + for (int wlen = 0; wlen < len; wlen++) { p += utf_char2bytes((uint8_t)buf[wlen], p); } buf = ip->bw_conv_buf; len = (int)(p - ip->bw_conv_buf); } else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1)) { + unsigned c; + int n = 0; // Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or // Latin1 chars in the file. - if (flags & FIO_LATIN1) { - p = buf; // translate in-place (can only get shorter) - } else { - p = ip->bw_conv_buf; // translate to buffer - } - for (wlen = 0; wlen < len; wlen += n) { + // translate in-place (can only get shorter) or to buffer + char *p = flags & FIO_LATIN1 ? buf : ip->bw_conv_buf; + for (int wlen = 0; wlen < len; wlen += n) { if (wlen == 0 && ip->bw_restlen != 0) { - int l; - // Use remainder of previous call. Append the start of // buf[] to get a full sequence. Might still be too // short! - l = CONV_RESTLEN - ip->bw_restlen; - if (l > len) { - l = len; - } + int l = MIN(len, CONV_RESTLEN - ip->bw_restlen); memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l); n = utf_ptr2len_len((char *)ip->bw_rest, ip->bw_restlen + l); if (n > ip->bw_restlen + len) { @@ -3864,18 +3834,15 @@ static int buf_write_bytes(struct bw_info *ip) if (ip->bw_iconv_fd != (iconv_t)-1) { const char *from; size_t fromlen; - char *to; size_t tolen; // Convert with iconv(). if (ip->bw_restlen > 0) { - char *fp; - // Need to concatenate the remainder of the previous call and // the bytes of the current call. Use the end of the // conversion buffer for this. fromlen = (size_t)len + (size_t)ip->bw_restlen; - fp = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen; + char *fp = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen; memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen); memmove(fp + ip->bw_restlen, buf, (size_t)len); from = fp; @@ -3885,7 +3852,7 @@ static int buf_write_bytes(struct bw_info *ip) fromlen = (size_t)len; tolen = ip->bw_conv_buflen; } - to = ip->bw_conv_buf; + char *to = ip->bw_conv_buf; if (ip->bw_first) { size_t save_len = tolen; @@ -3925,7 +3892,7 @@ static int buf_write_bytes(struct bw_info *ip) // Only checking conversion, which is OK if we get here. return OK; } - wlen = (int)write_eintr(ip->bw_fd, buf, (size_t)len); + int wlen = (int)write_eintr(ip->bw_fd, buf, (size_t)len); return (wlen < len) ? FAIL : OK; } @@ -3940,7 +3907,6 @@ static bool ucs2bytes(unsigned c, char **pp, int flags) FUNC_ATTR_NONNULL_ALL { char_u *p = (char_u *)(*pp); bool error = false; - int cc; if (flags & FIO_UCS4) { if (flags & FIO_ENDIAN_L) { @@ -3963,7 +3929,7 @@ static bool ucs2bytes(unsigned c, char **pp, int flags) FUNC_ATTR_NONNULL_ALL if (c >= 0x100000) { error = true; } - cc = (int)(((c >> 10) & 0x3ff) + 0xd800); + int cc = (int)(((c >> 10) & 0x3ff) + 0xd800); if (flags & FIO_ENDIAN_L) { *p++ = (uint8_t)cc; *p++ = (uint8_t)(cc >> 8); @@ -4006,7 +3972,6 @@ static bool need_conversion(const char *fenc) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { int same_encoding; - int enc_flags; int fenc_flags; if (*fenc == NUL || strcmp(p_enc, fenc) == 0) { @@ -4015,7 +3980,7 @@ static bool need_conversion(const char *fenc) } else { // Ignore difference between "ansi" and "latin1", "ucs-4" and // "ucs-4be", etc. - enc_flags = get_fio_flags(p_enc); + int enc_flags = get_fio_flags(p_enc); fenc_flags = get_fio_flags(fenc); same_encoding = (enc_flags != 0 && fenc_flags == enc_flags); } @@ -4036,12 +4001,10 @@ static bool need_conversion(const char *fenc) /// @param name string to check for encoding static int get_fio_flags(const char *name) { - int prop; - if (*name == NUL) { name = p_enc; } - prop = enc_canon_props(name); + int prop = enc_canon_props(name); if (prop & ENC_UNICODE) { if (prop & ENC_2BYTE) { if (prop & ENC_ENDIAN_L) { @@ -4121,10 +4084,7 @@ static char *check_for_bom(const char *p_in, long size, int *lenp, int flags) /// @return the length of the BOM (zero when no BOM). static int make_bom(char_u *buf, char *name) { - int flags; - char *p; - - flags = get_fio_flags(name); + int flags = get_fio_flags(name); // Can't put a BOM in a non-Unicode file. if (flags == FIO_LATIN1 || flags == 0) { @@ -4137,7 +4097,7 @@ static int make_bom(char_u *buf, char *name) buf[2] = 0xbf; return 3; } - p = (char *)buf; + char *p = (char *)buf; (void)ucs2bytes(0xfeff, &p, flags); return (int)((char_u *)p - buf); } @@ -4153,8 +4113,6 @@ static int make_bom(char_u *buf, char *name) /// name. void shorten_buf_fname(buf_T *buf, char *dirname, int force) { - char *p; - if (buf->b_fname != NULL && !bt_nofilename(buf) && !path_with_url(buf->b_fname) @@ -4164,7 +4122,7 @@ void shorten_buf_fname(buf_T *buf, char *dirname, int force) if (buf->b_sfname != buf->b_ffname) { XFREE_CLEAR(buf->b_sfname); } - p = path_shorten_fname(buf->b_ffname, dirname); + char *p = path_shorten_fname(buf->b_ffname, dirname); if (p != NULL) { buf->b_sfname = xstrdup(p); buf->b_fname = buf->b_sfname; @@ -4461,10 +4419,7 @@ int vim_rename(const char *from, const char *to) { int fd_in; int fd_out; - int n; char *errmsg = NULL; - char *buffer; - long perm; #ifdef HAVE_ACL vim_acl_T acl; // ACL from original file #endif @@ -4506,7 +4461,7 @@ int vim_rename(const char *from, const char *to) return -1; } STRCPY(tempname, from); - for (n = 123; n < 99999; n++) { + for (int n = 123; n < 99999; n++) { char *tail = path_tail(tempname); snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - tempname - 1)), "%d", n); @@ -4540,7 +4495,7 @@ int vim_rename(const char *from, const char *to) } // Rename() failed, try copying the file. - perm = os_getperm(from); + long perm = os_getperm(from); #ifdef HAVE_ACL // For systems that support ACL: get the ACL from the original file. acl = os_get_acl(from); @@ -4566,7 +4521,7 @@ int vim_rename(const char *from, const char *to) // Avoid xmalloc() here as vim_rename() is called by buf_write() when nvim // is `preserve_exit()`ing. - buffer = try_malloc(BUFSIZE); + char *buffer = try_malloc(BUFSIZE); if (buffer == NULL) { close(fd_out); close(fd_in); @@ -4576,6 +4531,7 @@ int vim_rename(const char *from, const char *to) return -1; } + int n; while ((n = (int)read_eintr(fd_in, buffer, BUFSIZE)) > 0) { if (write_eintr(fd_out, buffer, (size_t)n) != n) { errmsg = _("E208: Error writing to \"%s\""); @@ -4619,8 +4575,6 @@ static int already_warned = false; /// @return true if some message was written (screen should be redrawn and cursor positioned). int check_timestamps(int focus) { - int didit = 0; - // Don't check timestamps while system() or another low-level function may // cause us to lose and gain focus. if (no_check_timestamps > 0) { @@ -4635,6 +4589,8 @@ int check_timestamps(int focus) return false; } + int didit = 0; + if (!stuff_empty() || global_busy || !typebuf_typed() || autocmd_busy || curbuf->b_ro_locked > 0 || allbuf_lock > 0) { @@ -4678,13 +4634,11 @@ static int move_lines(buf_T *frombuf, buf_T *tobuf) { buf_T *tbuf = curbuf; int retval = OK; - linenr_T lnum; - char *p; // Copy the lines in "frombuf" to "tobuf". curbuf = tobuf; - for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; lnum++) { - p = xstrdup(ml_get_buf(frombuf, lnum, false)); + for (linenr_T lnum = 1; lnum <= frombuf->b_ml.ml_line_count; lnum++) { + char *p = xstrdup(ml_get_buf(frombuf, lnum, false)); if (ml_append(lnum - 1, p, 0, false) == FAIL) { xfree(p); retval = FAIL; @@ -4696,7 +4650,7 @@ static int move_lines(buf_T *frombuf, buf_T *tobuf) // Delete all the lines in "frombuf". if (retval != FAIL) { curbuf = frombuf; - for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; lnum--) { + for (linenr_T lnum = curbuf->b_ml.ml_line_count; lnum > 0; lnum--) { if (ml_delete(lnum, false) == FAIL) { // Oops! We could try putting back the saved lines, but that // might fail again... @@ -4720,7 +4674,6 @@ int buf_check_timestamp(buf_T *buf) FUNC_ATTR_NONNULL_ALL { int retval = 0; - char *path; char *mesg = NULL; char *mesg2 = ""; bool helpmesg = false; @@ -4735,8 +4688,6 @@ int buf_check_timestamp(buf_T *buf) uint64_t orig_size = buf->b_orig_size; int orig_mode = buf->b_orig_mode; static bool busy = false; - char *s; - char *reason; bufref_T bufref; set_bufref(&bufref, buf); @@ -4784,6 +4735,7 @@ int buf_check_timestamp(buf_T *buf) // was set, the global option value otherwise. reload = RELOAD_NORMAL; } else { + char *reason; if (!file_info_ok) { reason = "deleted"; } else if (bufIsChanged(buf)) { @@ -4810,7 +4762,7 @@ int buf_check_timestamp(buf_T *buf) if (!bufref_valid(&bufref)) { emsg(_("E246: FileChangedShell autocommand deleted buffer")); } - s = get_vim_var_str(VV_FCS_CHOICE); + char *s = get_vim_var_str(VV_FCS_CHOICE); if (strcmp(s, "reload") == 0 && *reason != 'd') { reload = RELOAD_NORMAL; } else if (strcmp(s, "edit") == 0) { @@ -4863,7 +4815,7 @@ int buf_check_timestamp(buf_T *buf) } if (mesg != NULL) { - path = home_replace_save(buf, buf->b_fname); + char *path = home_replace_save(buf, buf->b_fname); if (!helpmesg) { mesg2 = ""; } @@ -4946,8 +4898,6 @@ int buf_check_timestamp(buf_T *buf) void buf_reload(buf_T *buf, int orig_mode, bool reload_options) { exarg_T ea; - pos_T old_cursor; - linenr_T old_topline; int old_ro = buf->b_p_ro; buf_T *savebuf; bufref_T bufref; @@ -4967,8 +4917,8 @@ void buf_reload(buf_T *buf, int orig_mode, bool reload_options) prep_exarg(&ea, buf); } - old_cursor = curwin->w_cursor; - old_topline = curwin->w_topline; + pos_T old_cursor = curwin->w_cursor; + linenr_T old_topline = curwin->w_topline; if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) { // Save all the text, so that the reload can be undone. @@ -5454,24 +5404,19 @@ bool match_file_pat(char *pattern, regprog_T **prog, char *fname, char *sfname, bool match_file_list(char *list, char *sfname, char *ffname) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 3) { - char buf[100]; - char *tail; - char *regpat; - char allow_dirs; - bool match; - char *p; - - tail = path_tail(sfname); + char *tail = path_tail(sfname); // try all patterns in 'wildignore' - p = list; + char *p = list; while (*p) { + char buf[100]; copy_option_part(&p, buf, ARRAY_SIZE(buf), ","); - regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, false); + char allow_dirs; + char *regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, false); if (regpat == NULL) { break; } - match = match_file_pat(regpat, NULL, ffname, sfname, tail, (int)allow_dirs); + bool match = match_file_pat(regpat, NULL, ffname, sfname, tail, (int)allow_dirs); xfree(regpat); if (match) { return true; @@ -5494,15 +5439,6 @@ bool match_file_list(char *list, char *sfname, char *ffname) char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs, int no_bslash) FUNC_ATTR_NONNULL_ARG(1) { - const char *endp; - char *reg_pat; - const char *p; - int nested = 0; - bool add_dollar = true; - - if (allow_dirs != NULL) { - *allow_dirs = false; - } if (pat_end == NULL) { pat_end = pat + strlen(pat); } @@ -5511,9 +5447,13 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs return xstrdup("^$"); } + if (allow_dirs != NULL) { + *allow_dirs = false; + } + size_t size = 2; // '^' at start, '$' at end. - for (p = pat; p < pat_end; p++) { + for (const char *p = pat; p < pat_end; p++) { switch (*p) { case '*': case '.': @@ -5534,7 +5474,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs break; } } - reg_pat = xmalloc(size + 1); + char *reg_pat = xmalloc(size + 1); size_t i = 0; @@ -5545,14 +5485,16 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs } else { reg_pat[i++] = '^'; } - endp = pat_end - 1; + const char *endp = pat_end - 1; + bool add_dollar = true; if (endp >= pat && *endp == '*') { while (endp - pat > 0 && *endp == '*') { endp--; } add_dollar = false; } - for (p = pat; *p && nested >= 0 && p <= endp; p++) { + int nested = 0; + for (const char *p = pat; *p && nested >= 0 && p <= endp; p++) { switch (*p) { case '*': reg_pat[i++] = '.'; -- cgit From 843c9025ae8b44b14d0908674c8874a51dc13a38 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Thu, 26 Jan 2023 21:35:06 +0100 Subject: build: check if libvterm version meets requirement (#22010) The vterm.h file only specifies major and minor version, but not patch, meaning that requiring a specific patch number isn't currently possible. --- src/nvim/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 2361210e59..faeef65261 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -30,9 +30,8 @@ find_package(LibTermkey 0.22 REQUIRED) target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBTERMKEY_INCLUDE_DIRS}) target_link_libraries(main_lib INTERFACE ${LIBTERMKEY_LIBRARIES}) -find_package(LIBVTERM 0.3 REQUIRED) -target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBVTERM_INCLUDE_DIRS}) -target_link_libraries(main_lib INTERFACE ${LIBVTERM_LIBRARIES}) +find_package(libvterm 0.3 REQUIRED) +target_link_libraries(main_lib INTERFACE libvterm) find_package(Iconv REQUIRED) target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${Iconv_INCLUDE_DIRS}) -- cgit From 9b43dcdbff4fd9418a66a4b356e3cb8a11762971 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 27 Jan 2023 09:48:00 +0000 Subject: fix(test): unset XDG_CONFIG_HOME when running oldtest - also fix test_taglist.vim for users running with a tags file created in runtime/doc --- src/nvim/testdir/runnvim.sh | 3 +++ src/nvim/testdir/test_taglist.vim | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/runnvim.sh b/src/nvim/testdir/runnvim.sh index 322265737a..3a0a94b6bf 100755 --- a/src/nvim/testdir/runnvim.sh +++ b/src/nvim/testdir/runnvim.sh @@ -30,6 +30,9 @@ main() {( . "$CI_DIR/common/suite.sh" . "$CI_DIR/common/test.sh" + # Redirect XDG_CONFIG_HOME so users local config doesn't interfere + export XDG_CONFIG_HOME="$root" + export VIMRUNTIME="$root/runtime" if ! "$nvim_prg" \ -u NONE -i NONE \ diff --git a/src/nvim/testdir/test_taglist.vim b/src/nvim/testdir/test_taglist.vim index 0387ef2bd8..75d28c3ec4 100644 --- a/src/nvim/testdir/test_taglist.vim +++ b/src/nvim/testdir/test_taglist.vim @@ -105,8 +105,8 @@ func Test_tagfiles() help let tf = tagfiles() " Nvim: expectation(s) based on tags in build dir (added to &rtp). - " Filter out the (non-existing) '../../../runtime/doc/tags'. - call filter(tf, 'filereadable(v:val)') + " Filter out the '../../../runtime/doc/tags'. + call filter(tf, 'v:val != "../../../runtime/doc/tags"') call assert_equal(1, len(tf)) call assert_equal(fnamemodify(expand('$BUILD_DIR/runtime/doc/tags'), ':p:gs?\\?/?'), \ fnamemodify(tf[0], ':p:gs?\\?/?')) -- cgit From 068151f5c69c9ba5e7d80101ccc62b4aea138a04 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 11:02:00 +0000 Subject: refactor(option.c): factor out some nextchar checks --- src/nvim/option.c | 53 ++++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 641f07d70b..64128333a9 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -726,14 +726,9 @@ void ex_set(exarg_T *eap) (void)do_set(eap->arg, flags); } -static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, int afterchar, - const char *varp, char **errmsg) +static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, const char *varp, + char **errmsg) { - if (nextchar == '=' || nextchar == ':') { - *errmsg = e_invarg; - return; - } - varnumber_T value; // ":set opt!": invert @@ -745,24 +740,16 @@ static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, in value = (int)(intptr_t)options[opt_idx].def_val; } else if (nextchar == '<') { // For 'autoread' -1 means to use global value. - if ((int *)varp == &curbuf->b_p_ar - && opt_flags == OPT_LOCAL) { + if ((int *)varp == &curbuf->b_p_ar && opt_flags == OPT_LOCAL) { value = -1; } else { - value = *(int *)get_varp_scope(&(options[opt_idx]), - OPT_GLOBAL); + value = *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); } } else { - // ":set invopt": invert - // ":set opt" or ":set noopt": set or reset - if (nextchar != NUL && !ascii_iswhite(afterchar)) { - *errmsg = e_trailing; - return; - } - if (prefix == 2) { // inv - value = *(int *)(varp) ^ 1; + if (prefix == 2) { + value = *(int *)varp ^ 1; // ":set invopt": invert } else { - value = prefix; + value = prefix; // ":set opt" or ":set noopt": set or reset } } @@ -1301,12 +1288,12 @@ static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t fla } static void do_set_option_value(int opt_idx, int opt_flags, char **argp, int prefix, int nextchar, - int afterchar, set_op_T op, uint32_t flags, char *varp, - char *errbuf, size_t errbuflen, char **errmsg) + set_op_T op, uint32_t flags, char *varp, char *errbuf, + size_t errbuflen, char **errmsg) { int value_checked = false; if (flags & P_BOOL) { // boolean - do_set_bool(opt_idx, opt_flags, prefix, nextchar, afterchar, varp, errmsg); + do_set_bool(opt_idx, opt_flags, prefix, nextchar, varp, errmsg); } else if (flags & P_NUM) { // numeric do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg); } else if (opt_idx >= 0) { // string. @@ -1441,12 +1428,24 @@ static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errb return; } - if (!(flags & P_BOOL) && vim_strchr("=:&<", nextchar) == NULL) { - *errmsg = e_invarg; - return; + if (flags & P_BOOL) { + if (vim_strchr("=:", nextchar) != NULL) { + *errmsg = e_invarg; + return; + } + + if (vim_strchr("!&<", nextchar) == NULL && nextchar != NUL && !ascii_iswhite(afterchar)) { + *errmsg = e_trailing; + return; + } + } else { + if (vim_strchr("=:&<", nextchar) == NULL) { + *errmsg = e_invarg; + return; + } } - do_set_option_value(opt_idx, opt_flags, argp, prefix, nextchar, afterchar, op, flags, varp, + do_set_option_value(opt_idx, opt_flags, argp, prefix, nextchar, op, flags, varp, errbuf, errbuflen, errmsg); } -- cgit From 77a0ce1d9b7c6c223fedec043cdd7379d0047bf8 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 26 Jan 2023 11:17:36 +0000 Subject: refactor(option.c): factor out string option special case handling --- src/nvim/option.c | 138 +++++++++++++++++++++++++++++------------------------- 1 file changed, 74 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 64128333a9..b8e234981a 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -817,6 +817,78 @@ static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, co errbuf, errbuflen, opt_flags); } +// Handle some special cases with string option values +static void munge_string_opt_val(char **varp, char **oldval, char **const origval, + char_u **const origval_l, char_u **const origval_g, + char **const argp, char *const whichwrap, size_t whichwraplen, + char **const save_argp) +{ + // Set 'keywordprg' to ":help" if an empty + // value was passed to :set by the user. + if (varp == &p_kp && (**argp == NUL || **argp == ' ')) { + *save_argp = *argp; + *argp = ":help"; + } else if (varp == &p_bs && ascii_isdigit(**(char_u **)varp)) { + // Convert 'backspace' number to string, for + // adding, prepending and removing string. + const int i = getdigits_int(varp, true, 0); + switch (i) { + case 0: + *varp = empty_option; + break; + case 1: + *varp = xstrdup("indent,eol"); + break; + case 2: + *varp = xstrdup("indent,eol,start"); + break; + case 3: + *varp = xstrdup("indent,eol,nostop"); + break; + } + xfree(*oldval); + if (*origval == *oldval) { + *origval = *varp; + } + if (*origval_l == (char_u *)(*oldval)) { + *origval_l = *(char_u **)varp; + } + if (*origval_g == (char_u *)(*oldval)) { + *origval_g = *(char_u **)varp; + } + *oldval = *varp; + } else if (varp == &p_ww && ascii_isdigit(**argp)) { + // Convert 'whichwrap' number to string, for backwards compatibility + // with Vim 3.0. + *whichwrap = NUL; + int i = getdigits_int(argp, true, 0); + if (i & 1) { + xstrlcat(whichwrap, "b,", whichwraplen); + } + if (i & 2) { + xstrlcat(whichwrap, "s,", whichwraplen); + } + if (i & 4) { + xstrlcat(whichwrap, "h,l,", whichwraplen); + } + if (i & 8) { + xstrlcat(whichwrap, "<,>,", whichwraplen); + } + if (i & 16) { + xstrlcat(whichwrap, "[,],", whichwraplen); + } + if (*whichwrap != NUL) { // remove trailing , + whichwrap[strlen(whichwrap) - 1] = NUL; + } + *save_argp = *argp; + *argp = whichwrap; + } else if (**argp == '>' && (varp == &p_dir || varp == &p_bdir)) { + // Remove '>' before 'dir' and 'bdir', for backwards compatibility with + // version 3.0 + (*argp)++; + } +} + /// Part of do_set() for string options. static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, set_op_T op_arg, uint32_t flags, char *varp_arg, char *errbuf, size_t errbuflen, @@ -884,70 +956,8 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, } else { arg++; // jump to after the '=' or ':' - // Set 'keywordprg' to ":help" if an empty - // value was passed to :set by the user. - if (varp == (char *)&p_kp && (*arg == NUL || *arg == ' ')) { - save_arg = arg; - arg = ":help"; - } else if (varp == (char *)&p_bs && ascii_isdigit(**(char_u **)varp)) { - // Convert 'backspace' number to string, for - // adding, prepending and removing string. - int i = getdigits_int((char **)varp, true, 0); - switch (i) { - case 0: - *(char **)varp = empty_option; - break; - case 1: - *(char_u **)varp = (char_u *)xstrdup("indent,eol"); - break; - case 2: - *(char_u **)varp = (char_u *)xstrdup("indent,eol,start"); - break; - case 3: - *(char_u **)varp = (char_u *)xstrdup("indent,eol,nostop"); - break; - } - xfree(oldval); - if (origval == oldval) { - origval = *(char **)varp; - } - if (origval_l == (char_u *)oldval) { - origval_l = *(char_u **)varp; - } - if (origval_g == (char_u *)oldval) { - origval_g = *(char_u **)varp; - } - oldval = *(char **)varp; - } else if (varp == (char *)&p_ww && ascii_isdigit(*arg)) { - // Convert 'whichwrap' number to string, for backwards compatibility - // with Vim 3.0. - *whichwrap = NUL; - int i = getdigits_int(&arg, true, 0); - if (i & 1) { - xstrlcat(whichwrap, "b,", sizeof(whichwrap)); - } - if (i & 2) { - xstrlcat(whichwrap, "s,", sizeof(whichwrap)); - } - if (i & 4) { - xstrlcat(whichwrap, "h,l,", sizeof(whichwrap)); - } - if (i & 8) { - xstrlcat(whichwrap, "<,>,", sizeof(whichwrap)); - } - if (i & 16) { - xstrlcat(whichwrap, "[,],", sizeof(whichwrap)); - } - if (*whichwrap != NUL) { // remove trailing , - whichwrap[strlen(whichwrap) - 1] = NUL; - } - save_arg = arg; - arg = whichwrap; - } else if (*arg == '>' && (varp == (char *)&p_dir || varp == (char *)&p_bdir)) { - // Remove '>' before 'dir' and 'bdir', for backwards compatibility with - // version 3.0 - arg++; - } + munge_string_opt_val((char **)varp, &oldval, &origval, &origval_l, &origval_g, &arg, + whichwrap, sizeof(whichwrap), &save_arg); // Copy the new string into allocated memory. // Can't use set_string_option_direct(), because we need to remove the -- cgit From d85ed00a8cc2274eff4409e2b18ba34178ae567a Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Fri, 27 Jan 2023 11:53:32 +0100 Subject: build: find unibilium without relying on libfindmacros (#22015) This will remove the warning about the find module not providing a version. --- src/nvim/CMakeLists.txt | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index faeef65261..77ed0490d8 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -22,9 +22,8 @@ find_package(TreeSitter REQUIRED) target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${TreeSitter_INCLUDE_DIRS}) target_link_libraries(main_lib INTERFACE ${TreeSitter_LIBRARIES}) -find_package(UNIBILIUM 2.0 REQUIRED) -target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${UNIBILIUM_INCLUDE_DIRS}) -target_link_libraries(main_lib INTERFACE ${UNIBILIUM_LIBRARIES}) +find_package(unibilium 2.0 REQUIRED) +target_link_libraries(main_lib INTERFACE unibilium) find_package(LibTermkey 0.22 REQUIRED) target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBTERMKEY_INCLUDE_DIRS}) @@ -174,24 +173,6 @@ if(CI_BUILD) endif() endif() -list(APPEND CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}") -list(APPEND CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}") -check_c_source_compiles(" -#include - -int -main(void) -{ - unibi_str_from_var(unibi_var_from_str(\"\")); - return unibi_num_from_var(unibi_var_from_num(0)); -} -" UNIBI_HAS_VAR_FROM) -list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}") -list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}") -if(UNIBI_HAS_VAR_FROM) - target_compile_definitions(main_lib INTERFACE NVIM_UNIBI_HAS_VAR_FROM) -endif() - list(APPEND CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}") check_c_source_compiles(" #include -- cgit From aec4b476c5689f032103ab3e0ca068fc2af8bbba Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 27 Jan 2023 11:24:20 +0000 Subject: docs(api): tweak data arg for nvim_create_autocmd (#22008) Fixes #21964 --- src/nvim/api/autocmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index 931363e199..a2cb297b15 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -404,7 +404,7 @@ cleanup: /// - match: (string) expanded value of || /// - buf: (number) expanded value of || /// - file: (string) expanded value of || -/// - data: (any) arbitrary data passed to |nvim_exec_autocmds()| +/// - data: (any) arbitrary data passed from |nvim_exec_autocmds()| /// - command (string) optional: Vim command to execute on event. Cannot be used with /// {callback} /// - once (boolean) optional: defaults to false. Run the autocommand -- cgit From 881d4adb5942301a26ccd45315e146eccb114519 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 28 Jan 2023 00:42:13 +0100 Subject: build: enable ccache by default if available (#22020) Initial benchmarks show that this gives a nice 50% compile time reduction for neovim. This shouldn't affect users or CI, but it's a nice speedup for local development. The C_COMPILER_LAUNCHER target property is only supported by Makefiles and Ninja generators only, so this won't give a speedup when using the Xcode and Visual Studio generators even if ccache is available. --- src/nvim/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 77ed0490d8..d1bf08f3fb 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -688,6 +688,13 @@ set_target_properties(nvim EXPORT_COMPILE_COMMANDS ON ENABLE_EXPORTS TRUE) +find_program(CCACHE_PRG ccache) +if(CCACHE_PRG) + set_target_properties(nvim + PROPERTIES + C_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;CCACHE_SLOPPINESS=pch_defines,time_macros;${CCACHE_PRG}") +endif() + if(${CMAKE_VERSION} VERSION_LESS 3.20) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) endif() -- cgit From b4c4c232ba6fe3df5c6f12faff4405a16e4d40df Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 28 Jan 2023 13:06:45 +0800 Subject: fix(fileio.c): don't use uninitialized memory (#22031) --- src/nvim/fileio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 6b3e7dddb5..fbb5c4f1fa 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -5439,6 +5439,10 @@ bool match_file_list(char *list, char *sfname, char *ffname) char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs, int no_bslash) FUNC_ATTR_NONNULL_ARG(1) { + if (allow_dirs != NULL) { + *allow_dirs = false; + } + if (pat_end == NULL) { pat_end = pat + strlen(pat); } @@ -5447,10 +5451,6 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs return xstrdup("^$"); } - if (allow_dirs != NULL) { - *allow_dirs = false; - } - size_t size = 2; // '^' at start, '$' at end. for (const char *p = pat; p < pat_end; p++) { -- cgit From 4c90a84c61d19e5131579b2c38960de3ec8e4a5e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 29 Jan 2023 07:42:22 +0800 Subject: vim-patch:9.0.1255: changing 'virtualedit' does not have immediate effect (#22039) Problem: Changing 'virtualedit' does not have immediate effect. Solution: Correct how is checked for a changed value. (closes vim/vim#11878) https://github.com/vim/vim/commit/8fe5b9c8c1223861cec0484ccc031858ae08d107 Co-authored-by: Bram Moolenaar --- src/nvim/optionstr.c | 3 ++- src/nvim/testdir/test_virtualedit.vim | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 5ebff9ed77..30afb0db37 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1404,10 +1404,11 @@ static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, char ** } else { if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) { *errmsg = e_invarg; - } else if (strcmp(p_ve, oldval) != 0) { + } else if (strcmp(ve, oldval) != 0) { // Recompute cursor position in case the new 've' setting // changes something. validate_virtcol_win(win); + // XXX: this only works when win == curwin coladvance(win->w_virtcol); } } diff --git a/src/nvim/testdir/test_virtualedit.vim b/src/nvim/testdir/test_virtualedit.vim index 2bf8c3fc77..20a5f87517 100644 --- a/src/nvim/testdir/test_virtualedit.vim +++ b/src/nvim/testdir/test_virtualedit.vim @@ -537,6 +537,19 @@ func Test_global_local_virtualedit() set virtualedit& endfunc +func Test_virtualedit_setlocal() + enew + setglobal virtualedit=all + setlocal virtualedit=all + normal! l + redraw + setlocal virtualedit=none + call assert_equal(1, wincol()) + + setlocal virtualedit& + set virtualedit& +endfunc + func Test_virtualedit_mouse() let save_mouse = &mouse set mouse=a -- cgit From 8144deb0989ea5c61fe9a1a5802d230eba33dfdd Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sun, 29 Jan 2023 10:39:20 +0100 Subject: vim-patch:9.0.1256: NetworkManager connection files are not recognized (#22038) Problem: NetworkManager connection files are not recognized. Solution: Add a pattern for NetworkManager connection files. (closes vim/vim#11893) https://github.com/vim/vim/commit/04e4f1d98556e67d7337224b67b71c828410ee0f Co-authored-by: ObserverOfTime --- src/nvim/testdir/test_filetype.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index cddb1349f5..a4fbe48249 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -123,7 +123,7 @@ let s:filename_checks = { \ 'conaryrecipe': ['file.recipe'], \ 'conf': ['auto.master'], \ 'config': ['configure.in', 'configure.ac', '/etc/hostname.file', 'any/etc/hostname.file'], - \ 'confini': ['/etc/pacman.conf', 'any/etc/pacman.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials'], + \ 'confini': ['/etc/pacman.conf', 'any/etc/pacman.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials', 'file.nmconnection'], \ 'context': ['tex/context/any/file.tex', 'file.mkii', 'file.mkiv', 'file.mkvi', 'file.mkxl', 'file.mklx'], \ 'cook': ['file.cook'], \ 'cpp': ['file.cxx', 'file.c++', 'file.hh', 'file.hxx', 'file.hpp', 'file.ipp', 'file.moc', 'file.tcc', 'file.inl', 'file.tlh'], -- cgit From 930125647fd99de78b6845f9a4db637ae4517b84 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 29 Jan 2023 17:02:34 +0100 Subject: build: enable ccache project-wide (#22045) Currently, only the nvim target uses ccache but not libnvim or unittests. It is generally a good idea to operate on targets rather than globally, but this is an exception as there isn't a target where we don't want to use ccache on. --- src/nvim/CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index d1bf08f3fb..77ed0490d8 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -688,13 +688,6 @@ set_target_properties(nvim EXPORT_COMPILE_COMMANDS ON ENABLE_EXPORTS TRUE) -find_program(CCACHE_PRG ccache) -if(CCACHE_PRG) - set_target_properties(nvim - PROPERTIES - C_COMPILER_LAUNCHER "${CMAKE_COMMAND};-E;env;CCACHE_SLOPPINESS=pch_defines,time_macros;${CCACHE_PRG}") -endif() - if(${CMAKE_VERSION} VERSION_LESS 3.20) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) endif() -- cgit From c9ac4e487706658852f0e6c2e71cf669dafba90b Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Sun, 29 Jan 2023 14:19:07 -0500 Subject: vim-patch:9.0.1261: Elsa files are not recognized (#22047) Problem: Elsa files are not recognized. Solution: Add the name of Elsa files. (Amaan Qureshi) https://github.com/vim/vim/commit/2a99fe6c41efcd5d1eb47823e7e73cf391e230ba --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index a4fbe48249..128ecfb408 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -181,6 +181,7 @@ let s:filename_checks = { \ 'elixir': ['file.ex', 'file.exs', 'mix.lock'], \ 'elm': ['file.elm'], \ 'elmfilt': ['filter-rules'], + \ 'elsa': ['file.lc'], \ 'elvish': ['file.elv'], \ 'epuppet': ['file.epp'], \ 'erlang': ['file.erl', 'file.hrl', 'file.yaws'], -- cgit From 27b81af19c498892f4b0444ad29b7be842f8e7b8 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 30 Jan 2023 19:06:32 +0100 Subject: refactor!: remove has("debug") (#22060) This value can not be relied on as it doesn't work for multi-configuration generators. I don't think this undocumented option is used much, if at all, so I think we should remove it. --- src/nvim/eval/funcs.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 938fef9a52..48f3cd4293 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3064,9 +3064,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) "conceal", "cursorbind", "cursorshape", -#ifdef DEBUG - "debug", -#endif "dialog_con", "diff", "digraphs", -- cgit From 860fea1a3f880c2da0ac351a9523156bcfc67361 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 31 Jan 2023 07:08:23 +0800 Subject: fix(highlight): properly deal with underline mask when listing (#22057) --- src/nvim/highlight.c | 10 +++++----- src/nvim/highlight_defs.h | 4 ++-- src/nvim/highlight_group.c | 9 +++++++-- 3 files changed, 14 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 9dab91cc2b..c20eac3c28 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -842,14 +842,14 @@ void hlattrs2dict(Dictionary *dict, HlAttrs ae, bool use_rgb) PUT_C(hl, "underline", BOOLEAN_OBJ(true)); break; - case HL_UNDERDOUBLE: - PUT_C(hl, "underdouble", BOOLEAN_OBJ(true)); - break; - case HL_UNDERCURL: PUT_C(hl, "undercurl", BOOLEAN_OBJ(true)); break; + case HL_UNDERDOUBLE: + PUT_C(hl, "underdouble", BOOLEAN_OBJ(true)); + break; + case HL_UNDERDOTTED: PUT_C(hl, "underdotted", BOOLEAN_OBJ(true)); break; @@ -930,8 +930,8 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e CHECK_FLAG(dict, mask, bold, , HL_BOLD); CHECK_FLAG(dict, mask, italic, , HL_ITALIC); CHECK_FLAG(dict, mask, underline, , HL_UNDERLINE); - CHECK_FLAG(dict, mask, underdouble, , HL_UNDERDOUBLE); CHECK_FLAG(dict, mask, undercurl, , HL_UNDERCURL); + CHECK_FLAG(dict, mask, underdouble, , HL_UNDERDOUBLE); CHECK_FLAG(dict, mask, underdotted, , HL_UNDERDOTTED); CHECK_FLAG(dict, mask, underdashed, , HL_UNDERDASHED); CHECK_FLAG(dict, mask, standout, , HL_STANDOUT); diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h index a4dcf6eb60..95c81ac9db 100644 --- a/src/nvim/highlight_defs.h +++ b/src/nvim/highlight_defs.h @@ -18,8 +18,8 @@ typedef enum { // The next three bits are all underline styles HL_UNDERLINE_MASK = 0x38, HL_UNDERLINE = 0x08, - HL_UNDERDOUBLE = 0x10, - HL_UNDERCURL = 0x18, + HL_UNDERCURL = 0x10, + HL_UNDERDOUBLE = 0x18, HL_UNDERDOTTED = 0x20, HL_UNDERDASHED = 0x28, // 0x30 and 0x38 spare for underline styles diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index 5b1ea9967d..3d91335f55 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -1553,12 +1553,17 @@ static bool highlight_list_arg(const int id, bool didh, const int type, int iarg } else { // type == LIST_ATTR buf[0] = NUL; for (int i = 0; hl_attr_table[i] != 0; i++) { - if (iarg & hl_attr_table[i]) { + if (((hl_attr_table[i] & HL_UNDERLINE_MASK) + && ((iarg & HL_UNDERLINE_MASK) == hl_attr_table[i])) + || (!(hl_attr_table[i] & HL_UNDERLINE_MASK) + && (iarg & hl_attr_table[i]))) { if (buf[0] != NUL) { xstrlcat(buf, ",", 100); } xstrlcat(buf, hl_name_table[i], 100); - iarg &= ~hl_attr_table[i]; // don't want "inverse" + if (!(hl_attr_table[i] & HL_UNDERLINE_MASK)) { + iarg &= ~hl_attr_table[i]; // don't want "inverse" + } } } } -- cgit From b649a96fc09fa7f18a988b0b0be5dadb54ad49de Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 31 Jan 2023 08:12:10 +0100 Subject: vim-patch:9.0.1263: KDL files are not recognized (#22058) Problem: KDL files are not recognized. Solution: Add a pattern for KDL files. (Amaan Qureshi, closes vim/vim#11898) https://github.com/vim/vim/commit/907349a74331fc1bc48cf43c1e7d54cb9e0e4fc9 Co-authored-by: Amaan Qureshi --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 128ecfb408..e366fd23ad 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -302,6 +302,7 @@ let s:filename_checks = { \ 'jsp': ['file.jsp'], \ 'julia': ['file.jl'], \ 'kconfig': ['Kconfig', 'Kconfig.debug', 'Kconfig.file'], + \ 'kdl': ['file.kdl'], \ 'kivy': ['file.kv'], \ 'kix': ['file.kix'], \ 'kotlin': ['file.kt', 'file.ktm', 'file.kts'], -- cgit From b7d09695c4107bfbe03e9755f22e65027a8b18c2 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 30 Jan 2023 13:02:50 +0000 Subject: refactor(fileio.c): refactor match_file_path() --- src/nvim/fileio.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index fbb5c4f1fa..6bd1655ebc 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -5363,13 +5363,7 @@ bool match_file_pat(char *pattern, regprog_T **prog, char *fname, char *sfname, bool result = false; regmatch.rm_ic = p_fic; // ignore case if 'fileignorecase' is set - { - if (prog != NULL) { - regmatch.regprog = *prog; - } else { - regmatch.regprog = vim_regcomp(pattern, RE_MAGIC); - } - } + regmatch.regprog = prog != NULL ? *prog : vim_regcomp(pattern, RE_MAGIC); // Try for a match with the pattern with: // 1. the full file name, when the pattern has a '/'. -- cgit From 99149153c40725859ca7f4db17ff9018f29c3529 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 30 Jan 2023 13:03:10 +0000 Subject: refactor(fileio.c): refactor vim_rename() --- src/nvim/fileio.c | 73 +++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 6bd1655ebc..7826071424 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -4410,6 +4410,38 @@ int put_time(FILE *fd, time_t time_) return fwrite(buf, sizeof(uint8_t), ARRAY_SIZE(buf), fd) == 1 ? OK : FAIL; } +static int rename_with_tmp(const char *const from, const char *const to) +{ + // Find a name that doesn't exist and is in the same directory. + // Rename "from" to "tempname" and then rename "tempname" to "to". + if (strlen(from) >= MAXPATHL - 5) { + return -1; + } + + char tempname[MAXPATHL + 1]; + STRCPY(tempname, from); + for (int n = 123; n < 99999; n++) { + char *tail = path_tail(tempname); + snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - tempname - 1)), "%d", n); + + if (!os_path_exists(tempname)) { + if (os_rename(from, tempname) == OK) { + if (os_rename(tempname, to) == OK) { + return 0; + } + // Strange, the second step failed. Try moving the + // file back and return failure. + (void)os_rename(tempname, from); + return -1; + } + // If it fails for one temp name it will most likely fail + // for any temp name, give up. + return -1; + } + } + return -1; +} + /// os_rename() only works if both files are on the same file system, this /// function will (attempts to?) copy the file across if rename fails -- webb /// @@ -4417,12 +4449,7 @@ int put_time(FILE *fd, time_t time_) int vim_rename(const char *from, const char *to) FUNC_ATTR_NONNULL_ALL { - int fd_in; - int fd_out; char *errmsg = NULL; -#ifdef HAVE_ACL - vim_acl_T acl; // ACL from original file -#endif bool use_tmp_file = false; // When the names are identical, there is nothing to do. When they refer @@ -4453,34 +4480,7 @@ int vim_rename(const char *from, const char *to) } if (use_tmp_file) { - char tempname[MAXPATHL + 1]; - - // Find a name that doesn't exist and is in the same directory. - // Rename "from" to "tempname" and then rename "tempname" to "to". - if (strlen(from) >= MAXPATHL - 5) { - return -1; - } - STRCPY(tempname, from); - for (int n = 123; n < 99999; n++) { - char *tail = path_tail(tempname); - snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - tempname - 1)), "%d", n); - - if (!os_path_exists(tempname)) { - if (os_rename(from, tempname) == OK) { - if (os_rename(tempname, to) == OK) { - return 0; - } - // Strange, the second step failed. Try moving the - // file back and return failure. - (void)os_rename(tempname, from); - return -1; - } - // If it fails for one temp name it will most likely fail - // for any temp name, give up. - return -1; - } - } - return -1; + return rename_with_tmp(from, to); } // Delete the "to" file, this is required on some systems to make the @@ -4498,9 +4498,9 @@ int vim_rename(const char *from, const char *to) long perm = os_getperm(from); #ifdef HAVE_ACL // For systems that support ACL: get the ACL from the original file. - acl = os_get_acl(from); + vim_acl_T acl = os_get_acl(from); #endif - fd_in = os_open((char *)from, O_RDONLY, 0); + int fd_in = os_open((char *)from, O_RDONLY, 0); if (fd_in < 0) { #ifdef HAVE_ACL os_free_acl(acl); @@ -4509,8 +4509,7 @@ int vim_rename(const char *from, const char *to) } // Create the new file with same permissions as the original. - fd_out = os_open((char *)to, - O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, (int)perm); + int fd_out = os_open((char *)to, O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, (int)perm); if (fd_out < 0) { close(fd_in); #ifdef HAVE_ACL -- cgit From f770e05c8718bc885f93585a211c5dd1c621ed01 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 30 Jan 2023 13:11:53 +0000 Subject: refactor(fileio.c): refactor buf_write_bytes --- src/nvim/fileio.c | 113 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 7826071424..27ae622172 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -3733,6 +3733,67 @@ static bool time_differs(const FileInfo *file_info, long mtime, long mtime_ns) F #endif } +static int buf_write_convert_with_iconv(struct bw_info *ip, char **bufp, int *lenp) +{ + const char *from; + size_t fromlen; + size_t tolen; + + int len = *lenp; + + // Convert with iconv(). + if (ip->bw_restlen > 0) { + // Need to concatenate the remainder of the previous call and + // the bytes of the current call. Use the end of the + // conversion buffer for this. + fromlen = (size_t)len + (size_t)ip->bw_restlen; + char *fp = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen; + memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen); + memmove(fp + ip->bw_restlen, *bufp, (size_t)len); + from = fp; + tolen = ip->bw_conv_buflen - fromlen; + } else { + from = *bufp; + fromlen = (size_t)len; + tolen = ip->bw_conv_buflen; + } + char *to = ip->bw_conv_buf; + + if (ip->bw_first) { + size_t save_len = tolen; + + // output the initial shift state sequence + (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen); + + // There is a bug in iconv() on Linux (which appears to be + // wide-spread) which sets "to" to NULL and messes up "tolen". + if (to == NULL) { + to = ip->bw_conv_buf; + tolen = save_len; + } + ip->bw_first = false; + } + + // If iconv() has an error or there is not enough room, fail. + if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen) + == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL) + || fromlen > CONV_RESTLEN) { + ip->bw_conv_error = true; + return FAIL; + } + + // copy remainder to ip->bw_rest[] to be used for the next call. + if (fromlen > 0) { + memmove(ip->bw_rest, (void *)from, fromlen); + } + ip->bw_restlen = (int)fromlen; + + *bufp = ip->bw_conv_buf; + *lenp = (int)(to - ip->bw_conv_buf); + + return OK; +} + /// Call write() to write a number of bytes to the file. /// Handles 'encoding' conversion. /// @@ -3832,59 +3893,9 @@ static int buf_write_bytes(struct bw_info *ip) } if (ip->bw_iconv_fd != (iconv_t)-1) { - const char *from; - size_t fromlen; - size_t tolen; - - // Convert with iconv(). - if (ip->bw_restlen > 0) { - // Need to concatenate the remainder of the previous call and - // the bytes of the current call. Use the end of the - // conversion buffer for this. - fromlen = (size_t)len + (size_t)ip->bw_restlen; - char *fp = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen; - memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen); - memmove(fp + ip->bw_restlen, buf, (size_t)len); - from = fp; - tolen = ip->bw_conv_buflen - fromlen; - } else { - from = buf; - fromlen = (size_t)len; - tolen = ip->bw_conv_buflen; - } - char *to = ip->bw_conv_buf; - - if (ip->bw_first) { - size_t save_len = tolen; - - // output the initial shift state sequence - (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen); - - // There is a bug in iconv() on Linux (which appears to be - // wide-spread) which sets "to" to NULL and messes up "tolen". - if (to == NULL) { - to = ip->bw_conv_buf; - tolen = save_len; - } - ip->bw_first = false; - } - - // If iconv() has an error or there is not enough room, fail. - if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen) - == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL) - || fromlen > CONV_RESTLEN) { - ip->bw_conv_error = true; + if (buf_write_convert_with_iconv(ip, &buf, &len) == FAIL) { return FAIL; } - - // copy remainder to ip->bw_rest[] to be used for the next call. - if (fromlen > 0) { - memmove(ip->bw_rest, (void *)from, fromlen); - } - ip->bw_restlen = (int)fromlen; - - buf = ip->bw_conv_buf; - len = (int)(to - ip->bw_conv_buf); } } -- cgit From 740f6ae168bf845360ee01442837237b717d53c6 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 30 Jan 2023 13:18:00 +0000 Subject: refactor(fileio.c): refactor buf_write_bytes (2) --- src/nvim/fileio.c | 187 +++++++++++++++++++++++++++++------------------------- 1 file changed, 99 insertions(+), 88 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 27ae622172..e2138485e9 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -3794,6 +3794,103 @@ static int buf_write_convert_with_iconv(struct bw_info *ip, char **bufp, int *le return OK; } +static int buf_write_convert(struct bw_info *ip, char **bufp, int *lenp) +{ + int flags = ip->bw_flags; // extra flags + + if (flags & FIO_UTF8) { + // Convert latin1 in the buffer to UTF-8 in the file. + char *p = ip->bw_conv_buf; // translate to buffer + for (int wlen = 0; wlen < *lenp; wlen++) { + p += utf_char2bytes((uint8_t)(*bufp)[wlen], p); + } + *bufp = ip->bw_conv_buf; + *lenp = (int)(p - ip->bw_conv_buf); + } else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1)) { + unsigned c; + int n = 0; + // Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or + // Latin1 chars in the file. + // translate in-place (can only get shorter) or to buffer + char *p = flags & FIO_LATIN1 ? *bufp : ip->bw_conv_buf; + for (int wlen = 0; wlen < *lenp; wlen += n) { + if (wlen == 0 && ip->bw_restlen != 0) { + // Use remainder of previous call. Append the start of + // buf[] to get a full sequence. Might still be too + // short! + int l = MIN(*lenp, CONV_RESTLEN - ip->bw_restlen); + memmove(ip->bw_rest + ip->bw_restlen, *bufp, (size_t)l); + n = utf_ptr2len_len((char *)ip->bw_rest, ip->bw_restlen + l); + if (n > ip->bw_restlen + *lenp) { + // We have an incomplete byte sequence at the end to + // be written. We can't convert it without the + // remaining bytes. Keep them for the next call. + if (ip->bw_restlen + *lenp > CONV_RESTLEN) { + return FAIL; + } + ip->bw_restlen += *lenp; + break; + } + if (n > 1) { + c = (unsigned)utf_ptr2char((char *)ip->bw_rest); + } else { + c = ip->bw_rest[0]; + } + if (n >= ip->bw_restlen) { + n -= ip->bw_restlen; + ip->bw_restlen = 0; + } else { + ip->bw_restlen -= n; + memmove(ip->bw_rest, ip->bw_rest + n, + (size_t)ip->bw_restlen); + n = 0; + } + } else { + n = utf_ptr2len_len(*bufp + wlen, *lenp - wlen); + if (n > *lenp - wlen) { + // We have an incomplete byte sequence at the end to + // be written. We can't convert it without the + // remaining bytes. Keep them for the next call. + if (*lenp - wlen > CONV_RESTLEN) { + return FAIL; + } + ip->bw_restlen = *lenp - wlen; + memmove(ip->bw_rest, *bufp + wlen, + (size_t)ip->bw_restlen); + break; + } + if (n > 1) { + c = (unsigned)utf_ptr2char(*bufp + wlen); + } else { + c = (uint8_t)(*bufp)[wlen]; + } + } + + if (ucs2bytes(c, &p, flags) && !ip->bw_conv_error) { + ip->bw_conv_error = true; + ip->bw_conv_error_lnum = ip->bw_start_lnum; + } + if (c == NL) { + ip->bw_start_lnum++; + } + } + if (flags & FIO_LATIN1) { + *lenp = (int)(p - *bufp); + } else { + *bufp = ip->bw_conv_buf; + *lenp = (int)(p - ip->bw_conv_buf); + } + } + + if (ip->bw_iconv_fd != (iconv_t)-1) { + if (buf_write_convert_with_iconv(ip, bufp, lenp) == FAIL) { + return FAIL; + } + } + + return OK; +} + /// Call write() to write a number of bytes to the file. /// Handles 'encoding' conversion. /// @@ -3808,94 +3905,8 @@ static int buf_write_bytes(struct bw_info *ip) // Skip conversion when writing the BOM. if (!(flags & FIO_NOCONVERT)) { - if (flags & FIO_UTF8) { - // Convert latin1 in the buffer to UTF-8 in the file. - char *p = ip->bw_conv_buf; // translate to buffer - for (int wlen = 0; wlen < len; wlen++) { - p += utf_char2bytes((uint8_t)buf[wlen], p); - } - buf = ip->bw_conv_buf; - len = (int)(p - ip->bw_conv_buf); - } else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1)) { - unsigned c; - int n = 0; - // Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or - // Latin1 chars in the file. - // translate in-place (can only get shorter) or to buffer - char *p = flags & FIO_LATIN1 ? buf : ip->bw_conv_buf; - for (int wlen = 0; wlen < len; wlen += n) { - if (wlen == 0 && ip->bw_restlen != 0) { - // Use remainder of previous call. Append the start of - // buf[] to get a full sequence. Might still be too - // short! - int l = MIN(len, CONV_RESTLEN - ip->bw_restlen); - memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l); - n = utf_ptr2len_len((char *)ip->bw_rest, ip->bw_restlen + l); - if (n > ip->bw_restlen + len) { - // We have an incomplete byte sequence at the end to - // be written. We can't convert it without the - // remaining bytes. Keep them for the next call. - if (ip->bw_restlen + len > CONV_RESTLEN) { - return FAIL; - } - ip->bw_restlen += len; - break; - } - if (n > 1) { - c = (unsigned)utf_ptr2char((char *)ip->bw_rest); - } else { - c = ip->bw_rest[0]; - } - if (n >= ip->bw_restlen) { - n -= ip->bw_restlen; - ip->bw_restlen = 0; - } else { - ip->bw_restlen -= n; - memmove(ip->bw_rest, ip->bw_rest + n, - (size_t)ip->bw_restlen); - n = 0; - } - } else { - n = utf_ptr2len_len(buf + wlen, len - wlen); - if (n > len - wlen) { - // We have an incomplete byte sequence at the end to - // be written. We can't convert it without the - // remaining bytes. Keep them for the next call. - if (len - wlen > CONV_RESTLEN) { - return FAIL; - } - ip->bw_restlen = len - wlen; - memmove(ip->bw_rest, buf + wlen, - (size_t)ip->bw_restlen); - break; - } - if (n > 1) { - c = (unsigned)utf_ptr2char(buf + wlen); - } else { - c = (uint8_t)buf[wlen]; - } - } - - if (ucs2bytes(c, &p, flags) && !ip->bw_conv_error) { - ip->bw_conv_error = true; - ip->bw_conv_error_lnum = ip->bw_start_lnum; - } - if (c == NL) { - ip->bw_start_lnum++; - } - } - if (flags & FIO_LATIN1) { - len = (int)(p - buf); - } else { - buf = ip->bw_conv_buf; - len = (int)(p - ip->bw_conv_buf); - } - } - - if (ip->bw_iconv_fd != (iconv_t)-1) { - if (buf_write_convert_with_iconv(ip, &buf, &len) == FAIL) { - return FAIL; - } + if (buf_write_convert(ip, &buf, &len) == FAIL) { + return FAIL; } } -- cgit From f4b1f0d042a910f069cde9f336bb4d2a8443713c Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 30 Jan 2023 13:18:46 +0000 Subject: refactor(fileio.c): remove HAS_BW_FLAGS --- src/nvim/fileio.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index e2138485e9..826b25cd3e 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -81,7 +81,6 @@ # define UV_FS_COPYFILE_FICLONE 0 #endif -#define HAS_BW_FLAGS enum { FIO_LATIN1 = 0x01, // convert Latin1 FIO_UTF8 = 0x02, // convert UTF-8 @@ -107,9 +106,7 @@ struct bw_info { int bw_fd; // file descriptor char *bw_buf; // buffer with data to be written int bw_len; // length of data -#ifdef HAS_BW_FLAGS int bw_flags; // FIO_ flags -#endif char_u bw_rest[CONV_RESTLEN]; // not converted bytes int bw_restlen; // nr of bytes in bw_rest[] int bw_first; // first write call @@ -2150,9 +2147,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en int notconverted = false; char *fenc; // effective 'fileencoding' char *fenc_tofree = NULL; // allocated "fenc" -#ifdef HAS_BW_FLAGS int wb_flags = 0; -#endif #ifdef HAVE_ACL vim_acl_T acl = NULL; // ACL copied from original file to // backup or new file @@ -3117,9 +3112,7 @@ restore_backup: } write_info.bw_len = bufsize; -#ifdef HAS_BW_FLAGS write_info.bw_flags = wb_flags; -#endif fileformat = get_fileformat_force(buf, eap); s = buffer; len = 0; @@ -3899,9 +3892,7 @@ static int buf_write_bytes(struct bw_info *ip) { char *buf = ip->bw_buf; // data to write int len = ip->bw_len; // length of data -#ifdef HAS_BW_FLAGS int flags = ip->bw_flags; // extra flags -#endif // Skip conversion when writing the BOM. if (!(flags & FIO_NOCONVERT)) { -- cgit From b001f25204042ada6459d13f21ff29dfa0ba494c Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 30 Jan 2023 13:39:15 +0000 Subject: refactor(fileio.c): factor out autocmd handling from buf_write() --- src/nvim/fileio.c | 363 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 190 insertions(+), 173 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 826b25cd3e..e81d5f614f 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2076,6 +2076,188 @@ char *new_file_message(void) return shortmess(SHM_NEW) ? _("[New]") : _("[New File]"); } +static int buf_write_do_autocmds(buf_T *buf, char **fnamep, char **sfnamep, char **ffnamep, + linenr_T start, linenr_T *endp, exarg_T *eap, bool append, + bool filtering, bool reset_changed, bool overwriting, bool whole, + const pos_T orig_start, const pos_T orig_end) +{ + linenr_T old_line_count = buf->b_ml.ml_line_count; + int msg_save = msg_scroll; + + aco_save_T aco; + int buf_ffname = false; + int buf_sfname = false; + int buf_fname_f = false; + int buf_fname_s = false; + int did_cmd = false; + int nofile_err = false; + int empty_memline = (buf->b_ml.ml_mfp == NULL); + bufref_T bufref; + + char *sfname = *sfnamep; + + // Apply PRE autocommands. + // Set curbuf to the buffer to be written. + // Careful: The autocommands may call buf_write() recursively! + if (*ffnamep == buf->b_ffname) { + buf_ffname = true; + } + if (sfname == buf->b_sfname) { + buf_sfname = true; + } + if (*fnamep == buf->b_ffname) { + buf_fname_f = true; + } + if (*fnamep == buf->b_sfname) { + buf_fname_s = true; + } + + // Set curwin/curbuf to buf and save a few things. + aucmd_prepbuf(&aco, buf); + set_bufref(&bufref, buf); + + if (append) { + if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD, + sfname, sfname, false, curbuf, eap))) { + if (overwriting && bt_nofilename(curbuf)) { + nofile_err = true; + } else { + apply_autocmds_exarg(EVENT_FILEAPPENDPRE, + sfname, sfname, false, curbuf, eap); + } + } + } else if (filtering) { + apply_autocmds_exarg(EVENT_FILTERWRITEPRE, + NULL, sfname, false, curbuf, eap); + } else if (reset_changed && whole) { + int was_changed = curbufIsChanged(); + + did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD, + sfname, sfname, false, curbuf, eap); + if (did_cmd) { + if (was_changed && !curbufIsChanged()) { + // Written everything correctly and BufWriteCmd has reset + // 'modified': Correct the undo information so that an + // undo now sets 'modified'. + u_unchanged(curbuf); + u_update_save_nr(curbuf); + } + } else { + if (overwriting && bt_nofilename(curbuf)) { + nofile_err = true; + } else { + apply_autocmds_exarg(EVENT_BUFWRITEPRE, + sfname, sfname, false, curbuf, eap); + } + } + } else { + if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD, + sfname, sfname, false, curbuf, eap))) { + if (overwriting && bt_nofilename(curbuf)) { + nofile_err = true; + } else { + apply_autocmds_exarg(EVENT_FILEWRITEPRE, + sfname, sfname, false, curbuf, eap); + } + } + } + + // restore curwin/curbuf and a few other things + aucmd_restbuf(&aco); + + // In three situations we return here and don't write the file: + // 1. the autocommands deleted or unloaded the buffer. + // 2. The autocommands abort script processing. + // 3. If one of the "Cmd" autocommands was executed. + if (!bufref_valid(&bufref)) { + buf = NULL; + } + if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline) + || did_cmd || nofile_err + || aborting()) { + if (buf != NULL && (cmdmod.cmod_flags & CMOD_LOCKMARKS)) { + // restore the original '[ and '] positions + buf->b_op_start = orig_start; + buf->b_op_end = orig_end; + } + + no_wait_return--; + msg_scroll = msg_save; + if (nofile_err) { + semsg(_(e_no_matching_autocommands_for_buftype_str_buffer), curbuf->b_p_bt); + } + + if (nofile_err + || aborting()) { + // An aborting error, interrupt or exception in the + // autocommands. + return FAIL; + } + if (did_cmd) { + if (buf == NULL) { + // The buffer was deleted. We assume it was written + // (can't retry anyway). + return OK; + } + if (overwriting) { + // Assume the buffer was written, update the timestamp. + ml_timestamp(buf); + if (append) { + buf->b_flags &= ~BF_NEW; + } else { + buf->b_flags &= ~BF_WRITE_MASK; + } + } + if (reset_changed && buf->b_changed && !append + && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)) { + // Buffer still changed, the autocommands didn't work properly. + return FAIL; + } + return OK; + } + if (!aborting()) { + emsg(_("E203: Autocommands deleted or unloaded buffer to be written")); + } + return FAIL; + } + + // The autocommands may have changed the number of lines in the file. + // When writing the whole file, adjust the end. + // When writing part of the file, assume that the autocommands only + // changed the number of lines that are to be written (tricky!). + if (buf->b_ml.ml_line_count != old_line_count) { + if (whole) { // write all + *endp = buf->b_ml.ml_line_count; + } else if (buf->b_ml.ml_line_count > old_line_count) { // more lines + *endp += buf->b_ml.ml_line_count - old_line_count; + } else { // less lines + *endp -= old_line_count - buf->b_ml.ml_line_count; + if (*endp < start) { + no_wait_return--; + msg_scroll = msg_save; + emsg(_("E204: Autocommand changed number of lines in unexpected way")); + return FAIL; + } + } + } + + // The autocommands may have changed the name of the buffer, which may + // be kept in fname, ffname and sfname. + if (buf_ffname) { + *ffnamep = buf->b_ffname; + } + if (buf_sfname) { + *sfnamep = buf->b_sfname; + } + if (buf_fname_f) { + *fnamep = buf->b_ffname; + } + if (buf_fname_s) { + *fnamep = buf->b_sfname; + } + return NOTDONE; +} + /// buf_write() - write to file "fname" lines "start" through "end" /// /// We do our own buffering here because fwrite() is so slow. @@ -2139,7 +2321,6 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en #endif // writing everything int whole = (start == 1 && end == buf->b_ml.ml_line_count); - linenr_T old_line_count = buf->b_ml.ml_line_count; int fileformat; int write_bin; struct bw_info write_info; // info for buf_write_bytes() @@ -2155,8 +2336,6 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en int write_undo_file = false; context_sha256_T sha_ctx; unsigned int bkc = get_bkc_value(buf); - const pos_T orig_start = buf->b_op_start; - const pos_T orig_end = buf->b_op_end; if (fname == NULL || *fname == NUL) { // safety check return FAIL; @@ -2230,182 +2409,20 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en no_wait_return++; // don't wait for return yet + const pos_T orig_start = buf->b_op_start; + const pos_T orig_end = buf->b_op_end; + // Set '[ and '] marks to the lines to be written. buf->b_op_start.lnum = start; buf->b_op_start.col = 0; buf->b_op_end.lnum = end; buf->b_op_end.col = 0; - { - aco_save_T aco; - int buf_ffname = false; - int buf_sfname = false; - int buf_fname_f = false; - int buf_fname_s = false; - int did_cmd = false; - int nofile_err = false; - int empty_memline = (buf->b_ml.ml_mfp == NULL); - bufref_T bufref; - - // Apply PRE autocommands. - // Set curbuf to the buffer to be written. - // Careful: The autocommands may call buf_write() recursively! - if (ffname == buf->b_ffname) { - buf_ffname = true; - } - if (sfname == buf->b_sfname) { - buf_sfname = true; - } - if (fname == buf->b_ffname) { - buf_fname_f = true; - } - if (fname == buf->b_sfname) { - buf_fname_s = true; - } - - // Set curwin/curbuf to buf and save a few things. - aucmd_prepbuf(&aco, buf); - set_bufref(&bufref, buf); - - if (append) { - if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD, - sfname, sfname, false, curbuf, eap))) { - if (overwriting && bt_nofilename(curbuf)) { - nofile_err = true; - } else { - apply_autocmds_exarg(EVENT_FILEAPPENDPRE, - sfname, sfname, false, curbuf, eap); - } - } - } else if (filtering) { - apply_autocmds_exarg(EVENT_FILTERWRITEPRE, - NULL, sfname, false, curbuf, eap); - } else if (reset_changed && whole) { - int was_changed = curbufIsChanged(); - - did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD, - sfname, sfname, false, curbuf, eap); - if (did_cmd) { - if (was_changed && !curbufIsChanged()) { - // Written everything correctly and BufWriteCmd has reset - // 'modified': Correct the undo information so that an - // undo now sets 'modified'. - u_unchanged(curbuf); - u_update_save_nr(curbuf); - } - } else { - if (overwriting && bt_nofilename(curbuf)) { - nofile_err = true; - } else { - apply_autocmds_exarg(EVENT_BUFWRITEPRE, - sfname, sfname, false, curbuf, eap); - } - } - } else { - if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD, - sfname, sfname, false, curbuf, eap))) { - if (overwriting && bt_nofilename(curbuf)) { - nofile_err = true; - } else { - apply_autocmds_exarg(EVENT_FILEWRITEPRE, - sfname, sfname, false, curbuf, eap); - } - } - } - - // restore curwin/curbuf and a few other things - aucmd_restbuf(&aco); - - // In three situations we return here and don't write the file: - // 1. the autocommands deleted or unloaded the buffer. - // 2. The autocommands abort script processing. - // 3. If one of the "Cmd" autocommands was executed. - if (!bufref_valid(&bufref)) { - buf = NULL; - } - if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline) - || did_cmd || nofile_err - || aborting()) { - if (buf != NULL && (cmdmod.cmod_flags & CMOD_LOCKMARKS)) { - // restore the original '[ and '] positions - buf->b_op_start = orig_start; - buf->b_op_end = orig_end; - } - - no_wait_return--; - msg_scroll = msg_save; - if (nofile_err) { - semsg(_(e_no_matching_autocommands_for_buftype_str_buffer), curbuf->b_p_bt); - } - - if (nofile_err - || aborting()) { - // An aborting error, interrupt or exception in the - // autocommands. - return FAIL; - } - if (did_cmd) { - if (buf == NULL) { - // The buffer was deleted. We assume it was written - // (can't retry anyway). - return OK; - } - if (overwriting) { - // Assume the buffer was written, update the timestamp. - ml_timestamp(buf); - if (append) { - buf->b_flags &= ~BF_NEW; - } else { - buf->b_flags &= ~BF_WRITE_MASK; - } - } - if (reset_changed && buf->b_changed && !append - && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)) { - // Buffer still changed, the autocommands didn't work properly. - return FAIL; - } - return OK; - } - if (!aborting()) { - emsg(_("E203: Autocommands deleted or unloaded buffer to be written")); - } - return FAIL; - } - - // The autocommands may have changed the number of lines in the file. - // When writing the whole file, adjust the end. - // When writing part of the file, assume that the autocommands only - // changed the number of lines that are to be written (tricky!). - if (buf->b_ml.ml_line_count != old_line_count) { - if (whole) { // write all - end = buf->b_ml.ml_line_count; - } else if (buf->b_ml.ml_line_count > old_line_count) { // more lines - end += buf->b_ml.ml_line_count - old_line_count; - } else { // less lines - end -= old_line_count - buf->b_ml.ml_line_count; - if (end < start) { - no_wait_return--; - msg_scroll = msg_save; - emsg(_("E204: Autocommand changed number of lines in unexpected way")); - return FAIL; - } - } - } - - // The autocommands may have changed the name of the buffer, which may - // be kept in fname, ffname and sfname. - if (buf_ffname) { - ffname = buf->b_ffname; - } - if (buf_sfname) { - sfname = buf->b_sfname; - } - if (buf_fname_f) { - fname = buf->b_ffname; - } - if (buf_fname_s) { - fname = buf->b_sfname; - } + int res = buf_write_do_autocmds(buf, &fname, &sfname, &ffname, start, &end, eap, append, + filtering, reset_changed, overwriting, whole, orig_start, + orig_end); + if (res != NOTDONE) { + return res; } if (cmdmod.cmod_flags & CMOD_LOCKMARKS) { -- cgit From 253a4d7074bd2ed31e26ed663aedda66e8dca833 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 30 Jan 2023 13:58:07 +0000 Subject: refactor(fileio.c): more bools --- src/nvim/fileio.c | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index e81d5f614f..c7fcd85c7e 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2085,13 +2085,9 @@ static int buf_write_do_autocmds(buf_T *buf, char **fnamep, char **sfnamep, char int msg_save = msg_scroll; aco_save_T aco; - int buf_ffname = false; - int buf_sfname = false; - int buf_fname_f = false; - int buf_fname_s = false; - int did_cmd = false; - int nofile_err = false; - int empty_memline = (buf->b_ml.ml_mfp == NULL); + bool did_cmd = false; + bool nofile_err = false; + bool empty_memline = buf->b_ml.ml_mfp == NULL; bufref_T bufref; char *sfname = *sfnamep; @@ -2099,26 +2095,18 @@ static int buf_write_do_autocmds(buf_T *buf, char **fnamep, char **sfnamep, char // Apply PRE autocommands. // Set curbuf to the buffer to be written. // Careful: The autocommands may call buf_write() recursively! - if (*ffnamep == buf->b_ffname) { - buf_ffname = true; - } - if (sfname == buf->b_sfname) { - buf_sfname = true; - } - if (*fnamep == buf->b_ffname) { - buf_fname_f = true; - } - if (*fnamep == buf->b_sfname) { - buf_fname_s = true; - } + bool buf_ffname = *ffnamep == buf->b_ffname; + bool buf_sfname = sfname == buf->b_sfname; + bool buf_fname_f = *fnamep == buf->b_ffname; + bool buf_fname_s = *fnamep == buf->b_sfname; // Set curwin/curbuf to buf and save a few things. aucmd_prepbuf(&aco, buf); set_bufref(&bufref, buf); if (append) { - if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD, - sfname, sfname, false, curbuf, eap))) { + did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD, sfname, sfname, false, curbuf, eap); + if (!did_cmd) { if (overwriting && bt_nofilename(curbuf)) { nofile_err = true; } else { @@ -2130,10 +2118,9 @@ static int buf_write_do_autocmds(buf_T *buf, char **fnamep, char **sfnamep, char apply_autocmds_exarg(EVENT_FILTERWRITEPRE, NULL, sfname, false, curbuf, eap); } else if (reset_changed && whole) { - int was_changed = curbufIsChanged(); + bool was_changed = curbufIsChanged(); - did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD, - sfname, sfname, false, curbuf, eap); + did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD, sfname, sfname, false, curbuf, eap); if (did_cmd) { if (was_changed && !curbufIsChanged()) { // Written everything correctly and BufWriteCmd has reset @@ -2151,8 +2138,8 @@ static int buf_write_do_autocmds(buf_T *buf, char **fnamep, char **sfnamep, char } } } else { - if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD, - sfname, sfname, false, curbuf, eap))) { + did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD, sfname, sfname, false, curbuf, eap); + if (!did_cmd) { if (overwriting && bt_nofilename(curbuf)) { nofile_err = true; } else { -- cgit From d6d6ab3f8e77d54c8030c0c18f17d3c72ac4445c Mon Sep 17 00:00:00 2001 From: bfredl Date: Sat, 26 Feb 2022 15:19:10 +0100 Subject: feat(lua): low-level interpreter mode (nvim -ll) --- src/nvim/lua/executor.c | 67 ++++++++++++++++++++++++++++++++++++------------- src/nvim/main.c | 16 ++++++++++-- 2 files changed, 63 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 5ffd90fddd..d144a5ae23 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -64,6 +64,7 @@ #include "nvim/window.h" static int in_fast_callback = 0; +static bool in_script = false; // Initialized in nlua_init(). static lua_State *global_lstate = NULL; @@ -133,8 +134,13 @@ static void nlua_error(lua_State *const lstate, const char *const msg) str = lua_tolstring(lstate, -1, &len); } - msg_ext_set_kind("lua_error"); - semsg_multiline(msg, (int)len, str); + if (in_script) { + os_errmsg(str); + os_errmsg("\n"); + } else { + msg_ext_set_kind("lua_error"); + semsg_multiline(msg, (int)len, str); + } lua_pop(lstate, 1); } @@ -534,7 +540,7 @@ int nlua_get_global_ref_count(void) return nlua_global_refs->ref_count; } -static void nlua_common_vim_init(lua_State *lstate, bool is_thread) +static void nlua_common_vim_init(lua_State *lstate, bool is_thread, bool is_standalone) FUNC_ATTR_NONNULL_ARG(1) { nlua_ref_state_t *ref_state = nlua_new_ref_state(lstate, is_thread); @@ -567,7 +573,9 @@ static void nlua_common_vim_init(lua_State *lstate, bool is_thread) lua_setfield(lstate, -2, "_empty_dict_mt"); // vim.loop - if (is_thread) { + if (is_standalone) { + // do nothing, use libluv like in a standalone interpreter + } else if (is_thread) { luv_set_callback(lstate, nlua_luv_thread_cb_cfpcall); luv_set_thread(lstate, nlua_luv_thread_cfpcall); luv_set_cthread(lstate, nlua_luv_thread_cfcpcall); @@ -606,7 +614,7 @@ static int nlua_module_preloader(lua_State *lstate) return 1; } -static bool nlua_init_packages(lua_State *lstate) +static bool nlua_init_packages(lua_State *lstate, bool is_standalone) FUNC_ATTR_NONNULL_ALL { // put builtin packages in preload @@ -618,7 +626,7 @@ static bool nlua_init_packages(lua_State *lstate) lua_pushcclosure(lstate, nlua_module_preloader, 1); // [package, preload, cclosure] lua_setfield(lstate, -2, def.name); // [package, preload] - if (nlua_disable_preload && strequal(def.name, "vim.inspect")) { + if ((nlua_disable_preload && !is_standalone) && strequal(def.name, "vim.inspect")) { break; } } @@ -769,7 +777,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_pushcfunction(lstate, &nlua_ui_detach); lua_setfield(lstate, -2, "ui_detach"); - nlua_common_vim_init(lstate, false); + nlua_common_vim_init(lstate, false, false); // patch require() (only for --startuptime) if (time_fd != NULL) { @@ -788,7 +796,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL lua_setglobal(lstate, "vim"); - if (!nlua_init_packages(lstate)) { + if (!nlua_init_packages(lstate, false)) { return false; } @@ -823,10 +831,29 @@ void nlua_init(char **argv, int argc, int lua_arg0) } static lua_State *nlua_thread_acquire_vm(void) +{ + return nlua_init_state(true); +} + +void nlua_run_script(char **argv, int argc, int lua_arg0) + FUNC_ATTR_NORETURN +{ + in_script = true; + global_lstate = nlua_init_state(false); + luv_set_thread_cb(nlua_thread_acquire_vm, nlua_common_free_all_mem); + nlua_init_argv(global_lstate, argv, argc, lua_arg0); + bool lua_ok = nlua_exec_file(argv[lua_arg0 - 1]); +#ifdef EXITFREE + nlua_free_all_mem(); +#endif + exit(lua_ok ? 0 : 1); +} + +lua_State *nlua_init_state(bool thread) { // If it is called from the main thread, it will attempt to rebuild the cache. const uv_thread_t self = uv_thread_self(); - if (uv_thread_equal(&main_thread, &self)) { + if (!in_script && uv_thread_equal(&main_thread, &self)) { runtime_search_path_validate(); } @@ -835,9 +862,11 @@ static lua_State *nlua_thread_acquire_vm(void) // Add in the lua standard libraries luaL_openlibs(lstate); - // print - lua_pushcfunction(lstate, &nlua_print); - lua_setglobal(lstate, "print"); + if (!in_script) { + // print + lua_pushcfunction(lstate, &nlua_print); + lua_setglobal(lstate, "print"); + } lua_pushinteger(lstate, 0); lua_setfield(lstate, LUA_REGISTRYINDEX, "nlua.refcount"); @@ -845,18 +874,20 @@ static lua_State *nlua_thread_acquire_vm(void) // vim lua_newtable(lstate); - nlua_common_vim_init(lstate, true); + nlua_common_vim_init(lstate, thread, in_script); nlua_state_add_stdlib(lstate, true); - lua_createtable(lstate, 0, 0); - lua_pushcfunction(lstate, nlua_thr_api_nvim__get_runtime); - lua_setfield(lstate, -2, "nvim__get_runtime"); - lua_setfield(lstate, -2, "api"); + if (!in_script) { + lua_createtable(lstate, 0, 0); + lua_pushcfunction(lstate, nlua_thr_api_nvim__get_runtime); + lua_setfield(lstate, -2, "nvim__get_runtime"); + lua_setfield(lstate, -2, "api"); + } lua_setglobal(lstate, "vim"); - nlua_init_packages(lstate); + nlua_init_packages(lstate, in_script); lua_getglobal(lstate, "package"); lua_getfield(lstate, -1, "loaded"); diff --git a/src/nvim/main.c b/src/nvim/main.c index bbe877356d..8df82c710a 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -239,6 +239,14 @@ int main(int argc, char **argv) argv0 = argv[0]; + if (argc > 1 && STRICMP(argv[1], "-ll") == 0) { + if (argc == 2) { + print_mainerr(err_arg_missing, argv[1]); + exit(1); + } + nlua_run_script(argv, argc, 3); + } + char *fname = NULL; // file name from command line mparm_T params; // various parameters passed between // main() and other functions. @@ -2110,6 +2118,12 @@ static int execute_env(char *env) /// @param str string to append to the primary error message, or NULL static void mainerr(const char *errstr, const char *str) FUNC_ATTR_NORETURN +{ + print_mainerr(errstr, str); + os_exit(1); +} + +static void print_mainerr(const char *errstr, const char *str) { char *prgname = path_tail(argv0); @@ -2126,8 +2140,6 @@ static void mainerr(const char *errstr, const char *str) os_errmsg(_("\nMore info with \"")); os_errmsg(prgname); os_errmsg(" -h\"\n"); - - os_exit(1); } /// Prints version information for "nvim -v" or "nvim --version". -- cgit From 9417a3d98a10265fe4265e40ad204ead00a7e0a2 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 30 Jan 2023 15:30:05 +0000 Subject: refactor(fileio.c): reduce scope of locals --- src/nvim/fileio.c | 108 +++++++++++++++++++++++++++--------------------------- 1 file changed, 53 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index c7fcd85c7e..88d92b7dfa 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2266,18 +2266,6 @@ static int buf_write_do_autocmds(buf_T *buf, char **fnamep, char **sfnamep, char int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T end, exarg_T *eap, int append, int forceit, int reset_changed, int filtering) { - int fd; - char *backup = NULL; - int backup_copy = false; // copy the original file? - int dobackup; - char *ffname; - char *wfname = NULL; // name of file to write to - char *s; - char *ptr; - char c; - int len; - linenr_T lnum; - long nchars; #define SET_ERRMSG_NUM(num, msg) \ errnum = (num), errmsg = (msg), errmsgarg = 0 #define SET_ERRMSG_ARG(msg, error) \ @@ -2288,38 +2276,13 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en char *errmsg = NULL; int errmsgarg = 0; bool errmsg_allocated = false; - char *buffer; - char smallbuf[SMBUFSIZE]; - int bufsize; - long perm; // file permissions int retval = OK; - int newfile = false; // true if file doesn't exist yet int msg_save = msg_scroll; - int overwriting; // true if writing over original - int no_eol = false; // no end-of-line written - int device = false; // writing to a device int prev_got_int = got_int; - int checking_conversion; - bool file_readonly = false; // overwritten file is read-only static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')"; -#if defined(UNIX) - int made_writable = false; // 'w' bit has been set -#endif // writing everything int whole = (start == 1 && end == buf->b_ml.ml_line_count); - int fileformat; - int write_bin; - struct bw_info write_info; // info for buf_write_bytes() - int converted = false; - int notconverted = false; - char *fenc; // effective 'fileencoding' - char *fenc_tofree = NULL; // allocated "fenc" - int wb_flags = 0; -#ifdef HAVE_ACL - vim_acl_T acl = NULL; // ACL copied from original file to - // backup or new file -#endif int write_undo_file = false; context_sha256_T sha_ctx; unsigned int bkc = get_bkc_value(buf); @@ -2346,6 +2309,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en } // must init bw_conv_buf and bw_iconv_fd before jumping to "fail" + struct bw_info write_info; // info for buf_write_bytes() write_info.bw_conv_buf = NULL; write_info.bw_conv_error = false; write_info.bw_conv_error_lnum = 0; @@ -2383,16 +2347,13 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en // Avoids problems with networks and when directory names are changed. // Don't do this for Windows, a "cd" in a sub-shell may have moved us to // another directory, which we don't detect. - ffname = fname; // remember full fname + char *ffname = fname; // remember full fname #ifdef UNIX fname = sfname; #endif - if (buf->b_ffname != NULL && path_fnamecmp(ffname, buf->b_ffname) == 0) { - overwriting = true; - } else { - overwriting = false; - } +// true if writing over original + int overwriting = buf->b_ffname != NULL && path_fnamecmp(ffname, buf->b_ffname) == 0; no_wait_return++; // don't wait for return yet @@ -2434,7 +2395,9 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en } msg_scroll = false; // always overwrite the file message now - buffer = verbose_try_malloc(BUFSIZE); + char *buffer = verbose_try_malloc(BUFSIZE); + int bufsize; + char smallbuf[SMBUFSIZE]; // can't allocate big buffer, use small one (to be able to write when out of // memory) if (buffer == NULL) { @@ -2444,8 +2407,20 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en bufsize = BUFSIZE; } + int newfile = false; // true if file doesn't exist yet + int device = false; // writing to a device + char *backup = NULL; + char *fenc_tofree = NULL; // allocated "fenc" + // Get information about original file (if there is one). FileInfo file_info_old; + +#ifdef HAVE_ACL + vim_acl_T acl = NULL; // ACL copied from original file to + // backup or new file +#endif + + long perm; // file permissions #if defined(UNIX) perm = -1; if (!os_fileinfo(fname, &file_info_old)) { @@ -2470,12 +2445,12 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en } #else // win32 // Check for a writable device name. - c = fname == NULL ? NODE_OTHER : os_nodetype(fname); - if (c == NODE_OTHER) { + char nodetype = fname == NULL ? NODE_OTHER : os_nodetype(fname); + if (nodetype == NODE_OTHER) { SET_ERRMSG_NUM("E503", _("is not a file or writable device")); goto fail; } - if (c == NODE_WRITABLE) { + if (nodetype == NODE_WRITABLE) { device = true; newfile = true; perm = -1; @@ -2493,6 +2468,8 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en } #endif // !UNIX + bool file_readonly = false; // overwritten file is read-only + if (!device && !newfile) { // Check if the file is really writable (when renaming the file to // make a backup we won't discover it later). @@ -2524,11 +2501,13 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en #endif // If 'backupskip' is not empty, don't make a backup for some files. - dobackup = (p_wb || p_bk || *p_pm != NUL); + bool dobackup = (p_wb || p_bk || *p_pm != NUL); if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname)) { dobackup = false; } + int backup_copy = false; // copy the original file? + // Save the value of got_int and reset it. We don't want a previous // interruption cancel writing, only hitting CTRL-C while writing should // abort it. @@ -2573,8 +2552,8 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en break; } } - fd = os_open(IObuff, - O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, (int)perm); + int fd = os_open(IObuff, + O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, (int)perm); if (fd < 0) { // can't write in directory backup_copy = true; } else { @@ -2860,6 +2839,8 @@ nobackup: } #if defined(UNIX) + int made_writable = false; // 'w' bit has been set + // When using ":w!" and the file was read-only: make it writable if (forceit && perm >= 0 && !(perm & 0200) && file_info_old.stat.st_uid == getuid() @@ -2885,6 +2866,8 @@ nobackup: start = end + 1; } + char *wfname = NULL; // name of file to write to + // If the original file is being overwritten, there is a small chance that // we crash in the middle of writing. Therefore the file is preserved now. // This makes all block numbers positive so that recovery does not need @@ -2903,6 +2886,8 @@ nobackup: // multi-byte conversion. wfname = fname; + char *fenc; // effective 'fileencoding' + // Check for forced 'fileencoding' from "++opt=val" argument. if (eap != NULL && eap->force_enc != 0) { fenc = eap->cmd + eap->force_enc; @@ -2913,7 +2898,8 @@ nobackup: } // Check if the file needs to be converted. - converted = need_conversion(fenc); + int converted = need_conversion(fenc); + int wb_flags = 0; // Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or // Latin1 to Unicode conversion. This is handled in buf_write_bytes(). @@ -2960,6 +2946,8 @@ nobackup: } } + int notconverted = false; + if (converted && wb_flags == 0 && write_info.bw_iconv_fd == (iconv_t)-1 && wfname == fname) { @@ -2970,6 +2958,14 @@ nobackup: notconverted = true; } + int no_eol = false; // no end-of-line written + long nchars; + linenr_T lnum; + int fileformat; + int checking_conversion; + + int fd; + // If conversion is taking place, we may first pretend to write and check // for conversion errors. Then loop again to write for real. // When not doing conversion this writes for real right away. @@ -3086,6 +3082,7 @@ restore_backup: nchars = 0; // use "++bin", "++nobin" or 'binary' + int write_bin; if (eap != NULL && eap->force_bin != 0) { write_bin = (eap->force_bin == FORCE_BIN); } else { @@ -3118,15 +3115,16 @@ restore_backup: write_info.bw_len = bufsize; write_info.bw_flags = wb_flags; fileformat = get_fileformat_force(buf, eap); - s = buffer; - len = 0; + char *s = buffer; + int len = 0; for (lnum = start; lnum <= end; lnum++) { // The next while loop is done once for each character written. // Keep it fast! - ptr = ml_get_buf(buf, lnum, false) - 1; + char *ptr = ml_get_buf(buf, lnum, false) - 1; if (write_undo_file) { sha256_update(&sha_ctx, (uint8_t *)ptr + 1, (uint32_t)(strlen(ptr + 1) + 1)); } + char c; while ((c = *++ptr) != NUL) { if (c == NL) { *s = NUL; // replace newlines with NULs @@ -3349,7 +3347,7 @@ restore_backup: #endif if (!filtering) { add_quoted_fname(IObuff, IOSIZE, buf, (const char *)fname); - c = false; + char c = false; if (write_info.bw_conv_error) { STRCAT(IObuff, _(" CONVERSION ERROR")); c = true; -- cgit From 842cf780a6aa11df0411b41573f263bc5c151405 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 30 Jan 2023 17:20:25 +0000 Subject: refactor(fileio.c): do not use macros for error handling --- src/nvim/fileio.c | 133 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 74 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 88d92b7dfa..c5c5a26d9d 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -118,6 +118,13 @@ struct bw_info { iconv_t bw_iconv_fd; // descriptor for iconv() or -1 }; +typedef struct { + const char *num; + char *msg; + int arg; + bool alloc; +} Error_T; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "fileio.c.generated.h" #endif @@ -2245,6 +2252,39 @@ static int buf_write_do_autocmds(buf_T *buf, char **fnamep, char **sfnamep, char return NOTDONE; } +static inline Error_T set_err_num(const char *num, const char *msg) +{ + return (Error_T){ .num = num, .msg = (char *)msg, .arg = 0 }; +} + +static inline Error_T set_err_arg(const char *msg, int arg) +{ + return (Error_T){ .num = NULL, .msg = (char *)msg, .arg = arg }; +} + +static inline Error_T set_err(const char *msg) +{ + return (Error_T){ .num = NULL, .msg = (char *)msg, .arg = 0 }; +} + +static void emit_err(Error_T *e) +{ + if (e->num != NULL) { + if (e->arg != 0) { + semsg("%s: %s%s: %s", e->num, IObuff, e->msg, os_strerror(e->arg)); + } else { + semsg("%s: %s%s", e->num, IObuff, e->msg); + } + } else if (e->arg != 0) { + semsg(e->msg, os_strerror(e->arg)); + } else { + emsg(e->msg); + } + if (e->alloc) { + xfree(e->msg); + } +} + /// buf_write() - write to file "fname" lines "start" through "end" /// /// We do our own buffering here because fwrite() is so slow. @@ -2266,16 +2306,6 @@ static int buf_write_do_autocmds(buf_T *buf, char **fnamep, char **sfnamep, char int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T end, exarg_T *eap, int append, int forceit, int reset_changed, int filtering) { -#define SET_ERRMSG_NUM(num, msg) \ - errnum = (num), errmsg = (msg), errmsgarg = 0 -#define SET_ERRMSG_ARG(msg, error) \ - errnum = NULL, errmsg = (msg), errmsgarg = error -#define SET_ERRMSG(msg) \ - errnum = NULL, errmsg = (msg), errmsgarg = 0 - const char *errnum = NULL; - char *errmsg = NULL; - int errmsgarg = 0; - bool errmsg_allocated = false; int retval = OK; int msg_save = msg_scroll; int prev_got_int = got_int; @@ -2407,6 +2437,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en bufsize = BUFSIZE; } + Error_T err = { 0 }; int newfile = false; // true if file doesn't exist yet int device = false; // writing to a device char *backup = NULL; @@ -2429,11 +2460,11 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en perm = (long)file_info_old.stat.st_mode; if (!S_ISREG(file_info_old.stat.st_mode)) { // not a file if (S_ISDIR(file_info_old.stat.st_mode)) { - SET_ERRMSG_NUM("E502", _("is a directory")); + err = set_err_num("E502", _("is a directory")); goto fail; } if (os_nodetype(fname) != NODE_WRITABLE) { - SET_ERRMSG_NUM("E503", _("is not a file or writable device")); + err = set_err_num("E503", _("is not a file or writable device")); goto fail; } // It's a device of some kind (or a fifo) which we can write to @@ -2447,7 +2478,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en // Check for a writable device name. char nodetype = fname == NULL ? NODE_OTHER : os_nodetype(fname); if (nodetype == NODE_OTHER) { - SET_ERRMSG_NUM("E503", _("is not a file or writable device")); + err = set_err_num("E503", _("is not a file or writable device")); goto fail; } if (nodetype == NODE_WRITABLE) { @@ -2459,7 +2490,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en if (perm < 0) { newfile = true; } else if (os_isdir(fname)) { - SET_ERRMSG_NUM("E502", _("is a directory")); + err = set_err_num("E502", _("is a directory")); goto fail; } if (overwriting) { @@ -2477,9 +2508,9 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en if (!forceit && file_readonly) { if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) { - SET_ERRMSG_NUM("E504", _(err_readonly)); + err = set_err_num("E504", _(err_readonly)); } else { - SET_ERRMSG_NUM("E505", _("is read-only (add ! to override)")); + err = set_err_num("E505", _("is read-only (add ! to override)")); } goto fail; } @@ -2716,7 +2747,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en // copy the file if (os_copy(fname, backup, UV_FS_COPYFILE_FICLONE) != 0) { - SET_ERRMSG(_("E509: Cannot create backup file (add ! to override)")); + err = set_err(_("E509: Cannot create backup file (add ! to override)")); XFREE_CLEAR(backup); backup = NULL; continue; @@ -2730,21 +2761,21 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en #ifdef HAVE_ACL os_set_acl(backup, acl); #endif - SET_ERRMSG(NULL); + err = set_err(NULL); break; } } nobackup: - if (backup == NULL && errmsg == NULL) { - SET_ERRMSG(_("E509: Cannot create backup file (add ! to override)")); + if (backup == NULL && err.msg == NULL) { + err = set_err(_("E509: Cannot create backup file (add ! to override)")); } // Ignore errors when forceit is true. - if ((some_error || errmsg != NULL) && !forceit) { + if ((some_error || err.msg != NULL) && !forceit) { retval = FAIL; goto fail; } - SET_ERRMSG(NULL); + err = set_err(NULL); } else { // Make a backup by renaming the original file. @@ -2752,7 +2783,7 @@ nobackup: // overwrite a read-only file. But rename may be possible // anyway, thus we need an extra check here. if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL) { - SET_ERRMSG_NUM("E504", _(err_readonly)); + err = set_err_num("E504", _(err_readonly)); goto fail; } @@ -2832,7 +2863,7 @@ nobackup: } } if (backup == NULL && !forceit) { - SET_ERRMSG(_("E510: Can't make backup file (add ! to override)")); + err = set_err(_("E510: Can't make backup file (add ! to override)")); goto fail; } } @@ -2877,7 +2908,7 @@ nobackup: && !(exiting && backup != NULL)) { ml_preserve(buf, false, !!p_fs); if (got_int) { - SET_ERRMSG(_(e_interr)); + err = set_err(_(e_interr)); goto restore_backup; } } @@ -2939,7 +2970,7 @@ nobackup: if (*p_ccv != NUL) { wfname = vim_tempname(); if (wfname == NULL) { // Can't write without a tempfile! - SET_ERRMSG(_("E214: Can't find temp file for writing")); + err = set_err(_("E214: Can't find temp file for writing")); goto restore_backup; } } @@ -2952,7 +2983,7 @@ nobackup: && write_info.bw_iconv_fd == (iconv_t)-1 && wfname == fname) { if (!forceit) { - SET_ERRMSG(_("E213: Cannot convert (add ! to write without conversion)")); + err = set_err(_("E213: Cannot convert (add ! to write without conversion)")); goto restore_backup; } notconverted = true; @@ -3002,7 +3033,7 @@ nobackup: // A forced write will try to create a new file if the old one // is still readonly. This may also happen when the directory // is read-only. In that case the mch_remove() will fail. - if (errmsg == NULL) { + if (err.msg == NULL) { #ifdef UNIX FileInfo file_info; @@ -3010,10 +3041,10 @@ nobackup: if ((!newfile && os_fileinfo_hardlinks(&file_info_old) > 1) || (os_fileinfo_link(fname, &file_info) && !os_fileinfo_id_equal(&file_info, &file_info_old))) { - SET_ERRMSG(_("E166: Can't open linked file for writing")); + err = set_err(_("E166: Can't open linked file for writing")); } else { #endif - SET_ERRMSG_ARG(_("E212: Can't open file for writing: %s"), fd); + err = set_err_arg(_("E212: Can't open file for writing: %s"), fd); if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL && perm >= 0) { #ifdef UNIX @@ -3076,7 +3107,7 @@ restore_backup: } write_info.bw_fd = fd; } - SET_ERRMSG(NULL); + err = set_err(NULL); write_info.bw_buf = buffer; nchars = 0; @@ -3226,7 +3257,7 @@ restore_backup: if (p_fs && (error = os_fsync(fd)) != 0 && !device // fsync not supported on this storage. && error != UV_ENOTSUP) { - SET_ERRMSG_ARG(e_fsync, error); + err = set_err_arg(e_fsync, error); end = 0; } @@ -3253,7 +3284,7 @@ restore_backup: #endif if ((error = os_close(fd)) != 0) { - SET_ERRMSG_ARG(_("E512: Close failed: %s"), error); + err = set_err_arg(_("E512: Close failed: %s"), error); end = 0; } @@ -3289,23 +3320,23 @@ restore_backup: if (end == 0) { // Error encountered. - if (errmsg == NULL) { + if (err.msg == NULL) { if (write_info.bw_conv_error) { if (write_info.bw_conv_error_lnum == 0) { - SET_ERRMSG(_("E513: write error, conversion failed " - "(make 'fenc' empty to override)")); + err = set_err(_("E513: write error, conversion failed " + "(make 'fenc' empty to override)")); } else { - errmsg_allocated = true; - SET_ERRMSG(xmalloc(300)); - vim_snprintf(errmsg, 300, // NOLINT(runtime/printf) + err = set_err(xmalloc(300)); + err.alloc = true; + vim_snprintf(err.msg, 300, // NOLINT(runtime/printf) _("E513: write error, conversion failed in line %" PRIdLINENR " (make 'fenc' empty to override)"), write_info.bw_conv_error_lnum); } } else if (got_int) { - SET_ERRMSG(_(e_interr)); + err = set_err(_(e_interr)); } else { - SET_ERRMSG(_("E514: write error (file system full?)")); + err = set_err(_("E514: write error (file system full?)")); } } @@ -3486,27 +3517,14 @@ nofail: os_free_acl(acl); #endif - if (errmsg != NULL) { + if (err.msg != NULL) { // - 100 to save some space for further error message #ifndef UNIX add_quoted_fname(IObuff, IOSIZE - 100, buf, (const char *)sfname); #else add_quoted_fname(IObuff, IOSIZE - 100, buf, (const char *)fname); #endif - if (errnum != NULL) { - if (errmsgarg != 0) { - semsg("%s: %s%s: %s", errnum, IObuff, errmsg, os_strerror(errmsgarg)); - } else { - semsg("%s: %s%s", errnum, IObuff, errmsg); - } - } else if (errmsgarg != 0) { - semsg(errmsg, os_strerror(errmsgarg)); - } else { - emsg(errmsg); - } - if (errmsg_allocated) { - xfree(errmsg); - } + emit_err(&err); retval = FAIL; if (end == 0) { @@ -3570,9 +3588,6 @@ nofail: got_int |= prev_got_int; return retval; -#undef SET_ERRMSG -#undef SET_ERRMSG_ARG -#undef SET_ERRMSG_NUM } /// Set the name of the current buffer. Use when the buffer doesn't have a -- cgit From cb3be2c766b79cf7a9ba642a565fa87aab76d2ab Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 31 Jan 2023 09:27:22 +0000 Subject: refactor(fileio.c): factor out buf_write post autocmds --- src/nvim/fileio.c | 55 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index c5c5a26d9d..047abebde0 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2252,6 +2252,35 @@ static int buf_write_do_autocmds(buf_T *buf, char **fnamep, char **sfnamep, char return NOTDONE; } +static void buf_write_do_post_autocmds(buf_T *buf, char *fname, exarg_T *eap, bool append, + bool filtering, bool reset_changed, bool whole) +{ + aco_save_T aco; + + curbuf->b_no_eol_lnum = 0; // in case it was set by the previous read + + // Apply POST autocommands. + // Careful: The autocommands may call buf_write() recursively! + aucmd_prepbuf(&aco, buf); + + if (append) { + apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname, + false, curbuf, eap); + } else if (filtering) { + apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname, + false, curbuf, eap); + } else if (reset_changed && whole) { + apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname, + false, curbuf, eap); + } else { + apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname, + false, curbuf, eap); + } + + // restore curwin/curbuf and a few other things + aucmd_restbuf(&aco); +} + static inline Error_T set_err_num(const char *num, const char *msg) { return (Error_T){ .num = num, .msg = (char *)msg, .arg = 0 }; @@ -3555,31 +3584,7 @@ nofail: } if (!should_abort(retval)) { - aco_save_T aco; - - curbuf->b_no_eol_lnum = 0; // in case it was set by the previous read - - // Apply POST autocommands. - // Careful: The autocommands may call buf_write() recursively! - aucmd_prepbuf(&aco, buf); - - if (append) { - apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname, - false, curbuf, eap); - } else if (filtering) { - apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname, - false, curbuf, eap); - } else if (reset_changed && whole) { - apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname, - false, curbuf, eap); - } else { - apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname, - false, curbuf, eap); - } - - // restore curwin/curbuf and a few other things - aucmd_restbuf(&aco); - + buf_write_do_post_autocmds(buf, fname, eap, append, filtering, reset_changed, whole); if (aborting()) { // autocmds may abort script processing retval = false; } -- cgit From eacdece35426ce6e929fdd44d4ea331dc8317ea4 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 31 Jan 2023 09:24:41 +0000 Subject: refactor(fileio.c): factor out file info calc --- src/nvim/fileio.c | 205 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 122 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 047abebde0..cad48aee52 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -125,6 +125,8 @@ typedef struct { bool alloc; } Error_T; +static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')"; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "fileio.c.generated.h" #endif @@ -2314,6 +2316,111 @@ static void emit_err(Error_T *e) } } +#if defined(UNIX) + +static int get_fileinfo_os(char *fname, FileInfo *file_info_old, bool overwriting, long *perm, + bool *device, bool *newfile, Error_T *err) +{ + *perm = -1; + if (!os_fileinfo(fname, file_info_old)) { + *newfile = true; + } else { + *perm = (long)file_info_old->stat.st_mode; + if (!S_ISREG(file_info_old->stat.st_mode)) { // not a file + if (S_ISDIR(file_info_old->stat.st_mode)) { + *err = set_err_num("E502", _("is a directory")); + return FAIL; + } + if (os_nodetype(fname) != NODE_WRITABLE) { + *err = set_err_num("E503", _("is not a file or writable device")); + return FAIL; + } + // It's a device of some kind (or a fifo) which we can write to + // but for which we can't make a backup. + *device = true; + *newfile = true; + *perm = -1; + } + } + return OK; +} + +#else + +static int get_fileinfo_os(char *fname, FileInfo *file_info_old, bool overwriting, long *perm, + bool *device, bool *newfile, Error_T *err) +{ + // Check for a writable device name. + char nodetype = fname == NULL ? NODE_OTHER : (char)os_nodetype(fname); + if (nodetype == NODE_OTHER) { + *err = set_err_num("E503", _("is not a file or writable device")); + return FAIL; + } + if (nodetype == NODE_WRITABLE) { + *device = true; + *newfile = true; + *perm = -1; + } else { + *perm = os_getperm((const char *)fname); + if (*perm < 0) { + *newfile = true; + } else if (os_isdir(fname)) { + *err = set_err_num("E502", _("is a directory")); + return FAIL; + } + if (overwriting) { + os_fileinfo(fname, file_info_old); + } + } + return OK; +} + +#endif + +/// @param buf +/// @param fname File name +/// @param overwriting +/// @param forceit +/// @param[out] file_info_old +/// @param[out] perm +/// @param[out] device +/// @param[out] newfile +/// @param[out] readonly +static int get_fileinfo(buf_T *buf, char *fname, bool overwriting, bool forceit, + FileInfo *file_info_old, long *perm, bool *device, bool *newfile, + bool *readonly, Error_T *err) +{ + if (get_fileinfo_os(fname, file_info_old, overwriting, perm, device, newfile, err) == FAIL) { + return FAIL; + } + + *readonly = false; // overwritten file is read-only + + if (!*device && !*newfile) { + // Check if the file is really writable (when renaming the file to + // make a backup we won't discover it later). + *readonly = !os_file_is_writable(fname); + + if (!forceit && *readonly) { + if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) { + *err = set_err_num("E504", _(err_readonly)); + } else { + *err = set_err_num("E505", _("is read-only (add ! to override)")); + } + return FAIL; + } + + // If 'forceit' is false, check if the timestamp hasn't changed since reading the file. + if (overwriting && !forceit) { + int retval = check_mtime(buf, file_info_old); + if (retval == FAIL) { + return FAIL; + } + } + } + return OK; +} + /// buf_write() - write to file "fname" lines "start" through "end" /// /// We do our own buffering here because fwrite() is so slow. @@ -2338,8 +2445,6 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en int retval = OK; int msg_save = msg_scroll; int prev_got_int = got_int; - static char *err_readonly = - "is read-only (cannot override: \"W\" in 'cpoptions')"; // writing everything int whole = (start == 1 && end == buf->b_ml.ml_line_count); int write_undo_file = false; @@ -2467,8 +2572,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en } Error_T err = { 0 }; - int newfile = false; // true if file doesn't exist yet - int device = false; // writing to a device + long perm; // file permissions + bool newfile = false; // true if file doesn't exist yet + bool device = false; // writing to a device + bool file_readonly = false; // overwritten file is read-only char *backup = NULL; char *fenc_tofree = NULL; // allocated "fenc" @@ -2480,78 +2587,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en // backup or new file #endif - long perm; // file permissions -#if defined(UNIX) - perm = -1; - if (!os_fileinfo(fname, &file_info_old)) { - newfile = true; - } else { - perm = (long)file_info_old.stat.st_mode; - if (!S_ISREG(file_info_old.stat.st_mode)) { // not a file - if (S_ISDIR(file_info_old.stat.st_mode)) { - err = set_err_num("E502", _("is a directory")); - goto fail; - } - if (os_nodetype(fname) != NODE_WRITABLE) { - err = set_err_num("E503", _("is not a file or writable device")); - goto fail; - } - // It's a device of some kind (or a fifo) which we can write to - // but for which we can't make a backup. - device = true; - newfile = true; - perm = -1; - } - } -#else // win32 - // Check for a writable device name. - char nodetype = fname == NULL ? NODE_OTHER : os_nodetype(fname); - if (nodetype == NODE_OTHER) { - err = set_err_num("E503", _("is not a file or writable device")); + if (get_fileinfo(buf, fname, overwriting, forceit, &file_info_old, &perm, &device, &newfile, + &file_readonly, &err) == FAIL) { goto fail; } - if (nodetype == NODE_WRITABLE) { - device = true; - newfile = true; - perm = -1; - } else { - perm = os_getperm((const char *)fname); - if (perm < 0) { - newfile = true; - } else if (os_isdir(fname)) { - err = set_err_num("E502", _("is a directory")); - goto fail; - } - if (overwriting) { - os_fileinfo(fname, &file_info_old); - } - } -#endif // !UNIX - - bool file_readonly = false; // overwritten file is read-only - - if (!device && !newfile) { - // Check if the file is really writable (when renaming the file to - // make a backup we won't discover it later). - file_readonly = !os_file_is_writable(fname); - - if (!forceit && file_readonly) { - if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) { - err = set_err_num("E504", _(err_readonly)); - } else { - err = set_err_num("E505", _("is read-only (add ! to override)")); - } - goto fail; - } - - // If 'forceit' is false, check if the timestamp hasn't changed since reading the file. - if (overwriting && !forceit) { - retval = check_mtime(buf, &file_info_old); - if (retval == FAIL) { - goto fail; - } - } - } #ifdef HAVE_ACL // For systems that support ACL: get the ACL from the original file. @@ -3407,37 +3446,37 @@ restore_backup: #endif if (!filtering) { add_quoted_fname(IObuff, IOSIZE, buf, (const char *)fname); - char c = false; + bool insert_space = false; if (write_info.bw_conv_error) { STRCAT(IObuff, _(" CONVERSION ERROR")); - c = true; + insert_space = true; if (write_info.bw_conv_error_lnum != 0) { vim_snprintf_add(IObuff, IOSIZE, _(" in line %" PRId64 ";"), (int64_t)write_info.bw_conv_error_lnum); } } else if (notconverted) { STRCAT(IObuff, _("[NOT converted]")); - c = true; + insert_space = true; } else if (converted) { STRCAT(IObuff, _("[converted]")); - c = true; + insert_space = true; } if (device) { STRCAT(IObuff, _("[Device]")); - c = true; + insert_space = true; } else if (newfile) { STRCAT(IObuff, new_file_message()); - c = true; + insert_space = true; } if (no_eol) { msg_add_eol(); - c = true; + insert_space = true; } // may add [unix/dos/mac] if (msg_add_fileformat(fileformat)) { - c = true; + insert_space = true; } - msg_add_lines(c, (long)lnum, nchars); // add line/char count + msg_add_lines(insert_space, (long)lnum, nchars); // add line/char count if (!shortmess(SHM_WRITE)) { if (append) { STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended")); -- cgit From 33a183e8981de7894968a0d2aef836d9296786a7 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 31 Jan 2023 10:04:44 +0000 Subject: refactor(fileio.c): make unreadable expression readable --- src/nvim/fileio.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index cad48aee52..098db6b4af 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -3090,14 +3090,12 @@ nobackup: // quotum for number of files). // Appending will fail if the file does not exist and forceit is // false. - while ((fd = os_open(wfname, - O_WRONLY | - (append - ? (forceit - ? (O_APPEND | O_CREAT) - : O_APPEND) - : (O_CREAT | O_TRUNC)), - perm < 0 ? 0666 : (perm & 0777))) < 0) { + const int fflags = O_WRONLY | (append + ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND) + : (O_CREAT | O_TRUNC)); + const int mode = perm < 0 ? 0666 : (perm & 0777); + + while ((fd = os_open(wfname, fflags, mode)) < 0) { // A forced write will try to create a new file if the old one // is still readonly. This may also happen when the directory // is read-only. In that case the mch_remove() will fail. -- cgit From c1a3865c476844e1b30200e2e7f3f9f2fa682329 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 31 Jan 2023 11:26:43 +0000 Subject: refactor(fileio.c): factor out backup creation --- src/nvim/fileio.c | 635 +++++++++++++++++++++++++++--------------------------- 1 file changed, 322 insertions(+), 313 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 098db6b4af..4b3a52759d 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2421,6 +2421,324 @@ static int get_fileinfo(buf_T *buf, char *fname, bool overwriting, bool forceit, return OK; } +static int buf_write_make_backup(char *fname, bool append, FileInfo *file_info_old, vim_acl_T acl, + long perm, unsigned int bkc, bool file_readonly, bool forceit, + int *backup_copyp, char **backupp, Error_T *err) +{ + FileInfo file_info; + const bool no_prepend_dot = false; + + if ((bkc & BKC_YES) || append) { // "yes" + *backup_copyp = true; + } else if ((bkc & BKC_AUTO)) { // "auto" + // Don't rename the file when: + // - it's a hard link + // - it's a symbolic link + // - we don't have write permission in the directory + if (os_fileinfo_hardlinks(file_info_old) > 1 + || !os_fileinfo_link(fname, &file_info) + || !os_fileinfo_id_equal(&file_info, file_info_old)) { + *backup_copyp = true; + } else { + // Check if we can create a file and set the owner/group to + // the ones from the original file. + // First find a file name that doesn't exist yet (use some + // arbitrary numbers). + STRCPY(IObuff, fname); + for (int i = 4913;; i += 123) { + char *tail = path_tail(IObuff); + size_t size = (size_t)(tail - IObuff); + snprintf(tail, IOSIZE - size, "%d", i); + if (!os_fileinfo_link(IObuff, &file_info)) { + break; + } + } + int fd = os_open(IObuff, + O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, (int)perm); + if (fd < 0) { // can't write in directory + *backup_copyp = true; + } else { +#ifdef UNIX + os_fchown(fd, (uv_uid_t)file_info_old->stat.st_uid, (uv_gid_t)file_info_old->stat.st_gid); + if (!os_fileinfo(IObuff, &file_info) + || file_info.stat.st_uid != file_info_old->stat.st_uid + || file_info.stat.st_gid != file_info_old->stat.st_gid + || (long)file_info.stat.st_mode != perm) { + *backup_copyp = true; + } +#endif + // Close the file before removing it, on MS-Windows we + // can't delete an open file. + close(fd); + os_remove(IObuff); + } + } + } + + // Break symlinks and/or hardlinks if we've been asked to. + if ((bkc & BKC_BREAKSYMLINK) || (bkc & BKC_BREAKHARDLINK)) { +#ifdef UNIX + bool file_info_link_ok = os_fileinfo_link(fname, &file_info); + + // Symlinks. + if ((bkc & BKC_BREAKSYMLINK) + && file_info_link_ok + && !os_fileinfo_id_equal(&file_info, file_info_old)) { + *backup_copyp = false; + } + + // Hardlinks. + if ((bkc & BKC_BREAKHARDLINK) + && os_fileinfo_hardlinks(file_info_old) > 1 + && (!file_info_link_ok + || os_fileinfo_id_equal(&file_info, file_info_old))) { + *backup_copyp = false; + } +#endif + } + + // make sure we have a valid backup extension to use + char *backup_ext = *p_bex == NUL ? ".bak" : p_bex; + + if (*backup_copyp) { + int some_error = false; + + // Try to make the backup in each directory in the 'bdir' option. + // + // Unix semantics has it, that we may have a writable file, + // that cannot be recreated with a simple open(..., O_CREAT, ) e.g: + // - the directory is not writable, + // - the file may be a symbolic link, + // - the file may belong to another user/group, etc. + // + // For these reasons, the existing writable file must be truncated + // and reused. Creation of a backup COPY will be attempted. + char *dirp = p_bdir; + while (*dirp) { + // Isolate one directory name, using an entry in 'bdir'. + size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ","); + char *p = IObuff + dir_len; + bool trailing_pathseps = after_pathsep(IObuff, p) && p[-1] == p[-2]; + if (trailing_pathseps) { + IObuff[dir_len - 2] = NUL; + } + if (*dirp == NUL && !os_isdir(IObuff)) { + int ret; + char *failed_dir; + if ((ret = os_mkdir_recurse(IObuff, 0755, &failed_dir)) != 0) { + semsg(_("E303: Unable to create directory \"%s\" for backup file: %s"), + failed_dir, os_strerror(ret)); + xfree(failed_dir); + } + } + if (trailing_pathseps) { + // Ends with '//', Use Full path + if ((p = make_percent_swname(IObuff, fname)) + != NULL) { + *backupp = modname(p, backup_ext, no_prepend_dot); + xfree(p); + } + } + + char *rootname = get_file_in_dir(fname, IObuff); + if (rootname == NULL) { + some_error = true; // out of memory + goto nobackup; + } + + FileInfo file_info_new; + { + // + // Make the backup file name. + // + if (*backupp == NULL) { + *backupp = modname(rootname, backup_ext, no_prepend_dot); + } + + if (*backupp == NULL) { + xfree(rootname); + some_error = true; // out of memory + goto nobackup; + } + + // Check if backup file already exists. + if (os_fileinfo(*backupp, &file_info_new)) { + if (os_fileinfo_id_equal(&file_info_new, file_info_old)) { + // + // Backup file is same as original file. + // May happen when modname() gave the same file back (e.g. silly + // link). If we don't check here, we either ruin the file when + // copying or erase it after writing. + // + XFREE_CLEAR(*backupp); // no backup file to delete + } else if (!p_bk) { + // We are not going to keep the backup file, so don't + // delete an existing one, and try to use another name instead. + // Change one character, just before the extension. + // + char *wp = *backupp + strlen(*backupp) - 1 - strlen(backup_ext); + if (wp < *backupp) { // empty file name ??? + wp = *backupp; + } + *wp = 'z'; + while (*wp > 'a' && os_fileinfo(*backupp, &file_info_new)) { + (*wp)--; + } + // They all exist??? Must be something wrong. + if (*wp == 'a') { + XFREE_CLEAR(*backupp); + } + } + } + } + xfree(rootname); + + // Try to create the backup file + if (*backupp != NULL) { + // remove old backup, if present + os_remove(*backupp); + + // set file protection same as original file, but + // strip s-bit. + (void)os_setperm((const char *)(*backupp), perm & 0777); + +#ifdef UNIX + // + // Try to set the group of the backup same as the original file. If + // this fails, set the protection bits for the group same as the + // protection bits for others. + // + if (file_info_new.stat.st_gid != file_info_old->stat.st_gid + && os_chown(*backupp, (uv_uid_t)-1, (uv_gid_t)file_info_old->stat.st_gid) != 0) { + os_setperm((const char *)(*backupp), + ((int)perm & 0707) | (((int)perm & 07) << 3)); + } +#endif + + // copy the file + if (os_copy(fname, *backupp, UV_FS_COPYFILE_FICLONE) != 0) { + *err = set_err(_("E509: Cannot create backup file (add ! to override)")); + XFREE_CLEAR(*backupp); + *backupp = NULL; + continue; + } + +#ifdef UNIX + os_file_settime(*backupp, + (double)file_info_old->stat.st_atim.tv_sec, + (double)file_info_old->stat.st_mtim.tv_sec); +#endif +#ifdef HAVE_ACL + os_set_acl(*backupp, acl); +#endif + *err = set_err(NULL); + break; + } + } + +nobackup: + if (*backupp == NULL && err->msg == NULL) { + *err = set_err(_("E509: Cannot create backup file (add ! to override)")); + } + // Ignore errors when forceit is true. + if ((some_error || err->msg != NULL) && !forceit) { + return FAIL; + } + *err = set_err(NULL); + } else { + // Make a backup by renaming the original file. + + // If 'cpoptions' includes the "W" flag, we don't want to + // overwrite a read-only file. But rename may be possible + // anyway, thus we need an extra check here. + if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL) { + *err = set_err_num("E504", _(err_readonly)); + return FAIL; + } + + // Form the backup file name - change path/fo.o.h to + // path/fo.o.h.bak Try all directories in 'backupdir', first one + // that works is used. + char *dirp = p_bdir; + while (*dirp) { + // Isolate one directory name and make the backup file name. + size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ","); + char *p = IObuff + dir_len; + bool trailing_pathseps = after_pathsep(IObuff, p) && p[-1] == p[-2]; + if (trailing_pathseps) { + IObuff[dir_len - 2] = NUL; + } + if (*dirp == NUL && !os_isdir(IObuff)) { + int ret; + char *failed_dir; + if ((ret = os_mkdir_recurse(IObuff, 0755, &failed_dir)) != 0) { + semsg(_("E303: Unable to create directory \"%s\" for backup file: %s"), + failed_dir, os_strerror(ret)); + xfree(failed_dir); + } + } + if (trailing_pathseps) { + // path ends with '//', use full path + if ((p = make_percent_swname(IObuff, fname)) + != NULL) { + *backupp = modname(p, backup_ext, no_prepend_dot); + xfree(p); + } + } + + if (*backupp == NULL) { + char *rootname = get_file_in_dir(fname, IObuff); + if (rootname == NULL) { + *backupp = NULL; + } else { + *backupp = modname(rootname, backup_ext, no_prepend_dot); + xfree(rootname); + } + } + + if (*backupp != NULL) { + // If we are not going to keep the backup file, don't + // delete an existing one, try to use another name. + // Change one character, just before the extension. + if (!p_bk && os_path_exists(*backupp)) { + p = *backupp + strlen(*backupp) - 1 - strlen(backup_ext); + if (p < *backupp) { // empty file name ??? + p = *backupp; + } + *p = 'z'; + while (*p > 'a' && os_path_exists(*backupp)) { + (*p)--; + } + // They all exist??? Must be something wrong! + if (*p == 'a') { + XFREE_CLEAR(*backupp); + } + } + } + if (*backupp != NULL) { + // Delete any existing backup and move the current version + // to the backup. For safety, we don't remove the backup + // until the write has finished successfully. And if the + // 'backup' option is set, leave it around. + + // If the renaming of the original file to the backup file + // works, quit here. + /// + if (vim_rename(fname, *backupp) == 0) { + break; + } + + XFREE_CLEAR(*backupp); // don't do the rename below + } + } + if (*backupp == NULL && !forceit) { + *err = set_err(_("E510: Can't make backup file (add ! to override)")); + return FAIL; + } + } + return OK; +} + /// buf_write() - write to file "fname" lines "start" through "end" /// /// We do our own buffering here because fwrite() is so slow. @@ -2582,10 +2900,8 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en // Get information about original file (if there is one). FileInfo file_info_old; -#ifdef HAVE_ACL vim_acl_T acl = NULL; // ACL copied from original file to // backup or new file -#endif if (get_fileinfo(buf, fname, overwriting, forceit, &file_info_old, &perm, &device, &newfile, &file_readonly, &err) == FAIL) { @@ -2623,317 +2939,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en // Do not make any backup, if 'writebackup' and 'backup' are both switched // off. This helps when editing large files on almost-full disks. if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup) { - FileInfo file_info; - const bool no_prepend_dot = false; - - if ((bkc & BKC_YES) || append) { // "yes" - backup_copy = true; - } else if ((bkc & BKC_AUTO)) { // "auto" - // Don't rename the file when: - // - it's a hard link - // - it's a symbolic link - // - we don't have write permission in the directory - if (os_fileinfo_hardlinks(&file_info_old) > 1 - || !os_fileinfo_link(fname, &file_info) - || !os_fileinfo_id_equal(&file_info, &file_info_old)) { - backup_copy = true; - } else { - // Check if we can create a file and set the owner/group to - // the ones from the original file. - // First find a file name that doesn't exist yet (use some - // arbitrary numbers). - STRCPY(IObuff, fname); - for (int i = 4913;; i += 123) { - char *tail = path_tail(IObuff); - size_t size = (size_t)(tail - IObuff); - snprintf(tail, IOSIZE - size, "%d", i); - if (!os_fileinfo_link(IObuff, &file_info)) { - break; - } - } - int fd = os_open(IObuff, - O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, (int)perm); - if (fd < 0) { // can't write in directory - backup_copy = true; - } else { -#ifdef UNIX - os_fchown(fd, (uv_uid_t)file_info_old.stat.st_uid, (uv_gid_t)file_info_old.stat.st_gid); - if (!os_fileinfo(IObuff, &file_info) - || file_info.stat.st_uid != file_info_old.stat.st_uid - || file_info.stat.st_gid != file_info_old.stat.st_gid - || (long)file_info.stat.st_mode != perm) { - backup_copy = true; - } -#endif - // Close the file before removing it, on MS-Windows we - // can't delete an open file. - close(fd); - os_remove(IObuff); - } - } - } - - // Break symlinks and/or hardlinks if we've been asked to. - if ((bkc & BKC_BREAKSYMLINK) || (bkc & BKC_BREAKHARDLINK)) { -#ifdef UNIX - bool file_info_link_ok = os_fileinfo_link(fname, &file_info); - - // Symlinks. - if ((bkc & BKC_BREAKSYMLINK) - && file_info_link_ok - && !os_fileinfo_id_equal(&file_info, &file_info_old)) { - backup_copy = false; - } - - // Hardlinks. - if ((bkc & BKC_BREAKHARDLINK) - && os_fileinfo_hardlinks(&file_info_old) > 1 - && (!file_info_link_ok - || os_fileinfo_id_equal(&file_info, &file_info_old))) { - backup_copy = false; - } -#endif - } - - // make sure we have a valid backup extension to use - char *backup_ext = *p_bex == NUL ? ".bak" : p_bex; - - if (backup_copy) { - int some_error = false; - - // Try to make the backup in each directory in the 'bdir' option. - // - // Unix semantics has it, that we may have a writable file, - // that cannot be recreated with a simple open(..., O_CREAT, ) e.g: - // - the directory is not writable, - // - the file may be a symbolic link, - // - the file may belong to another user/group, etc. - // - // For these reasons, the existing writable file must be truncated - // and reused. Creation of a backup COPY will be attempted. - char *dirp = p_bdir; - while (*dirp) { - // Isolate one directory name, using an entry in 'bdir'. - size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ","); - char *p = IObuff + dir_len; - bool trailing_pathseps = after_pathsep(IObuff, p) && p[-1] == p[-2]; - if (trailing_pathseps) { - IObuff[dir_len - 2] = NUL; - } - if (*dirp == NUL && !os_isdir(IObuff)) { - int ret; - char *failed_dir; - if ((ret = os_mkdir_recurse(IObuff, 0755, &failed_dir)) != 0) { - semsg(_("E303: Unable to create directory \"%s\" for backup file: %s"), - failed_dir, os_strerror(ret)); - xfree(failed_dir); - } - } - if (trailing_pathseps) { - // Ends with '//', Use Full path - if ((p = make_percent_swname(IObuff, fname)) - != NULL) { - backup = modname(p, backup_ext, no_prepend_dot); - xfree(p); - } - } - - char *rootname = get_file_in_dir(fname, IObuff); - if (rootname == NULL) { - some_error = true; // out of memory - goto nobackup; - } - - FileInfo file_info_new; - { - // - // Make the backup file name. - // - if (backup == NULL) { - backup = modname(rootname, backup_ext, no_prepend_dot); - } - - if (backup == NULL) { - xfree(rootname); - some_error = true; // out of memory - goto nobackup; - } - - // Check if backup file already exists. - if (os_fileinfo(backup, &file_info_new)) { - if (os_fileinfo_id_equal(&file_info_new, &file_info_old)) { - // - // Backup file is same as original file. - // May happen when modname() gave the same file back (e.g. silly - // link). If we don't check here, we either ruin the file when - // copying or erase it after writing. - // - XFREE_CLEAR(backup); // no backup file to delete - } else if (!p_bk) { - // We are not going to keep the backup file, so don't - // delete an existing one, and try to use another name instead. - // Change one character, just before the extension. - // - char *wp = backup + strlen(backup) - 1 - strlen(backup_ext); - if (wp < backup) { // empty file name ??? - wp = backup; - } - *wp = 'z'; - while (*wp > 'a' && os_fileinfo(backup, &file_info_new)) { - (*wp)--; - } - // They all exist??? Must be something wrong. - if (*wp == 'a') { - XFREE_CLEAR(backup); - } - } - } - } - xfree(rootname); - - // Try to create the backup file - if (backup != NULL) { - // remove old backup, if present - os_remove(backup); - - // set file protection same as original file, but - // strip s-bit. - (void)os_setperm((const char *)backup, perm & 0777); - -#ifdef UNIX - // - // Try to set the group of the backup same as the original file. If - // this fails, set the protection bits for the group same as the - // protection bits for others. - // - if (file_info_new.stat.st_gid != file_info_old.stat.st_gid - && os_chown(backup, (uv_uid_t)-1, (uv_gid_t)file_info_old.stat.st_gid) != 0) { - os_setperm((const char *)backup, - ((int)perm & 0707) | (((int)perm & 07) << 3)); - } -#endif - - // copy the file - if (os_copy(fname, backup, UV_FS_COPYFILE_FICLONE) != 0) { - err = set_err(_("E509: Cannot create backup file (add ! to override)")); - XFREE_CLEAR(backup); - backup = NULL; - continue; - } - -#ifdef UNIX - os_file_settime(backup, - (double)file_info_old.stat.st_atim.tv_sec, - (double)file_info_old.stat.st_mtim.tv_sec); -#endif -#ifdef HAVE_ACL - os_set_acl(backup, acl); -#endif - err = set_err(NULL); - break; - } - } - -nobackup: - if (backup == NULL && err.msg == NULL) { - err = set_err(_("E509: Cannot create backup file (add ! to override)")); - } - // Ignore errors when forceit is true. - if ((some_error || err.msg != NULL) && !forceit) { - retval = FAIL; - goto fail; - } - err = set_err(NULL); - } else { - // Make a backup by renaming the original file. - - // If 'cpoptions' includes the "W" flag, we don't want to - // overwrite a read-only file. But rename may be possible - // anyway, thus we need an extra check here. - if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL) { - err = set_err_num("E504", _(err_readonly)); - goto fail; - } - - // Form the backup file name - change path/fo.o.h to - // path/fo.o.h.bak Try all directories in 'backupdir', first one - // that works is used. - char *dirp = p_bdir; - while (*dirp) { - // Isolate one directory name and make the backup file name. - size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ","); - char *p = IObuff + dir_len; - bool trailing_pathseps = after_pathsep(IObuff, p) && p[-1] == p[-2]; - if (trailing_pathseps) { - IObuff[dir_len - 2] = NUL; - } - if (*dirp == NUL && !os_isdir(IObuff)) { - int ret; - char *failed_dir; - if ((ret = os_mkdir_recurse(IObuff, 0755, &failed_dir)) != 0) { - semsg(_("E303: Unable to create directory \"%s\" for backup file: %s"), - failed_dir, os_strerror(ret)); - xfree(failed_dir); - } - } - if (trailing_pathseps) { - // path ends with '//', use full path - if ((p = make_percent_swname(IObuff, fname)) - != NULL) { - backup = modname(p, backup_ext, no_prepend_dot); - xfree(p); - } - } - - if (backup == NULL) { - char *rootname = get_file_in_dir(fname, IObuff); - if (rootname == NULL) { - backup = NULL; - } else { - backup = modname(rootname, backup_ext, no_prepend_dot); - xfree(rootname); - } - } - - if (backup != NULL) { - // If we are not going to keep the backup file, don't - // delete an existing one, try to use another name. - // Change one character, just before the extension. - if (!p_bk && os_path_exists(backup)) { - p = backup + strlen(backup) - 1 - strlen(backup_ext); - if (p < backup) { // empty file name ??? - p = backup; - } - *p = 'z'; - while (*p > 'a' && os_path_exists(backup)) { - (*p)--; - } - // They all exist??? Must be something wrong! - if (*p == 'a') { - XFREE_CLEAR(backup); - } - } - } - if (backup != NULL) { - // Delete any existing backup and move the current version - // to the backup. For safety, we don't remove the backup - // until the write has finished successfully. And if the - // 'backup' option is set, leave it around. - - // If the renaming of the original file to the backup file - // works, quit here. - /// - if (vim_rename(fname, backup) == 0) { - break; - } - - XFREE_CLEAR(backup); // don't do the rename below - } - } - if (backup == NULL && !forceit) { - err = set_err(_("E510: Can't make backup file (add ! to override)")); - goto fail; - } + if (buf_write_make_backup(fname, append, &file_info_old, acl, perm, bkc, file_readonly, forceit, + &backup_copy, &backup, &err) == FAIL) { + retval = FAIL; + goto fail; } } -- cgit From 42999a8d645ccf880222f0192671b8ce01bde361 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 30 Jan 2023 14:46:28 +0100 Subject: fix(test): fix issues detected by running unittests in ASAN/UBSAN --- src/nvim/lua/executor.c | 3 +++ src/nvim/marktree.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index d144a5ae23..1415ceeaed 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -821,6 +821,9 @@ void nlua_init(char **argv, int argc, int lua_arg0) luaL_openlibs(lstate); if (!nlua_state_init(lstate)) { os_errmsg(_("E970: Failed to initialize builtin lua modules\n")); +#ifdef EXITFREE + nlua_common_free_all_mem(lstate); +#endif os_exit(1); } diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c index 2036ddd21d..77ba6e6fa4 100644 --- a/src/nvim/marktree.c +++ b/src/nvim/marktree.c @@ -1182,7 +1182,7 @@ static size_t check_node(MarkTree *b, mtnode_t *x, mtpos_t *last, bool *last_rig assert(x->ptr[i] != x->ptr[j]); } } - } else { + } else if (x->n > 0) { *last = x->key[x->n - 1].pos; } return n_keys; -- cgit From 13aa23b62af4df3e7f10687b76fe8c04efa2a598 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 30 Jan 2023 20:36:49 +0100 Subject: refactor(tests): run unittests using main nvim binary in interpreter mode This allows us to get rid of the separate "nvim-test" target --- src/nvim/CMakeLists.txt | 31 +++++++++---------------------- src/nvim/tui/input.c | 16 +--------------- src/nvim/tui/input.h | 8 ++------ 3 files changed, 12 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 77ed0490d8..7b56af59da 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -52,7 +52,7 @@ if(PREFER_LUA) find_package(Lua 5.1 EXACT REQUIRED) target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LUA_INCLUDE_DIR}) target_link_libraries(main_lib INTERFACE ${LUA_LIBRARIES}) - # Passive (not REQUIRED): if LUAJIT_FOUND is not set, nvim-test is skipped. + # Passive (not REQUIRED): if LUAJIT_FOUND is not set, fixtures for unittests is skipped. find_package(LuaJit) else() find_package(LuaJit REQUIRED) @@ -679,6 +679,14 @@ if(UNIX) endif() endif() +if(NOT LUAJIT_FOUND) + message(STATUS "luajit not found, skipping unit tests") +elseif(CMAKE_BUILD_TYPE MATCHES Debug) + glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c) + list(APPEND NVIM_SOURCES ${UNIT_TEST_FIXTURES}) + target_compile_definitions(main_lib INTERFACE UNIT_TESTING) +endif() + target_sources(nvim PRIVATE ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} ${NVIM_GENERATED_SOURCES} ${NVIM_SOURCES} ${NVIM_HEADERS} ${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS}) @@ -837,27 +845,6 @@ set_target_properties( target_compile_definitions(libnvim PRIVATE MAKE_LIB) target_link_libraries(libnvim PRIVATE main_lib PUBLIC libuv_lib) -if(NOT LUAJIT_FOUND) - message(STATUS "luajit not found, skipping nvim-test (unit tests) target") -else() - glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c) - add_library( - nvim-test - MODULE - EXCLUDE_FROM_ALL - ${NVIM_SOURCES} ${NVIM_GENERATED_SOURCES} - ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} - ${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS} - ${UNIT_TEST_FIXTURES} - ) - target_link_libraries(nvim-test PRIVATE ${LUAJIT_LIBRARIES} main_lib PUBLIC libuv_lib) - if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - target_link_libraries(nvim-test PRIVATE "-framework CoreServices") - endif() - target_include_directories(nvim-test PRIVATE ${LUAJIT_INCLUDE_DIRS}) - target_compile_definitions(nvim-test PRIVATE UNIT_TESTING) -endif() - if(CLANG_ASAN_UBSAN) message(STATUS "Enabling Clang address sanitizer and undefined behavior sanitizer for nvim.") if(CI_BUILD) diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 2cb39ab26b..733aa25f03 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -117,14 +117,6 @@ static const struct kitty_key_map_entry { static Map(KittyKey, cstr_t) kitty_key_map = MAP_INIT; -#ifndef UNIT_TESTING -typedef enum { - kIncomplete = -1, - kNotApplicable = 0, - kComplete = 1, -} HandleState; -#endif - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "tui/input.c.generated.h" #endif @@ -584,7 +576,7 @@ static void set_bg(char *bgvalue) // ignored in the calculations. // // [1] https://en.wikipedia.org/wiki/Luma_%28video%29 -static HandleState handle_background_color(TermInput *input) +HandleState handle_background_color(TermInput *input) { if (input->waiting_for_bg_response <= 0) { return kNotApplicable; @@ -669,12 +661,6 @@ static HandleState handle_background_color(TermInput *input) } return kComplete; } -#ifdef UNIT_TESTING -HandleState ut_handle_background_color(TermInput *input) -{ - return handle_background_color(input); -} -#endif static void handle_raw_buffer(TermInput *input, bool force) { diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h index 5df108b107..d33cea6383 100644 --- a/src/nvim/tui/input.h +++ b/src/nvim/tui/input.h @@ -40,18 +40,14 @@ typedef struct term_input { TUIData *tui_data; } TermInput; -#ifdef INCLUDE_GENERATED_DECLARATIONS -# include "tui/input.h.generated.h" -#endif - -#ifdef UNIT_TESTING typedef enum { kIncomplete = -1, kNotApplicable = 0, kComplete = 1, } HandleState; -HandleState ut_handle_background_color(TermInput *input); +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "tui/input.h.generated.h" #endif #endif // NVIM_TUI_INPUT_H -- cgit From 249b9de4056d0e0a57c59bc533a0cf2b96c42436 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 1 Feb 2023 08:17:18 +0800 Subject: refactor(optionstr.c): align comments (#22070) Align comments in did_set_string_option_for() at column 57. --- src/nvim/optionstr.c | 276 ++++++++++++++++++++++++++------------------------- 1 file changed, 143 insertions(+), 133 deletions(-) (limited to 'src') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 30afb0db37..ca50c3ab00 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -638,13 +638,11 @@ char *check_stl_option(char *s) return NULL; } -static int shada_idx = -1; - +/// Check for a "normal" directory or file name in some options. Disallow a +/// path separator (slash and/or backslash), wildcards and characters that are +/// often illegal in a file name. Be more permissive if "secure" is off. static bool check_illegal_path_names(char *val, uint32_t flags) { - // Disallow a path separator (slash and/or backslash), wildcards and - // characters that are often illegal in a file name. Be more permissive - // if "secure" is off. return (((flags & P_NFNAME) && strpbrk(val, (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL) || ((flags & P_NDNAME) @@ -701,8 +699,8 @@ static void did_set_breakindentopt(win_T *win, char **errmsg) static void did_set_isopt(buf_T *buf, bool *did_chartab, char **errmsg) { // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[] - // If the new option is invalid, use old value. 'lisp' option: refill - // g_chartab[] for '-' char + // If the new option is invalid, use old value. + // 'lisp' option: refill g_chartab[] for '-' char if (buf_init_chartab(buf, true) == FAIL) { *did_chartab = true; // need to restore it below *errmsg = e_invarg; // error in value @@ -1013,6 +1011,8 @@ static void did_set_verbosefile(char **errmsg) } } +static int shada_idx = -1; + static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf, size_t errbuflen, char **errmsg) { @@ -1272,6 +1272,16 @@ static void did_set_completeopt(char **errmsg) } } +#ifdef BACKSLASH_IN_FILENAME +static void did_set_completeslash(buf_T *buf, char **errmsg) +{ + if (check_opt_strings(p_csl, p_csl_values, false) != OK + || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) { + *errmsg = e_invarg; + } +} +#endif + static void did_set_signcolumn(win_T *win, char **varp, const char *oldval, char **errmsg) { if (check_signcolumn(*varp) != OK) { @@ -1561,7 +1571,7 @@ static void do_filetype_autocmd(buf_T *buf, char **varp, int opt_flags, bool val } } -static void did_set_spelllang_source(win_T *win) +static void do_spelllang_source(win_T *win) { char fname[200]; char *q = win->w_s->b_p_spl; @@ -1614,238 +1624,238 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char char **gvarp = (char **)get_varp_scope(opt, OPT_GLOBAL); // Disallow changing some options from secure mode - if ((secure || sandbox != 0) - && (opt->flags & P_SECURE)) { + if ((secure || sandbox != 0) && (opt->flags & P_SECURE)) { errmsg = e_secure; - } else if (check_illegal_path_names(*varp, opt->flags)) { // Check for a "normal" directory or file name in some options. + } else if (check_illegal_path_names(*varp, opt->flags)) { errmsg = e_invarg; - } else if (gvarp == &p_bkc) { // 'backupcopy' + } else if (gvarp == &p_bkc) { // 'backupcopy' did_set_backupcopy(buf, oldval, opt_flags, &errmsg); - } else if (varp == &p_bex || varp == &p_pm) { // 'backupext' and 'patchmode' + } else if (varp == &p_bex // 'backupext' + || varp == &p_pm) { // 'patchmode' did_set_backupext_or_patchmode(&errmsg); - } else if (varp == &win->w_p_briopt) { // 'breakindentopt' + } else if (varp == &win->w_p_briopt) { // 'breakindentopt' did_set_breakindentopt(win, &errmsg); - } else if (varp == &p_isi - || varp == &buf->b_p_isk - || varp == &p_isp - || varp == &p_isf) { - // 'isident', 'iskeyword', 'isprint or 'isfname' option + } else if (varp == &p_isi // 'isident' + || varp == &buf->b_p_isk // 'iskeyword' + || varp == &p_isp // 'isprint' + || varp == &p_isf) { // 'isfname' did_set_isopt(buf, &did_chartab, &errmsg); - } else if (varp == &p_hf) { // 'helpfile' + } else if (varp == &p_hf) { // 'helpfile' did_set_helpfile(); - } else if (varp == &p_rtp || varp == &p_pp) { // 'runtimepath' 'packpath' + } else if (varp == &p_rtp // 'runtimepath' + || varp == &p_pp) { // 'packpath' runtime_search_path_invalidate(); - } else if (varp == &win->w_p_culopt - || gvarp == &win->w_allbuf_opt.wo_culopt) { // 'cursorlineopt' + } else if (gvarp == &win->w_allbuf_opt.wo_culopt) { // 'cursorlineopt' did_set_cursorlineopt(win, varp, &errmsg); - } else if (varp == &win->w_p_cc) { // 'colorcolumn' + } else if (varp == &win->w_p_cc) { // 'colorcolumn' errmsg = check_colorcolumn(win); - } else if (varp == &p_hlg) { // 'helplang' + } else if (varp == &p_hlg) { // 'helplang' did_set_helplang(&errmsg); - } else if (varp == &p_hl) { // 'highlight' + } else if (varp == &p_hl) { // 'highlight' did_set_highlight(varp, &errmsg); - } else if (varp == &p_jop) { // 'jumpoptions' + } else if (varp == &p_jop) { // 'jumpoptions' did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true, &errmsg); - } else if (gvarp == &p_nf) { // 'nrformats' + } else if (gvarp == &p_nf) { // 'nrformats' did_set_opt_strings(*varp, p_nf_values, true, &errmsg); - } else if (varp == &p_ssop) { // 'sessionoptions' + } else if (varp == &p_ssop) { // 'sessionoptions' did_set_sessionoptions(oldval, &errmsg); - } else if (varp == &p_vop) { // 'viewoptions' + } else if (varp == &p_vop) { // 'viewoptions' did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, true, &errmsg); - } else if (varp == &p_rdb) { // 'redrawdebug' + } else if (varp == &p_rdb) { // 'redrawdebug' did_set_opt_flags(p_rdb, p_rdb_values, &rdb_flags, true, &errmsg); - } else if (varp == &p_sbo) { // 'scrollopt' + } else if (varp == &p_sbo) { // 'scrollopt' did_set_opt_strings(p_sbo, p_scbopt_values, true, &errmsg); - } else if (varp == &p_ambw || (int *)varp == &p_emoji) { // 'ambiwidth' + } else if (varp == &p_ambw // 'ambiwidth' + || (int *)varp == &p_emoji) { // 'emoji' did_set_ambiwidth(&errmsg); - } else if (varp == &p_bg) { // 'background' + } else if (varp == &p_bg) { // 'background' did_set_background(&errmsg); - } else if (varp == &p_wim) { // 'wildmode' + } else if (varp == &p_wim) { // 'wildmode' did_set_wildmode(&errmsg); - } else if (varp == &p_wop) { // 'wildoptions' + } else if (varp == &p_wop) { // 'wildoptions' did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true, &errmsg); - } else if (varp == &p_wak) { // 'winaltkeys' + } else if (varp == &p_wak) { // 'winaltkeys' did_set_winaltkeys(&errmsg); - } else if (varp == &p_ei) { // 'eventignore' + } else if (varp == &p_ei) { // 'eventignore' did_set_eventignore(&errmsg); - } else if (varp == &p_enc || gvarp == &p_fenc || gvarp == &p_menc) { - // 'encoding', 'fileencoding' and 'makeencoding' + } else if (varp == &p_enc // 'encoding' + || gvarp == &p_fenc // 'fileencoding' + || gvarp == &p_menc) { // 'makeencoding' did_set_encoding(buf, varp, gvarp, opt_flags, &errmsg); - } else if (varp == &buf->b_p_keymap) { + } else if (varp == &buf->b_p_keymap) { // 'keymap' did_set_keymap(buf, varp, opt_flags, value_checked, &errmsg); - } else if (gvarp == &p_ff) { // 'fileformat' + } else if (gvarp == &p_ff) { // 'fileformat' did_set_fileformat(buf, varp, oldval, opt_flags, &errmsg); - } else if (varp == &p_ffs) { // 'fileformats' + } else if (varp == &p_ffs) { // 'fileformats' did_set_opt_strings(p_ffs, p_ff_values, true, &errmsg); - } else if (gvarp == &p_mps) { // 'matchpairs' + } else if (gvarp == &p_mps) { // 'matchpairs' did_set_matchpairs(varp, &errmsg); - } else if (gvarp == &p_com) { // 'comments' + } else if (gvarp == &p_com) { // 'comments' did_set_comments(varp, errbuf, errbuflen, &errmsg); - } else if (varp == &p_lcs || varp == &p_fcs) { // global 'listchars' or 'fillchars' + } else if (varp == &p_lcs // global 'listchars' + || varp == &p_fcs) { // global 'fillchars' did_set_global_listfillchars(win, varp, opt_flags, &errmsg); - } else if (varp == &win->w_p_lcs) { // local 'listchars' + } else if (varp == &win->w_p_lcs) { // local 'listchars' errmsg = set_chars_option(win, varp, true); - } else if (varp == &win->w_p_fcs) { // local 'fillchars' + } else if (varp == &win->w_p_fcs) { // local 'fillchars' errmsg = set_chars_option(win, varp, true); - } else if (varp == &p_cedit) { // 'cedit' + } else if (varp == &p_cedit) { // 'cedit' errmsg = check_cedit(); - } else if (varp == &p_vfile) { // 'verbosefile' + } else if (varp == &p_vfile) { // 'verbosefile' did_set_verbosefile(&errmsg); - } else if (varp == &p_shada) { // 'shada' + } else if (varp == &p_shada) { // 'shada' did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen, &errmsg); - } else if (gvarp == &p_sbr) { // 'showbreak' + } else if (gvarp == &p_sbr) { // 'showbreak' did_set_showbreak(varp, &errmsg); - } else if (varp == &p_guicursor) { // 'guicursor' + } else if (varp == &p_guicursor) { // 'guicursor' errmsg = parse_shape_opt(SHAPE_CURSOR); - } else if (varp == &p_langmap) { // 'langmap' + } else if (varp == &p_langmap) { // 'langmap' langmap_set(); - } else if (varp == &p_breakat) { // 'breakat' + } else if (varp == &p_breakat) { // 'breakat' fill_breakat_flags(); - } else if (varp == &p_titlestring || varp == &p_iconstring) { - // 'titlestring' and 'iconstring' + } else if (varp == &p_titlestring // 'titlestring' + || varp == &p_iconstring) { // 'iconstring' did_set_titleiconstring(varp); - } else if (varp == &p_sel) { // 'selection' + } else if (varp == &p_sel) { // 'selection' did_set_selection(&errmsg); - } else if (varp == &p_slm) { // 'selectmode' + } else if (varp == &p_slm) { // 'selectmode' did_set_opt_strings(p_slm, p_slm_values, true, &errmsg); - } else if (varp == &p_km) { // 'keymodel' + } else if (varp == &p_km) { // 'keymodel' did_set_keymodel(&errmsg); - } else if (varp == &p_mousem) { // 'mousemodel' + } else if (varp == &p_mousem) { // 'mousemodel' did_set_opt_strings(p_mousem, p_mousem_values, false, &errmsg); - } else if (varp == &p_mousescroll) { // 'mousescroll' + } else if (varp == &p_mousescroll) { // 'mousescroll' errmsg = check_mousescroll(p_mousescroll); - } else if (varp == &p_swb) { // 'switchbuf' + } else if (varp == &p_swb) { // 'switchbuf' did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true, &errmsg); - } else if (varp == &p_spk) { // 'splitkeep' + } else if (varp == &p_spk) { // 'splitkeep' did_set_opt_strings(p_spk, p_spk_values, false, &errmsg); - } else if (varp == &p_debug) { // 'debug' + } else if (varp == &p_debug) { // 'debug' did_set_opt_strings(p_debug, p_debug_values, true, &errmsg); - } else if (varp == &p_dy) { // 'display' + } else if (varp == &p_dy) { // 'display' did_set_display(&errmsg); - } else if (varp == &p_ead) { // 'eadirection' + } else if (varp == &p_ead) { // 'eadirection' did_set_opt_strings(p_ead, p_ead_values, false, &errmsg); - } else if (varp == &p_cb) { // 'clipboard' + } else if (varp == &p_cb) { // 'clipboard' did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true, &errmsg); - } else if (varp == &win->w_s->b_p_spf) { + } else if (varp == &win->w_s->b_p_spf) { // 'spellfile' did_set_spellfile(varp, &errmsg); - } else if (varp == &win->w_s->b_p_spl) { // 'spell' + } else if (varp == &win->w_s->b_p_spl) { // 'spell' did_set_spell(varp, &errmsg); - } else if (varp == &win->w_s->b_p_spc) { + } else if (varp == &win->w_s->b_p_spc) { // 'spellcapcheck' did_set_spellcapcheck(win, &errmsg); - } else if (varp == &win->w_s->b_p_spo) { // 'spelloptions' + } else if (varp == &win->w_s->b_p_spo) { // 'spelloptions' did_set_spelloptions(win, &errmsg); - } else if (varp == &p_sps) { // 'spellsuggest' + } else if (varp == &p_sps) { // 'spellsuggest' did_set_spellsuggest(&errmsg); - } else if (varp == &p_msm) { // 'mkspellmem' + } else if (varp == &p_msm) { // 'mkspellmem' did_set_mkspellmem(&errmsg); - } else if (gvarp == &p_bh) { + } else if (gvarp == &p_bh) { // 'bufhidden' did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false, &errmsg); - } else if (gvarp == &p_bt) { // 'buftype' + } else if (gvarp == &p_bt) { // 'buftype' did_set_buftype(buf, win, &errmsg); - } else if (gvarp == &p_stl || gvarp == &p_wbr || varp == &p_tal - || varp == &p_ruf || varp == &win->w_p_stc) { - // 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn' + } else if (gvarp == &p_stl // 'statusline' + || gvarp == &p_wbr // 'winbar' + || varp == &p_tal // 'tabline' + || varp == &p_ruf // 'rulerformat' + || varp == &win->w_p_stc) { // 'statuscolumn' did_set_statusline(win, varp, gvarp, &errmsg); - } else if (gvarp == &p_cpt) { // 'complete' + } else if (gvarp == &p_cpt) { // 'complete' did_set_complete(varp, errbuf, errbuflen, &errmsg); - } else if (varp == &p_cot) { // 'completeopt' + } else if (varp == &p_cot) { // 'completeopt' did_set_completeopt(&errmsg); #ifdef BACKSLASH_IN_FILENAME - } else if (gvarp == &p_csl) { // 'completeslash' - if (check_opt_strings(p_csl, p_csl_values, false) != OK - || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) { - errmsg = e_invarg; - } + } else if (gvarp == &p_csl) { // 'completeslash' + did_set_completeslash(buf, &errmsg); #endif - } else if (varp == &win->w_p_scl) { // 'signcolumn' + } else if (varp == &win->w_p_scl) { // 'signcolumn' did_set_signcolumn(win, varp, oldval, &errmsg); - } else if (varp == &p_sloc) { // 'showcmdloc' + } else if (varp == &p_sloc) { // 'showcmdloc' did_set_opt_strings(*varp, p_sloc_values, false, &errmsg); - } else if (varp == &win->w_p_fdc - || varp == &win->w_allbuf_opt.wo_fdc) { - // 'foldcolumn' + } else if (gvarp == &win->w_allbuf_opt.wo_fdc) { // 'foldcolumn' did_set_foldcolumn(varp, &errmsg); - } else if (varp == &p_pt) { // 'pastetoggle' + } else if (varp == &p_pt) { // 'pastetoggle' did_set_pastetoggle(); - } else if (varp == &p_bs) { // 'backspace' + } else if (varp == &p_bs) { // 'backspace' did_set_backspace(&errmsg); } else if (varp == &p_bo) { did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true, &errmsg); - } else if (gvarp == &p_tc) { // 'tagcase' + } else if (gvarp == &p_tc) { // 'tagcase' did_set_tagcase(buf, opt_flags, &errmsg); - } else if (varp == &p_cmp) { // 'casemap' + } else if (varp == &p_cmp) { // 'casemap' did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true, &errmsg); - } else if (varp == &p_dip) { // 'diffopt' + } else if (varp == &p_dip) { // 'diffopt' did_set_diffopt(&errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fdm) { // 'foldmethod' + } else if (gvarp == &win->w_allbuf_opt.wo_fdm) { // 'foldmethod' did_set_foldmethod(win, varp, &errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fmr) { // 'foldmarker' + } else if (gvarp == &win->w_allbuf_opt.wo_fmr) { // 'foldmarker' did_set_foldmarker(win, varp, &errmsg); - } else if (gvarp == &p_cms) { // 'commentstring' + } else if (gvarp == &p_cms) { // 'commentstring' did_set_commentstring(varp, &errmsg); - } else if (varp == &p_fdo) { // 'foldopen' + } else if (varp == &p_fdo) { // 'foldopen' did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true, &errmsg); - } else if (varp == &p_fcl) { // 'foldclose' + } else if (varp == &p_fcl) { // 'foldclose' did_set_opt_strings(*varp, p_fcl_values, true, &errmsg); - } else if (gvarp == &win->w_allbuf_opt.wo_fdi) { // 'foldignore' + } else if (gvarp == &win->w_allbuf_opt.wo_fdi) { // 'foldignore' did_set_foldignore(win); - } else if (gvarp == &p_ve) { // 'virtualedit' + } else if (gvarp == &p_ve) { // 'virtualedit' did_set_virtualedit(win, opt_flags, oldval, &errmsg); - } else if (gvarp == &p_cino) { // 'cinoptions' + } else if (gvarp == &p_cino) { // 'cinoptions' // TODO(vim): recognize errors parse_cino(buf); - } else if (gvarp == &p_lop) { // 'lispoptions' + } else if (gvarp == &p_lop) { // 'lispoptions' did_set_lispoptions(varp, &errmsg); - } else if (varp == &p_icm) { // 'inccommand' + } else if (varp == &p_icm) { // 'inccommand' did_set_opt_strings(*varp, p_icm_values, false, &errmsg); - } else if (gvarp == &p_ft || gvarp == &p_syn) { + } else if (gvarp == &p_ft // 'filetype' + || gvarp == &p_syn) { // 'syntax' did_set_filetype_or_syntax(varp, oldval, value_checked, &value_changed, &errmsg); - } else if (varp == &win->w_p_winhl) { + } else if (varp == &win->w_p_winhl) { // 'winhighlight' did_set_winhl(win, &errmsg); } else if (varp == &p_tpf) { did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true, &errmsg); - } else if (varp == &buf->b_p_vsts) { // 'varsofttabstop' + } else if (varp == &buf->b_p_vsts) { // 'varsofttabstop' did_set_varsoftabstop(buf, varp, &errmsg); - } else if (varp == &buf->b_p_vts) { // 'vartabstop' + } else if (varp == &buf->b_p_vts) { // 'vartabstop' did_set_vartabstop(buf, win, varp, &errmsg); - } else if (varp == &p_dex // 'diffexpr' - || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr' - || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext' - || gvarp == &p_fex // 'formatexpr' - || gvarp == &p_inex // 'includeexpr' - || gvarp == &p_inde // 'indentexpr' - || varp == &p_pex // 'patchexpr' - || varp == &p_ccv) { // 'charconvert' + } else if (varp == &p_dex // 'diffexpr' + || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr' + || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext' + || gvarp == &p_fex // 'formatexpr' + || gvarp == &p_inex // 'includeexpr' + || gvarp == &p_inde // 'indentexpr' + || varp == &p_pex // 'patchexpr' + || varp == &p_ccv) { // 'charconvert' did_set_optexpr(varp); if (varp == &win->w_p_fde && foldmethodIsExpr(win)) { foldUpdateAll(win); } - } else if (gvarp == &p_cfu) { // 'completefunc' + } else if (gvarp == &p_cfu) { // 'completefunc' set_completefunc_option(&errmsg); - } else if (gvarp == &p_ofu) { // 'omnifunc' + } else if (gvarp == &p_ofu) { // 'omnifunc' set_omnifunc_option(buf, &errmsg); - } else if (gvarp == &p_tsrfu) { // 'thesaurusfunc' + } else if (gvarp == &p_tsrfu) { // 'thesaurusfunc' set_thesaurusfunc_option(&errmsg); - } else if (varp == &p_opfunc) { // 'operatorfunc' + } else if (varp == &p_opfunc) { // 'operatorfunc' set_operatorfunc_option(&errmsg); - } else if (varp == &p_qftf) { // 'quickfixtextfunc' + } else if (varp == &p_qftf) { // 'quickfixtextfunc' qf_process_qftf_option(&errmsg); - } else if (gvarp == &p_tfu) { // 'tagfunc' + } else if (gvarp == &p_tfu) { // 'tagfunc' set_tagfunc_option(&errmsg); - } else if (varp == &p_ww) { // 'whichwrap' + } else if (varp == &p_ww) { // 'whichwrap' did_set_option_listflag(varp, WW_ALL, errbuf, errbuflen, &errmsg); - } else if (varp == &p_shm) { // 'shortmess' + } else if (varp == &p_shm) { // 'shortmess' did_set_option_listflag(varp, SHM_ALL, errbuf, errbuflen, &errmsg); - } else if (varp == &p_cpo) { // 'cpoptions' + } else if (varp == &p_cpo) { // 'cpoptions' did_set_option_listflag(varp, CPO_VI, errbuf, errbuflen, &errmsg); - } else if (varp == &buf->b_p_fo) { // 'formatoptions' + } else if (varp == &buf->b_p_fo) { // 'formatoptions' did_set_option_listflag(varp, FO_ALL, errbuf, errbuflen, &errmsg); - } else if (varp == &win->w_p_cocu) { // 'concealcursor' + } else if (varp == &win->w_p_cocu) { // 'concealcursor' did_set_option_listflag(varp, COCU_ALL, errbuf, errbuflen, &errmsg); - } else if (varp == &p_mouse) { // 'mouse' + } else if (varp == &p_mouse) { // 'mouse' did_set_option_listflag(varp, MOUSE_ALL, errbuf, errbuflen, &errmsg); - } else if (gvarp == &p_flp) { + } else if (gvarp == &p_flp) { // 'formatlistpat' if (win->w_briopt_list) { // Changing Formatlistpattern when briopt includes the list setting: // redraw @@ -1853,7 +1863,7 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char } } - // If error detected, restore the previous value. + // If an error is detected, restore the previous value. if (errmsg != NULL) { free_string_option(*varp); *varp = oldval; @@ -1890,7 +1900,7 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char } else if (varp == &buf->b_p_ft) { do_filetype_autocmd(buf, varp, opt_flags, value_changed); } else if (varp == &win->w_s->b_p_spl) { - did_set_spelllang_source(win); + do_spelllang_source(win); } } -- cgit From 7880eeb2ee9d4a0d3eeeec58c8af9a144c8d5e77 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 1 Feb 2023 08:21:32 +0800 Subject: vim-patch:9.0.1270: crash when using search stat in narrow screen (#22078) Problem: Crash when using search stat in narrow screen. Solution: Check length of message. (closes vim/vim#11921) https://github.com/vim/vim/commit/a7d36b732070944aab614944075ec0b409311482 --- src/nvim/search.c | 7 ++++++- src/nvim/testdir/test_search_stat.vim | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/search.c b/src/nvim/search.c index b24b6ad27c..eb5cc2e07f 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -2644,7 +2644,12 @@ static void cmdline_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, bool sh len += 2; } - memmove(msgbuf + strlen(msgbuf) - len, t, len); + size_t msgbuf_len = strlen(msgbuf); + if (len > msgbuf_len) { + len = msgbuf_len; + } + memmove(msgbuf + msgbuf_len - len, t, len); + if (dirc == '?' && stat.cur == maxcount + 1) { stat.cur = -1; } diff --git a/src/nvim/testdir/test_search_stat.vim b/src/nvim/testdir/test_search_stat.vim index 77bd50ada2..1b2d854829 100644 --- a/src/nvim/testdir/test_search_stat.vim +++ b/src/nvim/testdir/test_search_stat.vim @@ -270,6 +270,29 @@ func Test_searchcount_fails() call assert_fails('echo searchcount({"pos" : [1, 2, []]})', 'E745:') endfunc +func Test_search_stat_narrow_screen() + " This used to crash Vim + let save_columns = &columns + try + let after =<< trim [CODE] + set laststatus=2 + set columns=16 + set shortmess-=S showcmd + call setline(1, 'abc') + call feedkeys("/abc\:quit!\") + autocmd VimLeavePre * call writefile(["done"], "Xdone") + [CODE] + + if !RunVim([], after, '--clean') + return + endif + call assert_equal("done", readfile("Xdone")[0]) + call delete('Xdone') + finally + let &columns = save_columns + endtry +endfunc + func Test_searchcount_in_statusline() CheckScreendump -- cgit From d63ad600e0571ccf07eed1e841e8519da7d4af9f Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 1 Feb 2023 10:08:50 +0100 Subject: vim-patch:9.0.1268: .clangd and .stylelintrc files don't get a filetype (#22079) Problem: .clangd and .stylelintrc files don't get a filetype. Solution: Use yaml for .clangd and json for .stylelintrc files. (Mark Skelton, closes vim/vim#11916) https://github.com/vim/vim/commit/9c51798a1f3b79ace5ae0551a8bb122025ac94ed Co-authored-by: Mark Skelton --- src/nvim/testdir/test_filetype.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index e366fd23ad..88c25ab115 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -295,7 +295,7 @@ let s:filename_checks = { \ 'jq': ['file.jq'], \ 'jovial': ['file.jov', 'file.j73', 'file.jovial'], \ 'jproperties': ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file', 'org.eclipse.xyz.prefs'], - \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.prettierrc', '.firebaserc', 'file.slnf'], + \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.prettierrc', '.firebaserc', '.stylelintrc', 'file.slnf'], \ 'json5': ['file.json5'], \ 'jsonc': ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json'], \ 'jsonnet': ['file.jsonnet', 'file.libsonnet'], @@ -657,7 +657,7 @@ let s:filename_checks = { \ 'xsd': ['file.xsd'], \ 'xslt': ['file.xsl', 'file.xslt'], \ 'yacc': ['file.yy', 'file.yxx', 'file.y++'], - \ 'yaml': ['file.yaml', 'file.yml', '.clang-format', '.clang-tidy'], + \ 'yaml': ['file.yaml', 'file.yml', '.clangd', '.clang-format', '.clang-tidy'], \ 'yang': ['file.yang'], \ 'z8a': ['file.z8a'], \ 'zig': ['file.zig'], -- cgit From 01d3a64e284749ac1ae40b0caf7165155063fc4f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 1 Feb 2023 18:07:09 +0800 Subject: vim-patch:8.1.1827: allocating more memory than needed for extended structs (#22081) Problem: Allocating more memory than needed for extended structs. Solution: Use offsetof() instead of sizeof(). (Dominique Pelle, closes vim/vim#4786) https://github.com/vim/vim/commit/47ed553fd5bebfc36eb8aa81686eeaa5a84eccac --- src/nvim/getchar.c | 2 +- src/nvim/regexp_bt.c | 2 +- src/nvim/sign.c | 2 +- src/nvim/sign_defs.h | 6 +++--- src/nvim/syntax.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 51554fea22..8ed9381bca 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -252,7 +252,7 @@ static void add_buff(buffheader_T *const buf, const char *const s, ptrdiff_t sle } else { len = (size_t)slen; } - buffblock_T *p = xmalloc(sizeof(buffblock_T) + len); + buffblock_T *p = xmalloc(offsetof(buffblock_T, b_str) + len + 1); buf->bh_space = len - (size_t)slen; xstrlcpy(p->b_str, s, (size_t)slen + 1); diff --git a/src/nvim/regexp_bt.c b/src/nvim/regexp_bt.c index 1b32447d77..af3d93f7c4 100644 --- a/src/nvim/regexp_bt.c +++ b/src/nvim/regexp_bt.c @@ -2862,7 +2862,7 @@ static regprog_T *bt_regcomp(uint8_t *expr, int re_flags) } // Allocate space. - bt_regprog_T *r = xmalloc(sizeof(bt_regprog_T) + (size_t)regsize); + bt_regprog_T *r = xmalloc(offsetof(bt_regprog_T, program) + (size_t)regsize); r->re_in_use = false; // Second pass: emit code. diff --git a/src/nvim/sign.c b/src/nvim/sign.c index d0c093d93a..00e282b76e 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -103,7 +103,7 @@ static signgroup_T *sign_group_ref(const char *groupname) hi = hash_lookup(&sg_table, (char *)groupname, strlen(groupname), hash); if (HASHITEM_EMPTY(hi)) { // new group - group = xmalloc(sizeof(signgroup_T) + strlen(groupname)); + group = xmalloc(offsetof(signgroup_T, sg_name) + strlen(groupname) + 1); STRCPY(group->sg_name, groupname); group->sg_refcount = 1; diff --git a/src/nvim/sign_defs.h b/src/nvim/sign_defs.h index 16e783aab7..7aa06ce48a 100644 --- a/src/nvim/sign_defs.h +++ b/src/nvim/sign_defs.h @@ -10,9 +10,9 @@ // Sign group typedef struct signgroup_S { - uint16_t sg_refcount; // number of signs in this group - int sg_next_sign_id; // next sign id for this group - char sg_name[1]; // sign group name + int sg_next_sign_id; ///< next sign id for this group + uint16_t sg_refcount; ///< number of signs in this group + char sg_name[1]; ///< sign group name, actually longer } signgroup_T; // Macros to get the sign group structure from the group name diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 05c570e52f..49b63ad324 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -3736,7 +3736,7 @@ static void add_keyword(char *const name, const int id, const int flags, sizeof(name_folded)) : name; - keyentry_T *const kp = xmalloc(sizeof(keyentry_T) + strlen(name_ic)); + keyentry_T *const kp = xmalloc(offsetof(keyentry_T, keyword) + strlen(name_ic) + 1); STRCPY(kp->keyword, name_ic); kp->k_syn.id = (int16_t)id; kp->k_syn.inc_tag = current_syn_inc_tag; -- cgit From b3d304df93347ef3f585ae91ae9ff6f5f28651af Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 31 Jan 2023 11:47:02 +0000 Subject: refactor(fileio.c): remove HAVE_ACL ifdefs --- src/nvim/fileio.c | 18 ------------------ src/nvim/os/fs.c | 2 +- src/nvim/undo.c | 2 -- 3 files changed, 1 insertion(+), 21 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 4b3a52759d..77b8cc833f 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2628,9 +2628,7 @@ static int buf_write_make_backup(char *fname, bool append, FileInfo *file_info_o (double)file_info_old->stat.st_atim.tv_sec, (double)file_info_old->stat.st_mtim.tv_sec); #endif -#ifdef HAVE_ACL os_set_acl(*backupp, acl); -#endif *err = set_err(NULL); break; } @@ -2908,12 +2906,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en goto fail; } -#ifdef HAVE_ACL // For systems that support ACL: get the ACL from the original file. if (!newfile) { acl = os_get_acl(fname); } -#endif // If 'backupskip' is not empty, don't make a backup for some files. bool dobackup = (p_wb || p_bk || *p_pm != NUL); @@ -3371,13 +3367,11 @@ restore_backup: if (perm >= 0) { // Set perm. of new file same as old file. (void)os_setperm((const char *)wfname, (int)perm); } -#ifdef HAVE_ACL // Probably need to set the ACL before changing the user (can't set the // ACL on a file the user doesn't own). if (!backup_copy) { os_set_acl(wfname, acl); } -#endif if (wfname != fname) { // The file was written to a temp file, now it needs to be converted @@ -3588,9 +3582,7 @@ nofail: iconv_close(write_info.bw_iconv_fd); write_info.bw_iconv_fd = (iconv_t)-1; } -#ifdef HAVE_ACL os_free_acl(acl); -#endif if (err.msg != NULL) { // - 100 to save some space for further error message @@ -4577,15 +4569,11 @@ int vim_rename(const char *from, const char *to) // Rename() failed, try copying the file. long perm = os_getperm(from); -#ifdef HAVE_ACL // For systems that support ACL: get the ACL from the original file. vim_acl_T acl = os_get_acl(from); -#endif int fd_in = os_open((char *)from, O_RDONLY, 0); if (fd_in < 0) { -#ifdef HAVE_ACL os_free_acl(acl); -#endif return -1; } @@ -4593,9 +4581,7 @@ int vim_rename(const char *from, const char *to) int fd_out = os_open((char *)to, O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, (int)perm); if (fd_out < 0) { close(fd_in); -#ifdef HAVE_ACL os_free_acl(acl); -#endif return -1; } @@ -4605,9 +4591,7 @@ int vim_rename(const char *from, const char *to) if (buffer == NULL) { close(fd_out); close(fd_in); -#ifdef HAVE_ACL os_free_acl(acl); -#endif return -1; } @@ -4631,10 +4615,8 @@ int vim_rename(const char *from, const char *to) #ifndef UNIX // For Unix os_open() already set the permission. os_setperm(to, perm); #endif -#ifdef HAVE_ACL os_set_acl(to, acl); os_free_acl(acl); -#endif if (errmsg != NULL) { semsg(errmsg, to); return -1; diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 302faa8140..8915b0de3e 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -788,6 +788,7 @@ int os_setperm(const char *const name, int perm) # ifdef HAVE_SYS_ACCESS_H # include # endif +#endif // Return a pointer to the ACL of file "fname" in allocated memory. // Return NULL if the ACL is not available for whatever reason. @@ -811,7 +812,6 @@ void os_free_acl(vim_acl_T aclent) return; } } -#endif #ifdef UNIX /// Checks if the current user owns a file. diff --git a/src/nvim/undo.c b/src/nvim/undo.c index 0f12c00f15..2b5dd297b5 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -1339,14 +1339,12 @@ write_error: semsg(_("E829: write error in undo file: %s"), file_name); } -#ifdef HAVE_ACL if (buf->b_ffname != NULL) { // For systems that support ACL: get the ACL from the original file. vim_acl_T acl = os_get_acl(buf->b_ffname); os_set_acl(file_name, acl); os_free_acl(acl); } -#endif theend: if (file_name != name) { -- cgit From 6aee2336ca75301bd4db6b99c2392f63f8304335 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 31 Jan 2023 12:00:33 +0000 Subject: refactor(fileio.c): normalize ifdefs As well as improving readbability, this also avoids all Treesitter parsing errors which cannot handle elaborate use of the preprocessor. --- src/nvim/fileio.c | 76 +++++++++++++++++++++++++++------------------------ src/nvim/os/os_defs.h | 6 ++++ 2 files changed, 46 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 77b8cc833f..716d7af149 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -389,13 +389,18 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, perm = os_getperm(fname); // On Unix it is possible to read a directory, so we have to // check for it before os_open(). + +#ifdef OPEN_CHR_FILES +# define IS_CHR_DEV(perm, fname) S_ISCHR(perm) && is_dev_fd_file(fname) +#else +# define IS_CHR_DEV(perm, fname) false +#endif + if (perm >= 0 && !S_ISREG(perm) // not a regular file ... && !S_ISFIFO(perm) // ... or fifo && !S_ISSOCK(perm) // ... or socket -#ifdef OPEN_CHR_FILES - && !(S_ISCHR(perm) && is_dev_fd_file(fname)) + && !(IS_CHR_DEV(perm, fname)) // ... or a character special file named /dev/fd/ -#endif ) { if (S_ISDIR(perm)) { if (!silent) { @@ -513,15 +518,18 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, } return OK; // a new file is not an error } - filemess(curbuf, sfname, ((fd == UV_EFBIG) ? _("[File too big]") : #if defined(UNIX) && defined(EOVERFLOW) + filemess(curbuf, sfname, ((fd == UV_EFBIG) ? _("[File too big]") : // libuv only returns -errno // in Unix and in Windows // open() does not set // EOVERFLOW (fd == -EOVERFLOW) ? _("[File too big]") : -#endif _("[Permission Denied]")), 0); +#else + filemess(curbuf, sfname, ((fd == UV_EFBIG) ? _("[File too big]") : + _("[Permission Denied]")), 0); +#endif curbuf->b_p_ro = true; // must use "w!" now return FAIL; @@ -2865,13 +2873,12 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en msg_scroll = true; // don't overwrite previous file message } if (!filtering) { - filemess(buf, + // show that we are busy #ifndef UNIX - sfname, + filemess(buf, sfname, "", 0); #else - fname, + filemess(buf, fname, "", 0); #endif - "", 0); // show that we are busy } msg_scroll = false; // always overwrite the file message now @@ -3114,29 +3121,32 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en && !os_fileinfo_id_equal(&file_info, &file_info_old))) { err = set_err(_("E166: Can't open linked file for writing")); } else { -#endif - err = set_err_arg(_("E212: Can't open file for writing: %s"), fd); - if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL - && perm >= 0) { -#ifdef UNIX - // we write to the file, thus it should be marked - // writable after all - if (!(perm & 0200)) { - made_writable = true; - } - perm |= 0200; - if (file_info_old.stat.st_uid != getuid() - || file_info_old.stat.st_gid != getgid()) { - perm &= 0777; + err = set_err_arg(_("E212: Can't open file for writing: %s"), fd); + if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL && perm >= 0) { + // we write to the file, thus it should be marked + // writable after all + if (!(perm & 0200)) { + made_writable = true; + } + perm |= 0200; + if (file_info_old.stat.st_uid != getuid() + || file_info_old.stat.st_gid != getgid()) { + perm &= 0777; + } + if (!append) { // don't remove when appending + os_remove(wfname); + } + continue; } -#endif + } +#else + err = set_err_arg(_("E212: Can't open file for writing: %s"), fd); + if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL && perm >= 0) { if (!append) { // don't remove when appending os_remove(wfname); } continue; } -#ifdef UNIX - } #endif } @@ -3774,14 +3784,15 @@ static int check_mtime(buf_T *buf, FileInfo *file_info) static bool time_differs(const FileInfo *file_info, long mtime, long mtime_ns) FUNC_ATTR_CONST { - return file_info->stat.st_mtim.tv_nsec != mtime_ns #if defined(__linux__) || defined(MSWIN) + return file_info->stat.st_mtim.tv_nsec != mtime_ns // On a FAT filesystem, esp. under Linux, there are only 5 bits to store // the seconds. Since the roundoff is done when flushing the inode, the // time may change unexpectedly by one second!!! || file_info->stat.st_mtim.tv_sec - mtime > 1 || mtime - file_info->stat.st_mtim.tv_sec > 1; #else + return file_info->stat.st_mtim.tv_nsec != mtime_ns || file_info->stat.st_mtim.tv_sec != mtime; #endif } @@ -5600,11 +5611,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs // regexp. // An escaped { must be unescaped since we use magic not // verymagic. Use "\\\{n,m\}"" to get "\{n,m}". - if (*++p == '?' -#ifdef BACKSLASH_IN_FILENAME - && no_bslash -#endif - ) { + if (*++p == '?' && (!BACKSLASH_IN_FILENAME_BOOL || no_bslash)) { reg_pat[i++] = '?'; } else if (*p == ',' || *p == '%' || *p == '#' || ascii_isspace(*p) || *p == '{' || *p == '}') { @@ -5615,10 +5622,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs p += 2; } else { if (allow_dirs != NULL && vim_ispathsep(*p) -#ifdef BACKSLASH_IN_FILENAME - && (!no_bslash || *p != '\\') -#endif - ) { + && (!BACKSLASH_IN_FILENAME_BOOL || (!no_bslash || *p != '\\'))) { *allow_dirs = true; } reg_pat[i++] = '\\'; diff --git a/src/nvim/os/os_defs.h b/src/nvim/os/os_defs.h index a30e16eeba..f86c0d3483 100644 --- a/src/nvim/os/os_defs.h +++ b/src/nvim/os/os_defs.h @@ -13,6 +13,12 @@ # include "nvim/os/unix_defs.h" #endif +#ifdef BACKSLASH_IN_FILENAME +# define BACKSLASH_IN_FILENAME_BOOL true +#else +# define BACKSLASH_IN_FILENAME_BOOL false +#endif + #if !defined(NAME_MAX) && defined(_XOPEN_NAME_MAX) # define NAME_MAX _XOPEN_NAME_MAX #endif -- cgit From 4cc0d6b854b44c0b8466e0a84bbc9e350cda8c4f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 1 Feb 2023 21:53:32 +0800 Subject: vim-patch:9.0.1271: using sizeof() and subtract array size is tricky (#22087) Problem: Using sizeof() and subtract array size is tricky. Solution: Use offsetof() instead. (closes vim/vim#11926) https://github.com/vim/vim/commit/1b438a8228a415720efb5ca1c0503f5467292e8e --- src/nvim/eval/vars.c | 2 +- src/nvim/file_search.c | 2 +- src/nvim/memline.c | 5 +++-- src/nvim/message.c | 2 +- src/nvim/regexp_nfa.c | 2 +- src/nvim/spell.c | 2 +- src/nvim/spellfile.c | 2 +- src/nvim/spellsuggest.c | 2 +- 8 files changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 3e593151fc..9ed245d6c4 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1347,7 +1347,7 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, // Make sure dict is valid assert(dict != NULL); - v = xmalloc(sizeof(dictitem_T) + strlen(varname)); + v = xmalloc(offsetof(dictitem_T, di_key) + strlen(varname) + 1); STRCPY(v->di_key, varname); if (hash_add(ht, (char *)v->di_key) == FAIL) { xfree(v); diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index e236f23895..a0435afd65 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -1092,7 +1092,7 @@ static int ff_check_visited(ff_visited_T **visited_list, char *fname, char *wc_p } // New file/dir. Add it to the list of visited files/dirs. - vp = xmalloc(sizeof(ff_visited_T) + strlen(ff_expand_buffer)); + vp = xmalloc(offsetof(ff_visited_T, ffv_fname) + strlen(ff_expand_buffer) + 1); if (!url) { vp->file_id_valid = true; diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 10a8195e7a..b3fc64a68c 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -149,7 +149,7 @@ struct data_block { #define DB_INDEX_MASK (~DB_MARKED) #define INDEX_SIZE (sizeof(unsigned)) // size of one db_index entry -#define HEADER_SIZE (sizeof(DATA_BL) - INDEX_SIZE) // size of data block header +#define HEADER_SIZE (offsetof(DATA_BL, db_index)) // size of data block header enum { B0_FNAME_SIZE_ORG = 900, // what it was in older versions @@ -2720,7 +2720,8 @@ static bhdr_T *ml_new_ptr(memfile_T *mfp) PTR_BL *pp = hp->bh_data; pp->pb_id = PTR_ID; pp->pb_count = 0; - pp->pb_count_max = (uint16_t)((mfp->mf_page_size - sizeof(PTR_BL)) / sizeof(PTR_EN) + 1); + pp->pb_count_max + = (uint16_t)((mfp->mf_page_size - offsetof(PTR_BL, pb_pointer)) / sizeof(PTR_EN)); return hp; } diff --git a/src/nvim/message.c b/src/nvim/message.c index 7f29b19031..3b3dfcd5b6 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -2514,7 +2514,7 @@ static void store_sb_text(char **sb_str, char *s, int attr, int *sb_col, int fin } if (s > *sb_str) { - mp = xmalloc((sizeof(msgchunk_T) + (size_t)(s - *sb_str))); + mp = xmalloc(offsetof(msgchunk_T, sb_text) + (size_t)(s - *sb_str) + 1); mp->sb_eol = (char)finish; mp->sb_msg_col = *sb_col; mp->sb_attr = attr; diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index 93b03f0632..ea59e7d464 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -7511,7 +7511,7 @@ static regprog_T *nfa_regcomp(uint8_t *expr, int re_flags) post2nfa(postfix, post_ptr, true); // allocate the regprog with space for the compiled regexp - size_t prog_size = sizeof(nfa_regprog_T) + sizeof(nfa_state_T) * (size_t)(nstate - 1); + size_t prog_size = offsetof(nfa_regprog_T, state) + sizeof(nfa_state_T) * (size_t)nstate; prog = xmalloc(prog_size); state_ptr = prog->state; prog->re_in_use = false; diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 8e18be5bd1..2204cda169 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -1745,7 +1745,7 @@ void count_common_word(slang_T *lp, char *word, int len, uint8_t count) const size_t p_len = strlen(p); hashitem_T *hi = hash_lookup(&lp->sl_wordcount, (const char *)p, p_len, hash); if (HASHITEM_EMPTY(hi)) { - wc = xmalloc(sizeof(wordcount_T) + p_len); + wc = xmalloc(offsetof(wordcount_T, wc_word) + p_len + 1); memcpy(wc->wc_word, p, p_len + 1); wc->wc_count = count; hash_add_item(&lp->sl_wordcount, hi, (char *)wc->wc_word, hash); diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 44414ca1a5..7b124ae6b6 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -3855,7 +3855,7 @@ static void *getroom(spellinfo_T *spin, size_t len, bool align) if (bl == NULL || (size_t)bl->sb_used + len > SBLOCKSIZE) { // Allocate a block of memory. It is not freed until much later. - bl = xcalloc(1, (sizeof(sblock_T) + SBLOCKSIZE)); + bl = xcalloc(1, offsetof(sblock_T, sb_data) + SBLOCKSIZE + 1); bl->sb_next = spin->si_blocks; spin->si_blocks = bl; bl->sb_used = 0; diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c index 22add418a0..54b6f552b5 100644 --- a/src/nvim/spellsuggest.c +++ b/src/nvim/spellsuggest.c @@ -2828,7 +2828,7 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T hi = hash_lookup(&slang->sl_sounddone, (const char *)goodword, goodword_len, hash); if (HASHITEM_EMPTY(hi)) { - sft = xmalloc(sizeof(sftword_T) + goodword_len); + sft = xmalloc(offsetof(sftword_T, sft_word) + goodword_len + 1); sft->sft_score = (int16_t)score; memcpy(sft->sft_word, goodword, goodword_len + 1); hash_add_item(&slang->sl_sounddone, hi, (char *)sft->sft_word, hash); -- cgit From fa35d3c33a74123a3a3374566652161d3ad6ee5c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 2 Feb 2023 08:05:15 +0800 Subject: vim-patch:9.0.1273: "1v" may select block with wrong size (#22092) Problem: "1v" may select block with wrong size. (Evgeni Chasnovski) Solution: Compute "curswant" in the right line. (closes vim/vim#11925) https://github.com/vim/vim/commit/8f531662e28c37560bf5ac20a059bf00d01ee5a4 Co-authored-by: Bram Moolenaar --- src/nvim/normal.c | 4 ++++ src/nvim/testdir/test_visual.vim | 11 +++++++++++ 2 files changed, 15 insertions(+) (limited to 'src') diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 58a18ca5a8..b88cfb8926 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -5072,9 +5072,13 @@ static void nv_visual(cmdarg_T *cap) curwin->w_curswant = MAXCOL; coladvance(MAXCOL); } else if (VIsual_mode == Ctrl_V) { + // Update curswant on the original line, that is where "col" is valid. + linenr_T lnum = curwin->w_cursor.lnum; + curwin->w_cursor.lnum = VIsual.lnum; update_curswant_force(); assert(cap->count0 >= INT_MIN && cap->count0 <= INT_MAX); curwin->w_curswant += resel_VIsual_vcol * (int)cap->count0 - 1; + curwin->w_cursor.lnum = lnum; coladvance(curwin->w_curswant); } else { curwin->w_set_curswant = true; diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim index 14d62089cf..1e9629c2c4 100644 --- a/src/nvim/testdir/test_visual.vim +++ b/src/nvim/testdir/test_visual.vim @@ -1319,6 +1319,17 @@ func Test_visual_block_with_substitute() endfunc func Test_visual_reselect_with_count() + enew + call setline(1, ['aaaaaa', '✗ bbbb', '✗ bbbb']) + exe "normal! 2Gw\jed" + exe "normal! gg0lP" + call assert_equal(['abbbbaaaaa', '✗bbbb ', '✗ '], getline(1, '$')) + + exe "normal! 1vr." + call assert_equal(['a....aaaaa', '✗.... ', '✗ '], getline(1, '$')) + + bwipe! + " this was causing an illegal memory access let lines =<< trim END -- cgit From ecc1595c7b81987ca9d6265d1e08ef37a05c95bf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Feb 2023 08:07:11 +0800 Subject: version.c: update [skip ci] (#21306) Co-authored-by: marvim N/A patches: vim-patch:9.0.1272: typo in pattern for filetype detection --- src/nvim/version.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/version.c b/src/nvim/version.c index 11f1d6695e..3324ac2a94 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -795,7 +795,7 @@ static const int included_patches[] = { 1702, 1701, // 1700, - // 1699, + 1699, 1698, 1697, 1696, @@ -1361,7 +1361,7 @@ static const int included_patches[] = { // 1136, 1135, 1134, - // 1133, + 1133, 1132, 1131, 1130, @@ -1674,7 +1674,7 @@ static const int included_patches[] = { 823, 822, 821, - // 820, + 820, 819, 818, 817, -- cgit From 2c5906b55bb6092121f4d3b032d5449da7675c2b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 2 Feb 2023 10:05:03 +0800 Subject: fix(exit): skip unnecessary steps in TUI preserve_exit() (#21897) This prevents the TUI from doing unexpected things when receiving a deadly signal or running out of memory. --- src/nvim/main.c | 5 +++++ src/nvim/tui/tui.c | 3 +++ 2 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/nvim/main.c b/src/nvim/main.c index 8df82c710a..e26922bf8e 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -811,6 +811,11 @@ void preserve_exit(void) really_exiting = true; // Ignore SIGHUP while we are already exiting. #9274 signal_reject_deadly(); + + if (ui_client_channel_id) { + os_exit(1); + } + os_errmsg(IObuff); os_errmsg("\n"); ui_flush(); diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index a50e44f7a3..ceda3b2076 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -458,6 +458,9 @@ static void tui_terminal_stop(TUIData *tui) void tui_stop(TUIData *tui) { + if (tui->stopped) { + return; + } tui_terminal_stop(tui); stream_set_blocking(tui->input.in_fd, true); // normalize stream (#2598) tinput_destroy(&tui->input); -- cgit From 64fa75a86a9e2e301e884e21911d71688fc8f122 Mon Sep 17 00:00:00 2001 From: luukvbaal <31730729+luukvbaal@users.noreply.github.com> Date: Thu, 2 Feb 2023 10:35:51 +0100 Subject: fix(column): estimate 'statuscolumn' width appropriately Problem: The 'statuscolumn' width is being estimated without the proper context. In particular, this resulted in the fact that a custom fold column could be included in the estimated `number_width()`, and doubly added when actually drawing the statuscolumn due to `win_col_off()` also adding the `'foldcolumn'` width. Resulting in a status column that is `'foldcolumn'` cells wider than necessary. Solution: Estimate 'statuscolumn' width in `get_statuscol_str()` when a buffer's line count has changed. --- src/nvim/buffer_defs.h | 1 + src/nvim/drawline.c | 13 ++++++++++++- src/nvim/screen.c | 11 +++-------- 3 files changed, 16 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index f01edd1ad2..4c99191170 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1392,6 +1392,7 @@ struct window_S { int w_prev_fraction_row; linenr_T w_nrwidth_line_count; // line count when ml_nrwidth_width was computed. + linenr_T w_statuscol_line_count; // line count when 'statuscolumn' width was computed. int w_nrwidth_width; // nr of chars to print line count. qf_info_T *w_llist; // Location list for this window diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index e24d86b353..01ff207c2b 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -412,7 +412,6 @@ static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, i bool use_cul = use_cursor_line_sign(wp, lnum); int virtnum = row - startrow - filler_lines; - set_vim_var_nr(VV_VIRTNUM, virtnum); // When called the first time for line "lnum" set num_attr if (stcp->num_attr == 0) { stcp->num_attr = sign_num_attr ? sign_num_attr @@ -437,6 +436,18 @@ static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, i } stcp->sign_text[i] = NULL; + // When a buffer's line count has changed, make a best estimate for the full + // width of the status column by building with "w_nrwidth_line_count". Add + // potentially truncated width and rebuild before drawing anything. + if (wp->w_statuscol_line_count != wp->w_nrwidth_line_count) { + wp->w_statuscol_line_count = wp->w_nrwidth_line_count; + set_vim_var_nr(VV_VIRTNUM, 0); + build_statuscol_str(wp, wp->w_nrwidth_line_count, 0, stcp->width, + ' ', stcp->text, &stcp->hlrec, stcp); + stcp->width += stcp->truncate; + } + set_vim_var_nr(VV_VIRTNUM, virtnum); + int width = build_statuscol_str(wp, lnum, relnum, stcp->width, ' ', stcp->text, &stcp->hlrec, stcp); // Force a redraw in case of error or when truncated diff --git a/src/nvim/screen.c b/src/nvim/screen.c index ebff52cd69..05da6e0ef1 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -768,7 +768,6 @@ void comp_col(void) /// Otherwise it depends on 'numberwidth' and the line count. int number_width(win_T *wp) { - int n; linenr_T lnum; if (wp->w_p_rnu && !wp->w_p_nu) { @@ -784,17 +783,13 @@ int number_width(win_T *wp) } wp->w_nrwidth_line_count = lnum; - // make best estimate for 'statuscolumn' + // reset for 'statuscolumn' if (*wp->w_p_stc != NUL) { - char buf[MAXPATHL]; - wp->w_nrwidth_width = 0; - n = build_statuscol_str(wp, lnum, 0, 0, NUL, buf, NULL, NULL); - n = MAX(n, (wp->w_p_nu || wp->w_p_rnu) * (int)wp->w_p_nuw); - wp->w_nrwidth_width = MIN(n, MAX_NUMBERWIDTH); + wp->w_nrwidth_width = (wp->w_p_nu || wp->w_p_rnu) * (int)wp->w_p_nuw; return wp->w_nrwidth_width; } - n = 0; + int n = 0; do { lnum /= 10; n++; -- cgit From b02eeb6a7281df0561a021d7ae595c84be9a01be Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 2 Feb 2023 13:21:44 +0000 Subject: fix(lua): mark some eval functions that can run in API-fast --- src/nvim/eval.lua | 68 +++++++++++++++++++++++++++---------------------------- src/nvim/os/fs.c | 6 +---- 2 files changed, 35 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index c17a44b990..9a5ab51c71 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -26,7 +26,7 @@ return { acos={args=1, base=1, float_func="acos"}, -- WJMc add={args=2, base=1}, ['and']={args=2, base=1}, - api_info={}, + api_info={fast=true}, append={args=2, base=2}, appendbufline={args=3, base=3}, argc={args={0, 1}}, @@ -64,14 +64,14 @@ return { bufwinid={args=1, base=1}, bufwinnr={args=1, base=1}, byte2line={args=1, base=1}, - byteidx={args=2, base=1}, - byteidxcomp={args=2, base=1}, + byteidx={args=2, base=1, fast=true}, + byteidxcomp={args=2, base=1, fast=true}, call={args={2, 3}, base=1}, ceil={args=1, base=1, float_func="ceil"}, changenr={}, chanclose={args={1, 2}}, chansend={args=2}, - char2nr={args={1, 2}, base=1}, + char2nr={args={1, 2}, base=1, fast=true}, charclass={args=1, base=1}, charcol={args={1, 2}, base=1}, charidx={args={2, 3}, base=1}, @@ -100,7 +100,7 @@ return { deletebufline={args={2,3}, base=1}, dictwatcheradd={args=3}, dictwatcherdel={args=3}, - did_filetype={}, + did_filetype={fast=true}, diff_filler={args=1, base=1}, diff_hlID={args=2, base=1}, digraph_get={args=1, base=1}, @@ -108,11 +108,11 @@ return { digraph_set={args=2, base=1}, digraph_setlist={args=1, base=1}, empty={args=1, base=1}, - environ={}, - escape={args=2, base=1}, + environ={fast=true}, + escape={args=2, base=1, fast=true}, eval={args=1, base=1}, eventhandler={}, - executable={args=1, base=1}, + executable={args=1, base=1, fast=true}, execute={args={1, 2}, base=1}, exepath={args=1, base=1}, exists={args=1, base=1}, @@ -122,8 +122,8 @@ return { extend={args={2, 3}, base=1}, feedkeys={args={1, 2}, base=1}, file_readable={args=1, base=1, func='f_filereadable'}, -- obsolete - filereadable={args=1, base=1}, - filewritable={args=1, base=1}, + filereadable={args=1, base=1, fast=true}, + filewritable={args=1, base=1, fast=true}, filter={args=2, base=1}, finddir={args={1, 3}, base=1}, findfile={args={1, 3}, base=1}, @@ -131,8 +131,8 @@ return { float2nr={args=1, base=1}, floor={args=1, base=1, float_func="floor"}, fmod={args=2, base=1}, - fnameescape={args=1, base=1}, - fnamemodify={args=2, base=1}, + fnameescape={args=1, base=1, fast=true}, + fnamemodify={args=2, base=1, fast=true}, foldclosed={args=1, base=1}, foldclosedend={args=1, base=1}, foldlevel={args=1, base=1}, @@ -167,17 +167,17 @@ return { getcwd={args={0, 2}, base=1}, getenv={args=1, base=1}, getfontname={args={0, 1}}, - getfperm={args=1, base=1}, - getfsize={args=1, base=1}, - getftime={args=1, base=1}, - getftype={args=1, base=1}, + getfperm={args=1, base=1, fast=true}, + getfsize={args=1, base=1, fast=true}, + getftime={args=1, base=1, fast=true}, + getftype={args=1, base=1, fast=true}, getjumplist={args={0, 2}, base=1}, getline={args={1, 2}, base=1}, getloclist={args={1, 2}}, getmarklist={args={0, 1}, base=1}, getmatches={args={0, 1}}, getmousepos={}, - getpid={}, + getpid={fast=true}, getpos={args=1, base=1}, getqflist={args={0, 1}}, getreg={args={0, 3}, base=1}, @@ -208,7 +208,7 @@ return { histnr={args=1, base=1}, hlID={args=1, base=1}, hlexists={args=1, base=1}, - hostname={}, + hostname={fast=true}, iconv={args=3, base=1, fast=true}, indent={args=1, base=1}, index={args={2, 4}, base=1}, @@ -221,7 +221,7 @@ return { insert={args={2, 3}, base=1}, interrupt={args=0}, invert={args=1, base=1}, - isdirectory={args=1, base=1}, + isdirectory={args=1, base=1, fast=true}, isinf={args=1, base=1}, islocked={args=1, base=1}, isnan={args=1, base=1}, @@ -300,13 +300,13 @@ return { reg_executing={}, reg_recording={}, reg_recorded={}, - reltime={args={0, 2}, base=1}, - reltimefloat={args=1, base=1}, - reltimestr={args=1, base=1}, + reltime={args={0, 2}, base=1, fast=true}, + reltimefloat={args=1, base=1, fast=true}, + reltimestr={args=1, base=1, fast=true}, remove={args={2, 3}, base=1}, rename={args=2, base=1}, - ['repeat']={args=2, base=1}, - resolve={args=1, base=1}, + ['repeat']={args=2, base=1, fast=true}, + resolve={args=1, base=1, fast=true}, reverse={args=1, base=1}, round={args=1, base=1, float_func="round"}, rpcnotify={args=varargs(2)}, @@ -374,24 +374,24 @@ return { split={args={1, 3}, base=1}, sqrt={args=1, base=1, float_func="sqrt"}, srand={args={0, 1}, base=1}, - stdpath={args=1}, + stdpath={args=1, fast=true}, str2float={args=1, base=1}, str2list={args={1, 2}, base=1}, str2nr={args={1, 3}, base=1}, strcharlen={args=1, base=1}, - strcharpart={args={2, 3}, base=1}, + strcharpart={args={2, 3}, base=1, fast=true}, strchars={args={1, 2}, base=1}, strdisplaywidth={args={1, 2}, base=1}, strftime={args={1, 2}, base=1}, strgetchar={args=2, base=1}, - stridx={args={2, 3}, base=1}, + stridx={args={2, 3}, base=1, fast=true}, string={args=1, base=1}, strlen={args=1, base=1}, - strpart={args={2, 4}, base=1}, + strpart={args={2, 4}, base=1, fast=true}, strptime={args=2, base=1}, strridx={args={2, 3}, base=1}, - strtrans={args=1, base=1}, - strwidth={args=1, base=1}, + strtrans={args=1, base=1, fast=true}, + strwidth={args=1, base=1, fast=true}, submatch={args={1, 2}, base=1}, substitute={args=4, base=1}, swapinfo={args=1, base=1}, @@ -419,12 +419,12 @@ return { timer_start={args={2, 3}, base=1}, timer_stop={args=1, base=1}, timer_stopall={args=0}, - tolower={args=1, base=1}, - toupper={args=1, base=1}, + tolower={args=1, base=1, fast=true}, + toupper={args=1, base=1, fast=true}, tr={args=3, base=1}, trim={args={1, 3}, base=1}, trunc={args=1, base=1, float_func="trunc"}, - type={args=1, base=1}, + type={args=1, base=1, fast=true}, undofile={args=1, base=1}, undotree={}, uniq={args={1, 3}, base=1}, @@ -447,7 +447,7 @@ return { win_splitmove={args={2, 3}, base=1}, winbufnr={args=1, base=1}, wincol={}, - windowsversion={}, + windowsversion={fast=true}, winheight={args=1, base=1}, winlayout={args={0, 1}, base=1}, winline={}, diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 302faa8140..6157341ec9 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -146,11 +146,7 @@ bool os_isdir(const char *name) return false; } - if (!S_ISDIR(mode)) { - return false; - } - - return true; + return S_ISDIR(mode); } /// Check what `name` is: -- cgit From d3355ad01c3b9d1dbc62210c29d8e51245f081aa Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 2 Feb 2023 22:42:15 +0800 Subject: fix(tui): detach/attach on suspend/resume (#22040) Problem: When a TUI client is suspended it still receives UI events from the server, and has to process these accumulated events when it is resumed. With mulitple TUI clients this is a bigger problem, considering the following steps: 1. A TUI client is attached. 2. CTRL-Z is pressed and the first client is suspended. 3. Another TUI client is attached. 4. CTRL-Z is pressed and a "suspend" event is sent to both clients. The second client is suspended, while the first client isn't able to process the event because it has already been suspended. 5. The first client is resumed. It processes the accumulated "suspend" event and suspends immediately. Solution: Make a TUI client detach on suspend and re-attach on resume. --- src/nvim/tui/tui.c | 2 ++ src/nvim/ui_client.c | 29 +++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index ceda3b2076..f760e99262 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -1347,6 +1347,7 @@ static void show_verbose_terminfo(TUIData *tui) static void suspend_event(void **argv) { TUIData *tui = argv[0]; + ui_client_detach(); bool enable_mouse = tui->mouse_enabled; tui_terminal_stop(tui); stream_set_blocking(tui->input.in_fd, true); // normalize stream (#2598) @@ -1359,6 +1360,7 @@ static void suspend_event(void **argv) tui_mouse_on(tui); } stream_set_blocking(tui->input.in_fd, false); // libuv expects this + ui_client_attach(tui->width, tui->height, tui->term); } #endif diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 378c0e4831..b5c8dff412 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -23,6 +23,7 @@ #include "nvim/ui_client.h" static TUIData *tui = NULL; +static bool ui_client_is_remote = false; // uncrustify:off #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -66,13 +67,8 @@ uint64_t ui_client_start_server(int argc, char **argv) return channel->id; } -void ui_client_run(bool remote_ui) - FUNC_ATTR_NORETURN +void ui_client_attach(int width, int height, char *term) { - int width, height; - char *term; - tui = tui_start(&width, &height, &term); - MAXSIZE_TEMP_ARRAY(args, 3); ADD_C(args, INTEGER_OBJ(width)); ADD_C(args, INTEGER_OBJ(height)); @@ -82,14 +78,14 @@ void ui_client_run(bool remote_ui) PUT_C(opts, "ext_linegrid", BOOLEAN_OBJ(true)); PUT_C(opts, "ext_termcolors", BOOLEAN_OBJ(true)); if (term) { - PUT(opts, "term_name", STRING_OBJ(cstr_to_string(term))); + PUT_C(opts, "term_name", STRING_OBJ(cstr_as_string(term))); } if (ui_client_bg_response != kNone) { bool is_dark = (ui_client_bg_response == kTrue); PUT_C(opts, "term_background", STRING_OBJ(cstr_as_string(is_dark ? "dark" : "light"))); } PUT_C(opts, "term_colors", INTEGER_OBJ(t_colors)); - if (!remote_ui) { + if (!ui_client_is_remote) { PUT_C(opts, "stdin_tty", BOOLEAN_OBJ(stdin_isatty)); PUT_C(opts, "stdout_tty", BOOLEAN_OBJ(stdout_isatty)); if (ui_client_forward_stdin) { @@ -100,6 +96,23 @@ void ui_client_run(bool remote_ui) rpc_send_event(ui_client_channel_id, "nvim_ui_attach", args); ui_client_attached = true; +} + +void ui_client_detach(void) +{ + rpc_send_event(ui_client_channel_id, "nvim_ui_detach", (Array)ARRAY_DICT_INIT); + ui_client_attached = false; +} + +void ui_client_run(bool remote_ui) + FUNC_ATTR_NORETURN +{ + ui_client_is_remote = remote_ui; + int width, height; + char *term; + tui = tui_start(&width, &height, &term); + + ui_client_attach(width, height, term); // os_exit() will be invoked when the client channel detaches while (true) { -- cgit From c05b3c3bbdef4018ce70f0c822c4a55654a9c186 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Thu, 2 Feb 2023 17:26:22 +0100 Subject: vim-patch:9.0.1274: FIRRTL files are not recognized (#22102) Problem: FIRRTL files are not recognized. Solution: Add a pattern for FIRRTL files. (Amaan Qureshi, closes vim/vim#11931) https://github.com/vim/vim/commit/685bf83b73d0fe6fd36bb2949bebd6aae66a139e Co-authored-by: Amaan Qureshi --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 88c25ab115..7b5ec22dd4 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -199,6 +199,7 @@ let s:filename_checks = { \ 'fennel': ['file.fnl'], \ 'fetchmail': ['.fetchmailrc'], \ 'fgl': ['file.4gl', 'file.4gh', 'file.m4gl'], + \ 'firrtl': ['file.fir'], \ 'fish': ['file.fish'], \ 'focexec': ['file.fex', 'file.focexec'], \ 'form': ['file.frm'], -- cgit From ebd2372f928c6f1cfe823d36aabf479f6930232f Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Thu, 2 Feb 2023 23:56:25 +0100 Subject: refactor: use flexible arrays instead of the length-of-one trick (#22072) The "length-of-one" trick, where the last element of a struct is an array of size 1, but extra size is allocated when calling malloc where it uses more than 1 element in the array, cause problems with some compilers. Some compilers set _FORTIFY_SOURCE=2 by default which incorrectly considers it as an overflow. More information: https://github.com/neovim/neovim/issues/223#issuecomment-1413828554 Using flexible array members allows us to to properly convey to the compiler that its size may be larger than 1. This also enables us to remove lengthy workarounds that are unreliable, as they depend on CMAKE_BUILD_TYPE which isn't defined for multi-config generators. Closes: https://github.com/neovim/neovim/issues/223 --- src/nvim/CMakeLists.txt | 28 ---------------------------- src/nvim/file_search.c | 2 +- src/nvim/memline.c | 4 ++-- src/nvim/message.c | 2 +- src/nvim/regexp_defs.h | 4 ++-- src/nvim/sign_defs.h | 2 +- src/nvim/spell_defs.h | 2 +- src/nvim/spellfile.c | 2 +- src/nvim/spellsuggest.c | 2 +- src/nvim/syntax_defs.h | 2 +- 10 files changed, 11 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 7b56af59da..62b661dc2d 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -219,34 +219,6 @@ endif() list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${TreeSitter_INCLUDE_DIRS}") list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "${TreeSitter_LIBRARIES}") -# Include because some toolchains define _FORTIFY_SOURCE=2 in -# internal header files, which should in turn be #included by . -check_c_source_compiles(" -#include - -#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 1 -#error \"_FORTIFY_SOURCE > 1\" -#endif -int -main(void) -{ - return 0; -} -" HAS_ACCEPTABLE_FORTIFY) - -if(NOT HAS_ACCEPTABLE_FORTIFY) - message(STATUS "Unsupported _FORTIFY_SOURCE found, forcing _FORTIFY_SOURCE=1") - # Extract possible prefix to _FORTIFY_SOURCE (e.g. -Wp,-D_FORTIFY_SOURCE). - string(REGEX MATCH "[^\ ]+-D_FORTIFY_SOURCE" _FORTIFY_SOURCE_PREFIX "${CMAKE_C_FLAGS}") - string(REPLACE "-D_FORTIFY_SOURCE" "" _FORTIFY_SOURCE_PREFIX "${_FORTIFY_SOURCE_PREFIX}" ) - if(NOT _FORTIFY_SOURCE_PREFIX STREQUAL "") - message(STATUS "Detected _FORTIFY_SOURCE Prefix=${_FORTIFY_SOURCE_PREFIX}") - endif() - # -U in add_definitions doesn't end up in the correct spot, so we add it to - # the flags variable instead. - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FORTIFY_SOURCE_PREFIX}-U_FORTIFY_SOURCE ${_FORTIFY_SOURCE_PREFIX}-D_FORTIFY_SOURCE=1") -endif() - target_compile_definitions(main_lib INTERFACE INCLUDE_GENERATED_DECLARATIONS) # Remove --sort-common from linker flags, as this seems to cause bugs (see #2641, #3374). diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index a0435afd65..42ba0bee97 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -117,7 +117,7 @@ typedef struct ff_visited { FileID file_id; // The memory for this struct is allocated according to the length of // ffv_fname. - char ffv_fname[1]; // actually longer + char ffv_fname[]; } ff_visited_T; // We might have to manage several visited lists during a search. diff --git a/src/nvim/memline.c b/src/nvim/memline.c index b3fc64a68c..dfca19aa96 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -117,7 +117,7 @@ struct pointer_block { uint16_t pb_id; // ID for pointer block: PTR_ID uint16_t pb_count; // number of pointers in this block uint16_t pb_count_max; // maximum value for pb_count - PTR_EN pb_pointer[1]; // list of pointers to blocks (actually longer) + PTR_EN pb_pointer[]; // list of pointers to blocks // followed by empty space until end of page }; @@ -133,7 +133,7 @@ struct data_block { unsigned db_txt_end; // byte just after data block // linenr_T db_line_count; long db_line_count; // number of lines in this block - unsigned db_index[1]; // index for start of line (actually bigger) + unsigned db_index[]; // index for start of line // followed by empty space up to db_txt_start // followed by the text in the lines until // end of page diff --git a/src/nvim/message.c b/src/nvim/message.c index 3b3dfcd5b6..40453211b4 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -64,7 +64,7 @@ struct msgchunk_S { char sb_eol; // true when line ends after this text int sb_msg_col; // column in which text starts int sb_attr; // text attributes - char sb_text[1]; // text to be displayed, actually longer + char sb_text[]; // text to be displayed }; // Magic chars used in confirm dialog strings diff --git a/src/nvim/regexp_defs.h b/src/nvim/regexp_defs.h index 16bb2db464..b27a5b5942 100644 --- a/src/nvim/regexp_defs.h +++ b/src/nvim/regexp_defs.h @@ -102,7 +102,7 @@ typedef struct { char_u *regmust; int regmlen; char_u reghasz; - char_u program[1]; // actually longer.. + char_u program[]; } bt_regprog_T; // Structure representing a NFA state. @@ -138,7 +138,7 @@ typedef struct { char *pattern; int nsubexp; // number of () int nstate; - nfa_state_T state[1]; // actually longer.. + nfa_state_T state[]; } nfa_regprog_T; // Structure to be used for single-line matching. diff --git a/src/nvim/sign_defs.h b/src/nvim/sign_defs.h index 7aa06ce48a..bae5344588 100644 --- a/src/nvim/sign_defs.h +++ b/src/nvim/sign_defs.h @@ -12,7 +12,7 @@ typedef struct signgroup_S { int sg_next_sign_id; ///< next sign id for this group uint16_t sg_refcount; ///< number of signs in this group - char sg_name[1]; ///< sign group name, actually longer + char sg_name[]; ///< sign group name } signgroup_T; // Macros to get the sign group structure from the group name diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h index 726af7d698..4d365deab1 100644 --- a/src/nvim/spell_defs.h +++ b/src/nvim/spell_defs.h @@ -243,7 +243,7 @@ typedef enum { typedef struct wordcount_S { uint16_t wc_count; ///< nr of times word was seen - char_u wc_word[1]; ///< word, actually longer + char_u wc_word[]; ///< word } wordcount_T; #define WC_KEY_OFF offsetof(wordcount_T, wc_word) diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 7b124ae6b6..5e7ebc4c87 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -404,7 +404,7 @@ typedef struct sblock_S sblock_T; struct sblock_S { int sb_used; // nr of bytes already in use sblock_T *sb_next; // next block in list - char_u sb_data[1]; // data, actually longer + char_u sb_data[]; // data }; // A node in the tree. diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c index 54b6f552b5..0ddf07e3a6 100644 --- a/src/nvim/spellsuggest.c +++ b/src/nvim/spellsuggest.c @@ -2708,7 +2708,7 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u * /// handled already. typedef struct { int16_t sft_score; ///< lowest score used - char_u sft_word[1]; ///< soundfolded word, actually longer + char_u sft_word[]; ///< soundfolded word } sftword_T; static sftword_T dumsft; diff --git a/src/nvim/syntax_defs.h b/src/nvim/syntax_defs.h index 3f3101f7e3..218cd3623d 100644 --- a/src/nvim/syntax_defs.h +++ b/src/nvim/syntax_defs.h @@ -30,7 +30,7 @@ struct keyentry { int16_t *next_list; // ID list for next match (if non-zero) int flags; int k_char; // conceal substitute character - char keyword[1]; // actually longer + char keyword[]; }; // Struct used to store one state of the state stack. -- cgit From f9826e1dff5f1ac8212ca55a847c872c426142db Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Fri, 3 Feb 2023 00:00:15 +0100 Subject: build: stop relying on CMAKE_BUILD_TYPE to determine the build type (#22051) Any logic involving CMAKE_BUILD_TYPE is automatically broken as it won't work with multi-config generators. The only exception is if we explicitly check whether the current generator is single-config as well. Instead, use generator expressions or cmake variables that allows to set options for certain build types only such as INTERPROCEDURAL_OPTIMIZATION_. Opt to generate all headers with optimization level O2 with no debug information for all build types as that is the simplest way to make it behave the same for all generators. --- src/nvim/CMakeLists.txt | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 62b661dc2d..fd34a30619 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -412,7 +412,15 @@ else() ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion -Wno-strict-prototypes") endif() -if(NOT "${MIN_LOG_LEVEL}" MATCHES "^$") +# Log level (MIN_LOG_LEVEL in log.h) +if("${MIN_LOG_LEVEL}" MATCHES "^$") + # Minimize logging for release-type builds. + target_compile_definitions(main_lib INTERFACE MIN_LOG_LEVEL=$,1,3>) +else() + if(NOT MIN_LOG_LEVEL MATCHES "^[0-3]$") + message(FATAL_ERROR "invalid MIN_LOG_LEVEL: " ${MIN_LOG_LEVEL}) + endif() + message(STATUS "MIN_LOG_LEVEL=${MIN_LOG_LEVEL}") target_compile_definitions(main_lib INTERFACE MIN_LOG_LEVEL=${MIN_LOG_LEVEL}) endif() @@ -435,10 +443,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_OSX_SYSROOT) list(APPEND gen_cflags "-isysroot") list(APPEND gen_cflags "${CMAKE_OSX_SYSROOT}") endif() -string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type) -separate_arguments(C_FLAGS_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS}) -separate_arguments(C_FLAGS_${build_type}_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS_${build_type}}) -set(gen_cflags ${gen_cflags} ${C_FLAGS_${build_type}_ARRAY} ${C_FLAGS_ARRAY}) +set(gen_cflags ${gen_cflags} -O2) set(NVIM_VERSION_GIT_H ${PROJECT_BINARY_DIR}/cmake.config/auto/versiondef_git.h) add_custom_target(update_version_stamp @@ -653,10 +658,10 @@ endif() if(NOT LUAJIT_FOUND) message(STATUS "luajit not found, skipping unit tests") -elseif(CMAKE_BUILD_TYPE MATCHES Debug) +else() glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c) - list(APPEND NVIM_SOURCES ${UNIT_TEST_FIXTURES}) - target_compile_definitions(main_lib INTERFACE UNIT_TESTING) + target_sources(nvim PRIVATE $<$:${UNIT_TEST_FIXTURES}>) + target_compile_definitions(nvim PRIVATE $<$:UNIT_TESTING>) endif() target_sources(nvim PRIVATE ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} @@ -681,8 +686,11 @@ endif() if(ENABLE_LTO) include(CheckIPOSupported) check_ipo_supported(RESULT IPO_SUPPORTED) - if(IPO_SUPPORTED AND (NOT CMAKE_BUILD_TYPE MATCHES Debug)) - set_target_properties(nvim PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) + if(IPO_SUPPORTED) + set_target_properties(nvim PROPERTIES + INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE + INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE + INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL TRUE) endif() endif() @@ -942,6 +950,3 @@ add_custom_target(generated-sources DEPENDS ) add_subdirectory(po) - -include(GetCompileFlags) -get_compile_flags(NVIM_VERSION_CFLAGS) -- cgit From 7a710f5f0840724b7352ab36cfa9b8db5d533657 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Sat, 4 Feb 2023 00:17:04 +0100 Subject: fix(column): no longer reset nrwidth_line_count for 'statuscolumn' Problem: We still explicitly reset `nrwidth_line_count` when changing `'number'` or `'relativenumber'` but this is no longer needed since the introduction of a `statuscol_line_count`. Solution: Remove reset of `nrwidth_line_count`. Resolve https://github.com/neovim/neovim/pull/22094#issuecomment-1416168926. --- src/nvim/option.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 387b94533c..fd58ebd6fe 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2158,9 +2158,6 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va if (curwin->w_p_spell) { errmsg = did_set_spelllang(curwin); } - } else if (((int *)varp == &curwin->w_p_nu || (int *)varp == &curwin->w_p_rnu) - && *curwin->w_p_stc != NUL) { // '(relative)number' + 'statuscolumn' - curwin->w_nrwidth_line_count = 0; } if ((int *)varp == &curwin->w_p_arab) { -- cgit From 60ab22dfa6c9888fe8e261f185bfe4b0ab72956e Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Sat, 4 Feb 2023 10:43:20 +0100 Subject: refactor(column): remove unused build_statuscol_str() arguments Problem: `build_statuscol_str()` still has arguments that were necessary for building a status column string in `number_width()`, which was abandoned in #22094. Solution: Remove unused arguments. --- src/nvim/drawline.c | 6 ++---- src/nvim/statusline.c | 11 ++++------- 2 files changed, 6 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 01ff207c2b..7a64f8ac9d 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -442,14 +442,12 @@ static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, i if (wp->w_statuscol_line_count != wp->w_nrwidth_line_count) { wp->w_statuscol_line_count = wp->w_nrwidth_line_count; set_vim_var_nr(VV_VIRTNUM, 0); - build_statuscol_str(wp, wp->w_nrwidth_line_count, 0, stcp->width, - ' ', stcp->text, &stcp->hlrec, stcp); + build_statuscol_str(wp, wp->w_nrwidth_line_count, 0, stcp); stcp->width += stcp->truncate; } set_vim_var_nr(VV_VIRTNUM, virtnum); - int width = build_statuscol_str(wp, lnum, relnum, stcp->width, - ' ', stcp->text, &stcp->hlrec, stcp); + int width = build_statuscol_str(wp, lnum, relnum, stcp); // Force a redraw in case of error or when truncated if (*wp->w_p_stc == NUL || (stcp->truncate > 0 && wp->w_nrwidth < MAX_NUMBERWIDTH)) { if (stcp->truncate) { // Avoid truncating 'statuscolumn' diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 6ad1f31143..a1523f6574 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -885,11 +885,8 @@ void draw_tabline(void) /// Build the 'statuscolumn' string for line "lnum". When "relnum" == -1, /// the v:lnum and v:relnum variables don't have to be updated. /// -/// @param hlrec HL attributes (can be NULL) -/// @param stcp Status column attributes (can be NULL) /// @return The width of the built status column string for line "lnum" -int build_statuscol_str(win_T *wp, linenr_T lnum, long relnum, int maxwidth, int fillchar, - char *buf, stl_hlrec_t **hlrec, statuscol_T *stcp) +int build_statuscol_str(win_T *wp, linenr_T lnum, long relnum, statuscol_T *stcp) { bool fillclick = relnum >= 0 && lnum == wp->w_topline; @@ -900,8 +897,8 @@ int build_statuscol_str(win_T *wp, linenr_T lnum, long relnum, int maxwidth, int StlClickRecord *clickrec; char *stc = xstrdup(wp->w_p_stc); - int width = build_stl_str_hl(wp, buf, MAXPATHL, stc, "statuscolumn", OPT_LOCAL, fillchar, - maxwidth, hlrec, fillclick ? &clickrec : NULL, stcp); + int width = build_stl_str_hl(wp, stcp->text, MAXPATHL, stc, "statuscolumn", OPT_LOCAL, ' ', + stcp->width, &stcp->hlrec, fillclick ? &clickrec : NULL, stcp); xfree(stc); // Only update click definitions once per window per redraw @@ -909,7 +906,7 @@ int build_statuscol_str(win_T *wp, linenr_T lnum, long relnum, int maxwidth, int stl_clear_click_defs(wp->w_statuscol_click_defs, wp->w_statuscol_click_defs_size); wp->w_statuscol_click_defs = stl_alloc_click_defs(wp->w_statuscol_click_defs, width, &wp->w_statuscol_click_defs_size); - stl_fill_click_defs(wp->w_statuscol_click_defs, clickrec, buf, width, false); + stl_fill_click_defs(wp->w_statuscol_click_defs, clickrec, stcp->text, width, false); } return width; -- cgit From 08fb3b5309dee79585f3eec2450636966cbb01b4 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Tue, 31 Jan 2023 00:52:34 +0100 Subject: perf(column): only build fold/sign column when present in 'statuscolumn' Problem: The fold and sign column is built and stored regardless of whether the corresponding item is present in 'statuscolumn'. Solution: Since the 'statuscolumn' parses itself, we can defer building the columns until the corresponding item is actually encountered. --- src/nvim/buffer_defs.h | 11 ++++++----- src/nvim/drawline.c | 45 +++++++++++---------------------------------- src/nvim/fold.h | 11 ----------- src/nvim/fold_defs.h | 17 +++++++++++++++++ src/nvim/statusline.c | 38 +++++++++++++++++++++++++++++--------- 5 files changed, 63 insertions(+), 59 deletions(-) create mode 100644 src/nvim/fold_defs.h (limited to 'src') diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 4c99191170..4f0e991ad5 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -18,6 +18,7 @@ typedef struct { #include "klib/kvec.h" #include "nvim/api/private/defs.h" #include "nvim/eval/typval.h" +#include "nvim/fold_defs.h" #include "nvim/garray.h" #include "nvim/grid_defs.h" #include "nvim/hashtab.h" @@ -1423,17 +1424,17 @@ struct statuscol { int width; ///< width of the status column int cur_attr; ///< current attributes in text int num_attr; ///< attributes used for line number - int fold_attr; ///< attributes used for fold column - int sign_attr[SIGN_SHOW_MAX + 1]; ///< attributes used for signs + int sign_cul_attr; ///< cursorline sign attr int truncate; ///< truncated width - bool draw; ///< draw statuscolumn or not - char fold_text[9 * 4 + 1]; ///< text in fold column (%C) - char *sign_text[SIGN_SHOW_MAX + 1]; ///< text in sign column (%s) + bool draw; ///< whether to draw the statuscolumn + bool use_cul; ///< whether to use cursorline attrs char text[MAXPATHL]; ///< text in status column char *textp; ///< current position in text char *text_end; ///< end of text (the NUL byte) stl_hlrec_t *hlrec; ///< highlight groups stl_hlrec_t *hlrecp; ///< current highlight group + foldinfo_T foldinfo; ///< fold information + SignTextAttrs *sattrs; ///< sign attributes }; /// Macros defined in Vim, but not in Neovim diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 01ff207c2b..5281370995 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -404,37 +404,10 @@ static int get_sign_attrs(buf_T *buf, linenr_T lnum, SignTextAttrs *sattrs, int /// the start of the buffer line "lnum" and once for the wrapped lines. /// /// @param[out] stcp Status column attributes -static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines, - int cul_attr, int sign_num_attr, int sign_cul_attr, statuscol_T *stcp, - foldinfo_T foldinfo, SignTextAttrs *sattrs) +static void get_statuscol_str(win_T *wp, linenr_T lnum, int virtnum, statuscol_T *stcp) { - long relnum = -1; - bool use_cul = use_cursor_line_sign(wp, lnum); - int virtnum = row - startrow - filler_lines; - - // When called the first time for line "lnum" set num_attr - if (stcp->num_attr == 0) { - stcp->num_attr = sign_num_attr ? sign_num_attr - : get_line_number_attr(wp, lnum, row, startrow, filler_lines); - } - // When called for the first non-filler row of line "lnum" set num v:vars and fold column - if (virtnum == 0) { - relnum = labs(get_cursor_rel_lnum(wp, lnum)); - if (compute_foldcolumn(wp, 0)) { - size_t n = fill_foldcolumn(stcp->fold_text, wp, foldinfo, lnum); - stcp->fold_text[n] = NUL; - stcp->fold_attr = win_hl_attr(wp, use_cul ? HLF_CLF : HLF_FC); - } - } - // Make sure to clear->set->clear sign column for filler->first->wrapped lines - int i = 0; - for (; i < wp->w_scwidth; i++) { - SignTextAttrs *sattr = virtnum ? NULL : sign_get_attr(i, sattrs, wp->w_scwidth); - stcp->sign_text[i] = sattr && sattr->text ? sattr->text : " "; - stcp->sign_attr[i] = sattr ? (use_cul && sign_cul_attr ? sign_cul_attr : sattr->hl_attr_id) - : win_hl_attr(wp, use_cul ? HLF_CLS : HLF_SC); - } - stcp->sign_text[i] = NULL; + // When called for the first non-filler row of line "lnum" set num v:vars + long relnum = virtnum == 0 ? labs(get_cursor_rel_lnum(wp, lnum)) : -1; // When a buffer's line count has changed, make a best estimate for the full // width of the status column by building with "w_nrwidth_line_count". Add @@ -496,8 +469,7 @@ static void get_statuscol_display_info(statuscol_T *stcp, LineDrawState *draw_st if (stcp->textp + *n_extrap < stcp->text_end) { int hl = stcp->hlrecp->userhl; stcp->textp = stcp->hlrecp->start; - stcp->cur_attr = hl < 0 ? syn_id2attr(-stcp->hlrecp->userhl) - : hl > 0 ? hl : stcp->num_attr; + stcp->cur_attr = hl < 0 ? syn_id2attr(-hl) : hl > 0 ? hl : stcp->num_attr; stcp->hlrecp++; *draw_state = WL_STC - 1; } @@ -1211,7 +1183,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (*wp->w_p_stc != NUL) { // Draw the 'statuscolumn' if option is set. statuscol.draw = true; + statuscol.sattrs = sattrs; + statuscol.foldinfo = foldinfo; statuscol.width = win_col_off(wp); + statuscol.use_cul = use_cursor_line_sign(wp, lnum); + statuscol.sign_cul_attr = statuscol.use_cul ? sign_cul_attr : 0; + statuscol.num_attr = sign_num_attr ? sign_num_attr + : get_line_number_attr(wp, lnum, row, startrow, filler_lines); } int sign_idx = 0; @@ -1357,8 +1335,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // Draw the 'statuscolumn' if option is set. if (statuscol.draw) { if (statuscol.textp == NULL) { - get_statuscol_str(wp, lnum, row, startrow, filler_lines, cul_attr, - sign_num_attr, sign_cul_attr, &statuscol, foldinfo, sattrs); + get_statuscol_str(wp, lnum, row - startrow - filler_lines, &statuscol); if (wp->w_redr_statuscol) { break; } diff --git a/src/nvim/fold.h b/src/nvim/fold.h index ac1e8c9419..cf44cf14c3 100644 --- a/src/nvim/fold.h +++ b/src/nvim/fold.h @@ -9,17 +9,6 @@ #include "nvim/pos.h" #include "nvim/types.h" -// Info used to pass info about a fold from the fold-detection code to the -// code that displays the foldcolumn. -typedef struct foldinfo { - linenr_T fi_lnum; // line number where fold starts - int fi_level; // level of the fold; when this is zero the - // other fields are invalid - int fi_low_level; // lowest fold level that starts in the same - // line - linenr_T fi_lines; -} foldinfo_T; - EXTERN int disable_fold_update INIT(= 0); #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/fold_defs.h b/src/nvim/fold_defs.h new file mode 100644 index 0000000000..c528d25348 --- /dev/null +++ b/src/nvim/fold_defs.h @@ -0,0 +1,17 @@ +#ifndef NVIM_FOLD_DEFS_H +#define NVIM_FOLD_DEFS_H + +#include "nvim/pos.h" + +// Info used to pass info about a fold from the fold-detection code to the +// code that displays the foldcolumn. +typedef struct foldinfo { + linenr_T fi_lnum; // line number where fold starts + int fi_level; // level of the fold; when this is zero the + // other fields are invalid + int fi_low_level; // lowest fold level that starts in the same + // line + linenr_T fi_lines; +} foldinfo_T; + +#endif // NVIM_FOLD_DEFS_H diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 6ad1f31143..1882cbbacc 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -38,7 +38,7 @@ #include "nvim/path.h" #include "nvim/pos.h" #include "nvim/screen.h" -#include "nvim/sign_defs.h" +#include "nvim/sign.h" #include "nvim/statusline.h" #include "nvim/strings.h" #include "nvim/types.h" @@ -1648,20 +1648,40 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n if (stcp == NULL) { break; } - bool fold = opt == STL_FOLDCOL; + int width = fold ? (compute_foldcolumn(wp, 0) > 0) : wp->w_scwidth; + + if (width == 0) { + break; + } + + char *p; + if (fold) { + size_t n = fill_foldcolumn(out_p, wp, stcp->foldinfo, (linenr_T)get_vim_var_nr(VV_LNUM)); + stl_items[curitem].minwid = win_hl_attr(wp, stcp->use_cul ? HLF_CLF : HLF_FC); + p = out_p; + p[n] = NUL; + } + *buf_tmp = NUL; - for (int i = 0; i <= SIGN_SHOW_MAX; i++) { - char *p = fold ? stcp->fold_text : stcp->sign_text[i]; - if ((!p || !*p) && *buf_tmp == NUL) { - break; + varnumber_T virtnum = get_vim_var_nr(VV_VIRTNUM); + for (int i = 0; i <= width; i++) { + if (i == width) { + if (*buf_tmp == NUL) { + break; + } + stl_items[curitem].minwid = 0; + } else if (!fold) { + SignTextAttrs *sattr = virtnum ? NULL : sign_get_attr(i, stcp->sattrs, wp->w_scwidth); + p = sattr && sattr->text ? sattr->text : " "; + stl_items[curitem].minwid = sattr ? stcp->sign_cul_attr ? stcp->sign_cul_attr + : sattr->hl_attr_id + : win_hl_attr(wp, stcp->use_cul ? HLF_CLS : HLF_SC); } stl_items[curitem].type = Highlight; stl_items[curitem].start = out_p + strlen(buf_tmp); - stl_items[curitem].minwid = !p || (fold && i) ? 0 : fold ? stcp->fold_attr - : stcp->sign_attr[i]; curitem++; - if (!p || (fold && i)) { + if (i == width) { str = buf_tmp; break; } -- cgit From a4e376f09b30250e4e464a7c8b6c5278f0943ced Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Sat, 4 Feb 2023 11:05:24 +0100 Subject: refactor(statusline): move statusline defs to statusline_defs.h --- src/nvim/buffer_defs.h | 51 -------------------------------------------- src/nvim/statusline_defs.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 4f0e991ad5..dda8e7dacd 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -18,7 +18,6 @@ typedef struct { #include "klib/kvec.h" #include "nvim/api/private/defs.h" #include "nvim/eval/typval.h" -#include "nvim/fold_defs.h" #include "nvim/garray.h" #include "nvim/grid_defs.h" #include "nvim/hashtab.h" @@ -338,36 +337,6 @@ struct mapblock { bool m_replace_keycodes; // replace keycodes in result of expression }; -/// Used for highlighting in the status line. -typedef struct stl_hlrec stl_hlrec_t; -struct stl_hlrec { - char *start; - int userhl; // 0: no HL, 1-9: User HL, < 0 for syn ID -}; - -/// Used for building the status line. -typedef struct stl_item stl_item_t; -struct stl_item { - // Where the item starts in the status line output buffer - char *start; - // Function to run for ClickFunc items. - char *cmd; - // The minimum width of the item - int minwid; - // The maximum width of the item - int maxwid; - enum { - Normal, - Empty, - Group, - Separate, - Highlight, - TabPage, - ClickFunc, - Trunc, - } type; -}; - // values for b_syn_spell: what to do with toplevel text #define SYNSPL_DEFAULT 0 // spell check if @Spell not defined #define SYNSPL_TOP 1 // spell check toplevel text @@ -1417,26 +1386,6 @@ struct window_S { size_t w_statuscol_click_defs_size; }; -/// Struct to hold info for 'statuscolumn' -typedef struct statuscol statuscol_T; - -struct statuscol { - int width; ///< width of the status column - int cur_attr; ///< current attributes in text - int num_attr; ///< attributes used for line number - int sign_cul_attr; ///< cursorline sign attr - int truncate; ///< truncated width - bool draw; ///< whether to draw the statuscolumn - bool use_cul; ///< whether to use cursorline attrs - char text[MAXPATHL]; ///< text in status column - char *textp; ///< current position in text - char *text_end; ///< end of text (the NUL byte) - stl_hlrec_t *hlrec; ///< highlight groups - stl_hlrec_t *hlrecp; ///< current highlight group - foldinfo_T foldinfo; ///< fold information - SignTextAttrs *sattrs; ///< sign attributes -}; - /// Macros defined in Vim, but not in Neovim // uncrustify:off #define CHANGEDTICK(buf) \ diff --git a/src/nvim/statusline_defs.h b/src/nvim/statusline_defs.h index eac9dfd690..6835d62cdd 100644 --- a/src/nvim/statusline_defs.h +++ b/src/nvim/statusline_defs.h @@ -3,7 +3,10 @@ #include +#include "nvim/fold_defs.h" #include "nvim/macros.h" +#include "nvim/os/os_defs.h" +#include "nvim/sign_defs.h" /// Status line click definition typedef struct { @@ -23,4 +26,54 @@ typedef struct { const char *start; ///< Location where region starts. } StlClickRecord; +/// Used for highlighting in the status line. +typedef struct stl_hlrec stl_hlrec_t; +struct stl_hlrec { + char *start; + int userhl; // 0: no HL, 1-9: User HL, < 0 for syn ID +}; + +/// Used for building the status line. +typedef struct stl_item stl_item_t; +struct stl_item { + // Where the item starts in the status line output buffer + char *start; + // Function to run for ClickFunc items. + char *cmd; + // The minimum width of the item + int minwid; + // The maximum width of the item + int maxwid; + enum { + Normal, + Empty, + Group, + Separate, + Highlight, + TabPage, + ClickFunc, + Trunc, + } type; +}; + +/// Struct to hold info for 'statuscolumn' +typedef struct statuscol statuscol_T; + +struct statuscol { + int width; ///< width of the status column + int cur_attr; ///< current attributes in text + int num_attr; ///< attributes used for line number + int sign_cul_attr; ///< cursorline sign attr + int truncate; ///< truncated width + bool draw; ///< whether to draw the statuscolumn + bool use_cul; ///< whether to use cursorline attrs + char text[MAXPATHL]; ///< text in status column + char *textp; ///< current position in text + char *text_end; ///< end of text (the NUL byte) + stl_hlrec_t *hlrec; ///< highlight groups + stl_hlrec_t *hlrecp; ///< current highlight group + foldinfo_T foldinfo; ///< fold information + SignTextAttrs *sattrs; ///< sign attributes +}; + #endif // NVIM_STATUSLINE_DEFS_H -- cgit From 90333b24c3582cb017d823583d4896c8bbb8edb8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 4 Feb 2023 19:35:31 +0800 Subject: vim-patch:9.0.1277: cursor may move with autocmd in Visual mode (#22116) Problem: Cursor may move with autocmd in Visual mode. Solution: Restore "VIsual_active" before calling check_cursor(). (closes vim/vim#11939) https://github.com/vim/vim/commit/49f0524fb575bb1cf4881e472afab7d37c579440 --- src/nvim/autocmd.c | 5 ++++- src/nvim/testdir/test_functions.vim | 11 ++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 01ebdfdafe..897c9533e5 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -1535,6 +1535,7 @@ win_found: globaldir = aco->globaldir; // the buffer contents may have changed + VIsual_active = aco->save_VIsual_active; check_cursor(); if (curwin->w_topline > curbuf->b_ml.ml_line_count) { curwin->w_topline = curbuf->b_ml.ml_line_count; @@ -1563,14 +1564,16 @@ win_found: curwin = save_curwin; curbuf = curwin->w_buffer; prevwin = win_find_by_handle(aco->save_prevwin_handle); + // In case the autocommand moves the cursor to a position that does not // exist in curbuf + VIsual_active = aco->save_VIsual_active; check_cursor(); } } - check_cursor(); // just in case lines got deleted VIsual_active = aco->save_VIsual_active; + check_cursor(); // just in case lines got deleted if (VIsual_active) { check_pos(curbuf, &VIsual); } diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 500c30c76b..4ed1187a19 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -1511,7 +1511,7 @@ endfunc func Test_setbufvar_options() " This tests that aucmd_prepbuf() and aucmd_restbuf() properly restore the - " window layout. + " window layout and cursor position. call assert_equal(1, winnr('$')) split dummy_preview resize 2 @@ -1525,11 +1525,20 @@ func Test_setbufvar_options() execute 'belowright vertical split #' . dummy_buf call assert_equal(wh, winheight(0)) let dum1_id = win_getid() + call setline(1, 'foo') + normal! V$ + call assert_equal(4, col('.')) + call setbufvar('dummy_preview', '&buftype', 'nofile') + call assert_equal(4, col('.')) wincmd h let wh = winheight(0) + call setline(1, 'foo') + normal! V$ + call assert_equal(4, col('.')) let dummy_buf = bufnr('dummy_buf2', v:true) eval 'nofile'->setbufvar(dummy_buf, '&buftype') + call assert_equal(4, col('.')) execute 'belowright vertical split #' . dummy_buf call assert_equal(wh, winheight(0)) -- cgit From 69bb145cea56067e6e82ed0a130a51c0d611e540 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 4 Feb 2023 20:14:31 +0800 Subject: refactor(exit): pass error message to preserve_exit() (#22097) Problem: 1. Some calls to preserve_exit() don't put a message in IObuff, so the IObuff printed by preserve_exit() contains unrelated information. 2. If a TUI client runs out of memory or receives a deadly signal, the error message is shown on alternate screen and cannot be easily seen because the TUI exits alternate screen soon afterwards. Solution: Pass error message to preserve_exit() and exit alternate screen before printing it. Note that this doesn't fix the problem that server error messages cannot be easily seen on exit. This is tracked in #21608 and #21843. --- src/nvim/event/rstream.c | 2 +- src/nvim/lua/executor.c | 4 +--- src/nvim/main.c | 13 ++++++++----- src/nvim/memory.c | 15 ++++----------- src/nvim/os/input.c | 3 +-- src/nvim/os/signal.c | 5 ++--- src/nvim/tui/tui.c | 5 +---- src/nvim/ui_client.c | 4 +++- 8 files changed, 21 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/nvim/event/rstream.c b/src/nvim/event/rstream.c index a88d62fd6b..a145452afd 100644 --- a/src/nvim/event/rstream.c +++ b/src/nvim/event/rstream.c @@ -155,7 +155,7 @@ static void fread_idle_cb(uv_idle_t *handle) uintmax_t fpos_intmax = stream->fpos; if (fpos_intmax > INT64_MAX) { ELOG("stream offset overflow"); - preserve_exit(); + preserve_exit("stream offset overflow"); } // Synchronous read diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 1415ceeaed..007662fbc9 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -211,9 +211,7 @@ static int nlua_luv_cfpcall(lua_State *lstate, int nargs, int nresult, int flags if (status) { if (status == LUA_ERRMEM && !(flags & LUVF_CALLBACK_NOEXIT)) { // consider out of memory errors unrecoverable, just like xmalloc() - os_errmsg(e_outofmem); - os_errmsg("\n"); - preserve_exit(); + preserve_exit(e_outofmem); } const char *error = lua_tostring(lstate, -1); diff --git a/src/nvim/main.c b/src/nvim/main.c index e26922bf8e..2bbe70784d 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -790,10 +790,10 @@ void getout(int exitval) os_exit(exitval); } -/// Preserve files, print contents of `IObuff`, and exit 1. +/// Preserve files, print contents of `errmsg`, and exit 1. /// /// May be called from deadly_signal(). -void preserve_exit(void) +void preserve_exit(const char *errmsg) FUNC_ATTR_NORETURN { // 'true' when we are sure to exit, e.g., after a deadly signal @@ -813,11 +813,14 @@ void preserve_exit(void) signal_reject_deadly(); if (ui_client_channel_id) { - os_exit(1); + // For TUI: exit alternate screen so that the error messages can be seen. + ui_client_stop(); } - - os_errmsg(IObuff); + os_errmsg(errmsg); os_errmsg("\n"); + if (ui_client_channel_id) { + os_exit(1); + } ui_flush(); ml_close_notmod(); // close all not-modified buffers diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 5356300382..4e799dfd08 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -121,9 +121,7 @@ void *xmalloc(size_t size) { void *ret = try_malloc(size); if (!ret) { - os_errmsg(e_outofmem); - os_errmsg("\n"); - preserve_exit(); + preserve_exit(e_outofmem); } return ret; } @@ -152,9 +150,7 @@ void *xcalloc(size_t count, size_t size) try_to_free_memory(); ret = calloc(allocated_count, allocated_size); if (!ret) { - os_errmsg(e_outofmem); - os_errmsg("\n"); - preserve_exit(); + preserve_exit(e_outofmem); } } return ret; @@ -174,9 +170,7 @@ void *xrealloc(void *ptr, size_t size) try_to_free_memory(); ret = realloc(ptr, allocated_size); if (!ret) { - os_errmsg(e_outofmem); - os_errmsg("\n"); - preserve_exit(); + preserve_exit(e_outofmem); } } return ret; @@ -194,8 +188,7 @@ void *xmallocz(size_t size) { size_t total_size = size + 1; if (total_size < size) { - os_errmsg(_("Vim: Data too large to fit into virtual memory space\n")); - preserve_exit(); + preserve_exit(_("Vim: Data too large to fit into virtual memory space\n")); } void *ret = xmalloc(total_size); diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 759b3cf83c..44ad0315a5 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -550,8 +550,7 @@ static void read_error_exit(void) if (silent_mode) { // Normal way to exit for "nvim -es". getout(0); } - STRCPY(IObuff, _("Vim: Error reading input, exiting...\n")); - preserve_exit(); + preserve_exit(_("Vim: Error reading input, exiting...\n")); } static bool pending_events(MultiQueue *events) diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c index b8daaabba2..e7b745fb7e 100644 --- a/src/nvim/os/signal.c +++ b/src/nvim/os/signal.c @@ -172,11 +172,10 @@ static void deadly_signal(int signum) ILOG("got signal %d (%s)", signum, signal_name(signum)); - snprintf(IObuff, sizeof(IObuff), "Vim: Caught deadly signal '%s'\r\n", - signal_name(signum)); + snprintf(IObuff, IOSIZE, "Vim: Caught deadly signal '%s'\r\n", signal_name(signum)); // Preserve files and exit. - preserve_exit(); + preserve_exit(IObuff); } static void on_signal(SignalWatcher *handle, int signum, void *data) diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index f760e99262..fff5c865bf 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -458,9 +458,6 @@ static void tui_terminal_stop(TUIData *tui) void tui_stop(TUIData *tui) { - if (tui->stopped) { - return; - } tui_terminal_stop(tui); stream_set_blocking(tui->input.in_fd, true); // normalize stream (#2598) tinput_destroy(&tui->input); @@ -470,7 +467,7 @@ void tui_stop(TUIData *tui) } /// Returns true if UI `ui` is stopped. -static bool tui_is_stopped(TUIData *tui) +bool tui_is_stopped(TUIData *tui) { return tui->stopped; } diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index b5c8dff412..58edd7aff3 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -122,7 +122,9 @@ void ui_client_run(bool remote_ui) void ui_client_stop(void) { - tui_stop(tui); + if (!tui_is_stopped(tui)) { + tui_stop(tui); + } } void ui_client_set_size(int width, int height) -- cgit From 4b9bb3a1841489a18bbeb124fc11cbf359553ef5 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sat, 4 Feb 2023 16:05:45 +0100 Subject: vim-patch:9.0.1278: go.work.sum files are not recognized (#22121) Problem: go.work.sum files are not recognized. Solution: Recognize go.work.sum files as the gosum filetype. (Amaan Qureshi, closes vim/vim#11940) https://github.com/vim/vim/commit/4ad8ae8465e30df38dba31910f130891b16d38a0 Co-authored-by: Amaan Qureshi --- src/nvim/testdir/test_filetype.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 7b5ec22dd4..7cf32bd3a5 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -235,7 +235,7 @@ let s:filename_checks = { \ 'gnuplot': ['file.gpi', '.gnuplot'], \ 'go': ['file.go'], \ 'gomod': ['go.mod'], - \ 'gosum': ['go.sum'], + \ 'gosum': ['go.sum', 'go.work.sum'], \ 'gowork': ['go.work'], \ 'gp': ['file.gp', '.gprc'], \ 'gpg': ['/.gnupg/options', '/.gnupg/gpg.conf', '/usr/any/gnupg/options.skel', 'any/.gnupg/gpg.conf', 'any/.gnupg/options', 'any/usr/any/gnupg/options.skel'], -- cgit From 5c4b503d3cb4a48d083bcf50d4932927e6eb749d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 5 Feb 2023 09:37:12 +0800 Subject: vim-patch:9.0.1279: display shows lines scrolled down erroneously (#22126) Problem: Display shows lines scrolled down erroneously. (Yishai Lerner) Solution: Do not change "wl_lnum" at index zero. (closes vim/vim#11938) https://github.com/vim/vim/commit/61fdbfa1e3c842252b701aec12f45839ca41ece5 Co-authored-by: Bram Moolenaar --- src/nvim/change.c | 4 +++- src/nvim/testdir/test_move.vim | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/change.c b/src/nvim/change.c index 06696610b0..1bd7ea3a5a 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -296,7 +296,9 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T for (int i = 0; i < wp->w_lines_valid; i++) { if (wp->w_lines[i].wl_valid) { if (wp->w_lines[i].wl_lnum >= lnum) { - if (wp->w_lines[i].wl_lnum < lnume) { + // Do not change wl_lnum at index zero, it is used to + // compare with w_topline. Invalidate it instead. + if (wp->w_lines[i].wl_lnum < lnume || i == 0) { // line included in change wp->w_lines[i].wl_valid = false; } else if (xtra != 0) { diff --git a/src/nvim/testdir/test_move.vim b/src/nvim/testdir/test_move.vim index 8c40369dbd..40d75d887e 100644 --- a/src/nvim/testdir/test_move.vim +++ b/src/nvim/testdir/test_move.vim @@ -1,5 +1,8 @@ " Test the ":move" command. +source check.vim +source screendump.vim + func Test_move() enew! call append(0, ['line 1', 'line 2', 'line 3']) @@ -43,4 +46,25 @@ func Test_move() %bwipeout! endfunc +func Test_move_undo() + CheckRunVimInTerminal + + let lines =<< trim END + call setline(1, ['First', 'Second', 'Third', 'Fourth']) + END + call writefile(lines, 'Xtest_move_undo.vim', 'D') + let buf = RunVimInTerminal('-S Xtest_move_undo.vim', #{rows: 10, cols: 60, statusoff: 2}) + + call term_sendkeys(buf, "gg:move +1\") + call VerifyScreenDump(buf, 'Test_move_undo_1', {}) + + " here the display would show the last few lines scrolled down + call term_sendkeys(buf, "u") + call term_sendkeys(buf, ":\") + call VerifyScreenDump(buf, 'Test_move_undo_2', {}) + + call StopVimInTerminal(buf) +endfunc + + " vim: shiftwidth=2 sts=2 expandtab -- cgit From 23e34fe534d201a1323ab040cb2201d21fe865cc Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sun, 5 Feb 2023 17:59:18 +0100 Subject: vim-patch:9.0.1281: Cadence files are not recognized (#22130) Problem: Cadence files are not recognized. Solution: Recognize Cadence files. (Janez Podhostnik, closes vim/vim#11951) https://github.com/vim/vim/commit/cb626a4692df7154be02b47d6089ec679e95cb44 Co-authored-by: Janez Podhostnik --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 7cf32bd3a5..3af200799a 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -522,6 +522,7 @@ let s:filename_checks = { \ 'sinda': ['file.sin', 'file.s85'], \ 'sisu': ['file.sst', 'file.ssm', 'file.ssi', 'file.-sst', 'file._sst', 'file.sst.meta', 'file.-sst.meta', 'file._sst.meta'], \ 'skill': ['file.il', 'file.ils', 'file.cdf'], + \ 'cdc': ['file.cdc'], \ 'slang': ['file.sl'], \ 'slice': ['file.ice'], \ 'slpconf': ['/etc/slp.conf', 'any/etc/slp.conf'], -- cgit From 228684d2fbb6262f761b2b5d7001033bd69880c1 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sun, 5 Feb 2023 23:49:43 +0000 Subject: fix(decoration): don't show signcolumn for non-sign_text extmark (#22135) Fixes: #22127 --- src/nvim/buffer_defs.h | 1 + src/nvim/decoration.c | 14 +++++++++----- src/nvim/extmark.c | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 4c99191170..3601dc7062 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -838,6 +838,7 @@ struct file_buffer { Map(uint32_t, uint32_t) b_extmark_ns[1]; // extmark namespaces size_t b_virt_line_blocks; // number of virt_line blocks size_t b_signs; // number of sign extmarks + size_t b_signs_with_text; // number of sign extmarks with text // array of channel_id:s which have asked to receive updates for this // buffer. diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 63c55ec602..c98ffbeefb 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -100,9 +100,13 @@ void decor_remove(buf_T *buf, int row, int row2, Decoration *decor) if (decor_has_sign(decor)) { assert(buf->b_signs > 0); buf->b_signs--; - } - if (row2 >= row && decor->sign_text) { - buf_signcols_del_check(buf, row + 1, row2 + 1); + if (decor->sign_text) { + assert(buf->b_signs_with_text > 0); + buf->b_signs_with_text--; + if (row2 >= row) { + buf_signcols_del_check(buf, row + 1, row2 + 1); + } + } } } decor_free(decor); @@ -445,11 +449,11 @@ int decor_signcols(buf_T *buf, DecorState *state, int row, int end_row, int max) int signcols = 0; // highest value of count int currow = -1; // current row - if (max <= 1 && buf->b_signs >= (size_t)max) { + if (max <= 1 && buf->b_signs_with_text >= (size_t)max) { return max; } - if (buf->b_signs == 0) { + if (buf->b_signs_with_text == 0) { return 0; } diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index 3e059bcc6c..1132a5e752 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -152,6 +152,7 @@ revised: buf->b_signs++; } if (decor->sign_text) { + buf->b_signs_with_text++; // TODO(lewis6991): smarter invalidation buf_signcols_add_check(buf, NULL); } -- cgit From 1675f0e270579036c454c38f28e650b60a3fba1a Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Mon, 6 Feb 2023 04:01:17 -0500 Subject: vim-patch:9.0.1282: Ron files are not recognized (#22132) Problem: Ron files are not recognized. Solution: Recognize Ron files. (Amaan Qureshi, closes vim/vim#11948) https://github.com/vim/vim/commit/c8ef30bc2eaec956549510cd4b2efc96b7aee563 --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 3af200799a..bdd12d44cb 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -489,6 +489,7 @@ let s:filename_checks = { \ 'rnoweb': ['file.rnw', 'file.snw'], \ 'robot': ['file.robot', 'file.resource'], \ 'robots': ['robots.txt'], + \ 'ron': ['file.ron'], \ 'routeros': ['file.rsc'], \ 'rpcgen': ['file.x'], \ 'rpl': ['file.rpl'], -- cgit From e1f03c481a1cf87cead2c5af66b36dbdfbb9a983 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Mon, 6 Feb 2023 10:01:38 +0100 Subject: feat(spell): also source `spell/LANG.lua` when setting `spelllang` (#22111) Problem: only Vimscript files are sourced when setting spelling language Solution: also source Lua files after sourcing Vimscript files Closes #22110 --- src/nvim/optionstr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index ca50c3ab00..901477d869 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1581,7 +1581,7 @@ static void do_spelllang_source(win_T *win) q += 4; } - // Source the spell/LANG.vim in 'runtimepath'. + // Source the spell/LANG.{vim,lua} in 'runtimepath'. // They could set 'spellcapcheck' depending on the language. // Use the first name in 'spelllang' up to '_region' or // '.encoding'. @@ -1592,7 +1592,7 @@ static void do_spelllang_source(win_T *win) } } if (p > q) { - vim_snprintf(fname, sizeof(fname), "spell/%.*s.vim", (int)(p - q), q); + vim_snprintf(fname, sizeof(fname), "spell/%.*s.\\(vim\\|lua\\)", (int)(p - q), q); source_runtime(fname, DIP_ALL); } } -- cgit From 1391385ba9f83d32f3b6fc54587f03a1d34960d9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 7 Feb 2023 07:54:33 +0800 Subject: vim-patch:9.0.1290: CTRL-N and -P on cmdline don't trigger CmdlineChanged (#22151) Problem: CTRL-N and -P on cmdline don't trigger CmdlineChanged. Solution: Jump to cmdline_changed instead of cmdline_not_changed. (closes vim/vim#11956) https://github.com/vim/vim/commit/af9e28a5b8f888b79459393ddb26fffe613c3f3c Cherry-pick Test_Cmdline() change from patch 9.0.1039. --- src/nvim/ex_getln.c | 4 ++-- src/nvim/testdir/test_autocmd.vim | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 76c3680742..eadeb839de 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2015,7 +2015,7 @@ static int command_line_handle_key(CommandLineState *s) if (nextwild(&s->xpc, wild_type, 0, s->firstc != '@') == FAIL) { break; } - return command_line_not_changed(s); + return command_line_changed(s); } FALLTHROUGH; @@ -2037,7 +2037,7 @@ static int command_line_handle_key(CommandLineState *s) if (nextwild(&s->xpc, wild_type, 0, s->firstc != '@') == FAIL) { break; } - return command_line_not_changed(s); + return command_line_changed(s); } else { switch (command_line_browse_history(s)) { case CMDLINE_CHANGED: diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 83af0f6be0..a1a3ba3198 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -1897,6 +1897,50 @@ func Test_Cmdline() call assert_equal(':', g:entered) au! CmdlineChanged + let g:log = [] + cnoremap call setcmdline('ls') + autocmd CmdlineChanged : let g:log += [getcmdline()] + call feedkeys(":\", 'xt') + call assert_equal(['ls'], g:log) + unlet g:log + au! CmdlineChanged + cunmap + + let g:log = [] + autocmd CmdlineChanged : let g:log += [getcmdline()] + call feedkeys(":sign \\\\\\\", 'xt') + call assert_equal([ + \ 's', + \ 'si', + \ 'sig', + \ 'sign', + \ 'sign ', + \ 'sign define', + \ 'sign jump', + \ 'sign list', + \ 'sign jump', + \ 'sign define', + \ 'sign ', + \ ], g:log) + let g:log = [] + set wildmenu wildoptions+=pum + call feedkeys(":sign \\\\\\", 'xt') + call assert_equal([ + \ 's', + \ 'si', + \ 'sig', + \ 'sign', + \ 'sign ', + \ 'sign unplace', + \ 'sign jump', + \ 'sign define', + \ 'sign undefine', + \ 'sign unplace', + \ ], g:log) + set wildmenu& wildoptions& + unlet g:log + au! CmdlineChanged + au! CmdlineEnter : let g:entered = expand('') au! CmdlineLeave : let g:left = expand('') let g:entered = 0 -- cgit From 8fbe75b3dda7ab3b9e6df0d5406539bde4c80887 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Tue, 7 Feb 2023 10:29:37 +0100 Subject: vim-patch:9.0.1288: FunC files are not recognized (#22153) Problem: FunC files are not recognized. Solution: Recognize FunC files. (Amaan Qureshi, closes vim/vim#11949) https://github.com/vim/vim/commit/91deac45392fe93094b9c31403b1ae771dc71938 Co-authored-by: Amaan Qureshi --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index bdd12d44cb..901d1c79de 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -211,6 +211,7 @@ let s:filename_checks = { \ 'fsh': ['file.fsh'], \ 'fsharp': ['file.fs', 'file.fsi', 'file.fsx'], \ 'fstab': ['fstab', 'mtab'], + \ 'func': ['file.fc'], \ 'fusion': ['file.fusion'], \ 'fvwm': ['/.fvwm/file', 'any/.fvwm/file'], \ 'gdb': ['.gdbinit', 'gdbinit', 'file.gdb', '.config/gdbearlyinit', '.gdbearlyinit'], -- cgit From c1d76363ac72a7a17b657eaa99df4533d169a40b Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 7 Feb 2023 14:43:45 +0100 Subject: ci: simplify how environment variables are used (#22067) Having a clear separation between when we manipulate variables and when we export them to GITHUB_ENV makes it less error-prone. --- src/nvim/CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index fd34a30619..e4bbdda0c3 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -166,13 +166,14 @@ if(CI_BUILD) target_compile_options(main_lib INTERFACE -WX) else() target_compile_options(main_lib INTERFACE -Werror) - if(DEFINED ENV{BUILD_UCHAR}) - # Get some test coverage for unsigned char - target_compile_options(main_lib INTERFACE -funsigned-char) - endif() endif() endif() +option(UNSIGNED_CHAR "Set char to be unsigned" OFF) +if(UNSIGNED_CHAR) + target_compile_options(main_lib INTERFACE -funsigned-char) +endif() + list(APPEND CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}") check_c_source_compiles(" #include -- cgit From 1ca4a8b1ddf5256ad53cf486d0b2125434168270 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 8 Feb 2023 09:47:55 +0100 Subject: vim-patch:9.0.1291: Move language files are not recognized (#22162) Problem: Move language files are not recognized. Solution: Recognize Move language files. (Amaan Qureshi, closes vim/vim#11947) https://github.com/vim/vim/commit/6642982beaf4f1f5164f0315a1b3e3c275156089 Co-authored-by: Amaan Qureshi --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 901d1c79de..0264e203d9 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -381,6 +381,7 @@ let s:filename_checks = { \ 'monk': ['file.isc', 'file.monk', 'file.ssc', 'file.tsc'], \ 'moo': ['file.moo'], \ 'moonscript': ['file.moon'], + \ 'move': ['file.move'], \ 'mp': ['file.mp', 'file.mpxl', 'file.mpiv', 'file.mpvi'], \ 'mplayerconf': ['mplayer.conf', '/.mplayer/config', 'any/.mplayer/config'], \ 'mrxvtrc': ['mrxvtrc', '.mrxvtrc'], -- cgit From 645daaf5e912ca8623a99dbc2cdbeb34d64a91f8 Mon Sep 17 00:00:00 2001 From: Enan Ajmain <3nan.ajmain@gmail.com> Date: Wed, 8 Feb 2023 15:08:18 +0600 Subject: build(Windows): make bundling nvim-qt optional (#21866) Closes https://github.com/neovim/neovim/issues/14552. --- src/nvim/CMakeLists.txt | 127 +++++++++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index e4bbdda0c3..fd1c3c28db 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -712,6 +712,59 @@ if(WIN32) -P ${PROJECT_SOURCE_DIR}/cmake/WindowsDllCopy.cmake) add_dependencies(nvim_runtime_deps nvim_dll_deps) + if(USE_BUNDLED_NVIMQT) + set(NVIMQT_DEPS + # Dependencies for neovim-qt + bearer/qgenericbearer.dll + iconengines/qsvgicon.dll + imageformats/qgif.dll + imageformats/qicns.dll + imageformats/qico.dll + imageformats/qjpeg.dll + imageformats/qsvg.dll + imageformats/qtga.dll + imageformats/qtiff.dll + imageformats/qwbmp.dll + imageformats/qwebp.dll + platforms/qwindows.dll + styles/qwindowsvistastyle.dll + translations/qt_ar.qm + translations/qt_bg.qm + translations/qt_ca.qm + translations/qt_cs.qm + translations/qt_da.qm + translations/qt_de.qm + translations/qt_en.qm + translations/qt_es.qm + translations/qt_fi.qm + translations/qt_fr.qm + translations/qt_gd.qm + translations/qt_he.qm + translations/qt_hu.qm + translations/qt_it.qm + translations/qt_ja.qm + translations/qt_ko.qm + translations/qt_lv.qm + translations/qt_pl.qm + translations/qt_ru.qm + translations/qt_sk.qm + translations/qt_uk.qm + D3Dcompiler_47.dll + libEGL.dll + libgcc_s_seh-1.dll + libGLESv2.dll + libstdc++-6.dll + libwinpthread-1.dll + nvim-qt.exe + opengl32sw.dll + Qt5Core.dll + Qt5Gui.dll + Qt5Network.dll + Qt5Svg.dll + Qt5Widgets.dll + ) + endif() + # A CMake script is used for copying the files to avoid the # "command line is too long" error that occurs when Ninja tries running # a command that exceeds the length limit (8191 characters) on Windows. @@ -719,67 +772,19 @@ if(WIN32) set(EXTERNAL_BLOBS_SCRIPT "file(MAKE_DIRECTORY \"${PROJECT_BINARY_DIR}/windows_runtime_deps/platforms\")") foreach(DEP_FILE IN ITEMS - curl-ca-bundle.crt - curl.exe - diff.exe - tee.exe - win32yank.exe - xxd.exe - - # Dependencies for neovim-qt - bearer/qgenericbearer.dll - iconengines/qsvgicon.dll - imageformats/qgif.dll - imageformats/qicns.dll - imageformats/qico.dll - imageformats/qjpeg.dll - imageformats/qsvg.dll - imageformats/qtga.dll - imageformats/qtiff.dll - imageformats/qwbmp.dll - imageformats/qwebp.dll - platforms/qwindows.dll - styles/qwindowsvistastyle.dll - translations/qt_ar.qm - translations/qt_bg.qm - translations/qt_ca.qm - translations/qt_cs.qm - translations/qt_da.qm - translations/qt_de.qm - translations/qt_en.qm - translations/qt_es.qm - translations/qt_fi.qm - translations/qt_fr.qm - translations/qt_gd.qm - translations/qt_he.qm - translations/qt_hu.qm - translations/qt_it.qm - translations/qt_ja.qm - translations/qt_ko.qm - translations/qt_lv.qm - translations/qt_pl.qm - translations/qt_ru.qm - translations/qt_sk.qm - translations/qt_uk.qm - D3Dcompiler_47.dll - libEGL.dll - libgcc_s_seh-1.dll - libGLESv2.dll - libstdc++-6.dll - libwinpthread-1.dll - nvim-qt.exe - opengl32sw.dll - Qt5Core.dll - Qt5Gui.dll - Qt5Network.dll - Qt5Svg.dll - Qt5Widgets.dll - - ) - get_filename_component(DEP_FILE_DIR ${DEP_FILE} DIRECTORY) - set(EXTERNAL_BLOBS_SCRIPT "${EXTERNAL_BLOBS_SCRIPT}\n" - "file(COPY \"${DEPS_PREFIX}/bin/${DEP_FILE}\" - DESTINATION \"${PROJECT_BINARY_DIR}/windows_runtime_deps/${DEP_FILE_DIR}\")") + curl-ca-bundle.crt + curl.exe + diff.exe + tee.exe + win32yank.exe + xxd.exe + + ${NVIMQT_DEPS} + ) + get_filename_component(DEP_FILE_DIR ${DEP_FILE} DIRECTORY) + set(EXTERNAL_BLOBS_SCRIPT "${EXTERNAL_BLOBS_SCRIPT}\n" + "file(COPY \"${DEPS_PREFIX}/bin/${DEP_FILE}\" + DESTINATION \"${PROJECT_BINARY_DIR}/windows_runtime_deps/${DEP_FILE_DIR}\")") endforeach() file(WRITE ${PROJECT_BINARY_DIR}/external_blobs.cmake ${EXTERNAL_BLOBS_SCRIPT}) add_custom_target(external_blobs -- cgit From 4d2c1004e96faad1179591b4409a75965af43985 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 8 Feb 2023 11:00:16 +0100 Subject: build: prefer -D = over -D= (#22164) This makes it easier to see that -D is referring to the entire "=", rather than only . It also help syntax highlighters highlight built-in variables. --- src/nvim/CMakeLists.txt | 18 +++++++++--------- src/nvim/po/CMakeLists.txt | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index fd1c3c28db..5e5634ba77 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -449,12 +449,12 @@ set(gen_cflags ${gen_cflags} -O2) set(NVIM_VERSION_GIT_H ${PROJECT_BINARY_DIR}/cmake.config/auto/versiondef_git.h) add_custom_target(update_version_stamp COMMAND ${CMAKE_COMMAND} - -DNVIM_VERSION_MAJOR=${NVIM_VERSION_MAJOR} - -DNVIM_VERSION_MINOR=${NVIM_VERSION_MINOR} - -DNVIM_VERSION_PATCH=${NVIM_VERSION_PATCH} - -DNVIM_VERSION_PRERELEASE=${NVIM_VERSION_PRERELEASE} - -DOUTPUT=${NVIM_VERSION_GIT_H} - -DNVIM_SOURCE_DIR=${CMAKE_SOURCE_DIR} + -D NVIM_VERSION_MAJOR=${NVIM_VERSION_MAJOR} + -D NVIM_VERSION_MINOR=${NVIM_VERSION_MINOR} + -D NVIM_VERSION_PATCH=${NVIM_VERSION_PATCH} + -D NVIM_VERSION_PRERELEASE=${NVIM_VERSION_PRERELEASE} + -D OUTPUT=${NVIM_VERSION_GIT_H} + -D NVIM_SOURCE_DIR=${CMAKE_SOURCE_DIR} -P ${PROJECT_SOURCE_DIR}/cmake/GenerateVersion.cmake BYPRODUCTS ${NVIM_VERSION_GIT_H}) @@ -706,9 +706,9 @@ if(WIN32) add_custom_target(nvim_dll_deps DEPENDS nvim COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps COMMAND ${CMAKE_COMMAND} - "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" - -DBINARY="${PROJECT_BINARY_DIR}/bin/nvim${CMAKE_EXECUTABLE_SUFFIX}" - -DDST=${PROJECT_BINARY_DIR}/windows_runtime_deps + -D CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} + -D BINARY="${PROJECT_BINARY_DIR}/bin/nvim${CMAKE_EXECUTABLE_SUFFIX}" + -D DST=${PROJECT_BINARY_DIR}/windows_runtime_deps -P ${PROJECT_SOURCE_DIR}/cmake/WindowsDllCopy.cmake) add_dependencies(nvim_runtime_deps nvim_dll_deps) diff --git a/src/nvim/po/CMakeLists.txt b/src/nvim/po/CMakeLists.txt index 1db21880bb..a5a3c135d3 100644 --- a/src/nvim/po/CMakeLists.txt +++ b/src/nvim/po/CMakeLists.txt @@ -100,12 +100,12 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG) add_custom_target(update-po-${lang} COMMAND ${CMAKE_COMMAND} - -DICONV_PRG=${ICONV_PRG} - -DINPUT_FILE=${inputFile} - -DOUTPUT_FILE=${outputFile} - -DINPUT_ENC=${inputEnc} - -DOUTPUT_ENC=${outputEnc} - -DOUTPUT_CHARSET=${outputCharSet} + -D ICONV_PRG=${ICONV_PRG} + -D INPUT_FILE=${inputFile} + -D OUTPUT_FILE=${outputFile} + -D INPUT_ENC=${inputEnc} + -D OUTPUT_ENC=${outputEnc} + -D OUTPUT_CHARSET=${outputCharSet} -P ${PROJECT_SOURCE_DIR}/cmake/ConvertPo.cmake COMMENT "Updating ${outputName}.po" DEPENDS ${inputFile}) -- cgit From 3074ae69710f401d928356e7c3182edb0b0b2669 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 8 Feb 2023 16:21:05 +0100 Subject: ci(oldtest): make a copy of scripts of ci/common in testdir (#22170) Having separate copies makes it easier to not accidentally break something when modifying the scripts. --- src/nvim/testdir/runnvim.sh | 5 ++- src/nvim/testdir/suite.sh | 36 ++++++++++++++++++++ src/nvim/testdir/test.sh | 82 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 src/nvim/testdir/suite.sh create mode 100644 src/nvim/testdir/test.sh (limited to 'src') diff --git a/src/nvim/testdir/runnvim.sh b/src/nvim/testdir/runnvim.sh index 3a0a94b6bf..f316c7376e 100755 --- a/src/nvim/testdir/runnvim.sh +++ b/src/nvim/testdir/runnvim.sh @@ -22,13 +22,12 @@ main() {( i=$(( i+1 )) done - export CI_DIR="$root/ci" BUILD_DIR="$(dirname "$nvim_prg")/.." export BUILD_DIR export FAILED=0 - . "$CI_DIR/common/suite.sh" - . "$CI_DIR/common/test.sh" + . $(dirname $0)/suite.sh + . $(dirname $0)/test.sh # Redirect XDG_CONFIG_HOME so users local config doesn't interfere export XDG_CONFIG_HOME="$root" diff --git a/src/nvim/testdir/suite.sh b/src/nvim/testdir/suite.sh new file mode 100644 index 0000000000..3059773ca1 --- /dev/null +++ b/src/nvim/testdir/suite.sh @@ -0,0 +1,36 @@ +# Test success marker. If END_MARKER file exists, we know that all tests +# finished. If FAIL_SUMMARY_FILE exists we know that some tests failed, this +# file will contain information about failed tests. Build is considered +# successful if tests ended without any of them failing. +END_MARKER="$BUILD_DIR/.tests_finished" +FAIL_SUMMARY_FILE="$BUILD_DIR/.test_errors" + +fail() { + local test_name="$1" + local message="$2" + + : "${message:=Test $test_name failed}" + + local full_msg="$test_name :: $message" + echo "${full_msg}" >> "${FAIL_SUMMARY_FILE}" + echo "Failed: $full_msg" + export FAILED=1 +} + +ended_successfully() { + if test -f "${FAIL_SUMMARY_FILE}" ; then + echo 'Test failed, complete summary:' + cat "${FAIL_SUMMARY_FILE}" + + if [[ "$GITHUB_ACTIONS" == "true" ]]; then + rm -f "$FAIL_SUMMARY_FILE" + fi + + return 1 + fi + if ! test -f "${END_MARKER}" ; then + echo 'ended_successfully called before end marker was touched' + return 1 + fi + return 0 +} diff --git a/src/nvim/testdir/test.sh b/src/nvim/testdir/test.sh new file mode 100644 index 0000000000..eab1736c32 --- /dev/null +++ b/src/nvim/testdir/test.sh @@ -0,0 +1,82 @@ +. $(dirname $0)/suite.sh + +print_core() { + local app="$1" + local core="$2" + if test "$app" = quiet ; then + echo "Found core $core" + return 0 + fi + echo "======= Core file $core =======" + if test "${CI_OS_NAME}" = osx ; then + lldb -Q -o "bt all" -f "${app}" -c "${core}" + else + gdb -n -batch -ex 'thread apply all bt full' "${app}" -c "${core}" + fi +} + +check_core_dumps() { + local del= + if test "$1" = "--delete" ; then + del=1 + shift + fi + local app="${1:-${BUILD_DIR}/bin/nvim}" + local cores + if test "${CI_OS_NAME}" = osx ; then + cores="$(find /cores/ -type f -print)" + local _sudo='sudo' + else + cores="$(find ./ -type f \( -name 'core.*' -o -name core -o -name nvim.core \) -print)" + local _sudo= + fi + + if test -z "${cores}" ; then + return + fi + local core + for core in $cores; do + if test "$del" = "1" ; then + print_core "$app" "$core" >&2 + "$_sudo" rm "$core" + else + print_core "$app" "$core" + fi + done + if test "$app" != quiet ; then + fail 'cores' 'Core dumps found' + fi +} + +check_logs() { + # Iterate through each log to remove an useless warning. + # shellcheck disable=SC2044 + for log in $(find "${1}" -type f -name "${2}"); do + sed -i "${log}" \ + -e '/Warning: noted but unhandled ioctl/d' \ + -e '/could cause spurious value errors to appear/d' \ + -e '/See README_MISSING_SYSCALL_OR_IOCTL for guidance/d' + done + + # Now do it again, but only consider files with size > 0. + local err="" + # shellcheck disable=SC2044 + for log in $(find "${1}" -type f -name "${2}" -size +0); do + cat "${log}" + err=1 + rm "${log}" + done + if test -n "${err}" ; then + fail 'logs' 'Runtime errors detected.' + fi +} + +valgrind_check() { + check_logs "${1}" "valgrind-*" +} + +check_sanitizer() { + if test -n "${CLANG_SANITIZER}"; then + check_logs "${1}" "*san.*" | cat + fi +} -- cgit From f4c836ad704045434f56498a0ceea4c7e705ab07 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 8 Feb 2023 17:37:15 +0100 Subject: build(windows): specify Windows 8 as the minimum version (#22173) This will allow MSVC to use newer features not available in Vista and Windows 7. --- src/nvim/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 5e5634ba77..90b17492bf 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -135,8 +135,7 @@ if(MINGW) target_compile_definitions(main_lib INTERFACE __USE_MINGW_ANSI_STDIO) endif() if(WIN32) - # Windows Vista is the minimum supported version - target_compile_definitions(main_lib INTERFACE _WIN32_WINNT=0x0600 MSWIN) + target_compile_definitions(main_lib INTERFACE _WIN32_WINNT=0x0602 MSWIN) endif() # OpenBSD's GCC (4.2.1) doesn't have -Wvla -- cgit From 625e990976540a0e2d2bccb98deb57d0919d1e89 Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 8 Feb 2023 16:16:16 +0100 Subject: refactor(ui): cleanup 'redrawdebug', introduce "flush" mode --- src/nvim/option_defs.h | 2 ++ src/nvim/optionstr.c | 3 ++- src/nvim/ui.c | 6 +++++- 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index d190fc5999..0e0cc4c983 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -630,6 +630,8 @@ EXTERN unsigned rdb_flags; #define RDB_NOTHROTTLE 0x002 #define RDB_INVALID 0x004 #define RDB_NODELTA 0x008 +#define RDB_LINE 0x010 +#define RDB_FLUSH 0x020 EXTERN long p_rdt; // 'redrawtime' EXTERN long p_re; // 'regexpengine' diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 901477d869..7efbeadb2f 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -125,7 +125,8 @@ static char *(p_spo_values[]) = { "camel", "noplainbuffer", NULL }; static char *(p_icm_values[]) = { "nosplit", "split", NULL }; static char *(p_jop_values[]) = { "stack", "view", NULL }; static char *(p_tpf_values[]) = { "BS", "HT", "FF", "ESC", "DEL", "C0", "C1", NULL }; -static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelta", NULL }; +static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelta", "line", + "flush", NULL }; static char *(p_sloc_values[]) = { "last", "statusline", "tabline", NULL }; /// All possible flags for 'shm'. diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 9f1cb87eb0..b22dc4a661 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -419,7 +419,7 @@ void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol, (const sattr_T *)grid->attrs + off); // 'writedelay': flush & delay each time. - if (p_wd && !(rdb_flags & RDB_COMPOSITOR)) { + if (p_wd && (rdb_flags & RDB_LINE)) { // If 'writedelay' is active, set the cursor to indicate what was drawn. ui_call_grid_cursor_goto(grid->handle, row, MIN(clearcol, (int)grid->cols - 1)); @@ -510,6 +510,10 @@ void ui_flush(void) pending_has_mouse = has_mouse; } ui_call_flush(); + + if (p_wd && (rdb_flags & RDB_FLUSH)) { + os_microdelay((uint64_t)labs(p_wd) * 1000U, true); + } } /// Check if 'mouse' is active for the current mode -- cgit From 28e26e05bc4cd2bd8e1abc2dd4d720fd9199456d Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 8 Feb 2023 16:24:33 +0100 Subject: perf(ui): mitigate redraw latency regression from TUI refactor While the new RPC encoder/decoder implementation in general should have less overhead than the deleted UIBridge serializer previously used for the TUI, it regresses on redraw latency in one important aspect. The old bridge implementation allowed the TUI to process a previous screen line internally in parallel with the main thread rendering the next one in win_line etc. As printing the escape sequences in highlighted cells has a considerable hit in profiles, this has a substantial effect on redraw latency. The RPC implementation, however, waits with sending any data until either a flush, or the buffer is full. This change lowers the granularity of communication again, using an adjustable threshold counted in number of cell events (discounting long repeats and clearing as maximum a single extra event). The current value is guesstimated to something simple on a reasonable scale, which should be bigger than a single line, but multiple events for a big multi-window screen. --- src/nvim/api/ui.c | 10 ++++++++++ src/nvim/ui.h | 2 ++ 2 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index e67607a7e4..3ad625234c 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -202,6 +202,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona data->flushed_events = false; data->ncalls_pos = NULL; data->ncalls = 0; + data->ncells_pending = 0; data->buf_wptr = data->buf; data->temp_buf = NULL; data->wildmenu_active = false; @@ -854,18 +855,25 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int mpack_uint(buf, repeat); } } + data->ncells_pending += MIN(repeat, 2); last_hl = attrs[i]; repeat = 0; } } if (endcol < clearcol) { nelem++; + data->ncells_pending += 1; mpack_array(buf, 3); mpack_str(buf, " "); mpack_uint(buf, (uint32_t)clearattr); mpack_uint(buf, (uint32_t)(clearcol - endcol)); } mpack_w2(&lenpos, nelem); + + if (data->ncells_pending > 500) { + // pass of cells to UI to let it start processing them + remote_ui_flush_buf(ui); + } } else { for (int i = 0; i < endcol - startcol; i++) { remote_ui_cursor_goto(ui, row, startcol + i); @@ -917,6 +925,8 @@ void remote_ui_flush_buf(UI *ui) // we have sent events to the client, but possibly not yet the final "flush" // event. data->flushed_events = true; + + data->ncells_pending = 0; } /// An intentional flush (vsync) when Nvim is finished redrawing the screen diff --git a/src/nvim/ui.h b/src/nvim/ui.h index 9140a9f1f3..e83f93eb07 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -79,6 +79,8 @@ typedef struct { uint32_t ncalls; ///< number of calls made to the current event (plus one for the name!) bool flushed_events; ///< events where sent to client without "flush" event + size_t ncells_pending; ///< total number of cells since last buffer flush + int hl_id; // Current highlight for legacy put event. Integer cursor_row, cursor_col; // Intended visible cursor position. -- cgit From d6d3a9201302c5c728d2bdd1c50678e18645e7eb Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 8 Feb 2023 18:16:48 +0100 Subject: build: replace check-single-includes with clang-tidy (#22061) Clang-tidy already does what check-single-includes does automatically on top of its regular linting. It is also generator independent, so it doesn't take an eternity to run on slower generators such as Visual Studio. --- src/nvim/CMakeLists.txt | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 90b17492bf..5fda718dbb 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -878,44 +878,35 @@ function(get_test_target prefix sfile relative_path_var target_var) endif() endfunction() +find_program(CLANG_TIDY_PRG clang-tidy) +set(EXCLUDE_CLANG_TIDY typval_encode.c.h ui_events.in.h) if(WIN32) - set(NO_SINGLE_CHECK_HEADERS + list(APPEND EXCLUDE_CLANG_TIDY os/pty_process_unix.h os/unix_defs.h) else() - set(NO_SINGLE_CHECK_HEADERS + list(APPEND EXCLUDE_CLANG_TIDY os/win_defs.h os/pty_process_win.h os/pty_conpty_win.h os/os_win_console.h) endif() -foreach(hfile ${NVIM_HEADERS}) - get_test_target(test-includes "${hfile}" relative_path texe) - - if(NOT ${hfile} MATCHES "[.](c|in)[.]h$") - set(tsource "${GENERATED_DIR}/${relative_path}.test-include.c") - write_file("${tsource}" "#include \"${hfile}\"\nint main(int argc, char **argv) { return 0; }") - add_executable( - ${texe} - EXCLUDE_FROM_ALL - ${tsource} ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_HEADERS}) - target_link_libraries(${texe} PRIVATE main_lib) - set_target_properties(${texe} PROPERTIES FOLDER test) - - list(FIND NO_SINGLE_CHECK_HEADERS "${relative_path}" hfile_exclude_idx) - if(${hfile_exclude_idx} EQUAL -1) - list(APPEND HEADER_CHECK_TARGETS ${texe}) - endif() - endif() -endforeach() -add_custom_target(check-single-includes DEPENDS ${HEADER_CHECK_TARGETS}) +add_glob_target( + TARGET clang-tidy + COMMAND ${CLANG_TIDY_PRG} + FILES ${NVIM_SOURCES} ${NVIM_HEADERS} + FLAGS --quiet + EXCLUDE ${EXCLUDE_CLANG_TIDY}) +add_custom_target(copy_compile_commands + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/compile_commands.json ${PROJECT_SOURCE_DIR}/compile_commands.json) +add_dependencies(copy_compile_commands nvim) +add_dependencies(clang-tidy copy_compile_commands) if(CI_BUILD) set(LINT_OUTPUT_FORMAT gh_action) else() set(LINT_OUTPUT_FORMAT vs7) endif() - add_glob_target( TARGET lintc-clint COMMAND ${PROJECT_SOURCE_DIR}/src/clint.py -- cgit From eebed91d11dd225e56011ae1dbc152db66429d52 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 8 Feb 2023 18:20:45 +0100 Subject: build: remove unused function get_test_target (#22176) --- src/nvim/CMakeLists.txt | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 5fda718dbb..5973fe1716 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -859,25 +859,6 @@ elseif(CLANG_TSAN) target_link_libraries(nvim PRIVATE -fsanitize=thread) endif() -function(get_test_target prefix sfile relative_path_var target_var) - get_filename_component(full_d "${sfile}" DIRECTORY) - file(RELATIVE_PATH d "${PROJECT_SOURCE_DIR}/src/nvim" "${full_d}") - if(d MATCHES "^[.][.]") - file(RELATIVE_PATH d "${GENERATED_DIR}" "${full_d}") - endif() - get_filename_component(r "${sfile}" NAME) - if(NOT d MATCHES "^[.]?$") - set(r "${d}/${r}") - endif() - string(REGEX REPLACE "[/.]" "-" suffix "${r}") - set(${relative_path_var} ${r} PARENT_SCOPE) - if(prefix STREQUAL "") - set(${target_var} "${suffix}" PARENT_SCOPE) - else() - set(${target_var} "${prefix}-${suffix}" PARENT_SCOPE) - endif() -endfunction() - find_program(CLANG_TIDY_PRG clang-tidy) set(EXCLUDE_CLANG_TIDY typval_encode.c.h ui_events.in.h) if(WIN32) -- cgit From 2294210660056df2f8abb277776cfd68f3fb1156 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 8 Feb 2023 18:32:17 +0100 Subject: ci: remove fail summary (#22174) The tests already have a summary at the end, there's no need for an additional fail summary wrapper. --- src/nvim/testdir/runnvim.sh | 1 - src/nvim/testdir/suite.sh | 26 -------------------------- src/nvim/testdir/test.sh | 11 ++++++++++- 3 files changed, 10 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/runnvim.sh b/src/nvim/testdir/runnvim.sh index f316c7376e..4d8ea0527d 100755 --- a/src/nvim/testdir/runnvim.sh +++ b/src/nvim/testdir/runnvim.sh @@ -26,7 +26,6 @@ main() {( export BUILD_DIR export FAILED=0 - . $(dirname $0)/suite.sh . $(dirname $0)/test.sh # Redirect XDG_CONFIG_HOME so users local config doesn't interfere diff --git a/src/nvim/testdir/suite.sh b/src/nvim/testdir/suite.sh index 3059773ca1..bf5a16fd89 100644 --- a/src/nvim/testdir/suite.sh +++ b/src/nvim/testdir/suite.sh @@ -1,10 +1,3 @@ -# Test success marker. If END_MARKER file exists, we know that all tests -# finished. If FAIL_SUMMARY_FILE exists we know that some tests failed, this -# file will contain information about failed tests. Build is considered -# successful if tests ended without any of them failing. -END_MARKER="$BUILD_DIR/.tests_finished" -FAIL_SUMMARY_FILE="$BUILD_DIR/.test_errors" - fail() { local test_name="$1" local message="$2" @@ -12,25 +5,6 @@ fail() { : "${message:=Test $test_name failed}" local full_msg="$test_name :: $message" - echo "${full_msg}" >> "${FAIL_SUMMARY_FILE}" echo "Failed: $full_msg" export FAILED=1 } - -ended_successfully() { - if test -f "${FAIL_SUMMARY_FILE}" ; then - echo 'Test failed, complete summary:' - cat "${FAIL_SUMMARY_FILE}" - - if [[ "$GITHUB_ACTIONS" == "true" ]]; then - rm -f "$FAIL_SUMMARY_FILE" - fi - - return 1 - fi - if ! test -f "${END_MARKER}" ; then - echo 'ended_successfully called before end marker was touched' - return 1 - fi - return 0 -} diff --git a/src/nvim/testdir/test.sh b/src/nvim/testdir/test.sh index eab1736c32..affdc308d1 100644 --- a/src/nvim/testdir/test.sh +++ b/src/nvim/testdir/test.sh @@ -1,4 +1,13 @@ -. $(dirname $0)/suite.sh +fail() { + local test_name="$1" + local message="$2" + + : "${message:=Test $test_name failed}" + + local full_msg="$test_name :: $message" + echo "Failed: $full_msg" + export FAILED=1 +} print_core() { local app="$1" -- cgit From 5638813066453bf094650fca795f38f201d311b0 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 8 Feb 2023 19:31:10 +0100 Subject: build: reuse source files with interface library (#22177) This will minimize duplication by only needing to specify required files for nvim and libnvim once. --- src/nvim/CMakeLists.txt | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 5973fe1716..52bafffefe 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -664,9 +664,14 @@ else() target_compile_definitions(nvim PRIVATE $<$:UNIT_TESTING>) endif() -target_sources(nvim PRIVATE ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} - ${NVIM_GENERATED_SOURCES} ${NVIM_SOURCES} ${NVIM_HEADERS} - ${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS}) +target_sources(main_lib INTERFACE + ${NVIM_GENERATED_FOR_SOURCES} + ${NVIM_GENERATED_FOR_HEADERS} + ${NVIM_GENERATED_SOURCES} + ${NVIM_SOURCES} + ${NVIM_HEADERS} + ${EXTERNAL_SOURCES} + ${EXTERNAL_HEADERS}) set_target_properties(nvim PROPERTIES @@ -809,14 +814,7 @@ install(DIRECTORY ${BINARY_LIB_DIR} DESTINATION ${CMAKE_INSTALL_LIBDIR}/nvim/ USE_SOURCE_PERMISSIONS) -add_library( - libnvim - STATIC - EXCLUDE_FROM_ALL - ${NVIM_SOURCES} ${NVIM_GENERATED_SOURCES} - ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} - ${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS} -) +add_library(libnvim STATIC EXCLUDE_FROM_ALL) if(MSVC) set(LIBNVIM_NAME libnvim) else() -- cgit From ecc40660d1577835245d99f95e14762a30d36054 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 9 Feb 2023 10:53:47 +0800 Subject: fix(rpc): ignore redraw events when not in UI client (#21892) Otherwise it will crash. --- src/nvim/msgpack_rpc/channel.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index d60e18590f..193c88646a 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -247,10 +247,12 @@ static void parse_msgpack(Channel *channel) Unpacker *p = channel->rpc.unpacker; while (unpacker_advance(p)) { if (p->type == kMessageTypeRedrawEvent) { - if (p->grid_line_event) { - ui_client_event_raw_line(p->grid_line_event); - } else if (p->ui_handler.fn != NULL && p->result.type == kObjectTypeArray) { - p->ui_handler.fn(p->result.data.array); + if (ui_client_channel_id) { + if (p->grid_line_event) { + ui_client_event_raw_line(p->grid_line_event); + } else if (p->ui_handler.fn != NULL && p->result.type == kObjectTypeArray) { + p->ui_handler.fn(p->result.data.array); + } } arena_mem_free(arena_finish(&p->arena)); } else if (p->type == kMessageTypeResponse) { -- cgit From b2b82ff14281a4784790af288cde13984d5d5727 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 9 Feb 2023 14:36:17 +0800 Subject: fix(rpc): ignore redraw events when exiting (#22184) When a TUI client has already stopped, handling UI events will cause a heap-use-after-free, so ignore them. --- src/nvim/msgpack_rpc/channel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 193c88646a..34c8f89e3f 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -247,7 +247,8 @@ static void parse_msgpack(Channel *channel) Unpacker *p = channel->rpc.unpacker; while (unpacker_advance(p)) { if (p->type == kMessageTypeRedrawEvent) { - if (ui_client_channel_id) { + // When exiting, ui_client_stop() has already been called, so don't handle UI events. + if (ui_client_channel_id && !exiting) { if (p->grid_line_event) { ui_client_event_raw_line(p->grid_line_event); } else if (p->ui_handler.fn != NULL && p->result.type == kObjectTypeArray) { -- cgit From 257765d9e0f20dc060f496ed400b16203e44dc9c Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 9 Feb 2023 20:55:35 +0100 Subject: refactor(ui): don't reimplement redrawing in focus gained handling These are just ordinary boring events now. Modes already redraw events themselves. --- src/nvim/autocmd.c | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 897c9533e5..0485fbcdb0 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -2740,14 +2740,12 @@ void do_autocmd_focusgained(bool gained) { static bool recursive = false; static Timestamp last_time = (time_t)0; - bool need_redraw = false; if (recursive) { return; // disallow recursion } recursive = true; - need_redraw |= apply_autocmds((gained ? EVENT_FOCUSGAINED : EVENT_FOCUSLOST), - NULL, NULL, false, curbuf); + apply_autocmds((gained ? EVENT_FOCUSGAINED : EVENT_FOCUSLOST), NULL, NULL, false, curbuf); // When activated: Check if any file was modified outside of Vim. // Only do this when not done within the last two seconds as: @@ -2755,32 +2753,10 @@ void do_autocmd_focusgained(bool gained) // has a granularity of 2 seconds. // 2. We could get multiple notifications in a row. if (gained && last_time + (Timestamp)2000 < os_now()) { - need_redraw = check_timestamps(true); + check_timestamps(true); last_time = os_now(); } - if (need_redraw) { - // Something was executed, make sure the cursor is put back where it - // belongs. - need_wait_return = false; - - if (State & MODE_CMDLINE) { - redrawcmdline(); - } else if ((State & MODE_NORMAL) || (State & MODE_INSERT)) { - if (must_redraw != 0) { - update_screen(); - } - - setcursor(); - } - - ui_flush(); - } - - if (need_maketitle) { - maketitle(); - } - recursive = false; } -- cgit From 30b29a36e80bfeed50bb6ea618401fe35100490f Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 9 Feb 2023 20:56:30 +0100 Subject: refactor(ui): remove some superfluous ui_flush() calls - mapping has no business saving and restoring the low-level UI cursor. The cursor will be put in a reasonable position after input is processed, chill out. - TUI handles output needed for suspend - vgetc() family of function does flushing --- src/nvim/eval.c | 1 - src/nvim/eval/userfunc.c | 3 +-- src/nvim/ex_cmds.c | 1 - src/nvim/ex_docmd.c | 6 +----- src/nvim/getchar.c | 45 +++++++++++++++++++++------------------------ src/nvim/option.c | 1 - src/nvim/popupmenu.c | 1 - src/nvim/ui.c | 5 ----- 8 files changed, 23 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 4392ea306f..4de4b7a080 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -7469,7 +7469,6 @@ void ex_execute(exarg_T *eap) if (eap->cmdidx == CMD_echomsg) { msg_ext_set_kind("echomsg"); msg_attr(ga.ga_data, echo_attr); - ui_flush(); } else if (eap->cmdidx == CMD_echoerr) { // We don't want to abort following commands, restore did_emsg. int save_did_emsg = did_emsg; diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 6c6dc3fa43..957733ecd5 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2150,8 +2150,7 @@ void ex_function(exarg_T *eap) } } msg_prt_line(FUNCLINE(fp, j), false); - ui_flush(); // show a line at a time - os_breakcheck(); + line_breakcheck(); // show multiple lines at a time! } if (!got_int) { msg_putchar('\n'); diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 437a05f61d..ae7abfc5e7 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -1507,7 +1507,6 @@ void print_line(linenr_T lnum, int use_number, int list) print_line_no_prefix(lnum, use_number, list); if (save_silent) { msg_putchar('\n'); - ui_flush(); silent_mode = save_silent; } info_message = false; diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index a24e8458a6..017787f238 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -4838,13 +4838,9 @@ static void ex_stop(exarg_T *eap) } apply_autocmds(EVENT_VIMSUSPEND, NULL, NULL, false, NULL); - // TODO(bfredl): the TUI should do this on suspend - ui_cursor_goto(Rows - 1, 0); - ui_call_grid_scroll(1, 0, Rows, 0, Columns, 1, 0); + ui_call_suspend(); ui_flush(); - ui_call_suspend(); // call machine specific function - ui_flush(); maketitle(); resettitle(); // force updating the title ui_refresh(); // may have resized window diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 8ed9381bca..f5728d29c1 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2218,9 +2218,6 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) if (mp->m_expr) { const int save_vgetc_busy = vgetc_busy; const bool save_may_garbage_collect = may_garbage_collect; - const int save_cursor_row = ui_current_row(); - const int save_cursor_col = ui_current_col(); - const handle_T save_cursor_grid = ui_cursor_grid(); const int prev_did_emsg = did_emsg; vgetc_busy = 0; @@ -2232,28 +2229,28 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) } map_str = eval_map_expr(mp, NUL); - // The mapping may do anything, but we expect it to take care of - // redrawing. Do put the cursor back where it was. - ui_grid_cursor_goto(save_cursor_grid, save_cursor_row, save_cursor_col); - ui_flush(); - - // If an error was displayed and the expression returns an empty - // string, generate a to allow for a redraw. - if (prev_did_emsg != did_emsg && (map_str == NULL || *map_str == NUL)) { - char buf[4]; - xfree(map_str); - buf[0] = (char)K_SPECIAL; - buf[1] = (char)KS_EXTRA; - buf[2] = KE_IGNORE; - buf[3] = NUL; - map_str = xstrdup(buf); - if (State & MODE_CMDLINE) { - // redraw the command below the error - msg_didout = true; - if (msg_row < cmdline_row) { - msg_row = cmdline_row; + if ((map_str == NULL || *map_str == NUL)) { + // If an error was displayed and the expression returns an empty + // string, generate a to allow for a redraw. + if (prev_did_emsg != did_emsg) { + char buf[4]; + xfree(map_str); + buf[0] = (char)K_SPECIAL; + buf[1] = (char)KS_EXTRA; + buf[2] = KE_IGNORE; + buf[3] = NUL; + map_str = xstrdup(buf); + if (State & MODE_CMDLINE) { + // redraw the command below the error + msg_didout = true; + if (msg_row < cmdline_row) { + msg_row = cmdline_row; + } + redrawcmd(); } - redrawcmd(); + } else if (State & (MODE_NORMAL | MODE_INSERT)) { + // otherwise, just put back the cursor + setcursor(); } } diff --git a/src/nvim/option.c b/src/nvim/option.c index 387b94533c..066ca8f003 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1549,7 +1549,6 @@ int do_set(char *arg, int opt_flags) silent_mode = false; info_message = true; // use os_msg(), not os_errmsg() msg_putchar('\n'); - ui_flush(); silent_mode = true; info_message = false; // use os_msg(), not os_errmsg() } diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index 245ce87865..45c1afd70e 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -1092,7 +1092,6 @@ void pum_show_popupmenu(vimmenu_T *menu) pum_is_drawn = true; pum_redraw(); setcursor_mayforce(true); - ui_flush(); int c = vgetc(); diff --git a/src/nvim/ui.c b/src/nvim/ui.c index b22dc4a661..8172a46773 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -472,11 +472,6 @@ int ui_current_col(void) return cursor_col; } -handle_T ui_cursor_grid(void) -{ - return cursor_grid_handle; -} - void ui_flush(void) { assert(!ui_client_channel_id); -- cgit From f8f82901cdd0ccd5308e05c73af6deb7d083720f Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 1 Feb 2023 12:54:22 +0100 Subject: fix(tests): fixes for using vim.mpack and more ASAN --- src/mpack/lmpack.c | 16 ++++++++-------- src/mpack/object.c | 11 ++++++++--- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/mpack/lmpack.c b/src/mpack/lmpack.c index 53d7092a0c..957bac37cc 100644 --- a/src/mpack/lmpack.c +++ b/src/mpack/lmpack.c @@ -644,7 +644,13 @@ static void lmpack_unparse_enter(mpack_parser_t *parser, mpack_node_t *node) mpack_node_t *n; int has_meta = lua_getmetatable(L, -1); - if (packer->ext != LUA_NOREF && has_meta) { + int has_mtdict = false; + if (has_meta && packer->mtdict != LUA_NOREF) { + lmpack_geti(L, packer->reg, packer->mtdict); // [table, metatable, mtdict] + has_mtdict = lua_rawequal(L, -1, -2); + lua_pop(L, 1); // [table, metatable]; + } + if (packer->ext != LUA_NOREF && has_meta && !has_mtdict) { /* check if there's a handler for this metatable */ lmpack_geti(L, packer->reg, packer->ext); lua_pushvalue(L, -2); @@ -701,14 +707,7 @@ static void lmpack_unparse_enter(mpack_parser_t *parser, mpack_node_t *node) } } - int is_array = 1; if (has_meta) { - // stack: [table, metatable] - if (packer->mtdict != LUA_NOREF) { - lmpack_geti(L, packer->reg, packer->mtdict); // [table, metatable, mtdict] - is_array = !lua_rawequal(L, -1, -2); - lua_pop(L, 1); // [table, metatable]; - } lua_pop(L, 1); // [table] } @@ -726,6 +725,7 @@ static void lmpack_unparse_enter(mpack_parser_t *parser, mpack_node_t *node) lua_pop(L, 1); } + int is_array = !has_mtdict; len = lmpack_objlen(L, &is_array); if (is_array) { node->tok = mpack_pack_array(len); diff --git a/src/mpack/object.c b/src/mpack/object.c index e2d893bc88..60f49f73aa 100644 --- a/src/mpack/object.c +++ b/src/mpack/object.c @@ -128,8 +128,11 @@ MPACK_API int mpack_unparse(mpack_parser_t *parser, char **buf, size_t *buflen, return status; } -MPACK_API void mpack_parser_copy(mpack_parser_t *dst, mpack_parser_t *src) +MPACK_API void mpack_parser_copy(mpack_parser_t *d, mpack_parser_t *s) { + // workaround UBSAN being NOT happy with a flexible array member with arr[N>1] initial size + mpack_one_parser_t *dst = (mpack_one_parser_t *)d; + mpack_one_parser_t *src = (mpack_one_parser_t *)s; mpack_uint32_t i; mpack_uint32_t dst_capacity = dst->capacity; assert(src->capacity <= dst_capacity); @@ -148,8 +151,9 @@ static int mpack_parser_full(mpack_parser_t *parser) return parser->size == parser->capacity; } -static mpack_node_t *mpack_parser_push(mpack_parser_t *parser) +static mpack_node_t *mpack_parser_push(mpack_parser_t *p) { + mpack_one_parser_t *parser = (mpack_one_parser_t *)p; mpack_node_t *top; assert(parser->size < parser->capacity); top = parser->items + parser->size + 1; @@ -162,8 +166,9 @@ static mpack_node_t *mpack_parser_push(mpack_parser_t *parser) return top; } -static mpack_node_t *mpack_parser_pop(mpack_parser_t *parser) +static mpack_node_t *mpack_parser_pop(mpack_parser_t *p) { + mpack_one_parser_t *parser = (mpack_one_parser_t *)p; mpack_node_t *top, *parent; assert(parser->size); top = parser->items + parser->size; -- cgit From 4c64cbe99f2616a1d1126257da8d40773f4adba1 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Fri, 10 Feb 2023 20:20:18 +0100 Subject: build: mark uninteresting variables as advanced (#22208) Only the most important variables should be shown by default. --- src/nvim/CMakeLists.txt | 6 +++--- src/nvim/po/CMakeLists.txt | 11 ++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 52bafffefe..5953dd3ab9 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -252,11 +252,11 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") target_compile_definitions(main_lib INTERFACE _GNU_SOURCE) endif() -option(USE_GCOV "Enable gcov support" OFF) -if(USE_GCOV) +option(ENABLE_GCOV "Enable gcov support" OFF) +if(ENABLE_GCOV) if(CLANG_TSAN) # GCOV and TSAN results in false data race reports - message(FATAL_ERROR "USE_GCOV cannot be used with CLANG_TSAN") + message(FATAL_ERROR "ENABLE_GCOV cannot be used with CLANG_TSAN") endif() message(STATUS "Enabling gcov support") target_compile_options(main_lib INTERFACE --coverage) diff --git a/src/nvim/po/CMakeLists.txt b/src/nvim/po/CMakeLists.txt index a5a3c135d3..74f043fe03 100644 --- a/src/nvim/po/CMakeLists.txt +++ b/src/nvim/po/CMakeLists.txt @@ -1,9 +1,14 @@ find_package(Gettext REQUIRED) find_program(XGETTEXT_PRG xgettext) find_program(ICONV_PRG iconv) - -option(LANGUAGES "Localizations to build") -if(NOT LANGUAGES) +mark_as_advanced( + GETTEXT_MSGFMT_EXECUTABLE + GETTEXT_MSGMERGE_EXECUTABLE + ICONV_PRG + XGETTEXT_PRG) + +option(ENABLE_LANGUAGES "Localizations to build" ON) +if(ENABLE_LANGUAGES) set(LANGUAGES af ca -- cgit From 87d08095451d8d34030ddc62df093394f247740f Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 18 Jan 2023 15:42:30 +0100 Subject: build(ci): let ASAN print tracebacks for more errors (SIGABORT, SIGILL) --- src/nvim/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/README.md b/src/nvim/README.md index 6876227e48..712fda87ba 100644 --- a/src/nvim/README.md +++ b/src/nvim/README.md @@ -70,8 +70,8 @@ Create a directory to store logs: Configure the sanitizer(s) via these environment variables: - # Change to detect_leaks=1 to detect memory leaks (slower). - export ASAN_OPTIONS="detect_leaks=0:log_path=$HOME/logs/asan" + # Change to detect_leaks=1 to detect memory leaks (slower, noisier). + export ASAN_OPTIONS="detect_leaks=0:log_path=$HOME/logs/asan,handle_abort=1,handle_sigill=1" # Show backtraces in the logs. export UBSAN_OPTIONS=print_stacktrace=1 export MSAN_OPTIONS="log_path=${HOME}/logs/msan" -- cgit From c9b0fe1f41ebaa6815a69ac614a5b2d1bab6f720 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Feb 2023 08:20:31 +0800 Subject: vim-patch:9.0.1297: wrong value for $LC_CTYPE makes the environ test fail (#22210) Problem: Wrong value for $LC_CTYPE makes the environ test fail. Solution: Unset $LC_CTYPE when running tests. (closes vim/vim#11963) https://github.com/vim/vim/commit/962d91643520ec3748fcf5af3263d89ccfcdda92 Co-authored-by: WuerfelDev --- src/nvim/testdir/test_environ.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/testdir/test_environ.vim b/src/nvim/testdir/test_environ.vim index d8344817f5..b5dbdce104 100644 --- a/src/nvim/testdir/test_environ.vim +++ b/src/nvim/testdir/test_environ.vim @@ -73,7 +73,7 @@ func Test_mac_locale() " If $LANG is not set then the system locale will be used. " Run Vim after unsetting all the locale environmental vars, and capture the " output of :lang. - let lang_results = system("unset LANG; unset LC_MESSAGES; " .. + let lang_results = system("unset LANG; unset LC_MESSAGES; unset LC_CTYPE; " .. \ shellescape(v:progpath) .. \ " --clean -esX -c 'redir @a' -c 'lang' -c 'put a' -c 'print' -c 'qa!' ") -- cgit From c8c930ea785aa393ebc819139913a9e05f0ccd45 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 11 Feb 2023 10:24:46 +0100 Subject: refactor: reduce scope of locals as per the style guide (#22206) --- src/nvim/arglist.c | 9 ++--- src/nvim/cmdhist.c | 20 ++++------ src/nvim/edit.c | 70 +++++++++++++-------------------- src/nvim/ex_cmds.c | 22 ++++------- src/nvim/ex_cmds2.c | 10 ++--- src/nvim/ex_eval.c | 68 ++++++++++++-------------------- src/nvim/ex_getln.c | 24 ++++-------- src/nvim/ex_session.c | 14 +++---- src/nvim/file_search.c | 6 +-- src/nvim/getchar.c | 25 ++++++------ src/nvim/help.c | 13 +++---- src/nvim/indent.c | 29 +++++--------- src/nvim/mapping.c | 10 ++--- src/nvim/mbyte.c | 44 +++++++-------------- src/nvim/mouse.c | 43 +++++++------------- src/nvim/ops.c | 104 +++++++++++++++++++++---------------------------- src/nvim/popupmenu.c | 22 +++++------ src/nvim/profile.c | 13 ++----- src/nvim/spell.c | 7 ++-- src/nvim/spellfile.c | 81 +++++++++++++------------------------- src/nvim/window.c | 3 +- 21 files changed, 240 insertions(+), 397 deletions(-) (limited to 'src') diff --git a/src/nvim/arglist.c b/src/nvim/arglist.c index c6a4be7e13..3882b98c2c 100644 --- a/src/nvim/arglist.c +++ b/src/nvim/arglist.c @@ -619,8 +619,6 @@ void ex_argument(exarg_T *eap) /// Edit file "argn" of the argument lists. void do_argfile(exarg_T *eap, int argn) { - int other; - char *p; int old_arg_idx = curwin->w_arg_idx; if (argn < 0 || argn >= ARGCOUNT) { @@ -646,9 +644,9 @@ void do_argfile(exarg_T *eap, int argn) } else { // if 'hidden' set, only check for changed file when re-editing // the same buffer - other = true; + int other = true; if (buf_hide(curbuf)) { - p = fix_fname(alist_name(&ARGLIST[argn])); + char *p = fix_fname(alist_name(&ARGLIST[argn])); other = otherfile(p); xfree(p); } @@ -683,8 +681,6 @@ void do_argfile(exarg_T *eap, int argn) /// ":next", and commands that behave like it. void ex_next(exarg_T *eap) { - int i; - // check for changed buffer now, if this fails the argument list is not // redefined. if (buf_hide(curbuf) @@ -692,6 +688,7 @@ void ex_next(exarg_T *eap) || !check_changed(curbuf, CCGD_AW | (eap->forceit ? CCGD_FORCEIT : 0) | CCGD_EXCMD)) { + int i; if (*eap->arg != NUL) { // redefine file list if (do_arglist(eap->arg, AL_SET, 0, true) == FAIL) { return; diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c index 2df82d9355..c2928eb9c4 100644 --- a/src/nvim/cmdhist.c +++ b/src/nvim/cmdhist.c @@ -368,7 +368,6 @@ static int get_history_idx(int histype) static int calc_hist_idx(int histype, int num) { int i; - int wrapped = false; if (hislen == 0 || histype < 0 || histype >= HIST_COUNT || (i = hisidx[histype]) < 0 || num == 0) { @@ -377,6 +376,7 @@ static int calc_hist_idx(int histype, int num) histentry_T *hist = history[histype]; if (num > 0) { + int wrapped = false; while (hist[i].hisnum > num) { if (--i < 0) { if (wrapped) { @@ -568,14 +568,12 @@ void f_histdel(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "histget()" function void f_histget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - HistoryType type; - int idx; - const char *const str = tv_get_string_chk(&argvars[0]); // NULL on type error if (str == NULL) { rettv->vval.v_string = NULL; } else { - type = get_histtype(str, strlen(str), false); + int idx; + HistoryType type = get_histtype(str, strlen(str), false); if (argvars[1].v_type == VAR_UNKNOWN) { idx = get_history_idx(type); } else { @@ -603,13 +601,11 @@ void f_histnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// :history command - print a history void ex_history(exarg_T *eap) { - histentry_T *hist; int histype1 = HIST_CMD; int histype2 = HIST_CMD; int hisidx1 = 1; int hisidx2 = -1; - int idx; - int i, j, k; + int i; char *end; char *arg = eap->arg; @@ -649,10 +645,10 @@ void ex_history(exarg_T *eap) assert(history_names[histype1] != NULL); STRCAT(STRCAT(IObuff, history_names[histype1]), " history"); msg_puts_title(IObuff); - idx = hisidx[histype1]; - hist = history[histype1]; - j = hisidx1; - k = hisidx2; + int idx = hisidx[histype1]; + histentry_T *hist = history[histype1]; + int j = hisidx1; + int k = hisidx2; if (j < 0) { j = (-j > hislen) ? 0 : hist[(hislen + j + idx + 1) % hislen].hisnum; } diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 96df6a3044..4fe1c08974 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -558,10 +558,9 @@ static int insert_execute(VimState *state, int key) if (ins_compl_accept_char(s->c)) { // Trigger InsertCharPre. char *str = do_insert_char_pre(s->c); - char *p; if (str != NULL) { - for (p = str; *p != NUL; MB_PTR_ADV(p)) { + for (char *p = str; *p != NUL; MB_PTR_ADV(p)) { ins_compl_addleader(utf_ptr2char(p)); } xfree(str); @@ -1122,12 +1121,11 @@ normalchar: if (!p_paste) { // Trigger InsertCharPre. char *str = do_insert_char_pre(s->c); - char *p; if (str != NULL) { if (*str != NUL && stop_arrow() != FAIL) { // Insert the new value of v:char literally. - for (p = str; *p != NUL; MB_PTR_ADV(p)) { + for (char *p = str; *p != NUL; MB_PTR_ADV(p)) { s->c = utf_ptr2char(p); if (s->c == CAR || s->c == K_KENTER || s->c == NL) { ins_eol(s->c); @@ -1410,9 +1408,8 @@ static int pc_col; void edit_putchar(int c, bool highlight) { - int attr; - if (curwin->w_grid_alloc.chars != NULL || default_grid.chars != NULL) { + int attr; update_topline(curwin); // just in case w_topline isn't valid validate_cursor(); if (highlight) { @@ -1583,7 +1580,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang int start_col; colnr_T vc; colnr_T orig_col = 0; // init for GCC - char *new_line, *orig_line = NULL; // init for GCC + char *orig_line = NULL; // init for GCC // MODE_VREPLACE state needs to know what the line was like before changing if (State & VREPLACE_FLAG) { @@ -1742,7 +1739,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang // then put it back again the way we wanted it. if (State & VREPLACE_FLAG) { // Save new line - new_line = xstrdup(get_cursor_line_ptr()); + char *new_line = xstrdup(get_cursor_line_ptr()); // We only put back the new line up to the cursor new_line[curwin->w_cursor.col] = NUL; @@ -1949,9 +1946,6 @@ int get_literal(bool no_simplify) /// @param ctrlv `c` was typed after CTRL-V static void insert_special(int c, int allow_modmask, int ctrlv) { - char *p; - int len; - // Special function key, translate into "". Up to the last '>' is // inserted with ins_str(), so as not to replace characters in replace // mode. @@ -1961,8 +1955,8 @@ static void insert_special(int c, int allow_modmask, int ctrlv) allow_modmask = true; } if (IS_SPECIAL(c) || (mod_mask && allow_modmask)) { - p = (char *)get_special_key_name(c, mod_mask); - len = (int)strlen(p); + char *p = (char *)get_special_key_name(c, mod_mask); + int len = (int)strlen(p); c = (uint8_t)p[len - 1]; if (len > 2) { if (stop_arrow() == FAIL) { @@ -2294,7 +2288,6 @@ int stop_arrow(void) /// @param nomove , don't move cursor static void stop_insert(pos_T *end_insert_pos, int esc, int nomove) { - int cc; char *ptr; stop_redo_ins(); @@ -2314,6 +2307,7 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove) } if (!arrow_used && end_insert_pos != NULL) { + int cc; // Auto-format now. It may seem strange to do this when stopping an // insertion (or moving the cursor), but it's required when appending // a line and having it end in a space. But only do it when something @@ -2883,7 +2877,6 @@ static void mb_replace_pop_ins(int cc) int n; char_u buf[MB_MAXBYTES + 1]; int i; - int c; if ((n = MB_BYTE2LEN(cc)) > 1) { buf[0] = (char_u)cc; @@ -2897,7 +2890,7 @@ static void mb_replace_pop_ins(int cc) // Handle composing chars. for (;;) { - c = replace_pop(); + int c = replace_pop(); if (c == -1) { // stack empty break; } @@ -2943,17 +2936,13 @@ static void replace_flush(void) static void replace_do_bs(int limit_col) { int cc; - int orig_len = 0; - int ins_len; - int orig_vcols = 0; colnr_T start_vcol; - char *p; - int i; - int vcol; const int l_State = State; cc = replace_pop(); if (cc > 0) { + int orig_len = 0; + int orig_vcols = 0; if (l_State & VREPLACE_FLAG) { // Get the number of screen cells used by the character we are // going to delete. @@ -2969,10 +2958,10 @@ static void replace_do_bs(int limit_col) if (l_State & VREPLACE_FLAG) { // Get the number of screen cells used by the inserted characters - p = get_cursor_pos_ptr(); - ins_len = (int)strlen(p) - orig_len; - vcol = start_vcol; - for (i = 0; i < ins_len; i++) { + char *p = get_cursor_pos_ptr(); + int ins_len = (int)strlen(p) - orig_len; + int vcol = start_vcol; + for (int i = 0; i < ins_len; i++) { vcol += win_chartabsize(curwin, p + i, vcol); i += utfc_ptr2len(p) - 1; } @@ -3786,14 +3775,11 @@ static void ins_bs_one(colnr_T *vcolp) static bool ins_bs(int c, int mode, int *inserted_space_p) FUNC_ATTR_NONNULL_ARG(3) { - linenr_T lnum; int cc; int temp = 0; // init for GCC colnr_T save_col; - colnr_T mincol; bool did_backspace = false; int in_indent; - int oldState; int cpc[MAX_MCO]; // composing characters bool call_fix_indent = false; @@ -3844,7 +3830,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) // Delete newline! if (curwin->w_cursor.col == 0) { - lnum = Insstart.lnum; + linenr_T lnum = Insstart.lnum; if (curwin->w_cursor.lnum == lnum || revins_on) { if (u_save((linenr_T)(curwin->w_cursor.lnum - 2), (linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL) { @@ -3900,7 +3886,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) // Do the next ins_char() in MODE_NORMAL state, to // prevent ins_char() from replacing characters and // avoiding showmatch(). - oldState = State; + int oldState = State; State = MODE_NORMAL; // restore characters (blanks) deleted after cursor while (cc > 0) { @@ -3920,7 +3906,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) if (revins_on) { // put cursor on last inserted char dec_cursor(); } - mincol = 0; + colnr_T mincol = 0; // keep indent if (mode == BACKSPACE_LINE && (curbuf->b_p_ai || cindent_on()) @@ -3944,7 +3930,6 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) && (*(get_cursor_pos_ptr() - 1) == TAB || (*(get_cursor_pos_ptr() - 1) == ' ' && (!*inserted_space_p || arrow_used)))))) { - int ts; colnr_T vcol; colnr_T want_vcol; colnr_T start_vcol; @@ -3959,7 +3944,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol); inc_cursor(); if (p_sta && in_indent) { - ts = get_sw_value(curbuf); + int ts = get_sw_value(curbuf); want_vcol = (want_vcol / ts) * ts; } else { want_vcol = tabstop_start(want_vcol, @@ -3999,7 +3984,6 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) } } else { // Delete up to starting point, start of line or previous word. - int prev_cclass = 0; int cclass = mb_get_class(get_cursor_pos_ptr()); do { @@ -4008,7 +3992,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p) } cc = gchar_cursor(); // look multi-byte character class - prev_cclass = cclass; + int prev_cclass = cclass; cclass = mb_get_class(get_cursor_pos_ptr()); if (mode == BACKSPACE_WORD && !ascii_isspace(cc)) { // start of word? mode = BACKSPACE_WORD_NOT_SPACE; @@ -4425,7 +4409,6 @@ static void ins_pagedown(void) static bool ins_tab(void) FUNC_ATTR_WARN_UNUSED_RESULT { - int i; int temp; if (Insstart_blank_vcol == MAXCOL && curwin->w_cursor.lnum == Insstart.lnum) { @@ -4501,6 +4484,7 @@ static bool ins_tab(void) if (!curbuf->b_p_et && (tabstop_count(curbuf->b_p_vsts_array) > 0 || get_sts_value() > 0 || (p_sta && ind))) { + int i; char *ptr; char *saved_line = NULL; // init for GCC pos_T pos; @@ -4690,7 +4674,6 @@ bool ins_eol(int c) static int ins_digraph(void) { int c; - int cc; bool did_putchar = false; pc_status = PC_STATUS_UNSET; @@ -4736,7 +4719,7 @@ static int ins_digraph(void) } no_mapping++; allow_keys++; - cc = plain_vgetc(); + int cc = plain_vgetc(); no_mapping--; allow_keys--; if (did_putchar) { @@ -4835,13 +4818,14 @@ static int ins_ctrl_ey(int tc) // Used when inserting a "normal" character. static void ins_try_si(int c) { - pos_T *pos, old_pos; - char *ptr; - int i; - bool temp; + pos_T *pos; // do some very smart indenting when entering '{' or '}' if (((did_si || can_si_back) && c == '{') || (can_si && c == '}' && inindent(0))) { + pos_T old_pos; + char *ptr; + int i; + bool temp; // for '}' set indent equal to indent of line containing matching '{' if (c == '}' && (pos = findmatch(NULL, '{')) != NULL) { old_pos = curwin->w_cursor; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index ae7abfc5e7..da78861d87 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -724,7 +724,6 @@ sortend: /// @return FAIL for failure, OK otherwise int do_move(linenr_T line1, linenr_T line2, linenr_T dest) { - char *str; linenr_T l; linenr_T extra; // Num lines added before line1 linenr_T num_lines; // Num lines moved @@ -761,7 +760,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) return FAIL; } for (extra = 0, l = line1; l <= line2; l++) { - str = xstrdup(ml_get(l + extra)); + char *str = xstrdup(ml_get(l + extra)); ml_append(dest + l - line1, str, (colnr_T)0, false); xfree(str); if (dest < line1) { @@ -875,10 +874,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest) /// ":copy" void ex_copy(linenr_T line1, linenr_T line2, linenr_T n) { - linenr_T count; - char *p; - - count = line2 - line1 + 1; + linenr_T count = line2 - line1 + 1; if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) { curbuf->b_op_start.lnum = n + 1; curbuf->b_op_end.lnum = n + count; @@ -902,7 +898,7 @@ void ex_copy(linenr_T line1, linenr_T line2, linenr_T n) while (line1 <= line2) { // need to use xstrdup() because the line will be unlocked within // ml_append() - p = xstrdup(ml_get(line1)); + char *p = xstrdup(ml_get(line1)); ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, false); xfree(p); @@ -952,7 +948,6 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out char *t; char *p; char *trailarg; - size_t len; int scroll_save = msg_scroll; // @@ -975,7 +970,7 @@ void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out // Skip leading white space to avoid a strange error with some shells. trailarg = skipwhite(arg); do { - len = strlen(trailarg) + 1; + size_t len = strlen(trailarg) + 1; if (newcmd != NULL) { len += strlen(newcmd); } @@ -2736,7 +2731,6 @@ void ex_append(exarg_T *eap) linenr_T lnum = eap->line2; int indent = 0; char *p; - int vcol; int empty = (curbuf->b_ml.ml_flags & ML_EMPTY); // the ! flag toggles autoindent @@ -2803,7 +2797,7 @@ void ex_append(exarg_T *eap) } // Look for the "." after automatic indent. - vcol = 0; + int vcol = 0; for (p = theline; indent > vcol; p++) { if (*p == ' ') { vcol++; @@ -4339,7 +4333,6 @@ static void global_exe_one(char *const cmd, const linenr_T lnum) void ex_global(exarg_T *eap) { linenr_T lnum; // line number according to old situation - int ndone = 0; int type; // first char of cmd: 'v' or 'g' char *cmd; // command argument @@ -4411,6 +4404,7 @@ void ex_global(exarg_T *eap) global_exe_one(cmd, lnum); } } else { + int ndone = 0; // pass 1: set marks for each (not) matching line for (lnum = eap->line1; lnum <= eap->line2 && !got_int; lnum++) { // a match on this line? @@ -4687,8 +4681,6 @@ int ex_substitute_preview(exarg_T *eap, long cmdpreview_ns, handle_T cmdpreview_ /// @return a pointer to the char just past the pattern plus flags. char *skip_vimgrep_pat(char *p, char **s, int *flags) { - int c; - if (vim_isIDc((uint8_t)(*p))) { // ":vimgrep pattern fname" if (s != NULL) { @@ -4703,7 +4695,7 @@ char *skip_vimgrep_pat(char *p, char **s, int *flags) if (s != NULL) { *s = p + 1; } - c = (uint8_t)(*p); + int c = (uint8_t)(*p); p = skip_regexp(p + 1, c, true); if (*p != c) { return NULL; diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index d08823bc30..c777efb445 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -446,12 +446,9 @@ int buf_write_all(buf_T *buf, int forceit) /// ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo" void ex_listdo(exarg_T *eap) { - int i; win_T *wp; tabpage_T *tp; - int next_fnum = 0; char *save_ei = NULL; - char *p_shm_save; if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo) { // Don't do syntax HL autocommands. Skipping the syntax file is a @@ -469,7 +466,9 @@ void ex_listdo(exarg_T *eap) || !check_changed(curbuf, CCGD_AW | (eap->forceit ? CCGD_FORCEIT : 0) | CCGD_EXCMD)) { - i = 0; + int next_fnum = 0; + char *p_shm_save; + int i = 0; // start at the eap->line1 argument/window/buffer wp = firstwin; tp = first_tabpage; @@ -762,14 +761,13 @@ void ex_compiler(exarg_T *eap) /// ":checktime [buffer]" void ex_checktime(exarg_T *eap) { - buf_T *buf; int save_no_check_timestamps = no_check_timestamps; no_check_timestamps = 0; if (eap->addr_count == 0) { // default is all buffers check_timestamps(false); } else { - buf = buflist_findnr((int)eap->line2); + buf_T *buf = buflist_findnr((int)eap->line2); if (buf != NULL) { // cannot happen? (void)buf_check_timestamp(buf); } diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index f76e60f6c5..2c578564bc 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -278,9 +278,8 @@ bool cause_errthrow(const char *mesg, bool severe, bool *ignore) /// Free a "msg_list" and the messages it contains. static void free_msglist(msglist_T *l) { - msglist_T *messages, *next; - - messages = l; + msglist_T *next; + msglist_T *messages = l; while (messages != NULL) { next = messages->next; xfree(messages->msg); @@ -379,9 +378,10 @@ int do_intthrow(cstack_T *cstack) char *get_exception_string(void *value, except_type_T type, char *cmdname, int *should_free) { char *ret, *mesg; - char *p, *val; if (type == ET_ERROR) { + char *p; + char *val; *should_free = true; mesg = ((msglist_T *)value)->throw_msg; if (cmdname != NULL && *cmdname != NUL) { @@ -441,9 +441,6 @@ char *get_exception_string(void *value, except_type_T type, char *cmdname, int * /// exception. static int throw_exception(void *value, except_type_T type, char *cmdname) { - except_T *excp; - int should_free; - // Disallow faking Interrupt or error exceptions as user exceptions. They // would be treated differently from real interrupt or error exceptions // when no active try block is found, see do_cmdline(). @@ -456,7 +453,7 @@ static int throw_exception(void *value, except_type_T type, char *cmdname) } } - excp = xmalloc(sizeof(except_T)); + except_T *excp = xmalloc(sizeof(except_T)); if (type == ET_ERROR) { // Store the original message and prefix the exception value with @@ -464,6 +461,7 @@ static int throw_exception(void *value, except_type_T type, char *cmdname) excp->messages = (msglist_T *)value; } + int should_free; excp->value = get_exception_string(value, type, cmdname, &should_free); if (excp->value == NULL && should_free) { goto nomem; @@ -525,8 +523,6 @@ fail: /// caught and the catch clause has been ended normally. static void discard_exception(except_T *excp, bool was_finished) { - char *saved_IObuff; - if (current_exception == excp) { current_exception = NULL; } @@ -538,7 +534,7 @@ static void discard_exception(except_T *excp, bool was_finished) if (p_verbose >= 13 || debug_break_level > 0) { int save_msg_silent = msg_silent; - saved_IObuff = xstrdup(IObuff); + char *saved_IObuff = xstrdup(IObuff); if (debug_break_level > 0) { msg_silent = false; // display messages } else { @@ -677,7 +673,6 @@ static void report_pending(int action, int pending, void *value) { char *mesg; char *s; - int save_msg_silent; assert(value || !(pending & CSTP_THROW)); @@ -727,7 +722,7 @@ static void report_pending(int action, int pending, void *value) } } - save_msg_silent = msg_silent; + int save_msg_silent = msg_silent; if (debug_break_level > 0) { msg_silent = false; // display messages } @@ -806,8 +801,6 @@ void ex_eval(exarg_T *eap) /// Handle ":if". void ex_if(exarg_T *eap) { - int skip; - int result; cstack_T *const cstack = eap->cstack; if (cstack->cs_idx == CSTACK_LEN - 1) { @@ -816,10 +809,10 @@ void ex_if(exarg_T *eap) cstack->cs_idx++; cstack->cs_flags[cstack->cs_idx] = 0; - skip = CHECK_SKIP; + int skip = CHECK_SKIP; bool error; - result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); + int result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); if (!skip && !error) { if (result) { @@ -860,7 +853,6 @@ void ex_endif(exarg_T *eap) /// Handle ":else" and ":elseif". void ex_else(exarg_T *eap) { - bool result = false; cstack_T *const cstack = eap->cstack; bool skip = CHECK_SKIP; @@ -907,6 +899,7 @@ void ex_else(exarg_T *eap) } if (eap->cmdidx == CMD_elseif) { + bool result = false; bool error; // When skipping we ignore most errors, but a missing expression is // wrong, perhaps it should have been "else". @@ -941,13 +934,12 @@ void ex_else(exarg_T *eap) void ex_while(exarg_T *eap) { bool error; - int skip; - int result; cstack_T *const cstack = eap->cstack; if (cstack->cs_idx == CSTACK_LEN - 1) { eap->errmsg = _("E585: :while/:for nesting too deep"); } else { + int result; // The loop flag is set when we have jumped back from the matching // ":endwhile" or ":endfor". When not set, need to initialise this // cstack entry. @@ -959,7 +951,7 @@ void ex_while(exarg_T *eap) cstack->cs_flags[cstack->cs_idx] = eap->cmdidx == CMD_while ? CSF_WHILE : CSF_FOR; - skip = CHECK_SKIP; + int skip = CHECK_SKIP; if (eap->cmdidx == CMD_while) { // ":while bool-expr" result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); @@ -1013,7 +1005,6 @@ void ex_while(exarg_T *eap) /// Handle ":continue" void ex_continue(exarg_T *eap) { - int idx; cstack_T *const cstack = eap->cstack; if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0) { @@ -1023,7 +1014,7 @@ void ex_continue(exarg_T *eap) // conditional not in its finally clause (which is then to be executed // next). Therefore, deactivate all conditionals except the ":while" // itself (if reached). - idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, false); + int idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, false); assert(idx >= 0); if (cstack->cs_flags[idx] & (CSF_WHILE | CSF_FOR)) { rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel); @@ -1043,7 +1034,6 @@ void ex_continue(exarg_T *eap) /// Handle ":break" void ex_break(exarg_T *eap) { - int idx; cstack_T *const cstack = eap->cstack; if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0) { @@ -1053,7 +1043,7 @@ void ex_break(exarg_T *eap) // conditional not in its finally clause (which is then to be // executed next) is found. In the latter case, make the ":break" // pending for execution at the ":endtry". - idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, true); + int idx = cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, true); if (idx >= 0 && !(cstack->cs_flags[idx] & (CSF_WHILE | CSF_FOR))) { cstack->cs_pending[idx] = CSTP_BREAK; report_make_pending(CSTP_BREAK, NULL); @@ -1065,10 +1055,8 @@ void ex_break(exarg_T *eap) void ex_endwhile(exarg_T *eap) { cstack_T *const cstack = eap->cstack; - int idx; char *err; int csf; - int fl; if (eap->cmdidx == CMD_endwhile) { err = e_while; @@ -1081,7 +1069,7 @@ void ex_endwhile(exarg_T *eap) if (cstack->cs_looplevel <= 0 || cstack->cs_idx < 0) { eap->errmsg = _(err); } else { - fl = cstack->cs_flags[cstack->cs_idx]; + int fl = cstack->cs_flags[cstack->cs_idx]; if (!(fl & csf)) { // If we are in a ":while" or ":for" but used the wrong endloop // command, do not rewind to the next enclosing ":for"/":while". @@ -1098,6 +1086,7 @@ void ex_endwhile(exarg_T *eap) eap->errmsg = _(e_endtry); } // Try to find the matching ":while" and report what's missing. + int idx; for (idx = cstack->cs_idx; idx > 0; idx--) { fl = cstack->cs_flags[idx]; if ((fl & CSF_TRY) && !(fl & CSF_FINALLY)) { @@ -1163,7 +1152,6 @@ void ex_throw(exarg_T *eap) /// used for rethrowing an uncaught exception. void do_throw(cstack_T *cstack) { - int idx; int inactivate_try = false; // @@ -1187,7 +1175,7 @@ void do_throw(cstack_T *cstack) got_int = false; } #endif - idx = cleanup_conditionals(cstack, 0, inactivate_try); + int idx = cleanup_conditionals(cstack, 0, inactivate_try); if (idx >= 0) { // If this try conditional is active and we are before its first // ":catch", set THROWN so that the ":catch" commands will check @@ -1220,7 +1208,6 @@ void do_throw(cstack_T *cstack) /// Handle ":try" void ex_try(exarg_T *eap) { - int skip; cstack_T *const cstack = eap->cstack; if (cstack->cs_idx == CSTACK_LEN - 1) { @@ -1231,7 +1218,7 @@ void ex_try(exarg_T *eap) cstack->cs_flags[cstack->cs_idx] = CSF_TRY; cstack->cs_pending[cstack->cs_idx] = CSTP_NONE; - skip = CHECK_SKIP; + int skip = CHECK_SKIP; if (!skip) { // Set ACTIVE and TRUE. TRUE means that the corresponding ":catch" @@ -1271,12 +1258,9 @@ void ex_catch(exarg_T *eap) int idx = 0; bool give_up = false; bool skip = false; - bool caught = false; char *end; - char save_char = 0; char *save_cpo; regmatch_T regmatch; - int prev_got_int; cstack_T *const cstack = eap->cstack; char *pat; @@ -1319,6 +1303,7 @@ void ex_catch(exarg_T *eap) } if (!give_up) { + bool caught = false; // Don't do something when no exception has been thrown or when the // corresponding try block never got active (because of an inactive // surrounding conditional or after an error or interrupt or throw). @@ -1344,6 +1329,7 @@ void ex_catch(exarg_T *eap) // the original exception, replace it by an interrupt exception, // and don't catch it in this try block. if (!dbg_check_skipped(eap) || !do_intthrow(cstack)) { + char save_char = 0; // Terminate the pattern and avoid the 'l' flag in 'cpoptions' // while compiling it. if (end != NULL) { @@ -1365,12 +1351,11 @@ void ex_catch(exarg_T *eap) if (regmatch.regprog == NULL) { semsg(_(e_invarg2), pat); } else { - // // Save the value of got_int and reset it. We don't want // a previous interruption cancel matching, only hitting // CTRL-C while matching should abort it. - // - prev_got_int = got_int; + + int prev_got_int = got_int; got_int = false; caught = vim_regexec_nl(®match, current_exception->value, (colnr_T)0); got_int |= prev_got_int; @@ -1415,7 +1400,6 @@ void ex_catch(exarg_T *eap) void ex_finally(exarg_T *eap) { int idx; - int skip = false; int pending = CSTP_NONE; cstack_T *const cstack = eap->cstack; @@ -1451,7 +1435,7 @@ void ex_finally(exarg_T *eap) // ":finally". After every other error (did_emsg or the conditional // errors detected above) or after an interrupt (got_int) or an // exception (did_throw), the finally clause must be executed. - skip = !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE); + int skip = !(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE); if (!skip) { // When debugging or a breakpoint was encountered, display the @@ -1985,14 +1969,12 @@ void ex_endfunction(exarg_T *eap) /// @return true if the string "p" looks like a ":while" or ":for" command. int has_loop_cmd(char *p) { - int len; - // skip modifiers, white space and ':' for (;;) { while (*p == ' ' || *p == '\t' || *p == ':') { p++; } - len = modifier_len(p); + int len = modifier_len(p); if (len == 0) { break; } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index eadeb839de..95564da7cb 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1729,7 +1729,6 @@ static int command_line_browse_history(CommandLineState *s) if (s->hiscnt != s->save_hiscnt) { // jumped to other entry char *p; - int len = 0; int old_firstc; XFREE_CLEAR(ccline.cmdbuff); @@ -1743,6 +1742,7 @@ static int command_line_browse_history(CommandLineState *s) if (s->histype == HIST_SEARCH && p != s->lookfor && (old_firstc = (uint8_t)p[strlen(p) + 1]) != s->firstc) { + int len = 0; // Correct for the separator character used when // adding the history entry vs the one used now. // First loop: count length. @@ -3676,7 +3676,6 @@ static void restore_cmdline(CmdlineInfo *ccp) static bool cmdline_paste(int regname, bool literally, bool remcr) { char *arg; - char *p; bool allocated; // check for valid regname; also accept special characters for CTRL-R in @@ -3708,7 +3707,7 @@ static bool cmdline_paste(int regname, bool literally, bool remcr) // When 'incsearch' is set and CTRL-R CTRL-W used: skip the duplicate // part of the word. - p = arg; + char *p = arg; if (p_is && regname == Ctrl_W) { char *w; int len; @@ -3743,17 +3742,15 @@ static bool cmdline_paste(int regname, bool literally, bool remcr) // line. void cmdline_paste_str(char *s, int literally) { - int c, cv; - if (literally) { put_on_cmdline(s, -1, true); } else { while (*s != NUL) { - cv = (uint8_t)(*s); + int cv = (uint8_t)(*s); if (cv == Ctrl_V && s[1]) { s++; } - c = mb_cptr2char_adv((const char **)&s); + int c = mb_cptr2char_adv((const char **)&s); if (cv == Ctrl_V || c == ESC || c == Ctrl_C || c == CAR || c == NL || c == Ctrl_L || (c == Ctrl_BSL && *s == Ctrl_N)) { @@ -3781,8 +3778,6 @@ void redrawcmdline(void) static void redrawcmdprompt(void) { - int i; - if (cmd_silent) { return; } @@ -3801,7 +3796,7 @@ static void redrawcmdprompt(void) ccline.cmdindent--; } } else { - for (i = ccline.cmdindent; i > 0; i--) { + for (int i = ccline.cmdindent; i > 0; i--) { msg_putchar(' '); } } @@ -4284,12 +4279,10 @@ void cmdline_init(void) /// Returns NULL if value is OK, error message otherwise. char *check_cedit(void) { - int n; - if (*p_cedit == NUL) { cedit_key = -1; } else { - n = string_to_key(p_cedit); + int n = string_to_key(p_cedit); if (vim_isprintc(n)) { return e_invarg; } @@ -4309,9 +4302,7 @@ static int open_cmdwin(void) bufref_T old_curbuf; bufref_T bufref; win_T *old_curwin = curwin; - win_T *wp; int i; - linenr_T lnum; garray_T winsizes; char typestr[2]; int save_restart_edit = restart_edit; @@ -4392,7 +4383,7 @@ static int open_cmdwin(void) if (get_hislen() > 0 && histtype != HIST_INVALID) { i = *get_hisidx(histtype); if (i >= 0) { - lnum = 0; + linenr_T lnum = 0; do { if (++i == get_hislen()) { i = 0; @@ -4463,6 +4454,7 @@ static int open_cmdwin(void) cmdwin_result = Ctrl_C; emsg(_("E199: Active window or buffer deleted")); } else { + win_T *wp; // autocmds may abort script processing if (aborting() && cmdwin_result != K_IGNORE) { cmdwin_result = Ctrl_C; diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c index 3de5e1db52..8e3e68d9b7 100644 --- a/src/nvim/ex_session.c +++ b/src/nvim/ex_session.c @@ -65,10 +65,10 @@ static int put_view_curpos(FILE *fd, const win_T *wp, char *spaces) static int ses_winsizes(FILE *fd, int restore_size, win_T *tab_firstwin) { - int n = 0; win_T *wp; if (restore_size && (ssop_flags & SSOP_WINSIZE)) { + int n = 0; for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) { if (!ses_do_win(wp)) { continue; @@ -218,14 +218,13 @@ static int ses_do_win(win_T *wp) static int ses_arglist(FILE *fd, char *cmd, garray_T *gap, int fullname, unsigned *flagp) { char *buf = NULL; - char *s; if (fprintf(fd, "%s\n%s\n", cmd, "%argdel") < 0) { return FAIL; } for (int i = 0; i < gap->ga_len; i++) { // NULL file names are skipped (only happens when out of memory). - s = alist_name(&((aentry_T *)gap->ga_data)[i]); + char *s = alist_name(&((aentry_T *)gap->ga_data)[i]); if (s != NULL) { if (fullname) { buf = xmalloc(MAXPATHL); @@ -551,7 +550,6 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr static int makeopens(FILE *fd, char *dirnow) { int only_save_windows = true; - int nr; int restore_size = true; win_T *wp; char *sname; @@ -753,11 +751,9 @@ static int makeopens(FILE *fd, char *dirnow) PUTLINE_FAIL("let &splitright = s:save_splitright"); } - // // Check if window sizes can be restored (no windows omitted). // Remember the window number of the current window after restoring. - // - nr = 0; + int nr = 0; for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) { if (ses_do_win(wp)) { nr++; @@ -927,11 +923,9 @@ void ex_loadview(exarg_T *eap) void ex_mkrc(exarg_T *eap) { FILE *fd; - int failed = false; int view_session = false; // :mkview, :mksession int using_vdir = false; // using 'viewdir'? char *viewFile = NULL; - unsigned *flagp; if (eap->cmdidx == CMD_mksession || eap->cmdidx == CMD_mkview) { view_session = true; @@ -970,6 +964,8 @@ void ex_mkrc(exarg_T *eap) fd = open_exfile(fname, eap->forceit, WRITEBIN); if (fd != NULL) { + int failed = false; + unsigned *flagp; if (eap->cmdidx == CMD_mkview) { flagp = &vop_flags; } else { diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 42ba0bee97..e27c7c4349 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -1026,8 +1026,6 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char *filename, static bool ff_wc_equal(char *s1, char *s2) { int i, j; - int c1 = NUL; - int c2 = NUL; int prev1 = NUL; int prev2 = NUL; @@ -1040,8 +1038,8 @@ static bool ff_wc_equal(char *s1, char *s2) } for (i = 0, j = 0; s1[i] != NUL && s2[j] != NUL;) { - c1 = utf_ptr2char(s1 + i); - c2 = utf_ptr2char(s2 + j); + int c1 = utf_ptr2char(s1 + i); + int c2 = utf_ptr2char(s2 + j); if ((p_fic ? mb_tolower(c1) != mb_tolower(c2) : c1 != c2) && (prev1 != '*' || prev2 != '*')) { diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index f5728d29c1..ca00c5b449 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -155,7 +155,6 @@ static char *get_buffcont(buffheader_T *buffer, int dozero) { size_t count = 0; char *p = NULL; - char *p2; // compute the total length of the string for (const buffblock_T *bp = buffer->bh_first.b_next; @@ -165,7 +164,7 @@ static char *get_buffcont(buffheader_T *buffer, int dozero) if (count || dozero) { p = xmalloc(count + 1); - p2 = p; + char *p2 = p; for (const buffblock_T *bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next) { for (const char *str = bp->b_str; *str;) { @@ -1020,8 +1019,6 @@ int typebuf_maplen(void) // remove "len" characters from typebuf.tb_buf[typebuf.tb_off + offset] void del_typebuf(int len, int offset) { - int i; - if (len == 0) { return; // nothing to do } @@ -1034,7 +1031,7 @@ void del_typebuf(int len, int offset) typebuf.tb_off += len; } else { // Have to move the characters in typebuf.tb_buf[] and typebuf.tb_noremap[] - i = typebuf.tb_off + offset; + int i = typebuf.tb_off + offset; // Leave some extra room at the end to avoid reallocation. if (typebuf.tb_off > MAXMAPLEN) { memmove(typebuf.tb_buf + MAXMAPLEN, @@ -1408,10 +1405,8 @@ int merge_modifiers(int c_arg, int *modifiers) /// Returns the modifiers in the global "mod_mask". int vgetc(void) { - int c, c2; - int n; + int c; char_u buf[MB_MAXBYTES + 1]; - int i; // Do garbage collection when garbagecollect() was called previously and // we are now at the toplevel. @@ -1429,6 +1424,9 @@ int vgetc(void) mouse_row = old_mouse_row; mouse_col = old_mouse_col; } else { + int c2; + int n; + int i; // number of characters recorded from the last vgetc() call static size_t last_vgetc_recorded_len = 0; @@ -1754,9 +1752,9 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) int grid = mouse_grid; linenr_T lnum; win_T *wp; - int winnr = 1; if (row >= 0 && col >= 0) { + int winnr = 1; // Find the window at the mouse coordinates and compute the // text position. win_T *const win = mouse_find_win(&grid, &row, &col); @@ -1921,9 +1919,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) int max_mlen = 0; int tb_c1; int mlen; - int nolmaplen; int keylen = *keylenp; - int i; int local_State = get_real_state(); bool is_plug_map = false; @@ -1956,6 +1952,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) && State != MODE_ASKMORE && State != MODE_CONFIRM && !at_ins_compl_key()) { + int nolmaplen; if (tb_c1 == K_SPECIAL) { nolmaplen = 2; } else { @@ -2168,6 +2165,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) // complete match if (keylen >= 0 && keylen <= typebuf.tb_len) { + int i; char *map_str = NULL; // Write chars to script file(s). @@ -2509,9 +2507,6 @@ static int vgetorpeek(bool advance) && (State & MODE_INSERT) && (p_timeout || (keylen == KEYLEN_PART_KEY && p_ttimeout)) && (c = inchar(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_len, 3, 25L)) == 0) { - colnr_T col = 0; - char_u *ptr; - if (mode_displayed) { unshowmode(true); mode_deleted = true; @@ -2522,6 +2517,8 @@ static int vgetorpeek(bool advance) // move cursor left, if possible if (curwin->w_cursor.col != 0) { + colnr_T col = 0; + char_u *ptr; if (curwin->w_wcol > 0) { // After auto-indenting and no text is following, // we are expecting to truncate the trailing diff --git a/src/nvim/help.c b/src/nvim/help.c index bbc552fa4c..ab9d68fd89 100644 --- a/src/nvim/help.c +++ b/src/nvim/help.c @@ -660,7 +660,6 @@ void fix_help_buffer(void) { linenr_T lnum; char *line; - bool in_example = false; // Set filetype to "help". if (strcmp(curbuf->b_p_ft, "help") != 0) { @@ -670,6 +669,7 @@ void fix_help_buffer(void) } if (!syntax_present(curwin)) { + bool in_example = false; for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) { line = ml_get_buf(curbuf, lnum, false); const size_t len = strlen(line); @@ -722,9 +722,7 @@ void fix_help_buffer(void) && path_full_compare(rt, NameBuff, false, true) != kEqualFiles) { int fcount; char **fnames; - char *s; vimconv_T vc; - char *cp; // Find all "doc/ *.txt" files in this directory. if (!add_pathsep(NameBuff) @@ -740,6 +738,8 @@ void fix_help_buffer(void) if (gen_expand_wildcards(1, buff_list, &fcount, &fnames, EW_FILE|EW_SILENT) == OK && fcount > 0) { + char *s; + char *cp; // If foo.abx is found use it instead of foo.txt in // the same directory. for (int i1 = 0; i1 < fcount; i1++) { @@ -1080,7 +1080,6 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr) FUNC_ATTR_NONNULL_ALL { - int len; garray_T ga; char lang[2]; char ext[5]; @@ -1111,7 +1110,7 @@ static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr) int j; ga_init(&ga, 1, 10); for (int i = 0; i < filecount; i++) { - len = (int)strlen(files[i]); + int len = (int)strlen(files[i]); if (len <= 4) { continue; } @@ -1177,7 +1176,6 @@ static void helptags_cb(char *fname, void *cookie) void ex_helptags(exarg_T *eap) { expand_T xpc; - char *dirname; bool add_help_tags = false; // Check for ":helptags ++t {dir}". @@ -1191,7 +1189,8 @@ void ex_helptags(exarg_T *eap) } else { ExpandInit(&xpc); xpc.xp_context = EXPAND_DIRECTORIES; - dirname = ExpandOne(&xpc, eap->arg, NULL, WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE); + char *dirname = + ExpandOne(&xpc, eap->arg, NULL, WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE); if (dirname == NULL || !os_isdir(dirname)) { semsg(_("E150: Not a directory: %s"), eap->arg); } else { diff --git a/src/nvim/indent.c b/src/nvim/indent.c index ec6c72da6d..ee9bc48460 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -460,7 +460,6 @@ int set_indent(int size, int flags) int line_len; int doit = false; int ind_done = 0; // Measured in spaces. - int ind_col = 0; int tab_pad; int retval = false; @@ -479,6 +478,7 @@ int set_indent(int size, int flags) // 'preserveindent' are set count the number of characters at the // beginning of the line to be copied. if (!curbuf->b_p_et || (!(flags & SIN_INSERT) && curbuf->b_p_pi)) { + int ind_col = 0; // If 'preserveindent' is set then reuse as much as possible of // the existing indent structure for the new indent. if (!(flags & SIN_INSERT) && curbuf->b_p_pi) { @@ -936,14 +936,10 @@ void ex_retab(exarg_T *eap) long num_spaces = 0; long num_tabs; long len; - long col; - long vcol; long start_col = 0; // For start of white-space string long start_vcol = 0; // For start of white-space string long old_len; - char *ptr; char *new_line = (char *)1; // init to non-NULL - bool did_undo; // called u_save for current line long *new_vts_array = NULL; char *new_ts_str; // string value of tab argument @@ -972,10 +968,10 @@ void ex_retab(exarg_T *eap) new_ts_str = xstrnsave(new_ts_str, (size_t)(eap->arg - new_ts_str)); } for (lnum = eap->line1; !got_int && lnum <= eap->line2; lnum++) { - ptr = ml_get(lnum); - col = 0; - vcol = 0; - did_undo = false; + char *ptr = ml_get(lnum); + long col = 0; + long vcol = 0; + bool did_undo = false; // called u_save for current line for (;;) { if (ascii_iswhite(ptr[col])) { if (!got_tab && num_spaces == 0) { @@ -1186,10 +1182,6 @@ int get_lisp_indent(void) pos_T *pos, realpos, paren; int amount; char *that; - colnr_T col; - colnr_T firsttry; - int parencount; - int quotecount; int vi_lisp; // Set vi_lisp to use the vi-compatible method. @@ -1213,7 +1205,7 @@ int get_lisp_indent(void) // Extra trick: Take the indent of the first previous non-white // line that is at the same () level. amount = -1; - parencount = 0; + int parencount = 0; while (--curwin->w_cursor.lnum >= pos->lnum) { if (linewhite(curwin->w_cursor.lnum)) { @@ -1268,7 +1260,7 @@ int get_lisp_indent(void) if (amount == -1) { curwin->w_cursor.lnum = pos->lnum; curwin->w_cursor.col = pos->col; - col = pos->col; + colnr_T col = pos->col; that = get_cursor_line_ptr(); @@ -1298,7 +1290,7 @@ int get_lisp_indent(void) that++; amount++; } - firsttry = amount; + colnr_T firsttry = amount; init_chartabsize_arg(&cts, curwin, (colnr_T)(that - line), amount, line, that); @@ -1319,13 +1311,13 @@ int get_lisp_indent(void) } parencount = 0; - quotecount = 0; init_chartabsize_arg(&cts, curwin, (colnr_T)(that - line), amount, line, that); if (vi_lisp || ((*that != '"') && (*that != '\'') && (*that != '#') && (((uint8_t)(*that) < '0') || ((uint8_t)(*that) > '9')))) { + int quotecount = 0; while (*cts.cts_ptr && (!ascii_iswhite(*cts.cts_ptr) || quotecount || parencount) && (!((*cts.cts_ptr == '(' || *cts.cts_ptr == '[') @@ -1373,12 +1365,11 @@ int get_lisp_indent(void) static int lisp_match(char *p) { char buf[LSIZE]; - int len; char *word = *curbuf->b_p_lw != NUL ? curbuf->b_p_lw : p_lispwords; while (*word != NUL) { (void)copy_option_part(&word, buf, LSIZE, ","); - len = (int)strlen(buf); + int len = (int)strlen(buf); if ((strncmp(buf, p, (size_t)len) == 0) && ascii_iswhite_or_nul(p[len])) { return true; diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 831d1299a8..5547b6c367 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -1434,15 +1434,11 @@ int ExpandMappings(char *pat, regmatch_T *regmatch, int *numMatches, char ***mat // Return true if there is an abbreviation, false if not. bool check_abbr(int c, char *ptr, int col, int mincol) { - int len; int scol; // starting column of the abbr. - int j; - char *s; char_u tb[MB_MAXBYTES + 4]; mapblock_T *mp; mapblock_T *mp2; int clen = 0; // length in characters - bool is_id = true; if (typebuf.tb_no_abbr_cnt) { // abbrev. are not recursive return false; @@ -1462,6 +1458,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol) } { + bool is_id = true; bool vim_abbr; char *p = mb_prevptr(ptr, ptr + col); if (!vim_iswordp(p)) { @@ -1489,7 +1486,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol) } if (scol < col) { // there is a word in front of the cursor ptr += scol; - len = col - scol; + int len = col - scol; mp = curbuf->b_first_abbr; mp2 = first_abbr; if (mp == NULL) { @@ -1532,7 +1529,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol) // // Character CTRL-] is treated specially - it completes the // abbreviation, but is not inserted into the input stream. - j = 0; + int j = 0; if (c != Ctrl_RSB) { // special key code, split up if (IS_SPECIAL(c) || c == K_SPECIAL) { @@ -1568,6 +1565,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol) const bool silent = mp->m_silent; const bool expr = mp->m_expr; + char *s; if (expr) { s = eval_map_expr(mp, c); } else { diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 8b50ba719a..1cc3198216 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -449,18 +449,16 @@ int mb_get_class_tab(const char *p, const uint64_t *const chartab) static bool intable(const struct interval *table, size_t n_items, int c) FUNC_ATTR_PURE { - int mid, bot, top; - // first quick check for Latin1 etc. characters if (c < table[0].first) { return false; } // binary search in table - bot = 0; - top = (int)(n_items - 1); + int bot = 0; + int top = (int)(n_items - 1); while (top >= bot) { - mid = (bot + top) / 2; + int mid = (bot + top) / 2; if (table[mid].last < c) { bot = mid + 1; } else if (table[mid].first > c) { @@ -518,11 +516,9 @@ int utf_char2cells(int c) /// This doesn't take care of unprintable characters, use ptr2cells() for that. int utf_ptr2cells(const char *p) { - int c; - // Need to convert to a character number. if ((uint8_t)(*p) >= 0x80) { - c = utf_ptr2char(p); + int c = utf_ptr2char(p); // An illegal byte is displayed as . if (utf_ptr2len(p) == 1 || c == NUL) { return 4; @@ -540,14 +536,12 @@ int utf_ptr2cells(const char *p) /// For an empty string or truncated character returns 1. int utf_ptr2cells_len(const char *p, int size) { - int c; - // Need to convert to a wide character. if (size > 0 && (uint8_t)(*p) >= 0x80) { if (utf_ptr2len_len(p, size) < utf8len_tab[(uint8_t)(*p)]) { return 1; // truncated } - c = utf_ptr2char((char *)p); + int c = utf_ptr2char((char *)p); // An illegal byte is displayed as . if (utf_ptr2len((char *)p) == 1 || c == NUL) { return 4; @@ -664,8 +658,6 @@ int utf_ptr2char(const char *const p_in) // "s". static int utf_safe_read_char_adv(const char_u **s, size_t *n) { - int c; - if (*n == 0) { // end of buffer return 0; } @@ -682,7 +674,7 @@ static int utf_safe_read_char_adv(const char_u **s, size_t *n) // We have a multibyte sequence and it isn't truncated by buffer // limits so utf_ptr2char() is safe to use. Or the first byte is // illegal (k=0), and it's also safe to use utf_ptr2char(). - c = utf_ptr2char((char *)(*s)); + int c = utf_ptr2char((char *)(*s)); // On failure, utf_ptr2char() returns the first byte, so here we // check equality with the first byte. The only non-ASCII character @@ -1141,7 +1133,6 @@ int utf_class_tab(const int c, const uint64_t *const chartab) }; int bot = 0; int top = ARRAY_SIZE(classes) - 1; - int mid; // First quick check for Latin1 characters, use 'iskeyword'. if (c < 0x100) { @@ -1161,7 +1152,7 @@ int utf_class_tab(const int c, const uint64_t *const chartab) // binary search in table while (top >= bot) { - mid = (bot + top) / 2; + int mid = (bot + top) / 2; if (classes[mid].last < (unsigned int)c) { bot = mid + 1; } else if (classes[mid].first > (unsigned int)c) { @@ -1186,13 +1177,12 @@ bool utf_ambiguous_width(int c) // the given conversion "table". Uses binary search on "table". static int utf_convert(int a, const convertStruct *const table, size_t n_items) { - size_t start, mid, end; // indices into table - - start = 0; - end = n_items; + // indices into table + size_t start = 0; + size_t end = n_items; while (start < end) { // need to search further - mid = (end + start) / 2; + size_t mid = (end + start) / 2; if (table[mid].rangeEnd < a) { start = mid + 1; } else { @@ -1579,9 +1569,6 @@ void show_utf8(void) /// Returns 0 when already at the first byte of a character. int utf_head_off(const char *base_in, const char *p_in) { - int c; - int len; - if ((uint8_t)(*p_in) < 0x80) { // be quick for ASCII return 0; } @@ -1603,7 +1590,7 @@ int utf_head_off(const char *base_in, const char *p_in) } // Check for illegal sequence. Do allow an illegal byte after where we // started. - len = utf8len_tab[*q]; + int len = utf8len_tab[*q]; if (len != (int)(s - q + 1) && len != (int)(p - q + 1)) { return 0; } @@ -1612,7 +1599,7 @@ int utf_head_off(const char *base_in, const char *p_in) break; } - c = utf_ptr2char((char *)q); + int c = utf_ptr2char((char *)q); if (utf_iscomposing(c)) { continue; } @@ -1795,7 +1782,6 @@ int mb_off_next(const char *base, const char *p_in) { const uint8_t *p = (uint8_t *)p_in; int i; - int j; if (*p < 0x80) { // be quick for ASCII return 0; @@ -1804,6 +1790,7 @@ int mb_off_next(const char *base, const char *p_in) // Find the next character that isn't 10xx.xxxx for (i = 0; (p[i] & 0xc0) == 0x80; i++) {} if (i > 0) { + int j; // Check for illegal sequence. for (j = 0; p - j > (uint8_t *)base; j++) { if ((p[-j] & 0xc0) != 0x80) { @@ -2479,7 +2466,6 @@ char *string_convert_ext(const vimconv_T *const vcp, char *ptr, size_t *lenp, si { char_u *retval = NULL; char_u *d; - int l; int c; size_t len; @@ -2547,7 +2533,7 @@ char *string_convert_ext(const vimconv_T *const vcp, char *ptr, size_t *lenp, si retval = xmalloc(len + 1); d = retval; for (size_t i = 0; i < len; i++) { - l = utf_ptr2len_len(ptr + i, (int)(len - i)); + int l = utf_ptr2len_len(ptr + i, (int)(len - i)); if (l == 0) { *d++ = NUL; } else if (l == 1) { diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 950b025e53..60efd6a72a 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -86,15 +86,11 @@ static int get_mouse_class(char *p) /// Move "pos" back to the start of the word it's in. static void find_start_of_word(pos_T *pos) { - char *line; - int cclass; - int col; - - line = ml_get(pos->lnum); - cclass = get_mouse_class(line + pos->col); + char *line = ml_get(pos->lnum); + int cclass = get_mouse_class(line + pos->col); while (pos->col > 0) { - col = pos->col - 1; + int col = pos->col - 1; col -= utf_head_off(line, line + col); if (get_mouse_class(line + col) != cclass) { break; @@ -109,7 +105,6 @@ static void find_end_of_word(pos_T *pos) { char *line; int cclass; - int col; line = ml_get(pos->lnum); if (*p_sel == 'e' && pos->col > 0) { @@ -118,7 +113,7 @@ static void find_end_of_word(pos_T *pos) } cclass = get_mouse_class(line + pos->col); while (line[pos->col] != NUL) { - col = pos->col + utfc_ptr2len(line + pos->col); + int col = pos->col + utfc_ptr2len(line + pos->col); if (get_mouse_class(line + col) != cclass) { if (*p_sel == 'e') { pos->col = col; @@ -296,18 +291,16 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent) bool in_status_line; // mouse in status line static bool in_tab_line = false; // mouse clicked in tab line bool in_sep_line; // mouse in vertical separator line - int c1, c2; - pos_T save_cursor; + int c1; win_T *old_curwin = curwin; static pos_T orig_cursor; colnr_T leftcol, rightcol; pos_T end_visual; - long diff; int old_active = VIsual_active; int old_mode = VIsual_mode; int regname; - save_cursor = curwin->w_cursor; + pos_T save_cursor = curwin->w_cursor; for (;;) { which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag); @@ -731,6 +724,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent) } if (start_visual.lnum) { // right click in visual mode + long diff; // When ALT is pressed make Visual mode blockwise. if (mod_mask & MOD_MASK_ALT) { VIsual_mode = Ctrl_V; @@ -800,6 +794,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent) // Middle mouse click: Put text before cursor. if (which_button == MOUSE_MIDDLE) { + int c2; if (regname == 0 && eval_has_provider("clipboard")) { regname = '*'; } @@ -888,13 +883,13 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent) // A double click selects a word or a block. if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) { pos_T *pos = NULL; - int gc; if (is_click) { // If the character under the cursor (skipping white space) is // not a word character, try finding a match and select a (), // {}, [], #if/#endif, etc. block. end_visual = curwin->w_cursor; + int gc; while (gc = gchar_pos(&end_visual), ascii_iswhite(gc)) { inc(&end_visual); } @@ -1388,16 +1383,14 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump) { int col = *colp; int row = *rowp; - linenr_T lnum; bool retval = false; - int off; int count; if (win->w_p_rl) { col = win->w_width_inner - 1 - col; } - lnum = win->w_topline; + linenr_T lnum = win->w_topline; while (row > 0) { // Don't include filler lines in "count" @@ -1429,7 +1422,7 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump) if (!retval) { // Compute the column without wrapping. - off = win_col_off(win) - win_col_off2(win); + int off = win_col_off(win) - win_col_off2(win); if (col < off) { col = off; } @@ -1467,9 +1460,7 @@ win_T *mouse_find_win(int *gridp, int *rowp, int *colp) return NULL; } - frame_T *fp; - - fp = topframe; + frame_T *fp = topframe; *rowp -= firstwin->w_winrow; for (;;) { if (fp->fr_layout == FR_LEAF) { @@ -1716,10 +1707,8 @@ static int mouse_adjust_click(win_T *wp, int row, int col) ptr_end += utfc_ptr2len(ptr_end); } - int matchid; int prev_matchid; int nudge = 0; - int cwidth = 0; vcol = offset; @@ -1727,7 +1716,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col) #define DECR() nudge--; ptr_end -= utfc_ptr2len((char *)ptr_end) while (ptr < ptr_end && *ptr != NUL) { - cwidth = win_chartabsize(curwin, ptr, vcol); + int cwidth = win_chartabsize(curwin, ptr, vcol); vcol += cwidth; if (cwidth > 1 && *ptr == '\t' && nudge > 0) { // A tab will "absorb" any previous adjustments. @@ -1738,7 +1727,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col) } } - matchid = syn_get_concealed_id(wp, lnum, (colnr_T)(ptr - line)); + int matchid = syn_get_concealed_id(wp, lnum, (colnr_T)(ptr - line)); if (matchid != 0) { if (wp->w_p_cole == 3) { INCR(); @@ -1780,9 +1769,7 @@ int mouse_check_fold(void) int max_col = Columns; int multigrid = ui_has(kUIMultigrid); - win_T *wp; - - wp = mouse_find_win(&click_grid, &click_row, &click_col); + win_T *wp = mouse_find_win(&click_grid, &click_row, &click_col); if (wp && multigrid) { max_row = wp->w_grid_alloc.rows; max_col = wp->w_grid_alloc.cols; diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 435ca106ab..6326130c5a 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -214,7 +214,6 @@ int get_extra_op_char(int optype) void op_shift(oparg_T *oap, int curs_top, int amount) { long i; - int first_char; int block_col = 0; if (u_save((linenr_T)(oap->start.lnum - 1), @@ -227,7 +226,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount) } for (i = oap->line_count - 1; i >= 0; i--) { - first_char = (uint8_t)(*get_cursor_line_ptr()); + int first_char = (uint8_t)(*get_cursor_line_ptr()); if (first_char == NUL) { // empty line curwin->w_cursor.col = 0; } else if (oap->motion_type == kMTBlockWise) { @@ -289,15 +288,13 @@ void op_shift(oparg_T *oap, int curs_top, int amount) /// @param call_changed_bytes call changed_bytes() void shift_line(int left, int round, int amount, int call_changed_bytes) { - int count; - int i, j; const int sw_val = (int)get_sw_value_indent(curbuf); - count = get_indent(); // get current indent + int count = get_indent(); // get current indent if (round) { // round off indent - i = count / sw_val; // number of 'shiftwidth' rounded down - j = count % sw_val; // extra spaces + int i = count / sw_val; // number of 'shiftwidth' rounded down + int j = count % sw_val; // extra spaces if (j && left) { // first remove extra spaces amount--; } @@ -636,8 +633,6 @@ static void block_insert(oparg_T *oap, char *s, int b_insert, struct block_def * void op_reindent(oparg_T *oap, Indenter how) { long i = 0; - char *l; - int amount; linenr_T first_changed = 0; linenr_T last_changed = 0; linenr_T start_lnum = curwin->w_cursor.lnum; @@ -652,6 +647,8 @@ void op_reindent(oparg_T *oap, Indenter how) // for each line separately, especially when undoing. if (u_savecommon(curbuf, start_lnum - 1, start_lnum + (linenr_T)oap->line_count, start_lnum + (linenr_T)oap->line_count, false) == OK) { + char *l; + int amount; for (i = oap->line_count - 1; i >= 0 && !got_int; i--) { // it's a slow thing to do, so give feedback so there's no worry // that the computer's just hung. @@ -902,7 +899,6 @@ bool yank_register_mline(int regname) /// @return FAIL for failure, OK otherwise. int do_record(int c) { - char *p; static int regname; yankreg_T *old_y_previous; int retval; @@ -927,7 +923,7 @@ int do_record(int c) dict_T *dict = get_v_event(&save_v_event); // The recorded text contents. - p = (char *)get_recorded(); + char *p = (char *)get_recorded(); if (p != NULL) { // Remove escaping for K_SPECIAL in multi-byte chars. vim_unescape_ks((char_u *)p); @@ -1149,7 +1145,6 @@ int do_execreg(int regname, int colon, int addcr, int silent) // Insert lines into typeahead buffer, from last one to first one. put_reedit_in_typebuf(silent); - char *escaped; for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included // insert NL between lines and after last line if type is kMTLineWise if (reg->y_type == kMTLineWise || i < reg->y_size - 1 || addcr) { @@ -1168,7 +1163,7 @@ int do_execreg(int regname, int colon, int addcr, int silent) free_str = true; } } - escaped = vim_strsave_escape_ks(str); + char *escaped = vim_strsave_escape_ks(str); if (free_str) { xfree(str); } @@ -1651,10 +1646,9 @@ int op_delete(oparg_T *oap) } } else { if (virtual_op) { - int endcol = 0; - // For virtualedit: break the tabs that are partly included. if (gchar_pos(&oap->start) == '\t') { + int endcol = 0; if (u_save_cursor() == FAIL) { // save first line for undo return FAIL; } @@ -1820,10 +1814,7 @@ static void replace_character(int c) /// Replace a whole area with one character. static int op_replace(oparg_T *oap, int c) { - int n, numc; - int num_chars; - char *newp, *oldp; - colnr_T oldlen; + int n; struct block_def bd; char *after_p = NULL; int had_ctrl_v_cr = false; @@ -1848,6 +1839,11 @@ static int op_replace(oparg_T *oap, int c) // block mode replace if (oap->motion_type == kMTBlockWise) { + int numc; + int num_chars; + char *newp; + char *oldp; + colnr_T oldlen; bd.is_MAX = (curwin->w_curswant == MAXCOL); for (; curwin->w_cursor.lnum <= oap->end.lnum; curwin->w_cursor.lnum++) { curwin->w_cursor.col = 0; // make sure cursor position is valid @@ -2218,12 +2214,11 @@ bool swapchar(int op_type, pos_T *pos) /// Insert and append operators for Visual mode. void op_insert(oparg_T *oap, long count1) { - long ins_len, pre_textlen = 0; - char *firstline, *ins_text; - colnr_T ind_pre_col = 0, ind_post_col; - int ind_pre_vcol = 0, ind_post_vcol = 0; + long pre_textlen = 0; + char *firstline; + colnr_T ind_pre_col = 0; + int ind_pre_vcol = 0; struct block_def bd; - int i; pos_T t1; // edit() changes this - record it for OP_APPEND @@ -2284,7 +2279,7 @@ void op_insert(oparg_T *oap, long count1) if (u_save_cursor() == FAIL) { return; } - for (i = 0; i < bd.endspaces; i++) { + for (int i = 0; i < bd.endspaces; i++) { ins_char(' '); } bd.textlen += bd.endspaces; @@ -2321,12 +2316,13 @@ void op_insert(oparg_T *oap, long count1) } if (oap->motion_type == kMTBlockWise) { + int ind_post_vcol = 0; struct block_def bd2; bool did_indent = false; // if indent kicked in, the firstline might have changed // but only do that, if the indent actually increased - ind_post_col = (colnr_T)getwhitecols_curline(); + colnr_T ind_post_col = (colnr_T)getwhitecols_curline(); if (curbuf->b_op_start.col > ind_pre_col && ind_post_col > ind_pre_col) { bd.textcol += ind_post_col - ind_pre_col; ind_post_vcol = get_indent(); @@ -2414,9 +2410,9 @@ void op_insert(oparg_T *oap, long count1) } else { firstline += add; } - ins_len = (long)strlen(firstline) - pre_textlen - offset; + long ins_len = (long)strlen(firstline) - pre_textlen - offset; if (pre_textlen >= 0 && ins_len > 0) { - ins_text = xstrnsave(firstline, (size_t)ins_len); + char *ins_text = xstrnsave(firstline, (size_t)ins_len); // block handled here if (u_save(oap->start.lnum, (linenr_T)(oap->end.lnum + 1)) == OK) { block_insert(oap, ins_text, (oap->op_type == OP_INSERT), &bd); @@ -2434,20 +2430,13 @@ void op_insert(oparg_T *oap, long count1) /// @return true if edit() returns because of a CTRL-O command int op_change(oparg_T *oap) { - colnr_T l; int retval; - long offset; - linenr_T linenr; - long ins_len; long pre_textlen = 0; long pre_indent = 0; - char *newp; char *firstline; - char *ins_text; - char *oldp; struct block_def bd; - l = oap->start.col; + colnr_T l = oap->start.col; if (oap->motion_type == kMTLineWise) { l = 0; can_si = may_do_si(); // Like opening a new line, do smart indent @@ -2499,6 +2488,7 @@ int op_change(oparg_T *oap) // Don't repeat the insert when Insert mode ended with CTRL-C. if (oap->motion_type == kMTBlockWise && oap->start.lnum != oap->end.lnum && !got_int) { + long ins_len; // Auto-indenting may have changed the indent. If the cursor was past // the indent, exclude that indent change from the inserted text. firstline = ml_get(oap->start.lnum); @@ -2511,11 +2501,14 @@ int op_change(oparg_T *oap) ins_len = (long)strlen(firstline) - pre_textlen; if (ins_len > 0) { + long offset; + char *newp; + char *oldp; // Subsequent calls to ml_get() flush the firstline data - take a // copy of the inserted text. - ins_text = xmalloc((size_t)(ins_len + 1)); + char *ins_text = xmalloc((size_t)(ins_len + 1)); xstrlcpy(ins_text, firstline + bd.textcol, (size_t)ins_len + 1); - for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum; + for (linenr_T linenr = oap->start.lnum + 1; linenr <= oap->end.lnum; linenr++) { block_prep(oap, &bd, linenr, true); if (!bd.is_short || virtual_op) { @@ -2619,7 +2612,6 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) yankreg_T newreg; // new yank register when appending char **new_ptr; linenr_T lnum; // current line number - size_t j; MotionType yank_type = oap->motion_type; size_t yanklines = (size_t)oap->line_count; linenr_T yankendlnum = oap->end.lnum; @@ -2743,6 +2735,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) } if (curr != reg) { // append the new block to the old block + size_t j; new_ptr = xmalloc(sizeof(char *) * (curr->y_size + reg->y_size)); for (j = 0; j < curr->y_size; j++) { new_ptr[j] = curr->y_array[j]; @@ -3773,7 +3766,6 @@ void ex_display(exarg_T *eap) { char *p; yankreg_T *yb; - int name; char *arg = eap->arg; int clen; int type; @@ -3786,7 +3778,7 @@ void ex_display(exarg_T *eap) // Highlight title msg_puts_title(_("\nType Name Content")); for (int i = -1; i < NUM_REGISTERS && !got_int; i++) { - name = get_register_name(i); + int name = get_register_name(i); switch (get_reg_type(name, NULL)) { case kMTLineWise: type = 'l'; break; @@ -3912,13 +3904,11 @@ void ex_display(exarg_T *eap) static void dis_msg(const char *p, bool skip_esc) FUNC_ATTR_NONNULL_ALL { - int n; - int l; - - n = Columns - 6; + int n = Columns - 6; while (*p != NUL && !(*p == ESC && skip_esc && *(p + 1) == NUL) && (n -= ptr2cells(p)) >= 0) { + int l; if ((l = utfc_ptr2len(p)) > 1) { msg_outtrans_len(p, l); p += l; @@ -4389,7 +4379,6 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd) changed_lines(pos.lnum, 0, pos.lnum + 1, 0L, true); } } else { - int one_change; int length; pos_T startpos; @@ -4429,7 +4418,7 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd) length = oap->end.col - pos.col + 1; } } - one_change = do_addsub(oap->op_type, &pos, length, amount); + int one_change = do_addsub(oap->op_type, &pos, length, amount); if (one_change) { // Remember the start position of the first change. if (change_cnt == 0) { @@ -5323,7 +5312,6 @@ void cursor_pos_info(dict_T *dict) char *p; char buf1[50]; char buf2[40]; - linenr_T lnum; varnumber_T byte_count = 0; varnumber_T bom_count = 0; varnumber_T byte_count_cursor = 0; @@ -5331,9 +5319,6 @@ void cursor_pos_info(dict_T *dict) varnumber_T char_count_cursor = 0; varnumber_T word_count = 0; varnumber_T word_count_cursor = 0; - int eol_size; - varnumber_T last_check = 100000L; - long line_count_selected = 0; pos_T min_pos, max_pos; oparg_T oparg; struct block_def bd; @@ -5347,6 +5332,10 @@ void cursor_pos_info(dict_T *dict) return; } } else { + linenr_T lnum; + int eol_size; + varnumber_T last_check = 100000L; + long line_count_selected = 0; if (get_fileformat(curbuf) == EOL_DOS) { eol_size = 2; } else { @@ -5777,22 +5766,20 @@ typedef struct { void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) { oparg_T *oap = cap->oap; - pos_T old_cursor; - bool empty_region_error; - int restart_edit_save; int lbr_saved = curwin->w_p_lbr; // The visual area is remembered for redo static redo_VIsual_T redo_VIsual = { NUL, 0, 0, 0, 0 }; - bool include_line_break = false; - - old_cursor = curwin->w_cursor; + pos_T old_cursor = curwin->w_cursor; // If an operation is pending, handle it... if ((finish_op || VIsual_active) && oap->op_type != OP_NOP) { + bool empty_region_error; + int restart_edit_save; + bool include_line_break = false; // Yank can be redone when 'y' is in 'cpoptions', but not when yanking // for the clipboard. const bool redo_yank = vim_strchr(p_cpo, CPO_YANK) != NULL && !gui_yank; @@ -5914,8 +5901,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) } else if (VIsual_mode == 'v') { // If 'selection' is "exclusive", backup one character for // charwise selections. - include_line_break = - unadjust_for_sel(); + include_line_break = unadjust_for_sel(); } oap->start = VIsual; diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index 45c1afd70e..cdf8d5720b 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -113,8 +113,6 @@ static void pum_compute_size(void) void pum_display(pumitem_T *array, int size, int selected, bool array_changed, int cmd_startcol) { int context_lines; - int above_row; - int below_row; int redo_count = 0; int pum_win_row; int cursor_col; @@ -134,8 +132,8 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i pum_is_visible = true; pum_is_drawn = true; validate_cursor_col(); - above_row = 0; - below_row = cmdline_row; + int above_row = 0; + int below_row = cmdline_row; // wildoptions=pum if (State == MODE_CMDLINE) { @@ -409,17 +407,15 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i void pum_redraw(void) { int row = 0; - int grid_col; int attr_norm = win_hl_attr(curwin, HLF_PNI); int attr_select = win_hl_attr(curwin, HLF_PSI); int attr_scroll = win_hl_attr(curwin, HLF_PSB); int attr_thumb = win_hl_attr(curwin, HLF_PST); - int attr; int i; - int idx; char *s; char *p = NULL; - int totwidth, width, w; + int width; + int w; int thumb_pos = 0; int thumb_height = 1; int round; @@ -485,8 +481,8 @@ void pum_redraw(void) } for (i = 0; i < pum_height; i++) { - idx = i + pum_first; - attr = (idx == pum_selected) ? attr_select : attr_norm; + int idx = i + pum_first; + int attr = (idx == pum_selected) ? attr_select : attr_norm; grid_puts_line_start(&pum_grid, row); @@ -501,8 +497,8 @@ void pum_redraw(void) // Display each entry, use two spaces for a Tab. // Do this 3 times: For the main text, kind and extra info - grid_col = col_off; - totwidth = 0; + int grid_col = col_off; + int totwidth = 0; for (round = 1; round <= 3; round++) { width = 0; @@ -725,7 +721,6 @@ static bool pum_set_selected(int n, int repeat) && (vim_strchr(p_cot, 'p') != NULL)) { win_T *curwin_save = curwin; tabpage_T *curtab_save = curtab; - int res = OK; // Open a preview window. 3 lines by default. Prefer // 'previewheight' if set and smaller. @@ -744,6 +739,7 @@ static bool pum_set_selected(int n, int repeat) g_do_tagpreview = 0; if (curwin->w_p_pvw) { + int res = OK; if (!resized && (curbuf->b_nwindows == 1) && (curbuf->b_fname == NULL) diff --git a/src/nvim/profile.c b/src/nvim/profile.c index fd024f2d38..173332a428 100644 --- a/src/nvim/profile.c +++ b/src/nvim/profile.c @@ -689,10 +689,8 @@ void profile_init(scriptitem_T *si) /// @param tm place to store wait time void script_prof_save(proftime_T *tm) { - scriptitem_T *si; - if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) { - si = &SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_pr_nest++ == 0) { si->sn_pr_child = profile_start(); } @@ -720,12 +718,11 @@ void script_prof_restore(const proftime_T *tm) /// Dump the profiling results for all scripts in file "fd". static void script_dump_profile(FILE *fd) { - scriptitem_T *si; FILE *sfd; sn_prl_T *pp; for (int id = 1; id <= script_items.ga_len; id++) { - si = &SCRIPT_ITEM(id); + scriptitem_T *si = &SCRIPT_ITEM(id); if (si->sn_prof_on) { fprintf(fd, "SCRIPT %s\n", si->sn_name); if (si->sn_pr_count == 1) { @@ -808,7 +805,6 @@ void profile_dump(void) void script_line_start(void) { scriptitem_T *si; - sn_prl_T *pp; if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) { return; @@ -822,7 +818,7 @@ void script_line_start(void) while (si->sn_prl_ga.ga_len <= si->sn_prl_idx && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen) { // Zero counters for a line that was not used before. - pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len); + sn_prl_T *pp = &PRL_ITEM(si, si->sn_prl_ga.ga_len); pp->snp_count = 0; pp->sn_prl_total = profile_zero(); pp->sn_prl_self = profile_zero(); @@ -853,7 +849,6 @@ void script_line_exec(void) void script_line_end(void) { scriptitem_T *si; - sn_prl_T *pp; if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) { return; @@ -862,7 +857,7 @@ void script_line_end(void) if (si->sn_prof_on && si->sn_prl_idx >= 0 && si->sn_prl_idx < si->sn_prl_ga.ga_len) { if (si->sn_prl_execed) { - pp = &PRL_ITEM(si, si->sn_prl_idx); + sn_prl_T *pp = &PRL_ITEM(si, si->sn_prl_idx); pp->snp_count++; si->sn_prl_start = profile_end(si->sn_prl_start); si->sn_prl_start = profile_sub_wait(si->sn_prl_wait, si->sn_prl_start); diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 2204cda169..8ef3aed417 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -380,7 +380,7 @@ size_t spell_check(win_T *wp, char *ptr, hlf_T *attrp, int *capcol, bool docount MB_PTR_ADV(mi.mi_end); } else if (mi.mi_result == SP_BAD && LANGP_ENTRY(wp->w_s->b_langp, 0)->lp_slang->sl_nobreak) { - char *p, *fp; + char *p; int save_result = mi.mi_result; // First language in 'spelllang' is NOBREAK. Find first position @@ -388,7 +388,7 @@ size_t spell_check(win_T *wp, char *ptr, hlf_T *attrp, int *capcol, bool docount mi.mi_lp = LANGP_ENTRY(wp->w_s->b_langp, 0); if (mi.mi_lp->lp_slang->sl_fidxs != NULL) { p = mi.mi_word; - fp = mi.mi_fword; + char *fp = mi.mi_fword; for (;;) { MB_PTR_ADV(p); MB_PTR_ADV(fp); @@ -2834,7 +2834,6 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) int j, z; int reslen; int k = 0; - int z0; int k0; int n0; int pri; @@ -2875,7 +2874,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) while ((c = word[i]) != NUL) { // Start with the first rule that has the character in the word. int n = slang->sl_sal_first[c & 0xff]; - z0 = 0; + int z0 = 0; if (n >= 0) { // Check all rules for the same index byte. diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 5e7ebc4c87..594b05dd6b 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -1385,7 +1385,6 @@ static int read_compound(FILE *fd, slang_T *slang, int len) int c; int atstart; int cnt; - garray_T *gap; if (todo < 2) { return SP_FORMERROR; // need at least two bytes @@ -1420,7 +1419,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len) todo--; slang->sl_compoptions = c; - gap = &slang->sl_comppat; + garray_T *gap = &slang->sl_comppat; c = get2c(fd); // if (c < 0) { return SP_TRUNCERROR; @@ -1612,7 +1611,6 @@ static void set_sal_first(slang_T *lp) { salfirst_T *sfirst; salitem_T *smp; - int c; garray_T *gap = &lp->sl_sal; sfirst = lp->sl_sal_first; @@ -1624,7 +1622,7 @@ static void set_sal_first(slang_T *lp) // Use the lowest byte of the first character. For latin1 it's // the character, for other encodings it should differ for most // characters. - c = *smp[i].sm_lead_w & 0xff; + int c = *smp[i].sm_lead_w & 0xff; if (sfirst[c] == -1) { sfirst[c] = i; @@ -1738,7 +1736,6 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx int i; int n; idx_T idx = startidx; - int c; int c2; #define SHARED_MASK 0x8000000 @@ -1754,7 +1751,7 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx // Read the byte values, flag/region bytes and shared indexes. for (i = 1; i <= len; i++) { - c = getc(fd); // + int c = getc(fd); // if (c < 0) { return SP_TRUNCERROR; } @@ -2434,7 +2431,6 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname) && strcmp(cur_aff->ah_key, items[1]) == 0 && itemcnt >= 5) { affentry_T *aff_entry; - bool upper = false; int lasti = 5; // Myspell allows extra text after the item, but that might @@ -2493,6 +2489,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname) // COMPOUNDFORBIDFLAG and COMPOUNDPERMITFLAG. if (*items[0] == 'P' && aff->af_pfxpostpone && aff_entry->ae_flags == NULL) { + bool upper = false; // When the chop string is one lower-case letter and // the add string ends in the upper-case letter we set // the "upper" flag, clear "ae_chop" and remove the @@ -2502,10 +2499,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname) && aff_entry->ae_add != NULL && aff_entry->ae_chop[utfc_ptr2len(aff_entry->ae_chop)] == NUL) { - int c, c_up; - - c = utf_ptr2char(aff_entry->ae_chop); - c_up = SPELL_TOUPPER(c); + int c = utf_ptr2char(aff_entry->ae_chop); + int c_up = SPELL_TOUPPER(c); if (c_up != c && (aff_entry->ae_cond == NULL || utf_ptr2char(aff_entry->ae_cond) == c)) { @@ -2535,8 +2530,6 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname) if (aff_entry->ae_chop == NULL) { int idx; - char_u **pp; - int n; // Find a previously used condition. for (idx = spin->si_prefcond.ga_len - 1; idx >= 0; idx--) { @@ -2548,7 +2541,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname) if (idx < 0) { // Not found, add a new condition. idx = spin->si_prefcond.ga_len; - pp = GA_APPEND_VIA_PTR(char_u *, &spin->si_prefcond); + char_u **pp = GA_APPEND_VIA_PTR(char_u *, &spin->si_prefcond); *pp = (aff_entry->ae_cond == NULL) ? NULL : (char_u *)getroom_save(spin, aff_entry->ae_cond); } @@ -2562,7 +2555,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname) // PFX_FLAGS is a negative number, so that // tree_add_word() knows this is the prefix tree. - n = PFX_FLAGS; + int n = PFX_FLAGS; if (!cur_aff->ah_combine) { n |= WFP_NC; } @@ -2636,11 +2629,9 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname) fname, lnum); } } else if (do_mapline) { - int c; - // Check that every character appears only once. for (p = items[1]; *p != NUL;) { - c = mb_ptr2char_adv((const char **)&p); + int c = mb_ptr2char_adv((const char **)&p); if ((!GA_EMPTY(&spin->si_map) && vim_strchr(spin->si_map.ga_data, c) != NULL) @@ -2791,14 +2782,12 @@ static bool is_aff_rule(char **items, int itemcnt, char *rulename, int mincount) static void aff_process_flags(afffile_T *affile, affentry_T *entry) { char *p; - char_u *prevp; - unsigned flag; if (entry->ae_flags != NULL && (affile->af_compforbid != 0 || affile->af_comppermit != 0)) { for (p = entry->ae_flags; *p != NUL;) { - prevp = (char_u *)p; - flag = get_affitem(affile->af_flagtype, &p); + char_u *prevp = (char_u *)p; + unsigned flag = get_affitem(affile->af_flagtype, &p); if (flag == affile->af_comppermit || flag == affile->af_compforbid) { STRMOVE(prevp, (char *)p); p = (char *)prevp; @@ -2833,10 +2822,9 @@ static bool spell_info_item(char *s) // returns zero for failure. static unsigned affitem2flag(int flagtype, char *item, char *fname, int lnum) { - unsigned res; char *p = item; - res = get_affitem(flagtype, &p); + unsigned res = get_affitem(flagtype, &p); if (res == 0) { if (flagtype == AFT_NUM) { smsg(_("Flag is not a number in %s line %d: %s"), @@ -2889,30 +2877,27 @@ static unsigned get_affitem(int flagtype, char **pp) /// they fit in one byte. static void process_compflags(spellinfo_T *spin, afffile_T *aff, char *compflags) { - char *p; char *prevp; unsigned flag; compitem_T *ci; int id; - int len; - char_u *tp; char key[AH_KEY_LEN]; hashitem_T *hi; // Make room for the old and the new compflags, concatenated with a / in // between. Processing it makes it shorter, but we don't know by how // much, thus allocate the maximum. - len = (int)strlen(compflags) + 1; + int len = (int)strlen(compflags) + 1; if (spin->si_compflags != NULL) { len += (int)strlen(spin->si_compflags) + 1; } - p = getroom(spin, (size_t)len, false); + char *p = getroom(spin, (size_t)len, false); if (spin->si_compflags != NULL) { STRCPY(p, spin->si_compflags); STRCAT(p, "/"); } spin->si_compflags = p; - tp = (char_u *)p + strlen(p); + char_u *tp = (char_u *)p + strlen(p); for (p = compflags; *p != NUL;) { if (vim_strchr("/?*+[]", (uint8_t)(*p)) != NULL) { @@ -3061,7 +3046,6 @@ static void spell_free_aff(afffile_T *aff) { hashtab_T *ht; hashitem_T *hi; - int todo; affheader_T *ah; affentry_T *ae; @@ -3069,7 +3053,7 @@ static void spell_free_aff(afffile_T *aff) // All this trouble to free the "ae_prog" items... for (ht = &aff->af_pref;; ht = &aff->af_suff) { - todo = (int)ht->ht_used; + int todo = (int)ht->ht_used; for (hi = ht->ht_array; todo > 0; hi++) { if (!HASHITEM_EMPTY(hi)) { todo--; @@ -3106,7 +3090,6 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile) int l; hash_T hash; hashitem_T *hi; - FILE *fd; int lnum = 1; int non_ascii = 0; int retval = OK; @@ -3116,7 +3099,7 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile) Timestamp last_msg_time = 0; // Open the file. - fd = os_fopen(fname, "r"); + FILE *fd = os_fopen(fname, "r"); if (fd == NULL) { semsg(_(e_notopen), fname); return FAIL; @@ -3340,15 +3323,13 @@ static int get_affix_flags(afffile_T *affile, char *afflist) // and return the number of affixes. static int get_pfxlist(afffile_T *affile, char *afflist, char_u *store_afflist) { - char *p; - char *prevp; int cnt = 0; int id; char key[AH_KEY_LEN]; hashitem_T *hi; - for (p = afflist; *p != NUL;) { - prevp = p; + for (char *p = afflist; *p != NUL;) { + char *prevp = p; if (get_affitem(affile->af_flagtype, &p) != 0) { // A flag is a postponed prefix flag if it appears in "af_pref" // and its ID is not zero. @@ -3375,14 +3356,12 @@ static int get_pfxlist(afffile_T *affile, char *afflist, char_u *store_afflist) // Puts the flags in "store_afflist[]". static void get_compflags(afffile_T *affile, char *afflist, char_u *store_afflist) { - char *p; - char *prevp; int cnt = 0; char key[AH_KEY_LEN]; hashitem_T *hi; - for (p = afflist; *p != NUL;) { - prevp = p; + for (char *p = afflist; *p != NUL;) { + char *prevp = p; if (get_affitem(affile->af_flagtype, &p) != 0) { // A flag is a compound flag if it appears in "af_comp". xstrlcpy(key, prevp, (size_t)(p - prevp) + 1); @@ -3418,7 +3397,6 @@ static int store_aff_word(spellinfo_T *spin, char *word, char *afflist, afffile_ hashtab_T *ht, hashtab_T *xht, int condit, int flags, char *pfxlist, int pfxlen) { - int todo; hashitem_T *hi; affheader_T *ah; affentry_T *ae; @@ -3435,7 +3413,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char *afflist, afffile_ size_t wordlen = strlen(word); int use_condit; - todo = (int)ht->ht_used; + int todo = (int)ht->ht_used; for (hi = ht->ht_array; todo > 0 && retval == OK; hi++) { if (!HASHITEM_EMPTY(hi)) { todo--; @@ -4414,7 +4392,6 @@ static int write_vim_spell(spellinfo_T *spin, char *fname) // the table (avoids that it conflicts). File is shorter too. if (!spin->si_ascii && !spin->si_add) { char folchars[128 * 8]; - int flags; putc(SN_CHARFLAGS, fd); // putc(SNF_REQUIRED, fd); // @@ -4428,7 +4405,7 @@ static int write_vim_spell(spellinfo_T *spin, char *fname) fputc(128, fd); // for (size_t i = 128; i < 256; i++) { - flags = 0; + int flags = 0; if (spelltab.st_isw[i]) { flags |= CF_WORD; } @@ -5528,8 +5505,6 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo) char *fname; char *fnamebuf = NULL; char line[MAXWLEN * 2]; - long fpos, fpos_next = 0; - int i; char *spf; if (!valid_spell_word(word, word + len)) { @@ -5546,6 +5521,7 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo) } fname = int_wordlist; } else { + int i; // If 'spellfile' isn't set figure out a good default value. if (*curwin->w_s->b_p_spf == NUL) { init_spellfile(); @@ -5585,6 +5561,8 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo) } if (what == SPELL_ADD_BAD || undo) { + long fpos_next = 0; + long fpos = 0; // When the word appears as good word we need to remove that one, // since its flags sort before the one with WF_BANNED. fd = os_fopen(fname, "r"); @@ -5784,11 +5762,9 @@ static void set_spell_charflags(const char_u *flags, int cnt, char *fol) static int set_spell_finish(spelltab_T *new_st) { - int i; - if (did_set_spelltab) { // check that it's the same table - for (i = 0; i < 256; i++) { + for (int i = 0; i < 256; i++) { if (spelltab.st_isw[i] != new_st->st_isw[i] || spelltab.st_isu[i] != new_st->st_isu[i] || spelltab.st_fold[i] != new_st->st_fold[i] @@ -5841,7 +5817,6 @@ static void set_map_str(slang_T *lp, char *map) { char *p; int headc = 0; - int c; int i; if (*map == NUL) { @@ -5860,7 +5835,7 @@ static void set_map_str(slang_T *lp, char *map) // "aaa/bbb/ccc/". Fill sl_map_array[c] with the character before c and // before the same slash. For characters above 255 sl_map_hash is used. for (p = map; *p != NUL;) { - c = mb_cptr2char_adv((const char **)&p); + int c = mb_cptr2char_adv((const char **)&p); if (c == '/') { headc = 0; } else { diff --git a/src/nvim/window.c b/src/nvim/window.c index 6b40ccdb84..c6694cd489 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -358,14 +358,13 @@ newwindow: msg(_(m_onlyone)); } else { tabpage_T *oldtab = curtab; - tabpage_T *newtab; // First create a new tab with the window, then go back to // the old tab and close the window there. win_T *wp = curwin; if (win_new_tabpage((int)Prenum, NULL) == OK && valid_tabpage(oldtab)) { - newtab = curtab; + tabpage_T *newtab = curtab; goto_tabpage_tp(oldtab, true, true); if (curwin == wp) { win_close(curwin, false, false); -- cgit From 7224c889e0d5d70b99ae377036baa6377c33a568 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 11 Feb 2023 10:25:24 +0100 Subject: build: enable MSVC level 3 warnings (#21934) MSVC has 4 different warning levels: 1 (severe), 2 (significant), 3 (production quality) and 4 (informational). Enabling level 3 warnings mostly revealed conversion problems, similar to GCC/clang -Wconversion flag. --- src/nvim/CMakeLists.txt | 5 ++--- src/nvim/api/command.c | 4 ++-- src/nvim/api/options.c | 2 +- src/nvim/channel.c | 4 +++- src/nvim/diff.c | 14 ++++++------ src/nvim/drawline.c | 32 +++++++++++++-------------- src/nvim/eval.c | 56 +++++++++++++++++++++++------------------------ src/nvim/eval/funcs.c | 39 +++++++++++++++++---------------- src/nvim/eval/typval.c | 20 ++++++++--------- src/nvim/eval/vars.c | 2 +- src/nvim/eval/window.c | 4 ++-- src/nvim/ex_cmds.c | 2 +- src/nvim/ex_docmd.c | 8 +++---- src/nvim/fileio.c | 16 +++++++++----- src/nvim/getchar.c | 4 ++-- src/nvim/lua/stdlib.c | 14 ++++++------ src/nvim/lua/treesitter.c | 16 +++++++------- src/nvim/lua/xdiff.c | 4 ++-- src/nvim/main.c | 3 +++ src/nvim/mbyte.c | 4 ++-- src/nvim/memline.c | 2 +- src/nvim/ops.c | 2 +- src/nvim/option.c | 15 +++++++------ src/nvim/os/env.c | 6 ++++- src/nvim/os/fileio.c | 4 ++++ src/nvim/os/fs.c | 21 +++++++++--------- src/nvim/search.c | 2 +- src/nvim/statusline.c | 17 +++++++------- src/nvim/tui/tui.c | 10 +++++---- src/nvim/ui_client.c | 5 ++++- src/nvim/usercmd.c | 26 ++++++++++------------ src/nvim/usercmd.h | 2 +- 32 files changed, 192 insertions(+), 173 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 5953dd3ab9..7409a5e5c5 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -78,8 +78,7 @@ if(ENABLE_IWYU) endif() if(MSVC) - # TODO(dundargoc): bump warning level - target_compile_options(main_lib INTERFACE -W2) + target_compile_options(main_lib INTERFACE -W3) # Disable warnings that give too many false positives. target_compile_options(main_lib INTERFACE -wd4311 -wd4146) @@ -406,7 +405,7 @@ list(REMOVE_ITEM NVIM_SOURCES ${to_remove}) # xdiff, mpack, lua-cjson: inlined external project, we don't maintain it. #9306 if(MSVC) set_source_files_properties( - ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} /wd4090 /wd4244") + ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -wd4090 -wd4244 -wd4267") else() set_source_files_properties( ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion -Wno-strict-prototypes") diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index abd265f2cf..7e7df3ee0f 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -512,7 +512,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error } else if (cmd->count.type != kObjectTypeInteger || cmd->count.data.integer < 0) { VALIDATION_ERROR("'count' must be a non-negative Integer"); } - set_cmd_count(&ea, cmd->count.data.integer, true); + set_cmd_count(&ea, (linenr_T)cmd->count.data.integer, true); } if (HAS_KEY(cmd->reg)) { @@ -1005,7 +1005,7 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, Error *err) { uint32_t argt = 0; - long def = -1; + int64_t def = -1; cmd_addr_T addr_type_arg = ADDR_NONE; int compl = EXPAND_NOTHING; char *compl_arg = NULL; diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index bfcb99754f..2a54c3b132 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -181,7 +181,7 @@ void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error switch (value.type) { case kObjectTypeInteger: - numval = value.data.integer; + numval = (long)value.data.integer; break; case kObjectTypeBoolean: numval = value.data.boolean ? 1 : 0; diff --git a/src/nvim/channel.c b/src/nvim/channel.c index 65bb87bc2c..7f8e1c9fd1 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -32,12 +32,14 @@ #include "nvim/msgpack_rpc/server.h" #include "nvim/os/os_defs.h" #include "nvim/os/shell.h" +#include "nvim/path.h" #include "nvim/rbuffer.h" + #ifdef MSWIN +# include "nvim/os/fs.h" # include "nvim/os/os_win_console.h" # include "nvim/os/pty_conpty_win.h" #endif -#include "nvim/path.h" static bool did_stdio = false; diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 032de561b3..3bdc965146 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -3409,7 +3409,7 @@ static int parse_diff_ed(char *line, diffhunk_T *hunk) linenr_T f1 = getdigits_int32(&p, true, 0); if (*p == ',') { p++; - l1 = getdigits(&p, true, 0); + l1 = getdigits_long(&p, true, 0); } else { l1 = f1; } @@ -3417,10 +3417,10 @@ static int parse_diff_ed(char *line, diffhunk_T *hunk) return FAIL; // invalid diff format } int difftype = (uint8_t)(*p++); - long f2 = getdigits(&p, true, 0); + long f2 = getdigits_long(&p, true, 0); if (*p == ',') { p++; - l2 = getdigits(&p, true, 0); + l2 = getdigits_long(&p, true, 0); } else { l2 = f2; } @@ -3458,18 +3458,18 @@ static int parse_diff_unified(char *line, diffhunk_T *hunk) long oldcount; long newline; long newcount; - long oldline = getdigits(&p, true, 0); + long oldline = getdigits_long(&p, true, 0); if (*p == ',') { p++; - oldcount = getdigits(&p, true, 0); + oldcount = getdigits_long(&p, true, 0); } else { oldcount = 1; } if (*p++ == ' ' && *p++ == '+') { - newline = getdigits(&p, true, 0); + newline = getdigits_long(&p, true, 0); if (*p == ',') { p++; - newcount = getdigits(&p, true, 0); + newcount = getdigits_long(&p, true, 0); } else { newcount = 1; } diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 01ff207c2b..6de920b544 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -615,7 +615,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, foldinfo_T foldinfo, DecorProviders *providers, char **provider_err) { int c = 0; // init for GCC - long vcol = 0; // virtual column (for tabs) + colnr_T vcol = 0; // virtual column (for tabs) long vcol_sbr = -1; // virtual column after showbreak long vcol_prev = -1; // "vcol" of previous character char *line; // current line @@ -657,7 +657,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, bool noinvcur = false; // don't invert the cursor bool lnum_in_visual_area = false; pos_T pos; - long v; + ptrdiff_t v; int char_attr = 0; // attributes for next character bool attr_pri = false; // char_attr has priority @@ -798,7 +798,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // Check for columns to display for 'colorcolumn'. color_cols = wp->w_buffer->terminal ? NULL : wp->w_p_cc_cols; if (color_cols != NULL) { - draw_color_col = advance_color_col((int)VCOL_HLC, &color_cols); + draw_color_col = advance_color_col(VCOL_HLC, &color_cols); } if (wp->w_p_spell @@ -1075,7 +1075,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, chartabsize_T cts; int charsize; - init_chartabsize_arg(&cts, wp, lnum, (colnr_T)vcol, line, ptr); + init_chartabsize_arg(&cts, wp, lnum, vcol, line, ptr); while (cts.cts_vcol < v && *cts.cts_ptr != NUL) { charsize = win_lbr_chartabsize(&cts, NULL); cts.cts_vcol += charsize; @@ -1096,7 +1096,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, || draw_color_col || virtual_active() || (VIsual_active && wp->w_buffer == curwin->w_buffer))) { - vcol = v; + vcol = (colnr_T)v; } // Handle a character that's not completely on the screen: Put ptr at @@ -1116,7 +1116,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (tocol <= vcol) { fromcol = 0; } else if (fromcol >= 0 && fromcol < vcol) { - fromcol = (int)vcol; + fromcol = vcol; } // When w_skipcol is non-zero, first line needs 'showbreak' @@ -1473,7 +1473,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (has_decor && row == startrow + filler_lines) { // hide virt_text on text hidden by 'nowrap' - decor_redraw_col(wp->w_buffer, (int)vcol, off, true, &decor_state); + decor_redraw_col(wp->w_buffer, vcol, off, true, &decor_state); } if (saved_n_extra) { @@ -1570,7 +1570,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } } else if (area_attr != 0 && (vcol == tocol || (noinvcur - && (colnr_T)vcol == wp->w_virtcol))) { + && vcol == wp->w_virtcol))) { area_attr = 0; // stop highlighting area_active = false; } @@ -1875,7 +1875,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (has_decor && v > 0) { bool selected = (area_active || (area_highlighting && noinvcur - && (colnr_T)vcol == wp->w_virtcol)); + && vcol == wp->w_virtcol)); int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v - 1, off, selected, &decor_state); if (extmark_attr != 0) { @@ -1984,7 +1984,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, char *p = ptr - (mb_off + 1); chartabsize_T cts; - init_chartabsize_arg(&cts, wp, lnum, (colnr_T)vcol, line, p); + init_chartabsize_arg(&cts, wp, lnum, vcol, line, p); n_extra = win_lbr_chartabsize(&cts, NULL) - 1; // We have just drawn the showbreak value, no need to add @@ -2003,7 +2003,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } if (c == TAB && n_extra + col > grid->cols) { - n_extra = tabstop_padding((colnr_T)vcol, wp->w_buffer->b_p_ts, + n_extra = tabstop_padding(vcol, wp->w_buffer->b_p_ts, wp->w_buffer->b_p_vts_array) - 1; } c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' '; @@ -2203,7 +2203,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, && (wp->w_p_rl ? (col >= 0) : (col < grid->cols)) && !(noinvcur && lnum == wp->w_cursor.lnum - && (colnr_T)vcol == wp->w_virtcol))) + && vcol == wp->w_virtcol))) && lcs_eol_one > 0) { // Display a '$' after the line or highlight an extra // character if the line break is included. @@ -2456,7 +2456,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // check if line ends before left margin if (vcol < v + col - win_col_off(wp)) { - vcol = v + col - win_col_off(wp); + vcol = (colnr_T)v + col - win_col_off(wp); } // Get rid of the boguscols now, we want to draw until the right // edge for 'cursorcolumn'. @@ -2464,7 +2464,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // boguscols = 0; // Disabled because value never read after this if (draw_color_col) { - draw_color_col = advance_color_col((int)VCOL_HLC, &color_cols); + draw_color_col = advance_color_col(VCOL_HLC, &color_cols); } bool has_virttext = false; @@ -2523,7 +2523,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, schar_from_ascii(linebuf_char[off], ' '); col += col_stride; if (draw_color_col) { - draw_color_col = advance_color_col((int)VCOL_HLC, &color_cols); + draw_color_col = advance_color_col(VCOL_HLC, &color_cols); } int col_attr = base_attr; @@ -2597,7 +2597,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // advance to the next 'colorcolumn' if (draw_color_col) { - draw_color_col = advance_color_col((int)VCOL_HLC, &color_cols); + draw_color_col = advance_color_col(VCOL_HLC, &color_cols); } // Highlight the cursor column if 'cursorcolumn' is set. But don't diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 4de4b7a080..edbeabc53d 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -3276,7 +3276,7 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose) { bool empty1 = false; bool empty2 = false; - long n1, n2 = 0; + int n1, n2 = 0; ptrdiff_t len = -1; int range = false; char *key = NULL; @@ -3375,14 +3375,14 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose) if (evaluate) { n1 = 0; if (!empty1 && rettv->v_type != VAR_DICT && !tv_is_luafunc(rettv)) { - n1 = tv_get_number(&var1); + n1 = (int)tv_get_number(&var1); tv_clear(&var1); } if (range) { if (empty2) { n2 = -1; } else { - n2 = tv_get_number(&var2); + n2 = (int)tv_get_number(&var2); tv_clear(&var2); } } @@ -3397,15 +3397,15 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose) // The resulting variable is a substring. If the indexes // are out of range the result is empty. if (n1 < 0) { - n1 = len + n1; + n1 = (int)len + n1; if (n1 < 0) { n1 = 0; } } if (n2 < 0) { - n2 = len + n2; + n2 = (int)len + n2; } else if (n2 >= len) { - n2 = len; + n2 = (int)len; } if (n1 >= len || n2 < 0 || n1 > n2) { v = NULL; @@ -3433,15 +3433,15 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose) // The resulting variable is a sub-blob. If the indexes // are out of range the result is empty. if (n1 < 0) { - n1 = len + n1; + n1 = (int)len + n1; if (n1 < 0) { n1 = 0; } } if (n2 < 0) { - n2 = len + n2; + n2 = (int)len + n2; } else if (n2 >= len) { - n2 = len - 1; + n2 = (int)len - 1; } if (n1 >= len || n2 < 0 || n1 > n2) { tv_clear(rettv); @@ -3449,8 +3449,8 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose) rettv->vval.v_blob = NULL; } else { blob_T *const blob = tv_blob_alloc(); - ga_grow(&blob->bv_ga, (int)(n2 - n1 + 1)); - blob->bv_ga.ga_len = (int)(n2 - n1 + 1); + ga_grow(&blob->bv_ga, n2 - n1 + 1); + blob->bv_ga.ga_len = n2 - n1 + 1; for (long i = n1; i <= n2; i++) { tv_blob_set(blob, (int)(i - n1), tv_blob_get(rettv->vval.v_blob, (int)i)); } @@ -3461,10 +3461,10 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose) // The resulting variable is a byte value. // If the index is too big or negative that is an error. if (n1 < 0) { - n1 = len + n1; + n1 = (int)len + n1; } if (n1 < len && n1 >= 0) { - const int v = (int)tv_blob_get(rettv->vval.v_blob, (int)n1); + const int v = (int)tv_blob_get(rettv->vval.v_blob, n1); tv_clear(rettv); rettv->v_type = VAR_NUMBER; rettv->vval.v_number = v; @@ -3476,7 +3476,7 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose) case VAR_LIST: len = tv_list_len(rettv->vval.v_list); if (n1 < 0) { - n1 = len + n1; + n1 = (int)len + n1; } if (!empty1 && (n1 < 0 || n1 >= len)) { // For a range we allow invalid values and return an empty @@ -3487,22 +3487,22 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose) } return FAIL; } - n1 = len; + n1 = (int)len; } if (range) { list_T *l; listitem_T *item; if (n2 < 0) { - n2 = len + n2; + n2 = (int)len + n2; } else if (n2 >= len) { - n2 = len - 1; + n2 = (int)len - 1; } if (!empty2 && (n2 < 0 || n2 + 1 < n1)) { n2 = -1; } l = tv_list_alloc(n2 - n1 + 1); - item = tv_list_find(rettv->vval.v_list, (int)n1); + item = tv_list_find(rettv->vval.v_list, n1); while (n1++ <= n2) { tv_list_append_tv(l, TV_LIST_ITEM_TV(item)); item = TV_LIST_ITEM_NEXT(rettv->vval.v_list, item); @@ -6220,25 +6220,25 @@ int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, bool c } int i = 0; - long n; + int n; if (fnump != NULL) { - n = tv_list_find_nr(l, i++, NULL); // fnum + n = (int)tv_list_find_nr(l, i++, NULL); // fnum if (n < 0) { return FAIL; } if (n == 0) { n = curbuf->b_fnum; // Current buffer. } - *fnump = (int)n; + *fnump = n; } - n = tv_list_find_nr(l, i++, NULL); // lnum + n = (int)tv_list_find_nr(l, i++, NULL); // lnum if (n < 0) { return FAIL; } - posp->lnum = (linenr_T)n; + posp->lnum = n; - n = tv_list_find_nr(l, i++, NULL); // col + n = (int)tv_list_find_nr(l, i++, NULL); // col if (n < 0) { return FAIL; } @@ -6252,15 +6252,15 @@ int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, bool c } n = buf_charidx_to_byteidx(buf, posp->lnum == 0 ? curwin->w_cursor.lnum : posp->lnum, - (int)n) + 1; + n) + 1; } - posp->col = (colnr_T)n; + posp->col = n; - n = tv_list_find_nr(l, i, NULL); // off + n = (int)tv_list_find_nr(l, i, NULL); // off if (n < 0) { posp->coladd = 0; } else { - posp->coladd = (colnr_T)n; + posp->coladd = n; } if (curswantp != NULL) { diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 48f3cd4293..884a50a433 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -492,7 +492,7 @@ buf_T *get_buf_arg(typval_T *arg) /// "byte2line(byte)" function static void f_byte2line(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - long boff = tv_get_number(&argvars[0]) - 1; + long boff = (long)tv_get_number(&argvars[0]) - 1; if (boff < 0) { rettv->vval.v_number = -1; } else { @@ -978,11 +978,11 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) listitem_T *li = tv_list_first(l); if (argvars[2].v_type != VAR_UNKNOWN) { if (argvars[3].v_type != VAR_UNKNOWN) { - long idx = tv_get_number_chk(&argvars[3], &error); + int64_t idx = tv_get_number_chk(&argvars[3], &error); if (!error) { li = tv_list_find(l, (int)idx); if (li == NULL) { - semsg(_(e_listidx), (int64_t)idx); + semsg(_(e_listidx), idx); } } } @@ -3589,7 +3589,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) semsg(_(e_listblobarg), "insert()"); } else if (!value_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), N_("insert() argument"), TV_TRANSLATE)) { - long before = 0; + int64_t before = 0; if (argvars[2].v_type != VAR_UNKNOWN) { before = tv_get_number_chk(&argvars[2], &error); } @@ -3602,7 +3602,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (before != tv_list_len(l)) { item = tv_list_find(l, (int)before); if (item == NULL) { - semsg(_(e_listidx), (int64_t)before); + semsg(_(e_listidx), before); l = NULL; } } @@ -4371,11 +4371,11 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, const SomeMatchType type) { char *str = NULL; - long len = 0; + int64_t len = 0; char *expr = NULL; regmatch_T regmatch; - long start = 0; - long nth = 1; + int64_t start = 0; + int64_t nth = 1; colnr_T startcol = 0; bool match = false; list_T *l = NULL; @@ -5387,7 +5387,7 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl char *prev = NULL; // previously read bytes, if any ptrdiff_t prevlen = 0; // length of data in prev ptrdiff_t prevsize = 0; // size of prev buffer - long maxline = MAXLNUM; + int64_t maxline = MAXLNUM; if (argvars[1].v_type != VAR_UNKNOWN) { if (strcmp(tv_get_string(&argvars[1]), "b") == 0) { @@ -6161,8 +6161,8 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) { bool save_p_ws = p_ws; int retval = 0; // default: FAIL - long lnum_stop = 0; - long time_limit = 0; + linenr_T lnum_stop = 0; + int64_t time_limit = 0; int options = SEARCH_KEEP; bool use_skip = false; @@ -6184,7 +6184,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) // Optional arguments: line number to stop searching, timeout and skip. if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) { - lnum_stop = tv_get_number_chk(&argvars[2], NULL); + lnum_stop = (linenr_T)tv_get_number_chk(&argvars[2], NULL); if (lnum_stop < 0) { goto theend; } @@ -6214,7 +6214,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) pos_T pos = save_cursor = curwin->w_cursor; pos_T firstpos = { 0 }; searchit_arg_T sia = { - .sa_stop_lnum = (linenr_T)lnum_stop, + .sa_stop_lnum = lnum_stop, .sa_tm = &tm, }; @@ -6652,8 +6652,8 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) bool save_p_ws = p_ws; int flags = 0; int retval = 0; // default: FAIL - long lnum_stop = 0; - long time_limit = 0; + linenr_T lnum_stop = 0; + int64_t time_limit = 0; // Get the three pattern arguments: start, middle, end. Will result in an // error if not a valid argument. @@ -6695,7 +6695,7 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) skip = &argvars[4]; if (argvars[5].v_type != VAR_UNKNOWN) { - lnum_stop = tv_get_number_chk(&argvars[5], NULL); + lnum_stop = (linenr_T)tv_get_number_chk(&argvars[5], NULL); if (lnum_stop < 0) { semsg(_(e_invarg2), tv_get_string(&argvars[5])); goto theend; @@ -6711,7 +6711,7 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) } retval = (int)do_searchpair(spat, mpat, epat, dir, skip, - flags, match_pos, (linenr_T)lnum_stop, time_limit); + flags, match_pos, lnum_stop, time_limit); theend: p_ws = save_p_ws; @@ -6758,7 +6758,7 @@ static void f_searchpairpos(typval_T *argvars, typval_T *rettv, EvalFuncData fpt /// @returns 0 or -1 for no match, long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir, const typval_T *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, - long time_limit) + int64_t time_limit) FUNC_ATTR_NONNULL_ARG(1, 2, 3) { long retval = 0; @@ -8695,7 +8695,8 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (!callback_from_typval(&callback, &argvars[1])) { return; } - rettv->vval.v_number = (varnumber_T)timer_start(tv_get_number(&argvars[0]), repeat, &callback); + rettv->vval.v_number = (varnumber_T)timer_start((const long)tv_get_number(&argvars[0]), repeat, + &callback); } /// "timer_stop(timerid)" function diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index c298064d86..6d1c17c97e 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -905,14 +905,14 @@ void tv_list_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) return; } - long idx = tv_get_number_chk(&argvars[1], &error); + int64_t idx = tv_get_number_chk(&argvars[1], &error); listitem_T *item; if (error) { // Type error: do nothing, errmsg already given. } else if ((item = tv_list_find(l, (int)idx)) == NULL) { - semsg(_(e_listidx), (int64_t)idx); + semsg(_(e_listidx), idx); } else { if (argvars[2].v_type == VAR_UNKNOWN) { // Remove one item, return its value. @@ -922,11 +922,11 @@ void tv_list_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) } else { listitem_T *item2; // Remove range of items, return list with values. - long end = tv_get_number_chk(&argvars[2], &error); + int64_t end = tv_get_number_chk(&argvars[2], &error); if (error) { // Type error: do nothing. } else if ((item2 = tv_list_find(l, (int)end)) == NULL) { - semsg(_(e_listidx), (int64_t)end); + semsg(_(e_listidx), end); } else { int cnt = 0; @@ -1140,7 +1140,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) { ListSortItem *ptrs; long len; - long i; + int i; // Pointer to current info struct used in compare function. Save and restore // the current one for nested calls. @@ -1184,7 +1184,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) } else { bool error = false; - i = tv_get_number_chk(&argvars[1], &error); + i = (int)tv_get_number_chk(&argvars[1], &error); if (error) { goto theend; // type error; errmsg already given } @@ -2715,7 +2715,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) } bool error = false; - long idx = tv_get_number_chk(&argvars[1], &error); + int64_t idx = tv_get_number_chk(&argvars[1], &error); if (!error) { const int len = tv_blob_len(b); @@ -2725,7 +2725,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) idx = len + idx; } if (idx < 0 || idx >= len) { - semsg(_(e_blobidx), (int64_t)idx); + semsg(_(e_blobidx), idx); return; } if (argvars[2].v_type == VAR_UNKNOWN) { @@ -2736,7 +2736,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) b->bv_ga.ga_len--; } else { // Remove range of items, return blob with values. - long end = tv_get_number_chk(&argvars[2], &error); + int64_t end = tv_get_number_chk(&argvars[2], &error); if (error) { return; } @@ -2745,7 +2745,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) end = len + end; } if (end >= len || idx > end) { - semsg(_(e_blobidx), (int64_t)end); + semsg(_(e_blobidx), end); return; } blob_T *const blob = tv_blob_alloc(); diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 9ed245d6c4..3d9b476863 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -696,7 +696,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo if (!failed) { if (opt_type != gov_string || s != NULL) { - char *err = set_option_value(arg, n, s, scope); + char *err = set_option_value(arg, (long)n, s, scope); arg_end = p; if (err != NULL) { emsg(_(err)); diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index f58a0c488a..c1d2e5b38f 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -192,9 +192,9 @@ win_T *find_tabwin(typval_T *wvp, typval_T *tvp) if (wvp->v_type != VAR_UNKNOWN) { if (tvp->v_type != VAR_UNKNOWN) { - long n = tv_get_number(tvp); + int n = (int)tv_get_number(tvp); if (n >= 0) { - tp = find_tabpage((int)n); + tp = find_tabpage(n); } } else { tp = curtab; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index da78861d87..036e34431b 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2939,7 +2939,7 @@ void ex_z(exarg_T *eap) bigness = 2 * curbuf->b_ml.ml_line_count; } - p_window = bigness; + p_window = (int)bigness; if (*kind == '=') { bigness += 2; } diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 017787f238..8440c45a9c 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1311,16 +1311,16 @@ static void parse_register(exarg_T *eap) } // Change line1 and line2 of Ex command to use count -void set_cmd_count(exarg_T *eap, long count, bool validate) +void set_cmd_count(exarg_T *eap, linenr_T count, bool validate) { if (eap->addr_type != ADDR_LINES) { // e.g. :buffer 2, :sleep 3 - eap->line2 = (linenr_T)count; + eap->line2 = count; if (eap->addr_count == 0) { eap->addr_count = 1; } } else { eap->line1 = eap->line2; - eap->line2 += (linenr_T)count - 1; + eap->line2 += count - 1; eap->addr_count++; // Be vi compatible: no error message for out of range. if (validate && eap->line2 > curbuf->b_ml.ml_line_count) { @@ -1338,7 +1338,7 @@ static int parse_count(exarg_T *eap, char **errormsg, bool validate) if ((eap->argt & EX_COUNT) && ascii_isdigit(*eap->arg) && (!(eap->argt & EX_BUFNAME) || *(p = skipdigits(eap->arg + 1)) == NUL || ascii_iswhite(*p))) { - long n = getdigits_long(&eap->arg, false, -1); + linenr_T n = getdigits_int32(&eap->arg, false, -1); eap->arg = skipwhite(eap->arg); if (eap->args != NULL) { diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index fbb5c4f1fa..8c904f0c0a 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -64,6 +64,10 @@ #include "nvim/undo.h" #include "nvim/vim.h" +#ifdef BACKSLASH_IN_FILENAME +# include "nvim/charset.h" +#endif + #if defined(HAVE_FLOCK) && defined(HAVE_DIRFD) # include # include @@ -207,7 +211,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, char *line_start = NULL; // init to shut up gcc int wasempty; // buffer was empty before reading colnr_T len; - long size = 0; + ptrdiff_t size = 0; uint8_t *p = NULL; off_T filesize = 0; bool skip_read = false; @@ -217,7 +221,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip, linenr_T linecnt; bool error = false; // errors encountered int ff_error = EOL_UNKNOWN; // file format with errors - long linerest = 0; // remaining chars in line + ptrdiff_t linerest = 0; // remaining chars in line int perm = 0; #ifdef UNIX int swap_mode = -1; // protection bits for swap file @@ -1079,7 +1083,7 @@ retry: if (size < 2 || curbuf->b_p_bin) { ccname = NULL; } else { - ccname = check_for_bom(ptr, size, &blen, + ccname = check_for_bom(ptr, (int)size, &blen, fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags(fenc)); } if (ccname != NULL) { @@ -4038,7 +4042,7 @@ static int get_fio_flags(const char *name) /// /// @return the name of the encoding and set "*lenp" to the length or, /// NULL when no BOM found. -static char *check_for_bom(const char *p_in, long size, int *lenp, int flags) +static char *check_for_bom(const char *p_in, int size, int *lenp, int flags) { const uint8_t *p = (const uint8_t *)p_in; char *name = NULL; @@ -5630,7 +5634,7 @@ long read_eintr(int fd, void *buf, size_t bufsize) long ret; for (;;) { - ret = read(fd, buf, bufsize); + ret = read(fd, buf, (unsigned int)bufsize); if (ret >= 0 || errno != EINTR) { break; } @@ -5647,7 +5651,7 @@ long write_eintr(int fd, void *buf, size_t bufsize) // Repeat the write() so long it didn't fail, other than being interrupted // by a signal. while (ret < (long)bufsize) { - long wlen = write(fd, (char *)buf + ret, bufsize - (size_t)ret); + long wlen = write(fd, (char *)buf + ret, (unsigned int)(bufsize - (size_t)ret)); if (wlen < 0) { if (errno != EINTR) { break; diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index ca00c5b449..387139fd29 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -582,7 +582,7 @@ void stuffRedoReadbuff(const char *s) add_buff(&readbuf2, s, -1L); } -void stuffReadbuffLen(const char *s, long len) +void stuffReadbuffLen(const char *s, ptrdiff_t len) { add_buff(&readbuf1, s, len); } @@ -634,7 +634,7 @@ void stuffescaped(const char *arg, bool literally) arg++; } if (arg > start) { - stuffReadbuffLen(start, (arg - start)); + stuffReadbuffLen(start, arg - start); } // stuff a single special character diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c index 6ebca6d97e..73246f81b7 100644 --- a/src/nvim/lua/stdlib.c +++ b/src/nvim/lua/stdlib.c @@ -78,20 +78,20 @@ static int regex_match_line(lua_State *lstate) return luaL_error(lstate, "not enough args"); } - long bufnr = luaL_checkinteger(lstate, 2); + handle_T bufnr = (handle_T)luaL_checkinteger(lstate, 2); linenr_T rownr = (linenr_T)luaL_checkinteger(lstate, 3); - long start = 0, end = -1; + int start = 0, end = -1; if (narg >= 4) { - start = luaL_checkinteger(lstate, 4); + start = (int)luaL_checkinteger(lstate, 4); } if (narg >= 5) { - end = luaL_checkinteger(lstate, 5); + end = (int)luaL_checkinteger(lstate, 5); if (end < 0) { return luaL_error(lstate, "invalid end"); } } - buf_T *buf = bufnr ? handle_get_buffer((int)bufnr) : curbuf; + buf_T *buf = bufnr ? handle_get_buffer(bufnr) : curbuf; if (!buf || buf->b_ml.ml_mfp == NULL) { return luaL_error(lstate, "invalid buffer"); } @@ -218,7 +218,7 @@ static int nlua_str_utf_start(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL { size_t s1_len; const char *s1 = luaL_checklstring(lstate, 1, &s1_len); - long offset = luaL_checkinteger(lstate, 2); + ptrdiff_t offset = luaL_checkinteger(lstate, 2); if (offset < 0 || offset > (intptr_t)s1_len) { return luaL_error(lstate, "index out of range"); } @@ -238,7 +238,7 @@ static int nlua_str_utf_end(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL { size_t s1_len; const char *s1 = luaL_checklstring(lstate, 1, &s1_len); - long offset = luaL_checkinteger(lstate, 2); + ptrdiff_t offset = luaL_checkinteger(lstate, 2); if (offset < 0 || offset > (intptr_t)s1_len) { return luaL_error(lstate, "index out of range"); } diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 56f4daed1a..5248ebed14 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -393,7 +393,7 @@ static int parser_parse(lua_State *L) TSTree *new_tree = NULL; size_t len; const char *str; - long bufnr; + handle_T bufnr; buf_T *buf; TSInput input; @@ -406,13 +406,13 @@ static int parser_parse(lua_State *L) break; case LUA_TNUMBER: - bufnr = lua_tointeger(L, 3); - buf = handle_get_buffer((handle_T)bufnr); + bufnr = (handle_T)lua_tointeger(L, 3); + buf = handle_get_buffer(bufnr); if (!buf) { #define BUFSIZE 256 char ebuf[BUFSIZE] = { 0 }; - vim_snprintf(ebuf, BUFSIZE, "invalid buffer handle: %ld", bufnr); + vim_snprintf(ebuf, BUFSIZE, "invalid buffer handle: %d", bufnr); return luaL_argerror(L, 3, ebuf); #undef BUFSIZE } @@ -898,8 +898,8 @@ static int node_child(lua_State *L) if (!node_check(L, 1, &node)) { return 0; } - long num = lua_tointeger(L, 2); - TSNode child = ts_node_child(node, (uint32_t)num); + uint32_t num = (uint32_t)lua_tointeger(L, 2); + TSNode child = ts_node_child(node, num); push_node(L, child, 1); return 1; @@ -911,8 +911,8 @@ static int node_named_child(lua_State *L) if (!node_check(L, 1, &node)) { return 0; } - long num = lua_tointeger(L, 2); - TSNode child = ts_node_named_child(node, (uint32_t)num); + uint32_t num = (uint32_t)lua_tointeger(L, 2); + TSNode child = ts_node_named_child(node, num); push_node(L, child, 1); return 1; diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c index 857b159af5..9a7ae5c146 100644 --- a/src/nvim/lua/xdiff.c +++ b/src/nvim/lua/xdiff.c @@ -257,13 +257,13 @@ static NluaXdiffMode process_xdl_diff_opts(lua_State *lstate, xdemitconf_t *cfg, if (check_xdiff_opt(v->type, kObjectTypeInteger, "ctxlen", err)) { goto exit_1; } - cfg->ctxlen = v->data.integer; + cfg->ctxlen = (long)v->data.integer; } else if (strequal("interhunkctxlen", k.data)) { if (check_xdiff_opt(v->type, kObjectTypeInteger, "interhunkctxlen", err)) { goto exit_1; } - cfg->interhunkctxlen = v->data.integer; + cfg->interhunkctxlen = (long)v->data.integer; } else if (strequal("linematch", k.data)) { *linematch = api_object_to_bool(*v, "linematch", false, err); if (ERROR_SET(err)) { diff --git a/src/nvim/main.c b/src/nvim/main.c index 2bbe70784d..f37c43d8c1 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -182,6 +182,9 @@ void early_init(mparm_T *paramp) #ifdef MSWIN OSVERSIONINFO ovi; ovi.dwOSVersionInfoSize = sizeof(ovi); + // Disable warning about GetVersionExA being deprecated. There doesn't seem to be a conventient + // replacement that doesn't add a ton of extra code as of writing this. +# pragma warning(suppress : 4996) GetVersionEx(&ovi); snprintf(windowsVersion, sizeof(windowsVersion), "%d.%d", (int)ovi.dwMajorVersion, (int)ovi.dwMinorVersion); diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 1cc3198216..2f1724369c 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -2613,8 +2613,8 @@ char *string_convert_ext(const vimconv_T *const vcp, char *ptr, size_t *lenp, si /// Table set by setcellwidths(). typedef struct { - long first; - long last; + int64_t first; + int64_t last; char width; } cw_interval_T; diff --git a/src/nvim/memline.c b/src/nvim/memline.c index dfca19aa96..2a4e0f7377 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -307,7 +307,7 @@ int ml_open(buf_T *buf) b0p->b0_uname[B0_UNAME_SIZE - 1] = NUL; os_get_hostname((char *)b0p->b0_hname, B0_HNAME_SIZE); b0p->b0_hname[B0_HNAME_SIZE - 1] = NUL; - long_to_char(os_get_pid(), b0p->b0_pid); + long_to_char((long)os_get_pid(), b0p->b0_pid); } // Always sync block number 0 to disk, so we can check the file name in diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 6326130c5a..f5f1a456f6 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -4127,7 +4127,7 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions linenr_T lnum = curwin->w_cursor.lnum + t; colnr_T mincol = (colnr_T)0; linenr_T lnum_amount = -t; - long col_amount = (cend - newp - spaces_removed); + colnr_T col_amount = (colnr_T)(cend - newp - spaces_removed); mark_col_adjust(lnum, mincol, lnum_amount, col_amount, spaces_removed); diff --git a/src/nvim/option.c b/src/nvim/option.c index 066ca8f003..32c2dc5286 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -30,7 +30,9 @@ #include #include "auto/config.h" +#include "nvim/api/extmark.h" #include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" @@ -61,6 +63,7 @@ #include "nvim/keycodes.h" #include "nvim/locale.h" #include "nvim/log.h" +#include "nvim/lua/executor.h" #include "nvim/macros.h" #include "nvim/mapping.h" #include "nvim/mbyte.h" @@ -75,6 +78,8 @@ #include "nvim/option.h" #include "nvim/option_defs.h" #include "nvim/optionstr.h" +#include "nvim/os/input.h" +#include "nvim/os/lang.h" #include "nvim/os/os.h" #include "nvim/path.h" #include "nvim/popupmenu.h" @@ -95,14 +100,10 @@ #include "nvim/undo.h" #include "nvim/vim.h" #include "nvim/window.h" -#ifdef MSWIN -# include "nvim/os/pty_conpty_win.h" + +#ifdef BACKSLASH_IN_FILENAME +# include "nvim/arglist.h" #endif -#include "nvim/api/extmark.h" -#include "nvim/api/private/helpers.h" -#include "nvim/lua/executor.h" -#include "nvim/os/input.h" -#include "nvim/os/lang.h" static char e_unknown_option[] = N_("E518: Unknown option"); diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 0611de14aa..30092b9142 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -34,7 +34,11 @@ #include "nvim/vim.h" #ifdef MSWIN -# include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8 +# include "nvim/mbyte.h" +#endif + +#ifdef BACKSLASH_IN_FILENAME +# include "nvim/fileio.h" #endif #ifdef HAVE__NSGETENVIRON diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c index 5af39555c9..846219f720 100644 --- a/src/nvim/os/fileio.c +++ b/src/nvim/os/fileio.c @@ -27,6 +27,10 @@ #include "nvim/rbuffer.h" #include "nvim/types.h" +#ifdef MSWIN +# include "nvim/os/os_win_console.h" +#endif + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/fileio.c.generated.h" #endif diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 6157341ec9..85d95960a7 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -12,14 +12,20 @@ #include #include #include +#include #include "auto/config.h" +#include "nvim/ascii.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/log.h" #include "nvim/macros.h" +#include "nvim/memory.h" +#include "nvim/message.h" #include "nvim/option_defs.h" #include "nvim/os/fs_defs.h" +#include "nvim/os/os.h" +#include "nvim/path.h" #include "nvim/types.h" #include "nvim/vim.h" @@ -27,24 +33,17 @@ # include #endif -#include - -#include "nvim/ascii.h" -#include "nvim/memory.h" -#include "nvim/message.h" -#include "nvim/os/os.h" -#include "nvim/path.h" - -struct iovec; - #ifdef MSWIN -# include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8 +# include "nvim/mbyte.h" +# include "nvim/option.h" #endif #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/fs.c.generated.h" #endif +struct iovec; + #define RUN_UV_FS_FUNC(ret, func, ...) \ do { \ bool did_try_to_free = false; \ diff --git a/src/nvim/search.c b/src/nvim/search.c index eb5cc2e07f..234ffb75cb 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -1031,7 +1031,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, long count, i struct soffset old_off; int retval; // Return value char *p; - long c; + int64_t c; char *dircp; char *strcopy = NULL; char *ps; diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 6ad1f31143..9552f3f42b 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -1,6 +1,5 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// #include #include @@ -1390,7 +1389,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n NumberBase base = kNumBaseDecimal; bool itemisflag = false; bool fillable = true; - long num = -1; + int num = -1; char *str = NULL; switch (opt) { case STL_FILEPATH: @@ -1520,10 +1519,10 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n // Overload %l with v:lnum for 'statuscolumn' if (opt_name != NULL && strcmp(opt_name, "statuscolumn") == 0) { if (wp->w_p_nu && !get_vim_var_nr(VV_VIRTNUM)) { - num = get_vim_var_nr(VV_LNUM); + num = (int)get_vim_var_nr(VV_LNUM); } } else { - num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? 0L : (long)(wp->w_cursor.lnum); + num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? 0L : wp->w_cursor.lnum; } break; @@ -1544,7 +1543,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n ? 0 : (int)wp->w_cursor.col + 1))) { break; } - num = (long)virtcol; + num = virtcol; break; } @@ -1604,8 +1603,8 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n long l = ml_find_line_or_offset(wp->w_buffer, wp->w_cursor.lnum, NULL, false); num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) || l < 0 ? - 0L : l + 1 + ((State & MODE_INSERT) == 0 && empty_line ? - 0 : (int)wp->w_cursor.col); + 0L : (int)l + 1 + ((State & MODE_INSERT) == 0 && empty_line ? + 0 : (int)wp->w_cursor.col); break; } case STL_BYTEVAL_X: @@ -1625,7 +1624,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n // Overload %r with v:relnum for 'statuscolumn' if (opt_name != NULL && strcmp(opt_name, "statuscolumn") == 0) { if (wp->w_p_rnu && !get_vim_var_nr(VV_VIRTNUM)) { - num = get_vim_var_nr(VV_RELNUM); + num = (int)get_vim_var_nr(VV_RELNUM); } } else { itemisflag = true; @@ -1889,7 +1888,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n // { Reduce the number by base^n while (num_chars-- > maxwid) { - num /= (long)base; + num /= (int)base; } // } diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index fff5c865bf..9415917e34 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -34,15 +34,17 @@ #include "nvim/msgpack_rpc/channel.h" #include "nvim/os/input.h" #include "nvim/os/os.h" -#include "nvim/ui_client.h" -#ifdef MSWIN -# include "nvim/os/os_win_console.h" -#endif #include "nvim/tui/input.h" #include "nvim/tui/terminfo.h" #include "nvim/tui/tui.h" #include "nvim/ugrid.h" #include "nvim/ui.h" +#include "nvim/ui_client.h" + +#ifdef MSWIN +# include "nvim/os/os_win_console.h" +# include "nvim/os/tty.h" +#endif // Space reserved in two output buffers to make the cursor normal or invisible // when flushing. No existing terminal will require 32 bytes to do that. diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 58edd7aff3..a7a85bf61f 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -22,6 +22,10 @@ #include "nvim/ui.h" #include "nvim/ui_client.h" +#ifdef MSWIN +# include "nvim/os/os_win_console.h" +#endif + static TUIData *tui = NULL; static bool ui_client_is_remote = false; @@ -31,7 +35,6 @@ static bool ui_client_is_remote = false; # include "ui_events_client.generated.h" #endif // uncrustify:on -// uint64_t ui_client_start_server(int argc, char **argv) { diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c index ef13f67e49..c6f1a8faba 100644 --- a/src/nvim/usercmd.c +++ b/src/nvim/usercmd.c @@ -531,15 +531,13 @@ static void uc_list(char *name, size_t name_len) if (a & (EX_RANGE | EX_COUNT)) { if (a & EX_COUNT) { // -count=N - snprintf(IObuff + len, IOSIZE, "%" PRId64 "c", - (int64_t)cmd->uc_def); + snprintf(IObuff + len, IOSIZE, "%" PRId64 "c", cmd->uc_def); len += (int)strlen(IObuff + len); } else if (a & EX_DFLALL) { IObuff[len++] = '%'; } else if (cmd->uc_def >= 0) { // -range=N - snprintf(IObuff + len, IOSIZE, "%" PRId64 "", - (int64_t)cmd->uc_def); + snprintf(IObuff + len, IOSIZE, "%" PRId64 "", cmd->uc_def); len += (int)strlen(IObuff + len); } else { IObuff[len++] = '.'; @@ -862,9 +860,9 @@ char *uc_validate_name(char *name) /// This function takes ownership of compl_arg, compl_luaref, and luaref. /// /// @return OK if the command is created, FAIL otherwise. -int uc_add_command(char *name, size_t name_len, const char *rep, uint32_t argt, long def, int flags, - int compl, char *compl_arg, LuaRef compl_luaref, LuaRef preview_luaref, - cmd_addr_T addr_type, LuaRef luaref, bool force) +int uc_add_command(char *name, size_t name_len, const char *rep, uint32_t argt, int64_t def, + int flags, int compl, char *compl_arg, LuaRef compl_luaref, + LuaRef preview_luaref, cmd_addr_T addr_type, LuaRef luaref, bool force) FUNC_ATTR_NONNULL_ARG(1, 3) { ucmd_T *cmd = NULL; @@ -1540,13 +1538,13 @@ static size_t uc_check_code(char *code, size_t len, char *buf, ucmd_T *cmd, exar case ct_RANGE: case ct_COUNT: { char num_buf[20]; - long num = (type == ct_LINE1) ? eap->line1 : - (type == ct_LINE2) ? eap->line2 : - (type == ct_RANGE) ? eap->addr_count : - (eap->addr_count > 0) ? eap->line2 : cmd->uc_def; + int64_t num = (type == ct_LINE1) ? eap->line1 : + (type == ct_LINE2) ? eap->line2 : + (type == ct_RANGE) ? eap->addr_count : + (eap->addr_count > 0) ? eap->line2 : cmd->uc_def; size_t num_len; - snprintf(num_buf, sizeof(num_buf), "%" PRId64, (int64_t)num); + snprintf(num_buf, sizeof(num_buf), "%" PRId64, num); num_len = strlen(num_buf); result = num_len; @@ -1783,7 +1781,7 @@ Dictionary commands_array(buf_T *buf) Object obj = NIL; if (cmd->uc_argt & EX_COUNT) { if (cmd->uc_def >= 0) { - snprintf(str, sizeof(str), "%" PRId64, (int64_t)cmd->uc_def); + snprintf(str, sizeof(str), "%" PRId64, cmd->uc_def); obj = STRING_OBJ(cstr_to_string(str)); // -count=N } else { obj = STRING_OBJ(cstr_to_string("0")); // -count @@ -1796,7 +1794,7 @@ Dictionary commands_array(buf_T *buf) if (cmd->uc_argt & EX_DFLALL) { obj = STRING_OBJ(cstr_to_string("%")); // -range=% } else if (cmd->uc_def >= 0) { - snprintf(str, sizeof(str), "%" PRId64, (int64_t)cmd->uc_def); + snprintf(str, sizeof(str), "%" PRId64, cmd->uc_def); obj = STRING_OBJ(cstr_to_string(str)); // -range=N } else { obj = STRING_OBJ(cstr_to_string(".")); // -range diff --git a/src/nvim/usercmd.h b/src/nvim/usercmd.h index b6bf6c1e33..0d9838abf2 100644 --- a/src/nvim/usercmd.h +++ b/src/nvim/usercmd.h @@ -12,7 +12,7 @@ typedef struct ucmd { char *uc_name; // The command name uint32_t uc_argt; // The argument type char *uc_rep; // The command's replacement string - long uc_def; // The default value for a range/count + int64_t uc_def; // The default value for a range/count int uc_compl; // completion type cmd_addr_T uc_addr_type; // The command's address type sctx_T uc_script_ctx; // SCTX where the command was defined -- cgit From 4be6c6cf0ddf5e31d4103cb5df06651ba6f4897b Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 11 Feb 2023 11:05:57 +0100 Subject: refactor: replace char_u with char (#21901) refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/api/autocmd.c | 16 +-- src/nvim/api/command.c | 8 +- src/nvim/api/vim.c | 6 +- src/nvim/autocmd.c | 8 +- src/nvim/cmdexpand.c | 18 +-- src/nvim/cursor.c | 4 +- src/nvim/debugger.c | 2 +- src/nvim/edit.c | 30 ++--- src/nvim/eval.c | 4 +- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/typval.c | 10 +- src/nvim/eval/userfunc.c | 20 ++-- src/nvim/ex_cmds.c | 8 +- src/nvim/ex_docmd.c | 12 +- src/nvim/ex_getln.c | 4 +- src/nvim/fileio.h | 2 - src/nvim/getchar.c | 14 +-- src/nvim/hashtab.c | 4 +- src/nvim/help.c | 2 +- src/nvim/highlight.c | 6 +- src/nvim/highlight_group.c | 4 +- src/nvim/input.c | 16 +-- src/nvim/keycodes.c | 46 ++++---- src/nvim/keycodes.h | 2 +- src/nvim/lua/executor.c | 2 +- src/nvim/lua/stdlib.c | 2 +- src/nvim/main.c | 2 +- src/nvim/mapping.c | 14 +-- src/nvim/mbyte.c | 8 +- src/nvim/memline.c | 42 +++---- src/nvim/message.c | 10 +- src/nvim/ops.c | 6 +- src/nvim/option.c | 32 +++--- src/nvim/path.c | 10 +- src/nvim/search.c | 11 +- src/nvim/sha256.c | 4 +- src/nvim/shada.c | 2 +- src/nvim/sign.c | 10 +- src/nvim/spell.c | 70 ++++++------ src/nvim/spell_defs.h | 26 ++--- src/nvim/spellfile.c | 149 +++++++++++++------------ src/nvim/spellsuggest.c | 273 ++++++++++++++++++++++----------------------- src/nvim/statusline.c | 2 +- src/nvim/testing.c | 4 +- src/nvim/textformat.c | 6 +- src/nvim/usercmd.c | 12 +- src/nvim/vim.h | 1 - 47 files changed, 471 insertions(+), 475 deletions(-) (limited to 'src') diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index a2cb297b15..f801c716e5 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -194,8 +194,8 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) goto cleanup; } - snprintf((char *)pattern_buflocal, BUFLOCAL_PAT_LEN, "", (int)buf->handle); - ADD(buffers, CSTR_TO_OBJ((char *)pattern_buflocal)); + snprintf(pattern_buflocal, BUFLOCAL_PAT_LEN, "", (int)buf->handle); + ADD(buffers, CSTR_TO_OBJ(pattern_buflocal)); } else if (opts->buffer.type == kObjectTypeArray) { if (opts->buffer.data.array.size > AUCMD_MAX_PATTERNS) { api_set_error(err, @@ -215,8 +215,8 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) goto cleanup; } - snprintf((char *)pattern_buflocal, BUFLOCAL_PAT_LEN, "", (int)buf->handle); - ADD(buffers, CSTR_TO_OBJ((char *)pattern_buflocal)); + snprintf(pattern_buflocal, BUFLOCAL_PAT_LEN, "", (int)buf->handle); + ADD(buffers, CSTR_TO_OBJ(pattern_buflocal)); }); } else if (opts->buffer.type != kObjectTypeNil) { api_set_error(err, kErrorTypeValidation, @@ -319,7 +319,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) PUT(autocmd_info, "pattern", - STRING_OBJ(cstr_to_string((char *)ap->pat))); + STRING_OBJ(cstr_to_string(ap->pat))); PUT(autocmd_info, "event", @@ -934,7 +934,7 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob char *pat = v->data.string.data; size_t patlen = aucmd_pattern_length(pat); while (patlen) { - ADD(*patterns, STRING_OBJ(cbuf_to_string((char *)pat, patlen))); + ADD(*patterns, STRING_OBJ(cbuf_to_string(pat, patlen))); pat = aucmd_next_pattern(pat, patlen); patlen = aucmd_pattern_length(pat); @@ -949,7 +949,7 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob char *pat = entry.data.string.data; size_t patlen = aucmd_pattern_length(pat); while (patlen) { - ADD(*patterns, STRING_OBJ(cbuf_to_string((char *)pat, patlen))); + ADD(*patterns, STRING_OBJ(cbuf_to_string(pat, patlen))); pat = aucmd_next_pattern(pat, patlen); patlen = aucmd_pattern_length(pat); @@ -975,7 +975,7 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob } snprintf((char *)pattern_buflocal, BUFLOCAL_PAT_LEN, "", (int)buf->handle); - ADD(*patterns, STRING_OBJ(cstr_to_string((char *)pattern_buflocal))); + ADD(*patterns, STRING_OBJ(cstr_to_string(pattern_buflocal))); } return true; diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 7e7df3ee0f..f09a00e5c2 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -127,7 +127,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) // otherwise split arguments by whitespace. if (ea.argt & EX_NOSPC) { if (*ea.arg != NUL) { - ADD(args, STRING_OBJ(cstrn_to_string((char *)ea.arg, length))); + ADD(args, STRING_OBJ(cstrn_to_string(ea.arg, length))); } } else { size_t end = 0; @@ -153,9 +153,9 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) } if (cmd != NULL) { - PUT(result, "cmd", CSTR_TO_OBJ((char *)cmd->uc_name)); + PUT(result, "cmd", CSTR_TO_OBJ(cmd->uc_name)); } else { - PUT(result, "cmd", CSTR_TO_OBJ((char *)get_command_name(NULL, ea.cmdidx))); + PUT(result, "cmd", CSTR_TO_OBJ(get_command_name(NULL, ea.cmdidx))); } if (ea.argt & EX_RANGE) { @@ -237,7 +237,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) break; } PUT(result, "addr", CSTR_TO_OBJ(addr)); - PUT(result, "nextcmd", CSTR_TO_OBJ((char *)ea.nextcmd)); + PUT(result, "nextcmd", CSTR_TO_OBJ(ea.nextcmd)); Dictionary mods = ARRAY_DICT_INIT; diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index a53b30dd8a..12ab40a687 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -554,7 +554,7 @@ static void find_runtime_cb(char *fname, void *cookie) { Array *rv = (Array *)cookie; if (fname != NULL) { - ADD(*rv, STRING_OBJ(cstr_to_string((char *)fname))); + ADD(*rv, STRING_OBJ(cstr_to_string(fname))); } } @@ -2266,7 +2266,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * for (stl_hlrec_t *sp = hltab; sp->start != NULL; sp++) { Dictionary hl_info = ARRAY_DICT_INIT; - PUT(hl_info, "start", INTEGER_OBJ((char *)sp->start - buf)); + PUT(hl_info, "start", INTEGER_OBJ(sp->start - buf)); if (sp->userhl == 0) { grpname = get_default_stl_hl(wp, use_winbar); @@ -2281,7 +2281,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * } PUT(result, "highlights", ARRAY_OBJ(hl_values)); } - PUT(result, "str", CSTR_TO_OBJ((char *)buf)); + PUT(result, "str", CSTR_TO_OBJ(buf)); return result; } diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 0485fbcdb0..239a07da1f 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -221,7 +221,7 @@ static void aupat_show(AutoPat *ap, event_T event, int previous_group) char *exec_to_string = aucmd_exec_to_string(ac, ac->exec); if (ac->desc != NULL) { size_t msglen = 100; - char *msg = (char *)xmallocz(msglen); + char *msg = xmallocz(msglen); if (ac->exec.type == CALLABLE_CB) { msg_puts_attr(exec_to_string, HL_ATTR(HLF_8)); snprintf(msg, msglen, " [%s]", ac->desc); @@ -286,7 +286,7 @@ static void au_show_for_event(int group, event_T event, char *pat) if (aupat_is_buflocal(pat, patlen)) { // normalize pat into standard "#N" form aupat_normalize_buflocal_pat(buflocal_pat, pat, patlen, aupat_get_buflocal_nr(pat, patlen)); - pat = (char *)buflocal_pat; + pat = buflocal_pat; patlen = (int)strlen(buflocal_pat); } @@ -2119,8 +2119,8 @@ static bool call_autocmd_callback(const AutoCmd *ac, const AutoPatCmd *apc) Dictionary data = ARRAY_DICT_INIT; PUT(data, "id", INTEGER_OBJ(ac->id)); PUT(data, "event", CSTR_TO_OBJ(event_nr2name(apc->event))); - PUT(data, "match", CSTR_TO_OBJ((char *)autocmd_match)); - PUT(data, "file", CSTR_TO_OBJ((char *)autocmd_fname)); + PUT(data, "match", CSTR_TO_OBJ(autocmd_match)); + PUT(data, "file", CSTR_TO_OBJ(autocmd_fname)); PUT(data, "buf", INTEGER_OBJ(autocmd_bufnr)); if (apc->data) { diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index 5e4b49db24..64e5664f1f 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -2000,8 +2000,8 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa case CMD_snoremap: case CMD_xmap: case CMD_xnoremap: - return (const char *)set_context_in_map_cmd(xp, (char *)cmd, (char *)arg, forceit, false, - false, cmdidx); + return set_context_in_map_cmd(xp, (char *)cmd, (char *)arg, forceit, false, + false, cmdidx); case CMD_unmap: case CMD_nunmap: case CMD_vunmap: @@ -2011,8 +2011,8 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa case CMD_lunmap: case CMD_sunmap: case CMD_xunmap: - return (const char *)set_context_in_map_cmd(xp, (char *)cmd, (char *)arg, forceit, false, - true, cmdidx); + return set_context_in_map_cmd(xp, (char *)cmd, (char *)arg, forceit, false, + true, cmdidx); case CMD_mapclear: case CMD_nmapclear: case CMD_vmapclear: @@ -2032,13 +2032,13 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa case CMD_cnoreabbrev: case CMD_iabbrev: case CMD_inoreabbrev: - return (const char *)set_context_in_map_cmd(xp, (char *)cmd, (char *)arg, forceit, true, - false, cmdidx); + return set_context_in_map_cmd(xp, (char *)cmd, (char *)arg, forceit, true, + false, cmdidx); case CMD_unabbreviate: case CMD_cunabbrev: case CMD_iunabbrev: - return (const char *)set_context_in_map_cmd(xp, (char *)cmd, (char *)arg, forceit, true, - true, cmdidx); + return set_context_in_map_cmd(xp, (char *)cmd, (char *)arg, forceit, true, + true, cmdidx); case CMD_menu: case CMD_noremenu: case CMD_unmenu: @@ -3238,7 +3238,7 @@ void globpath(char *path, char *file, garray_T *ga, int expand_options, bool dir ga_grow(ga, num_p); // take over the pointers and put them in "ga" for (int i = 0; i < num_p; i++) { - ((char_u **)ga->ga_data)[ga->ga_len] = (char_u *)p[i]; + ((char **)ga->ga_data)[ga->ga_len] = p[i]; ga->ga_len++; } xfree(p); diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c index b1dbc68ea3..ceeaa65206 100644 --- a/src/nvim/cursor.c +++ b/src/nvim/cursor.c @@ -494,10 +494,10 @@ int gchar_cursor(void) /// Write a character at the current cursor position. /// It is directly written into the block. -void pchar_cursor(char_u c) +void pchar_cursor(char c) { *(ml_get_buf(curbuf, curwin->w_cursor.lnum, true) - + curwin->w_cursor.col) = (char)c; + + curwin->w_cursor.col) = c; } /// @return pointer to cursor line. diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c index f7e70a78ce..dc58d6bf60 100644 --- a/src/nvim/debugger.c +++ b/src/nvim/debugger.c @@ -727,7 +727,7 @@ void ex_breaklist(exarg_T *eap) for (int i = 0; i < dbg_breakp.ga_len; i++) { struct debuggy *bp = &BREAKP(i); if (bp->dbg_type == DBG_FILE) { - home_replace(NULL, bp->dbg_name, (char *)NameBuff, MAXPATHL, true); + home_replace(NULL, bp->dbg_name, NameBuff, MAXPATHL, true); } if (bp->dbg_type != DBG_EXPR) { smsg(_("%3d %s %s line %" PRId64), diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 4fe1c08974..ff7899d0eb 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1401,7 +1401,7 @@ static int pc_status; #define PC_STATUS_RIGHT 1 // right half of double-wide char #define PC_STATUS_LEFT 2 // left half of double-wide char #define PC_STATUS_SET 3 // pc_bytes was filled -static char_u pc_bytes[MB_MAXBYTES + 1]; // saved bytes +static char pc_bytes[MB_MAXBYTES + 1]; // saved bytes static int pc_attr; static int pc_row; static int pc_col; @@ -1438,7 +1438,7 @@ void edit_putchar(int c, bool highlight) // save the character to be able to put it back if (pc_status == PC_STATUS_UNSET) { - grid_getbytes(&curwin->w_grid, pc_row, pc_col, (char *)pc_bytes, &pc_attr); + grid_getbytes(&curwin->w_grid, pc_row, pc_col, pc_bytes, &pc_attr); pc_status = PC_STATUS_SET; } grid_putchar(&curwin->w_grid, c, pc_row, pc_col, attr); @@ -1521,7 +1521,7 @@ void edit_unputchar(void) if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) { redrawWinline(curwin, curwin->w_cursor.lnum); } else { - grid_puts(&curwin->w_grid, (char *)pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr); + grid_puts(&curwin->w_grid, pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr); } } } @@ -2051,7 +2051,7 @@ void insertchar(int c, int flags, int second_indent) // Check whether this character should end a comment. if (did_ai && c == end_comment_pending) { - char_u lead_end[COM_MAX_LEN]; // end-comment string + char lead_end[COM_MAX_LEN]; // end-comment string // Need to remove existing (middle) comment leader and insert end // comment leader. First, check what comment leader we can find. @@ -2062,7 +2062,7 @@ void insertchar(int c, int flags, int second_indent) while (*p && p[-1] != ':') { // find end of middle flags p++; } - int middle_len = (int)copy_option_part(&p, (char *)lead_end, COM_MAX_LEN, ","); + int middle_len = (int)copy_option_part(&p, lead_end, COM_MAX_LEN, ","); // Don't count trailing white space for middle_len while (middle_len > 0 && ascii_iswhite(lead_end[middle_len - 1])) { middle_len--; @@ -2072,7 +2072,7 @@ void insertchar(int c, int flags, int second_indent) while (*p && p[-1] != ':') { // find end of end flags p++; } - int end_len = (int)copy_option_part(&p, (char *)lead_end, COM_MAX_LEN, ","); + int end_len = (int)copy_option_part(&p, lead_end, COM_MAX_LEN, ","); // Skip white space before the cursor i = curwin->w_cursor.col; @@ -2083,13 +2083,13 @@ void insertchar(int c, int flags, int second_indent) i -= middle_len; // Check some expected things before we go on - if (i >= 0 && lead_end[end_len - 1] == end_comment_pending) { + if (i >= 0 && (uint8_t)lead_end[end_len - 1] == end_comment_pending) { // Backspace over all the stuff we want to replace backspace_until_column(i); // Insert the end-comment string, except for the last // character, which will get inserted as normal later. - ins_bytes_len((char *)lead_end, (size_t)(end_len - 1)); + ins_bytes_len(lead_end, (size_t)(end_len - 1)); } } } @@ -2416,7 +2416,7 @@ void set_last_insert(int c) if (c < ' ' || c == DEL) { *s++ = Ctrl_V; } - s = (char *)add_char2buf(c, (char_u *)s); + s = add_char2buf(c, s); *s++ = ESC; *s++ = NUL; last_insert_skip = 0; @@ -2443,9 +2443,9 @@ void beginline(int flags) curwin->w_cursor.coladd = 0; if (flags & (BL_WHITE | BL_SOL)) { - char_u *ptr; + char *ptr; - for (ptr = (char_u *)get_cursor_line_ptr(); ascii_iswhite(*ptr) + for (ptr = get_cursor_line_ptr(); ascii_iswhite(*ptr) && !((flags & BL_FIX) && ptr[1] == NUL); ptr++) { curwin->w_cursor.col++; } @@ -2676,7 +2676,7 @@ int stuff_inserted(int c, long count, int no_esc) char *last_ptr; char last = NUL; - ptr = (char *)get_last_insert(); + ptr = get_last_insert(); if (ptr == NULL) { emsg(_(e_noinstext)); return FAIL; @@ -2725,13 +2725,13 @@ int stuff_inserted(int c, long count, int no_esc) return OK; } -char_u *get_last_insert(void) +char *get_last_insert(void) FUNC_ATTR_PURE { if (last_insert == NULL) { return NULL; } - return (char_u *)last_insert + last_insert_skip; + return last_insert + last_insert_skip; } // Get last inserted string, and remove trailing . @@ -4581,7 +4581,7 @@ static bool ins_tab(void) // Delete following spaces. i = cursor->col - fpos.col; if (i > 0) { - STRMOVE(ptr, (char *)ptr + i); + STRMOVE(ptr, ptr + i); // correct replace stack. if ((State & REPLACE_FLAG) && !(State & VREPLACE_FLAG)) { diff --git a/src/nvim/eval.c b/src/nvim/eval.c index edbeabc53d..fb69734457 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -3915,7 +3915,7 @@ char *partial_name(partial_T *pt) if (pt->pt_name != NULL) { return pt->pt_name; } - return (char *)pt->pt_func->uf_name; + return pt->pt_func->uf_name; } static void partial_free(partial_T *pt) @@ -5052,7 +5052,7 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref) if (tv_list_len(list) == 0) { arg_idx = 0; } else if (tv_list_len(list) > MAX_FUNC_ARGS) { - emsg_funcname((char *)e_toomanyarg, s); + emsg_funcname(e_toomanyarg, s); xfree(name); goto theend; } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 884a50a433..6f983d3208 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8769,7 +8769,7 @@ static void f_tr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tolen = utfc_ptr2len(p); if (idx-- == 0) { cplen = tolen; - cpstr = (char *)p; + cpstr = p; break; } } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 6d1c17c97e..9a3a1c3c0f 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -751,8 +751,8 @@ int tv_list_concat(list_T *const l1, list_T *const l2, typval_T *const tv) } typedef struct { - char_u *s; - char_u *tofree; + char *s; + char *tofree; } Join; /// Join list into a string, helper function @@ -785,7 +785,7 @@ static int list_join_inner(garray_T *const gap, list_T *const l, const char *con sumlen += len; Join *const p = GA_APPEND_VIA_PTR(Join, join_gap); - p->tofree = p->s = (char_u *)s; + p->tofree = p->s = s; line_breakcheck(); }); @@ -806,7 +806,7 @@ static int list_join_inner(garray_T *const gap, list_T *const l, const char *con const Join *const p = ((const Join *)join_gap->ga_data) + i; if (p->s != NULL) { - ga_concat(gap, (char *)p->s); + ga_concat(gap, p->s); } line_breakcheck(); } @@ -1673,7 +1673,7 @@ char *callback_to_string(Callback *cb) } const size_t msglen = 100; - char *msg = (char *)xmallocz(msglen); + char *msg = xmallocz(msglen); switch (cb->type) { case kCallbackFuncref: diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 957733ecd5..2496cbc430 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -880,7 +880,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett fc->rettv = rettv; fc->level = ex_nesting_level; // Check if this function has a breakpoint. - fc->breakpoint = dbg_find_breakpoint(false, (char *)fp->uf_name, (linenr_T)0); + fc->breakpoint = dbg_find_breakpoint(false, fp->uf_name, (linenr_T)0); fc->dbg_tick = debug_tick; // Set up fields for closure. @@ -1075,7 +1075,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett bool func_not_yet_profiling_but_should = do_profiling_yes - && !fp->uf_profiling && has_profiling(false, (char *)fp->uf_name, NULL); + && !fp->uf_profiling && has_profiling(false, fp->uf_name, NULL); if (func_not_yet_profiling_but_should) { started_profiling = true; @@ -1669,7 +1669,7 @@ static void list_func_head(ufunc_T *fp, int indent, bool force) if (fp->uf_name_exp != NULL) { msg_puts((const char *)fp->uf_name_exp); } else { - msg_puts((const char *)fp->uf_name); + msg_puts(fp->uf_name); } msg_putchar('('); int j; @@ -1999,10 +1999,10 @@ static void list_functions(regmatch_T *regmatch) todo--; if ((fp->uf_flags & FC_DEAD) == 0 && (regmatch == NULL - ? (!message_filtered((char *)fp->uf_name) + ? (!message_filtered(fp->uf_name) && !func_name_refcount(fp->uf_name)) : (!isdigit((uint8_t)(*fp->uf_name)) - && vim_regexec(regmatch, (char *)fp->uf_name, 0)))) { + && vim_regexec(regmatch, fp->uf_name, 0)))) { list_func_head(fp, false, false); if (changed != func_hashtab.ht_changed) { emsg(_("E454: function list was modified")); @@ -2194,7 +2194,7 @@ void ex_function(exarg_T *eap) j++; } if (arg[j] != NUL) { - emsg_funcname((char *)e_invarg2, arg); + emsg_funcname(e_invarg2, arg); } } // Disallow using the g: dict. @@ -2748,7 +2748,7 @@ char *get_user_func_name(expand_T *xp, int idx) } if (strlen(fp->uf_name) + 4 >= IOSIZE) { - return (char *)fp->uf_name; // Prevent overflow. + return fp->uf_name; // Prevent overflow. } cat_func_name(IObuff, fp); @@ -3228,7 +3228,7 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat) // If breakpoints have been added/deleted need to check for it. if (fcp->dbg_tick != debug_tick) { - fcp->breakpoint = dbg_find_breakpoint(false, (char *)fp->uf_name, SOURCING_LNUM); + fcp->breakpoint = dbg_find_breakpoint(false, fp->uf_name, SOURCING_LNUM); fcp->dbg_tick = debug_tick; } if (do_profiling == PROF_YES) { @@ -3258,9 +3258,9 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat) // Did we encounter a breakpoint? if (fcp->breakpoint != 0 && fcp->breakpoint <= SOURCING_LNUM) { - dbg_breakpoint((char *)fp->uf_name, SOURCING_LNUM); + dbg_breakpoint(fp->uf_name, SOURCING_LNUM); // Find next breakpoint. - fcp->breakpoint = dbg_find_breakpoint(false, (char *)fp->uf_name, SOURCING_LNUM); + fcp->breakpoint = dbg_find_breakpoint(false, fp->uf_name, SOURCING_LNUM); fcp->dbg_tick = debug_tick; } diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 036e34431b..67d1a1e2f7 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -1818,7 +1818,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) { char buff[DIALOG_MSG_SIZE]; - dialog_msg((char *)buff, _("Overwrite existing file \"%s\"?"), fname); + dialog_msg(buff, _("Overwrite existing file \"%s\"?"), fname); if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) != VIM_YES) { return FAIL; } @@ -1854,7 +1854,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) { char buff[DIALOG_MSG_SIZE]; - dialog_msg((char *)buff, + dialog_msg(buff, _("Swap file \"%s\" exists, overwrite anyway?"), swapname); if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) @@ -1974,11 +1974,11 @@ static int check_readonly(int *forceit, buf_T *buf) char buff[DIALOG_MSG_SIZE]; if (buf->b_p_ro) { - dialog_msg((char *)buff, + dialog_msg(buff, _("'readonly' option is set for \"%s\".\nDo you wish to write anyway?"), buf->b_fname); } else { - dialog_msg((char *)buff, + dialog_msg(buff, _("File permissions of \"%s\" are read-only.\nIt may still be possible to " "write it.\nDo you wish to try?"), buf->b_fname); diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 8440c45a9c..f460b4b93f 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -3200,7 +3200,7 @@ char *skip_range(const char *cmd, int *ctx) } // Skip ":" and white space. - cmd = skip_colon_white((char *)cmd, false); + cmd = skip_colon_white(cmd, false); return (char *)cmd; } @@ -4011,7 +4011,7 @@ static char *getargcmd(char **argp) if (*arg == '+') { // +[command] arg++; if (ascii_isspace(*arg) || *arg == '\0') { - command = (char *)dollar_command; + command = dollar_command; } else { command = arg; arg = skip_cmd_arg(command, true); @@ -4401,7 +4401,7 @@ static int check_more(int message, bool forceit) if ((p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) && curbuf->b_fname != NULL) { char buff[DIALOG_MSG_SIZE]; - vim_snprintf((char *)buff, DIALOG_MSG_SIZE, + vim_snprintf(buff, DIALOG_MSG_SIZE, NGETTEXT("%d more file to edit. Quit anyway?", "%d more files to edit. Quit anyway?", n), n); if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES) { @@ -4769,7 +4769,7 @@ void tabpage_close_other(tabpage_T *tp, int forceit) // Limit to 1000 windows, autocommands may add a window while we close // one. OK, so I'm paranoid... while (++done < 1000) { - snprintf((char *)prev_idx, sizeof(prev_idx), "%i", tabpage_index(tp)); + snprintf(prev_idx, sizeof(prev_idx), "%i", tabpage_index(tp)); win_T *wp = tp->tp_lastwin; ex_win_close(forceit, wp, tp); @@ -6748,7 +6748,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum // Note: In "\\%" the % is also not recognized! if (src > srcstart && src[-1] == '\\') { *usedlen = 0; - STRMOVE(src - 1, (char *)src); // remove backslash + STRMOVE(src - 1, src); // remove backslash return NULL; } @@ -6925,7 +6925,7 @@ char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnum *errormsg = _("E961: no line number to use for \"\""); return NULL; } - snprintf((char *)strbuf, sizeof(strbuf), "%" PRIdLINENR, + snprintf(strbuf, sizeof(strbuf), "%" PRIdLINENR, current_sctx.sc_lnum + SOURCING_LNUM); result = strbuf; break; diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 95564da7cb..6926a36366 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -3380,14 +3380,14 @@ static void ui_ext_cmdline_show(CmdlineInfo *line) ADD_C(item, INTEGER_OBJ(chunk.attr)); assert(chunk.end >= chunk.start); - ADD_C(item, STRING_OBJ(cbuf_as_string((char *)line->cmdbuff + chunk.start, + ADD_C(item, STRING_OBJ(cbuf_as_string(line->cmdbuff + chunk.start, (size_t)(chunk.end - chunk.start)))); ADD_C(content, ARRAY_OBJ(item)); } } else { Array item = arena_array(&arena, 2); ADD_C(item, INTEGER_OBJ(0)); - ADD_C(item, STRING_OBJ(cstr_as_string((char *)(line->cmdbuff)))); + ADD_C(item, STRING_OBJ(cstr_as_string(line->cmdbuff))); content = arena_array(&arena, 1); ADD_C(content, ARRAY_OBJ(item)); } diff --git a/src/nvim/fileio.h b/src/nvim/fileio.h index dabcda5bf2..3e51e361ac 100644 --- a/src/nvim/fileio.h +++ b/src/nvim/fileio.h @@ -18,8 +18,6 @@ #define READ_NOWINENTER 0x80 // do not trigger BufWinEnter #define READ_NOFILE 0x100 // do not read a file, do trigger BufReadCmd -#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y)) - typedef varnumber_T (*CheckItem)(void *expr, const char *name); #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 387139fd29..b54ecdb6ab 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -179,7 +179,7 @@ static char *get_buffcont(buffheader_T *buffer, int dozero) /// Return the contents of the record buffer as a single string /// and clear the record buffer. /// K_SPECIAL in the returned string is escaped. -char_u *get_recorded(void) +char *get_recorded(void) { char *p; size_t len; @@ -201,7 +201,7 @@ char_u *get_recorded(void) p[len - 1] = NUL; } - return (char_u *)p; + return p; } /// Return the contents of the redo buffer as a single string. @@ -978,7 +978,7 @@ int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent) int ins_char_typebuf(int c, int modifiers) { char_u buf[MB_MAXBYTES * 3 + 4]; - unsigned int len = special_to_buf(c, modifiers, true, buf); + unsigned int len = special_to_buf(c, modifiers, true, (char *)buf); assert(len < sizeof(buf)); buf[len] = NUL; (void)ins_typebuf((char *)buf, KeyNoremap, 0, !KeyTyped, cmd_silent); @@ -2197,7 +2197,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) // mode temporarily. Append K_SELECT to switch back to Select mode. if (VIsual_active && VIsual_select && (mp->m_mode & MODE_VISUAL)) { VIsual_select = false; - (void)ins_typebuf((char *)K_SELECT_STRING, REMAP_NONE, 0, true, false); + (void)ins_typebuf(K_SELECT_STRING, REMAP_NONE, 0, true, false); } // Copy the values from *mp that are used, because evaluating the @@ -2887,13 +2887,13 @@ int inchar(char_u *buf, int maxlen, long wait_time) typebuf.tb_change_cnt = 1; } - return fix_input_buffer(buf, len); + return fix_input_buffer((char *)buf, len); } // Fix typed characters for use by vgetc() and check_termcode(). // "buf[]" must have room to triple the number of bytes! // Returns the new length. -int fix_input_buffer(char_u *buf, int len) +int fix_input_buffer(char *buf, int len) FUNC_ATTR_NONNULL_ALL { if (!using_script()) { @@ -2905,7 +2905,7 @@ int fix_input_buffer(char_u *buf, int len) // Reading from script, need to process special bytes int i; - char_u *p = buf; + char_u *p = (char_u *)buf; // Two characters are special: NUL and K_SPECIAL. // Replace NUL by K_SPECIAL KS_ZERO KE_FILLER diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c index 851e70caca..8f4c7b1d80 100644 --- a/src/nvim/hashtab.c +++ b/src/nvim/hashtab.c @@ -457,8 +457,8 @@ hash_T hash_hash_len(const char *key, const size_t len) /// /// Used for testing because luajit ffi does not allow getting addresses of /// globals. -const char_u *_hash_key_removed(void) +const char *_hash_key_removed(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - return (char_u *)HI_KEY_REMOVED; + return HI_KEY_REMOVED; } diff --git a/src/nvim/help.c b/src/nvim/help.c index ab9d68fd89..ab4ce4e9ba 100644 --- a/src/nvim/help.c +++ b/src/nvim/help.c @@ -1089,7 +1089,7 @@ static void do_helptags(char *dirname, bool add_help_tags, bool ignore_writeerr) // Get a list of all files in the help directory and in subdirectories. xstrlcpy(NameBuff, dirname, sizeof(NameBuff)); - if (!add_pathsep((char *)NameBuff) + if (!add_pathsep(NameBuff) || xstrlcat(NameBuff, "**", sizeof(NameBuff)) >= MAXPATHL) { emsg(_(e_fnametoolong)); return; diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index c20eac3c28..5936e4ff2b 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -205,7 +205,7 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault) if (!valid_item && p->hl_def != LUA_NOREF && !recursive) { MAXSIZE_TEMP_ARRAY(args, 3); ADD_C(args, INTEGER_OBJ((Integer)ns_id)); - ADD_C(args, STRING_OBJ(cstr_to_string((char *)syn_id2name(hl_id)))); + ADD_C(args, STRING_OBJ(cstr_to_string(syn_id2name(hl_id)))); ADD_C(args, BOOLEAN_OBJ(link)); // TODO(bfredl): preload the "global" attr dict? @@ -1115,7 +1115,7 @@ static void hl_inspect_impl(Array *arr, int attr) case kHlSyntax: PUT(item, "kind", STRING_OBJ(cstr_to_string("syntax"))); PUT(item, "hi_name", - STRING_OBJ(cstr_to_string((char *)syn_id2name(e.id1)))); + STRING_OBJ(cstr_to_string(syn_id2name(e.id1)))); break; case kHlUI: @@ -1123,7 +1123,7 @@ static void hl_inspect_impl(Array *arr, int attr) const char *ui_name = (e.id1 == -1) ? "Normal" : hlf_names[e.id1]; PUT(item, "ui_name", STRING_OBJ(cstr_to_string(ui_name))); PUT(item, "hi_name", - STRING_OBJ(cstr_to_string((char *)syn_id2name(e.id2)))); + STRING_OBJ(cstr_to_string(syn_id2name(e.id2)))); break; case kHlTerminal: diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index 3d91335f55..e34c13abc1 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -1522,7 +1522,7 @@ Dictionary get_global_hl_defs(Arena *arena) char *link = hl_table[h->sg_link - 1].sg_name; PUT_C(attrs, "link", STRING_OBJ(cstr_as_string(link))); } - PUT_C(rv, (char *)h->sg_name, DICTIONARY_OBJ(attrs)); + PUT_C(rv, h->sg_name, DICTIONARY_OBJ(attrs)); } return rv; @@ -1547,7 +1547,7 @@ static bool highlight_list_arg(const int id, bool didh, const int type, int iarg char buf[100]; const char *ts = buf; if (type == LIST_INT) { - snprintf((char *)buf, sizeof(buf), "%d", iarg - 1); + snprintf(buf, sizeof(buf), "%d", iarg - 1); } else if (type == LIST_STRING) { ts = sarg; } else { // type == LIST_ATTR diff --git a/src/nvim/input.c b/src/nvim/input.c index 96214d45c2..2869155a09 100644 --- a/src/nvim/input.c +++ b/src/nvim/input.c @@ -86,7 +86,7 @@ int ask_yesno(const char *const str, const bool direct) /// Translates the interrupt character for unix to ESC. int get_keystroke(MultiQueue *events) { - char_u *buf = NULL; + char *buf = NULL; int buflen = 150; int maxlen; int len = 0; @@ -113,7 +113,7 @@ int get_keystroke(MultiQueue *events) // First time: blocking wait. Second time: wait up to 100ms for a // terminal code to complete. - n = os_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0, events); + n = os_inchar((uint8_t *)buf + len, maxlen, len == 0 ? -1L : 100L, 0, events); if (n > 0) { // Replace zero and K_SPECIAL by a special key code. n = fix_input_buffer(buf + len, n); @@ -128,14 +128,14 @@ int get_keystroke(MultiQueue *events) } // Handle modifier and/or special key code. - n = buf[0]; + n = (uint8_t)buf[0]; if (n == K_SPECIAL) { - n = TO_SPECIAL(buf[1], buf[2]); - if (buf[1] == KS_MODIFIER + n = TO_SPECIAL((uint8_t)buf[1], (uint8_t)buf[2]); + if ((uint8_t)buf[1] == KS_MODIFIER || n == K_IGNORE || (is_mouse_key(n) && n != K_LEFTMOUSE)) { - if (buf[1] == KS_MODIFIER) { - mod_mask = buf[2]; + if ((uint8_t)buf[1] == KS_MODIFIER) { + mod_mask = (uint8_t)buf[2]; } len -= 3; if (len > 0) { @@ -150,7 +150,7 @@ int get_keystroke(MultiQueue *events) continue; } buf[len >= buflen ? buflen - 1 : len] = NUL; - n = utf_ptr2char((char *)buf); + n = utf_ptr2char(buf); break; } xfree(buf); diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c index e19806e464..ff1bcffbdb 100644 --- a/src/nvim/keycodes.c +++ b/src/nvim/keycodes.c @@ -582,7 +582,7 @@ unsigned int trans_special(const char **const srcp, const size_t src_len, char * return 0; } - return special_to_buf(key, modifiers, escape_ks, (char_u *)dst); + return special_to_buf(key, modifiers, escape_ks, dst); } /// Put the character sequence for "key" with "modifiers" into "dst" and return @@ -590,27 +590,27 @@ unsigned int trans_special(const char **const srcp, const size_t src_len, char * /// When "escape_ks" is true escape K_SPECIAL bytes in the character. /// The sequence is not NUL terminated. /// This is how characters in a string are encoded. -unsigned int special_to_buf(int key, int modifiers, bool escape_ks, char_u *dst) +unsigned int special_to_buf(int key, int modifiers, bool escape_ks, char *dst) { unsigned int dlen = 0; // Put the appropriate modifier in a string. if (modifiers != 0) { - dst[dlen++] = K_SPECIAL; - dst[dlen++] = KS_MODIFIER; - dst[dlen++] = (char_u)modifiers; + dst[dlen++] = (char)(uint8_t)K_SPECIAL; + dst[dlen++] = (char)(uint8_t)KS_MODIFIER; + dst[dlen++] = (char)(uint8_t)modifiers; } if (IS_SPECIAL(key)) { - dst[dlen++] = K_SPECIAL; - dst[dlen++] = (char_u)KEY2TERMCAP0(key); - dst[dlen++] = KEY2TERMCAP1(key); + dst[dlen++] = (char)(uint8_t)K_SPECIAL; + dst[dlen++] = (char)(uint8_t)KEY2TERMCAP0(key); + dst[dlen++] = (char)(uint8_t)KEY2TERMCAP1(key); } else if (escape_ks) { - char_u *after = add_char2buf(key, dst + dlen); + char *after = add_char2buf(key, dst + dlen); assert(after >= dst && (uintmax_t)(after - dst) <= UINT_MAX); dlen = (unsigned int)(after - dst); } else { - dlen += (unsigned int)utf_char2bytes(key, (char *)dst + dlen); + dlen += (unsigned int)utf_char2bytes(key, dst + dlen); } return dlen; @@ -1033,20 +1033,20 @@ char *replace_termcodes(const char *const from, const size_t from_len, char **co /// @param[out] s Buffer to add to. Must have at least MB_MAXBYTES + 1 bytes. /// /// @return Pointer to after the added bytes. -char_u *add_char2buf(int c, char_u *s) +char *add_char2buf(int c, char *s) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { - char_u temp[MB_MAXBYTES + 1]; - const int len = utf_char2bytes(c, (char *)temp); + char temp[MB_MAXBYTES + 1]; + const int len = utf_char2bytes(c, temp); for (int i = 0; i < len; i++) { c = (uint8_t)temp[i]; // Need to escape K_SPECIAL like in the typeahead buffer. if (c == K_SPECIAL) { - *s++ = K_SPECIAL; - *s++ = KS_SPECIAL; + *s++ = (char)(uint8_t)K_SPECIAL; + *s++ = (char)(uint8_t)KS_SPECIAL; *s++ = KE_FILLER; } else { - *s++ = (char_u)c; + *s++ = (char)(uint8_t)c; } } return s; @@ -1060,9 +1060,9 @@ char *vim_strsave_escape_ks(char *p) // illegal utf-8 byte: // 0xc0 -> 0xc3 - 0x80 -> 0xc3 K_SPECIAL KS_SPECIAL KE_FILLER char *res = xmalloc(strlen(p) * 4 + 1); - char_u *d = (char_u *)res; - for (char_u *s = (char_u *)p; *s != NUL;) { - if (s[0] == K_SPECIAL && s[1] != NUL && s[2] != NUL) { + char *d = res; + for (char *s = p; *s != NUL;) { + if ((uint8_t)s[0] == K_SPECIAL && s[1] != NUL && s[2] != NUL) { // Copy special key unmodified. *d++ = *s++; *d++ = *s++; @@ -1070,8 +1070,8 @@ char *vim_strsave_escape_ks(char *p) } else { // Add character, possibly multi-byte to destination, escaping // K_SPECIAL. Be careful, it can be an illegal byte! - d = add_char2buf(utf_ptr2char((char *)s), d); - s += utf_ptr2len((char *)s); + d = add_char2buf(utf_ptr2char(s), d); + s += utf_ptr2len(s); } } *d = NUL; @@ -1081,9 +1081,9 @@ char *vim_strsave_escape_ks(char *p) /// Remove escaping from K_SPECIAL characters. Reverse of /// vim_strsave_escape_ks(). Works in-place. -void vim_unescape_ks(char_u *p) +void vim_unescape_ks(char *p) { - char_u *s = p, *d = p; + char_u *s = (char_u *)p, *d = (char_u *)p; while (*s != NUL) { if (s[0] == K_SPECIAL && s[1] == KS_SPECIAL && s[2] == KE_FILLER) { diff --git a/src/nvim/keycodes.h b/src/nvim/keycodes.h index 7842dee92c..7c143fc99e 100644 --- a/src/nvim/keycodes.h +++ b/src/nvim/keycodes.h @@ -59,7 +59,7 @@ // Used for switching Select mode back on after a mapping or menu. #define KS_SELECT 245 -#define K_SELECT_STRING (char_u *)"\200\365X" +#define K_SELECT_STRING "\200\365X" /// Used a termcap entry that produces a normal character. #define KS_KEY 242 diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 007662fbc9..5fbbb342bf 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1993,7 +1993,7 @@ char *nlua_register_table_as_callable(const typval_T *const arg) void nlua_execute_on_key(int c) { char buf[NUMBUFLEN]; - size_t buf_len = special_to_buf(c, mod_mask, false, (char_u *)buf); + size_t buf_len = special_to_buf(c, mod_mask, false, buf); lua_State *const lstate = global_lstate; diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c index 73246f81b7..5aeff4de98 100644 --- a/src/nvim/lua/stdlib.c +++ b/src/nvim/lua/stdlib.c @@ -222,7 +222,7 @@ static int nlua_str_utf_start(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL if (offset < 0 || offset > (intptr_t)s1_len) { return luaL_error(lstate, "index out of range"); } - int head_offset = utf_cp_head_off((char_u *)s1, (char_u *)s1 + offset - 1); + int head_offset = utf_cp_head_off(s1, s1 + offset - 1); lua_pushinteger(lstate, head_offset); return 1; } diff --git a/src/nvim/main.c b/src/nvim/main.c index f37c43d8c1..4ee02b4e1b 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1589,7 +1589,7 @@ static void open_script_files(mparm_T *parmp) scriptin[0] = file_open_new(&error, parmp->scriptin, kFileReadOnly|kFileNonBlocking, 0); if (scriptin[0] == NULL) { - vim_snprintf((char *)IObuff, IOSIZE, + vim_snprintf(IObuff, IOSIZE, _("Cannot open for reading: \"%s\": %s\n"), parmp->scriptin, os_strerror(error)); os_errmsg(IObuff); diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 5547b6c367..c740fb41bc 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -1162,7 +1162,7 @@ static bool expand_buffer = false; /// @param cpo_flags Value of various flags present in &cpo /// /// @return NULL when there is a problem. -static char_u *translate_mapping(char_u *str, int cpo_flags) +static char *translate_mapping(char_u *str, int cpo_flags) { garray_T ga; ga_init(&ga, 1, 40); @@ -1203,7 +1203,7 @@ static char_u *translate_mapping(char_u *str, int cpo_flags) } } ga_append(&ga, NUL); - return (char_u *)(ga.ga_data); + return (char *)ga.ga_data; } /// Work out what to complete when doing command line completion of mapping @@ -1212,8 +1212,8 @@ static char_u *translate_mapping(char_u *str, int cpo_flags) /// @param forceit true if '!' given /// @param isabbrev true if abbreviation /// @param isunmap true if unmap/unabbrev command -char_u *set_context_in_map_cmd(expand_T *xp, char *cmd, char *arg, bool forceit, bool isabbrev, - bool isunmap, cmdidx_T cmdidx) +char *set_context_in_map_cmd(expand_T *xp, char *cmd, char *arg, bool forceit, bool isabbrev, + bool isunmap, cmdidx_T cmdidx) { if (forceit && cmdidx != CMD_map && cmdidx != CMD_unmap) { xp->xp_context = EXPAND_NOTHING; @@ -1346,7 +1346,7 @@ int ExpandMappings(char *pat, regmatch_T *regmatch, int *numMatches, char ***mat continue; } - char *p = (char *)translate_mapping((char_u *)mp->m_keys, CPO_TO_CPO_FLAGS); + char *p = translate_mapping((char_u *)mp->m_keys, CPO_TO_CPO_FLAGS); if (p == NULL) { continue; } @@ -1503,7 +1503,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol) if (strchr((const char *)mp->m_keys, K_SPECIAL) != NULL) { // Might have K_SPECIAL escaped mp->m_keys. q = xstrdup(mp->m_keys); - vim_unescape_ks((char_u *)q); + vim_unescape_ks(q); qlen = (int)strlen(q); } // find entries with right mode and keys @@ -1607,7 +1607,7 @@ char *eval_map_expr(mapblock_T *mp, int c) // typeahead. if (mp->m_luaref == LUA_NOREF) { expr = xstrdup(mp->m_str); - vim_unescape_ks((char_u *)expr); + vim_unescape_ks(expr); } const bool replace_keycodes = mp->m_replace_keycodes; diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 2f1724369c..c2bde53b32 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1842,7 +1842,7 @@ int utf_cp_tail_off(const char *base, const char *p_in) /// @param[in] p Pointer to byte for which to return the offset to the previous codepoint // /// @return 0 if invalid sequence, else offset to previous codepoint -int utf_cp_head_off(const char_u *base, const char_u *p) +int utf_cp_head_off(const char *base, const char *p) { int i; int j; @@ -1853,16 +1853,16 @@ int utf_cp_head_off(const char_u *base, const char_u *p) // Find the first character that is not 10xx.xxxx for (i = 0; p - i > base; i--) { - if ((p[i] & 0xc0) != 0x80) { + if (((uint8_t)p[i] & 0xc0) != 0x80) { break; } } // Find the last character that is 10xx.xxxx - for (j = 0; (p[j + 1] & 0xc0) == 0x80; j++) {} + for (j = 0; ((uint8_t)p[j + 1] & 0xc0) == 0x80; j++) {} // Check for illegal sequence. - if (utf8len_tab[p[i]] == 1) { + if (utf8len_tab[(uint8_t)p[i]] == 1) { return 0; } return i; diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 2a4e0f7377..555f21c4fd 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -185,8 +185,8 @@ struct block0 { char_u b0_mtime[4]; // last modification time of file char_u b0_ino[4]; // inode of b0_fname char_u b0_pid[4]; // process id of creator (or 0) - char_u b0_uname[B0_UNAME_SIZE]; // name of user (uid if no name) - char_u b0_hname[B0_HNAME_SIZE]; // host name (if it has a name) + char b0_uname[B0_UNAME_SIZE]; // name of user (uid if no name) + char b0_hname[B0_HNAME_SIZE]; // host name (if it has a name) char b0_fname[B0_FNAME_SIZE_ORG]; // name of file being edited long b0_magic_long; // check for byte order of long int b0_magic_int; // check for byte order of int @@ -303,9 +303,9 @@ int ml_open(buf_T *buf) b0p->b0_dirty = buf->b_changed ? B0_DIRTY : 0; b0p->b0_flags = (char)(get_fileformat(buf) + 1); set_b0_fname(b0p, buf); - (void)os_get_username((char *)b0p->b0_uname, B0_UNAME_SIZE); + (void)os_get_username(b0p->b0_uname, B0_UNAME_SIZE); b0p->b0_uname[B0_UNAME_SIZE - 1] = NUL; - os_get_hostname((char *)b0p->b0_hname, B0_HNAME_SIZE); + os_get_hostname(b0p->b0_hname, B0_HNAME_SIZE); b0p->b0_hname[B0_HNAME_SIZE - 1] = NUL; long_to_char((long)os_get_pid(), b0p->b0_pid); } @@ -632,7 +632,7 @@ static void set_b0_fname(ZERO_BL *b0p, buf_T *buf) // editing the same file on different machines over a network. // First replace home dir path with "~/" with home_replace(). // Then insert the user name to get "~user/". - home_replace(NULL, buf->b_ffname, (char *)b0p->b0_fname, + home_replace(NULL, buf->b_ffname, b0p->b0_fname, B0_FNAME_SIZE_CRYPT, true); if (b0p->b0_fname[0] == '~') { // If there is no user name or it is too long, don't use "~/" @@ -691,7 +691,7 @@ static void add_b0_fenc(ZERO_BL *b0p, buf_T *buf) if ((int)strlen(b0p->b0_fname) + n + 1 > size) { b0p->b0_flags = (char)(b0p->b0_flags & ~B0_HAS_FENC); } else { - memmove((char *)b0p->b0_fname + size - n, + memmove(b0p->b0_fname + size - n, buf->b_p_fenc, (size_t)n); *(b0p->b0_fname + size - n - 1) = NUL; b0p->b0_flags |= B0_HAS_FENC; @@ -848,7 +848,7 @@ void ml_recover(bool checkext) msg_puts_attr(_("The file was created on "), attr | MSG_HIST); // avoid going past the end of a corrupted hostname b0p->b0_fname[0] = NUL; - msg_puts_attr((char *)b0p->b0_hname, attr | MSG_HIST); + msg_puts_attr(b0p->b0_hname, attr | MSG_HIST); msg_puts_attr(_(",\nor the file has been damaged."), attr | MSG_HIST); msg_end(); goto theend; @@ -886,7 +886,7 @@ void ml_recover(bool checkext) // If .swp file name given directly, use name from swap file for buffer. if (directly) { - expand_env((char *)b0p->b0_fname, NameBuff, MAXPATHL); + expand_env(b0p->b0_fname, NameBuff, MAXPATHL); if (setfname(curbuf, NameBuff, NULL, true) == FAIL) { goto theend; } @@ -922,7 +922,7 @@ void ml_recover(bool checkext) if (b0p->b0_flags & B0_HAS_FENC) { int fnsize = B0_FNAME_SIZE_NOCRYPT; - for (p = (char *)b0p->b0_fname + fnsize; p > b0p->b0_fname && p[-1] != NUL; p--) {} + for (p = b0p->b0_fname + fnsize; p > b0p->b0_fname && p[-1] != NUL; p--) {} b0_fenc = xstrnsave(p, (size_t)(b0p->b0_fname + fnsize - p)); } @@ -1411,11 +1411,11 @@ void get_b0_dict(const char *fname, dict_T *d) } else { // We have swap information. tv_dict_add_str_len(d, S_LEN("version"), b0.b0_version, 10); - tv_dict_add_str_len(d, S_LEN("user"), (char *)b0.b0_uname, + tv_dict_add_str_len(d, S_LEN("user"), b0.b0_uname, B0_UNAME_SIZE); - tv_dict_add_str_len(d, S_LEN("host"), (char *)b0.b0_hname, + tv_dict_add_str_len(d, S_LEN("host"), b0.b0_hname, B0_HNAME_SIZE); - tv_dict_add_str_len(d, S_LEN("fname"), (char *)b0.b0_fname, + tv_dict_add_str_len(d, S_LEN("fname"), b0.b0_fname, B0_FNAME_SIZE_ORG); tv_dict_add_nr(d, S_LEN("pid"), char_to_long(b0.b0_pid)); @@ -1480,7 +1480,7 @@ static time_t swapfile_info(char *fname) if (b0.b0_fname[0] == NUL) { msg_puts(_("[No Name]")); } else { - msg_outtrans((char *)b0.b0_fname); + msg_outtrans(b0.b0_fname); } msg_puts(_("\n modified: ")); @@ -1488,7 +1488,7 @@ static time_t swapfile_info(char *fname) if (*(b0.b0_uname) != NUL) { msg_puts(_("\n user name: ")); - msg_outtrans((char *)b0.b0_uname); + msg_outtrans(b0.b0_uname); } if (*(b0.b0_hname) != NUL) { @@ -1497,7 +1497,7 @@ static time_t swapfile_info(char *fname) } else { msg_puts(_("\n host name: ")); } - msg_outtrans((char *)b0.b0_hname); + msg_outtrans(b0.b0_hname); } if (char_to_long(b0.b0_pid) != 0L) { @@ -3029,7 +3029,7 @@ char *makeswapname(char *fname, char *ffname, buf_T *buf, char *dir_name) // Expand symlink in the file name, so that we put the swap file with the // actual file instead of with the symlink. - if (resolve_symlink(fname, (char *)fname_buf) == OK) { + if (resolve_symlink(fname, fname_buf) == OK) { fname_res = fname_buf; } #endif @@ -3267,12 +3267,12 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ // have a different mountpoint. if (b0.b0_flags & B0_SAME_DIR) { if (path_fnamecmp(path_tail(buf->b_ffname), - path_tail((char *)b0.b0_fname)) != 0 + path_tail(b0.b0_fname)) != 0 || !same_directory(fname, buf->b_ffname)) { // Symlinks may point to the same file even // when the name differs, need to check the // inode too. - expand_env((char *)b0.b0_fname, NameBuff, MAXPATHL); + expand_env(b0.b0_fname, NameBuff, MAXPATHL); if (fnamecmp_ino(buf->b_ffname, NameBuff, char_to_long(b0.b0_ino))) { differ = true; @@ -3281,7 +3281,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ } else { // The name in the swap file may be // "~user/path/file". Expand it first. - expand_env((char *)b0.b0_fname, NameBuff, MAXPATHL); + expand_env(b0.b0_fname, NameBuff, MAXPATHL); if (fnamecmp_ino(buf->b_ffname, NameBuff, char_to_long(b0.b0_ino))) { differ = true; @@ -3516,8 +3516,8 @@ static bool fnamecmp_ino(char *fname_c, char *fname_s, long ino_block0) // One of the inode numbers is unknown, try a forced vim_FullName() and // compare the file names. - retval_c = vim_FullName(fname_c, (char *)buf_c, MAXPATHL, true); - retval_s = vim_FullName(fname_s, (char *)buf_s, MAXPATHL, true); + retval_c = vim_FullName(fname_c, buf_c, MAXPATHL, true); + retval_s = vim_FullName(fname_s, buf_s, MAXPATHL, true); if (retval_c == OK && retval_s == OK) { return strcmp(buf_c, buf_s) != 0; } diff --git a/src/nvim/message.c b/src/nvim/message.c index 40453211b4..88f58ef0df 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1085,7 +1085,7 @@ void ex_messages(void *const eap_p) } else if (p->msg && p->msg[0]) { Array content_entry = ARRAY_DICT_INIT; ADD(content_entry, INTEGER_OBJ(p->attr)); - ADD(content_entry, STRING_OBJ(cstr_to_string((char *)(p->msg)))); + ADD(content_entry, STRING_OBJ(cstr_to_string(p->msg))); ADD(content, ARRAY_OBJ(content_entry)); } ADD(entry, ARRAY_OBJ(content)); @@ -1470,9 +1470,9 @@ void msg_putchar_attr(int c, int attr) buf[2] = (char)K_THIRD(c); buf[3] = NUL; } else { - buf[utf_char2bytes(c, (char *)buf)] = NUL; + buf[utf_char2bytes(c, buf)] = NUL; } - msg_puts_attr((const char *)buf, attr); + msg_puts_attr(buf, attr); } void msg_outnum(long n) @@ -2139,7 +2139,7 @@ static void msg_puts_display(const char *str, int maxlen, int attr, int recurse) int t_col = 0; // Screen cells todo, 0 when "t_s" not used. int l; int cw; - const char *sb_str = (char *)str; + const char *sb_str = str; int sb_col = msg_col; int wrap; int did_last_char; @@ -2153,7 +2153,7 @@ static void msg_puts_display(const char *str, int maxlen, int attr, int recurse) } // Concat pieces with the same highlight size_t len = strnlen(str, (size_t)maxlen); // -V781 - ga_concat_len(&msg_ext_last_chunk, (char *)str, len); + ga_concat_len(&msg_ext_last_chunk, str, len); msg_ext_cur_len += len; return; } diff --git a/src/nvim/ops.c b/src/nvim/ops.c index f5f1a456f6..0fb8a8004b 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -926,7 +926,7 @@ int do_record(int c) char *p = (char *)get_recorded(); if (p != NULL) { // Remove escaping for K_SPECIAL in multi-byte chars. - vim_unescape_ks((char_u *)p); + vim_unescape_ks(p); (void)tv_dict_add_str(dict, S_LEN("regcontents"), (const char *)p); } @@ -3848,7 +3848,7 @@ void ex_display(exarg_T *eap) } // display last inserted text - if ((p = (char *)get_last_insert()) != NULL + if ((p = get_last_insert()) != NULL && (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int && !message_filtered(p)) { msg_puts("\n c \". "); @@ -5490,7 +5490,7 @@ void cursor_pos_info(dict_T *dict) validate_virtcol(); col_print(buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1); - col_print((char *)buf2, sizeof(buf2), (int)strlen(p), linetabsize(p)); + col_print(buf2, sizeof(buf2), (int)strlen(p), linetabsize(p)); if (char_count_cursor == byte_count_cursor && char_count == byte_count) { diff --git a/src/nvim/option.c b/src/nvim/option.c index 32c2dc5286..d3fc998274 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -754,7 +754,7 @@ static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, co } } - *errmsg = set_bool_option(opt_idx, (char_u *)varp, (int)value, opt_flags); + *errmsg = set_bool_option(opt_idx, (char *)varp, (int)value, opt_flags); } static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, const set_op_T op, @@ -1109,7 +1109,7 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, } // Set the new value. - *(char_u **)(varp) = (char_u *)newval; + *(char **)(varp) = newval; // origval may be freed by did_set_string_option(), make a copy. char *saved_origval = (origval != NULL) ? xstrdup(origval) : NULL; @@ -1974,7 +1974,7 @@ static void apply_optionset_autocmd(int opt_idx, long opt_flags, long oldval, lo /// @param[in] opt_flags OPT_LOCAL and/or OPT_GLOBAL. /// /// @return NULL on success, error message on error. -static char *set_bool_option(const int opt_idx, char_u *const varp, const int value, +static char *set_bool_option(const int opt_idx, char *const varp, const int value, const int opt_flags) { int old_value = *(int *)varp; @@ -2010,7 +2010,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va // Ensure that options set to p_force_off cannot be enabled. } else if ((int *)varp == &p_force_off && p_force_off == true) { p_force_off = false; - return (char *)e_unsupportedoption; + return e_unsupportedoption; } else if ((int *)varp == &p_lrm) { // 'langremap' -> !'langnoremap' p_lnr = !p_lrm; @@ -2023,7 +2023,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va // delete the undo file, the option may be set again without making // any changes in between. if (curbuf->b_p_udf || p_udf) { - char_u hash[UNDO_HASH_SIZE]; + uint8_t hash[UNDO_HASH_SIZE]; FOR_ALL_BUFFERS(bp) { // When 'undofile' is set globally: for every buffer, otherwise @@ -2103,7 +2103,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va } } } - } else if (varp == (char_u *)&(curbuf->b_p_lisp)) { + } else if (varp == (char *)&(curbuf->b_p_lisp)) { // When 'lisp' option changes include/exclude '-' in // keyword characters. (void)buf_init_chartab(curbuf, false); // ignore errors @@ -3127,7 +3127,7 @@ char *set_option_value(const char *const name, const long number, const char *co if (flags & P_NUM) { return set_num_option(opt_idx, varp, numval, NULL, 0, opt_flags); } - return set_bool_option(opt_idx, varp, (int)numval, opt_flags); + return set_bool_option(opt_idx, (char *)varp, (int)numval, opt_flags); } /// Call set_option_value() and when an error is returned report it. @@ -3218,13 +3218,13 @@ static void showoptions(bool all, int opt_flags) continue; } - char_u *varp = NULL; + char *varp = NULL; if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) != 0) { if (p->indir != PV_NONE) { - varp = (char_u *)get_varp_scope(p, opt_flags); + varp = get_varp_scope(p, opt_flags); } } else { - varp = get_varp(p); + varp = (char *)get_varp(p); } if (varp != NULL && (all == 1 || (all == 0 && !optval_default(p, varp)))) { @@ -3278,7 +3278,7 @@ static void showoptions(bool all, int opt_flags) } /// Return true if option "p" has its default value. -static int optval_default(vimoption_T *p, const char_u *varp) +static int optval_default(vimoption_T *p, const char *varp) { if (varp == NULL) { return true; // hidden option is always at default @@ -3403,7 +3403,7 @@ int makeset(FILE *fd, int opt_flags, int local_only) continue; } // Global values are only written when not at the default value. - if ((opt_flags & OPT_GLOBAL) && optval_default(p, (char_u *)varp)) { + if ((opt_flags & OPT_GLOBAL) && optval_default(p, varp)) { continue; } @@ -3424,7 +3424,7 @@ int makeset(FILE *fd, int opt_flags, int local_only) // default, need to write it too. if (!(opt_flags & OPT_GLOBAL) && !local_only) { char_u *varp_fresh = (char_u *)get_varp_scope(p, OPT_GLOBAL); // local value - if (!optval_default(p, varp_fresh)) { + if (!optval_default(p, (char *)varp_fresh)) { round = 1; varp_local = (char_u *)varp; varp = (char *)varp_fresh; @@ -4966,7 +4966,7 @@ static void option_value2string(vimoption_T *opp, int scope) if (varp == NULL) { // Just in case. NameBuff[0] = NUL; } else if (opp->flags & P_EXPAND) { - home_replace(NULL, varp, (char *)NameBuff, MAXPATHL, false); + home_replace(NULL, varp, NameBuff, MAXPATHL, false); // Translate 'pastetoggle' into special key names. } else if ((char **)opp->var == &p_pt) { str2specialbuf((const char *)p_pt, NameBuff, MAXPATHL); @@ -5187,8 +5187,8 @@ void fill_breakat_flags(void) } if (p_breakat != NULL) { - for (char_u *p = (char_u *)p_breakat; *p; p++) { - breakat_flags[*p] = true; + for (char *p = p_breakat; *p; p++) { + breakat_flags[(uint8_t)(*p)] = true; } } } diff --git a/src/nvim/path.c b/src/nvim/path.c index e4c2253357..9bbf56276e 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -810,7 +810,7 @@ static int find_previous_pathsep(char *path, char **psep) } /// Returns true if "maybe_unique" is unique wrt other_paths in "gap". -/// "maybe_unique" is the end portion of "((char_u **)gap->ga_data)[i]". +/// "maybe_unique" is the end portion of "((char **)gap->ga_data)[i]". static bool is_unique(char *maybe_unique, garray_T *gap, int i) { char **other_paths = gap->ga_data; @@ -879,7 +879,7 @@ static void expand_path_option(char *curdir, garray_T *gap) } STRMOVE(buf + len + 1, buf); STRCPY(buf, curdir); - buf[len] = (char_u)PATHSEP; + buf[len] = PATHSEP; simplify_filename(buf); } @@ -1923,7 +1923,7 @@ void path_fix_case(char *name) xstrlcpy(newname + (tail - name), entry, (size_t)(MAXPATHL - (tail - name) + 1)); FileInfo file_info_new; - if (os_fileinfo_link((char *)newname, &file_info_new) + if (os_fileinfo_link(newname, &file_info_new) && os_fileinfo_id_equal(&file_info, &file_info_new)) { STRCPY(tail, entry); break; @@ -1956,11 +1956,11 @@ bool same_directory(char *f1, char *f2) return false; } - (void)vim_FullName(f1, (char *)ffname, MAXPATHL, false); + (void)vim_FullName(f1, ffname, MAXPATHL, false); t1 = path_tail_with_sep(ffname); t2 = path_tail_with_sep(f2); return t1 - ffname == t2 - f2 - && pathcmp((char *)ffname, f2, (int)(t1 - ffname)) == 0; + && pathcmp(ffname, f2, (int)(t1 - ffname)) == 0; } // Compare path "p[]" to "q[]". diff --git a/src/nvim/search.c b/src/nvim/search.c index 234ffb75cb..74ae76e3b2 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -95,7 +95,7 @@ static struct spat spats[2] = { static int last_idx = 0; // index in spats[] for RE_LAST -static char_u lastc[2] = { NUL, NUL }; // last character searched for +static uint8_t lastc[2] = { NUL, NUL }; // last character searched for static Direction lastcdir = FORWARD; // last direction of character search static int last_t_cmd = true; // last search t_cmd static char lastc_bytes[MB_MAXBYTES + 1]; @@ -439,7 +439,7 @@ int last_csearch_until(void) void set_last_csearch(int c, char *s, int len) { - *lastc = (char_u)c; + *lastc = (uint8_t)c; lastc_bytelen = len; if (len) { memcpy(lastc_bytes, s, (size_t)len); @@ -1053,7 +1053,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, long count, i // Find out the direction of the search. if (dirc == 0) { - dirc = (char_u)spats[0].off.dir; + dirc = (uint8_t)spats[0].off.dir; } else { spats[0].off.dir = (char)dirc; set_vv_searchforward(); @@ -1510,7 +1510,7 @@ int searchc(cmdarg_T *cap, int t_cmd) if (c != NUL) { // normal search: remember args for repeat if (!KeyStuffed) { // don't remember when redoing - *lastc = (char_u)c; + *lastc = (uint8_t)c; set_csearch_direction(dir); set_csearch_until(t_cmd); lastc_bytelen = utf_char2bytes(c, lastc_bytes); @@ -3125,8 +3125,7 @@ static int fuzzy_match_recursive(const char *fuzpat, const char *str, uint32_t s /// normalized and varies with pattern. /// Recursion is limited internally (default=10) to prevent degenerate cases /// (pat_arg="aaaaaa" str="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"). -/// Uses char_u for match indices. Therefore patterns are limited to -/// MAX_FUZZY_MATCHES characters. +/// Patterns are limited to MAX_FUZZY_MATCHES characters. /// /// @return true if "pat_arg" matches "str". Also returns the match score in /// "outScore" and the matching character positions in "matches". diff --git a/src/nvim/sha256.c b/src/nvim/sha256.c index db647f3ecb..f0a9aecdcc 100644 --- a/src/nvim/sha256.c +++ b/src/nvim/sha256.c @@ -201,14 +201,14 @@ void sha256_update(context_sha256_T *ctx, const uint8_t *input, size_t length) memcpy(ctx->buffer + left, input, fill); sha256_process(ctx, ctx->buffer); length -= fill; - input += fill; + input += fill; left = 0; } while (length >= SHA256_BUFFER_SIZE) { sha256_process(ctx, input); length -= SHA256_BUFFER_SIZE; - input += SHA256_BUFFER_SIZE; + input += SHA256_BUFFER_SIZE; } if (length) { diff --git a/src/nvim/shada.c b/src/nvim/shada.c index 90a01aaf97..98f10c0082 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -2579,7 +2579,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef { STATIC_CSTR_AS_STRING("pid"), INTEGER_OBJ((Integer)os_get_pid()) }, { STATIC_CSTR_AS_STRING("encoding"), - STRING_OBJ(cstr_as_string((char *)p_enc)) }, + STRING_OBJ(cstr_as_string(p_enc)) }, }), } } diff --git a/src/nvim/sign.c b/src/nvim/sign.c index 00e282b76e..a288fa2e9d 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -298,8 +298,8 @@ static dict_T *sign_get_info(sign_entry_T *sign) dict_T *d = tv_dict_alloc(); tv_dict_add_nr(d, S_LEN("id"), sign->se_id); tv_dict_add_str(d, S_LEN("group"), ((sign->se_group == NULL) - ? (char *)"" - : (char *)sign->se_group->sg_name)); + ? "" + : sign->se_group->sg_name)); tv_dict_add_nr(d, S_LEN("lnum"), sign->se_lnum); tv_dict_add_str(d, S_LEN("name"), sign_typenr2name(sign->se_typenr)); tv_dict_add_nr(d, S_LEN("priority"), sign->se_priority); @@ -576,7 +576,7 @@ static linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char *group) lnum = sign->se_lnum; buf_signcols_del_check(buf, lnum, lnum); if (sign->se_group != NULL) { - sign_group_unref((char *)sign->se_group->sg_name); + sign_group_unref(sign->se_group->sg_name); } xfree(sign); redraw_buf_line_later(buf, lnum, false); @@ -688,7 +688,7 @@ void buf_delete_signs(buf_T *buf, char *group) next->se_prev = sign->se_prev; } if (sign->se_group != NULL) { - sign_group_unref((char *)sign->se_group->sg_name); + sign_group_unref(sign->se_group->sg_name); } xfree(sign); } else { @@ -1778,7 +1778,7 @@ static char *get_nth_sign_group_name(int idx) todo--; if (current_idx++ == idx) { signgroup_T *const group = HI2SG(hi); - return (char *)group->sg_name; + return group->sg_name; } } } diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 8ef3aed417..117a770e50 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -437,14 +437,14 @@ static void find_word(matchinf_T *mip, int mode) int flen; char *ptr; slang_T *slang = mip->mi_lp->lp_slang; - char_u *byts; + uint8_t *byts; idx_T *idxs; if (mode == FIND_KEEPWORD || mode == FIND_KEEPCOMPOUND) { // Check for word with matching case in keep-case tree. ptr = mip->mi_word; flen = 9999; // no case folding, always enough bytes - byts = (char_u *)slang->sl_kbyts; + byts = (uint8_t *)slang->sl_kbyts; idxs = slang->sl_kidxs; if (mode == FIND_KEEPCOMPOUND) { @@ -455,7 +455,7 @@ static void find_word(matchinf_T *mip, int mode) // Check for case-folded in case-folded tree. ptr = mip->mi_fword; flen = mip->mi_fwordlen; // available case-folded bytes - byts = (char_u *)slang->sl_fbyts; + byts = (uint8_t *)slang->sl_fbyts; idxs = slang->sl_fidxs; if (mode == FIND_PREFIX) { @@ -964,7 +964,7 @@ bool can_compound(slang_T *slang, const char *word, const uint8_t *flags) bool match_compoundrule(slang_T *slang, const char_u *compflags) { // loop over all the COMPOUNDRULE entries - for (char_u *p = (char_u *)slang->sl_comprules; *p != NUL; p++) { + for (char *p = (char *)slang->sl_comprules; *p != NUL; p++) { // loop over the flags in the compound word we have made, match // them against the current rule entry for (int i = 0;; i++) { @@ -982,21 +982,21 @@ bool match_compoundrule(slang_T *slang, const char_u *compflags) // compare against all the flags in [] p++; while (*p != ']' && *p != NUL) { - if (*p++ == c) { + if ((uint8_t)(*p++) == c) { match = true; } } if (!match) { break; // none matches } - } else if (*p != c) { + } else if ((uint8_t)(*p) != c) { break; // flag of word doesn't match flag in pattern } p++; } // Skip to the next "/", where the next pattern starts. - p = (char_u *)vim_strchr((char *)p, '/'); + p = vim_strchr(p, '/'); if (p == NULL) { break; } @@ -1062,13 +1062,13 @@ static void find_prefix(matchinf_T *mip, int mode) int wlen = 0; slang_T *slang = mip->mi_lp->lp_slang; - char_u *byts = (char_u *)slang->sl_pbyts; + uint8_t *byts = (uint8_t *)slang->sl_pbyts; if (byts == NULL) { return; // array is empty } // We use the case-folded word here, since prefixes are always // case-folded. - char_u *ptr = (char_u *)mip->mi_fword; + char *ptr = mip->mi_fword; int flen = mip->mi_fwordlen; // available case-folded bytes if (mode == FIND_COMPOUND) { // Skip over the previously found word(s). @@ -1126,7 +1126,7 @@ static void find_prefix(matchinf_T *mip, int mode) } // Perform a binary search in the list of accepted bytes. - int c = ptr[wlen]; + int c = (uint8_t)ptr[wlen]; idx_T lo = arridx; idx_T hi = arridx + len - 1; while (lo < hi) { @@ -1483,9 +1483,9 @@ theend: // to skip those bytes if the word was OK. void spell_cat_line(char *buf, char *line, int maxlen) { - char_u *p = (char_u *)skipwhite(line); + char *p = skipwhite(line); while (vim_strchr("*#/\"\t", (uint8_t)(*p)) != NULL) { - p = (char_u *)skipwhite((char *)p + 1); + p = skipwhite(p + 1); } if (*p == NUL) { @@ -1494,10 +1494,10 @@ void spell_cat_line(char *buf, char *line, int maxlen) // Only worth concatenating if there is something else than spaces to // concatenate. - int n = (int)(p - (char_u *)line) + 1; + int n = (int)(p - line) + 1; if (n < maxlen - 1) { memset(buf, ' ', (size_t)n); - xstrlcpy(buf + n, (char *)p, (size_t)(maxlen - n)); + xstrlcpy(buf + n, p, (size_t)(maxlen - n)); } } @@ -1775,7 +1775,7 @@ bool byte_in_str(uint8_t *str, int n) int init_syl_tab(slang_T *slang) { ga_init(&slang->sl_syl_items, sizeof(syl_item_T), 4); - char *p = vim_strchr((char *)slang->sl_syllable, '/'); + char *p = vim_strchr(slang->sl_syllable, '/'); while (p != NULL) { *p++ = NUL; if (*p == NUL) { // trailing slash @@ -1838,7 +1838,7 @@ static int count_syllables(slang_T *slang, const char *word) // No recognized syllable item, at least a syllable char then? int c = utf_ptr2char(p); len = utfc_ptr2len(p); - if (vim_strchr((char *)slang->sl_syllable, c) == NULL) { + if (vim_strchr(slang->sl_syllable, c) == NULL) { skip = false; // No, search for next syllable } else if (!skip) { cnt++; // Yes, count it @@ -2167,7 +2167,7 @@ static void use_midword(slang_T *lp, win_T *wp) return; } - for (char *p = (char *)lp->sl_midword; *p != NUL;) { + for (char *p = lp->sl_midword; *p != NUL;) { const int c = utf_ptr2char(p); const int l = utfc_ptr2len(p); if (c < 256 && l <= 2) { @@ -2660,24 +2660,24 @@ void onecap_copy(char *word, char *wcopy, bool upper) // "wcopy[MAXWLEN]". The result is NUL terminated. void allcap_copy(char *word, char *wcopy) { - char_u *d = (char_u *)wcopy; + char *d = wcopy; for (char *s = word; *s != NUL;) { int c = mb_cptr2char_adv((const char **)&s); if (c == 0xdf) { c = 'S'; - if (d - (char_u *)wcopy >= MAXWLEN - 1) { + if (d - wcopy >= MAXWLEN - 1) { break; } - *d++ = (char_u)c; + *d++ = (char)c; } else { c = SPELL_TOUPPER(c); } - if (d - (char_u *)wcopy >= MAXWLEN - MB_MAXBYTES) { + if (d - wcopy >= MAXWLEN - MB_MAXBYTES) { break; } - d += utf_char2bytes(c, (char *)d); + d += utf_char2bytes(c, d); } *d = NUL; } @@ -2846,7 +2846,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) // But keep white space. int wordlen = 0; for (const char *s = (char *)inword; *s != NUL;) { - const char_u *t = (char_u *)s; + const char *t = s; int c = mb_cptr2char_adv(&s); if (slang->sl_rem_accents) { if (utf_class(c) == 0) { @@ -2857,7 +2857,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) did_white = true; } else { did_white = false; - if (!spell_iswordp_nmw((char *)t, curwin)) { + if (!spell_iswordp_nmw(t, curwin)) { continue; } } @@ -2914,10 +2914,10 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) } k++; } - char_u *s = (char_u *)smp[n].sm_rules; + char *s = smp[n].sm_rules; pri = 5; // default priority - p0 = *s; + p0 = (uint8_t)(*s); k0 = k; while (*s == '-' && k > 1) { k--; @@ -2928,7 +2928,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) } if (ascii_isdigit(*s)) { // determine priority - pri = *s - '0'; + pri = (uint8_t)(*s) - '0'; s++; } if (*s == '^' && *(s + 1) == '^') { @@ -2991,7 +2991,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) } p0 = 5; - s = (char_u *)smp[n0].sm_rules; + s = smp[n0].sm_rules; while (*s == '-') { // "k0" gets NOT reduced because // "if (k0 == k)" @@ -3001,7 +3001,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) s++; } if (ascii_isdigit(*s)) { - p0 = *s - '0'; + p0 = (uint8_t)(*s) - '0'; s++; } @@ -3032,8 +3032,8 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) // replace string ws = smp[n].sm_to_w; - s = (char_u *)smp[n].sm_rules; - p0 = (vim_strchr((char *)s, '<') != NULL) ? 1 : 0; + s = smp[n].sm_rules; + p0 = (vim_strchr(s, '<') != NULL) ? 1 : 0; if (p0 == 1 && z == 0) { // rule with '<' is used if (reslen > 0 && ws != NULL && *ws != NUL @@ -3076,7 +3076,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res) } else { c = *ws; } - if (strstr((char *)s, "^^") != NULL) { + if (strstr(s, "^^") != NULL) { if (c != NUL) { wres[reslen++] = c; } @@ -3462,7 +3462,7 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char *pat, Direction * has_word_up = true; } - char_u *byts = (char_u *)slang->sl_pbyts; + char *byts = slang->sl_pbyts; idx_T *idxs = slang->sl_pidxs; if (byts != NULL) { // array not is empty // Loop over all prefixes, building them byte-by-byte in prefix[]. @@ -3472,7 +3472,7 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char *pat, Direction * curi[0] = 1; while (depth >= 0 && !got_int) { int n = arridx[depth]; - int len = byts[n]; + int len = (uint8_t)byts[n]; if (curi[depth] > len) { // Done all bytes at this node, go up one level. depth--; @@ -3481,7 +3481,7 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char *pat, Direction * // Do one more byte at this node. n += curi[depth]; curi[depth]++; - c = byts[n]; + c = (uint8_t)byts[n]; if (c == 0) { // End of prefix, find out how many IDs there are. int i; diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h index 4d365deab1..93cf335c3a 100644 --- a/src/nvim/spell_defs.h +++ b/src/nvim/spell_defs.h @@ -82,7 +82,7 @@ typedef struct fromto_S { typedef struct salitem_S { char *sm_lead; // leading letters int sm_leadlen; // length of "sm_lead" - char_u *sm_oneof; // letters from () or NULL + char *sm_oneof; // letters from () or NULL char *sm_rules; // rules like ^, $, priority char *sm_to; // replacement. int *sm_lead_w; // wide character copy of "sm_lead" @@ -119,20 +119,20 @@ struct slang_S { char *sl_fname; // name of .spl file bool sl_add; // true if it's a .add file. - char *sl_fbyts; // case-folded word bytes - long sl_fbyts_len; // length of sl_fbyts - idx_T *sl_fidxs; // case-folded word indexes - char *sl_kbyts; // keep-case word bytes - idx_T *sl_kidxs; // keep-case word indexes - char *sl_pbyts; // prefix tree word bytes - idx_T *sl_pidxs; // prefix tree word indexes + char *sl_fbyts; // case-folded word bytes + long sl_fbyts_len; // length of sl_fbyts + idx_T *sl_fidxs; // case-folded word indexes + char *sl_kbyts; // keep-case word bytes + idx_T *sl_kidxs; // keep-case word indexes + char *sl_pbyts; // prefix tree word bytes + idx_T *sl_pidxs; // prefix tree word indexes - char_u *sl_info; // infotext string or NULL + char *sl_info; // infotext string or NULL char sl_regions[MAXREGIONS * 2 + 1]; // table with up to 8 region names plus NUL - char_u *sl_midword; // MIDWORD string or NULL + char *sl_midword; // MIDWORD string or NULL hashtab_T sl_wordcount; // hashtable with word count, wordcount_T @@ -141,13 +141,13 @@ struct slang_S { int sl_compsylmax; // COMPOUNDSYLMAX (default: MAXWLEN) int sl_compoptions; // COMP_* flags garray_T sl_comppat; // CHECKCOMPOUNDPATTERN items - regprog_T *sl_compprog; // COMPOUNDRULE turned into a regexp progrm - // (NULL when no compounding) + regprog_T *sl_compprog; // COMPOUNDRULE turned into a regexp progrm + // (NULL when no compounding) uint8_t *sl_comprules; // all COMPOUNDRULE concatenated (or NULL) uint8_t *sl_compstartflags; // flags for first compound word uint8_t *sl_compallflags; // all flags for compound words bool sl_nobreak; // When true: no spaces between words - char_u *sl_syllable; // SYLLABLE repeatable chars or NULL + char *sl_syllable; // SYLLABLE repeatable chars or NULL garray_T sl_syl_items; // syllable items int sl_prefixcnt; // number of items in "sl_prefprog" diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 594b05dd6b..22a8587f66 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -386,7 +386,7 @@ typedef struct affheader_S { // Flag used in compound items. typedef struct compitem_S { - char_u ci_key[AH_KEY_LEN]; // key for hashtab == name of compound + char ci_key[AH_KEY_LEN]; // key for hashtab == name of compound unsigned ci_flag; // affix name as number, uses "af_flagtype" int ci_newID; // affix ID after renumbering. } compitem_T; @@ -674,7 +674,7 @@ slang_T *spell_load_file(char *fname, char *lang, slang_T *old_lp, bool silent) res = 0; switch (n) { case SN_INFO: - lp->sl_info = READ_STRING(fd, len); // + lp->sl_info = read_string(fd, (size_t)len); // if (lp->sl_info == NULL) { goto endFAIL; } @@ -689,7 +689,7 @@ slang_T *spell_load_file(char *fname, char *lang, slang_T *old_lp, bool silent) break; case SN_MIDWORD: - lp->sl_midword = READ_STRING(fd, len); // + lp->sl_midword = read_string(fd, (size_t)len); // if (lp->sl_midword == NULL) { goto endFAIL; } @@ -716,7 +716,7 @@ slang_T *spell_load_file(char *fname, char *lang, slang_T *old_lp, bool silent) break; case SN_MAP: - p = (char *)READ_STRING(fd, len); // + p = read_string(fd, (size_t)len); // if (p == NULL) { goto endFAIL; } @@ -749,7 +749,7 @@ slang_T *spell_load_file(char *fname, char *lang, slang_T *old_lp, bool silent) break; case SN_SYLLABLE: - lp->sl_syllable = READ_STRING(fd, len); // + lp->sl_syllable = read_string(fd, (size_t)len); // if (lp->sl_syllable == NULL) { goto endFAIL; } @@ -838,8 +838,9 @@ endOK: // Fill in the wordcount fields for a trie. // Returns the total number of words. -static void tree_count_words(const char_u *byts, idx_T *idxs) +static void tree_count_words(const char *byts_in, idx_T *idxs) { + const uint8_t *byts= (const uint8_t *)byts_in; int depth; idx_T arridx[MAXWLEN]; int curi[MAXWLEN]; @@ -1000,8 +1001,8 @@ someerror: // Need to put word counts in the word tries, so that we can find // a word by its number. - tree_count_words((char_u *)slang->sl_fbyts, slang->sl_fidxs); - tree_count_words((char_u *)slang->sl_sbyts, slang->sl_sidxs); + tree_count_words(slang->sl_fbyts, slang->sl_fidxs); + tree_count_words(slang->sl_sbyts, slang->sl_sidxs); nextone: if (fd != NULL) { @@ -1017,10 +1018,10 @@ nextone: // Returns NULL when the count is zero. // Sets "*cntp" to SP_*ERROR when there is an error, length of the result // otherwise. -static char_u *read_cnt_string(FILE *fd, int cnt_bytes, int *cntp) +static char *read_cnt_string(FILE *fd, int cnt_bytes, int *cntp) { int cnt = 0; - char_u *str; + char *str; // read the length bytes, MSB first for (int i = 0; i < cnt_bytes; i++) { @@ -1036,7 +1037,7 @@ static char_u *read_cnt_string(FILE *fd, int cnt_bytes, int *cntp) if (cnt == 0) { return NULL; // nothing to read, return NULL } - str = READ_STRING(fd, cnt); + str = read_string(fd, (size_t)cnt); if (str == NULL) { *cntp = SP_OTHERERROR; } @@ -1065,13 +1066,13 @@ static int read_charflags_section(FILE *fd) int flagslen, follen; // - flags = (char *)read_cnt_string(fd, 1, &flagslen); + flags = read_cnt_string(fd, 1, &flagslen); if (flagslen < 0) { return flagslen; } // - fol = read_cnt_string(fd, 2, &follen); + fol = (char_u *)read_cnt_string(fd, 2, &follen); if (follen < 0) { xfree(flags); return follen; @@ -1143,14 +1144,14 @@ static int read_rep_section(FILE *fd, garray_T *gap, int16_t *first) for (; gap->ga_len < cnt; gap->ga_len++) { int c; ftp = &((fromto_T *)gap->ga_data)[gap->ga_len]; - ftp->ft_from = (char *)read_cnt_string(fd, 1, &c); + ftp->ft_from = read_cnt_string(fd, 1, &c); if (c < 0) { return c; } if (c == 0) { return SP_FORMERROR; } - ftp->ft_to = (char *)read_cnt_string(fd, 1, &c); + ftp->ft_to = read_cnt_string(fd, 1, &c); if (c <= 0) { xfree(ftp->ft_from); if (c < 0) { @@ -1181,7 +1182,7 @@ static int read_sal_section(FILE *fd, slang_T *slang) garray_T *gap; salitem_T *smp; int ccnt; - char_u *p; + char *p; slang->sl_sofo = false; @@ -1215,7 +1216,7 @@ static int read_sal_section(FILE *fd, slang_T *slang) return SP_TRUNCERROR; } p = xmalloc((size_t)ccnt + 2); - smp->sm_lead = (char *)p; + smp->sm_lead = p; // Read up to the first special char into sm_lead. int i = 0; @@ -1224,9 +1225,9 @@ static int read_sal_section(FILE *fd, slang_T *slang) if (vim_strchr("0123456789(-<^$", c) != NULL) { break; } - *p++ = (char_u)c; + *p++ = (char)(uint8_t)c; } - smp->sm_leadlen = (int)(p - (char_u *)smp->sm_lead); + smp->sm_leadlen = (int)(p - smp->sm_lead); *p++ = NUL; // Put (abc) chars in sm_oneof, if any. @@ -1237,7 +1238,7 @@ static int read_sal_section(FILE *fd, slang_T *slang) if (c == ')') { break; } - *p++ = (char_u)c; + *p++ = (char)(uint8_t)c; } *p++ = NUL; if (++i < ccnt) { @@ -1248,22 +1249,22 @@ static int read_sal_section(FILE *fd, slang_T *slang) } // Any following chars go in sm_rules. - smp->sm_rules = (char *)p; + smp->sm_rules = p; if (i < ccnt) { // store the char we got while checking for end of sm_lead - *p++ = (char_u)c; + *p++ = (char)(uint8_t)c; } i++; if (i < ccnt) { SPELL_READ_NONNUL_BYTES( // - (char *)p, (size_t)(ccnt - i), fd, + p, (size_t)(ccnt - i), fd, xfree(smp->sm_lead)); p += (ccnt - i); } *p++ = NUL; // - smp->sm_to = (char *)read_cnt_string(fd, 1, &ccnt); + smp->sm_to = read_cnt_string(fd, 1, &ccnt); if (ccnt < 0) { xfree(smp->sm_lead); return ccnt; @@ -1275,7 +1276,7 @@ static int read_sal_section(FILE *fd, slang_T *slang) if (smp->sm_oneof == NULL) { smp->sm_oneof_w = NULL; } else { - smp->sm_oneof_w = mb_str2wide((char *)smp->sm_oneof); + smp->sm_oneof_w = mb_str2wide(smp->sm_oneof); } if (smp->sm_to == NULL) { smp->sm_to_w = NULL; @@ -1290,12 +1291,12 @@ static int read_sal_section(FILE *fd, slang_T *slang) smp = &((salitem_T *)gap->ga_data)[gap->ga_len]; p = xmalloc(1); p[0] = NUL; - smp->sm_lead = (char *)p; + smp->sm_lead = p; smp->sm_lead_w = mb_str2wide(smp->sm_lead); smp->sm_leadlen = 0; smp->sm_oneof = NULL; smp->sm_oneof_w = NULL; - smp->sm_rules = (char *)p; + smp->sm_rules = p; smp->sm_to = NULL; smp->sm_to_w = NULL; gap->ga_len++; @@ -1350,13 +1351,13 @@ static int read_sofo_section(FILE *fd, slang_T *slang) slang->sl_sofo = true; // - from = (char *)read_cnt_string(fd, 2, &cnt); + from = read_cnt_string(fd, 2, &cnt); if (cnt < 0) { return cnt; } // - to = (char *)read_cnt_string(fd, 2, &cnt); + to = read_cnt_string(fd, 2, &cnt); if (cnt < 0) { xfree(from); return cnt; @@ -1428,7 +1429,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len) ga_init(gap, sizeof(char *), c); ga_grow(gap, c); while (--c >= 0) { - ((char **)(gap->ga_data))[gap->ga_len++] = (char *)read_cnt_string(fd, 1, &cnt); + ((char **)(gap->ga_data))[gap->ga_len++] = read_cnt_string(fd, 1, &cnt); // if (cnt < 0) { return cnt; @@ -1464,7 +1465,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len) uint8_t *crp = xmalloc((size_t)todo + 1); slang->sl_comprules = crp; - char_u *pp = (char_u *)pat; + char *pp = pat; *pp++ = '^'; *pp++ = '\\'; *pp++ = '('; @@ -1520,7 +1521,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len) if (c == '?' || c == '+' || c == '~') { *pp++ = '\\'; // "a?" becomes "a\?", "a+" becomes "a\+" } - pp += utf_char2bytes(c, (char *)pp); + pp += utf_char2bytes(c, pp); } } @@ -1954,9 +1955,9 @@ static void spell_print_node(wordnode_T *node, int depth) PRINTSOME(line1, depth, "(%d)", node->wn_nr, 0); PRINTSOME(line2, depth, " ", 0, 0); PRINTSOME(line3, depth, " ", 0, 0); - msg((char_u *)line1); - msg((char_u *)line2); - msg((char_u *)line3); + msg(line1); + msg(line2); + msg(line3); } else { node->wn_u1.index = true; @@ -1980,9 +1981,9 @@ static void spell_print_node(wordnode_T *node, int depth) } if (node->wn_byte == NUL) { - msg((char_u *)line1); - msg((char_u *)line2); - msg((char_u *)line3); + msg(line1); + msg(line2); + msg(line3); } // do the children @@ -2789,7 +2790,7 @@ static void aff_process_flags(afffile_T *affile, affentry_T *entry) char_u *prevp = (char_u *)p; unsigned flag = get_affitem(affile->af_flagtype, &p); if (flag == affile->af_comppermit || flag == affile->af_compforbid) { - STRMOVE(prevp, (char *)p); + STRMOVE(prevp, p); p = (char *)prevp; if (flag == affile->af_comppermit) { entry->ae_comppermit = true; @@ -2925,9 +2926,9 @@ static void process_compflags(spellinfo_T *spin, afffile_T *aff, char *compflags id = spin->si_newcompID--; } while (vim_strchr("/?*+[]\\-^", id) != NULL); ci->ci_newID = id; - hash_add(&aff->af_comp, (char *)ci->ci_key); + hash_add(&aff->af_comp, ci->ci_key); } - *tp++ = (char_u)id; + *tp++ = (uint8_t)id; } if (aff->af_flagtype == AFT_NUM && *p == ',') { p++; @@ -3079,21 +3080,21 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile) { hashtab_T ht; char line[MAXLINELEN]; - char_u *p; - char_u *afflist; - char_u store_afflist[MAXWLEN]; + char *p; + char *afflist; + char store_afflist[MAXWLEN]; int pfxlen; bool need_affix; char *dw; - char_u *pc; - char_u *w; + char *pc; + char *w; int l; hash_T hash; hashitem_T *hi; int lnum = 1; int non_ascii = 0; int retval = OK; - char_u message[MAXLINELEN + MAXWLEN]; + char message[MAXLINELEN + MAXWLEN]; int flags; int duplicate = 0; Timestamp last_msg_time = 0; @@ -3142,7 +3143,7 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile) // Convert from "SET" to 'encoding' when needed. if (spin->si_conv.vc_type != CONV_NONE) { - pc = (char_u *)string_convert(&spin->si_conv, (char *)line, NULL); + pc = string_convert(&spin->si_conv, (char *)line, NULL); if (pc == NULL) { smsg(_("Conversion failure for word in %s line %d: %s"), fname, lnum, line); @@ -3151,7 +3152,7 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile) w = pc; } else { pc = NULL; - w = (char_u *)line; + w = line; } // Truncate the word at the "/", set "afflist" to what follows. @@ -3159,7 +3160,7 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile) afflist = NULL; for (p = w; *p != NUL; MB_PTR_ADV(p)) { if (*p == '\\' && (p[1] == '\\' || p[1] == '/')) { - STRMOVE(p, (char *)p + 1); + STRMOVE(p, p + 1); } else if (*p == '/') { *p = NUL; afflist = p + 1; @@ -3168,7 +3169,7 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile) } // Skip non-ASCII words when "spin->si_ascii" is true. - if (spin->si_ascii && has_non_ascii((char *)w)) { + if (spin->si_ascii && has_non_ascii(w)) { non_ascii++; xfree(pc); continue; @@ -3180,11 +3181,11 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile) spin->si_msg_count = 0; if (os_time() > last_msg_time) { last_msg_time = os_time(); - vim_snprintf((char *)message, sizeof(message), + vim_snprintf(message, sizeof(message), _("line %6d, word %6ld - %s"), lnum, spin->si_foldwcount + spin->si_keepwcount, w); msg_start(); - msg_outtrans_long_attr((char *)message, 0); + msg_outtrans_long_attr(message, 0); msg_clr_eos(); msg_didout = false; msg_col = 0; @@ -3193,7 +3194,7 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile) } // Store the word in the hashtable to be able to find duplicates. - dw = getroom_save(spin, (char *)w); + dw = getroom_save(spin, w); if (dw == NULL) { retval = FAIL; xfree(pc); @@ -3201,7 +3202,7 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile) } hash = hash_hash(dw); - hi = hash_lookup(&ht, (const char *)dw, strlen(dw), hash); + hi = hash_lookup(&ht, dw, strlen(dw), hash); if (!HASHITEM_EMPTY(hi)) { if (p_verbose > 0) { smsg(_("Duplicate word in %s line %d: %s"), @@ -3221,45 +3222,45 @@ static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile) need_affix = false; if (afflist != NULL) { // Extract flags from the affix list. - flags |= get_affix_flags(affile, (char *)afflist); + flags |= get_affix_flags(affile, afflist); if (affile->af_needaffix != 0 - && flag_in_afflist(affile->af_flagtype, (char *)afflist, + && flag_in_afflist(affile->af_flagtype, afflist, affile->af_needaffix)) { need_affix = true; } if (affile->af_pfxpostpone) { // Need to store the list of prefix IDs with the word. - pfxlen = get_pfxlist(affile, (char *)afflist, store_afflist); + pfxlen = get_pfxlist(affile, afflist, store_afflist); } if (spin->si_compflags != NULL) { // Need to store the list of compound flags with the word. // Concatenate them to the list of prefix IDs. - get_compflags(affile, (char *)afflist, store_afflist + pfxlen); + get_compflags(affile, afflist, (char_u *)store_afflist + pfxlen); } } // Add the word to the word tree(s). if (store_word(spin, dw, flags, spin->si_region, - (char *)store_afflist, need_affix) == FAIL) { + store_afflist, need_affix) == FAIL) { retval = FAIL; } if (afflist != NULL) { // Find all matching suffixes and add the resulting words. // Additionally do matching prefixes that combine. - if (store_aff_word(spin, dw, (char *)afflist, affile, + if (store_aff_word(spin, dw, afflist, affile, &affile->af_suff, &affile->af_pref, - CONDIT_SUF, flags, (char *)store_afflist, pfxlen) == FAIL) { + CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL) { retval = FAIL; } // Find all matching prefixes and add the resulting words. - if (store_aff_word(spin, dw, (char *)afflist, affile, + if (store_aff_word(spin, dw, afflist, affile, &affile->af_pref, NULL, - CONDIT_SUF, flags, (char *)store_afflist, pfxlen) == FAIL) { + CONDIT_SUF, flags, store_afflist, pfxlen) == FAIL) { retval = FAIL; } } @@ -3321,7 +3322,7 @@ static int get_affix_flags(afffile_T *affile, char *afflist) // Used for PFXPOSTPONE. // Put the resulting flags in "store_afflist[MAXWLEN]" with a terminating NUL // and return the number of affixes. -static int get_pfxlist(afffile_T *affile, char *afflist, char_u *store_afflist) +static int get_pfxlist(afffile_T *affile, char *afflist, char *store_afflist) { int cnt = 0; int id; @@ -3338,7 +3339,7 @@ static int get_pfxlist(afffile_T *affile, char *afflist, char_u *store_afflist) if (!HASHITEM_EMPTY(hi)) { id = HI2AH(hi)->ah_newID; if (id != 0) { - store_afflist[cnt++] = (char_u)id; + store_afflist[cnt++] = (char)(uint8_t)id; } } } @@ -3408,7 +3409,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char *afflist, afffile_ char *use_pfxlist; int use_pfxlen; bool need_affix; - char_u store_afflist[MAXWLEN]; + char store_afflist[MAXWLEN]; char pfx_pfxlist[MAXWLEN]; size_t wordlen = strlen(word); int use_condit; @@ -3517,7 +3518,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char *afflist, afffile_ } else { use_pfxlen = 0; } - use_pfxlist = (char *)store_afflist; + use_pfxlist = store_afflist; // Combine the prefix IDs. Avoid adding the // same ID twice. @@ -3642,7 +3643,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char *fname) long lnum = 0; char rline[MAXLINELEN]; char *line; - char_u *pc = NULL; + char *pc = NULL; char_u *p; int l; int retval = OK; @@ -3684,13 +3685,13 @@ static int spell_read_wordfile(spellinfo_T *spin, char *fname) // Convert from "/encoding={encoding}" to 'encoding' when needed. xfree(pc); if (spin->si_conv.vc_type != CONV_NONE) { - pc = (char_u *)string_convert(&spin->si_conv, rline, NULL); + pc = string_convert(&spin->si_conv, rline, NULL); if (pc == NULL) { smsg(_("Conversion failure for word in %s line %ld: %s"), fname, lnum, rline); continue; } - line = (char *)pc; + line = pc; } else { pc = NULL; line = rline; @@ -3907,7 +3908,7 @@ static int store_word(spellinfo_T *spin, char *word, int flags, int region, cons { int len = (int)strlen(word); int ct = captype(word, word + len); - char_u foldword[MAXWLEN]; + char foldword[MAXWLEN]; int res = OK; // Avoid adding illegal bytes to the word tree. @@ -3915,10 +3916,10 @@ static int store_word(spellinfo_T *spin, char *word, int flags, int region, cons return FAIL; } - (void)spell_casefold(curwin, word, len, (char *)foldword, MAXWLEN); + (void)spell_casefold(curwin, word, len, foldword, MAXWLEN); for (const char_u *p = (char_u *)pfxlist; res == OK; p++) { if (!need_affix || (p != NULL && *p != NUL)) { - res = tree_add_word(spin, foldword, spin->si_foldroot, ct | flags, + res = tree_add_word(spin, (char_u *)foldword, spin->si_foldroot, ct | flags, region, p == NULL ? 0 : *p); } if (p == NULL || *p == NUL) { diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c index 0ddf07e3a6..c5efe6e94b 100644 --- a/src/nvim/spellsuggest.c +++ b/src/nvim/spellsuggest.c @@ -74,9 +74,9 @@ typedef struct suginfo_S { char *su_badptr; ///< start of bad word in line int su_badlen; ///< length of detected bad word in line int su_badflags; ///< caps flags for bad word - char_u su_badword[MAXWLEN]; ///< bad word truncated at su_badlen + char su_badword[MAXWLEN]; ///< bad word truncated at su_badlen char su_fbadword[MAXWLEN]; ///< su_badword case-folded - char_u su_sal_badword[MAXWLEN]; ///< su_badword soundfolded + char su_sal_badword[MAXWLEN]; ///< su_badword soundfolded hashtab_T su_banned; ///< table with banned words slang_T *su_sallang; ///< default language for sound folding } suginfo_T; @@ -269,13 +269,13 @@ static bool can_be_compound(trystate_T *sp, slang_T *slang, char_u *compflags, i /// Adjust the score of common words. /// /// @param split word was split, less bonus -static int score_wordcount_adj(slang_T *slang, int score, char_u *word, bool split) +static int score_wordcount_adj(slang_T *slang, int score, char *word, bool split) { wordcount_T *wc; int bonus; int newscore; - hashitem_T *hi = hash_find(&slang->sl_wordcount, (char *)word); + hashitem_T *hi = hash_find(&slang->sl_wordcount, word); if (HASHITEM_EMPTY(hi)) { return score; } @@ -302,14 +302,14 @@ static int score_wordcount_adj(slang_T *slang, int score, char_u *word, bool spl /// Like captype() but for a KEEPCAP word add ONECAP if the word starts with a /// capital. So that make_case_word() can turn WOrd into Word. /// Add ALLCAP for "WOrD". -static int badword_captype(char_u *word, char_u *end) +static int badword_captype(char *word, char *end) FUNC_ATTR_NONNULL_ALL { - int flags = captype((char *)word, (char *)end); + int flags = captype(word, end); int c; int l, u; bool first; - char_u *p; + char *p; if (!(flags & WF_KEEPCAP)) { return flags; @@ -319,7 +319,7 @@ static int badword_captype(char_u *word, char_u *end) l = u = 0; first = false; for (p = word; p < end; MB_PTR_ADV(p)) { - c = utf_ptr2char((char *)p); + c = utf_ptr2char(p); if (SPELL_ISUPPER(c)) { u++; if (p == word) { @@ -351,9 +351,9 @@ static int badword_captype(char_u *word, char_u *end) /// "pp" points to the bytes and is advanced over it. /// /// @return the offset. -static int bytes2offset(char_u **pp) +static int bytes2offset(char **pp) { - char_u *p = *pp; + char_u *p = (char_u *)(*pp); int nr; int c; @@ -374,7 +374,7 @@ static int bytes2offset(char_u **pp) nr = nr * 255 + (*p++ - 1); } - *pp = p; + *pp = (char *)p; return nr; } @@ -401,11 +401,11 @@ int spell_check_sps(void) sps_limit = 9999; for (p = p_sps; *p != NUL;) { - copy_option_part(&p, (char *)buf, MAXPATHL, ","); + copy_option_part(&p, buf, MAXPATHL, ","); f = 0; if (ascii_isdigit(*buf)) { - s = (char *)buf; + s = buf; sps_limit = getdigits_int(&s, true, 0); if (*s != NUL && !ascii_isdigit(*s)) { f = -1; @@ -450,7 +450,7 @@ void spell_suggest(int count) char *line; pos_T prev_cursor = curwin->w_cursor; char wcopy[MAXWLEN + 2]; - char_u *p; + char *p; int c; suginfo_T sug; suggest_T *stp; @@ -499,21 +499,21 @@ void spell_suggest(int count) // cursor. curwin->w_cursor = prev_cursor; line = get_cursor_line_ptr(); - p = (char_u *)line + curwin->w_cursor.col; + p = line + curwin->w_cursor.col; // Backup to before start of word. - while (p > (char_u *)line && spell_iswordp_nmw((char *)p, curwin)) { + while (p > line && spell_iswordp_nmw(p, curwin)) { MB_PTR_BACK(line, p); } // Forward to start of word. - while (*p != NUL && !spell_iswordp_nmw((char *)p, curwin)) { + while (*p != NUL && !spell_iswordp_nmw(p, curwin)) { MB_PTR_ADV(p); } - if (!spell_iswordp_nmw((char *)p, curwin)) { // No word found. + if (!spell_iswordp_nmw(p, curwin)) { // No word found. beep_flush(); return; } - curwin->w_cursor.col = (colnr_T)(p - (char_u *)line); + curwin->w_cursor.col = (colnr_T)(p - line); } // Get the word and its length. @@ -532,7 +532,7 @@ void spell_suggest(int count) } else { limit = sps_limit; } - spell_find_suggest((char_u *)line + curwin->w_cursor.col, badlen, &sug, limit, + spell_find_suggest(line + curwin->w_cursor.col, badlen, &sug, limit, true, need_cap, true); if (GA_EMPTY(&sug.su_ga)) { @@ -659,12 +659,12 @@ void spell_suggest(int count) // For redo we use a change-word command. ResetRedobuff(); AppendToRedobuff("ciw"); - AppendToRedobuffLit((char *)p + c, + AppendToRedobuffLit(p + c, stp->st_wordlen + sug.su_badlen - stp->st_orglen); AppendCharToRedobuff(ESC); // "p" may be freed here - ml_replace(curwin->w_cursor.lnum, (char *)p, false); + ml_replace(curwin->w_cursor.lnum, p, false); curwin->w_cursor.col = c; inserted_bytes(curwin->w_cursor.lnum, c, stp->st_orglen, stp->st_wordlen); @@ -686,12 +686,12 @@ void spell_suggest_list(garray_T *gap, char *word, int maxcount, bool need_cap, { suginfo_T sug; suggest_T *stp; - char_u *wcopy; + char *wcopy; - spell_find_suggest((char_u *)word, 0, &sug, maxcount, false, need_cap, interactive); + spell_find_suggest(word, 0, &sug, maxcount, false, need_cap, interactive); // Make room in "gap". - ga_init(gap, sizeof(char_u *), sug.su_ga.ga_len + 1); + ga_init(gap, sizeof(char *), sug.su_ga.ga_len + 1); ga_grow(gap, sug.su_ga.ga_len); for (int i = 0; i < sug.su_ga.ga_len; i++) { stp = &SUG(sug.su_ga, i); @@ -701,7 +701,7 @@ void spell_suggest_list(garray_T *gap, char *word, int maxcount, bool need_cap, wcopy = xmalloc((size_t)stp->st_wordlen + strlen(sug.su_badptr + stp->st_orglen) + 1); STRCPY(wcopy, stp->st_word); STRCPY(wcopy + stp->st_wordlen, sug.su_badptr + stp->st_orglen); - ((char_u **)gap->ga_data)[gap->ga_len++] = wcopy; + ((char **)gap->ga_data)[gap->ga_len++] = wcopy; } spell_find_cleanup(&sug); @@ -716,7 +716,7 @@ void spell_suggest_list(garray_T *gap, char *word, int maxcount, bool need_cap, /// @param badlen length of bad word or 0 if unknown /// @param banbadword don't include badword in suggestions /// @param need_cap word should start with capital -static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int maxcount, +static void spell_find_suggest(char *badptr, int badlen, suginfo_T *su, int maxcount, bool banbadword, bool need_cap, bool interactive) { hlf_T attr = HLF_COUNT; @@ -738,7 +738,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma } hash_init(&su->su_banned); - su->su_badptr = (char *)badptr; + su->su_badptr = badptr; if (badlen != 0) { su->su_badlen = badlen; } else { @@ -752,7 +752,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma if (su->su_badlen >= MAXWLEN) { su->su_badlen = MAXWLEN - 1; // just in case } - xstrlcpy((char *)su->su_badword, su->su_badptr, (size_t)su->su_badlen + 1); + xstrlcpy(su->su_badword, su->su_badptr, (size_t)su->su_badlen + 1); (void)spell_casefold(curwin, su->su_badptr, su->su_badlen, su->su_fbadword, MAXWLEN); @@ -762,8 +762,8 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma su->su_fbadword[su->su_badlen] = NUL; // get caps flags for bad word - su->su_badflags = badword_captype((char_u *)su->su_badptr, - (char_u *)su->su_badptr + su->su_badlen); + su->su_badflags = badword_captype(su->su_badptr, + su->su_badptr + su->su_badlen); if (need_cap) { su->su_badflags |= WF_ONECAP; } @@ -783,8 +783,8 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma // Soundfold the bad word with the default sound folding, so that we don't // have to do this many times. if (su->su_sallang != NULL) { - spell_soundfold(su->su_sallang, (char *)su->su_fbadword, true, - (char *)su->su_sal_badword); + spell_soundfold(su->su_sallang, su->su_fbadword, true, + su->su_sal_badword); } // If the word is not capitalised and spell_check() doesn't consider the @@ -792,14 +792,14 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma // for that. c = utf_ptr2char(su->su_badptr); if (!SPELL_ISUPPER(c) && attr == HLF_COUNT) { - make_case_word((char *)su->su_badword, buf, WF_ONECAP); - add_suggestion(su, &su->su_ga, (char *)buf, su->su_badlen, SCORE_ICASE, + make_case_word(su->su_badword, buf, WF_ONECAP); + add_suggestion(su, &su->su_ga, buf, su->su_badlen, SCORE_ICASE, 0, true, su->su_sallang, false); } // Ban the bad word itself. It may appear in another region. if (banbadword) { - add_banned(su, (char *)su->su_badword); + add_banned(su, su->su_badword); } // Make a copy of 'spellsuggest', because the expression may change it. @@ -807,22 +807,22 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma // Loop over the items in 'spellsuggest'. for (p = sps_copy; *p != NUL;) { - copy_option_part(&p, (char *)buf, MAXPATHL, ","); + copy_option_part(&p, buf, MAXPATHL, ","); if (strncmp(buf, "expr:", 5) == 0) { // Evaluate an expression. Skip this when called recursively, // when using spellsuggest() in the expression. if (!expr_busy) { expr_busy = true; - spell_suggest_expr(su, (char_u *)buf + 5); + spell_suggest_expr(su, buf + 5); expr_busy = false; } } else if (strncmp(buf, "file:", 5) == 0) { // Use list of suggestions in a file. - spell_suggest_file(su, (char_u *)buf + 5); + spell_suggest_file(su, buf + 5); } else if (strncmp(buf, "timeout:", 8) == 0) { // Limit the time searching for suggestions. - spell_suggest_timeout = atol((char *)buf + 8); + spell_suggest_timeout = atol(buf + 8); } else if (!did_intern) { // Use internal method once. spell_suggest_intern(su, interactive); @@ -843,7 +843,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma } /// Find suggestions by evaluating expression "expr". -static void spell_suggest_expr(suginfo_T *su, char_u *expr) +static void spell_suggest_expr(suginfo_T *su, char *expr) { int score; const char *p; @@ -851,7 +851,7 @@ static void spell_suggest_expr(suginfo_T *su, char_u *expr) // The work is split up in a few parts to avoid having to export // suginfo_T. // First evaluate the expression and get the resulting list. - list_T *const list = eval_spell_expr((char *)su->su_badword, (char *)expr); + list_T *const list = eval_spell_expr(su->su_badword, expr); if (list != NULL) { // Loop over the items in the list. TV_LIST_ITER(list, li, { @@ -873,43 +873,43 @@ static void spell_suggest_expr(suginfo_T *su, char_u *expr) } /// Find suggestions in file "fname". Used for "file:" in 'spellsuggest'. -static void spell_suggest_file(suginfo_T *su, char_u *fname) +static void spell_suggest_file(suginfo_T *su, char *fname) { FILE *fd; - char_u line[MAXWLEN * 2]; - char_u *p; + char line[MAXWLEN * 2]; + char *p; int len; - char_u cword[MAXWLEN]; + char cword[MAXWLEN]; // Open the file. - fd = os_fopen((char *)fname, "r"); + fd = os_fopen(fname, "r"); if (fd == NULL) { semsg(_(e_notopen), fname); return; } // Read it line by line. - while (!vim_fgets((char *)line, MAXWLEN * 2, fd) && !got_int) { + while (!vim_fgets(line, MAXWLEN * 2, fd) && !got_int) { line_breakcheck(); - p = (char_u *)vim_strchr((char *)line, '/'); + p = vim_strchr(line, '/'); if (p == NULL) { continue; // No Tab found, just skip the line. } *p++ = NUL; if (STRICMP(su->su_badword, line) == 0) { // Match! Isolate the good word, until CR or NL. - for (len = 0; p[len] >= ' '; len++) {} + for (len = 0; (uint8_t)p[len] >= ' '; len++) {} p[len] = NUL; // If the suggestion doesn't have specific case duplicate the case // of the bad word. - if (captype((char *)p, NULL) == 0) { - make_case_word((char *)p, (char *)cword, su->su_badflags); + if (captype(p, NULL) == 0) { + make_case_word(p, cword, su->su_badflags); p = cword; } - add_suggestion(su, &su->su_ga, (char *)p, su->su_badlen, + add_suggestion(su, &su->su_ga, p, su->su_badlen, SCORE_FILE, 0, true, su->su_sallang, false); } } @@ -1014,23 +1014,23 @@ static void spell_find_cleanup(suginfo_T *su) static void suggest_try_special(suginfo_T *su) { char c; - char_u word[MAXWLEN]; + char word[MAXWLEN]; // Recognize a word that is repeated: "the the". - char *p = skiptowhite((char *)su->su_fbadword); - size_t len = (size_t)(p - (char *)su->su_fbadword); + char *p = skiptowhite(su->su_fbadword); + size_t len = (size_t)(p - su->su_fbadword); p = skipwhite(p); if (strlen(p) == len && strncmp(su->su_fbadword, p, len) == 0) { // Include badflags: if the badword is onecap or allcap // use that for the goodword too: "The the" -> "The". c = su->su_fbadword[len]; su->su_fbadword[len] = NUL; - make_case_word(su->su_fbadword, (char *)word, su->su_badflags); + make_case_word(su->su_fbadword, word, su->su_badflags); su->su_fbadword[len] = c; // Give a soundalike score of 0, compute the score as if deleting one // character. - add_suggestion(su, &su->su_ga, (char *)word, su->su_badlen, + add_suggestion(su, &su->su_ga, word, su->su_badlen, RESCORE(SCORE_REP, 0), 0, true, su->su_sallang, false); } } @@ -1268,9 +1268,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // Set su->su_badflags to the caps type at this position. // Use the caps type until here for the prefix itself. n = nofold_len(fword, sp->ts_fidx, su->su_badptr); - flags = badword_captype((char_u *)su->su_badptr, (char_u *)su->su_badptr + n); - su->su_badflags = badword_captype((char_u *)su->su_badptr + n, - (char_u *)su->su_badptr + su->su_badlen); + flags = badword_captype(su->su_badptr, su->su_badptr + n); + su->su_badflags = badword_captype(su->su_badptr + n, + su->su_badptr + su->su_badlen); #ifdef DEBUG_TRIEWALK sprintf(changename[depth], "prefix"); // NOLINT(runtime/printf) #endif @@ -1371,11 +1371,11 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun (size_t)(sp->ts_fidx - sp->ts_splitfidx)) == 0) { preword[sp->ts_prewordlen] = NUL; newscore = score_wordcount_adj(slang, sp->ts_score, - (char_u *)preword + sp->ts_prewordlen, + preword + sp->ts_prewordlen, sp->ts_prewordlen > 0); // Add the suggestion if the score isn't too bad. if (newscore <= su->su_maxscore) { - add_suggestion(su, &su->su_ga, (char *)preword, + add_suggestion(su, &su->su_ga, preword, sp->ts_splitfidx - repextra, newscore, 0, false, lp->lp_sallang, false); @@ -1437,7 +1437,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun STRCPY(preword + sp->ts_prewordlen, tword + sp->ts_splitoff); } else if (flags & WF_KEEPCAP) { // Must find the word in the keep-case tree. - find_keepcap_word(slang, (char *)tword + sp->ts_splitoff, preword + sp->ts_prewordlen); + find_keepcap_word(slang, tword + sp->ts_splitoff, preword + sp->ts_prewordlen); } else { // Include badflags: If the badword is onecap or allcap // use that for the goodword too. But if the badword is @@ -1465,8 +1465,8 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun break; } if ((sp->ts_complen == sp->ts_compsplit - && WAS_BANNED(su, (char *)preword + sp->ts_prewordlen)) - || WAS_BANNED(su, (char *)preword)) { + && WAS_BANNED(su, preword + sp->ts_prewordlen)) + || WAS_BANNED(su, preword)) { if (slang->sl_compprog == NULL) { break; } @@ -1528,12 +1528,12 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // Give a bonus to words seen before. score = score_wordcount_adj(slang, sp->ts_score + newscore, - (char_u *)preword + sp->ts_prewordlen, + preword + sp->ts_prewordlen, sp->ts_prewordlen > 0); // Add the suggestion if the score isn't too bad. if (score <= su->su_maxscore) { - add_suggestion(su, &su->su_ga, (char *)preword, + add_suggestion(su, &su->su_ga, preword, sp->ts_fidx - repextra, score, 0, false, lp->lp_sallang, false); @@ -1546,7 +1546,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun preword + sp->ts_prewordlen, c == 0 ? WF_ALLCAP : 0); - add_suggestion(su, &su->su_ga, (char *)preword, + add_suggestion(su, &su->su_ga, preword, sp->ts_fidx - repextra, score + SCORE_ICASE, 0, false, lp->lp_sallang, false); @@ -1647,7 +1647,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // Give a bonus to words seen before. newscore = score_wordcount_adj(slang, newscore, - (char_u *)preword + sp->ts_prewordlen, true); + preword + sp->ts_prewordlen, true); } if (TRY_DEEPER(su, stack, depth, newscore)) { @@ -1715,8 +1715,8 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // set su->su_badflags to the caps type at this // position n = nofold_len(fword, sp->ts_fidx, su->su_badptr); - su->su_badflags = badword_captype((char_u *)su->su_badptr + n, - (char_u *)su->su_badptr + su->su_badlen); + su->su_badflags = badword_captype(su->su_badptr + n, + su->su_badptr + su->su_badlen); // Restart at top of the tree. sp->ts_arridx = 0; @@ -1843,7 +1843,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // For changing a composing character adjust // the score from SCORE_SUBST to // SCORE_SUBCOMP. - if (utf_iscomposing(utf_ptr2char((char *)tword + sp->ts_twordlen + if (utf_iscomposing(utf_ptr2char(tword + sp->ts_twordlen - sp->ts_tcharlen)) && utf_iscomposing(utf_ptr2char(fword + sp->ts_fcharstart))) { @@ -1851,7 +1851,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun } else if (!soundfold && slang->sl_has_map && similar_chars(slang, - utf_ptr2char((char *)tword + sp->ts_twordlen - + utf_ptr2char(tword + sp->ts_twordlen - sp->ts_tcharlen), utf_ptr2char(fword + sp->ts_fcharstart))) { // For a similar character adjust score from @@ -1860,7 +1860,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun } } else if (sp->ts_isdiff == DIFF_INSERT && sp->ts_twordlen > sp->ts_tcharlen) { - p = (char *)tword + sp->ts_twordlen - sp->ts_tcharlen; + p = tword + sp->ts_twordlen - sp->ts_tcharlen; c = utf_ptr2char(p); if (utf_iscomposing(c)) { // Inserting a composing char doesn't @@ -2310,7 +2310,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun fl = (int)strlen(ftp->ft_from); tl = (int)strlen(ftp->ft_to); if (fl != tl) { - STRMOVE(p + tl, (char *)p + fl); + STRMOVE(p + tl, p + fl); repextra += tl - fl; } memmove(p, ftp->ft_to, (size_t)tl); @@ -2340,7 +2340,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun tl = (int)strlen(ftp->ft_to); p = fword + sp->ts_fidx; if (fl != tl) { - STRMOVE(p + fl, (char *)p + tl); + STRMOVE(p + fl, p + tl); repextra -= tl - fl; } memmove(p, ftp->ft_from, (size_t)fl); @@ -2402,7 +2402,7 @@ static void find_keepcap_word(slang_T *slang, char *fword, char *kword) int len; int c; idx_T lo, hi, m; - char_u *p; + char *p; char_u *byts = (char_u *)slang->sl_kbyts; // array with bytes of the words idx_T *idxs = slang->sl_kidxs; // array with indexes @@ -2443,19 +2443,19 @@ static void find_keepcap_word(slang_T *slang, char *fword, char *kword) // round[depth] == 1: Try using the folded-case character. // round[depth] == 2: Try using the upper-case character. flen = utf_ptr2len(fword + fwordidx[depth]); - ulen = utf_ptr2len((char *)uword + uwordidx[depth]); + ulen = utf_ptr2len(uword + uwordidx[depth]); if (round[depth] == 1) { - p = (char_u *)fword + fwordidx[depth]; + p = fword + fwordidx[depth]; l = flen; } else { - p = (char_u *)uword + uwordidx[depth]; + p = uword + uwordidx[depth]; l = ulen; } for (tryidx = arridx[depth]; l > 0; l--) { // Perform a binary search in the list of accepted bytes. len = byts[tryidx++]; - c = *p++; + c = (uint8_t)(*p++); lo = tryidx; hi = tryidx + len - 1; while (lo < hi) { @@ -2512,7 +2512,7 @@ static void find_keepcap_word(slang_T *slang, char *fword, char *kword) static void score_comp_sal(suginfo_T *su) { langp_T *lp; - char_u badsound[MAXWLEN]; + char badsound[MAXWLEN]; int i; suggest_T *stp; suggest_T *sstp; @@ -2525,7 +2525,7 @@ static void score_comp_sal(suginfo_T *su) lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi); if (!GA_EMPTY(&lp->lp_slang->sl_sal)) { // soundfold the bad word - spell_soundfold(lp->lp_slang, (char *)su->su_fbadword, true, (char *)badsound); + spell_soundfold(lp->lp_slang, su->su_fbadword, true, badsound); for (i = 0; i < su->su_ga.ga_len; i++) { stp = &SUG(su->su_ga, i); @@ -2568,11 +2568,11 @@ static void score_combine(suginfo_T *su) if (!GA_EMPTY(&lp->lp_slang->sl_sal)) { // soundfold the bad word slang = lp->lp_slang; - spell_soundfold(slang, (char *)su->su_fbadword, true, badsound); + spell_soundfold(slang, su->su_fbadword, true, badsound); for (int i = 0; i < su->su_ga.ga_len; i++) { stp = &SUG(su->su_ga, i); - stp->st_altscore = stp_sal_score(stp, su, slang, (char_u *)badsound); + stp->st_altscore = stp_sal_score(stp, su, slang, badsound); if (stp->st_altscore == SCORE_MAXMAX) { stp->st_score = (stp->st_score * 3 + SCORE_BIG) / 4; } else { @@ -2593,7 +2593,7 @@ static void score_combine(suginfo_T *su) // Add the alternate score to su_sga. for (int i = 0; i < su->su_sga.ga_len; i++) { stp = &SUG(su->su_sga, i); - stp->st_altscore = spell_edit_score(slang, (char_u *)su->su_badword, (char_u *)stp->st_word); + stp->st_altscore = spell_edit_score(slang, su->su_badword, stp->st_word); if (stp->st_score == SCORE_MAXMAX) { stp->st_score = (SCORE_BIG * 7 + stp->st_altscore) / 8; } else { @@ -2654,14 +2654,14 @@ static void score_combine(suginfo_T *su) /// badword. /// /// @param badsound sound-folded badword -static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u *badsound) +static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char *badsound) { - char_u *p; - char_u *pbad; - char_u *pgood; - char_u badsound2[MAXWLEN]; - char_u fword[MAXWLEN]; - char_u goodsound[MAXWLEN]; + char *p; + char *pbad; + char *pgood; + char badsound2[MAXWLEN]; + char fword[MAXWLEN]; + char goodsound[MAXWLEN]; char goodword[MAXWLEN]; int lendiff; @@ -2670,7 +2670,7 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u * pbad = badsound; } else { // soundfold the bad word with more characters following - (void)spell_casefold(curwin, su->su_badptr, stp->st_orglen, (char *)fword, MAXWLEN); + (void)spell_casefold(curwin, su->su_badptr, stp->st_orglen, fword, MAXWLEN); // When joining two words the sound often changes a lot. E.g., "t he" // sounds like "t h" while "the" sounds like "@". Avoid that by @@ -2678,12 +2678,12 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u * // space. if (ascii_iswhite(su->su_badptr[su->su_badlen]) && *skiptowhite(stp->st_word) == NUL) { - for (p = fword; *(p = (char_u *)skiptowhite((char *)p)) != NUL;) { - STRMOVE(p, (char *)p + 1); + for (p = fword; *(p = skiptowhite(p)) != NUL;) { + STRMOVE(p, p + 1); } } - spell_soundfold(slang, (char *)fword, true, (char *)badsound2); + spell_soundfold(slang, fword, true, badsound2); pbad = badsound2; } @@ -2693,15 +2693,15 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u * STRCPY(goodword, stp->st_word); xstrlcpy(goodword + stp->st_wordlen, su->su_badptr + su->su_badlen - lendiff, (size_t)lendiff + 1); - pgood = (char_u *)goodword; + pgood = goodword; } else { - pgood = (char_u *)stp->st_word; + pgood = stp->st_word; } // Sound-fold the word and compute the score for the difference. - spell_soundfold(slang, (char *)pgood, false, (char *)goodsound); + spell_soundfold(slang, pgood, false, goodsound); - return soundalike_score((char *)goodsound, (char *)pbad); + return soundalike_score(goodsound, pbad); } /// structure used to store soundfolded words that add_sound_suggest() has @@ -2737,7 +2737,7 @@ static void suggest_try_soundalike_prep(void) /// Note: This doesn't support postponed prefixes. static void suggest_try_soundalike(suginfo_T *su) { - char_u salword[MAXWLEN]; + char salword[MAXWLEN]; langp_T *lp; slang_T *slang; @@ -2748,7 +2748,7 @@ static void suggest_try_soundalike(suginfo_T *su) slang = lp->lp_slang; if (!GA_EMPTY(&slang->sl_sal) && slang->sl_sbyts != NULL) { // soundfold the bad word - spell_soundfold(slang, (char *)su->su_fbadword, true, (char *)salword); + spell_soundfold(slang, su->su_fbadword, true, salword); // try all kinds of inserts/deletes/swaps/etc. // TODO(vim): also soundfold the next words, so that we can try joining @@ -2756,7 +2756,7 @@ static void suggest_try_soundalike(suginfo_T *su) #ifdef SUGGEST_PROFILE prof_init(); #endif - suggest_trie_walk(su, lp, (char *)salword, true); + suggest_trie_walk(su, lp, salword, true); #ifdef SUGGEST_PROFILE prof_report("soundalike"); #endif @@ -2802,9 +2802,9 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T { slang_T *slang = lp->lp_slang; // language for sound folding int sfwordnr; - char_u *nrline; + char *nrline; int orgnr; - char_u theword[MAXWLEN]; + char theword[MAXWLEN]; int i; int wlen; char_u *byts; @@ -2841,14 +2841,14 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T } // Find the word nr in the soundfold tree. - sfwordnr = soundfold_find(slang, (char_u *)goodword); + sfwordnr = soundfold_find(slang, goodword); if (sfwordnr < 0) { internal_error("add_sound_suggest()"); return; } // Go over the list of good words that produce this soundfold word - nrline = (char_u *)ml_get_buf(slang->sl_sugbuf, (linenr_T)sfwordnr + 1, false); + nrline = ml_get_buf(slang->sl_sugbuf, (linenr_T)sfwordnr + 1, false); orgnr = 0; while (*nrline != NUL) { // The wordnr was stored in a minimal nr of bytes as an offset to the @@ -2888,7 +2888,7 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T wordcount += wc; } - theword[wlen] = byts[n + i]; + theword[wlen] = (char)byts[n + i]; n = idxs[n + i]; } badword: @@ -2896,8 +2896,8 @@ badword: // Go over the possible flags and regions. for (; i <= byts[n] && byts[n + i] == NUL; i++) { - char_u cword[MAXWLEN]; - char_u *p; + char cword[MAXWLEN]; + char *p; int flags = (int)idxs[n + i]; // Skip words with the NOSUGGEST flag @@ -2907,13 +2907,13 @@ badword: if (flags & WF_KEEPCAP) { // Must find the word in the keep-case tree. - find_keepcap_word(slang, (char *)theword, (char *)cword); + find_keepcap_word(slang, theword, cword); p = cword; } else { flags |= su->su_badflags; if ((flags & WF_CAPMASK) != 0) { // Need to fix case according to "flags". - make_case_word((char *)theword, (char *)cword, flags); + make_case_word(theword, cword, flags); p = cword; } else { p = theword; @@ -2924,7 +2924,7 @@ badword: if (sps_flags & SPS_DOUBLE) { // Add the suggestion if the score isn't too bad. if (score <= su->su_maxscore) { - add_suggestion(su, &su->su_sga, (char *)p, su->su_badlen, + add_suggestion(su, &su->su_sga, p, su->su_badlen, score, 0, false, slang, false); } } else { @@ -2940,9 +2940,9 @@ badword: // lower to upper case. Helps for "tath" -> "Kath", which is // less common than "tath" -> "path". Don't do it when the // letter is the same, that has already been counted. - gc = utf_ptr2char((char *)p); + gc = utf_ptr2char(p); if (SPELL_ISUPPER(gc)) { - bc = utf_ptr2char((char *)su->su_badword); + bc = utf_ptr2char(su->su_badword); if (!SPELL_ISUPPER(bc) && SPELL_TOFOLD(bc) != SPELL_TOFOLD(gc)) { goodscore += SCORE_ICASE / 2; @@ -2958,10 +2958,9 @@ badword: // inefficient, using an array is quicker. limit = MAXSCORE(su->su_sfmaxscore - goodscore, score); if (limit > SCORE_LIMITMAX) { - goodscore += spell_edit_score(slang, (char_u *)su->su_badword, p); + goodscore += spell_edit_score(slang, su->su_badword, p); } else { - goodscore += spell_edit_score_limit(slang, (char_u *)su->su_badword, - p, limit); + goodscore += spell_edit_score_limit(slang, su->su_badword, p, limit); } // When going over the limit don't bother to do the rest. @@ -2972,7 +2971,7 @@ badword: // Add the suggestion if the score isn't too bad. goodscore = RESCORE(goodscore, score); if (goodscore <= su->su_sfmaxscore) { - add_suggestion(su, &su->su_ga, (char *)p, su->su_badlen, + add_suggestion(su, &su->su_ga, p, su->su_badlen, goodscore, score, true, slang, true); } } @@ -2982,13 +2981,13 @@ badword: } /// Find word "word" in fold-case tree for "slang" and return the word number. -static int soundfold_find(slang_T *slang, char_u *word) +static int soundfold_find(slang_T *slang, char *word) { idx_T arridx = 0; int len; int wlen = 0; int c; - char_u *ptr = word; + char_u *ptr = (char_u *)word; char_u *byts; idx_T *idxs; int wordnr = 0; @@ -3065,7 +3064,7 @@ static bool similar_chars(slang_T *slang, int c1, int c2) hashitem_T *hi; if (c1 >= 256) { - buf[utf_char2bytes(c1, (char *)buf)] = 0; + buf[utf_char2bytes(c1, buf)] = 0; hi = hash_find(&slang->sl_map_hash, buf); if (HASHITEM_EMPTY(hi)) { m1 = 0; @@ -3080,7 +3079,7 @@ static bool similar_chars(slang_T *slang, int c1, int c2) } if (c2 >= 256) { - buf[utf_char2bytes(c2, (char *)buf)] = 0; + buf[utf_char2bytes(c2, buf)] = 0; hi = hash_find(&slang->sl_map_hash, buf); if (HASHITEM_EMPTY(hi)) { m2 = 0; @@ -3244,7 +3243,7 @@ static void check_suggestions(suginfo_T *su, garray_T *gap) /// Add a word to be banned. static void add_banned(suginfo_T *su, char *word) { - char_u *s; + char *s; hash_T hash; hashitem_T *hi; @@ -3255,7 +3254,7 @@ static void add_banned(suginfo_T *su, char *word) return; } s = xmemdupz(word, word_len); - hash_add_item(&su->su_banned, hi, (char *)s, hash); + hash_add_item(&su->su_banned, hi, s, hash); } /// Recompute the score for all suggestions if sound-folding is possible. This @@ -3273,8 +3272,8 @@ static void rescore_suggestions(suginfo_T *su) static void rescore_one(suginfo_T *su, suggest_T *stp) { slang_T *slang = stp->st_slang; - char_u sal_badword[MAXWLEN]; - char_u *p; + char sal_badword[MAXWLEN]; + char *p; // Only rescore suggestions that have no sal score yet and do have a // language. @@ -3282,7 +3281,7 @@ static void rescore_one(suginfo_T *su, suggest_T *stp) if (slang == su->su_sallang) { p = su->su_sal_badword; } else { - spell_soundfold(slang, (char *)su->su_fbadword, true, (char *)sal_badword); + spell_soundfold(slang, su->su_fbadword, true, sal_badword); p = sal_badword; } @@ -3575,7 +3574,7 @@ static int soundalike_score(char *goodstart, char *badstart) /// The implementation of the algorithm comes from Aspell editdist.cpp, /// edit_distance(). It has been converted from C++ to C and modified to /// support multi-byte characters. -static int spell_edit_score(slang_T *slang, const char_u *badword, const char_u *goodword) +static int spell_edit_score(slang_T *slang, const char *badword, const char *goodword) { int *cnt; int j, i; @@ -3592,12 +3591,12 @@ static int spell_edit_score(slang_T *slang, const char_u *badword, const char_u // Get the characters from the multi-byte strings and put them in an // int array for easy access. badlen = 0; - for (const char *p = (char *)badword; *p != NUL;) { + for (const char *p = badword; *p != NUL;) { wbadword[badlen++] = mb_cptr2char_adv(&p); } wbadword[badlen++] = 0; goodlen = 0; - for (const char *p = (char *)goodword; *p != NUL;) { + for (const char *p = goodword; *p != NUL;) { wgoodword[goodlen++] = mb_cptr2char_adv(&p); } wgoodword[goodlen++] = 0; @@ -3673,14 +3672,14 @@ typedef struct { /// This uses a stack for the edits still to be tried. /// The idea comes from Aspell leditdist.cpp. Rewritten in C and added support /// for multi-byte characters. -static int spell_edit_score_limit(slang_T *slang, char_u *badword, char_u *goodword, int limit) +static int spell_edit_score_limit(slang_T *slang, char *badword, char *goodword, int limit) { return spell_edit_score_limit_w(slang, badword, goodword, limit); } /// Multi-byte version of spell_edit_score_limit(). /// Keep it in sync with the above! -static int spell_edit_score_limit_w(slang_T *slang, const char_u *badword, const char_u *goodword, +static int spell_edit_score_limit_w(slang_T *slang, const char *badword, const char *goodword, int limit) { limitscore_T stack[10]; // allow for over 3 * 2 edits @@ -3698,12 +3697,12 @@ static int spell_edit_score_limit_w(slang_T *slang, const char_u *badword, const // Get the characters from the multi-byte strings and put them in an // int array for easy access. bi = 0; - for (const char *p = (char *)badword; *p != NUL;) { + for (const char *p = badword; *p != NUL;) { wbadword[bi++] = mb_cptr2char_adv(&p); } wbadword[bi++] = 0; gi = 0; - for (const char *p = (char *)goodword; *p != NUL;) { + for (const char *p = goodword; *p != NUL;) { wgoodword[gi++] = mb_cptr2char_adv(&p); } wgoodword[gi++] = 0; diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 9552f3f42b..a094a5f945 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -582,7 +582,7 @@ void win_redr_ruler(win_T *wp, bool always) MAXSIZE_TEMP_ARRAY(content, 1); MAXSIZE_TEMP_ARRAY(chunk, 2); ADD_C(chunk, INTEGER_OBJ(attr)); - ADD_C(chunk, STRING_OBJ(cstr_as_string((char *)buffer))); + ADD_C(chunk, STRING_OBJ(cstr_as_string(buffer))); ADD_C(content, ARRAY_OBJ(chunk)); ui_call_msg_ruler(content); did_show_ext_ruler = true; diff --git a/src/nvim/testing.c b/src/nvim/testing.c index b5921b3445..3569856f2c 100644 --- a/src/nvim/testing.c +++ b/src/nvim/testing.c @@ -395,12 +395,12 @@ static int assert_equalfile(typval_T *argvars) char line2[200]; ptrdiff_t lineidx = 0; if (fd1 == NULL) { - snprintf(IObuff, IOSIZE, (char *)e_notread, fname1); + snprintf(IObuff, IOSIZE, e_notread, fname1); } else { FILE *const fd2 = os_fopen(fname2, READBIN); if (fd2 == NULL) { fclose(fd1); - snprintf(IObuff, IOSIZE, (char *)e_notread, fname2); + snprintf(IObuff, IOSIZE, e_notread, fname2); } else { int64_t linecount = 1; for (int64_t count = 0;; count++) { diff --git a/src/nvim/textformat.c b/src/nvim/textformat.c index e30580a748..69cc0e046b 100644 --- a/src/nvim/textformat.c +++ b/src/nvim/textformat.c @@ -72,7 +72,7 @@ bool has_format_option(int x) void internal_format(int textwidth, int second_indent, int flags, bool format_only, int c) { int cc; - int save_char = NUL; + char save_char = NUL; bool haveto_redraw = false; const bool fo_ins_blank = has_format_option(FO_INS_BLANK); const bool fo_multibyte = has_format_option(FO_MBYTE_BREAK); @@ -93,7 +93,7 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on && !(State & VREPLACE_FLAG)) { cc = gchar_cursor(); if (ascii_iswhite(cc)) { - save_char = cc; + save_char = (char)cc; pchar_cursor('x'); } } @@ -458,7 +458,7 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on } if (save_char != NUL) { // put back space after cursor - pchar_cursor((char_u)save_char); + pchar_cursor(save_char); } curwin->w_p_lbr = has_lbr; diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c index c6f1a8faba..3a5a4c3e91 100644 --- a/src/nvim/usercmd.c +++ b/src/nvim/usercmd.c @@ -298,8 +298,8 @@ const char *set_context_in_user_cmdarg(const char *cmd FUNC_ATTR_UNUSED, const c return arg; } if (context == EXPAND_MAPPINGS) { - return (const char *)set_context_in_map_cmd(xp, "map", (char *)arg, forceit, false, false, - CMD_map); + return set_context_in_map_cmd(xp, "map", (char *)arg, forceit, false, false, + CMD_map); } // Find start of last argument. const char *p = arg; @@ -1749,8 +1749,8 @@ Dictionary commands_array(buf_T *buf) Dictionary d = ARRAY_DICT_INIT; ucmd_T *cmd = USER_CMD_GA(gap, i); - PUT(d, "name", STRING_OBJ(cstr_to_string((char *)cmd->uc_name))); - PUT(d, "definition", STRING_OBJ(cstr_to_string((char *)cmd->uc_rep))); + PUT(d, "name", STRING_OBJ(cstr_to_string(cmd->uc_name))); + PUT(d, "definition", STRING_OBJ(cstr_to_string(cmd->uc_rep))); PUT(d, "script_id", INTEGER_OBJ(cmd->uc_script_ctx.sc_sid)); PUT(d, "bang", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_BANG))); PUT(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_TRLBAR))); @@ -1776,7 +1776,7 @@ Dictionary commands_array(buf_T *buf) PUT(d, "complete", (cmd_compl == NULL ? NIL : STRING_OBJ(cstr_to_string(cmd_compl)))); PUT(d, "complete_arg", cmd->uc_compl_arg == NULL - ? NIL : STRING_OBJ(cstr_to_string((char *)cmd->uc_compl_arg))); + ? NIL : STRING_OBJ(cstr_to_string(cmd->uc_compl_arg))); Object obj = NIL; if (cmd->uc_argt & EX_COUNT) { @@ -1812,7 +1812,7 @@ Dictionary commands_array(buf_T *buf) } PUT(d, "addr", obj); - PUT(rv, (char *)cmd->uc_name, DICTIONARY_OBJ(d)); + PUT(rv, cmd->uc_name, DICTIONARY_OBJ(d)); } return rv; } diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 3c765f8eb2..00e28e3e68 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -195,7 +195,6 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext() #define CLEAR_FIELD(field) memset(&(field), 0, sizeof(field)) #define CLEAR_POINTER(ptr) memset((ptr), 0, sizeof(*(ptr))) -// defines to avoid typecasts from (char_u *) to (char *) and back // (vim_strchr() is now in strings.c) #ifndef HAVE_STRNLEN -- cgit From 7d58de11f49c574a8a305e28e96b9ff810493012 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Feb 2023 18:25:01 +0800 Subject: fix(rpc)!: preseve files when stdio channel is closed (#22137) BREAKING CHANGE: Unsaved changes are now preserved rather than discarded when stdio channel is closed. --- src/nvim/event/process.c | 7 ++++++- src/nvim/main.c | 18 ++++++++++++------ src/nvim/msgpack_rpc/channel.c | 4 ++++ 3 files changed, 22 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 1a524a56ca..1219566e9b 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -422,7 +422,12 @@ static void exit_event(void **argv) } if (!exiting) { - os_exit(status); + if (ui_client_channel_id) { + os_exit(status); + } else { + assert(status == 0); // Called from rpc_close(), which passes 0 as status. + preserve_exit(NULL); + } } } diff --git a/src/nvim/main.c b/src/nvim/main.c index 4ee02b4e1b..f36730a8b3 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -674,6 +674,7 @@ void os_exit(int r) void getout(int exitval) FUNC_ATTR_NORETURN { + assert(!ui_client_channel_id); exiting = true; // On error during Ex mode, exit with a non-zero code. @@ -794,6 +795,7 @@ void getout(int exitval) } /// Preserve files, print contents of `errmsg`, and exit 1. +/// @param errmsg If NULL, this function will not print anything. /// /// May be called from deadly_signal(). void preserve_exit(const char *errmsg) @@ -819,19 +821,21 @@ void preserve_exit(const char *errmsg) // For TUI: exit alternate screen so that the error messages can be seen. ui_client_stop(); } - os_errmsg(errmsg); - os_errmsg("\n"); + if (errmsg != NULL) { + os_errmsg(errmsg); + os_errmsg("\n"); + } if (ui_client_channel_id) { os_exit(1); } - ui_flush(); ml_close_notmod(); // close all not-modified buffers FOR_ALL_BUFFERS(buf) { if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) { - os_errmsg("Vim: preserving files...\r\n"); - ui_flush(); + if (errmsg != NULL) { + os_errmsg("Vim: preserving files...\r\n"); + } ml_sync_all(false, false, true); // preserve all swap files break; } @@ -839,7 +843,9 @@ void preserve_exit(const char *errmsg) ml_close_all(false); // close all memfiles, without deleting - os_errmsg("Vim: Finished.\r\n"); + if (errmsg != NULL) { + os_errmsg("Vim: Finished.\r\n"); + } getout(1); } diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 34c8f89e3f..f8be0d4c8d 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -550,6 +550,10 @@ void rpc_close(Channel *channel) if (channel->streamtype == kChannelStreamStdio || (channel->id == ui_client_channel_id && channel->streamtype != kChannelStreamProc)) { + if (channel->streamtype == kChannelStreamStdio) { + // Avoid hanging when there are no other UIs and a prompt is triggered on exit. + remote_ui_disconnect(channel->id); + } exit_from_channel(0); } } -- cgit From 9437800d280385c018a99aa0fbe9043e4d7715aa Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Feb 2023 18:44:06 +0800 Subject: vim-patch:9.0.1298: inserting register on the cmdline does not trigger incsearch Problem: Inserting a register on the command line does not trigger incsearch or update hlsearch. Solution: Have cmdline_insert_reg() return CMDLINE_CHANGED when appropriate and handle it correctly. (Ken Takata, closes vim/vim#11960) https://github.com/vim/vim/commit/c4b7dec38292fe1cfad7aa5f244031fc6f7c7a09 Co-authored-by: K.Takata --- src/nvim/ex_getln.c | 16 ++++++++++------ src/nvim/testdir/test_hlsearch.vim | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 6926a36366..d55da46227 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1598,8 +1598,10 @@ static int command_line_insert_reg(CommandLineState *s) } } + bool literally = false; if (s->c != ESC) { // use ESC to cancel inserting register - cmdline_paste(s->c, i == Ctrl_R, false); + literally = i == Ctrl_R; + cmdline_paste(s->c, literally, false); // When there was a serious error abort getting the // command line. @@ -1624,8 +1626,9 @@ static int command_line_insert_reg(CommandLineState *s) ccline.special_char = NUL; redrawcmd(); - // The text has been stuffed, the command line didn't change yet. - return CMDLINE_NOT_CHANGED; + // The text has been stuffed, the command line didn't change yet, but it + // will change soon. The caller must take care of it. + return literally ? CMDLINE_NOT_CHANGED : CMDLINE_CHANGED; } /// Handle the Left and Right mouse clicks in the command-line mode. @@ -1857,12 +1860,13 @@ static int command_line_handle_key(CommandLineState *s) case Ctrl_R: // insert register switch (command_line_insert_reg(s)) { - case CMDLINE_NOT_CHANGED: - return command_line_not_changed(s); case GOTO_NORMAL_MODE: return 0; // back to cmd mode + case CMDLINE_NOT_CHANGED: + s->is_state.incsearch_postponed = true; + FALLTHROUGH; default: - return command_line_changed(s); + return command_line_not_changed(s); } case Ctrl_D: diff --git a/src/nvim/testdir/test_hlsearch.vim b/src/nvim/testdir/test_hlsearch.vim index cf2791113a..043d378a39 100644 --- a/src/nvim/testdir/test_hlsearch.vim +++ b/src/nvim/testdir/test_hlsearch.vim @@ -1,5 +1,8 @@ " Test for v:hlsearch +source check.vim +source screendump.vim + func Test_hlsearch() new call setline(1, repeat(['aaa'], 10)) @@ -63,3 +66,23 @@ func Test_hlsearch_eol_highlight() set nohlsearch bwipe! endfunc + +func Test_hlsearch_Ctrl_R() + CheckRunVimInTerminal + + let lines =<< trim END + set incsearch hlsearch + let @" = "text" + put + END + call writefile(lines, 'XhlsearchCtrlR', 'D') + let buf = RunVimInTerminal('-S XhlsearchCtrlR', #{rows: 6, cols: 60}) + + call term_sendkeys(buf, "/\\\"") + call VerifyScreenDump(buf, 'Test_hlsearch_ctrlr_1', {}) + + call term_sendkeys(buf, "\") + call StopVimInTerminal(buf) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab -- cgit From f1fcdcc2c43839b037517d1dd7b1a4570eb970a8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Feb 2023 19:01:43 +0800 Subject: vim-patch:9.0.1299: change for triggering incsearch not sufficiently tested Problem: Change for triggering incsearch not sufficiently tested. Solution: Add a test case. Simplify the code. (closes vim/vim#11971) https://github.com/vim/vim/commit/412e0e4ed903682f352d8ea58ded480930cc664f --- src/nvim/ex_getln.c | 11 +++++------ src/nvim/testdir/test_autocmd.vim | 22 ++++++++++++++++++---- 2 files changed, 23 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index d55da46227..af26fe8a1c 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1626,9 +1626,9 @@ static int command_line_insert_reg(CommandLineState *s) ccline.special_char = NUL; redrawcmd(); - // The text has been stuffed, the command line didn't change yet, but it - // will change soon. The caller must take care of it. - return literally ? CMDLINE_NOT_CHANGED : CMDLINE_CHANGED; + // With "literally": the command line has already changed. + // Else: the text has been stuffed, but the command line didn't change yet. + return literally ? CMDLINE_CHANGED : CMDLINE_NOT_CHANGED; } /// Handle the Left and Right mouse clicks in the command-line mode. @@ -1862,9 +1862,8 @@ static int command_line_handle_key(CommandLineState *s) switch (command_line_insert_reg(s)) { case GOTO_NORMAL_MODE: return 0; // back to cmd mode - case CMDLINE_NOT_CHANGED: - s->is_state.incsearch_postponed = true; - FALLTHROUGH; + case CMDLINE_CHANGED: + return command_line_changed(s); default: return command_line_not_changed(s); } diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index a1a3ba3198..30d30c8b29 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -1897,17 +1897,15 @@ func Test_Cmdline() call assert_equal(':', g:entered) au! CmdlineChanged + autocmd CmdlineChanged : let g:log += [getcmdline()] + let g:log = [] cnoremap call setcmdline('ls') - autocmd CmdlineChanged : let g:log += [getcmdline()] call feedkeys(":\", 'xt') call assert_equal(['ls'], g:log) - unlet g:log - au! CmdlineChanged cunmap let g:log = [] - autocmd CmdlineChanged : let g:log += [getcmdline()] call feedkeys(":sign \\\\\\\", 'xt') call assert_equal([ \ 's', @@ -1938,6 +1936,22 @@ func Test_Cmdline() \ 'sign unplace', \ ], g:log) set wildmenu& wildoptions& + + let g:log = [] + let @r = 'abc' + call feedkeys(":0\r1\\r2\\r3\", 'xt') + call assert_equal([ + \ '0', + \ '0a', + \ '0ab', + \ '0abc', + \ '0abc1', + \ '0abc1abc', + \ '0abc1abc2', + \ '0abc1abc2abc', + \ '0abc1abc2abc3', + \ ], g:log) + unlet g:log au! CmdlineChanged -- cgit From 374955bcc571dff05f068ec18d0f578d1f334c5f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Feb 2023 20:00:31 +0800 Subject: vim-patch:9.0.1300: 'statusline' only supports one "%=" item (#22218) Problem: 'statusline' only supports one "%=" item. Solution: Add support for multiple "%=" items. (TJ DeVries, Yegappan Lakshmanan, closes vim/vim#11970, closes vim/vim#11965) https://github.com/vim/vim/commit/3ec78f973fdaec2cea8e036ed38037b2fe40670b Co-authored-by: Yegappan Lakshmanan --- src/nvim/statusline.c | 13 ++++++------- src/nvim/testdir/test_statusline.vim | 4 ++++ 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index a094a5f945..6e0dc2e8f7 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -1094,7 +1094,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n continue; } - // STL_SEPARATE: Separation place between left and right aligned items. + // STL_SEPARATE: Separation between items, filled with white space. if (*fmt_p == STL_SEPARATE) { fmt_p++; // Ignored when we are inside of a grouping @@ -2066,8 +2066,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n int num_separators = 0; for (int i = 0; i < itemcnt; i++) { if (stl_items[i].type == Separate) { - // Create an array of the start location for each - // separator mark. + // Create an array of the start location for each separator mark. stl_separator_locations[num_separators] = i; num_separators++; } @@ -2079,17 +2078,17 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n int final_spaces = (maxwidth - width) - standard_spaces * (num_separators - 1); - for (int i = 0; i < num_separators; i++) { - int dislocation = (i == (num_separators - 1)) ? final_spaces : standard_spaces; + for (int l = 0; l < num_separators; l++) { + int dislocation = (l == (num_separators - 1)) ? final_spaces : standard_spaces; dislocation *= utf_char2len(fillchar); - char *start = stl_items[stl_separator_locations[i]].start; + char *start = stl_items[stl_separator_locations[l]].start; char *seploc = start + dislocation; STRMOVE(seploc, start); for (char *s = start; s < seploc;) { MB_CHAR2BYTES(fillchar, s); } - for (int item_idx = stl_separator_locations[i] + 1; + for (int item_idx = stl_separator_locations[l] + 1; item_idx < itemcnt; item_idx++) { stl_items[item_idx].start += dislocation; diff --git a/src/nvim/testdir/test_statusline.vim b/src/nvim/testdir/test_statusline.vim index 990c852ccd..1e06ad1c67 100644 --- a/src/nvim/testdir/test_statusline.vim +++ b/src/nvim/testdir/test_statusline.vim @@ -231,6 +231,10 @@ func Test_statusline() " %=: Separation point between left and right aligned items. set statusline=foo%=bar call assert_match('^foo\s\+bar\s*$', s:get_statusline()) + set statusline=foo%=bar%=baz + call assert_match('^foo\s\+bar\s\+baz\s*$', s:get_statusline()) + set statusline=foo%=bar%=baz%=qux + call assert_match('^foo\s\+bar\s\+baz\s\+qux\s*$', s:get_statusline()) " Test min/max width, leading zeroes, left/right justify. set statusline=%04B -- cgit From 224a3c77caa6fea8299eb3be326fa6ff7300a21b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Feb 2023 20:56:42 +0800 Subject: vim-patch:9.0.1295: the option initialization function is too long (#22222) Problem: The option initialization function is too long. Solution: Move code to separate functions. (Yegappan Lakshmanan, closes vim/vim#11966) https://github.com/vim/vim/commit/6c41bedeed2a1f98fb9c55ff85634138782ad92a Co-authored-by: Yegappan Lakshmanan --- src/nvim/option.c | 275 +++++++++++++++++++++++++++++------------------------- 1 file changed, 147 insertions(+), 128 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index d3fc998274..6c9fd275fa 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -166,121 +166,175 @@ void set_init_tablocal(void) p_ch = (long)options[ch_idx].def_val; } -/// Initialize the options, first part. -/// -/// Called only once from main(), just after creating the first buffer. -/// If "clean_arg" is true, Nvim was started with --clean. -/// -/// NOTE: ELOG() etc calls are not allowed here, as log location depends on -/// env var expansion which depends on expression evaluation and other -/// editor state initialized here. Do logging in set_init_2 or later. -void set_init_1(bool clean_arg) +/// Initialize the 'shell' option to a default value. +static void set_init_default_shell(void) { - langmap_init(); - // Find default value for 'shell' option. // Don't use it if it is empty. - { - const char *shell = os_getenv("SHELL"); - if (shell != NULL) { - if (vim_strchr(shell, ' ') != NULL) { - const size_t len = strlen(shell) + 3; // two quotes and a trailing NUL - char *const cmd = xmalloc(len); - snprintf(cmd, len, "\"%s\"", shell); - set_string_default("sh", cmd, true); - } else { - set_string_default("sh", (char *)shell, false); - } + const char *shell = os_getenv("SHELL"); + if (shell != NULL) { + if (vim_strchr(shell, ' ') != NULL) { + const size_t len = strlen(shell) + 3; // two quotes and a trailing NUL + char *const cmd = xmalloc(len); + snprintf(cmd, len, "\"%s\"", shell); + set_string_default("sh", cmd, true); + } else { + set_string_default("sh", (char *)shell, false); } } +} - // Set the default for 'backupskip' to include environment variables for - // temp files. - { +/// Set the default for 'backupskip' to include environment variables for +/// temp files. +static void set_init_default_backupskip(void) +{ #ifdef UNIX - static char *(names[4]) = { "", "TMPDIR", "TEMP", "TMP" }; + static char *(names[4]) = { "", "TMPDIR", "TEMP", "TMP" }; #else - static char *(names[3]) = { "TMPDIR", "TEMP", "TMP" }; + static char *(names[3]) = { "TMPDIR", "TEMP", "TMP" }; #endif - garray_T ga; - int opt_idx = findoption("backupskip"); + garray_T ga; + int opt_idx = findoption("backupskip"); - ga_init(&ga, 1, 100); - for (size_t n = 0; n < ARRAY_SIZE(names); n++) { - bool mustfree = true; - char *p; + ga_init(&ga, 1, 100); + for (size_t n = 0; n < ARRAY_SIZE(names); n++) { + bool mustfree = true; + char *p; #ifdef UNIX - if (*names[n] == NUL) { + if (*names[n] == NUL) { # ifdef __APPLE__ - p = "/private/tmp"; + p = "/private/tmp"; # else - p = "/tmp"; + p = "/tmp"; # endif - mustfree = false; - } else // NOLINT(readability/braces) + mustfree = false; + } else // NOLINT(readability/braces) #endif - { - p = vim_getenv(names[n]); - } - if (p != NULL && *p != NUL) { - // First time count the NUL, otherwise count the ','. - const size_t len = strlen(p) + 3; - char *item = xmalloc(len); - xstrlcpy(item, p, len); - add_pathsep(item); - xstrlcat(item, "*", len); - if (find_dup_item(ga.ga_data, item, options[opt_idx].flags) - == NULL) { - ga_grow(&ga, (int)len); - if (!GA_EMPTY(&ga)) { - STRCAT(ga.ga_data, ","); - } - STRCAT(ga.ga_data, p); - add_pathsep(ga.ga_data); - STRCAT(ga.ga_data, "*"); - ga.ga_len += (int)len; + { + p = vim_getenv(names[n]); + } + if (p != NULL && *p != NUL) { + // First time count the NUL, otherwise count the ','. + const size_t len = strlen(p) + 3; + char *item = xmalloc(len); + xstrlcpy(item, p, len); + add_pathsep(item); + xstrlcat(item, "*", len); + if (find_dup_item(ga.ga_data, item, options[opt_idx].flags) + == NULL) { + ga_grow(&ga, (int)len); + if (!GA_EMPTY(&ga)) { + STRCAT(ga.ga_data, ","); } - xfree(item); - } - if (mustfree) { - xfree(p); + STRCAT(ga.ga_data, p); + add_pathsep(ga.ga_data); + STRCAT(ga.ga_data, "*"); + ga.ga_len += (int)len; } + xfree(item); } - if (ga.ga_data != NULL) { - set_string_default("bsk", ga.ga_data, true); + if (mustfree) { + xfree(p); } } + if (ga.ga_data != NULL) { + set_string_default("bsk", ga.ga_data, true); + } +} - { - // Initialize the 'cdpath' option's default value. - char *cdpath = vim_getenv("CDPATH"); - if (cdpath != NULL) { - char *buf = xmalloc(2 * strlen(cdpath) + 2); - { - buf[0] = ','; // start with ",", current dir first - int j = 1; - for (int i = 0; cdpath[i] != NUL; i++) { - if (vim_ispathlistsep(cdpath[i])) { - buf[j++] = ','; - } else { - if (cdpath[i] == ' ' || cdpath[i] == ',') { - buf[j++] = '\\'; - } - buf[j++] = cdpath[i]; - } - } - buf[j] = NUL; - int opt_idx = findoption("cdpath"); - if (opt_idx >= 0) { - options[opt_idx].def_val = buf; - options[opt_idx].flags |= P_DEF_ALLOCED; - } else { - xfree(buf); // cannot happen - } +/// Initialize the 'cdpath' option to a default value. +static void set_init_default_cdpath(void) +{ + char *cdpath = vim_getenv("CDPATH"); + if (cdpath == NULL) { + return; + } + + char *buf = xmalloc(2 * strlen(cdpath) + 2); + buf[0] = ','; // start with ",", current dir first + int j = 1; + for (int i = 0; cdpath[i] != NUL; i++) { + if (vim_ispathlistsep(cdpath[i])) { + buf[j++] = ','; + } else { + if (cdpath[i] == ' ' || cdpath[i] == ',') { + buf[j++] = '\\'; + } + buf[j++] = cdpath[i]; + } + } + buf[j] = NUL; + int opt_idx = findoption("cdpath"); + if (opt_idx >= 0) { + options[opt_idx].def_val = buf; + options[opt_idx].flags |= P_DEF_ALLOCED; + } else { + xfree(buf); // cannot happen + } + xfree(cdpath); +} + +/// Expand environment variables and things like "~" for the defaults. +/// If option_expand() returns non-NULL the variable is expanded. This can +/// only happen for non-indirect options. +/// Also set the default to the expanded value, so ":set" does not list +/// them. +/// Don't set the P_ALLOCED flag, because we don't want to free the +/// default. +static void set_init_expand_env(void) +{ + for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) { + vimoption_T *opt = &options[opt_idx]; + if (opt->flags & P_NO_DEF_EXP) { + continue; + } + char *p; + if ((opt->flags & P_GETTEXT) && opt->var != NULL) { + p = _(*(char **)opt->var); + } else { + p = option_expand(opt_idx, NULL); + } + if (p != NULL) { + p = xstrdup(p); + *(char **)opt->var = p; + if (opt->flags & P_DEF_ALLOCED) { + xfree(opt->def_val); } - xfree(cdpath); + opt->def_val = p; + opt->flags |= P_DEF_ALLOCED; } } +} + +/// Initialize the encoding used for "default" in 'fileencodings'. +static void set_init_fenc_default(void) +{ + // enc_locale() will try to find the encoding of the current locale. + // This will be used when "default" is used as encoding specifier + // in 'fileencodings'. + char *p = enc_locale(); + if (p == NULL) { + // Use utf-8 as "default" if locale encoding can't be detected. + p = xmemdupz(S_LEN("utf-8")); + } + fenc_default = p; +} + +/// Initialize the options, first part. +/// +/// Called only once from main(), just after creating the first buffer. +/// If "clean_arg" is true, Nvim was started with --clean. +/// +/// NOTE: ELOG() etc calls are not allowed here, as log location depends on +/// env var expansion which depends on expression evaluation and other +/// editor state initialized here. Do logging in set_init_2 or later. +void set_init_1(bool clean_arg) +{ + langmap_init(); + + set_init_default_shell(); + set_init_default_backupskip(); + set_init_default_cdpath(); char *backupdir = stdpaths_user_state_subpath("backup", 2, true); const size_t backupdir_len = strlen(backupdir); @@ -329,33 +383,7 @@ void set_init_1(bool clean_arg) init_spell_chartab(); // Expand environment variables and things like "~" for the defaults. - // If option_expand() returns non-NULL the variable is expanded. This can - // only happen for non-indirect options. - // Also set the default to the expanded value, so ":set" does not list - // them. - // Don't set the P_ALLOCED flag, because we don't want to free the - // default. - for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) { - vimoption_T *opt = &options[opt_idx]; - if (opt->flags & P_NO_DEF_EXP) { - continue; - } - char *p; - if ((opt->flags & P_GETTEXT) && opt->var != NULL) { - p = _(*(char **)opt->var); - } else { - p = option_expand(opt_idx, NULL); - } - if (p != NULL) { - p = xstrdup(p); - *(char **)opt->var = p; - if (opt->flags & P_DEF_ALLOCED) { - xfree(opt->def_val); - } - opt->def_val = p; - opt->flags |= P_DEF_ALLOCED; - } - } + set_init_expand_env(); save_file_ff(curbuf); // Buffer is unchanged @@ -371,16 +399,7 @@ void set_init_1(bool clean_arg) didset_options2(); lang_init(); - - // enc_locale() will try to find the encoding of the current locale. - // This will be used when 'default' is used as encoding specifier - // in 'fileencodings' - char *p = enc_locale(); - if (p == NULL) { - // use utf-8 as 'default' if locale encoding can't be detected. - p = xmemdupz(S_LEN("utf-8")); - } - fenc_default = p; + set_init_fenc_default(); #ifdef HAVE_WORKING_LIBINTL // GNU gettext 0.10.37 supports this feature: set the codeset used for -- cgit From 5ca6cf55f9c772f5c691b08dc49581f27f88e8f9 Mon Sep 17 00:00:00 2001 From: glacambre Date: Sat, 11 Feb 2023 13:51:33 +0100 Subject: fix(helpers): restore channel id after a call to WITH_SCRIPT_CONTEXT In https://github.com/neovim/neovim/pull/22214, init_default_autocmds has been turned into a lua function call to nvim_create_augroup and nvim_create_autocmd. This introduced a strange regression: a test in vim_spec.lua started failing with its last_set_chan value switching from 0 to -9223372036854775808. It turns out that -9223372036854775808 is the value of LUA_INTERNAL_CALL and would be inherited as last_set_chan by options set from the command line due to the WITH_SCRIPT_CONTEXT macro not restoring the channel id (WITH_SCRIPT_CONTEXT is used by nvim_create_augroup). --- src/nvim/api/private/helpers.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h index ec97ba9ec6..b70452d7cb 100644 --- a/src/nvim/api/private/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -175,11 +175,13 @@ typedef struct { #define WITH_SCRIPT_CONTEXT(channel_id, code) \ do { \ const sctx_T save_current_sctx = current_sctx; \ + const uint64_t save_channel_id = current_channel_id; \ current_sctx.sc_sid = \ (channel_id) == LUA_INTERNAL_CALL ? SID_LUA : SID_API_CLIENT; \ current_sctx.sc_lnum = 0; \ current_channel_id = channel_id; \ code; \ + current_channel_id = save_channel_id; \ current_sctx = save_current_sctx; \ } while (0); -- cgit From c5b34fa55483d84d1de32937ffff0b7cf1aeba78 Mon Sep 17 00:00:00 2001 From: glacambre Date: Sat, 11 Feb 2023 09:45:11 +0100 Subject: refactor: move init_default_autocmds to lua The original motivation for this change came from developping https://github.com/neovim/neovim/pull/22159, which will require adding more autocommand creation to Neovim's startup sequence. This change requires lightly editing a test that expected no autocommand to have been created from lua. --- src/nvim/autocmd.c | 29 ----------------------------- src/nvim/main.c | 9 +++------ 2 files changed, 3 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 0485fbcdb0..4cc75fa9a6 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -2759,32 +2759,3 @@ void do_autocmd_focusgained(bool gained) recursive = false; } - -static void define_autocmd(event_T event, char *pat, char *group, bool once, bool nested, char *cmd) -{ - AucmdExecutable exec = AUCMD_EXECUTABLE_INIT; - exec.type = CALLABLE_EX; - exec.callable.cmd = cmd; // autocmd_register() makes a copy - int group_id = augroup_add(group); - autocmd_register(0, event, pat, (int)strlen(pat), group_id, once, nested, NULL, exec); -} - -/// initialization of default autocmds -void init_default_autocmds(void) -{ - // open terminals when opening files that start with term:// -#define PROTO "term://" - define_autocmd(EVENT_BUFREADCMD, PROTO "*", "nvim_terminal", false, true, - "if !exists('b:term_title')|call termopen(" - // Capture the command string - "matchstr(expand(\"\"), " - "'\\c\\m" PROTO "\\%(.\\{-}//\\%(\\d\\+:\\)\\?\\)\\?\\zs.*'), " - // capture the working directory - "{'cwd': expand(get(matchlist(expand(\"\"), " - "'\\c\\m" PROTO "\\(.\\{-}\\)//'), 1, ''))})" - "|endif"); -#undef PROTO - // limit syntax synchronization in the command window - define_autocmd(EVENT_CMDWINENTER, "[:>]", "nvim_cmdwin", false, false, - "syntax sync minlines=1 maxlines=1"); -} diff --git a/src/nvim/main.c b/src/nvim/main.c index 2bbe70784d..1f155aa343 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -404,19 +404,16 @@ int main(int argc, char **argv) open_script_files(¶ms); - // Default mappings (incl. menus) + // Default mappings (incl. menus) & autocommands Error err = ERROR_INIT; - Object o = NLUA_EXEC_STATIC("return vim._init_default_mappings()", + Object o = NLUA_EXEC_STATIC("return vim._init_defaults()", (Array)ARRAY_DICT_INIT, &err); assert(!ERROR_SET(&err)); api_clear_error(&err); assert(o.type == kObjectTypeNil); api_free_object(o); - TIME_MSG("init default mappings"); - - init_default_autocmds(); - TIME_MSG("init default autocommands"); + TIME_MSG("init default mappings & autocommands"); bool vimrc_none = strequal(params.use_vimrc, "NONE"); -- cgit From 27177e581902967dcf4f2f426464da1b636ca420 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 11 Feb 2023 14:14:24 +0100 Subject: refactor: reduce scope of locals as per the style guide (#22211) --- src/nvim/cmdexpand.c | 26 ++++---- src/nvim/drawscreen.c | 5 +- src/nvim/eval/userfunc.c | 12 ++-- src/nvim/eval/vars.c | 16 ++--- src/nvim/grid.c | 23 +++----- src/nvim/input.c | 6 +- src/nvim/lua/executor.c | 3 +- src/nvim/lua/spell.c | 3 +- src/nvim/main.c | 9 +-- src/nvim/mark.c | 3 +- src/nvim/match.c | 3 +- src/nvim/memfile.c | 6 +- src/nvim/memline.c | 37 +++++------- src/nvim/menu.c | 6 +- src/nvim/message.c | 19 +++--- src/nvim/move.c | 2 +- src/nvim/normal.c | 33 ++++------- src/nvim/option.c | 3 +- src/nvim/optionstr.c | 3 +- src/nvim/plines.c | 15 ++--- src/nvim/runtime.c | 6 +- src/nvim/sign.c | 18 ++---- src/nvim/spellsuggest.c | 151 ++++++++++++++++------------------------------- src/nvim/tag.c | 49 ++++++--------- src/nvim/textobject.c | 37 ++++-------- 25 files changed, 177 insertions(+), 317 deletions(-) (limited to 'src') diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index 64e5664f1f..97feab2978 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -222,10 +222,8 @@ static void ExpandEscape(expand_T *xp, char *str, int numfiles, char **files, in int nextwild(expand_T *xp, int type, int options, bool escape) { CmdlineInfo *const ccline = get_cmdline_info(); - int i, j; - char *p1; + int i; char *p2; - int difflen; if (xp->xp_numfiles == -1) { set_expand_context(xp); @@ -258,6 +256,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape) // Get next/previous match for a previous expanded pattern. p2 = ExpandOne(xp, NULL, NULL, 0, type); } else { + char *p1; if (cmdline_fuzzy_completion_supported(xp)) { // If fuzzy matching, don't modify the search string p1 = xstrdup(xp->xp_pattern); @@ -282,6 +281,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape) // Longest match: make sure it is not shorter, happens with :help. if (p2 != NULL && type == WILD_LONGEST) { + int j; for (j = 0; (size_t)j < xp->xp_pattern_len; j++) { if (ccline->cmdbuff[i + j] == '*' || ccline->cmdbuff[i + j] == '?') { @@ -295,7 +295,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape) } if (p2 != NULL && !got_int) { - difflen = (int)strlen(p2) - (int)(xp->xp_pattern_len); + int difflen = (int)strlen(p2) - (int)(xp->xp_pattern_len); if (ccline->cmdlen + difflen + 4 > ccline->cmdbufflen) { realloc_cmdbuff(ccline->cmdlen + difflen + 4); xp->xp_pattern = ccline->cmdbuff + i; @@ -454,8 +454,6 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m char *selend = NULL; static int first_match = 0; bool add_left = false; - char *s; - int emenu; int l; if (matches == NULL) { // interrupted completion? @@ -528,10 +526,9 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m selstart_col = clen; } - s = SHOW_MATCH(i); + char *s = SHOW_MATCH(i); // Check for menu separators - replace with '|' - emenu = (xp->xp_context == EXPAND_MENUS - || xp->xp_context == EXPAND_MENUNAMES); + int emenu = (xp->xp_context == EXPAND_MENUS || xp->xp_context == EXPAND_MENUNAMES); if (emenu && menu_is_separator(s)) { STRCPY(buf + len, transchar('|')); l = (int)strlen(buf + len); @@ -847,7 +844,6 @@ char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode) static int findex; static char *orig_save = NULL; // kept value of orig int orig_saved = false; - int i; // first handle the case of using an old match if (mode == WILD_NEXT || mode == WILD_PREV @@ -900,12 +896,12 @@ char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode) // TODO(philix): use xstpcpy instead of strcat in a loop (ExpandOne) if (mode == WILD_ALL && xp->xp_numfiles > 0 && !got_int) { size_t len = 0; - for (i = 0; i < xp->xp_numfiles; i++) { + for (int i = 0; i < xp->xp_numfiles; i++) { len += strlen(xp->xp_files[i]) + 1; } ss = xmalloc(len); *ss = NUL; - for (i = 0; i < xp->xp_numfiles; i++) { + for (int i = 0; i < xp->xp_numfiles; i++) { STRCAT(ss, xp->xp_files[i]); if (i != xp->xp_numfiles - 1) { STRCAT(ss, (options & WILD_USE_NL) ? "\n" : " "); @@ -1375,7 +1371,6 @@ void set_expand_context(expand_T *xp) static const char *set_cmd_index(const char *cmd, exarg_T *eap, expand_T *xp, int *complp) { const char *p = NULL; - size_t len = 0; const bool fuzzy = cmdline_fuzzy_complete(cmd); // Isolate the command and search for it in the command table. @@ -1410,7 +1405,7 @@ static const char *set_cmd_index(const char *cmd, exarg_T *eap, expand_T *xp, in if (p == cmd && vim_strchr("@*!=><&~#", (uint8_t)(*p)) != NULL) { p++; } - len = (size_t)(p - cmd); + size_t len = (size_t)(p - cmd); if (len == 0) { xp->xp_context = EXPAND_UNSUCCESSFUL; @@ -2955,7 +2950,6 @@ static void expand_shellcmd(char *filepat, char ***matches, int *numMatches, int char *path = NULL; garray_T ga; char *buf = xmalloc(MAXPATHL); - size_t l; char *s, *e; int flags = flagsarg; bool did_curdir = false; @@ -3013,7 +3007,7 @@ static void expand_shellcmd(char *filepat, char ***matches, int *numMatches, int flags &= ~EW_DIR; } - l = (size_t)(e - s); + size_t l = (size_t)(e - s); if (l > MAXPATHL - 5) { break; } diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 04c342e068..2bc335a7e0 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -1620,8 +1620,6 @@ static void win_update(win_T *wp, DecorProviders *providers) && !(dollar_vcol >= 0 && mod_bot == mod_top + 1) && row >= top_end) { int old_rows = 0; - int new_rows = 0; - int xtra_rows; linenr_T l; int i; @@ -1656,6 +1654,7 @@ static void win_update(win_T *wp, DecorProviders *providers) bot_start = 0; bot_scroll_start = 0; } else { + int new_rows = 0; // Able to count old number of rows: Count new window // rows, and may insert/delete lines long j = idx; @@ -1674,7 +1673,7 @@ static void win_update(win_T *wp, DecorProviders *providers) break; } } - xtra_rows = new_rows - old_rows; + int xtra_rows = new_rows - old_rows; if (xtra_rows < 0) { // May scroll text up. If there is not enough // remaining text or scrolling fails, must redraw the diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 2496cbc430..3c4cc34464 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -729,7 +729,6 @@ static void cleanup_function_call(funccall_T *fc) /// @param[in] force When true, we are exiting. static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force) { - funccall_T **pfc; int i; if (fc == NULL) { @@ -738,7 +737,7 @@ static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force) fc->fc_refcount--; if (force ? fc->fc_refcount <= 0 : !fc_referenced(fc)) { - for (pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->caller) { + for (funccall_T **pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->caller) { if (fc == *pfc) { *pfc = fc->caller; free_funccal_contents(fc); @@ -3289,7 +3288,6 @@ int func_has_abort(void *cookie) /// Changes "rettv" in-place. void make_partial(dict_T *const selfdict, typval_T *const rettv) { - char *fname; char *tofree = NULL; ufunc_T *fp; char fname_buf[FLEN_FIXED + 1]; @@ -3298,7 +3296,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) if (rettv->v_type == VAR_PARTIAL && rettv->vval.v_partial->pt_func != NULL) { fp = rettv->vval.v_partial->pt_func; } else { - fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING + char *fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING ? rettv->vval.v_string : rettv->vval.v_partial->pt_name; // Translate "s:func" to the stored function name. @@ -3319,7 +3317,6 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) pt->pt_name = rettv->vval.v_string; } else { partial_T *ret_pt = rettv->vval.v_partial; - int i; // Partial: copy the function name, use selfdict and copy // args. Can't take over name or args, the partial might @@ -3335,7 +3332,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) size_t arg_size = sizeof(typval_T) * (size_t)ret_pt->pt_argc; pt->pt_argv = (typval_T *)xmalloc(arg_size); pt->pt_argc = ret_pt->pt_argc; - for (i = 0; i < pt->pt_argc; i++) { + for (int i = 0; i < pt->pt_argc; i++) { tv_copy(&ret_pt->pt_argv[i], &pt->pt_argv[i]); } } @@ -3641,14 +3638,13 @@ bool set_ref_in_func(char *name, ufunc_T *fp_in, int copyID) int error = FCERR_NONE; char fname_buf[FLEN_FIXED + 1]; char *tofree = NULL; - char *fname; bool abort = false; if (name == NULL && fp_in == NULL) { return false; } if (fp_in == NULL) { - fname = fname_trans_sid(name, fname_buf, &tofree, &error); + char *fname = fname_trans_sid(name, fname_buf, &tofree, &error); fp = find_func(fname); } if (fp != NULL) { diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 3d9b476863..d80bdc70f6 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -369,12 +369,10 @@ int ex_let_vars(char *arg_start, typval_T *tv, int copy, int semicolon, int var_ /// @return NULL for an error. const char *skip_var_list(const char *arg, int *var_count, int *semicolon) { - const char *p; - const char *s; - if (*arg == '[') { + const char *s; // "[var, var]": find the matching ']'. - p = arg; + const char *p = arg; for (;;) { p = skipwhite(p + 1); // skip whites after '[', ';' or ',' s = skip_var_one((char *)p); @@ -575,7 +573,6 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_WARN_UNUSED_RESULT { char *arg_end = NULL; - int len; // ":let $VAR = expr": Set environment variable. if (*arg == '$') { @@ -586,7 +583,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo // Find the end of the name. arg++; char *name = arg; - len = get_env_len((const char **)&arg); + int len = get_env_len((const char **)&arg); if (len == 0) { semsg(_(e_invarg2), name - 1); } else { @@ -722,12 +719,10 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo && vim_strchr(endchars, (uint8_t)(*skipwhite(arg + 1))) == NULL) { emsg(_(e_letunexp)); } else { - char *s; - char *ptofree = NULL; const char *p = tv_get_string_chk(tv); if (p != NULL && op != NULL && *op == '.') { - s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc); + char *s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc); if (s != NULL) { ptofree = concat_str(s, p); p = (const char *)ptofree; @@ -861,10 +856,9 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ { int forceit = eap->forceit; int ret = OK; - int cc; if (lp->ll_tv == NULL) { - cc = (uint8_t)(*name_end); + int cc = (uint8_t)(*name_end); *name_end = NUL; // Environment variable, normal name or expanded name. diff --git a/src/nvim/grid.c b/src/nvim/grid.c index 46f8a59710..8815ac726a 100644 --- a/src/nvim/grid.c +++ b/src/nvim/grid.c @@ -204,15 +204,11 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, int len = textlen; int c; size_t max_off; - int mbyte_blen = 1; - int mbyte_cells = 1; - int u8c = 0; int u8cc[MAX_MCO]; bool clear_next_cell = false; int prev_c = 0; // previous Arabic character int pc, nc, nc1; int pcc[MAX_MCO]; - int need_redraw; bool do_flush = false; grid_adjust(&grid, &row, &col); @@ -249,13 +245,13 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, && *ptr != NUL) { c = (unsigned char)(*ptr); // check if this is the first byte of a multibyte - mbyte_blen = len > 0 + int mbyte_blen = len > 0 ? utfc_ptr2len_len(ptr, (int)((text + len) - ptr)) : utfc_ptr2len(ptr); - u8c = len >= 0 + int u8c = len >= 0 ? utfc_ptr2char_len(ptr, u8cc, (int)((text + len) - ptr)) : utfc_ptr2char(ptr, u8cc); - mbyte_cells = utf_char2cells(u8c); + int mbyte_cells = utf_char2cells(u8c); if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c)) { // Do Arabic shaping. if (len >= 0 && (int)(ptr - text) + mbyte_blen >= len) { @@ -287,11 +283,11 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, schar_T buf; schar_from_cc(buf, u8c, u8cc); - need_redraw = schar_cmp(grid->chars[off], buf) - || (mbyte_cells == 2 && grid->chars[off + 1][0] != 0) - || grid->attrs[off] != attr - || exmode_active - || rdb_flags & RDB_NODELTA; + int need_redraw = schar_cmp(grid->chars[off], buf) + || (mbyte_cells == 2 && grid->chars[off + 1][0] != 0) + || grid->attrs[off] != attr + || exmode_active + || rdb_flags & RDB_NODELTA; if (need_redraw) { // When at the end of the text and overwriting a two-cell @@ -497,7 +493,6 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle size_t max_off_from; size_t max_off_to; int col = 0; - bool redraw_this; // Does character need redraw? bool redraw_next; // redraw_this for next character bool clear_next = false; int char_cells; // 1: normal char @@ -559,7 +554,7 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle if (col + 1 < endcol) { char_cells = line_off2cells(linebuf_char, off_from, max_off_from); } - redraw_this = redraw_next; + bool redraw_this = redraw_next; // Does character need redraw? redraw_next = grid_char_needs_redraw(grid, off_from + (size_t)char_cells, off_to + (size_t)char_cells, endcol - col - char_cells); diff --git a/src/nvim/input.c b/src/nvim/input.c index 2869155a09..5b9b866778 100644 --- a/src/nvim/input.c +++ b/src/nvim/input.c @@ -88,7 +88,6 @@ int get_keystroke(MultiQueue *events) { char *buf = NULL; int buflen = 150; - int maxlen; int len = 0; int n; int save_mapped_ctrl_c = mapped_ctrl_c; @@ -100,7 +99,7 @@ int get_keystroke(MultiQueue *events) // Leave some room for check_termcode() to insert a key code into (max // 5 chars plus NUL). And fix_input_buffer() can triple the number of // bytes. - maxlen = (buflen - 6 - len) / 3; + int maxlen = (buflen - 6 - len) / 3; if (buf == NULL) { buf = xmalloc((size_t)buflen); } else if (maxlen < 10) { @@ -166,7 +165,6 @@ int get_keystroke(MultiQueue *events) int get_number(int colon, int *mouse_used) { int n = 0; - int c; int typed = 0; if (mouse_used != NULL) { @@ -183,7 +181,7 @@ int get_number(int colon, int *mouse_used) allow_keys++; // no mapping here, but recognize keys for (;;) { ui_cursor_goto(msg_row, msg_col); - c = safe_vgetc(); + int c = safe_vgetc(); if (ascii_isdigit(c)) { n = n * 10 + c - '0'; msg_putchar(c); diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 5fbbb342bf..c8fc76e20d 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1766,13 +1766,12 @@ bool nlua_exec_file(const char *path) StringBuilder sb = KV_INITIAL_VALUE; kv_resize(sb, 64); - ptrdiff_t read_size = -1; // Read all input from stdin, unless interrupted (ctrl-c). while (true) { if (got_int) { // User canceled. return false; } - read_size = file_read(stdin_dup, IObuff, 64); + ptrdiff_t read_size = file_read(stdin_dup, IObuff, 64); if (read_size < 0) { // Error. return false; } diff --git a/src/nvim/lua/spell.c b/src/nvim/lua/spell.c index d510d25e90..78e023c26d 100644 --- a/src/nvim/lua/spell.c +++ b/src/nvim/lua/spell.c @@ -51,7 +51,6 @@ int nlua_spell_check(lua_State *lstate) } hlf_T attr = HLF_COUNT; - size_t len = 0; size_t pos = 0; int capcol = -1; int no_res = 0; @@ -61,7 +60,7 @@ int nlua_spell_check(lua_State *lstate) while (*str != NUL) { attr = HLF_COUNT; - len = spell_check(curwin, (char *)str, &attr, &capcol, false); + size_t len = spell_check(curwin, (char *)str, &attr, &capcol, false); assert(len <= INT_MAX); if (attr != HLF_COUNT) { diff --git a/src/nvim/main.c b/src/nvim/main.c index f36730a8b3..c12de07077 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -920,9 +920,8 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr, } Array args = ARRAY_DICT_INIT; - String arg_s; for (int t_argc = remote_args; t_argc < argc; t_argc++) { - arg_s = cstr_to_string(argv[t_argc]); + String arg_s = cstr_to_string(argv[t_argc]); ADD(args, STRING_OBJ(arg_s)); } @@ -1620,9 +1619,6 @@ static void open_script_files(mparm_T *parmp) // Also does recovery if "recoverymode" set. static void create_windows(mparm_T *parmp) { - int dorewind; - int done = 0; - // Create the number of windows that was requested. if (parmp->window_count == -1) { // was not set parmp->window_count = 1; @@ -1658,6 +1654,7 @@ static void create_windows(mparm_T *parmp) } do_modelines(0); // do modelines } else { + int done = 0; // Open a buffer for windows that don't have one yet. // Commands in the vimrc might have loaded a file or split the window. // Watch out for autocommands that delete a window. @@ -1665,7 +1662,7 @@ static void create_windows(mparm_T *parmp) // Don't execute Win/Buf Enter/Leave autocommands here autocmd_no_enter++; autocmd_no_leave++; - dorewind = true; + int dorewind = true; while (done++ < 1000) { if (dorewind) { if (parmp->window_layout == WIN_TABS) { diff --git a/src/nvim/mark.c b/src/nvim/mark.c index f1a1f25e6c..0a944da2c4 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -521,11 +521,10 @@ fmark_T *pos_to_mark(buf_T *buf, fmark_T *fmp, pos_T pos) /// @return whether the buffer was switched or not. static MarkMoveRes switch_to_mark_buf(fmark_T *fm, bool pcmark_on_switch) { - bool res; if (fm->fnum != curbuf->b_fnum) { // Switch to another file. int getfile_flag = pcmark_on_switch ? GETF_SETMARK : 0; - res = buflist_getfile(fm->fnum, (linenr_T)1, getfile_flag, false) == OK; + bool res = buflist_getfile(fm->fnum, (linenr_T)1, getfile_flag, false) == OK; return res == true ? kMarkSwitchedBuf : kMarkMoveFailed; } return 0; diff --git a/src/nvim/match.c b/src/nvim/match.c index 6663dfd7ec..93c8a58051 100644 --- a/src/nvim/match.c +++ b/src/nvim/match.c @@ -419,7 +419,6 @@ static void next_search_hl(win_T *win, match_T *search_hl, match_T *shl, linenr_ colnr_T mincol, matchitem_T *cur) FUNC_ATTR_NONNULL_ARG(2) { - linenr_T l; colnr_T matchcol; long nmatched = 0; const int called_emsg_before = called_emsg; @@ -435,7 +434,7 @@ static void next_search_hl(win_T *win, match_T *search_hl, match_T *shl, linenr_ // 1. If the "lnum" is below a previous match, start a new search. // 2. If the previous match includes "mincol", use it. // 3. Continue after the previous match. - l = shl->lnum + shl->rm.endpos[0].lnum - shl->rm.startpos[0].lnum; + linenr_T l = shl->lnum + shl->rm.endpos[0].lnum - shl->rm.startpos[0].lnum; if (lnum > l) { shl->lnum = 0; } else if (lnum < l || shl->rm.endpos[0].col > mincol) { diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c index 46be9ccea5..118b5d5886 100644 --- a/src/nvim/memfile.c +++ b/src/nvim/memfile.c @@ -603,11 +603,9 @@ static int mf_read(memfile_T *mfp, bhdr_T *hp) static int mf_write(memfile_T *mfp, bhdr_T *hp) { off_T offset; // offset in the file - blocknr_T nr; // block nr which is being written bhdr_T *hp2; unsigned page_size; // number of bytes in a page unsigned page_count; // number of pages written - unsigned size; // number of bytes written if (mfp->mf_fd < 0) { // there is no file, can't write return FAIL; @@ -626,7 +624,7 @@ static int mf_write(memfile_T *mfp, bhdr_T *hp) /// If block 'mf_infile_count' is not in the hash list, it has been /// freed. Fill the space in the file with data from the current block. for (;;) { - nr = hp->bh_bnum; + blocknr_T nr = hp->bh_bnum; // block nr which is being written if (nr > mfp->mf_infile_count) { // beyond end of file nr = mfp->mf_infile_count; hp2 = mf_find_hash(mfp, nr); // NULL caught below @@ -645,7 +643,7 @@ static int mf_write(memfile_T *mfp, bhdr_T *hp) } else { page_count = hp2->bh_page_count; } - size = page_size * page_count; + unsigned size = page_size * page_count; // number of bytes written void *data = (hp2 == NULL) ? hp->bh_data : hp2->bh_data; if ((unsigned)write_eintr(mfp->mf_fd, data, size) != size) { /// Avoid repeating the error message, this mostly happens when the diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 555f21c4fd..ff0a6d7627 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -2022,7 +2022,6 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char *line, colnr_T len, boo int lineadd; blocknr_T bnum_left, bnum_right; linenr_T lnum_left, lnum_right; - int pb_idx; PTR_BL *pp_new; // We are going to allocate a new data block. Depending on the @@ -2156,7 +2155,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char *line, colnr_T len, boo // update pointer blocks for the new data block for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; stack_idx--) { infoptr_T *ip = &(buf->b_ml.ml_stack[stack_idx]); - pb_idx = ip->ip_index; + int pb_idx = ip->ip_index; if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) { return FAIL; } @@ -3211,7 +3210,6 @@ static int do_swapexists(buf_T *buf, char *fname) static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_existing_dir) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 2, 4) { - size_t n; char *buf_fname = buf->b_fname; // Isolate a directory name from *dirp and put it in dir_name. @@ -3224,6 +3222,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_ char *fname = makeswapname(buf_fname, buf->b_ffname, buf, dir_name); for (;;) { + size_t n; if (fname == NULL) { // must be out of memory break; } @@ -3605,11 +3604,8 @@ static void ml_updatechunk(buf_T *buf, linenr_T line, long len, int updtype) linenr_T curline = ml_upd_lastcurline; int curix = ml_upd_lastcurix; - long size; chunksize_T *curchnk; - int rest; bhdr_T *hp; - DATA_BL *dp; if (buf->b_ml.ml_usedchunks == -1 || len == 0) { return; @@ -3655,6 +3651,8 @@ static void ml_updatechunk(buf_T *buf, linenr_T line, long len, int updtype) } curchnk->mlcs_totalsize += len; if (updtype == ML_CHNK_ADDLINE) { + int rest; + DATA_BL *dp; curchnk->mlcs_numlines++; // May resize here so we don't have to do it in both cases below @@ -3665,17 +3663,14 @@ static void ml_updatechunk(buf_T *buf, linenr_T line, long len, int updtype) } if (buf->b_ml.ml_chunksize[curix].mlcs_numlines >= MLCS_MAXL) { - int count; // number of entries in block - int idx; int text_end; - int linecnt; memmove(buf->b_ml.ml_chunksize + curix + 1, buf->b_ml.ml_chunksize + curix, (size_t)(buf->b_ml.ml_usedchunks - curix) * sizeof(chunksize_T)); // Compute length of first half of lines in the split chunk - size = 0; - linecnt = 0; + long size = 0; + int linecnt = 0; while (curline < buf->b_ml.ml_line_count && linecnt < MLCS_MINL) { if ((hp = ml_find_line(buf, curline, ML_FIND)) == NULL) { @@ -3683,8 +3678,9 @@ static void ml_updatechunk(buf_T *buf, linenr_T line, long len, int updtype) return; } dp = hp->bh_data; - count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1; - idx = curline - buf->b_ml.ml_locked_low; + int count + = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1; // number of entries in block + int idx = curline - buf->b_ml.ml_locked_low; curline = buf->b_ml.ml_locked_high + 1; if (idx == 0) { // first line in block, text at the end text_end = (int)dp->db_txt_end; @@ -3793,13 +3789,8 @@ long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp, bool no_ff) int curix; long size; bhdr_T *hp; - DATA_BL *dp; - int count; // number of entries in block - int idx; - int start_idx; int text_end; long offset; - int len; int ffdos = !no_ff && (get_fileformat(buf) == EOL_DOS); int extra = 0; @@ -3859,9 +3850,11 @@ long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp, bool no_ff) || (hp = ml_find_line(buf, curline, ML_FIND)) == NULL) { return -1; } - dp = hp->bh_data; - count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1; - start_idx = idx = curline - buf->b_ml.ml_locked_low; + DATA_BL *dp = hp->bh_data; + int count + = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1; // number of entries in block + int idx; + int start_idx = idx = curline - buf->b_ml.ml_locked_low; if (idx == 0) { // first line in block, text at the end text_end = (int)dp->db_txt_end; } else { @@ -3889,7 +3882,7 @@ long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp, bool no_ff) idx++; } } - len = text_end - (int)((dp->db_index[idx]) & DB_INDEX_MASK); + int len = text_end - (int)((dp->db_index[idx]) & DB_INDEX_MASK); size += len; if (offset != 0 && size >= offset) { if (size + ffdos == offset) { diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 2a18b08d8d..8ab515bf0e 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -815,7 +815,6 @@ static int show_menus(char *const path_name, int modes) static void show_menus_recursive(vimmenu_T *menu, int modes, int depth) { int i; - int bit; if (menu != NULL && (menu->modes & modes) == 0x0) { return; @@ -838,7 +837,7 @@ static void show_menus_recursive(vimmenu_T *menu, int modes, int depth) } if (menu != NULL && menu->children == NULL) { - for (bit = 0; bit < MENU_MODES; bit++) { + for (int bit = 0; bit < MENU_MODES; bit++) { if ((menu->modes & modes & (1 << bit)) != 0) { msg_putchar('\n'); if (got_int) { // "q" hit for "--more--" @@ -902,7 +901,6 @@ char *set_context_in_menu_cmd(expand_T *xp, const char *cmd, char *arg, bool for char *after_dot; char *p; char *path_name = NULL; - char *name; int unmenu; vimmenu_T *menu; int expand_menus; @@ -963,7 +961,7 @@ char *set_context_in_menu_cmd(expand_T *xp, const char *cmd, char *arg, bool for path_name = xmalloc(path_len); xstrlcpy(path_name, arg, path_len); } - name = path_name; + char *name = path_name; while (name != NULL && *name) { p = menu_name_skip(name); while (menu != NULL) { diff --git a/src/nvim/message.c b/src/nvim/message.c index 88f58ef0df..4904bde095 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -369,14 +369,13 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline) char *msg_strtrunc(char *s, int force) { char *buf = NULL; - int len; - int room; // May truncate message to avoid a hit-return prompt if ((!msg_scroll && !need_wait_return && shortmess(SHM_TRUNCALL) && !exmode_active && msg_silent == 0 && !ui_has(kUIMessages)) || force) { - len = vim_strsize(s); + int room; + int len = vim_strsize(s); if (msg_scrolled != 0) { // Use all the columns. room = (Rows - msg_row) * Columns - 1; @@ -1033,7 +1032,6 @@ void ex_messages(void *const eap_p) { const exarg_T *const eap = (const exarg_T *)eap_p; struct msg_hist *p; - int c = 0; if (strcmp(eap->arg, "clear") == 0) { int keep = eap->addr_count == 0 ? 0 : eap->line2; @@ -1052,6 +1050,7 @@ void ex_messages(void *const eap_p) p = first_msg_hist; if (eap->addr_count != 0) { + int c = 0; // Count total messages for (; p != NULL && !got_int; p = p->next) { c++; @@ -1542,7 +1541,6 @@ int msg_outtrans_len_attr(const char *msgstr, int len, int attr) const char *str = msgstr; const char *plain_start = msgstr; char *s; - int mb_l; int c; int save_got_int = got_int; @@ -1565,7 +1563,7 @@ int msg_outtrans_len_attr(const char *msgstr, int len, int attr) // Normal characters are printed several at a time. while (--len >= 0 && !got_int) { // Don't include composing chars after the end. - mb_l = utfc_ptr2len_len(str, len + 1); + int mb_l = utfc_ptr2len_len(str, len + 1); if (mb_l > 1) { c = utf_ptr2char(str); if (vim_isprintc(c)) { @@ -2652,12 +2650,11 @@ void msg_sb_eol(void) static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp) { msgchunk_T *mp = smp; - char *p; for (;;) { msg_row = row; msg_col = mp->sb_msg_col; - p = mp->sb_text; + char *p = mp->sb_text; if (*p == '\n') { // don't display the line break p++; } @@ -2767,7 +2764,6 @@ static int do_more_prompt(int typed_char) int oldState = State; int c; int retval = false; - int toscroll; bool to_redraw = false; msgchunk_T *mp_last = NULL; msgchunk_T *mp; @@ -2809,7 +2805,7 @@ static int do_more_prompt(int typed_char) c = get_keystroke(resize_events); } - toscroll = 0; + int toscroll = 0; switch (c) { case BS: // scroll one line back case K_BS: @@ -3507,7 +3503,6 @@ int do_dialog(int type, char *title, char *message, char *buttons, int dfltbutto { int retval = 0; char *hotkeys; - int c; int i; if (silent_mode // No dialogs in silent mode ("ex -s") @@ -3530,7 +3525,7 @@ int do_dialog(int type, char *title, char *message, char *buttons, int dfltbutto for (;;) { // Get a typed character directly from the user. - c = get_keystroke(NULL); + int c = get_keystroke(NULL); switch (c) { case CAR: // User accepts default option case NL: diff --git a/src/nvim/move.c b/src/nvim/move.c index 3af26b910e..a946633bf6 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -145,7 +145,6 @@ void update_topline(win_T *wp) { linenr_T old_topline; int old_topfill; - bool check_topline = false; bool check_botline = false; long *so_ptr = wp->w_p_so >= 0 ? &wp->w_p_so : &p_so; long save_so = *so_ptr; @@ -189,6 +188,7 @@ void update_topline(win_T *wp) wp->w_viewport_invalid = true; wp->w_scbind_pos = 1; } else { + bool check_topline = false; // If the cursor is above or near the top of the window, scroll the window // to show the line the cursor is in, with 'scrolloff' context. if (wp->w_topline > 1) { diff --git a/src/nvim/normal.c b/src/nvim/normal.c index b88cfb8926..a84d5c73a4 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -401,10 +401,8 @@ void init_normal_cmds(void) /// @return -1 for invalid command. static int find_command(int cmdchar) { - int i; int idx; int top, bot; - int c; // A multi-byte character is never a command. if (cmdchar >= 0x100) { @@ -429,8 +427,8 @@ static int find_command(int cmdchar) top = NV_CMDS_SIZE - 1; idx = -1; while (bot <= top) { - i = (top + bot) / 2; - c = nv_cmds[nv_cmd_idx[i]].cmd_char; + int i = (top + bot) / 2; + int c = nv_cmds[nv_cmd_idx[i]].cmd_char; if (c < 0) { c = -c; } @@ -693,7 +691,6 @@ static void normal_get_additional_char(NormalState *s) int *cp; bool repl = false; // get character for replace mode bool lit = false; // get extra character literally - bool langmap_active = false; // using :lmap mappings int lang; // getting a text character no_mapping++; @@ -729,6 +726,7 @@ static void normal_get_additional_char(NormalState *s) // Get a second or third character. if (cp != NULL) { + bool langmap_active = false; // using :lmap mappings if (repl) { State = MODE_REPLACE; // pretend Replace mode ui_cursor_shape(); // show different cursor shape @@ -1848,7 +1846,6 @@ void clear_showcmd(void) snprintf(showcmd_buf, SHOWCMD_BUFLEN, "%" PRId64, (int64_t)lines); } else { char *s, *e; - int l; int bytes = 0; int chars = 0; @@ -1860,7 +1857,7 @@ void clear_showcmd(void) e = ml_get_pos(&VIsual); } while ((*p_sel != 'e') ? s <= e : s < e) { - l = utfc_ptr2len(s); + int l = utfc_ptr2len(s); if (l == 0) { bytes++; chars++; @@ -2427,7 +2424,6 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist) int linelen = linetabsize(get_cursor_line_ptr()); bool retval = true; bool atend = false; - int n; int col_off1; // margin offset for first screen line int col_off2; // margin offset for wrapped screen line int width1; // text width for first screen line @@ -2446,6 +2442,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist) } if (curwin->w_width_inner != 0) { + int n; // Instead of sticking at the last character of the buffer line we // try to stick in the last column of the screen. if (curwin->w_curswant == MAXCOL) { @@ -2793,7 +2790,6 @@ static int nv_zg_zw(cmdarg_T *cap, int nchar) /// Commands that start with "z". static void nv_zet(cmdarg_T *cap) { - int n; colnr_T col; int nchar = cap->nchar; long old_fdl = curwin->w_p_fdl; @@ -2949,7 +2945,7 @@ static void nv_zet(cmdarg_T *cap) } else { getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col); } - n = curwin->w_width_inner - curwin_col_off(); + int n = curwin->w_width_inner - curwin_col_off(); if (col + siso < n) { col = 0; } else { @@ -3438,7 +3434,6 @@ static void nv_ident(cmdarg_T *cap) int cmdchar; bool g_cmd; // "g" command bool tag_cmd = false; - char *aux_ptr; if (cap->cmdchar == 'g') { // "g*", "g#", "g]" and "gCTRL-]" cmdchar = cap->nchar; @@ -3542,6 +3537,7 @@ static void nv_ident(cmdarg_T *cap) STRCAT(buf, p); xfree(p); } else { + char *aux_ptr; if (cmdchar == '*') { aux_ptr = (magic_isset() ? "/.*~[^$\\" : "/^$\\"); } else if (cmdchar == '#') { @@ -3653,10 +3649,8 @@ static void nv_tagpop(cmdarg_T *cap) /// Handle scrolling command 'H', 'L' and 'M'. static void nv_scroll(cmdarg_T *cap) { - int used = 0; long n; linenr_T lnum; - int half; cap->oap->motion_type = kMTLineWise; setpcmark(); @@ -3683,11 +3677,12 @@ static void nv_scroll(cmdarg_T *cap) } } else { if (cap->cmdchar == 'M') { + int used = 0; // Don't count filler lines above the window. used -= win_get_fill(curwin, curwin->w_topline) - curwin->w_topfill; validate_botline(curwin); // make sure w_empty_rows is valid - half = (curwin->w_height_inner - curwin->w_empty_rows + 1) / 2; + int half = (curwin->w_height_inner - curwin->w_empty_rows + 1) / 2; for (n = 0; curwin->w_topline + n < curbuf->b_ml.ml_line_count; n++) { // Count half the number of filler lines to be "below this // line" and half to be "above the next line". @@ -4115,7 +4110,6 @@ static void nv_bracket_block(cmdarg_T *cap, const pos_T *old_pos) pos_T prev_pos; long n; int findc; - int c; if (cap->nchar == '*') { cap->nchar = '/'; @@ -4155,6 +4149,7 @@ static void nv_bracket_block(cmdarg_T *cap, const pos_T *old_pos) // Try finding the '{' or '}' we want to be at. // Also repeat for the given count. if (cap->nchar == 'm' || cap->nchar == 'M') { + int c; // norm is true for "]M" and "[m" int norm = ((findc == '{') == (cap->nchar == 'm')); @@ -4361,7 +4356,6 @@ static void nv_brackets(cmdarg_T *cap) /// Handle Normal mode "%" command. static void nv_percent(cmdarg_T *cap) { - pos_T *pos; linenr_T lnum = curwin->w_cursor.lnum; cap->oap->inclusive = true; @@ -4391,6 +4385,7 @@ static void nv_percent(cmdarg_T *cap) beginline(BL_SOL | BL_FIX); } } else { // "%" : go to matching paren + pos_T *pos; cap->oap->motion_type = kMTCharWise; cap->oap->use_reg_one = true; if ((pos = findmatch(cap->oap, NUL)) == NULL) { @@ -6046,9 +6041,8 @@ static void adjust_for_sel(cmdarg_T *cap) /// @return true when backed up to the previous line. bool unadjust_for_sel(void) { - pos_T *pp; - if (*p_sel == 'e' && !equalpos(VIsual, curwin->w_cursor)) { + pos_T *pp; if (lt(VIsual, curwin->w_cursor)) { pp = &curwin->w_cursor; } else { @@ -6460,7 +6454,6 @@ static void nv_put(cmdarg_T *cap) /// @param fix_indent true for "[p", "[P", "]p" and "]P". static void nv_put_opt(cmdarg_T *cap, bool fix_indent) { - int regname = 0; yankreg_T *savereg = NULL; bool empty = false; bool was_visual = false; @@ -6506,7 +6499,7 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent) // Need to save and restore the registers that the delete // overwrites if the old contents is being put. was_visual = true; - regname = cap->oap->regname; + int regname = cap->oap->regname; bool keep_registers = cap->cmdchar == 'P'; // '+' and '*' could be the same selection bool clipoverwrite = (regname == '+' || regname == '*') && (cb_flags & CB_UNNAMEDMASK); diff --git a/src/nvim/option.c b/src/nvim/option.c index 6c9fd275fa..26466c2869 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -4850,10 +4850,9 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, char *fuzzystr, int *numM // loop == 0: count the number of matching options // loop == 1: copy the matching options into allocated memory for (int loop = 0; loop <= 1; loop++) { - int match; regmatch->rm_ic = ic; if (xp->xp_context != EXPAND_BOOL_SETTINGS) { - for (match = 0; match < (int)ARRAY_SIZE(names); + for (int match = 0; match < (int)ARRAY_SIZE(names); match++) { if (match_str(names[match], regmatch, *matches, count, (loop == 0), fuzzy, fuzzystr, fuzmatch)) { diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 7efbeadb2f..5f8514b1a6 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -330,7 +330,6 @@ void set_string_option_direct(const char *name, int opt_idx, const char *val, in int set_sid) { char *s; - char **varp; int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0; int idx = opt_idx; @@ -353,7 +352,7 @@ void set_string_option_direct(const char *name, int opt_idx, const char *val, in s = xstrdup(val); { - varp = (char **)get_varp_scope(opt, both ? OPT_LOCAL : opt_flags); + char **varp = (char **)get_varp_scope(opt, both ? OPT_LOCAL : opt_flags); if ((opt_flags & OPT_FREE) && (opt->flags & P_ALLOCED)) { free_string_option(*varp); } diff --git a/src/nvim/plines.c b/src/nvim/plines.c index 5469d94800..a3e5640b18 100644 --- a/src/nvim/plines.c +++ b/src/nvim/plines.c @@ -356,14 +356,9 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp) char *s = cts->cts_ptr; colnr_T vcol = cts->cts_vcol; - colnr_T col2; colnr_T col_adj = 0; // vcol + screen size of tab - colnr_T colmax; - int added; int mb_added = 0; int numberextra; - char *ps; - int n; cts->cts_cur_text_width = 0; @@ -397,12 +392,12 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp) // Count all characters from first non-blank after a blank up to next // non-blank after a blank. numberextra = win_col_off(wp); - col2 = vcol; - colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj); + colnr_T col2 = vcol; + colnr_T colmax = (colnr_T)(wp->w_width_inner - numberextra - col_adj); if (vcol >= colmax) { colmax += col_adj; - n = colmax + win_col_off2(wp); + int n = colmax + win_col_off2(wp); if (n > 0) { colmax += (((vcol - colmax) / n) + 1) * n - col_adj; @@ -410,7 +405,7 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp) } for (;;) { - ps = s; + char *ps = s; MB_PTR_ADV(s); c = (uint8_t)(*s); @@ -439,7 +434,7 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp) // string at start of line. // Set *headp to the size of what we add. // Do not use 'showbreak' at the NUL after the text. - added = 0; + int added = 0; char *const sbr = c == NUL ? empty_option : get_showbreak_value(wp); if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && vcol != 0) { colnr_T sbrlen = 0; diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index b071e10cf9..70e1e00623 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -276,10 +276,8 @@ static void source_callback(char *fname, void *cookie) /// return FAIL when no file could be sourced, OK otherwise. int do_in_path(char *path, char *name, int flags, DoInRuntimepathCB callback, void *cookie) { - char *tail; int num_files; char **files; - int i; bool did_one = false; // Make a copy of 'runtimepath'. Invoking the callback may change the @@ -287,6 +285,8 @@ int do_in_path(char *path, char *name, int flags, DoInRuntimepathCB callback, vo char *rtp_copy = xstrdup(path); char *buf = xmallocz(MAXPATHL); { + char *tail; + int i; if (p_verbose > 10 && name != NULL) { verbose_enter(); smsg(_("Searching for \"%s\" in \"%s\""), name, path); @@ -2329,7 +2329,6 @@ char *getsourceline(int c, void *cookie, int indent, bool do_concat) { struct source_cookie *sp = (struct source_cookie *)cookie; char *line; - char *p; // If breakpoints have been added/deleted need to check for it. if (sp->dbg_tick < debug_tick) { @@ -2359,6 +2358,7 @@ char *getsourceline(int c, void *cookie, int indent, bool do_concat) // Only concatenate lines starting with a \ when 'cpoptions' doesn't // contain the 'C' flag. if (line != NULL && do_concat && (vim_strchr(p_cpo, CPO_CONCAT) == NULL)) { + char *p; // compensate for the one line read-ahead sp->sourcing_lnum--; diff --git a/src/nvim/sign.c b/src/nvim/sign.c index a288fa2e9d..d555b8bf4a 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -153,11 +153,10 @@ static int sign_group_get_next_signid(buf_T *buf, const char *groupname) int id = 1; signgroup_T *group = NULL; sign_entry_T *sign; - hashitem_T *hi; int found = false; if (groupname != NULL) { - hi = hash_find(&sg_table, (char *)groupname); + hashitem_T *hi = hash_find(&sg_table, (char *)groupname); if (HASHITEM_EMPTY(hi)) { return id; } @@ -1198,7 +1197,6 @@ static linenr_T sign_jump(int sign_id, char *sign_group, buf_T *buf) /// ":sign define {name} ..." command static void sign_define_cmd(char *sign_name, char *cmdline) { - char *arg; char *p = cmdline; char *icon = NULL; char *text = NULL; @@ -1210,7 +1208,7 @@ static void sign_define_cmd(char *sign_name, char *cmdline) // set values for a defined sign. for (;;) { - arg = skipwhite(p); + char *arg = skipwhite(p); if (*arg == NUL) { break; } @@ -1585,7 +1583,6 @@ static void sign_getinfo(sign_T *sp, dict_T *retdict) static void sign_getlist(const char *name, list_T *retlist) { sign_T *sp = first_sign; - dict_T *dict; if (name != NULL) { sp = sign_find((char *)name, NULL); @@ -1595,7 +1592,7 @@ static void sign_getlist(const char *name, list_T *retlist) } for (; sp != NULL && !got_int; sp = sp->sn_next) { - dict = tv_dict_alloc(); + dict_T *dict = tv_dict_alloc(); tv_list_append_dict(retlist, dict); sign_getinfo(sp, dict); @@ -1610,11 +1607,10 @@ list_T *get_buffer_signs(buf_T *buf) FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { sign_entry_T *sign; - dict_T *d; list_T *const l = tv_list_alloc(kListLenMayKnow); FOR_ALL_SIGNS_IN_BUF(buf, sign) { - d = sign_get_info(sign); + dict_T *d = sign_get_info(sign); tv_list_append_dict(l, d); } return l; @@ -2055,7 +2051,6 @@ void f_sign_getdefined(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) void f_sign_getplaced(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { buf_T *buf = NULL; - dict_T *dict; dictitem_T *di; linenr_T lnum = 0; int sign_id = 0; @@ -2072,6 +2067,7 @@ void f_sign_getplaced(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } if (argvars[1].v_type != VAR_UNKNOWN) { + dict_T *dict; if (argvars[1].v_type != VAR_DICT || ((dict = argvars[1].vval.v_dict) == NULL)) { emsg(_(e_dictreq)); @@ -2327,8 +2323,6 @@ static void sign_undefine_multiple(list_T *l, list_T *retlist) /// "sign_undefine()" function void f_sign_undefine(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - const char *name; - if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_UNKNOWN) { // Undefine multiple signs tv_list_alloc_ret(rettv, kListLenMayKnow); @@ -2345,7 +2339,7 @@ void f_sign_undefine(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = 0; } else { // Free only the specified sign - name = tv_get_string_chk(&argvars[0]); + const char *name = tv_get_string_chk(&argvars[0]); if (name == NULL) { return; } diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c index c5efe6e94b..66829c60c9 100644 --- a/src/nvim/spellsuggest.c +++ b/src/nvim/spellsuggest.c @@ -271,7 +271,6 @@ static bool can_be_compound(trystate_T *sp, slang_T *slang, char_u *compflags, i /// @param split word was split, less bonus static int score_wordcount_adj(slang_T *slang, int score, char *word, bool split) { - wordcount_T *wc; int bonus; int newscore; @@ -280,7 +279,7 @@ static int score_wordcount_adj(slang_T *slang, int score, char *word, bool split return score; } - wc = HI2WC(hi); + wordcount_T *wc = HI2WC(hi); if (wc->wc_count < SCORE_THRES2) { bonus = SCORE_COMMON1; } else if (wc->wc_count < SCORE_THRES3) { @@ -306,20 +305,17 @@ static int badword_captype(char *word, char *end) FUNC_ATTR_NONNULL_ALL { int flags = captype(word, end); - int c; - int l, u; - bool first; - char *p; if (!(flags & WF_KEEPCAP)) { return flags; } // Count the number of UPPER and lower case letters. - l = u = 0; - first = false; - for (p = word; p < end; MB_PTR_ADV(p)) { - c = utf_ptr2char(p); + int l= 0; + int u= 0; + bool first = false; + for (char *p = word; p < end; MB_PTR_ADV(p)) { + int c = utf_ptr2char(p); if (SPELL_ISUPPER(c)) { u++; if (p == word) { @@ -355,9 +351,8 @@ static int bytes2offset(char **pp) { char_u *p = (char_u *)(*pp); int nr; - int c; - c = *p++; + int c = *p++; if ((c & 0x80) == 0x00) { // 1 byte nr = c - 1; } else if ((c & 0xc0) == 0x80) { // 2 bytes @@ -392,18 +387,16 @@ static int sps_limit = 9999; ///< max nr of suggestions given /// Sets "sps_flags" and "sps_limit". int spell_check_sps(void) { - char *p; char *s; char buf[MAXPATHL]; - int f; sps_flags = 0; sps_limit = 9999; - for (p = p_sps; *p != NUL;) { + for (char *p = p_sps; *p != NUL;) { copy_option_part(&p, buf, MAXPATHL, ","); - f = 0; + int f = 0; if (ascii_isdigit(*buf)) { s = buf; sps_limit = getdigits_int(&s, true, 0); @@ -451,11 +444,9 @@ void spell_suggest(int count) pos_T prev_cursor = curwin->w_cursor; char wcopy[MAXWLEN + 2]; char *p; - int c; suginfo_T sug; suggest_T *stp; int mouse_used; - int need_cap; int limit; int selected = count; int badlen = 0; @@ -519,7 +510,7 @@ void spell_suggest(int count) // Get the word and its length. // Figure out if the word should be capitalised. - need_cap = check_need_cap(curwin->w_cursor.lnum, curwin->w_cursor.col); + int need_cap = check_need_cap(curwin->w_cursor.lnum, curwin->w_cursor.col); // Make a copy of current line since autocommands may free the line. line = xstrdup(get_cursor_line_ptr()); @@ -651,7 +642,7 @@ void spell_suggest(int count) // Replace the word. p = xmalloc(strlen(line) - (size_t)stp->st_orglen + (size_t)stp->st_wordlen + 1); - c = (int)(sug.su_badptr - line); + int c = (int)(sug.su_badptr - line); memmove(p, line, (size_t)c); STRCPY(p + c, stp->st_word); STRCAT(p, sug.su_badptr + stp->st_orglen); @@ -685,7 +676,6 @@ void spell_suggest(int count) void spell_suggest_list(garray_T *gap, char *word, int maxcount, bool need_cap, bool interactive) { suginfo_T sug; - suggest_T *stp; char *wcopy; spell_find_suggest(word, 0, &sug, maxcount, false, need_cap, interactive); @@ -694,7 +684,7 @@ void spell_suggest_list(garray_T *gap, char *word, int maxcount, bool need_cap, ga_init(gap, sizeof(char *), sug.su_ga.ga_len + 1); ga_grow(gap, sug.su_ga.ga_len); for (int i = 0; i < sug.su_ga.ga_len; i++) { - stp = &SUG(sug.su_ga, i); + suggest_T *stp = &SUG(sug.su_ga, i); // The suggested word may replace only part of "word", add the not // replaced part. @@ -721,11 +711,8 @@ static void spell_find_suggest(char *badptr, int badlen, suginfo_T *su, int maxc { hlf_T attr = HLF_COUNT; char buf[MAXPATHL]; - char *p; bool do_combine = false; - char *sps_copy; static bool expr_busy = false; - int c; langp_T *lp; bool did_intern = false; @@ -790,7 +777,7 @@ static void spell_find_suggest(char *badptr, int badlen, suginfo_T *su, int maxc // If the word is not capitalised and spell_check() doesn't consider the // word to be bad then it might need to be capitalised. Add a suggestion // for that. - c = utf_ptr2char(su->su_badptr); + int c = utf_ptr2char(su->su_badptr); if (!SPELL_ISUPPER(c) && attr == HLF_COUNT) { make_case_word(su->su_badword, buf, WF_ONECAP); add_suggestion(su, &su->su_ga, buf, su->su_badlen, SCORE_ICASE, @@ -803,10 +790,10 @@ static void spell_find_suggest(char *badptr, int badlen, suginfo_T *su, int maxc } // Make a copy of 'spellsuggest', because the expression may change it. - sps_copy = xstrdup(p_sps); + char *sps_copy = xstrdup(p_sps); // Loop over the items in 'spellsuggest'. - for (p = sps_copy; *p != NUL;) { + for (char *p = sps_copy; *p != NUL;) { copy_option_part(&p, buf, MAXPATHL, ","); if (strncmp(buf, "expr:", 5) == 0) { @@ -845,7 +832,6 @@ static void spell_find_suggest(char *badptr, int badlen, suginfo_T *su, int maxc /// Find suggestions by evaluating expression "expr". static void spell_suggest_expr(suginfo_T *su, char *expr) { - int score; const char *p; // The work is split up in a few parts to avoid having to export @@ -857,7 +843,7 @@ static void spell_suggest_expr(suginfo_T *su, char *expr) TV_LIST_ITER(list, li, { if (TV_LIST_ITEM_TV(li)->v_type == VAR_LIST) { // Get the word and the score from the items. - score = get_spellword(TV_LIST_ITEM_TV(li)->vval.v_list, &p); + int score = get_spellword(TV_LIST_ITEM_TV(li)->vval.v_list, &p); if (score >= 0 && score <= su->su_maxscore) { add_suggestion(su, &su->su_ga, p, su->su_badlen, score, 0, true, su->su_sallang, false); @@ -875,14 +861,12 @@ static void spell_suggest_expr(suginfo_T *su, char *expr) /// Find suggestions in file "fname". Used for "file:" in 'spellsuggest'. static void spell_suggest_file(suginfo_T *su, char *fname) { - FILE *fd; char line[MAXWLEN * 2]; - char *p; int len; char cword[MAXWLEN]; // Open the file. - fd = os_fopen(fname, "r"); + FILE *fd = os_fopen(fname, "r"); if (fd == NULL) { semsg(_(e_notopen), fname); return; @@ -892,7 +876,7 @@ static void spell_suggest_file(suginfo_T *su, char *fname) while (!vim_fgets(line, MAXWLEN * 2, fd) && !got_int) { line_breakcheck(); - p = vim_strchr(line, '/'); + char *p = vim_strchr(line, '/'); if (p == NULL) { continue; // No Tab found, just skip the line. } @@ -1013,7 +997,6 @@ static void spell_find_cleanup(suginfo_T *su) /// Try finding suggestions by recognizing specific situations. static void suggest_try_special(suginfo_T *su) { - char c; char word[MAXWLEN]; // Recognize a word that is repeated: "the the". @@ -1023,7 +1006,7 @@ static void suggest_try_special(suginfo_T *su) if (strlen(p) == len && strncmp(su->su_fbadword, p, len) == 0) { // Include badflags: if the badword is onecap or allcap // use that for the goodword too: "The the" -> "The". - c = su->su_fbadword[len]; + char c = su->su_fbadword[len]; su->su_fbadword[len] = NUL; make_case_word(su->su_fbadword, word, su->su_badflags); su->su_fbadword[len] = c; @@ -1084,16 +1067,14 @@ static void prof_report(char *name) static void suggest_try_change(suginfo_T *su) { char fword[MAXWLEN]; // copy of the bad word, case-folded - int n; - char *p; langp_T *lp; // We make a copy of the case-folded bad word, so that we can modify it // to find matches (esp. REP items). Append some more text, changing // chars after the bad word may help. STRCPY(fword, su->su_fbadword); - n = (int)strlen(fword); - p = su->su_badptr + su->su_badlen; + int n = (int)strlen(fword); + char *p = su->su_badptr + su->su_badlen; (void)spell_casefold(curwin, p, (int)strlen(p), fword + n, MAXWLEN - n); // Make sure the resulting text is not longer than the original text. @@ -1165,12 +1146,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // when going deeper but not when coming // back. char_u compflags[MAXWLEN]; // compound flags, one for each word - trystate_T *sp; int newscore; int score; char_u *byts, *fbyts, *pbyts; idx_T *idxs, *fidxs, *pidxs; - int depth; int c, c2, c3; int n = 0; int flags; @@ -1195,8 +1174,8 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // "tword[]" contains the word collected from nodes in the tree. // "fword[]" the word we are trying to match with (initially the bad // word). - depth = 0; - sp = &stack[0]; + int depth = 0; + trystate_T *sp = &stack[0]; CLEAR_POINTER(sp); // -V1068 sp->ts_curi = 1; @@ -2387,7 +2366,6 @@ static void go_deeper(trystate_T *stack, int depth, int score_add) static void find_keepcap_word(slang_T *slang, char *fword, char *kword) { char uword[MAXWLEN]; // "fword" in upper-case - int depth; idx_T tryidx; // The following arrays are used at each depth in the tree. @@ -2418,7 +2396,7 @@ static void find_keepcap_word(slang_T *slang, char *fword, char *kword) // Each character needs to be tried both case-folded and upper-case. // All this gets very complicated if we keep in mind that changing case // may change the byte length of a multi-byte character... - depth = 0; + int depth = 0; arridx[0] = 0; round[0] = 0; fwordidx[0] = 0; @@ -2656,16 +2634,14 @@ static void score_combine(suginfo_T *su) /// @param badsound sound-folded badword static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char *badsound) { - char *p; char *pbad; char *pgood; char badsound2[MAXWLEN]; char fword[MAXWLEN]; char goodsound[MAXWLEN]; char goodword[MAXWLEN]; - int lendiff; - lendiff = su->su_badlen - stp->st_orglen; + int lendiff = su->su_badlen - stp->st_orglen; if (lendiff >= 0) { pbad = badsound; } else { @@ -2678,7 +2654,7 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char *ba // space. if (ascii_iswhite(su->su_badptr[su->su_badlen]) && *skiptowhite(stp->st_word) == NUL) { - for (p = fword; *(p = skiptowhite(p)) != NUL;) { + for (char *p = fword; *(p = skiptowhite(p)) != NUL;) { STRMOVE(p, p + 1); } } @@ -2801,9 +2777,6 @@ static void suggest_try_soundalike_finish(void) static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T *lp) { slang_T *slang = lp->lp_slang; // language for sound folding - int sfwordnr; - char *nrline; - int orgnr; char theword[MAXWLEN]; int i; int wlen; @@ -2813,8 +2786,6 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T int wordcount; int wc; int goodscore; - hash_T hash; - hashitem_T *hi; sftword_T *sft; int bc, gc; int limit; @@ -2823,10 +2794,9 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T // times with different scores. Since the following is quite slow only do // the words that have a better score than before. Use a hashtable to // remember the words that have been done. - hash = hash_hash(goodword); + hash_T hash = hash_hash(goodword); const size_t goodword_len = strlen(goodword); - hi = hash_lookup(&slang->sl_sounddone, (const char *)goodword, goodword_len, - hash); + hashitem_T *hi = hash_lookup(&slang->sl_sounddone, (const char *)goodword, goodword_len, hash); if (HASHITEM_EMPTY(hi)) { sft = xmalloc(offsetof(sftword_T, sft_word) + goodword_len + 1); sft->sft_score = (int16_t)score; @@ -2841,15 +2811,15 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T } // Find the word nr in the soundfold tree. - sfwordnr = soundfold_find(slang, goodword); + int sfwordnr = soundfold_find(slang, goodword); if (sfwordnr < 0) { internal_error("add_sound_suggest()"); return; } // Go over the list of good words that produce this soundfold word - nrline = ml_get_buf(slang->sl_sugbuf, (linenr_T)sfwordnr + 1, false); - orgnr = 0; + char *nrline = ml_get_buf(slang->sl_sugbuf, (linenr_T)sfwordnr + 1, false); + int orgnr = 0; while (*nrline != NUL) { // The wordnr was stored in a minimal nr of bytes as an offset to the // previous wordnr. @@ -2984,24 +2954,20 @@ badword: static int soundfold_find(slang_T *slang, char *word) { idx_T arridx = 0; - int len; int wlen = 0; - int c; char_u *ptr = (char_u *)word; - char_u *byts; - idx_T *idxs; int wordnr = 0; - byts = (char_u *)slang->sl_sbyts; - idxs = slang->sl_sidxs; + char_u *byts = (char_u *)slang->sl_sbyts; + idx_T *idxs = slang->sl_sidxs; for (;;) { // First byte is the number of possible bytes. - len = byts[arridx++]; + int len = byts[arridx++]; // If the first possible byte is a zero the word could end here. // If the word ends we found the word. If not skip the NUL bytes. - c = ptr[wlen]; + int c = ptr[wlen]; if (byts[arridx] == NUL) { if (c == NUL) { break; @@ -3212,19 +3178,17 @@ static void add_suggestion(suginfo_T *su, garray_T *gap, const char *goodword, i /// @param gap either su_ga or su_sga static void check_suggestions(suginfo_T *su, garray_T *gap) { - suggest_T *stp; char longword[MAXWLEN + 1]; - int len; hlf_T attr; if (gap->ga_len == 0) { return; } - stp = &SUG(*gap, 0); + suggest_T *stp = &SUG(*gap, 0); for (int i = gap->ga_len - 1; i >= 0; i--) { // Need to append what follows to check for "the the". xstrlcpy(longword, stp[i].st_word, MAXWLEN + 1); - len = stp[i].st_wordlen; + int len = stp[i].st_wordlen; xstrlcpy(longword + len, su->su_badptr + stp[i].st_orglen, (size_t)(MAXWLEN - len + 1)); attr = HLF_COUNT; @@ -3243,17 +3207,13 @@ static void check_suggestions(suginfo_T *su, garray_T *gap) /// Add a word to be banned. static void add_banned(suginfo_T *su, char *word) { - char *s; - hash_T hash; - hashitem_T *hi; - - hash = hash_hash(word); + hash_T hash = hash_hash(word); const size_t word_len = strlen(word); - hi = hash_lookup(&su->su_banned, word, word_len, hash); + hashitem_T *hi = hash_lookup(&su->su_banned, word, word_len, hash); if (!HASHITEM_EMPTY(hi)) { // already present return; } - s = xmemdupz(word, word_len); + char *s = xmemdupz(word, word_len); hash_add_item(&su->su_banned, hi, s, hash); } @@ -3273,19 +3233,19 @@ static void rescore_one(suginfo_T *su, suggest_T *stp) { slang_T *slang = stp->st_slang; char sal_badword[MAXWLEN]; - char *p; // Only rescore suggestions that have no sal score yet and do have a // language. if (slang != NULL && !GA_EMPTY(&slang->sl_sal) && !stp->st_had_bonus) { + char_u *p; if (slang == su->su_sallang) { - p = su->su_sal_badword; + p = (char_u *)su->su_sal_badword; } else { spell_soundfold(slang, su->su_fbadword, true, sal_badword); - p = sal_badword; + p = (char_u *)sal_badword; } - stp->st_altscore = stp_sal_score(stp, su, slang, p); + stp->st_altscore = stp_sal_score(stp, su, slang, (char *)p); if (stp->st_altscore == SCORE_MAXMAX) { stp->st_altscore = SCORE_BIG; } @@ -3354,9 +3314,6 @@ static int soundalike_score(char *goodstart, char *badstart) { char *goodsound = goodstart; char *badsound = badstart; - int goodlen; - int badlen; - int n; char *pl, *ps; char *pl2, *ps2; int score = 0; @@ -3389,12 +3346,12 @@ static int soundalike_score(char *goodstart, char *badstart) } } - goodlen = (int)strlen(goodsound); - badlen = (int)strlen(badsound); + int goodlen = (int)strlen(goodsound); + int badlen = (int)strlen(badsound); // Return quickly if the lengths are too different to be fixed by two // changes. - n = goodlen - badlen; + int n = goodlen - badlen; if (n < -2 || n > 2) { return SCORE_MAXMAX; } @@ -3683,25 +3640,21 @@ static int spell_edit_score_limit_w(slang_T *slang, const char *badword, const c int limit) { limitscore_T stack[10]; // allow for over 3 * 2 edits - int stackidx; - int bi, gi; int bi2, gi2; int bc, gc; - int score; int score_off; - int minscore; int round; int wbadword[MAXWLEN]; int wgoodword[MAXWLEN]; // Get the characters from the multi-byte strings and put them in an // int array for easy access. - bi = 0; + int bi = 0; for (const char *p = badword; *p != NUL;) { wbadword[bi++] = mb_cptr2char_adv(&p); } wbadword[bi++] = 0; - gi = 0; + int gi = 0; for (const char *p = goodword; *p != NUL;) { wgoodword[gi++] = mb_cptr2char_adv(&p); } @@ -3714,11 +3667,11 @@ static int spell_edit_score_limit_w(slang_T *slang, const char *badword, const c // pushed unto a stack and tried later, some are tried right away. At the // end of the word the score for one alternative is known. The lowest // possible score is stored in "minscore". - stackidx = 0; + int stackidx = 0; bi = 0; gi = 0; - score = 0; - minscore = limit + 1; + int score = 0; + int minscore = limit + 1; for (;;) { // Skip over an equal part, score remains the same. diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 42618e8924..4fecbeebc3 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -979,27 +979,22 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char /// window. static int add_llist_tags(char *tag, int num_matches, char **matches) { - list_T *list; char tag_name[128 + 1]; - char *fname; - char *cmd; int i; char *p; tagptrs_T tagp; - fname = xmalloc(MAXPATHL + 1); - cmd = xmalloc(CMDBUFFSIZE + 1); - list = tv_list_alloc(0); + char *fname = xmalloc(MAXPATHL + 1); + char *cmd = xmalloc(CMDBUFFSIZE + 1); + list_T *list = tv_list_alloc(0); for (i = 0; i < num_matches; i++) { - int len, cmd_len; - long lnum; dict_T *dict; parse_match(matches[i], &tagp); // Save the tag name - len = (int)(tagp.tagname_end - tagp.tagname); + int len = (int)(tagp.tagname_end - tagp.tagname); if (len > 128) { len = 128; } @@ -1016,7 +1011,7 @@ static int add_llist_tags(char *tag, int num_matches, char **matches) // Get the line number or the search pattern used to locate // the tag. - lnum = 0; + long lnum = 0; if (isdigit((uint8_t)(*tagp.command))) { // Line number is used to locate the tag lnum = atol(tagp.command); @@ -1065,7 +1060,7 @@ static int add_llist_tags(char *tag, int num_matches, char **matches) STRCAT(cmd, "\\V"); len += 2; - cmd_len = (int)(cmd_end - cmd_start + 1); + int cmd_len = (int)(cmd_end - cmd_start + 1); if (cmd_len > (CMDBUFFSIZE - 5)) { cmd_len = CMDBUFFSIZE - 5; } @@ -1162,10 +1157,8 @@ void do_tags(exarg_T *eap) // Make sure case is folded to uppercase in comparison (like for 'sort -f') static int tag_strnicmp(char *s1, char *s2, size_t len) { - int i; - while (len > 0) { - i = TOUPPER_ASC((uint8_t)(*s1)) - TOUPPER_ASC((uint8_t)(*s2)); + int i = TOUPPER_ASC((uint8_t)(*s1)) - TOUPPER_ASC((uint8_t)(*s2)); if (i != 0) { return i; // this character different } @@ -1733,14 +1726,13 @@ static tagmatch_status_T findtags_parse_line(findtags_state_T *st, tagptrs_T *ta tagsearch_info_T *sinfo_p) { int status; - int i; - int cmplen; - int tagcmp; // Figure out where the different strings are in this line. // For "normal" tags: Do a quick check if the tag matches. // This speeds up tag searching a lot! if (st->orgpat->headlen) { + int i; + int tagcmp; CLEAR_FIELD(*tagpp); tagpp->tagname = st->lbuf; tagpp->tagname_end = vim_strchr(st->lbuf, TAB); @@ -1751,7 +1743,7 @@ static tagmatch_status_T findtags_parse_line(findtags_state_T *st, tagptrs_T *ta // Skip this line if the length of the tag is different and // there is no regexp, or the tag is too short. - cmplen = (int)(tagpp->tagname_end - tagpp->tagname); + int cmplen = (int)(tagpp->tagname_end - tagpp->tagname); if (p_tl != 0 && cmplen > p_tl) { // adjust for 'taglength' cmplen = (int)p_tl; } @@ -2719,7 +2711,7 @@ static int parse_match(char *lbuf, tagptrs_T *tagp) { int retval; char *p; - char *pc, *pt; + char *pt; tagp->tag_fname = lbuf + 1; lbuf += strlen(tagp->tag_fname) + 2; @@ -2739,6 +2731,7 @@ static int parse_match(char *lbuf, tagptrs_T *tagp) // Try to find a kind field: "kind:" or just "" p = tagp->command; if (find_extra(&p) == OK) { + char *pc; tagp->command_end = p; if (p > tagp->command && p[-1] == '|') { tagp->command_end = p - 1; // drop trailing bar @@ -2995,7 +2988,6 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, int keep_help) retval = OK; } else { int found = 1; - char cc; // try again, ignore case now p_ic = true; @@ -3004,7 +2996,7 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, int keep_help) // Failed to find pattern, take a guess: "^func (" found = 2; (void)test_for_static(&tagp); - cc = *tagp.tagname_end; + char cc = *tagp.tagname_end; *tagp.tagname_end = NUL; snprintf(pbuf, LSIZE, "^%s\\s\\*(", tagp.tagname); if (!do_search(NULL, '/', '/', pbuf, (long)1, search_options, NULL)) { @@ -3155,10 +3147,10 @@ static char *expand_tag_fname(char *fname, char *const tag_fname, const bool exp /// file. static int test_for_current(char *fname, char *fname_end, char *tag_fname, char *buf_ffname) { - char c; int retval = false; if (buf_ffname != NULL) { // if the buffer has a name + char c; { c = *fname_end; *fname_end = NUL; @@ -3225,7 +3217,6 @@ static void tagstack_clear_entry(taggy_T *item) /// @param tagnames expand tag names int expand_tags(int tagnames, char *pat, int *num_file, char ***file) { - int i; int extra_flag; char *name_buf; size_t name_buf_size = 100; @@ -3251,7 +3242,7 @@ int expand_tags(int tagnames, char *pat, int *num_file, char ***file) if (ret == OK && !tagnames) { // Reorganize the tags for display and matching as strings of: // "\0\0\0" - for (i = 0; i < *num_file; i++) { + for (int i = 0; i < *num_file; i++) { size_t len; parse_match((*file)[i], &t_p); @@ -3327,7 +3318,6 @@ int get_tags(list_T *list, char *pat, char *buf_fname) char *full_fname; dict_T *dict; tagptrs_T tp; - bool is_static; ret = find_tags(pat, &num_matches, &matches, TAG_REGEXP | TAG_NOIC, MAXCOL, buf_fname); @@ -3342,7 +3332,7 @@ int get_tags(list_T *list, char *pat, char *buf_fname) (void)parse_result; assert(parse_result == OK); - is_static = test_for_static(&tp); + bool is_static = test_for_static(&tp); // Skip pseudo-tag lines. if (strncmp(tp.tagname, "!_TAG_", 6) == 0) { @@ -3377,7 +3367,7 @@ int get_tags(list_T *list, char *pat, char *buf_fname) // skip "file:" (static tag) p += 4; } else if (!ascii_iswhite(*p)) { - char *s, *n; + char *n; int len; // Add extra field as a dict entry. Fields are @@ -3388,7 +3378,7 @@ int get_tags(list_T *list, char *pat, char *buf_fname) } len = (int)(p - n); if (*p == ':' && len > 0) { - s = ++p; + char *s = ++p; while (*p != NUL && (uint8_t)(*p) >= ' ') { p++; } @@ -3447,7 +3437,6 @@ void get_tagstack(win_T *wp, dict_T *retdict) { list_T *l; int i; - dict_T *d; tv_dict_add_nr(retdict, S_LEN("length"), wp->w_tagstacklen); tv_dict_add_nr(retdict, S_LEN("curidx"), wp->w_tagstackidx + 1); @@ -3455,7 +3444,7 @@ void get_tagstack(win_T *wp, dict_T *retdict) tv_dict_add_list(retdict, S_LEN("items"), l); for (i = 0; i < wp->w_tagstacklen; i++) { - d = tv_dict_alloc(); + dict_T *d = tv_dict_alloc(); tv_list_append_dict(l, d); get_tag_details(&wp->w_tagstack[i], d); } diff --git a/src/nvim/textobject.c b/src/nvim/textobject.c index 8e786c271c..37f893ecec 100644 --- a/src/nvim/textobject.c +++ b/src/nvim/textobject.c @@ -176,7 +176,6 @@ found: bool findpar(bool *pincl, int dir, long count, int what, bool both) { linenr_T curr; - bool did_skip; // true after separating lines have been skipped bool first; // true on first line linenr_T fold_first; // first line of a closed fold linenr_T fold_last; // last line of a closed fold @@ -186,7 +185,7 @@ bool findpar(bool *pincl, int dir, long count, int what, bool both) curr = curwin->w_cursor.lnum; while (count--) { - did_skip = false; + bool did_skip = false; // true after separating lines have been skipped for (first = true;; first = false) { if (*ml_get(curr) != NUL) { did_skip = true; @@ -324,10 +323,6 @@ static int cls(void) /// @param bigword "W", "E" or "B" int fwd_word(long count, bool bigword, bool eol) { - int sclass; // starting class - int i; - int last_line; - curwin->w_cursor.coladd = 0; cls_bigword = bigword; while (--count >= 0) { @@ -336,12 +331,12 @@ int fwd_word(long count, bool bigword, bool eol) if (hasFolding(curwin->w_cursor.lnum, NULL, &curwin->w_cursor.lnum)) { coladvance(MAXCOL); } - sclass = cls(); + int sclass = cls(); // starting class // We always move at least one character, unless on the last // character in the buffer. - last_line = (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count); - i = inc_cursor(); + int last_line = (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count); + int i = inc_cursor(); if (i == -1 || (i >= 1 && last_line)) { // started at last char in file return FAIL; } @@ -493,13 +488,11 @@ finished: /// @return FAIL if start of the file was reached. int bckend_word(long count, bool bigword, bool eol) { - int sclass; // starting class - int i; - curwin->w_cursor.coladd = 0; cls_bigword = bigword; while (--count >= 0) { - sclass = cls(); + int i; + int sclass = cls(); // starting class if ((i = dec_cursor()) == -1) { return FAIL; } @@ -562,10 +555,8 @@ static void back_in_line(void) static void find_first_blank(pos_T *posp) { - int c; - while (decl(posp) != -1) { - c = gchar_pos(posp); + int c = gchar_pos(posp); if (!ascii_iswhite(c)) { incl(posp); break; @@ -598,7 +589,6 @@ static void findsent_forward(long count, bool at_start_sent) int current_word(oparg_T *oap, long count, bool include, bool bigword) { pos_T start_pos; - pos_T pos; bool inclusive = true; int include_white = false; @@ -703,7 +693,7 @@ int current_word(oparg_T *oap, long count, bool include, bool bigword) // word). Also when "2daw" deletes "word." at the end of the line // (cursor is at start of next line). // But don't delete white space at start of line (indent). - pos = curwin->w_cursor; // save cursor position + pos_T pos = curwin->w_cursor; // save cursor position curwin->w_cursor = start_pos; if (oneleft() == OK) { back_in_line(); @@ -1042,7 +1032,6 @@ static bool in_html_tag(bool end_tag) { char *line = get_cursor_line_ptr(); char *p; - int c; int lc = NUL; pos_T pos; @@ -1078,7 +1067,7 @@ static bool in_html_tag(bool end_tag) if (inc(&pos) < 0) { return false; } - c = (uint8_t)(*ml_get_pos(&pos)); + int c = (uint8_t)(*ml_get_pos(&pos)); if (c == '>') { break; } @@ -1443,10 +1432,8 @@ extend: /// @return column number of "quotechar" or -1 when not found. static int find_next_quote(char *line, int col, int quotechar, char *escape) { - int c; - for (;;) { - c = (uint8_t)line[col]; + int c = (uint8_t)line[col]; if (c == NUL) { return -1; } else if (escape != NULL && vim_strchr(escape, c)) { @@ -1471,12 +1458,10 @@ static int find_next_quote(char *line, int col, int quotechar, char *escape) /// @return the found column or zero. static int find_prev_quote(char *line, int col_start, int quotechar, char *escape) { - int n; - while (col_start > 0) { col_start--; col_start -= utf_head_off(line, line + col_start); - n = 0; + int n = 0; if (escape != NULL) { while (col_start - n > 0 && vim_strchr(escape, (uint8_t)line[col_start - n - 1]) != NULL) { -- cgit From 47638706a37534ae9bc7ac4c57ddb9fb2b44fef0 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 12 Feb 2023 17:41:54 +0100 Subject: build: treat clang-tidy warnings as errors (#22238) --- src/nvim/eval.c | 2 +- src/nvim/ops.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index fb69734457..1a10f8aebc 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -3410,7 +3410,7 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose) if (n1 >= len || n2 < 0 || n1 > n2) { v = NULL; } else { - v = xmemdupz(s + n1, (size_t)(n2 - n1 + 1)); + v = xmemdupz(s + n1, (size_t)n2 - (size_t)n1 + 1); } } else { // The resulting variable is a string of a single diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 0fb8a8004b..e89844098b 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -923,7 +923,7 @@ int do_record(int c) dict_T *dict = get_v_event(&save_v_event); // The recorded text contents. - char *p = (char *)get_recorded(); + char *p = get_recorded(); if (p != NULL) { // Remove escaping for K_SPECIAL in multi-byte chars. vim_unescape_ks(p); -- cgit From 5f72ab77bff1f1224be5cbbf9423bdddbc25635c Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 12 Feb 2023 18:48:49 +0100 Subject: refactor: reduce scope of locals as per the style guide 3 (#22221) refactor: reduce scope of locals as per the style guide --- src/nvim/debugger.c | 3 +-- src/nvim/diff.c | 3 +-- src/nvim/drawline.c | 10 +++----- src/nvim/eval.c | 22 +++++++---------- src/nvim/ex_eval.c | 3 +-- src/nvim/getchar.c | 12 ++++------ src/nvim/grid.c | 6 ++--- src/nvim/help.c | 35 +++++++++------------------ src/nvim/keycodes.c | 2 +- src/nvim/mark.c | 56 ++++++++++++++++--------------------------- src/nvim/mbyte.c | 10 +++----- src/nvim/menu.c | 17 ++++--------- src/nvim/runtime.c | 6 ++--- src/nvim/screen.c | 30 +++++++++-------------- src/nvim/search.c | 64 +++++++++++++++++-------------------------------- src/nvim/spellfile.c | 21 ++++++---------- src/nvim/spellsuggest.c | 3 +-- src/nvim/statusline.c | 48 +++++++++++++++---------------------- src/nvim/syntax.c | 26 +++++++------------- src/nvim/tag.c | 27 +++++++-------------- src/nvim/textformat.c | 18 +++++--------- 21 files changed, 147 insertions(+), 275 deletions(-) (limited to 'src') diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c index dc58d6bf60..3c9a63f5a3 100644 --- a/src/nvim/debugger.c +++ b/src/nvim/debugger.c @@ -75,7 +75,6 @@ void do_debug(char *cmd) tasave_T typeaheadbuf; bool typeahead_saved = false; int save_ignore_script = 0; - int n; char *cmdline = NULL; char *p; char *tail = NULL; @@ -146,7 +145,7 @@ void do_debug(char *cmd) } // don't debug any function call, e.g. from an expression mapping - n = debug_break_level; + int n = debug_break_level; debug_break_level = -1; xfree(cmdline); diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 3bdc965146..c5b28822d0 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -2652,8 +2652,7 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp) bool added = true; linenr_T off = lnum - dp->df_lnum[idx]; - int i; - for (i = 0; i < DB_COUNT; i++) { + for (int i = 0; i < DB_COUNT; i++) { if ((curtab->tp_diffbuf[i] != NULL) && (i != idx)) { // Skip lines that are not in the other change (filler lines). if (off >= dp->df_count[i]) { diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 6de920b544..e205850314 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1725,9 +1725,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // At start of the line we can have a composing char. // Draw it as a space with a composing char. if (utf_iscomposing(mb_c)) { - int i; - - for (i = MAX_MCO - 1; i > 0; i--) { + for (int i = MAX_MCO - 1; i > 0; i--) { u8cc[i] = u8cc[i - 1]; } u8cc[0] = mb_c; @@ -2102,7 +2100,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, n_extra = tab_len; } else { char *p; - int i; int saved_nextra = n_extra; if (vcol_off > 0) { @@ -2131,7 +2128,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, p[len] = NUL; xfree(p_extra_free); p_extra_free = p; - for (i = 0; i < tab_len; i++) { + for (int i = 0; i < tab_len; i++) { if (*p == NUL) { tab_len = i; break; @@ -2486,7 +2483,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, || draw_color_col || line_attr_lowprio || line_attr || diff_hlf != (hlf_T)0 || has_virttext)) { int rightmost_vcol = 0; - int i; if (wp->w_p_cuc) { rightmost_vcol = wp->w_virtcol; @@ -2494,7 +2490,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (draw_color_col) { // determine rightmost colorcolumn to possibly draw - for (i = 0; color_cols[i] >= 0; i++) { + for (int i = 0; color_cols[i] >= 0; i++) { if (rightmost_vcol < color_cols[i]) { rightmost_vcol = color_cols[i]; } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 1a10f8aebc..3ab704e250 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1949,7 +1949,6 @@ void set_context_for_expression(expand_T *xp, char *arg, cmdidx_T cmdidx) FUNC_ATTR_NONNULL_ALL { bool got_eq = false; - int c; char *p; if (cmdidx == CMD_let || cmdidx == CMD_const) { @@ -1970,7 +1969,7 @@ void set_context_for_expression(expand_T *xp, char *arg, cmdidx_T cmdidx) : EXPAND_EXPRESSION; } while ((xp->xp_pattern = strpbrk(arg, "\"'+-*/%.=!?~|&$([<>,#")) != NULL) { - c = (uint8_t)(*xp->xp_pattern); + int c = (uint8_t)(*xp->xp_pattern); if (c == '&') { c = (uint8_t)xp->xp_pattern[1]; if (c == '&') { @@ -2310,7 +2309,6 @@ int eval0(char *arg, typval_T *rettv, char **nextcmd, int evaluate) /// @return OK or FAIL. int eval1(char **arg, typval_T *rettv, int evaluate) { - bool result; typval_T var2; // Get the first variable. @@ -2319,7 +2317,7 @@ int eval1(char **arg, typval_T *rettv, int evaluate) } if ((*arg)[0] == '?') { - result = false; + bool result = false; if (evaluate) { bool error = false; @@ -2499,7 +2497,6 @@ static int eval4(char **arg, typval_T *rettv, int evaluate) char *p; exprtype_T type = EXPR_UNKNOWN; int len = 2; - bool ic; // Get the first variable. if (eval5(arg, rettv, evaluate) == FAIL) { @@ -2552,6 +2549,7 @@ static int eval4(char **arg, typval_T *rettv, int evaluate) // If there is a comparative operator, use it. if (type != EXPR_UNKNOWN) { + bool ic; // extra question mark appended: ignore case if (p[len] == '?') { ic = true; @@ -2594,7 +2592,6 @@ static int eval5(char **arg, typval_T *rettv, int evaluate) { typval_T var2; typval_T var3; - int op; varnumber_T n1, n2; float_T f1 = 0, f2 = 0; char *p; @@ -2606,7 +2603,7 @@ static int eval5(char **arg, typval_T *rettv, int evaluate) // Repeat computing, until no '+', '-' or '.' is following. for (;;) { - op = (char_u)(**arg); + int op = (char_u)(**arg); if (op != '+' && op != '-' && op != '.') { break; } @@ -3276,7 +3273,6 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose) { bool empty1 = false; bool empty2 = false; - int n1, n2 = 0; ptrdiff_t len = -1; int range = false; char *key = NULL; @@ -3373,7 +3369,8 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose) } if (evaluate) { - n1 = 0; + int n2 = 0; + int n1 = 0; if (!empty1 && rettv->v_type != VAR_DICT && !tv_is_luafunc(rettv)) { n1 = (int)tv_get_number(&var1); tv_clear(&var1); @@ -4784,8 +4781,6 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map) const char *const arg_errmsg = (map ? N_("map() argument") : N_("filter() argument")); - int save_did_emsg; - int idx = 0; // Always return the first argument, also on failure. tv_copy(&argvars[0], rettv); @@ -4815,12 +4810,13 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map) // message. Avoid a misleading error message for an empty string that // was not passed as argument. if (expr->v_type != VAR_UNKNOWN) { + int idx = 0; typval_T save_val; prepare_vimvar(VV_VAL, &save_val); // We reset "did_emsg" to be able to detect whether an error // occurred during evaluation of the expression. - save_did_emsg = did_emsg; + int save_did_emsg = did_emsg; did_emsg = false; typval_T save_key; @@ -8064,7 +8060,6 @@ repeat: /// @return an allocated string, NULL for error. char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, const char *flags) { - int sublen; regmatch_T regmatch; garray_T ga; char *zero_width = NULL; @@ -8080,6 +8075,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, const char regmatch.rm_ic = p_ic; regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); if (regmatch.regprog != NULL) { + int sublen; char *tail = str; char *end = str + strlen(str); while (vim_regexec_nl(®match, str, (colnr_T)(tail - str))) { diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 2c578564bc..1cef99297a 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -1154,7 +1154,6 @@ void do_throw(cstack_T *cstack) { int inactivate_try = false; - // // Cleanup and deactivate up to the next surrounding try conditional that // is not in its finally clause. Normally, do not deactivate the try // conditional itself, so that its ACTIVE flag can be tested below. But @@ -1162,7 +1161,7 @@ void do_throw(cstack_T *cstack) // deactivate the try conditional, too, as if the conversion had been done, // and reset the did_emsg or got_int flag, so this won't happen again at // the next surrounding try conditional. - // + #ifndef THROW_ON_ERROR_TRUE if (did_emsg && !THROW_ON_ERROR) { inactivate_try = true; diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index b54ecdb6ab..37840f8875 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -661,7 +661,6 @@ static int read_redo(bool init, bool old_redo) int c; int n; char_u buf[MB_MAXBYTES + 1]; - int i; if (init) { bp = old_redo ? old_redobuff.bh_first.b_next : redobuff.bh_first.b_next; @@ -682,7 +681,7 @@ static int read_redo(bool init, bool old_redo) } else { n = 1; } - for (i = 0;; i++) { + for (int i = 0;; i++) { if (c == K_SPECIAL) { // special key or escaped K_SPECIAL c = TO_SPECIAL(p[1], p[2]); p += 2; @@ -857,7 +856,6 @@ int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent) { char_u *s1, *s2; int addlen; - int i; int val; int nrm; @@ -947,7 +945,7 @@ int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent) } else { nrm = noremap; } - for (i = 0; i < addlen; i++) { + for (int i = 0; i < addlen; i++) { typebuf.tb_noremap[typebuf.tb_off + i + offset] = (uint8_t)((--nrm >= 0) ? val : RM_YES); } @@ -1426,7 +1424,6 @@ int vgetc(void) } else { int c2; int n; - int i; // number of characters recorded from the last vgetc() call static size_t last_vgetc_recorded_len = 0; @@ -1552,7 +1549,7 @@ int vgetc(void) if ((n = MB_BYTE2LEN_CHECK(c)) > 1) { no_mapping++; buf[0] = (char_u)c; - for (i = 1; i < n; i++) { + for (int i = 1; i < n; i++) { buf[i] = (char_u)vgetorpeek(true); if (buf[i] == K_SPECIAL) { // Must be a K_SPECIAL - KS_SPECIAL - KE_FILLER sequence, @@ -2904,13 +2901,12 @@ int fix_input_buffer(char *buf, int len) } // Reading from script, need to process special bytes - int i; char_u *p = (char_u *)buf; // Two characters are special: NUL and K_SPECIAL. // Replace NUL by K_SPECIAL KS_ZERO KE_FILLER // Replace K_SPECIAL by K_SPECIAL KS_SPECIAL KE_FILLER - for (i = len; --i >= 0; p++) { + for (int i = len; --i >= 0; p++) { if (p[0] == NUL || (p[0] == K_SPECIAL && (i < 2 || p[1] != KS_EXTRA))) { diff --git a/src/nvim/grid.c b/src/nvim/grid.c index 8815ac726a..16ebbfbb90 100644 --- a/src/nvim/grid.c +++ b/src/nvim/grid.c @@ -805,7 +805,6 @@ void grid_assign_handle(ScreenGrid *grid) /// 'row', 'col' and 'end' are relative to the start of the region. void grid_ins_lines(ScreenGrid *grid, int row, int line_count, int end, int col, int width) { - int i; int j; unsigned temp; @@ -820,7 +819,7 @@ void grid_ins_lines(ScreenGrid *grid, int row, int line_count, int end, int col, // Shift line_offset[] line_count down to reflect the inserted lines. // Clear the inserted lines. - for (i = 0; i < line_count; i++) { + for (int i = 0; i < line_count; i++) { if (width != grid->cols) { // need to copy part of a line j = end - 1 - i; @@ -855,7 +854,6 @@ void grid_ins_lines(ScreenGrid *grid, int row, int line_count, int end, int col, void grid_del_lines(ScreenGrid *grid, int row, int line_count, int end, int col, int width) { int j; - int i; unsigned temp; int row_off = 0; @@ -869,7 +867,7 @@ void grid_del_lines(ScreenGrid *grid, int row, int line_count, int end, int col, // Now shift line_offset[] line_count up to reflect the deleted lines. // Clear the inserted lines. - for (i = 0; i < line_count; i++) { + for (int i = 0; i < line_count; i++) { if (width != grid->cols) { // need to copy part of a line j = row + i; diff --git a/src/nvim/help.c b/src/nvim/help.c index ab4ce4e9ba..5fa48e0cee 100644 --- a/src/nvim/help.c +++ b/src/nvim/help.c @@ -47,19 +47,14 @@ void ex_help(exarg_T *eap) { char *arg; - char *tag; FILE *helpfd; // file descriptor of help file - int n; - int i; win_T *wp; int num_matches; char **matches; - char *p; int empty_fnum = 0; int alt_fnum = 0; buf_T *buf; int len; - char *lang; const bool old_KeyTyped = KeyTyped; if (eap != NULL) { @@ -88,13 +83,13 @@ void ex_help(exarg_T *eap) } // remove trailing blanks - p = arg + strlen(arg) - 1; + char *p = arg + strlen(arg) - 1; while (p > arg && ascii_iswhite(*p) && p[-1] != '\\') { *p-- = NUL; } // Check for a specified language - lang = check_help_lang(arg); + char *lang = check_help_lang(arg); // When no argument given go to the index. if (*arg == NUL) { @@ -102,9 +97,9 @@ void ex_help(exarg_T *eap) } // Check if there is a match for the argument. - n = find_help_tags(arg, &num_matches, &matches, eap != NULL && eap->forceit); + int n = find_help_tags(arg, &num_matches, &matches, eap != NULL && eap->forceit); - i = 0; + int i = 0; if (n != FAIL && lang != NULL) { // Find first item with the requested language. for (i = 0; i < num_matches; i++) { @@ -128,7 +123,7 @@ void ex_help(exarg_T *eap) } // The first match (in the requested language) is the best match. - tag = xstrdup(matches[i]); + char *tag = xstrdup(matches[i]); FreeWild(num_matches, matches); // Re-use an existing help window or open a new one. @@ -259,11 +254,8 @@ char *check_help_lang(char *arg) int help_heuristic(char *matched_string, int offset, int wrong_case) FUNC_ATTR_PURE { - int num_letters; - char *p; - - num_letters = 0; - for (p = matched_string; *p; p++) { + int num_letters = 0; + for (char *p = matched_string; *p; p++) { if (ASCII_ISALNUM(*p)) { num_letters++; } @@ -298,11 +290,8 @@ int help_heuristic(char *matched_string, int offset, int wrong_case) /// that has been put after the tagname by find_tags(). static int help_compare(const void *s1, const void *s2) { - char *p1; - char *p2; - - p1 = *(char **)s1 + strlen(*(char **)s1) + 1; - p2 = *(char **)s2 + strlen(*(char **)s2) + 1; + char *p1 = *(char **)s1 + strlen(*(char **)s1) + 1; + char *p2 = *(char **)s2 + strlen(*(char **)s2) + 1; // Compare by help heuristic number first. int cmp = strcmp(p1, p2); @@ -320,8 +309,6 @@ static int help_compare(const void *s1, const void *s2) /// When "keep_lang" is true try keeping the language of the current buffer. int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep_lang) { - int i; - // Specific tags that either have a specific replacement or won't go // through the generic rules. static char *(except_tbl[][2]) = { @@ -379,7 +366,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep // When the string starting with "expr-" and containing '?' and matches // the table, it is taken literally (but ~ is escaped). Otherwise '?' // is recognized as a wildcard. - for (i = (int)ARRAY_SIZE(expr_table); --i >= 0;) { + for (int i = (int)ARRAY_SIZE(expr_table); --i >= 0;) { if (strcmp(arg + 5, expr_table[i]) == 0) { for (int si = 0, di = 0;; si++) { if (arg[si] == '~') { @@ -396,7 +383,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep } else { // Recognize a few exceptions to the rule. Some strings that contain // '*'are changed to "star", otherwise '*' is recognized as a wildcard. - for (i = 0; except_tbl[i][0] != NULL; i++) { + for (int i = 0; except_tbl[i][0] != NULL; i++) { if (strcmp(arg, except_tbl[i][0]) == 0) { STRCPY(d, except_tbl[i][1]); break; diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c index ff1bcffbdb..8114efc10c 100644 --- a/src/nvim/keycodes.c +++ b/src/nvim/keycodes.c @@ -637,7 +637,6 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m const bool in_string = flags & FSK_IN_STRING; int modifiers; int bit; - int key; uvarnumber_T n; int l; @@ -685,6 +684,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m } if (bp <= end && *bp == '>') { // found matching '>' + int key; end_of_name = bp + 1; // Which modifiers are given? diff --git a/src/nvim/mark.c b/src/nvim/mark.c index 0a944da2c4..855fcb33ae 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -616,11 +616,8 @@ fmarkv_T mark_view_make(linenr_T topline, pos_T pos) /// @return next mark or NULL if no mark is found. fmark_T *getnextmark(pos_T *startpos, int dir, int begin_line) { - int i; fmark_T *result = NULL; - pos_T pos; - - pos = *startpos; + pos_T pos = *startpos; if (dir == BACKWARD && begin_line) { pos.col = 0; @@ -628,7 +625,7 @@ fmark_T *getnextmark(pos_T *startpos, int dir, int begin_line) pos.col = MAXCOL; } - for (i = 0; i < NMARKS; i++) { + for (int i = 0; i < NMARKS; i++) { if (curbuf->b_namedm[i].mark.lnum > 0) { if (dir == FORWARD) { if ((result == NULL || lt(curbuf->b_namedm[i].mark, result->mark)) @@ -685,18 +682,17 @@ static void fname2fnum(xfmark_T *fm) void fmarks_check_names(buf_T *buf) { char *name = buf->b_ffname; - int i; if (buf->b_ffname == NULL) { return; } - for (i = 0; i < NGLOBALMARKS; i++) { + for (int i = 0; i < NGLOBALMARKS; i++) { fmarks_check_one(&namedfm[i], name, buf); } FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - for (i = 0; i < wp->w_jumplistlen; i++) { + for (int i = 0; i < wp->w_jumplistlen; i++) { fmarks_check_one(&wp->w_jumplist[i], name, buf); } } @@ -820,7 +816,6 @@ static char *mark_line(pos_T *mp, int lead_len) void ex_marks(exarg_T *eap) { char *arg = eap->arg; - int i; char *name; pos_T *posp, *startp, *endp; @@ -829,10 +824,10 @@ void ex_marks(exarg_T *eap) } show_one_mark('\'', arg, &curwin->w_pcmark, NULL, true); - for (i = 0; i < NMARKS; i++) { + for (int i = 0; i < NMARKS; i++) { show_one_mark(i + 'a', arg, &curbuf->b_namedm[i].mark, NULL, true); } - for (i = 0; i < NGLOBALMARKS; i++) { + for (int i = 0; i < NGLOBALMARKS; i++) { if (namedfm[i].fmark.fnum != 0) { name = fm_getname(&namedfm[i].fmark, 15); } else { @@ -918,7 +913,6 @@ void ex_delmarks(exarg_T *eap) { char *p; int from, to; - int i; int lower; int digit; int n; @@ -953,7 +947,7 @@ void ex_delmarks(exarg_T *eap) from = to = (uint8_t)(*p); } - for (i = from; i <= to; i++) { + for (int i = from; i <= to; i++) { if (lower) { curbuf->b_namedm[i - 'a'].mark.lnum = 0; } else { @@ -997,13 +991,12 @@ void ex_delmarks(exarg_T *eap) // print the jumplist void ex_jumps(exarg_T *eap) { - int i; char *name; cleanup_jumplist(curwin, true); // Highlight title msg_puts_title(_("\n jump line col file/text")); - for (i = 0; i < curwin->w_jumplistlen && !got_int; i++) { + for (int i = 0; i < curwin->w_jumplistlen && !got_int; i++) { if (curwin->w_jumplist[i].fmark.mark.lnum != 0) { name = fm_getname(&curwin->w_jumplist[i].fmark, 16); @@ -1050,13 +1043,12 @@ void ex_clearjumps(exarg_T *eap) // print the changelist void ex_changes(exarg_T *eap) { - int i; char *name; // Highlight title msg_puts_title(_("\nchange line col text")); - for (i = 0; i < curbuf->b_changelistlen && !got_int; i++) { + for (int i = 0; i < curbuf->b_changelistlen && !got_int; i++) { if (curbuf->b_changelist[i].mark.lnum != 0) { msg_putchar('\n'); if (got_int) { @@ -1137,7 +1129,6 @@ void mark_adjust_nofold(linenr_T line1, linenr_T line2, linenr_T amount, linenr_ static void mark_adjust_internal(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T amount_after, bool adjust_folds, ExtmarkOp op) { - int i; int fnum = curbuf->b_fnum; linenr_T *lp; static pos_T initpos = { 1, 0, 0 }; @@ -1148,13 +1139,13 @@ static void mark_adjust_internal(linenr_T line1, linenr_T line2, linenr_T amount if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) { // named marks, lower case and upper case - for (i = 0; i < NMARKS; i++) { + for (int i = 0; i < NMARKS; i++) { ONE_ADJUST(&(curbuf->b_namedm[i].mark.lnum)); if (namedfm[i].fmark.fnum == fnum) { ONE_ADJUST_NODEL(&(namedfm[i].fmark.mark.lnum)); } } - for (i = NMARKS; i < NGLOBALMARKS; i++) { + for (int i = NMARKS; i < NGLOBALMARKS; i++) { if (namedfm[i].fmark.fnum == fnum) { ONE_ADJUST_NODEL(&(namedfm[i].fmark.mark.lnum)); } @@ -1172,7 +1163,7 @@ static void mark_adjust_internal(linenr_T line1, linenr_T line2, linenr_T amount } // list of change positions - for (i = 0; i < curbuf->b_changelistlen; i++) { + for (int i = 0; i < curbuf->b_changelistlen; i++) { ONE_ADJUST_NODEL(&(curbuf->b_changelist[i].mark.lnum)); } @@ -1216,7 +1207,7 @@ static void mark_adjust_internal(linenr_T line1, linenr_T line2, linenr_T amount if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) { // Marks in the jumplist. When deleting lines, this may create // duplicate marks in the jumplist, they will be removed later. - for (i = 0; i < win->w_jumplistlen; i++) { + for (int i = 0; i < win->w_jumplistlen; i++) { if (win->w_jumplist[i].fmark.fnum == fnum) { ONE_ADJUST_NODEL(&(win->w_jumplist[i].fmark.mark.lnum)); } @@ -1226,7 +1217,7 @@ static void mark_adjust_internal(linenr_T line1, linenr_T line2, linenr_T amount if (win->w_buffer == curbuf) { if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) { // marks in the tag stack - for (i = 0; i < win->w_tagstacklen; i++) { + for (int i = 0; i < win->w_tagstacklen; i++) { if (win->w_tagstack[i].fmark.fnum == fnum) { ONE_ADJUST_NODEL(&(win->w_tagstack[i].fmark.mark.lnum)); } @@ -1308,7 +1299,6 @@ static void mark_adjust_internal(linenr_T line1, linenr_T line2, linenr_T amount void mark_col_adjust(linenr_T lnum, colnr_T mincol, linenr_T lnum_amount, long col_amount, int spaces_removed) { - int i; int fnum = curbuf->b_fnum; pos_T *posp; @@ -1316,13 +1306,13 @@ void mark_col_adjust(linenr_T lnum, colnr_T mincol, linenr_T lnum_amount, long c return; // nothing to do } // named marks, lower case and upper case - for (i = 0; i < NMARKS; i++) { + for (int i = 0; i < NMARKS; i++) { COL_ADJUST(&(curbuf->b_namedm[i].mark)); if (namedfm[i].fmark.fnum == fnum) { COL_ADJUST(&(namedfm[i].fmark.mark)); } } - for (i = NMARKS; i < NGLOBALMARKS; i++) { + for (int i = NMARKS; i < NGLOBALMARKS; i++) { if (namedfm[i].fmark.fnum == fnum) { COL_ADJUST(&(namedfm[i].fmark.mark)); } @@ -1335,7 +1325,7 @@ void mark_col_adjust(linenr_T lnum, colnr_T mincol, linenr_T lnum_amount, long c COL_ADJUST(&(curbuf->b_last_change.mark)); // list of change positions - for (i = 0; i < curbuf->b_changelistlen; i++) { + for (int i = 0; i < curbuf->b_changelistlen; i++) { COL_ADJUST(&(curbuf->b_changelist[i].mark)); } @@ -1355,7 +1345,7 @@ void mark_col_adjust(linenr_T lnum, colnr_T mincol, linenr_T lnum_amount, long c // Adjust items in all windows related to the current buffer. FOR_ALL_WINDOWS_IN_TAB(win, curtab) { // marks in the jumplist - for (i = 0; i < win->w_jumplistlen; i++) { + for (int i = 0; i < win->w_jumplistlen; i++) { if (win->w_jumplist[i].fmark.fnum == fnum) { COL_ADJUST(&(win->w_jumplist[i].fmark.mark)); } @@ -1363,7 +1353,7 @@ void mark_col_adjust(linenr_T lnum, colnr_T mincol, linenr_T lnum_amount, long c if (win->w_buffer == curbuf) { // marks in the tag stack - for (i = 0; i < win->w_tagstacklen; i++) { + for (int i = 0; i < win->w_tagstacklen; i++) { if (win->w_tagstack[i].fmark.fnum == fnum) { COL_ADJUST(&(win->w_tagstack[i].fmark.mark)); } @@ -1456,9 +1446,7 @@ void cleanup_jumplist(win_T *wp, bool loadfiles) // Copy the jumplist from window "from" to window "to". void copy_jumplist(win_T *from, win_T *to) { - int i; - - for (i = 0; i < from->w_jumplistlen; i++) { + for (int i = 0; i < from->w_jumplistlen; i++) { to->w_jumplist[i] = from->w_jumplist[i]; if (from->w_jumplist[i].fname != NULL) { to->w_jumplist[i].fname = xstrdup(from->w_jumplist[i].fname); @@ -1670,9 +1658,7 @@ bool mark_set_local(const char name, buf_T *const buf, const fmark_T fm, const b // Free items in the jumplist of window "wp". void free_jumplist(win_T *wp) { - int i; - - for (i = 0; i < wp->w_jumplistlen; i++) { + for (int i = 0; i < wp->w_jumplistlen; i++) { free_xfmark(wp->w_jumplist[i]); } wp->w_jumplistlen = 0; diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index c2bde53b32..e27bb003e7 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -847,7 +847,6 @@ int utf_byte2len(int b) int utf_ptr2len_len(const char *p, int size) { int len; - int i; int m; len = utf8len_tab[(uint8_t)(*p)]; @@ -859,7 +858,7 @@ int utf_ptr2len_len(const char *p, int size) } else { m = len; } - for (i = 1; i < m; i++) { + for (int i = 1; i < m; i++) { if ((p[i] & 0xc0) != 0x80) { return 1; } @@ -1530,7 +1529,6 @@ void show_utf8(void) int rlen = 0; char *line; int clen; - int i; // Get the byte length of the char under the cursor, including composing // characters. @@ -1542,7 +1540,7 @@ void show_utf8(void) } clen = 0; - for (i = 0; i < len; i++) { + for (int i = 0; i < len; i++) { if (clen == 0) { // start of (composing) character, get its length if (i > 0) { @@ -2171,9 +2169,7 @@ char *enc_canonize(char *enc) /// Returns -1 when not found. static int enc_alias_search(const char *name) { - int i; - - for (i = 0; enc_alias_table[i].name != NULL; i++) { + for (int i = 0; enc_alias_table[i].name != NULL; i++) { if (strcmp(name, enc_alias_table[i].name) == 0) { return enc_alias_table[i].canon; } diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 8ab515bf0e..4fad926cb0 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -281,7 +281,6 @@ static int add_menu_path(const char *const menu_path, vimmenu_T *menuarg, const char *next_name; char c; char d; - int i; int pri_idx = 0; int old_modes = 0; int amenu; @@ -411,7 +410,7 @@ static int add_menu_path(const char *const menu_path, vimmenu_T *menuarg, const p = (call_data == NULL) ? NULL : xstrdup(call_data); // loop over all modes, may add more than one - for (i = 0; i < MENU_MODES; i++) { + for (int i = 0; i < MENU_MODES; i++) { if (modes & (1 << i)) { // free any old menu free_menu_string(menu, i); @@ -617,10 +616,7 @@ static int remove_menu(vimmenu_T **menup, char *name, int modes, bool silent) // Free the given menu structure and remove it from the linked list. static void free_menu(vimmenu_T **menup) { - int i; - vimmenu_T *menu; - - menu = *menup; + vimmenu_T *menu = *menup; // Don't change *menup until after calling gui_mch_destroy_menu(). The // MacOS code needs the original structure to properly delete the menu. @@ -630,7 +626,7 @@ static void free_menu(vimmenu_T **menup) xfree(menu->en_name); xfree(menu->en_dname); xfree(menu->actext); - for (i = 0; i < MENU_MODES; i++) { + for (int i = 0; i < MENU_MODES; i++) { free_menu_string(menu, i); } xfree(menu); @@ -640,9 +636,8 @@ static void free_menu(vimmenu_T **menup) static void free_menu_string(vimmenu_T *menu, int idx) { int count = 0; - int i; - for (i = 0; i < MENU_MODES; i++) { + for (int i = 0; i < MENU_MODES; i++) { if (menu->strings[i] == menu->strings[idx]) { count++; } @@ -662,13 +657,11 @@ static void free_menu_string(vimmenu_T *menu, int idx) /// @see menu_get static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes) { - dict_T *dict; - if (!menu || (menu->modes & modes) == 0x0) { return NULL; } - dict = tv_dict_alloc(); + dict_T *dict = tv_dict_alloc(); tv_dict_add_str(dict, S_LEN("name"), menu->dname); tv_dict_add_nr(dict, S_LEN("priority"), (int)menu->priority); tv_dict_add_nr(dict, S_LEN("hidden"), menu_is_hidden(menu->dname)); diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 70e1e00623..cff0f886ce 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -286,7 +286,6 @@ int do_in_path(char *path, char *name, int flags, DoInRuntimepathCB callback, vo char *buf = xmallocz(MAXPATHL); { char *tail; - int i; if (p_verbose > 10 && name != NULL) { verbose_enter(); smsg(_("Searching for \"%s\" in \"%s\""), name, path); @@ -335,7 +334,7 @@ int do_in_path(char *path, char *name, int flags, DoInRuntimepathCB callback, vo // Expand wildcards, invoke the callback for each match. if (gen_expand_wildcards(1, &buf, &num_files, &files, ew_flags) == OK) { - for (i = 0; i < num_files; i++) { + for (int i = 0; i < num_files; i++) { (*callback)(files[i], cookie); did_one = true; if (!(flags & DIP_ALL)) { @@ -416,7 +415,6 @@ int do_in_cached_path(char *name, int flags, DoInRuntimepathCB callback, void *c char *tail; int num_files; char **files; - int i; bool did_one = false; char buf[MAXPATHL]; @@ -469,7 +467,7 @@ int do_in_cached_path(char *name, int flags, DoInRuntimepathCB callback, void *c // Expand wildcards, invoke the callback for each match. char *(pat[]) = { buf }; if (gen_expand_wildcards(1, pat, &num_files, &files, ew_flags) == OK) { - for (i = 0; i < num_files; i++) { + for (int i = 0; i < num_files; i++) { (*callback)(files[i], cookie); did_one = true; if (!(flags & DIP_ALL)) { diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 05da6e0ef1..da9178bdff 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -248,11 +248,8 @@ size_t fill_foldcolumn(char *p, win_T *wp, foldinfo_T foldinfo, linenr_T lnum) /// Only works for single-byte characters (e.g., numbers). void rl_mirror(char *str) { - char *p1, *p2; - char t; - - for (p1 = str, p2 = str + strlen(str) - 1; p1 < p2; p1++, p2--) { - t = *p1; + for (char *p1 = str, *p2 = str + strlen(str) - 1; p1 < p2; p1++, p2--) { + char t = *p1; *p1 = *p2; *p2 = t; } @@ -264,9 +261,7 @@ void rl_mirror(char *str) /// line of the window right of it. If not, then it's a vertical separator. bool stl_connected(win_T *wp) { - frame_T *fr; - - fr = wp->w_frame; + frame_T *fr = wp->w_frame; while (fr->fr_parent != NULL) { if (fr->fr_parent->fr_layout == FR_COL) { if (fr->fr_next != NULL) { @@ -437,11 +432,7 @@ bool skip_showmode(void) /// @return the length of the message (0 if no message). int showmode(void) { - bool need_clear; int length = 0; - int do_mode; - int attr; - int sub_attr; if (ui_has(kUIMessages) && clear_cmdline) { msg_ext_clear(true); @@ -452,12 +443,13 @@ int showmode(void) msg_grid_validate(); - do_mode = ((p_smd && msg_silent == 0) - && ((State & MODE_TERMINAL) - || (State & MODE_INSERT) - || restart_edit != NUL - || VIsual_active)); + int do_mode = ((p_smd && msg_silent == 0) + && ((State & MODE_TERMINAL) + || (State & MODE_INSERT) + || restart_edit != NUL + || VIsual_active)); if (do_mode || reg_recording != 0) { + int sub_attr; if (skip_showmode()) { return 0; // show mode later } @@ -468,14 +460,14 @@ int showmode(void) check_for_delay(false); // if the cmdline is more than one line high, erase top lines - need_clear = clear_cmdline; + bool need_clear = clear_cmdline; if (clear_cmdline && cmdline_row < Rows - 1) { msg_clr_cmdline(); // will reset clear_cmdline } // Position on the last line in the window, column 0 msg_pos_mode(); - attr = HL_ATTR(HLF_CM); // Highlight mode + int attr = HL_ATTR(HLF_CM); // Highlight mode // When the screen is too narrow to show the entire mode message, // avoid scrolling and truncate instead. diff --git a/src/nvim/search.c b/src/nvim/search.c index 74ae76e3b2..e5a456161f 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -136,14 +136,12 @@ typedef struct SearchedFile { int search_regcomp(char *pat, char **used_pat, int pat_save, int pat_use, int options, regmmatch_T *regmatch) { - int magic; - int i; - rc_did_emsg = false; - magic = magic_isset(); + int magic = magic_isset(); // If no pattern given, use a previously defined pattern. if (pat == NULL || *pat == NUL) { + int i; if (pat_use == RE_LAST) { i = last_idx; } else { @@ -557,8 +555,6 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, lpos_T endpos; lpos_T matchpos; int loop; - pos_T start_pos; - int at_first_line; int extra_col; int start_char_len; bool match_ok; @@ -611,9 +607,9 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, extra_col = (options & SEARCH_START) ? start_char_len : 0; } - start_pos = *pos; // remember start pos for detecting no match + pos_T start_pos = *pos; // remember start pos for detecting no match found = 0; // default: not found - at_first_line = true; // default: start in first line + int at_first_line = true; // default: start in first line if (pos->lnum == 0) { // correct lnum for when starting in line 0 pos->lnum = 1; pos->col = 0; @@ -1028,7 +1024,6 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, long count, i { pos_T pos; // position of the last match char *searchstr; - struct soffset old_off; int retval; // Return value char *p; int64_t c; @@ -1047,7 +1042,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, long count, i // Save the values for when (options & SEARCH_KEEP) is used. // (there is no "if ()" around this because gcc wants them initialized) - old_off = spats[0].off; + struct soffset old_off = spats[0].off; pos = curwin->w_cursor; // start searching at the cursor position @@ -1434,8 +1429,6 @@ end_do_search: int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char *pat) { linenr_T start = 0; - char *ptr; - char *p; if (buf->b_ml.ml_line_count == 0) { return FAIL; @@ -1469,8 +1462,8 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char *pat) if (start == 0) { start = pos->lnum; } - ptr = ml_get_buf(buf, pos->lnum, false); - p = skipwhite(ptr); + char *ptr = ml_get_buf(buf, pos->lnum, false); + char *p = skipwhite(ptr); pos->col = (colnr_T)(p - ptr); // when adding lines the matching line may be empty but it is not @@ -1503,9 +1496,6 @@ int searchc(cmdarg_T *cap, int t_cmd) int c = cap->nchar; // char to search for int dir = cap->arg; // true for searching forward long count = cap->count1; // repeat count - int col; - char *p; - int len; bool stop = true; if (c != NUL) { // normal search: remember args for repeat @@ -1550,9 +1540,9 @@ int searchc(cmdarg_T *cap, int t_cmd) cap->oap->inclusive = true; } - p = get_cursor_line_ptr(); - col = curwin->w_cursor.col; - len = (int)strlen(p); + char *p = get_cursor_line_ptr(); + int col = curwin->w_cursor.col; + int len = (int)strlen(p); while (count--) { for (;;) { @@ -2295,15 +2285,10 @@ int check_linecomment(const char *line) /// @param c char to show match for void showmatch(int c) { - pos_T *lpos, save_cursor; - pos_T mpos; + pos_T *lpos; colnr_T vcol; long *so = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so; long *siso = curwin->w_p_siso >= 0 ? &curwin->w_p_siso : &p_siso; - long save_so; - long save_siso; - int save_state; - colnr_T save_dollar_vcol; char *p; // Only show match for chars in the 'matchpairs' option. @@ -2345,10 +2330,10 @@ void showmatch(int c) return; } - mpos = *lpos; // save the pos, update_screen() may change it - save_cursor = curwin->w_cursor; - save_so = *so; - save_siso = *siso; + pos_T mpos = *lpos; // save the pos, update_screen() may change it + pos_T save_cursor = curwin->w_cursor; + long save_so = *so; + long save_siso = *siso; // Handle "$" in 'cpo': If the ')' is typed on top of the "$", // stop displaying the "$". if (dollar_vcol >= 0 && dollar_vcol == curwin->w_virtcol) { @@ -2357,8 +2342,8 @@ void showmatch(int c) curwin->w_virtcol++; // do display ')' just before "$" update_screen(); // show the new char first - save_dollar_vcol = dollar_vcol; - save_state = State; + colnr_T save_dollar_vcol = dollar_vcol; + int save_state = State; State = MODE_SHOWMATCH; ui_cursor_shape(); // may show different cursor shape curwin->w_cursor = mpos; // move to matching char @@ -2531,7 +2516,6 @@ int current_search(long count, bool forward) static int is_zero_width(char *pattern, int move, pos_T *cur, Direction direction) { regmmatch_T regmatch; - int nmatched = 0; int result = -1; pos_T pos; const int called_emsg_before = called_emsg; @@ -2558,6 +2542,7 @@ static int is_zero_width(char *pattern, int move, pos_T *cur, Direction directio } if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, 1, SEARCH_KEEP + flag, RE_SEARCH, NULL) != FAIL) { + int nmatched = 0; // Zero-width pattern should match somewhere, then we can check if // start and end are in the same position. do { @@ -2587,9 +2572,7 @@ static int is_zero_width(char *pattern, int move, pos_T *cur, Direction directio /// return true if line 'lnum' is empty or has white chars only. int linewhite(linenr_T lnum) { - char *p; - - p = skipwhite(ml_get(lnum)); + char *p = skipwhite(ml_get(lnum)); return *p == NUL; } @@ -2682,7 +2665,6 @@ static void update_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, searchst static int chgtick = 0; static char *lastpat = NULL; static buf_T *lbuf = NULL; - proftime_T start; CLEAR_POINTER(stat); @@ -2722,6 +2704,7 @@ static void update_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, searchst && (dirc == 0 || dirc == '/' ? cur < cnt : cur > 0)) { cur += dirc == 0 ? 0 : dirc == '/' ? 1 : -1; } else { + proftime_T start; bool done_search = false; pos_T endpos = { 0, 0, 0 }; p_ws = false; @@ -2788,7 +2771,6 @@ void f_searchcount(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (argvars[0].v_type != VAR_UNKNOWN) { dict_T *dict; dictitem_T *di; - listitem_T *li; bool error = false; if (argvars[0].v_type != VAR_DICT || argvars[0].vval.v_dict == NULL) { @@ -2834,7 +2816,7 @@ void f_searchcount(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) semsg(_(e_invarg2), "List format should be [lnum, col, off]"); return; } - li = tv_list_find(di->di_tv.vval.v_list, 0L); + listitem_T *li = tv_list_find(di->di_tv.vval.v_list, 0L); if (li != NULL) { pos.lnum = (linenr_T)tv_get_number_chk(TV_LIST_ITEM_TV(li), &error); if (error) { @@ -4156,8 +4138,6 @@ static void show_pat_in_path(char *line, int type, bool did_show, int action, FI linenr_T *lnum, long count) FUNC_ATTR_NONNULL_ARG(1, 6) { - char *p; - if (did_show) { msg_putchar('\n'); // cursor below last one } else if (!msg_silent) { @@ -4167,7 +4147,7 @@ static void show_pat_in_path(char *line, int type, bool did_show, int action, FI return; } for (;;) { - p = line + strlen(line) - 1; + char *p = line + strlen(line) - 1; if (fp != NULL) { // We used fgets(), so get rid of newline at end if (p >= line && *p == '\n') { diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 22a8587f66..e9dd0a4d5e 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -897,7 +897,6 @@ void suggest_load_files(void) char *dotp; FILE *fd; char buf[MAXWLEN]; - int i; time_t timestamp; int wcount; int wordnr; @@ -925,7 +924,7 @@ void suggest_load_files(void) } // : - for (i = 0; i < VIMSUGMAGICL; i++) { + for (int i = 0; i < VIMSUGMAGICL; i++) { buf[i] = (char)getc(fd); // } if (strncmp(buf, VIMSUGMAGIC, VIMSUGMAGICL) != 0) { @@ -1734,7 +1733,6 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx bool prefixtree, int maxprefcondnr) { int len; - int i; int n; idx_T idx = startidx; int c2; @@ -1751,7 +1749,7 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx byts[idx++] = (char_u)len; // Read the byte values, flag/region bytes and shared indexes. - for (i = 1; i <= len; i++) { + for (int i = 1; i <= len; i++) { int c = getc(fd); // if (c < 0) { return SP_TRUNCERROR; @@ -1814,7 +1812,7 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx // Recursively read the children for non-shared siblings. // Skip the end-of-word ones (zero byte value) and the shared ones (and // remove SHARED_MASK) - for (i = 1; i <= len; i++) { + for (int i = 1; i <= len; i++) { if (byts[startidx + i] != 0) { if (idxs[startidx + i] & SHARED_MASK) { idxs[startidx + i] &= ~SHARED_MASK; @@ -2673,9 +2671,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname) && sofoto == NULL) { sofoto = getroom_save(spin, items[1]); } else if (strcmp(items[0], "COMMON") == 0) { - int i; - - for (i = 1; i < itemcnt; i++) { + for (int i = 1; i < itemcnt; i++) { if (HASHITEM_EMPTY(hash_find(&spin->si_commonwords, (char *)items[i]))) { p = xstrdup(items[i]); hash_add(&spin->si_commonwords, p); @@ -3954,10 +3950,9 @@ static int tree_add_word(spellinfo_T *spin, const char_u *word, wordnode_T *root wordnode_T *np; wordnode_T *copyp, **copyprev; wordnode_T **prev = NULL; - int i; // Add each byte of the word to the tree, including the NUL at the end. - for (i = 0;; i++) { + for (int i = 0;; i++) { // When there is more than one reference to this node we need to make // a copy, so that we can modify it. Copy the whole list of siblings // (we don't optimize for a partly shared list of siblings). @@ -5737,13 +5732,12 @@ static void set_spell_charflags(const char_u *flags, int cnt, char *fol) // We build the new tables here first, so that we can compare with the // previous one. spelltab_T new_st; - int i; char *p = fol; int c; clear_spell_chartab(&new_st); - for (i = 0; i < 128; i++) { + for (int i = 0; i < 128; i++) { if (i < cnt) { new_st.st_isw[i + 128] = (flags[i] & CF_WORD) != 0; new_st.st_isu[i + 128] = (flags[i] & CF_UPPER) != 0; @@ -5818,7 +5812,6 @@ static void set_map_str(slang_T *lp, char *map) { char *p; int headc = 0; - int i; if (*map == NUL) { lp->sl_has_map = false; @@ -5827,7 +5820,7 @@ static void set_map_str(slang_T *lp, char *map) lp->sl_has_map = true; // Init the array and hash tables empty. - for (i = 0; i < 256; i++) { + for (int i = 0; i < 256; i++) { lp->sl_map_array[i] = 0; } hash_init(&lp->sl_map_hash); diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c index 66829c60c9..d176a65228 100644 --- a/src/nvim/spellsuggest.c +++ b/src/nvim/spellsuggest.c @@ -2491,7 +2491,6 @@ static void score_comp_sal(suginfo_T *su) { langp_T *lp; char badsound[MAXWLEN]; - int i; suggest_T *stp; suggest_T *sstp; int score; @@ -2505,7 +2504,7 @@ static void score_comp_sal(suginfo_T *su) // soundfold the bad word spell_soundfold(lp->lp_slang, su->su_fbadword, true, badsound); - for (i = 0; i < su->su_ga.ga_len; i++) { + for (int i = 0; i < su->su_ga.ga_len; i++) { stp = &SUG(su->su_ga, i); // Case-fold the suggested word, sound-fold it and compute the diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 6e0dc2e8f7..6414b2bb74 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -260,23 +260,17 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler) { static bool entered = false; int attr; - int curattr; int row; int col = 0; int maxwidth; - int width; int n; - int len; int fillchar; char buf[MAXPATHL]; char *stl; - char *p; char *opt_name; int opt_scope = 0; stl_hlrec_t *hltab; StlClickRecord *tabtab; - win_T *ewp; - int p_crb_save; bool is_stl_global = global_stl_height() > 0; ScreenGrid *grid = &default_grid; @@ -369,22 +363,22 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler) // Temporarily reset 'cursorbind', we don't want a side effect from moving // the cursor away and back. - ewp = wp == NULL ? curwin : wp; - p_crb_save = ewp->w_p_crb; + win_T *ewp = wp == NULL ? curwin : wp; + int p_crb_save = ewp->w_p_crb; ewp->w_p_crb = false; // Make a copy, because the statusline may include a function call that // might change the option value and free the memory. stl = xstrdup(stl); - width = build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_name, opt_scope, - fillchar, maxwidth, &hltab, &tabtab, NULL); + int width = build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_name, opt_scope, + fillchar, maxwidth, &hltab, &tabtab, NULL); xfree(stl); ewp->w_p_crb = p_crb_save; // Make all characters printable. - p = transstr(buf, true); - len = (int)xstrlcpy(buf, p, sizeof(buf)); + char *p = transstr(buf, true); + int len = (int)xstrlcpy(buf, p, sizeof(buf)); len = (size_t)len < sizeof(buf) ? len : (int)sizeof(buf) - 1; xfree(p); @@ -398,7 +392,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler) // Draw each snippet with the specified highlighting. grid_puts_line_start(grid, row); - curattr = attr; + int curattr = attr; p = buf; for (n = 0; hltab[n].start != NULL; n++) { int textlen = (int)(hltab[n].start - p); @@ -709,21 +703,9 @@ static void ui_ext_tabline_update(void) /// Draw the tab pages line at the top of the Vim window. void draw_tabline(void) { - int tabcount = 0; - int tabwidth = 0; - int col = 0; - int scol = 0; - int attr; win_T *wp; - win_T *cwp; - int wincount; - int modified; - int c; - int len; int attr_nosel = HL_ATTR(HLF_TP); int attr_fill = HL_ATTR(HLF_TPF); - char *p; - int room; int use_sep_chars = (t_colors < 8); if (default_grid.chars == NULL) { @@ -748,6 +730,14 @@ void draw_tabline(void) if (*p_tal != NUL) { win_redr_custom(NULL, false, false); } else { + int tabcount = 0; + int tabwidth = 0; + int col = 0; + win_T *cwp; + int wincount; + int c; + int len; + char *p; FOR_ALL_TABS(tp) { tabcount++; } @@ -760,7 +750,7 @@ void draw_tabline(void) tabwidth = 6; } - attr = attr_nosel; + int attr = attr_nosel; tabcount = 0; FOR_ALL_TABS(tp) { @@ -768,7 +758,7 @@ void draw_tabline(void) break; } - scol = col; + int scol = col; if (tp == curtab) { cwp = curwin; @@ -791,7 +781,7 @@ void draw_tabline(void) grid_putchar(&default_grid, ' ', 0, col++, attr); - modified = false; + int modified = false; for (wincount = 0; wp != NULL; wp = wp->w_next, wincount++) { if (bufIsChanged(wp->w_buffer)) { @@ -816,7 +806,7 @@ void draw_tabline(void) grid_putchar(&default_grid, ' ', 0, col++, attr); } - room = scol - col + tabwidth - 1; + int room = scol - col + tabwidth - 1; if (room > 0) { // Get buffer name in NameBuff[] get_trans_bufname(cwp->w_buffer); diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 49b63ad324..d4161b9ca2 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -1218,7 +1218,6 @@ static synstate_T *store_current_state(void) // Copy a state stack from "from" in b_sst_array[] to current_state; static void load_current_state(synstate_T *from) { - int i; bufstate_T *bp; clear_current_state(); @@ -1231,7 +1230,7 @@ static void load_current_state(synstate_T *from) } else { bp = from->sst_union.sst_stack; } - for (i = 0; i < from->sst_stacksize; i++) { + for (int i = 0; i < from->sst_stacksize; i++) { CUR_STATE(i).si_idx = bp[i].bs_idx; CUR_STATE(i).si_flags = bp[i].bs_flags; CUR_STATE(i).si_seqnr = bp[i].bs_seqnr; @@ -3441,9 +3440,7 @@ static void syn_list_one(const int id, const bool syncing, const bool link_only) static void syn_list_flags(struct name_list *nlist, int flags, int attr) { - int i; - - for (i = 0; nlist[i].flag != 0; i++) { + for (int i = 0; nlist[i].flag != 0; i++) { if (flags & nlist[i].flag) { msg_puts_attr(nlist[i].name, attr); msg_putchar(' '); @@ -4736,17 +4733,15 @@ static void init_syn_patterns(void) /// @return a pointer to the next argument, or NULL in case of an error. static char *get_syn_pattern(char *arg, synpat_T *ci) { - char *end; int *p; int idx; - char *cpo_save; // need at least three chars if (arg == NULL || arg[0] == NUL || arg[1] == NUL || arg[2] == NUL) { return NULL; } - end = skip_regexp(arg + 1, *arg, true); + char *end = skip_regexp(arg + 1, *arg, true); if (*end != *arg) { // end delimiter not found semsg(_("E401: Pattern delimiter not found: %s"), arg); return NULL; @@ -4755,7 +4750,7 @@ static char *get_syn_pattern(char *arg, synpat_T *ci) ci->sp_pattern = xstrnsave(arg + 1, (size_t)(end - arg) - 1); // Make 'cpoptions' empty, to avoid the 'l' flag - cpo_save = p_cpo; + char *cpo_save = p_cpo; p_cpo = empty_option; ci->sp_prog = vim_regcomp(ci->sp_pattern, RE_MAGIC); p_cpo = cpo_save; @@ -5145,7 +5140,6 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in { int retval; int16_t *scl_list; - int16_t item; int16_t id = ssp->id; static int depth = 0; int r; @@ -5181,7 +5175,7 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in // If the first item is "ALLBUT", return true if "id" is NOT in the // contains list. We also require that "id" is at the same ":syn include" // level as the list. - item = *list; + int16_t item = *list; if (item >= SYNID_ALLBUT && item < SYNID_CLUSTER) { if (item < SYNID_TOP) { // ALL or ALLBUT: accept all groups in the same file @@ -5291,9 +5285,6 @@ void ex_syntax(exarg_T *eap) void ex_ownsyntax(exarg_T *eap) { - char *old_value; - char *new_value; - if (curwin->w_s == &curwin->w_buffer->b_s) { curwin->w_s = xcalloc(1, sizeof(synblock_T)); hash_init(&curwin->w_s->b_keywtab); @@ -5309,7 +5300,7 @@ void ex_ownsyntax(exarg_T *eap) } // Save value of b:current_syntax. - old_value = get_var_value("b:current_syntax"); + char *old_value = get_var_value("b:current_syntax"); if (old_value != NULL) { old_value = xstrdup(old_value); } @@ -5318,7 +5309,7 @@ void ex_ownsyntax(exarg_T *eap) apply_autocmds(EVENT_SYNTAX, eap->arg, curbuf->b_fname, true, curbuf); // Move value of b:current_syntax to w:current_syntax. - new_value = get_var_value("b:current_syntax"); + char *new_value = get_var_value("b:current_syntax"); if (new_value != NULL) { set_internal_string_var("w:current_syntax", new_value); } @@ -5483,10 +5474,9 @@ int get_syntax_info(int *seqnrp) int syn_get_concealed_id(win_T *wp, linenr_T lnum, colnr_T col) { int seqnr; - int syntax_flags; (void)syn_get_id(wp, lnum, col, false, NULL, false); - syntax_flags = get_syntax_info(&seqnr); + int syntax_flags = get_syntax_info(&seqnr); if (syntax_flags & HL_CONCEAL) { return seqnr; diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 4fecbeebc3..774157831d 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -795,7 +795,6 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char { taggy_T *tagstack = curwin->w_tagstack; int tagstackidx = curwin->w_tagstackidx; - int i; char *p; char *command_end; tagptrs_T tagp; @@ -821,7 +820,7 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char taglen_advance(taglen); msg_puts_attr(_("file\n"), HL_ATTR(HLF_T)); - for (i = 0; i < num_matches && !got_int; i++) { + for (int i = 0; i < num_matches && !got_int; i++) { parse_match(matches[i], &tagp); if (!new_tag && ( (g_do_tagpreview != 0 @@ -980,7 +979,6 @@ static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char static int add_llist_tags(char *tag, int num_matches, char **matches) { char tag_name[128 + 1]; - int i; char *p; tagptrs_T tagp; @@ -988,7 +986,7 @@ static int add_llist_tags(char *tag, int num_matches, char **matches) char *cmd = xmalloc(CMDBUFFSIZE + 1); list_T *list = tv_list_alloc(0); - for (i = 0; i < num_matches; i++) { + for (int i = 0; i < num_matches; i++) { dict_T *dict; parse_match(matches[i], &tagp); @@ -1119,7 +1117,6 @@ static void taglen_advance(int l) // Print the tag stack void do_tags(exarg_T *eap) { - int i; char *name; taggy_T *tagstack = curwin->w_tagstack; int tagstackidx = curwin->w_tagstackidx; @@ -1127,7 +1124,7 @@ void do_tags(exarg_T *eap) // Highlight title msg_puts_title(_("\n # TO tag FROM line in file/text")); - for (i = 0; i < tagstacklen; i++) { + for (int i = 0; i < tagstacklen; i++) { if (tagstack[i].tagname != NULL) { name = fm_getname(&(tagstack[i].fmark), 30); if (name == NULL) { // file name not available @@ -1731,8 +1728,6 @@ static tagmatch_status_T findtags_parse_line(findtags_state_T *st, tagptrs_T *ta // For "normal" tags: Do a quick check if the tag matches. // This speeds up tag searching a lot! if (st->orgpat->headlen) { - int i; - int tagcmp; CLEAR_FIELD(*tagpp); tagpp->tagname = st->lbuf; tagpp->tagname_end = vim_strchr(st->lbuf, TAB); @@ -1754,8 +1749,9 @@ static tagmatch_status_T findtags_parse_line(findtags_state_T *st, tagptrs_T *ta } if (st->state == TS_BINARY) { + int tagcmp; // Simplistic check for unsorted tags file. - i = (int)tagpp->tagname[0]; + int i = (int)tagpp->tagname[0]; if (margs->sortic) { i = TOUPPER_ASC(tagpp->tagname[0]); } @@ -2245,7 +2241,6 @@ static int findtags_copy_matches(findtags_state_T *st, char ***matchesp) const bool name_only = (st->flags & TAG_NAMES); char **matches; int mtt; - int i; char *mfp; char *p; @@ -2256,7 +2251,7 @@ static int findtags_copy_matches(findtags_state_T *st, char ***matchesp) } st->match_count = 0; for (mtt = 0; mtt < MT_COUNT; mtt++) { - for (i = 0; i < st->ga_match[mtt].ga_len; i++) { + for (int i = 0; i < st->ga_match[mtt].ga_len; i++) { mfp = ((char **)(st->ga_match[mtt].ga_data))[i]; if (matches == NULL) { xfree(mfp); @@ -2731,7 +2726,6 @@ static int parse_match(char *lbuf, tagptrs_T *tagp) // Try to find a kind field: "kind:" or just "" p = tagp->command; if (find_extra(&p) == OK) { - char *pc; tagp->command_end = p; if (p > tagp->command && p[-1] == '|') { tagp->command_end = p - 1; // drop trailing bar @@ -2752,7 +2746,7 @@ static int parse_match(char *lbuf, tagptrs_T *tagp) break; } - pc = vim_strchr(p, ':'); + char *pc = vim_strchr(p, ':'); pt = vim_strchr(p, '\t'); if (pc == NULL || (pt != NULL && pc > pt)) { tagp->tagkind = p; @@ -3435,15 +3429,12 @@ static void get_tag_details(taggy_T *tag, dict_T *retdict) // 'retdict'. void get_tagstack(win_T *wp, dict_T *retdict) { - list_T *l; - int i; - tv_dict_add_nr(retdict, S_LEN("length"), wp->w_tagstacklen); tv_dict_add_nr(retdict, S_LEN("curidx"), wp->w_tagstackidx + 1); - l = tv_list_alloc(2); + list_T *l = tv_list_alloc(2); tv_dict_add_list(retdict, S_LEN("items"), l); - for (i = 0; i < wp->w_tagstacklen; i++) { + for (int i = 0; i < wp->w_tagstacklen; i++) { dict_T *d = tv_dict_alloc(); tv_list_append_dict(l, d); get_tag_details(&wp->w_tagstack[i], d); diff --git a/src/nvim/textformat.c b/src/nvim/textformat.c index 69cc0e046b..05e57e4b8f 100644 --- a/src/nvim/textformat.c +++ b/src/nvim/textformat.c @@ -633,19 +633,16 @@ static bool paragraph_start(linenr_T lnum) /// @param prev_line may start in previous line void auto_format(bool trailblank, bool prev_line) { - pos_T pos; colnr_T len; - char *old; char *new, *pnew; - int wasatend; int cc; if (!has_format_option(FO_AUTO)) { return; } - pos = curwin->w_cursor; - old = get_cursor_line_ptr(); + pos_T pos = curwin->w_cursor; + char *old = get_cursor_line_ptr(); // may remove added space check_auto_format(false); @@ -655,7 +652,7 @@ void auto_format(bool trailblank, bool prev_line) // in 'formatoptions' and there is a single character before the cursor. // Otherwise the line would be broken and when typing another non-white // next they are not joined back together. - wasatend = (pos.col == (colnr_T)strlen(old)); + int wasatend = (pos.col == (colnr_T)strlen(old)); if (*old != NUL && !trailblank && wasatend) { dec_cursor(); cc = gchar_cursor(); @@ -733,18 +730,16 @@ void auto_format(bool trailblank, bool prev_line) /// @param end_insert true when ending Insert mode void check_auto_format(bool end_insert) { - int c = ' '; - int cc; - if (!did_add_space) { return; } - cc = gchar_cursor(); + int cc = gchar_cursor(); if (!WHITECHAR(cc)) { // Somehow the space was removed already. did_add_space = false; } else { + int c = ' '; if (!end_insert) { inc_cursor(); c = gchar_cursor(); @@ -886,7 +881,6 @@ void op_formatexpr(oparg_T *oap) int fex_format(linenr_T lnum, long count, int c) { int use_sandbox = was_set_insecurely(curwin, "formatexpr", OPT_LOCAL); - int r; // Set v:lnum to the first line number and v:count to the number of lines. // Set v:char to the character to be inserted (can be NUL). @@ -900,7 +894,7 @@ int fex_format(linenr_T lnum, long count, int c) if (use_sandbox) { sandbox++; } - r = (int)eval_to_number(fex); + int r = (int)eval_to_number(fex); if (use_sandbox) { sandbox--; } -- cgit From c2375efe56b3918f83ee143f48fb7a763fa50289 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 12 Feb 2023 17:32:49 +0800 Subject: fix(ui): make sure screen is valid after resizing Problem: When not inside an Ex command, screen_resize() calls update_screen(), which calls screenclear() and set the screen as valid. However, when inside an Ex command, redrawing is postponed so update_screen() screen doesn't do anything, and the screen is still invalid after the resize, causing ui_comp_raw_line() to be no-op until update_screen() is called on the main loop. Solution: Restore the call to screenclear() inside screen_resize() so that the screen is invalid after screen_resize(). Since screenclear() changes redraw type from UPD_CLEAR to UPD_NOT_VALID, it is called at most once for each resize, so this shouldn't change how much code is run in the common (not inside an Ex command) case. --- src/nvim/drawscreen.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 2bc335a7e0..814d443031 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -318,6 +318,10 @@ void screen_resize(int width, int height) resizing_autocmd = false; redraw_all_later(UPD_CLEAR); + if (State != MODE_ASKMORE && State != MODE_EXTERNCMD && State != MODE_CONFIRM) { + screenclear(); + } + if (starting != NO_SCREEN) { maketitle(); -- cgit From 41ebe41b62921142bb486e5f30bd2fa9f53f1700 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 12 Feb 2023 19:02:14 +0800 Subject: fix(ui-ext): force cursor update after resize in char-based UI Neither ui/screen.lua nor Neovim Qt keep cursor position after resizing. --- src/nvim/api/ui.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 3ad625234c..8f5465db77 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -645,6 +645,8 @@ void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height) Array args = data->call_buf; if (ui->ui_ext[kUILinegrid]) { ADD_C(args, INTEGER_OBJ(grid)); + } else { + data->client_col = -1; // force cursor update } ADD_C(args, INTEGER_OBJ(width)); ADD_C(args, INTEGER_OBJ(height)); -- cgit From bb9c673d2cf022e75d1d34d2b2dd12a1e41dc6ac Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 13 Feb 2023 20:04:54 +0100 Subject: ci: automatically maximize MIN_LOG_LEVEL if CI detected (#22248) Detect if on CI by checking that the CI environment variable is set to "true". This is a common pattern among CI providers, including github actions and cirrus. --- src/nvim/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 7409a5e5c5..a193af6d51 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -412,6 +412,9 @@ else() endif() # Log level (MIN_LOG_LEVEL in log.h) +if($ENV{CI} MATCHES "true") + set(MIN_LOG_LEVEL 3) +endif() if("${MIN_LOG_LEVEL}" MATCHES "^$") # Minimize logging for release-type builds. target_compile_definitions(main_lib INTERFACE MIN_LOG_LEVEL=$,1,3>) -- cgit From 1d6bb0892b58e5a4183e74c0fbd2dc20204e33a4 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 13 Feb 2023 20:55:49 +0100 Subject: build: remove ENABLE_COMPILER_SUGGESTIONS option (#22249) We need higher level and more meaningful cmake options. Having a cmake option for only controlling compiler flags is probably not worth it as the same can be achieved with: cmake -B build -D CMAKE_C_FLAGS= --- src/nvim/CMakeLists.txt | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index a193af6d51..22cbec0d06 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -105,30 +105,6 @@ if(HAVE_WIMPLICIT_FALLTHROUGH_FLAG) target_compile_options(main_lib INTERFACE -Wimplicit-fallthrough) endif() -option(ENABLE_COMPILER_SUGGESTIONS "Enable -Wsuggest compiler warnings" OFF) -if(ENABLE_COMPILER_SUGGESTIONS) - # Clang doesn't have -Wsuggest-attribute so check for each one. - check_c_compiler_flag(-Wsuggest-attribute=pure HAVE_WSUGGEST_ATTRIBUTE_PURE) - if(HAVE_WSUGGEST_ATTRIBUTE_PURE) - target_compile_options(main_lib INTERFACE -Wsuggest-attribute=pure) - endif() - - check_c_compiler_flag(-Wsuggest-attribute=const HAVE_WSUGGEST_ATTRIBUTE_CONST) - if(HAVE_WSUGGEST_ATTRIBUTE_CONST) - target_compile_options(main_lib INTERFACE -Wsuggest-attribute=const) - endif() - - check_c_compiler_flag(-Wsuggest-attribute=malloc HAVE_WSUGGEST_ATTRIBUTE_MALLOC) - if(HAVE_WSUGGEST_ATTRIBUTE_MALLOC) - target_compile_options(main_lib INTERFACE -Wsuggest-attribute=malloc) - endif() - - check_c_compiler_flag(-Wsuggest-attribute=cold HAVE_WSUGGEST_ATTRIBUTE_COLD) - if(HAVE_WSUGGEST_ATTRIBUTE_COLD) - target_compile_options(main_lib INTERFACE -Wsuggest-attribute=cold) - endif() -endif() - if(MINGW) # Use POSIX compatible stdio in Mingw target_compile_definitions(main_lib INTERFACE __USE_MINGW_ANSI_STDIO) -- cgit From 820430dc0bb84011edae801262e64a10be7ebb9d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 13 Feb 2023 16:33:20 +0800 Subject: fix(tui): exit on input eof --- src/nvim/os/input.c | 7 +------ src/nvim/tui/input.c | 3 ++- src/nvim/tui/tui.c | 4 ++-- src/nvim/ui_client.c | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 44ad0315a5..d472836d0a 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -470,11 +470,6 @@ static InbufPollResult inbuf_poll(int ms, MultiQueue *events) return input_eof ? kInputEof : kInputNone; } -void input_done(void) -{ - input_eof = true; -} - bool input_available(void) { return rbuffer_size(input_buffer) != 0; @@ -483,7 +478,7 @@ bool input_available(void) static void input_read_cb(Stream *stream, RBuffer *buf, size_t c, void *data, bool at_eof) { if (at_eof) { - input_done(); + input_eof = true; } assert(rbuffer_space(input_buffer) >= rbuffer_size(buf)); diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 733aa25f03..c992253e1f 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -185,8 +185,9 @@ void tinput_stop(TermInput *input) } static void tinput_done_event(void **argv) + FUNC_ATTR_NORETURN { - input_done(); + os_exit(1); } static void tinput_wait_enqueue(void **argv) diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 9415917e34..f7bc931e21 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -167,7 +167,7 @@ static bool cursor_style_enabled = false; # include "tui/tui.c.generated.h" #endif -TUIData *tui_start(int *width, int *height, char **term) +void tui_start(TUIData **tui_p, int *width, int *height, char **term) { TUIData *tui = xcalloc(1, sizeof(TUIData)); tui->is_starting = true; @@ -190,11 +190,11 @@ TUIData *tui_start(int *width, int *height, char **term) uv_timer_start(&tui->startup_delay_timer, after_startup_cb, 100, 0); + *tui_p = tui; loop_poll_events(&main_loop, 1); *width = tui->width; *height = tui->height; *term = tui->term; - return tui; } void tui_enable_extkeys(TUIData *tui) diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index a7a85bf61f..df0a26c6ee 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -113,7 +113,7 @@ void ui_client_run(bool remote_ui) ui_client_is_remote = remote_ui; int width, height; char *term; - tui = tui_start(&width, &height, &term); + tui_start(&tui, &width, &height, &term); ui_client_attach(width, height, term); -- cgit From 20c9f4b3521fa7ab5c5997c0ec1a3df2b5bd0dbe Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 14 Feb 2023 08:29:05 +0800 Subject: vim-patch:9.0.1307: setting 'formatoptions' with :let doesn't check for errors (#22252) Problem: Setting 'formatoptions' with :let doesn't check for errors. Solution: Pass "errbuf" to set_string_option(). (Yegappan Lakshmanan, closes vim/vim#11974, closes vim/vim#11972) https://github.com/vim/vim/commit/32ff96ef018eb1a5bea0953648b4892a6ee71658 Co-authored-by: Yegappan Lakshmanan --- src/nvim/option.c | 6 ++++-- src/nvim/optionstr.c | 5 +++-- src/nvim/testdir/test_options.vim | 41 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index 26466c2869..5ece5e4e5d 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3084,6 +3084,8 @@ char *set_option_value(const char *const name, const long number, const char *co const int opt_flags) FUNC_ATTR_NONNULL_ARG(1) { + static char errbuf[80]; + if (is_tty_option(name)) { return NULL; // Fail silently; many old vimrcs set t_xx options. } @@ -3106,7 +3108,7 @@ char *set_option_value(const char *const name, const long number, const char *co if (s == NULL || opt_flags & OPT_CLEAR) { s = ""; } - return set_string_option(opt_idx, s, opt_flags); + return set_string_option(opt_idx, s, opt_flags, errbuf, sizeof(errbuf)); } char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags); @@ -3144,7 +3146,7 @@ char *set_option_value(const char *const name, const long number, const char *co } } if (flags & P_NUM) { - return set_num_option(opt_idx, varp, numval, NULL, 0, opt_flags); + return set_num_option(opt_idx, varp, numval, errbuf, sizeof(errbuf), opt_flags); } return set_bool_option(opt_idx, (char *)varp, (int)numval, opt_flags); } diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 5f8514b1a6..f903ad3d09 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -410,7 +410,8 @@ void set_string_option_direct_in_win(win_T *wp, const char *name, int opt_idx, c /// #OPT_GLOBAL. /// /// @return NULL on success, an untranslated error message on error. -char *set_string_option(const int opt_idx, const char *const value, const int opt_flags) +char *set_string_option(const int opt_idx, const char *const value, const int opt_flags, + char *const errbuf, const size_t errbuflen) FUNC_ATTR_NONNULL_ARG(2) FUNC_ATTR_WARN_UNUSED_RESULT { vimoption_T *opt = get_option(opt_idx); @@ -442,7 +443,7 @@ char *set_string_option(const int opt_idx, const char *const value, const int op int value_checked = false; char *const errmsg = did_set_string_option(opt_idx, varp, oldval, - NULL, 0, + errbuf, errbuflen, opt_flags, &value_checked); if (errmsg == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index f51de94bac..43cc3632e6 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -434,6 +434,8 @@ func Test_set_errors() call assert_fails('set fileencoding=latin1', 'E21:') set modifiable& " call assert_fails('set t_#-&', 'E522:') + call assert_fails('let &formatoptions = "?"', 'E539:') + call assert_fails('call setbufvar("", "&formatoptions", "?")', 'E539:') endfunc func CheckWasSet(name) @@ -1300,5 +1302,44 @@ func Test_endoffile_default() call delete('Xtestout') endfunc +" Test for setting the 'lines' and 'columns' options to a minimum value +func Test_set_min_lines_columns() + let save_lines = &lines + let save_columns = &columns + + let after =<< trim END + set laststatus=1 + set nomore + let msg = [] + let v:errmsg = '' + silent! let &columns=0 + call add(msg, v:errmsg) + silent! set columns=0 + call add(msg, v:errmsg) + silent! call setbufvar('', '&columns', 0) + call add(msg, v:errmsg) + "call writefile(msg, 'XResultsetminlines') + silent! let &lines=0 + call add(msg, v:errmsg) + silent! set lines=0 + call add(msg, v:errmsg) + silent! call setbufvar('', '&lines', 0) + call add(msg, v:errmsg) + call writefile(msg, 'XResultsetminlines') + qall! + END + if RunVim([], after, '') + call assert_equal(['E594: Need at least 12 columns', + \ 'E594: Need at least 12 columns: columns=0', + \ 'E594: Need at least 12 columns', + \ 'E593: Need at least 2 lines', + \ 'E593: Need at least 2 lines: lines=0', + \ 'E593: Need at least 2 lines',], readfile('XResultsetminlines')) + endif + + call delete('XResultsetminlines') + let &lines = save_lines + let &columns = save_columns +endfunc " vim: shiftwidth=2 sts=2 expandtab -- cgit From 53968082675cd3b8d1809e53a47c0311b7347ef9 Mon Sep 17 00:00:00 2001 From: luukvbaal <31730729+luukvbaal@users.noreply.github.com> Date: Tue, 14 Feb 2023 08:52:22 +0100 Subject: fix(folds): cursorline highlight is not always applied on closed folds (#22242) Problem: The cursorline highlight logic checks for `w_cursor.lnum` which may be different from the line number passed to `win_line()` even when the cursor is actually on that line. Solution: Update cursor line highlight logic to check for the line number of the start of a closed fold if necessary. --- src/nvim/buffer_defs.h | 9 ++++++--- src/nvim/drawline.c | 39 ++++++++++++++++++--------------------- src/nvim/drawscreen.c | 20 +++++++++++++++----- 3 files changed, 39 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 3601dc7062..cace4b1364 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1112,20 +1112,23 @@ struct window_S { win_T *w_prev; ///< link to previous window win_T *w_next; ///< link to next window bool w_closing; ///< window is being closed, don't let - /// autocommands close it too. + ///< autocommands close it too. frame_T *w_frame; ///< frame containing this window pos_T w_cursor; ///< cursor position in buffer colnr_T w_curswant; ///< Column we want to be at. This is - /// used to try to stay in the same column - /// for up/down cursor motions. + ///< used to try to stay in the same column + ///< for up/down cursor motions. int w_set_curswant; // If set, then update w_curswant the next // time through cursupdate() to the // current virtual column + linenr_T w_cursorline; ///< Where 'cursorline' should be drawn, + ///< can be different from w_cursor.lnum + ///< for closed folds. linenr_T w_last_cursorline; ///< where last 'cursorline' was drawn pos_T w_last_cursormoved; ///< for CursorMoved event diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index e205850314..3bd55dbe09 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -303,7 +303,7 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, static bool use_cursor_line_sign(win_T *wp, linenr_T lnum) { return wp->w_p_cul - && lnum == wp->w_cursor.lnum + && lnum == wp->w_cursorline && (wp->w_p_culopt_flags & CULOPT_NBR); } @@ -517,7 +517,7 @@ static void get_statuscol_display_info(statuscol_T *stcp, LineDrawState *draw_st static bool use_cursor_line_nr(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines) { return wp->w_p_cul - && lnum == wp->w_cursor.lnum + && lnum == wp->w_cursorline && (wp->w_p_culopt_flags & CULOPT_NBR) && (row == startrow + filler_lines || (row > startrow + filler_lines @@ -547,6 +547,12 @@ static inline void get_line_number_str(win_T *wp, linenr_T lnum, char *buf, size static int get_line_number_attr(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines) { + if (use_cursor_line_nr(wp, lnum, row, startrow, filler_lines)) { + // TODO(vim): Can we use CursorLine instead of CursorLineNr + // when CursorLineNr isn't set? + return win_hl_attr(wp, HLF_CLN); + } + if (wp->w_p_rnu) { if (lnum < wp->w_cursor.lnum) { // Use LineNrAbove @@ -558,12 +564,6 @@ static int get_line_number_attr(win_T *wp, linenr_T lnum, int row, int startrow, } } - if (use_cursor_line_nr(wp, lnum, row, startrow, filler_lines)) { - // TODO(vim): Can we use CursorLine instead of CursorLineNr - // when CursorLineNr isn't set? - return win_hl_attr(wp, HLF_CLN); - } - return win_hl_attr(wp, HLF_N); } @@ -960,20 +960,17 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, filler_todo = filler_lines; // Cursor line highlighting for 'cursorline' in the current window. - if (lnum == wp->w_cursor.lnum) { - // Do not show the cursor line in the text when Visual mode is active, - // because it's not clear what is selected then. - if (wp->w_p_cul && !(wp == curwin && VIsual_active) - && wp->w_p_culopt_flags != CULOPT_NBR) { - cul_screenline = (wp->w_p_wrap - && (wp->w_p_culopt_flags & CULOPT_SCRLINE)); - if (!cul_screenline) { - apply_cursorline_highlight(wp, lnum, &line_attr, &cul_attr, &line_attr_lowprio); - } else { - margin_columns_win(wp, &left_curline_col, &right_curline_col); - } - area_highlighting = true; + if (wp->w_p_cul && wp->w_p_culopt_flags != CULOPT_NBR && lnum == wp->w_cursorline + // Do not show the cursor line in the text when Visual mode is active, + // because it's not clear what is selected then. + && !(wp == curwin && VIsual_active)) { + cul_screenline = (wp->w_p_wrap && (wp->w_p_culopt_flags & CULOPT_SCRLINE)); + if (!cul_screenline) { + apply_cursorline_highlight(wp, lnum, &line_attr, &cul_attr, &line_attr_lowprio); + } else { + margin_columns_win(wp, &left_curline_col, &right_curline_col); } + area_highlighting = true; } SignTextAttrs sattrs[SIGN_SHOW_MAX]; // sign attributes for the sign column diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 814d443031..2c0b6ea3b0 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -1552,7 +1552,15 @@ static void win_update(win_T *wp, DecorProviders *providers) wp->w_old_visual_col = 0; } - bool cursorline_standout = win_cursorline_standout(wp); + foldinfo_T cursorline_fi; + wp->w_cursorline = win_cursorline_standout(wp) ? wp->w_cursor.lnum : 0; + if (wp->w_p_cul) { + // Make sure that the cursorline on a closed fold is redrawn + cursorline_fi = fold_info(wp, wp->w_cursor.lnum); + if (cursorline_fi.fi_level > 0 && cursorline_fi.fi_lines > 0) { + wp->w_cursorline = cursorline_fi.fi_lnum; + } + } win_check_ns_hl(wp); @@ -1608,7 +1616,7 @@ static void win_update(win_T *wp, DecorProviders *providers) // if lines were inserted or deleted || (wp->w_match_head != NULL && buf->b_mod_xlines != 0))))) - || (cursorline_standout && lnum == wp->w_cursor.lnum) + || lnum == wp->w_cursorline || lnum == wp->w_last_cursorline) { if (lnum == mod_top) { top_to_mod = false; @@ -1759,7 +1767,8 @@ static void win_update(win_T *wp, DecorProviders *providers) // When lines are folded, display one line for all of them. // Otherwise, display normally (can be several display lines when // 'wrap' is on). - foldinfo_T foldinfo = fold_info(wp, lnum); + foldinfo_T foldinfo = wp->w_p_cul && lnum == wp->w_cursor.lnum ? + cursorline_fi : fold_info(wp, lnum); if (foldinfo.fi_lines == 0 && idx < wp->w_lines_valid @@ -1818,7 +1827,8 @@ static void win_update(win_T *wp, DecorProviders *providers) if (wp->w_p_rnu && wp->w_last_cursor_lnum_rnu != wp->w_cursor.lnum) { // 'relativenumber' set and cursor moved vertically: The // text doesn't need to be drawn, but the number column does. - foldinfo_T info = fold_info(wp, lnum); + foldinfo_T info = wp->w_p_cul && lnum == wp->w_cursor.lnum ? + cursorline_fi : fold_info(wp, lnum); (void)win_line(wp, lnum, srow, wp->w_grid.rows, true, true, info, &line_providers, &provider_err); } @@ -1853,7 +1863,7 @@ static void win_update(win_T *wp, DecorProviders *providers) // Now that the window has been redrawn with the old and new cursor line, // update w_last_cursorline. - wp->w_last_cursorline = cursorline_standout ? wp->w_cursor.lnum : 0; + wp->w_last_cursorline = wp->w_cursorline; wp->w_last_cursor_lnum_rnu = wp->w_p_rnu ? wp->w_cursor.lnum : 0; -- cgit From 46a87a5d2bac598fed0870f0d3c926087f95d30f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Feb 2023 05:19:04 -0500 Subject: refactor(api): VALIDATE macros #22187 Problem: - API validation involves too much boilerplate. - API validation errors are not consistently worded. Solution: Introduce some macros. Currently these are clumsy, but they at least help with consistency and avoid some nesting. --- src/nvim/api/autocmd.c | 229 ++++++++++++++-------------------- src/nvim/api/buffer.c | 153 +++++++++-------------- src/nvim/api/command.c | 63 +++++----- src/nvim/api/extmark.c | 268 ++++++++++++++++++++-------------------- src/nvim/api/options.c | 128 ++++++++----------- src/nvim/api/private/helpers.c | 30 +++++ src/nvim/api/private/validate.h | 69 +++++++++++ src/nvim/api/vim.c | 171 ++++++++++--------------- src/nvim/option.c | 6 +- src/nvim/ui.c | 9 +- 10 files changed, 539 insertions(+), 587 deletions(-) create mode 100644 src/nvim/api/private/validate.h (limited to 'src') diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index f801c716e5..9aadd48a13 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -12,6 +12,7 @@ #include "nvim/api/autocmd.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" @@ -107,22 +108,21 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) break; case kObjectTypeString: group = augroup_find(opts->group.data.string.data); - if (group < 0) { - api_set_error(err, kErrorTypeValidation, "invalid augroup passed."); + VALIDATE_S((group >= 0), "group", "", { goto cleanup; - } + }); break; case kObjectTypeInteger: group = (int)opts->group.data.integer; char *name = augroup_name(group); - if (!augroup_exists(name)) { - api_set_error(err, kErrorTypeValidation, "invalid augroup passed."); + VALIDATE_S(augroup_exists(name), "group", "", { goto cleanup; - } + }); break; default: - api_set_error(err, kErrorTypeValidation, "group must be a string or an integer."); - goto cleanup; + VALIDATE_S(false, "group (must be string or integer)", "", { + goto cleanup; + }); } if (opts->event.type != kObjectTypeNil) { @@ -134,29 +134,24 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) event_set[event_nr] = true; } else if (v.type == kObjectTypeArray) { FOREACH_ITEM(v.data.array, event_v, { - if (event_v.type != kObjectTypeString) { - api_set_error(err, - kErrorTypeValidation, - "Every event must be a string in 'event'"); + VALIDATE_T("event item", kObjectTypeString, event_v.type, { goto cleanup; - } + }); GET_ONE_EVENT(event_nr, event_v, cleanup); event_set[event_nr] = true; }) } else { - api_set_error(err, - kErrorTypeValidation, - "Not a valid 'event' value. Must be a string or an array"); - goto cleanup; + VALIDATE_S(false, "event (must be String or Array)", "", { + goto cleanup; + }); } } - if (opts->pattern.type != kObjectTypeNil && opts->buffer.type != kObjectTypeNil) { - api_set_error(err, kErrorTypeValidation, - "Cannot use both 'pattern' and 'buffer'"); + VALIDATE((opts->pattern.type == kObjectTypeNil || opts->buffer.type == kObjectTypeNil), + "Cannot use both 'pattern' and 'buffer'", { goto cleanup; - } + }); int pattern_filter_count = 0; if (opts->pattern.type != kObjectTypeNil) { @@ -166,25 +161,23 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) pattern_filter_count += 1; } else if (v.type == kObjectTypeArray) { if (v.data.array.size > AUCMD_MAX_PATTERNS) { - api_set_error(err, kErrorTypeValidation, - "Too many patterns. Please limit yourself to %d or fewer", + api_set_error(err, kErrorTypeValidation, "Too many patterns (maximum of %d)", AUCMD_MAX_PATTERNS); goto cleanup; } FOREACH_ITEM(v.data.array, item, { - if (item.type != kObjectTypeString) { - api_set_error(err, kErrorTypeValidation, "Invalid value for 'pattern': must be a string"); + VALIDATE_T("pattern", kObjectTypeString, item.type, { goto cleanup; - } + }); pattern_filters[pattern_filter_count] = item.data.string.data; pattern_filter_count += 1; }); } else { - api_set_error(err, kErrorTypeValidation, - "Not a valid 'pattern' value. Must be a string or an array"); - goto cleanup; + VALIDATE_EXP(false, "pattern", "String or Array", api_typename(v.type), { + goto cleanup; + }); } } @@ -198,17 +191,16 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) ADD(buffers, CSTR_TO_OBJ(pattern_buflocal)); } else if (opts->buffer.type == kObjectTypeArray) { if (opts->buffer.data.array.size > AUCMD_MAX_PATTERNS) { - api_set_error(err, - kErrorTypeValidation, - "Too many buffers. Please limit yourself to %d or fewer", AUCMD_MAX_PATTERNS); + api_set_error(err, kErrorTypeValidation, "Too many buffers (maximum of %d)", + AUCMD_MAX_PATTERNS); goto cleanup; } FOREACH_ITEM(opts->buffer.data.array, bufnr, { - if (bufnr.type != kObjectTypeInteger && bufnr.type != kObjectTypeBuffer) { - api_set_error(err, kErrorTypeValidation, "Invalid value for 'buffer': must be an integer"); + VALIDATE_EXP((bufnr.type == kObjectTypeInteger || bufnr.type == kObjectTypeBuffer), + "buffer", "Integer", api_typename(bufnr.type), { goto cleanup; - } + }); buf_T *buf = find_buffer_by_handle((Buffer)bufnr.data.integer, err); if (ERROR_SET(err)) { @@ -219,9 +211,9 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) ADD(buffers, CSTR_TO_OBJ(pattern_buflocal)); }); } else if (opts->buffer.type != kObjectTypeNil) { - api_set_error(err, kErrorTypeValidation, - "Invalid value for 'buffer': must be an integer or array of integers"); - goto cleanup; + VALIDATE_EXP(false, "buffer", "Integer or Array", api_typename(opts->buffer.type), { + goto cleanup; + }); } FOREACH_ITEM(buffers, bufnr, { @@ -432,30 +424,23 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc goto cleanup; } - if (opts->callback.type != kObjectTypeNil && opts->command.type != kObjectTypeNil) { - api_set_error(err, kErrorTypeValidation, "specify either 'callback' or 'command', not both"); + VALIDATE((opts->callback.type == kObjectTypeNil || opts->command.type == kObjectTypeNil), + "Cannot use both 'callback' and 'command'", { goto cleanup; - } else if (opts->callback.type != kObjectTypeNil) { - // TODO(tjdevries): It's possible we could accept callable tables, - // but we don't do that many other places, so for the moment let's - // not do that. + }); + + if (opts->callback.type != kObjectTypeNil) { + // NOTE: We could accept callable tables, but that isn't common in the API. Object *callback = &opts->callback; switch (callback->type) { case kObjectTypeLuaRef: - if (callback->data.luaref == LUA_NOREF) { - api_set_error(err, - kErrorTypeValidation, - "must pass an actual value"); + VALIDATE_S((callback->data.luaref != LUA_NOREF), "callback", "", { goto cleanup; - } - - if (!nlua_ref_is_function(callback->data.luaref)) { - api_set_error(err, - kErrorTypeValidation, - "must pass a function for callback"); + }); + VALIDATE_S(nlua_ref_is_function(callback->data.luaref), "callback", "", { goto cleanup; - } + }); cb.type = kCallbackLua; cb.data.luaref = api_new_luaref(callback->data.luaref); @@ -465,28 +450,25 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc cb.data.funcref = string_to_cstr(callback->data.string); break; default: - api_set_error(err, - kErrorTypeException, - "'callback' must be a lua function or name of vim function"); - goto cleanup; + VALIDATE_EXP(false, "callback", "Lua function or Vim function name", + api_typename(callback->type), { + goto cleanup; + }); } aucmd.type = CALLABLE_CB; aucmd.callable.cb = cb; } else if (opts->command.type != kObjectTypeNil) { Object *command = &opts->command; - if (command->type == kObjectTypeString) { - aucmd.type = CALLABLE_EX; - aucmd.callable.cmd = string_to_cstr(command->data.string); - } else { - api_set_error(err, - kErrorTypeValidation, - "'command' must be a string"); + VALIDATE_T("command", kObjectTypeString, command->type, { goto cleanup; - } + }); + aucmd.type = CALLABLE_EX; + aucmd.callable.cmd = string_to_cstr(command->data.string); } else { - api_set_error(err, kErrorTypeValidation, "must pass one of: 'command', 'callback'"); - goto cleanup; + VALIDATE_S(false, "'command' or 'callback' is required", "", { + goto cleanup; + }); } bool is_once = api_object_to_bool(opts->once, "once", false, err); @@ -502,24 +484,19 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc } if (opts->desc.type != kObjectTypeNil) { - if (opts->desc.type == kObjectTypeString) { - desc = opts->desc.data.string.data; - } else { - api_set_error(err, - kErrorTypeValidation, - "'desc' must be a string"); + VALIDATE_T("desc", kObjectTypeString, opts->desc.type, { goto cleanup; - } + }); + desc = opts->desc.data.string.data; } if (patterns.size == 0) { ADD(patterns, STRING_OBJ(STATIC_CSTR_TO_STRING("*"))); } - if (event_array.size == 0) { - api_set_error(err, kErrorTypeValidation, "'event' is a required key"); + VALIDATE_R((event_array.size != 0), "event", { goto cleanup; - } + }); autocmd_id = next_autocmd_id++; FOREACH_ITEM(event_array, event_str, { @@ -564,10 +541,9 @@ cleanup: void nvim_del_autocmd(Integer id, Error *err) FUNC_API_SINCE(9) { - if (id <= 0) { - api_set_error(err, kErrorTypeException, "Invalid autocmd id"); + VALIDATE_INT((id > 0), "autocmd id", id, { return; - } + }); if (!autocmd_delete_id(id)) { api_set_error(err, kErrorTypeException, "Failed to delete autocmd"); } @@ -610,11 +586,10 @@ void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Error *err) goto cleanup; } - if (opts->pattern.type != kObjectTypeNil && opts->buffer.type != kObjectTypeNil) { - api_set_error(err, kErrorTypeValidation, - "Cannot use both 'pattern' and 'buffer'"); + VALIDATE((opts->pattern.type == kObjectTypeNil || opts->buffer.type == kObjectTypeNil), + "Cannot use both 'pattern' and 'buffer'", { goto cleanup; - } + }); int au_group = get_augroup_from_object(opts->group, err); if (au_group == AUGROUP_ERROR) { @@ -772,32 +747,29 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err) break; case kObjectTypeString: au_group = augroup_find(opts->group.data.string.data); - if (au_group == AUGROUP_ERROR) { - api_set_error(err, - kErrorTypeValidation, - "invalid augroup: %s", opts->group.data.string.data); + VALIDATE_S((au_group != AUGROUP_ERROR), "group", opts->group.data.string.data, { goto cleanup; - } + }); break; case kObjectTypeInteger: au_group = (int)opts->group.data.integer; char *name = augroup_name(au_group); - if (!augroup_exists(name)) { - api_set_error(err, kErrorTypeValidation, "invalid augroup: %d", au_group); + VALIDATE_INT(augroup_exists(name), "group", (int64_t)au_group, { goto cleanup; - } + }); break; default: - api_set_error(err, kErrorTypeValidation, "'group' must be a string or an integer."); - goto cleanup; + VALIDATE_EXP(false, "group", "String or Integer", api_typename(opts->group.type), { + goto cleanup; + }); } if (opts->buffer.type != kObjectTypeNil) { Object buf_obj = opts->buffer; - if (buf_obj.type != kObjectTypeInteger && buf_obj.type != kObjectTypeBuffer) { - api_set_error(err, kErrorTypeException, "invalid buffer: %d", buf_obj.type); + VALIDATE_EXP((buf_obj.type == kObjectTypeInteger || buf_obj.type == kObjectTypeBuffer), + "buffer", "Integer", api_typename(buf_obj.type), { goto cleanup; - } + }); buf = find_buffer_by_handle((Buffer)buf_obj.data.integer, err); @@ -844,18 +816,15 @@ static bool check_autocmd_string_array(Array arr, char *k, Error *err) { FOREACH_ITEM(arr, entry, { if (entry.type != kObjectTypeString) { - api_set_error(err, - kErrorTypeValidation, - "All entries in '%s' must be strings", - k); + api_set_error(err, kErrorTypeValidation, "Invalid '%s' item type: expected String, got %s", + k, api_typename(entry.type)); return false; } // Disallow newlines in the middle of the line. const String l = entry.data.string; if (memchr(l.data, NL, l.size)) { - api_set_error(err, kErrorTypeValidation, - "String cannot contain newlines"); + api_set_error(err, kErrorTypeValidation, "'%s' item cannot contain newlines", k); return false; } }) @@ -873,10 +842,9 @@ static bool unpack_string_or_array(Array *array, Object *v, char *k, bool requir *array = copy_array(v->data.array, NULL); } else { if (required) { - api_set_error(err, - kErrorTypeValidation, - "'%s' must be an array or a string.", - k); + api_set_error(err, kErrorTypeValidation, + "Invalid '%s' type: expected Array or String, got %s", + k, api_typename(v->type)); return false; } } @@ -894,27 +862,22 @@ static int get_augroup_from_object(Object group, Error *err) return AUGROUP_DEFAULT; case kObjectTypeString: au_group = augroup_find(group.data.string.data); - if (au_group == AUGROUP_ERROR) { - api_set_error(err, - kErrorTypeValidation, - "invalid augroup: %s", group.data.string.data); - + VALIDATE_S((au_group != AUGROUP_ERROR), "group", group.data.string.data, { return AUGROUP_ERROR; - } + }); return au_group; case kObjectTypeInteger: au_group = (int)group.data.integer; char *name = augroup_name(au_group); - if (!augroup_exists(name)) { - api_set_error(err, kErrorTypeValidation, "invalid augroup: %d", au_group); + VALIDATE_INT(augroup_exists(name), "group", (int64_t)au_group, { return AUGROUP_ERROR; - } - + }); return au_group; default: - api_set_error(err, kErrorTypeValidation, "'group' must be a string or an integer."); - return AUGROUP_ERROR; + VALIDATE_EXP(false, "group", "String or Integer", api_typename(group.type), { + return AUGROUP_ERROR; + }); } } @@ -923,11 +886,12 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob { const char pattern_buflocal[BUFLOCAL_PAT_LEN]; - if (pattern.type != kObjectTypeNil && buffer.type != kObjectTypeNil) { - api_set_error(err, kErrorTypeValidation, - "cannot pass both: 'pattern' and 'buffer' for the same autocmd"); + VALIDATE((pattern.type == kObjectTypeNil || buffer.type == kObjectTypeNil), + "Cannot use both 'pattern' and 'buffer' for the same autocmd", { return false; - } else if (pattern.type != kObjectTypeNil) { + }); + + if (pattern.type != kObjectTypeNil) { Object *v = &pattern; if (v->type == kObjectTypeString) { @@ -956,18 +920,15 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob } }) } else { - api_set_error(err, - kErrorTypeValidation, - "'pattern' must be a string or table"); - return false; + VALIDATE_EXP(false, "pattern", "String or Table", api_typename(v->type), { + return false; + }); } } else if (buffer.type != kObjectTypeNil) { - if (buffer.type != kObjectTypeInteger && buffer.type != kObjectTypeBuffer) { - api_set_error(err, - kErrorTypeValidation, - "'buffer' must be an integer"); + VALIDATE_EXP((buffer.type == kObjectTypeInteger || buffer.type == kObjectTypeBuffer), + "buffer", "Integer", api_typename(buffer.type), { return false; - } + }); buf_T *buf = find_buffer_by_handle((Buffer)buffer.data.integer, err); if (ERROR_SET(err)) { diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index fe9e6077d6..b2e78db278 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -16,6 +16,7 @@ #include "nvim/api/buffer.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" @@ -179,11 +180,9 @@ Boolean nvim_buf_attach(uint64_t channel_id, Buffer buffer, Boolean send_buffer, if (is_lua) { for (size_t j = 0; cbs[j].name; j++) { if (strequal(cbs[j].name, k.data)) { - if (v->type != kObjectTypeLuaRef) { - api_set_error(err, kErrorTypeValidation, - "%s is not a function", cbs[j].name); + VALIDATE_T(cbs[j].name, kObjectTypeLuaRef, v->type, { goto error; - } + }); *(cbs[j].dest) = v->data.luaref; v->data.luaref = LUA_NOREF; key_used = true; @@ -194,26 +193,23 @@ Boolean nvim_buf_attach(uint64_t channel_id, Buffer buffer, Boolean send_buffer, if (key_used) { continue; } else if (strequal("utf_sizes", k.data)) { - if (v->type != kObjectTypeBoolean) { - api_set_error(err, kErrorTypeValidation, "utf_sizes must be boolean"); + VALIDATE_T("utf_sizes", kObjectTypeBoolean, v->type, { goto error; - } + }); cb.utf_sizes = v->data.boolean; key_used = true; } else if (strequal("preview", k.data)) { - if (v->type != kObjectTypeBoolean) { - api_set_error(err, kErrorTypeValidation, "preview must be boolean"); + VALIDATE_T("preview", kObjectTypeBoolean, v->type, { goto error; - } + }); cb.preview = v->data.boolean; key_used = true; } } - if (!key_used) { - api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); + VALIDATE_S(key_used, "key", k.data, { goto error; - } + }); } return buf_updates_register(buf, channel_id, cb, send_buffer); @@ -297,10 +293,9 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, start = normalize_index(buf, start, true, &oob); end = normalize_index(buf, end, true, &oob); - if (strict_indexing && oob) { - api_set_error(err, kErrorTypeValidation, "Index out of bounds"); + VALIDATE((!strict_indexing || !oob), "Index out of bounds", { return rv; - } + }); if (start >= end) { // Return 0-length array @@ -328,20 +323,15 @@ end: static bool check_string_array(Array arr, bool disallow_nl, Error *err) { for (size_t i = 0; i < arr.size; i++) { - if (arr.items[i].type != kObjectTypeString) { - api_set_error(err, - kErrorTypeValidation, - "All items in the replacement array must be strings"); + VALIDATE_T("replacement item", kObjectTypeString, arr.items[i].type, { return false; - } + }); // Disallow newlines in the middle of the line. if (disallow_nl) { const String l = arr.items[i].data.string; - if (memchr(l.data, NL, l.size)) { - api_set_error(err, kErrorTypeValidation, - "String cannot contain newlines"); + VALIDATE(!memchr(l.data, NL, l.size), "String cannot contain newlines", { return false; - } + }); } } return true; @@ -383,17 +373,12 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ start = normalize_index(buf, start, true, &oob); end = normalize_index(buf, end, true, &oob); - if (strict_indexing && oob) { - api_set_error(err, kErrorTypeValidation, "Index out of bounds"); + VALIDATE((!strict_indexing || !oob), "Index out of bounds", { return; - } - - if (start > end) { - api_set_error(err, - kErrorTypeValidation, - "Argument \"start\" is higher than \"end\""); + }); + VALIDATE((start <= end), "\"start\" is higher than \"end\"", { return; - } + }); bool disallow_nl = (channel_id != VIML_INTERNAL_CALL); if (!check_string_array(replacement, disallow_nl, err)) { @@ -453,10 +438,9 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ for (size_t i = 0; i < to_replace; i++) { int64_t lnum = start + (int64_t)i; - if (lnum >= MAXLNUM) { - api_set_error(err, kErrorTypeValidation, "Index value is too high"); + VALIDATE(lnum < MAXLNUM, "Index value is too high", { goto end; - } + }); if (ml_replace((linenr_T)lnum, lines[i], false) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to replace line"); @@ -473,10 +457,9 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ for (size_t i = to_replace; i < new_len; i++) { int64_t lnum = start + (int64_t)i - 1; - if (lnum >= MAXLNUM) { - api_set_error(err, kErrorTypeValidation, "Index value is too high"); + VALIDATE(lnum < MAXLNUM, "Index value is too high", { goto end; - } + }); if (ml_append((linenr_T)lnum, lines[i], 0, false) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to insert line"); @@ -563,16 +546,14 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In // check range is ordered and everything! // start_row, end_row within buffer len (except add text past the end?) start_row = normalize_index(buf, start_row, false, &oob); - if (oob) { - api_set_error(err, kErrorTypeValidation, "start_row out of bounds"); + VALIDATE((!oob), "start_row out of bounds", { return; - } + }); end_row = normalize_index(buf, end_row, false, &oob); - if (oob) { - api_set_error(err, kErrorTypeValidation, "end_row out of bounds"); + VALIDATE((!oob), "end_row out of bounds", { return; - } + }); char *str_at_start = NULL; char *str_at_end = NULL; @@ -580,23 +561,21 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In // Another call to ml_get_buf() may free the line, so make a copy. str_at_start = xstrdup(ml_get_buf(buf, (linenr_T)start_row, false)); size_t len_at_start = strlen(str_at_start); - if (start_col < 0 || (size_t)start_col > len_at_start) { - api_set_error(err, kErrorTypeValidation, "start_col out of bounds"); + VALIDATE((start_col >= 0 && (size_t)start_col <= len_at_start), "start_col out of bounds", { goto early_end; - } + }); // Another call to ml_get_buf() may free the line, so make a copy. str_at_end = xstrdup(ml_get_buf(buf, (linenr_T)end_row, false)); size_t len_at_end = strlen(str_at_end); - if (end_col < 0 || (size_t)end_col > len_at_end) { - api_set_error(err, kErrorTypeValidation, "end_col out of bounds"); + VALIDATE((end_col >= 0 && (size_t)end_col <= len_at_end), "end_col out of bounds", { goto early_end; - } + }); - if (start_row > end_row || (end_row == start_row && start_col > end_col)) { - api_set_error(err, kErrorTypeValidation, "start is higher than end"); + VALIDATE((start_row <= end_row && !(end_row == start_row && start_col > end_col)), + "start is higher than end", { goto early_end; - } + }); bool disallow_nl = (channel_id != VIML_INTERNAL_CALL); if (!check_string_array(replacement, disallow_nl, err)) { @@ -702,10 +681,9 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In for (size_t i = 0; i < to_replace; i++) { int64_t lnum = start_row + (int64_t)i; - if (lnum >= MAXLNUM) { - api_set_error(err, kErrorTypeValidation, "Index value is too high"); + VALIDATE((lnum < MAXLNUM), "Index value is too high", { goto end; - } + }); if (ml_replace((linenr_T)lnum, lines[i], false) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to replace line"); @@ -720,10 +698,9 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In for (size_t i = to_replace; i < new_len; i++) { int64_t lnum = start_row + (int64_t)i - 1; - if (lnum >= MAXLNUM) { - api_set_error(err, kErrorTypeValidation, "Index value is too high"); + VALIDATE((lnum < MAXLNUM), "Index value is too high", { goto end; - } + }); if (ml_append((linenr_T)lnum, lines[i], 0, false) == FAIL) { api_set_error(err, kErrorTypeException, "Failed to insert line"); @@ -800,10 +777,9 @@ ArrayOf(String) nvim_buf_get_text(uint64_t channel_id, Buffer buffer, { Array rv = ARRAY_DICT_INIT; - if (opts.size > 0) { - api_set_error(err, kErrorTypeValidation, "opts dict isn't empty"); + VALIDATE((opts.size == 0), "opts dict isn't empty", { return rv; - } + }); buf_T *buf = find_buffer_by_handle(buffer, err); @@ -820,18 +796,16 @@ ArrayOf(String) nvim_buf_get_text(uint64_t channel_id, Buffer buffer, start_row = normalize_index(buf, start_row, false, &oob); end_row = normalize_index(buf, end_row, false, &oob); - if (oob) { - api_set_error(err, kErrorTypeValidation, "Index out of bounds"); + VALIDATE((!oob), "Index out of bounds", { return rv; - } + }); // nvim_buf_get_lines doesn't care if the start row is greater than the end // row (it will just return an empty array), but nvim_buf_get_text does in // order to maintain symmetry with nvim_buf_set_text. - if (start_row > end_row) { - api_set_error(err, kErrorTypeValidation, "start is higher than end"); + VALIDATE((start_row <= end_row), "start is higher than end", { return rv; - } + }); bool replace_nl = (channel_id != VIML_INTERNAL_CALL); @@ -907,10 +881,9 @@ Integer nvim_buf_get_offset(Buffer buffer, Integer index, Error *err) return -1; } - if (index < 0 || index > buf->b_ml.ml_line_count) { - api_set_error(err, kErrorTypeValidation, "Index out of bounds"); + VALIDATE((index >= 0 && index <= buf->b_ml.ml_line_count), "Index out of bounds", { return 0; - } + }); return ml_find_line_or_offset(buf, (int)index + 1, NULL, true); } @@ -1118,8 +1091,9 @@ void nvim_buf_delete(Buffer buffer, Dictionary opts, Error *err) } else if (strequal("unload", k.data)) { unload = api_object_to_bool(v, "unload", false, err); } else { - api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); - return; + VALIDATE_S(false, "key", k.data, { + return; + }); } } @@ -1174,20 +1148,16 @@ Boolean nvim_buf_del_mark(Buffer buffer, String name, Error *err) return res; } - if (name.size != 1) { - api_set_error(err, kErrorTypeValidation, - "Mark name must be a single character"); + VALIDATE_S((name.size == 1), "mark name (must be a single char)", name.data, { return res; - } + }); fmark_T *fm = mark_get(buf, curwin, NULL, kMarkAllNoResolve, *name.data); // fm is NULL when there's no mark with the given name - if (fm == NULL) { - api_set_error(err, kErrorTypeValidation, "Invalid mark name: '%c'", - *name.data); + VALIDATE_S((fm != NULL), "mark name", name.data, { return res; - } + }); // mark.lnum is 0 when the mark is not valid in the buffer, or is not set. if (fm->mark.lnum != 0 && fm->fnum == buf->handle) { @@ -1224,11 +1194,9 @@ Boolean nvim_buf_set_mark(Buffer buffer, String name, Integer line, Integer col, return res; } - if (name.size != 1) { - api_set_error(err, kErrorTypeValidation, - "Mark name must be a single character"); + VALIDATE_S((name.size == 1), "mark name (must be a single char)", name.data, { return res; - } + }); res = set_mark(buf, name, line, col, err); @@ -1257,21 +1225,18 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) return rv; } - if (name.size != 1) { - api_set_error(err, kErrorTypeValidation, - "Mark name must be a single character"); + VALIDATE_S((name.size == 1), "mark name (must be a single char)", name.data, { return rv; - } + }); fmark_T *fm; pos_T pos; char mark = *name.data; fm = mark_get(buf, curwin, NULL, kMarkAllNoResolve, mark); - if (fm == NULL) { - api_set_error(err, kErrorTypeValidation, "Invalid mark name"); + VALIDATE_S((fm != NULL), "mark name", name.data, { return rv; - } + }); // (0, 0) uppercase/file mark set in another buffer. if (fm->fnum != buf->handle) { pos.lnum = 0; diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index f09a00e5c2..0a95833256 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -11,6 +11,7 @@ #include "nvim/api/command.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/buffer_defs.h" @@ -99,10 +100,9 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) { Dictionary result = ARRAY_DICT_INIT; - if (opts.size > 0) { - api_set_error(err, kErrorTypeValidation, "opts dict isn't empty"); + VALIDATE((opts.size == 0), "opts dict isn't empty", { return result; - } + }); // Parse command line exarg_T ea; @@ -998,7 +998,7 @@ void nvim_buf_del_user_command(Buffer buffer, String name, Error *err) } } - api_set_error(err, kErrorTypeException, "No such user-defined command: %s", name.data); + api_set_error(err, kErrorTypeException, "Invalid command (not found): %s", name.data); } void create_user_command(String name, Object command, Dict(user_command) *opts, int flags, @@ -1014,20 +1014,17 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, LuaRef compl_luaref = LUA_NOREF; LuaRef preview_luaref = LUA_NOREF; - if (!uc_validate_name(name.data)) { - api_set_error(err, kErrorTypeValidation, "Invalid command name"); + VALIDATE_S(uc_validate_name(name.data), "command name", name.data, { goto err; - } - - if (mb_islower(name.data[0])) { - api_set_error(err, kErrorTypeValidation, "'name' must begin with an uppercase letter"); + }); + VALIDATE_S(!mb_islower(name.data[0]), "command name (must begin with an uppercase letter)", + name.data, { goto err; - } - - if (HAS_KEY(opts->range) && HAS_KEY(opts->count)) { - api_set_error(err, kErrorTypeValidation, "'range' and 'count' are mutually exclusive"); + }); + VALIDATE((!HAS_KEY(opts->range) || !HAS_KEY(opts->count)), + "Cannot use both 'range' and 'count'", { goto err; - } + }); if (opts->nargs.type == kObjectTypeInteger) { switch (opts->nargs.data.integer) { @@ -1038,14 +1035,14 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, argt |= EX_EXTRA | EX_NOSPC | EX_NEEDARG; break; default: - api_set_error(err, kErrorTypeValidation, "Invalid value for 'nargs'"); - goto err; + VALIDATE_INT(false, "nargs", (int64_t)opts->nargs.data.integer, { + goto err; + }); } } else if (opts->nargs.type == kObjectTypeString) { - if (opts->nargs.data.string.size > 1) { - api_set_error(err, kErrorTypeValidation, "Invalid value for 'nargs'"); + VALIDATE_S((opts->nargs.data.string.size <= 1), "nargs", opts->nargs.data.string.data, { goto err; - } + }); switch (opts->nargs.data.string.data[0]) { case '*': @@ -1058,18 +1055,19 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, argt |= EX_EXTRA | EX_NEEDARG; break; default: - api_set_error(err, kErrorTypeValidation, "Invalid value for 'nargs'"); - goto err; + VALIDATE_S(false, "nargs", opts->nargs.data.string.data, { + goto err; + }); } } else if (HAS_KEY(opts->nargs)) { - api_set_error(err, kErrorTypeValidation, "Invalid value for 'nargs'"); - goto err; + VALIDATE_S(false, "nargs", "", { + goto err; + }); } - if (HAS_KEY(opts->complete) && !argt) { - api_set_error(err, kErrorTypeValidation, "'complete' used without 'nargs'"); + VALIDATE((!HAS_KEY(opts->complete) || argt), "'complete' used without 'nargs'", { goto err; - } + }); if (opts->range.type == kObjectTypeBoolean) { if (opts->range.data.boolean) { @@ -1077,13 +1075,12 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, addr_type_arg = ADDR_LINES; } } else if (opts->range.type == kObjectTypeString) { - if (opts->range.data.string.data[0] == '%' && opts->range.data.string.size == 1) { - argt |= EX_RANGE | EX_DFLALL; - addr_type_arg = ADDR_LINES; - } else { - api_set_error(err, kErrorTypeValidation, "Invalid value for 'range'"); + VALIDATE_S((opts->range.data.string.data[0] == '%' && opts->range.data.string.size == 1), + "range", "", { goto err; - } + }); + argt |= EX_RANGE | EX_DFLALL; + addr_type_arg = ADDR_LINES; } else if (opts->range.type == kObjectTypeInteger) { argt |= EX_RANGE | EX_ZEROR; def = opts->range.data.integer; diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index ab3b3485e4..71ba9cfd4c 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -11,6 +11,7 @@ #include "nvim/api/extmark.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/decoration.h" @@ -218,10 +219,9 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, return rv; } - if (!ns_initialized((uint32_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); + VALIDATE_INT(ns_initialized((uint32_t)ns_id), "ns_id", ns_id, { return rv; - } + }); bool details = false; for (size_t i = 0; i < opts.size; i++) { @@ -233,12 +233,14 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, } else if (v->type == kObjectTypeInteger) { details = v->data.integer; } else { - api_set_error(err, kErrorTypeValidation, "details is not an boolean"); - return rv; + VALIDATE_EXP(false, "details", "Boolean or Integer", api_typename(v->type), { + return rv; + }); } } else { - api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); - return rv; + VALIDATE_S(false, "key", k.data, { + return rv; + }); } } @@ -301,10 +303,9 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e return rv; } - if (!ns_initialized((uint32_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); + VALIDATE_INT(ns_initialized((uint32_t)ns_id), "ns_id", ns_id, { return rv; - } + }); Integer limit = -1; bool details = false; @@ -313,10 +314,9 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e String k = opts.items[i].key; Object *v = &opts.items[i].value; if (strequal("limit", k.data)) { - if (v->type != kObjectTypeInteger) { - api_set_error(err, kErrorTypeValidation, "limit is not an integer"); + VALIDATE_T("limit", kObjectTypeInteger, v->type, { return rv; - } + }); limit = v->data.integer; } else if (strequal("details", k.data)) { if (v->type == kObjectTypeBoolean) { @@ -324,12 +324,14 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e } else if (v->type == kObjectTypeInteger) { details = v->data.integer; } else { - api_set_error(err, kErrorTypeValidation, "details is not an boolean"); - return rv; + VALIDATE_EXP(false, "details", "Boolean or Integer", api_typename(v->type), { + return rv; + }); } } else { - api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); - return rv; + VALIDATE_S(false, "key", k.data, { + return rv; + }); } } @@ -501,27 +503,26 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer goto error; } - if (!ns_initialized((uint32_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); + VALIDATE_INT(ns_initialized((uint32_t)ns_id), "ns_id", ns_id, { goto error; - } + }); uint32_t id = 0; if (opts->id.type == kObjectTypeInteger && opts->id.data.integer > 0) { id = (uint32_t)opts->id.data.integer; } else if (HAS_KEY(opts->id)) { - api_set_error(err, kErrorTypeValidation, "id is not a positive integer"); - goto error; + VALIDATE_S(false, "id (must be positive integer)", "", { + goto error; + }); } int line2 = -1; // For backward compatibility we support "end_line" as an alias for "end_row" if (HAS_KEY(opts->end_line)) { - if (HAS_KEY(opts->end_row)) { - api_set_error(err, kErrorTypeValidation, "cannot use both end_row and end_line"); + VALIDATE(!HAS_KEY(opts->end_row), "cannot use both end_row and end_line", { goto error; - } + }); opts->end_row = opts->end_line; } @@ -536,29 +537,28 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer if (opts->end_row.type == kObjectTypeInteger) { Integer val = opts->end_row.data.integer; - if (val < 0 || (val > buf->b_ml.ml_line_count && strict)) { - api_set_error(err, kErrorTypeValidation, "end_row value outside range"); + VALIDATE((val >= 0 && !(val > buf->b_ml.ml_line_count && strict)), + "end_row value outside range", { goto error; - } else { - line2 = (int)val; - } + }); + line2 = (int)val; } else if (HAS_KEY(opts->end_row)) { - api_set_error(err, kErrorTypeValidation, "end_row is not an integer"); - goto error; + VALIDATE_T("end_row", kObjectTypeInteger, opts->end_row.type, { + goto error; + }); } colnr_T col2 = -1; if (opts->end_col.type == kObjectTypeInteger) { Integer val = opts->end_col.data.integer; - if (val < 0 || val > MAXCOL) { - api_set_error(err, kErrorTypeValidation, "end_col value outside range"); + VALIDATE((val >= 0 && val <= MAXCOL), "end_col value outside range", { goto error; - } else { - col2 = (int)val; - } + }); + col2 = (int)val; } else if (HAS_KEY(opts->end_col)) { - api_set_error(err, kErrorTypeValidation, "end_col is not an integer"); - goto error; + VALIDATE_T("end_col", kObjectTypeInteger, opts->end_col.type, { + goto error; + }); } // uncrustify:off @@ -596,8 +596,9 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer } has_decor = true; } else if (HAS_KEY(opts->conceal)) { - api_set_error(err, kErrorTypeValidation, "conceal is not a String"); - goto error; + VALIDATE_T("conceal", kObjectTypeString, opts->conceal.type, { + goto error; + }); } if (opts->virt_text.type == kObjectTypeArray) { @@ -608,8 +609,9 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer goto error; } } else if (HAS_KEY(opts->virt_text)) { - api_set_error(err, kErrorTypeValidation, "virt_text is not an Array"); - goto error; + VALIDATE_T("virt_text", kObjectTypeArray, opts->virt_text.type, { + goto error; + }); } if (opts->virt_text_pos.type == kObjectTypeString) { @@ -621,21 +623,23 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer } else if (strequal("right_align", str.data)) { decor.virt_text_pos = kVTRightAlign; } else { - api_set_error(err, kErrorTypeValidation, "virt_text_pos: invalid value"); - goto error; + VALIDATE_S(false, "virt_text_pos", "", { + goto error; + }); } } else if (HAS_KEY(opts->virt_text_pos)) { - api_set_error(err, kErrorTypeValidation, "virt_text_pos is not a String"); - goto error; + VALIDATE_T("virt_text_pos", kObjectTypeString, opts->virt_text_pos.type, { + goto error; + }); } if (opts->virt_text_win_col.type == kObjectTypeInteger) { decor.col = (int)opts->virt_text_win_col.data.integer; decor.virt_text_pos = kVTWinCol; } else if (HAS_KEY(opts->virt_text_win_col)) { - api_set_error(err, kErrorTypeValidation, - "virt_text_win_col is not a Number of the correct size"); - goto error; + VALIDATE_T("virt_text_win_col", kObjectTypeInteger, opts->virt_text_win_col.type, { + goto error; + }); } OPTION_TO_BOOL(decor.virt_text_hide, virt_text_hide, false); @@ -650,13 +654,14 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer } else if (strequal("blend", str.data)) { decor.hl_mode = kHlModeBlend; } else { - api_set_error(err, kErrorTypeValidation, - "virt_text_pos: invalid value"); - goto error; + VALIDATE_S(false, "virt_text_pos", "", { + goto error; + }); } } else if (HAS_KEY(opts->hl_mode)) { - api_set_error(err, kErrorTypeValidation, "hl_mode is not a String"); - goto error; + VALIDATE_T("hl_mode", kObjectTypeString, opts->hl_mode.type, { + goto error; + }); } bool virt_lines_leftcol = false; @@ -665,10 +670,9 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer if (opts->virt_lines.type == kObjectTypeArray) { Array a = opts->virt_lines.data.array; for (size_t j = 0; j < a.size; j++) { - if (a.items[j].type != kObjectTypeArray) { - api_set_error(err, kErrorTypeValidation, "virt_text_line item is not an Array"); + VALIDATE_T("virt_text_line", kObjectTypeArray, a.items[j].type, { goto error; - } + }); int dummig; VirtText jtem = parse_virt_text(a.items[j].data.array, err, &dummig); kv_push(decor.virt_lines, ((struct virt_line){ jtem, virt_lines_leftcol })); @@ -678,8 +682,9 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer has_decor = true; } } else if (HAS_KEY(opts->virt_lines)) { - api_set_error(err, kErrorTypeValidation, "virt_lines is not an Array"); - goto error; + VALIDATE_T("virt_lines", kObjectTypeArray, opts->virt_lines.type, { + goto error; + }); } OPTION_TO_BOOL(decor.virt_lines_above, virt_lines_above, false); @@ -687,26 +692,26 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer if (opts->priority.type == kObjectTypeInteger) { Integer val = opts->priority.data.integer; - if (val < 0 || val > UINT16_MAX) { - api_set_error(err, kErrorTypeValidation, "priority is not a valid value"); + VALIDATE_S((val >= 0 && val <= UINT16_MAX), "priority", "(out of range)", { goto error; - } + }); decor.priority = (DecorPriority)val; } else if (HAS_KEY(opts->priority)) { - api_set_error(err, kErrorTypeValidation, "priority is not a Number of the correct size"); - goto error; + VALIDATE_T("priority", kObjectTypeInteger, opts->priority.type, { + goto error; + }); } if (opts->sign_text.type == kObjectTypeString) { - if (!init_sign_text(&decor.sign_text, - opts->sign_text.data.string.data)) { - api_set_error(err, kErrorTypeValidation, "sign_text is not a valid value"); + VALIDATE_S(init_sign_text(&decor.sign_text, opts->sign_text.data.string.data), + "sign_text", "", { goto error; - } + }); has_decor = true; } else if (HAS_KEY(opts->sign_text)) { - api_set_error(err, kErrorTypeValidation, "sign_text is not a String"); - goto error; + VALIDATE_T("sign_text", kObjectTypeString, opts->sign_text.type, { + goto error; + }); } bool right_gravity = true; @@ -714,11 +719,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer // Only error out if they try to set end_right_gravity without // setting end_col or end_row - if (line2 == -1 && col2 == -1 && HAS_KEY(opts->end_right_gravity)) { - api_set_error(err, kErrorTypeValidation, - "cannot set end_right_gravity without setting end_row or end_col"); + VALIDATE(!(line2 == -1 && col2 == -1 && HAS_KEY(opts->end_right_gravity)), + "cannot set end_right_gravity without setting end_row or end_col", { goto error; - } + }); bool end_right_gravity = false; OPTION_TO_BOOL(end_right_gravity, end_right_gravity, false); @@ -742,16 +746,15 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer has_decor = true; } - if (line < 0) { - api_set_error(err, kErrorTypeValidation, "line value outside range"); + VALIDATE_S((line >= 0), "line", "(out of range)", { goto error; - } else if (line > buf->b_ml.ml_line_count) { - if (strict) { - api_set_error(err, kErrorTypeValidation, "line value outside range"); + }); + + if (line > buf->b_ml.ml_line_count) { + VALIDATE_S(!strict, "line", "(out of range)", { goto error; - } else { - line = buf->b_ml.ml_line_count; - } + }); + line = buf->b_ml.ml_line_count; } else if (line < buf->b_ml.ml_line_count) { len = ephemeral ? MAXCOL : strlen(ml_get_buf(buf, (linenr_T)line + 1, false)); } @@ -759,15 +762,14 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer if (col == -1) { col = (Integer)len; } else if (col > (Integer)len) { - if (strict) { - api_set_error(err, kErrorTypeValidation, "col value outside range"); + VALIDATE_S(!strict, "col", "(out of range)", { goto error; - } else { - col = (Integer)len; - } + }); + col = (Integer)len; } else if (col < -1) { - api_set_error(err, kErrorTypeValidation, "col value outside range"); - goto error; + VALIDATE_S(false, "col", "(out of range)", { + goto error; + }); } if (col2 >= 0) { @@ -781,12 +783,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer line2 = (int)line; } if (col2 > (Integer)len) { - if (strict) { - api_set_error(err, kErrorTypeValidation, "end_col value outside range"); + VALIDATE_S(!strict, "end_col", "(out of range)", { goto error; - } else { - col2 = (int)len; - } + }); + col2 = (int)len; } } else if (line2 >= 0) { col2 = 0; @@ -829,10 +829,9 @@ Boolean nvim_buf_del_extmark(Buffer buffer, Integer ns_id, Integer id, Error *er if (!buf) { return false; } - if (!ns_initialized((uint32_t)ns_id)) { - api_set_error(err, kErrorTypeValidation, "Invalid ns_id"); + VALIDATE_INT(ns_initialized((uint32_t)ns_id), "ns_id", ns_id, { return false; - } + }); return extmark_del(buf, (uint32_t)ns_id, (uint32_t)id); } @@ -887,14 +886,13 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In return 0; } - if (line < 0 || line >= MAXLNUM) { - api_set_error(err, kErrorTypeValidation, "Line number outside range"); + VALIDATE_S((line >= 0 && line < MAXLNUM), "line number", "(out of range)", { return 0; - } - if (col_start < 0 || col_start > MAXCOL) { - api_set_error(err, kErrorTypeValidation, "Column value outside range"); + }); + VALIDATE_S((col_start >= 0 && col_start <= MAXCOL), "column", "(out of range)", { return 0; - } + }); + if (col_end < 0 || col_end > MAXCOL) { col_end = MAXCOL; } @@ -950,10 +948,10 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, return; } - if (line_start < 0 || line_start >= MAXLNUM) { - api_set_error(err, kErrorTypeValidation, "Line number outside range"); + VALIDATE_S((line_start >= 0 && line_start < MAXLNUM), "line number", "(out of range)", { return; - } + }); + if (line_end < 0 || line_end > MAXLNUM) { line_end = MAXLNUM; } @@ -1034,11 +1032,10 @@ void nvim_set_decoration_provider(Integer ns_id, Dict(set_decoration_provider) * continue; } - if (v->type != kObjectTypeLuaRef) { - api_set_error(err, kErrorTypeValidation, - "%s is not a function", cbs[i].name); + VALIDATE_T(cbs[i].name, kObjectTypeLuaRef, v->type, { goto error; - } + }); + *(cbs[i].dest) = v->data.luaref; v->data.luaref = LUA_NOREF; } @@ -1075,39 +1072,39 @@ static bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, in *col = MAXCOL; return true; } else if (id < 0) { - api_set_error(err, kErrorTypeValidation, "Mark id must be positive"); - return false; + VALIDATE_INT(false, "mark id", id, { + return false; + }); } ExtmarkInfo extmark = extmark_from_id(buf, (uint32_t)ns_id, (uint32_t)id); - if (extmark.row >= 0) { - *row = extmark.row; - *col = extmark.col; - return true; - } else { - api_set_error(err, kErrorTypeValidation, "No mark with requested id"); + + VALIDATE_INT((extmark.row >= 0), "mark id (not found)", id, { return false; - } + }); + *row = extmark.row; + *col = extmark.col; + return true; // Check if it is a position } else if (obj.type == kObjectTypeArray) { Array pos = obj.data.array; - if (pos.size != 2 - || pos.items[0].type != kObjectTypeInteger - || pos.items[1].type != kObjectTypeInteger) { - api_set_error(err, kErrorTypeValidation, - "Position must have 2 integer elements"); + VALIDATE((pos.size == 2 + && pos.items[0].type == kObjectTypeInteger + && pos.items[1].type == kObjectTypeInteger), + "Invalid position: expected 2 Integer items", { return false; - } + }); + Integer pos_row = pos.items[0].data.integer; Integer pos_col = pos.items[1].data.integer; *row = (int)(pos_row >= 0 ? pos_row : MAXLNUM); *col = (colnr_T)(pos_col >= 0 ? pos_col : MAXCOL); return true; } else { - api_set_error(err, kErrorTypeValidation, - "Position must be a mark id Integer or position Array"); - return false; + VALIDATE(false, "Invalid position: expected mark id Integer or 2-item Array", { + return false; + }); } } // adapted from sign.c:sign_define_init_text. @@ -1151,17 +1148,14 @@ VirtText parse_virt_text(Array chunks, Error *err, int *width) VirtText virt_text = KV_INITIAL_VALUE; int w = 0; for (size_t i = 0; i < chunks.size; i++) { - if (chunks.items[i].type != kObjectTypeArray) { - api_set_error(err, kErrorTypeValidation, "Chunk is not an array"); + VALIDATE_T("chunk", kObjectTypeArray, chunks.items[i].type, { goto free_exit; - } + }); Array chunk = chunks.items[i].data.array; - if (chunk.size == 0 || chunk.size > 2 - || chunk.items[0].type != kObjectTypeString) { - api_set_error(err, kErrorTypeValidation, - "Chunk is not an array with one or two strings"); + VALIDATE((chunk.size > 0 && chunk.size <= 2 && chunk.items[0].type == kObjectTypeString), + "Invalid chunk: expected Array with 1 or 2 Strings", { goto free_exit; - } + }); String str = chunk.items[0].data.string; diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index 2a54c3b132..5b57b49ad6 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -9,6 +9,7 @@ #include "nvim/api/options.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/autocmd.h" #include "nvim/buffer_defs.h" #include "nvim/eval/window.h" @@ -31,11 +32,14 @@ static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_t } else if (!strcmp(opts->scope.data.string.data, "global")) { *scope = OPT_GLOBAL; } else { - api_set_error(err, kErrorTypeValidation, "invalid scope: must be 'local' or 'global'"); - return FAIL; + VALIDATE(false, "Invalid scope (expected 'local' or 'global')", { + return FAIL; + }); } } else if (HAS_KEY(opts->scope)) { - api_set_error(err, kErrorTypeValidation, "invalid value for key: scope"); + VALIDATE_T("scope", kObjectTypeString, opts->scope.type, { + return FAIL; + }); return FAIL; } @@ -48,8 +52,9 @@ static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_t return FAIL; } } else if (HAS_KEY(opts->win)) { - api_set_error(err, kErrorTypeValidation, "invalid value for key: win"); - return FAIL; + VALIDATE_T("win", kObjectTypeInteger, opts->win.type, { + return FAIL; + }); } if (opts->buf.type == kObjectTypeInteger) { @@ -60,19 +65,17 @@ static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_t return FAIL; } } else if (HAS_KEY(opts->buf)) { - api_set_error(err, kErrorTypeValidation, "invalid value for key: buf"); - return FAIL; + VALIDATE_T("buf", kObjectTypeInteger, opts->buf.type, { + return FAIL; + }); } - if (HAS_KEY(opts->scope) && HAS_KEY(opts->buf)) { - api_set_error(err, kErrorTypeValidation, "scope and buf cannot be used together"); + VALIDATE((!HAS_KEY(opts->scope) || !HAS_KEY(opts->buf)), "cannot use both 'scope' and 'buf'", { return FAIL; - } - - if (HAS_KEY(opts->win) && HAS_KEY(opts->buf)) { - api_set_error(err, kErrorTypeValidation, "buf and win cannot be used together"); + }); + VALIDATE((!HAS_KEY(opts->win) || !HAS_KEY(opts->buf)), "cannot use both 'buf' and 'win'", { return FAIL; - } + }); return OK; } @@ -132,8 +135,9 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) } break; default: - api_set_error(err, kErrorTypeValidation, "unknown option '%s'", name.data); - return rv; + VALIDATE_S(false, "option", name.data, { + return rv; + }); } return rv; @@ -193,8 +197,9 @@ void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error scope |= OPT_CLEAR; break; default: - api_set_error(err, kErrorTypeValidation, "invalid value for option"); - return; + VALIDATE_EXP(false, "option type", "Integer, Boolean, or String", api_typename(value.type), { + return; + }); } access_option_value_for(name.data, &numval, &stringval, scope, opt_type, to, false, err); @@ -351,21 +356,18 @@ static Object get_option_from(void *from, int type, String name, Error *err) { Object rv = OBJECT_INIT; - if (name.size == 0) { - api_set_error(err, kErrorTypeValidation, "Empty option name"); + VALIDATE_S(name.size > 0, "option name", "", { return rv; - } + }); // Return values int64_t numval; char *stringval = NULL; - int flags = get_option_value_strict(name.data, &numval, &stringval, type, from); - if (!flags) { - api_set_error(err, kErrorTypeValidation, "Invalid option name: '%s'", - name.data); + int flags = get_option_value_strict(name.data, &numval, &stringval, type, from); + VALIDATE_S(flags != 0, "option name", name.data, { return rv; - } + }); if (flags & SOPT_BOOL) { rv.type = kObjectTypeBoolean; @@ -374,20 +376,15 @@ static Object get_option_from(void *from, int type, String name, Error *err) rv.type = kObjectTypeInteger; rv.data.integer = numval; } else if (flags & SOPT_STRING) { - if (stringval) { - rv.type = kObjectTypeString; - rv.data.string.data = stringval; - rv.data.string.size = strlen(stringval); - } else { - api_set_error(err, kErrorTypeException, - "Failed to get value for option '%s'", - name.data); + if (!stringval) { + api_set_error(err, kErrorTypeException, "Failed to get option '%s'", name.data); + return rv; } + rv.type = kObjectTypeString; + rv.data.string.data = stringval; + rv.data.string.size = strlen(stringval); } else { - api_set_error(err, - kErrorTypeException, - "Unknown type for option '%s'", - name.data); + api_set_error(err, kErrorTypeException, "Unknown type for option '%s'", name.data); } return rv; @@ -402,29 +399,22 @@ static Object get_option_from(void *from, int type, String name, Error *err) /// @param[out] err Details of an error that may have occurred void set_option_to(uint64_t channel_id, void *to, int type, String name, Object value, Error *err) { - if (name.size == 0) { - api_set_error(err, kErrorTypeValidation, "Empty option name"); + VALIDATE_S(name.size > 0, "option name", "", { return; - } + }); int flags = get_option_value_strict(name.data, NULL, NULL, type, to); - - if (flags == 0) { - api_set_error(err, kErrorTypeValidation, "Invalid option name '%s'", - name.data); + VALIDATE_S(flags != 0, "option name", name.data, { return; - } + }); if (value.type == kObjectTypeNil) { if (type == SREQ_GLOBAL) { - api_set_error(err, kErrorTypeException, "Cannot unset option '%s'", - name.data); + api_set_error(err, kErrorTypeException, "Cannot unset option '%s'", name.data); return; } else if (!(flags & SOPT_GLOBAL)) { - api_set_error(err, - kErrorTypeException, - "Cannot unset option '%s' " - "because it doesn't have a global value", + api_set_error(err, kErrorTypeException, + "Cannot unset option '%s' because it doesn't have a global value", name.data); return; } else { @@ -437,39 +427,23 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object char *stringval = NULL; if (flags & SOPT_BOOL) { - if (value.type != kObjectTypeBoolean) { - api_set_error(err, - kErrorTypeValidation, - "Option '%s' requires a Boolean value", - name.data); + VALIDATE_FMT(value.type == kObjectTypeBoolean, "Option '%s' value must be Boolean", name.data, { return; - } - + }); numval = value.data.boolean; } else if (flags & SOPT_NUM) { - if (value.type != kObjectTypeInteger) { - api_set_error(err, kErrorTypeValidation, - "Option '%s' requires an integer value", - name.data); + VALIDATE_FMT(value.type == kObjectTypeInteger, "Option '%s' value must be Integer", name.data, { return; - } - - if (value.data.integer > INT_MAX || value.data.integer < INT_MIN) { - api_set_error(err, kErrorTypeValidation, - "Value for option '%s' is out of range", - name.data); + }); + VALIDATE_FMT((value.data.integer <= INT_MAX && value.data.integer >= INT_MIN), + "Option '%s' value is out of range", name.data, { return; - } - + }); numval = (int)value.data.integer; } else { - if (value.type != kObjectTypeString) { - api_set_error(err, kErrorTypeValidation, - "Option '%s' requires a string value", - name.data); + VALIDATE_FMT(value.type == kObjectTypeString, "Option '%s' value must be String", name.data, { return; - } - + }); stringval = value.data.string.data; } diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 519f2cc5bf..6beb3d8683 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -827,6 +827,36 @@ int object_to_hl_id(Object obj, const char *what, Error *err) } } +char *api_typename(ObjectType t) +{ + switch (t) { + case kObjectTypeNil: + return "nil"; + case kObjectTypeBoolean: + return "Boolean"; + case kObjectTypeInteger: + return "Integer"; + case kObjectTypeFloat: + return "Float"; + case kObjectTypeString: + return "String"; + case kObjectTypeArray: + return "Array"; + case kObjectTypeDictionary: + return "Dict"; + case kObjectTypeLuaRef: + return "Function"; + case kObjectTypeBuffer: + return "Buffer"; + case kObjectTypeWindow: + return "Window"; + case kObjectTypeTabpage: + return "Tabpage"; + default: + abort(); + } +} + HlMessage parse_hl_msg(Array chunks, Error *err) { HlMessage hl_msg = KV_INITIAL_VALUE; diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h new file mode 100644 index 0000000000..8448b416be --- /dev/null +++ b/src/nvim/api/private/validate.h @@ -0,0 +1,69 @@ +#ifndef NVIM_API_PRIVATE_VALIDATE_H +#define NVIM_API_PRIVATE_VALIDATE_H + +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" + +#define VALIDATE_INT(cond, name, val_, code) \ + do { \ + if (!(cond)) { \ + api_set_error(err, kErrorTypeValidation, "Invalid " name ": %" PRId64, val_); \ + code; \ + } \ + } while (0) + +#define VALIDATE_S(cond, name, val_, code) \ + do { \ + if (!(cond)) { \ + if (strequal(val_, "")) { \ + api_set_error(err, kErrorTypeValidation, "Invalid " name); \ + } else { \ + api_set_error(err, kErrorTypeValidation, "Invalid " name ": '%s'", val_); \ + } \ + code; \ + } \ + } while (0) + +#define VALIDATE_R(cond, name, code) \ + do { \ + if (!(cond)) { \ + api_set_error(err, kErrorTypeValidation, "'" name "' is required"); \ + code; \ + } \ + } while (0) + +#define VALIDATE_EXP(cond, name, expected, actual, code) \ + do { \ + if (!(cond)) { \ + api_set_error(err, kErrorTypeValidation, "Invalid " name ": expected %s, got %s", \ + expected, actual); \ + code; \ + } \ + } while (0) + +#define VALIDATE_T(name, expected_t, actual_t, code) \ + do { \ + if (expected_t != actual_t) { \ + api_set_error(err, kErrorTypeValidation, "Invalid %s: expected %s, got %s", \ + name, api_typename(expected_t), api_typename(actual_t)); \ + code; \ + } \ + } while (0) + +#define VALIDATE(cond, msg_, code) \ + do { \ + if (!(cond)) { \ + api_set_error(err, kErrorTypeValidation, "%s", msg_); \ + code; \ + } \ + } while (0) + +#define VALIDATE_FMT(cond, fmt_, msg_, code) \ + do { \ + if (!(cond)) { \ + api_set_error(err, kErrorTypeValidation, fmt_, msg_); \ + code; \ + } \ + } while (0) + +#endif // NVIM_API_PRIVATE_VALIDATE_H diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 12ab40a687..333749c42f 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -18,6 +18,7 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/api/vim.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" @@ -193,10 +194,9 @@ void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err) void nvim_set_hl_ns(Integer ns_id, Error *err) FUNC_API_SINCE(10) { - if (ns_id < 0) { - api_set_error(err, kErrorTypeValidation, "no such namespace"); + VALIDATE_INT((ns_id >= 0), "namespace", ns_id, { return; - } + }); ns_hl_global = (NS)ns_id; hl_check_ns(); @@ -500,10 +500,9 @@ Object nvim_notify(String msg, Integer log_level, Dictionary opts, Error *err) Integer nvim_strwidth(String text, Error *err) FUNC_API_SINCE(1) { - if (text.size > INT_MAX) { - api_set_error(err, kErrorTypeValidation, "String is too long"); + VALIDATE((text.size <= INT_MAX), "text length (too long)", { return 0; - } + }); return (Integer)mb_string2cells(text.data); } @@ -575,9 +574,7 @@ ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, E { bool is_lua = api_object_to_bool(opts->is_lua, "is_lua", false, err); bool source = api_object_to_bool(opts->do_source, "do_source", false, err); - if (source && !nlua_is_deferred_safe()) { - api_set_error(err, kErrorTypeValidation, "'do_source' cannot be used in fast callback"); - } + VALIDATE((!source || nlua_is_deferred_safe()), "'do_source' used in fast callback", {}); if (ERROR_SET(err)) { return (Array)ARRAY_DICT_INIT; @@ -602,10 +599,9 @@ ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, E void nvim_set_current_dir(String dir, Error *err) FUNC_API_SINCE(1) { - if (dir.size >= MAXPATHL) { - api_set_error(err, kErrorTypeValidation, "Directory name is too long"); + VALIDATE((dir.size < MAXPATHL), "directory name (too long)", { return; - } + }); char string[MAXPATHL]; memcpy(string, dir.data, dir.size); @@ -664,16 +660,14 @@ Object nvim_get_var(String name, Error *err) { dictitem_T *di = tv_dict_find(&globvardict, name.data, (ptrdiff_t)name.size); if (di == NULL) { // try to autoload script - if (!script_autoload(name.data, name.size, false) || aborting()) { - api_set_error(err, kErrorTypeValidation, "Key not found: %s", name.data); + VALIDATE_S((script_autoload(name.data, name.size, false) && !aborting()), "key", name.data, { return (Object)OBJECT_INIT; - } + }); di = tv_dict_find(&globvardict, name.data, (ptrdiff_t)name.size); } - if (di == NULL) { - api_set_error(err, kErrorTypeValidation, "Key not found: %s", name.data); + VALIDATE_S((di != NULL), "key (not found)", name.data, { return (Object)OBJECT_INIT; - } + }); return vim_to_object(&di->di_tv); } @@ -991,16 +985,14 @@ Integer nvim_open_term(Buffer buffer, DictionaryOf(LuaRef) opts, Error *err) String k = opts.items[i].key; Object *v = &opts.items[i].value; if (strequal("on_input", k.data)) { - if (v->type != kObjectTypeLuaRef) { - api_set_error(err, kErrorTypeValidation, - "%s is not a function", "on_input"); + VALIDATE_T("on_input", kObjectTypeLuaRef, v->type, { return 0; - } + }); cb = v->data.luaref; v->data.luaref = LUA_NOREF; break; } else { - api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data); + VALIDATE_S(false, "key", k.data, {}); } } @@ -1075,9 +1067,7 @@ void nvim_chan_send(Integer chan, String data, Error *err) channel_send((uint64_t)chan, data.data, data.size, false, &error); - if (error) { - api_set_error(err, kErrorTypeValidation, "%s", error); - } + VALIDATE(!error, error, {}); } /// Gets the current list of tabpage handles. @@ -1164,10 +1154,9 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err) static bool draining = false; bool cancel = false; - if (phase < -1 || phase > 3) { - api_set_error(err, kErrorTypeValidation, "Invalid phase: %" PRId64, phase); + VALIDATE_INT((phase >= -1 && phase <= 3), "phase", phase, { return false; - } + }); Array args = ARRAY_DICT_INIT; Object rv = OBJECT_INIT; if (phase == -1 || phase == 1) { // Start of paste-stream. @@ -1234,20 +1223,17 @@ void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, FUNC_API_CHECK_TEXTLOCK { yankreg_T *reg = xcalloc(1, sizeof(yankreg_T)); - if (!prepare_yankreg_from_object(reg, type, lines.size)) { - api_set_error(err, kErrorTypeValidation, "Invalid type: '%s'", type.data); + VALIDATE_S((prepare_yankreg_from_object(reg, type, lines.size)), "type", type.data, { goto cleanup; - } + }); if (lines.size == 0) { goto cleanup; // Nothing to do. } for (size_t i = 0; i < lines.size; i++) { - if (lines.items[i].type != kObjectTypeString) { - api_set_error(err, kErrorTypeValidation, - "Invalid lines (expected array of strings)"); + VALIDATE_T("line", kObjectTypeString, lines.items[i].type, { goto cleanup; - } + }); String line = lines.items[i].data.string; reg->y_array[i] = xmemdupz(line.data, line.size); memchrsub(reg->y_array[i], NUL, NL, line.size); @@ -1351,8 +1337,9 @@ Dictionary nvim_get_context(Dict(context) *opts, Error *err) if (opts->types.type == kObjectTypeArray) { types = opts->types.data.array; } else if (opts->types.type != kObjectTypeNil) { - api_set_error(err, kErrorTypeValidation, "invalid value for key: types"); - return (Dictionary)ARRAY_DICT_INIT; + VALIDATE_T("types", kObjectTypeArray, opts->types.type, { + return (Dictionary)ARRAY_DICT_INIT; + }); } int int_types = types.size > 0 ? 0 : kCtxAll; @@ -1373,8 +1360,9 @@ Dictionary nvim_get_context(Dict(context) *opts, Error *err) } else if (strequal(s, "funcs")) { int_types |= kCtxFuncs; } else { - api_set_error(err, kErrorTypeValidation, "unexpected type: %s", s); - return (Dictionary)ARRAY_DICT_INIT; + VALIDATE_S(false, "type", s, { + return (Dictionary)ARRAY_DICT_INIT; + }); } } } @@ -1651,34 +1639,20 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er size_t i; // also used for freeing the variables for (i = 0; i < calls.size; i++) { - if (calls.items[i].type != kObjectTypeArray) { - api_set_error(err, - kErrorTypeValidation, - "Items in calls array must be arrays"); + VALIDATE_T("calls item", kObjectTypeArray, calls.items[i].type, { goto theend; - } + }); Array call = calls.items[i].data.array; - if (call.size != 2) { - api_set_error(err, - kErrorTypeValidation, - "Items in calls array must be arrays of size 2"); + VALIDATE((call.size == 2), "Items in calls array must be arrays of size 2", { goto theend; - } - - if (call.items[0].type != kObjectTypeString) { - api_set_error(err, - kErrorTypeValidation, - "Name must be String"); + }); + VALIDATE_T("name", kObjectTypeString, call.items[0].type, { goto theend; - } + }); String name = call.items[0].data.string; - - if (call.items[1].type != kObjectTypeArray) { - api_set_error(err, - kErrorTypeValidation, - "Args must be Array"); + VALIDATE_T("args", kObjectTypeArray, call.items[1].type, { goto theend; - } + }); Array args = call.items[1].data.array; MsgpackRpcRequestHandler handler = @@ -1937,10 +1911,9 @@ void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Di Error *err) FUNC_API_SINCE(6) { - if (opts.size > 0) { - api_set_error(err, kErrorTypeValidation, "opts dict isn't empty"); + VALIDATE((opts.size == 0), "opts dict isn't empty", { return; - } + }); if (finish) { insert = true; @@ -1961,13 +1934,10 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, E g = &pum_grid; } else if (grid > 1) { win_T *wp = get_win_by_grid_handle((handle_T)grid); - if (wp != NULL && wp->w_grid_alloc.chars != NULL) { - g = &wp->w_grid_alloc; - } else { - api_set_error(err, kErrorTypeValidation, - "No grid with the given handle"); + VALIDATE_INT((wp != NULL && wp->w_grid_alloc.chars != NULL), "grid handle", grid, { return ret; - } + }); + g = &wp->w_grid_alloc; } if (row < 0 || row >= g->rows @@ -2009,20 +1979,16 @@ Boolean nvim_del_mark(String name, Error *err) FUNC_API_SINCE(8) { bool res = false; - if (name.size != 1) { - api_set_error(err, kErrorTypeValidation, - "Mark name must be a single character"); + VALIDATE_S((name.size == 1), "mark name (must be a single char)", name.data, { return res; - } + }); // Only allow file/uppercase marks // TODO(muniter): Refactor this ASCII_ISUPPER macro to a proper function - if (ASCII_ISUPPER(*name.data) || ascii_isdigit(*name.data)) { - res = set_mark(NULL, name, 0, 0, err); - } else { - api_set_error(err, kErrorTypeValidation, - "Only file/uppercase marks allowed, invalid mark name: '%c'", - *name.data); - } + VALIDATE_S((ASCII_ISUPPER(*name.data) || ascii_isdigit(*name.data)), + "mark name (must be file/uppercase)", name.data, { + return res; + }); + res = set_mark(NULL, name, 0, 0, err); return res; } @@ -2043,16 +2009,13 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err) { Array rv = ARRAY_DICT_INIT; - if (name.size != 1) { - api_set_error(err, kErrorTypeValidation, - "Mark name must be a single character"); + VALIDATE_S((name.size == 1), "mark name (must be a single char)", name.data, { return rv; - } else if (!(ASCII_ISUPPER(*name.data) || ascii_isdigit(*name.data))) { - api_set_error(err, kErrorTypeValidation, - "Only file/uppercase marks allowed, invalid mark name: '%c'", - *name.data); + }); + VALIDATE_S((ASCII_ISUPPER(*name.data) || ascii_isdigit(*name.data)), + "mark name (must be file/uppercase)", name.data, { return rv; - } + }); xfmark_T *mark = mark_get_global(false, *name.data); // false avoids loading the mark buffer pos_T pos = mark->fmark.mark; @@ -2137,27 +2100,28 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * if (str.size < 2 || memcmp(str.data, "%!", 2) != 0) { const char *const errmsg = check_stl_option(str.data); - if (errmsg) { - api_set_error(err, kErrorTypeValidation, "%s", errmsg); + VALIDATE(!errmsg, errmsg, { return result; - } + }); } if (HAS_KEY(opts->winid)) { - if (opts->winid.type != kObjectTypeInteger) { - api_set_error(err, kErrorTypeValidation, "winid must be an integer"); + VALIDATE_T("winid", kObjectTypeInteger, opts->winid.type, { return result; - } + }); window = (Window)opts->winid.data.integer; } if (HAS_KEY(opts->fillchar)) { - if (opts->fillchar.type != kObjectTypeString || opts->fillchar.data.string.size == 0 - || ((size_t)utf_ptr2len(opts->fillchar.data.string.data) - != opts->fillchar.data.string.size)) { - api_set_error(err, kErrorTypeValidation, "fillchar must be a single character"); + VALIDATE_T("fillchar", kObjectTypeString, opts->fillchar.type, { return result; - } + }); + VALIDATE((opts->fillchar.data.string.size != 0 + && ((size_t)utf_ptr2len(opts->fillchar.data.string.data) + == opts->fillchar.data.string.size)), + "Invalid fillchar (not a single character)", { + return result; + }); fillchar = utf_ptr2char(opts->fillchar.data.string.data); } if (HAS_KEY(opts->highlights)) { @@ -2211,10 +2175,9 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * } if (HAS_KEY(opts->maxwidth)) { - if (opts->maxwidth.type != kObjectTypeInteger) { - api_set_error(err, kErrorTypeValidation, "maxwidth must be an integer"); + VALIDATE_T("maxwidth", kObjectTypeInteger, opts->maxwidth.type, { return result; - } + }); maxwidth = (int)opts->maxwidth.data.integer; } else { diff --git a/src/nvim/option.c b/src/nvim/option.c index 5ece5e4e5d..1d7747de0b 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -33,6 +33,7 @@ #include "nvim/api/extmark.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" @@ -5624,10 +5625,9 @@ long get_sidescrolloff_value(win_T *wp) Dictionary get_vimoption(String name, Error *err) { int opt_idx = findoption_len((const char *)name.data, name.size); - if (opt_idx < 0) { - api_set_error(err, kErrorTypeValidation, "no such option: '%s'", name.data); + VALIDATE_S(opt_idx >= 0, "option (not found)", name.data, { return (Dictionary)ARRAY_DICT_INIT; - } + }); return vimoption2dict(&options[opt_idx]); } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 8172a46773..1693595ce8 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -11,6 +11,7 @@ #include "klib/kvec.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/api/ui.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" @@ -608,7 +609,7 @@ Array ui_array(void) return all_uis; } -void ui_grid_resize(handle_T grid_handle, int width, int height, Error *error) +void ui_grid_resize(handle_T grid_handle, int width, int height, Error *err) { if (grid_handle == DEFAULT_GRID_HANDLE) { screen_resize(width, height); @@ -616,11 +617,9 @@ void ui_grid_resize(handle_T grid_handle, int width, int height, Error *error) } win_T *wp = get_win_by_grid_handle(grid_handle); - if (wp == NULL) { - api_set_error(error, kErrorTypeValidation, - "No window with the given handle"); + VALIDATE_INT((wp != NULL), "window handle", (int64_t)grid_handle, { return; - } + }); if (wp->w_floating) { if (width != wp->w_width || height != wp->w_height) { -- cgit From ff3d04b75b4a9314815c37d53ebc4d035a043335 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Feb 2023 08:07:38 -0500 Subject: refactor(api): VALIDATE macros #22256 - VALIDATE() takes a format string - deduplicate check_string_array - VALIDATE_RANGE - validate UI args --- src/nvim/api/autocmd.c | 74 +++++++++---------------- src/nvim/api/buffer.c | 53 +++++++----------- src/nvim/api/command.c | 62 +++++++++++---------- src/nvim/api/extmark.c | 117 ++++++++++++++++++++-------------------- src/nvim/api/options.c | 46 ++++++++-------- src/nvim/api/private/helpers.c | 3 +- src/nvim/api/private/validate.c | 28 ++++++++++ src/nvim/api/private/validate.h | 27 +++++----- src/nvim/api/ui.c | 66 ++++++++++------------- src/nvim/api/vim.c | 59 +++++++++----------- src/nvim/highlight.c | 60 +++++++++++---------- 11 files changed, 284 insertions(+), 311 deletions(-) create mode 100644 src/nvim/api/private/validate.c (limited to 'src') diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index 9aadd48a13..36d3e04f54 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -125,7 +125,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) }); } - if (opts->event.type != kObjectTypeNil) { + if (HAS_KEY(opts->event)) { check_event = true; Object v = opts->event; @@ -148,13 +148,13 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) } } - VALIDATE((opts->pattern.type == kObjectTypeNil || opts->buffer.type == kObjectTypeNil), - "Cannot use both 'pattern' and 'buffer'", { + VALIDATE((!HAS_KEY(opts->pattern) || !HAS_KEY(opts->buffer)), + "%s", "Cannot use both 'pattern' and 'buffer'", { goto cleanup; }); int pattern_filter_count = 0; - if (opts->pattern.type != kObjectTypeNil) { + if (HAS_KEY(opts->pattern)) { Object v = opts->pattern; if (v.type == kObjectTypeString) { pattern_filters[pattern_filter_count] = v.data.string.data; @@ -210,7 +210,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) snprintf(pattern_buflocal, BUFLOCAL_PAT_LEN, "", (int)buf->handle); ADD(buffers, CSTR_TO_OBJ(pattern_buflocal)); }); - } else if (opts->buffer.type != kObjectTypeNil) { + } else if (HAS_KEY(opts->buffer)) { VALIDATE_EXP(false, "buffer", "Integer or Array", api_typename(opts->buffer.type), { goto cleanup; }); @@ -413,10 +413,8 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc { int64_t autocmd_id = -1; char *desc = NULL; - Array patterns = ARRAY_DICT_INIT; Array event_array = ARRAY_DICT_INIT; - AucmdExecutable aucmd = AUCMD_EXECUTABLE_INIT; Callback cb = CALLBACK_NONE; @@ -424,12 +422,12 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc goto cleanup; } - VALIDATE((opts->callback.type == kObjectTypeNil || opts->command.type == kObjectTypeNil), - "Cannot use both 'callback' and 'command'", { + VALIDATE((!HAS_KEY(opts->callback) || !HAS_KEY(opts->command)), + "%s", "Cannot use both 'callback' and 'command'", { goto cleanup; }); - if (opts->callback.type != kObjectTypeNil) { + if (HAS_KEY(opts->callback)) { // NOTE: We could accept callable tables, but that isn't common in the API. Object *callback = &opts->callback; @@ -458,7 +456,7 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc aucmd.type = CALLABLE_CB; aucmd.callable.cb = cb; - } else if (opts->command.type != kObjectTypeNil) { + } else if (HAS_KEY(opts->command)) { Object *command = &opts->command; VALIDATE_T("command", kObjectTypeString, command->type, { goto cleanup; @@ -466,7 +464,7 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc aucmd.type = CALLABLE_EX; aucmd.callable.cmd = string_to_cstr(command->data.string); } else { - VALIDATE_S(false, "'command' or 'callback' is required", "", { + VALIDATE(false, "%s", "Required: 'command' or 'callback'", { goto cleanup; }); } @@ -483,7 +481,7 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc goto cleanup; } - if (opts->desc.type != kObjectTypeNil) { + if (HAS_KEY(opts->desc)) { VALIDATE_T("desc", kObjectTypeString, opts->desc.type, { goto cleanup; }); @@ -494,7 +492,7 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc ADD(patterns, STRING_OBJ(STATIC_CSTR_TO_STRING("*"))); } - VALIDATE_R((event_array.size != 0), "event", { + VALIDATE_R((event_array.size > 0), "event", { goto cleanup; }); @@ -586,8 +584,8 @@ void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Error *err) goto cleanup; } - VALIDATE((opts->pattern.type == kObjectTypeNil || opts->buffer.type == kObjectTypeNil), - "Cannot use both 'pattern' and 'buffer'", { + VALIDATE((!HAS_KEY(opts->pattern) || !HAS_KEY(opts->buffer)), + "%s", "Cannot use both 'pattern' and 'buffer'", { goto cleanup; }); @@ -764,7 +762,7 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err) }); } - if (opts->buffer.type != kObjectTypeNil) { + if (HAS_KEY(opts->buffer)) { Object buf_obj = opts->buffer; VALIDATE_EXP((buf_obj.type == kObjectTypeInteger || buf_obj.type == kObjectTypeBuffer), "buffer", "Integer", api_typename(buf_obj.type), { @@ -786,7 +784,7 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err) ADD(patterns, STRING_OBJ(STATIC_CSTR_TO_STRING(""))); } - if (opts->data.type != kObjectTypeNil) { + if (HAS_KEY(opts->data)) { data = &opts->data; } @@ -797,7 +795,7 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err) GET_ONE_EVENT(event_nr, event_str, cleanup) FOREACH_ITEM(patterns, pat, { - char *fname = opts->buffer.type == kObjectTypeNil ? pat.data.string.data : NULL; + char *fname = !HAS_KEY(opts->buffer) ? pat.data.string.data : NULL; did_aucmd |= apply_autocmds_group(event_nr, fname, NULL, true, au_group, buf, NULL, data); }) @@ -812,41 +810,19 @@ cleanup: api_free_array(patterns); } -static bool check_autocmd_string_array(Array arr, char *k, Error *err) -{ - FOREACH_ITEM(arr, entry, { - if (entry.type != kObjectTypeString) { - api_set_error(err, kErrorTypeValidation, "Invalid '%s' item type: expected String, got %s", - k, api_typename(entry.type)); - return false; - } - - // Disallow newlines in the middle of the line. - const String l = entry.data.string; - if (memchr(l.data, NL, l.size)) { - api_set_error(err, kErrorTypeValidation, "'%s' item cannot contain newlines", k); - return false; - } - }) - return true; -} - static bool unpack_string_or_array(Array *array, Object *v, char *k, bool required, Error *err) { if (v->type == kObjectTypeString) { ADD(*array, copy_object(*v, NULL)); } else if (v->type == kObjectTypeArray) { - if (!check_autocmd_string_array(v->data.array, k, err)) { + if (!check_string_array(v->data.array, k, true, err)) { return false; } *array = copy_array(v->data.array, NULL); } else { - if (required) { - api_set_error(err, kErrorTypeValidation, - "Invalid '%s' type: expected Array or String, got %s", - k, api_typename(v->type)); + VALIDATE_EXP(!required, k, "Array or String", api_typename(v->type), { return false; - } + }); } return true; @@ -886,12 +862,12 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob { const char pattern_buflocal[BUFLOCAL_PAT_LEN]; - VALIDATE((pattern.type == kObjectTypeNil || buffer.type == kObjectTypeNil), - "Cannot use both 'pattern' and 'buffer' for the same autocmd", { + VALIDATE((!HAS_KEY(pattern) || !HAS_KEY(buffer)), + "%s", "Cannot use both 'pattern' and 'buffer' for the same autocmd", { return false; }); - if (pattern.type != kObjectTypeNil) { + if (HAS_KEY(pattern)) { Object *v = &pattern; if (v->type == kObjectTypeString) { @@ -904,7 +880,7 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob patlen = aucmd_pattern_length(pat); } } else if (v->type == kObjectTypeArray) { - if (!check_autocmd_string_array(v->data.array, "pattern", err)) { + if (!check_string_array(v->data.array, "pattern", true, err)) { return false; } @@ -924,7 +900,7 @@ static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Ob return false; }); } - } else if (buffer.type != kObjectTypeNil) { + } else if (HAS_KEY(buffer)) { VALIDATE_EXP((buffer.type == kObjectTypeInteger || buffer.type == kObjectTypeBuffer), "buffer", "Integer", api_typename(buffer.type), { return false; diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index b2e78db278..9c2d14d30f 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -293,7 +293,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, start = normalize_index(buf, start, true, &oob); end = normalize_index(buf, end, true, &oob); - VALIDATE((!strict_indexing || !oob), "Index out of bounds", { + VALIDATE((!strict_indexing || !oob), "%s", "Index out of bounds", { return rv; }); @@ -320,23 +320,6 @@ end: return rv; } -static bool check_string_array(Array arr, bool disallow_nl, Error *err) -{ - for (size_t i = 0; i < arr.size; i++) { - VALIDATE_T("replacement item", kObjectTypeString, arr.items[i].type, { - return false; - }); - // Disallow newlines in the middle of the line. - if (disallow_nl) { - const String l = arr.items[i].data.string; - VALIDATE(!memchr(l.data, NL, l.size), "String cannot contain newlines", { - return false; - }); - } - } - return true; -} - /// Sets (replaces) a line-range in the buffer. /// /// Indexing is zero-based, end-exclusive. Negative indices are interpreted @@ -373,15 +356,15 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ start = normalize_index(buf, start, true, &oob); end = normalize_index(buf, end, true, &oob); - VALIDATE((!strict_indexing || !oob), "Index out of bounds", { + VALIDATE((!strict_indexing || !oob), "%s", "Index out of bounds", { return; }); - VALIDATE((start <= end), "\"start\" is higher than \"end\"", { + VALIDATE((start <= end), "%s", "'start' is higher than 'end'", { return; }); bool disallow_nl = (channel_id != VIML_INTERNAL_CALL); - if (!check_string_array(replacement, disallow_nl, err)) { + if (!check_string_array(replacement, "replacement string", disallow_nl, err)) { return; } @@ -438,7 +421,7 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ for (size_t i = 0; i < to_replace; i++) { int64_t lnum = start + (int64_t)i; - VALIDATE(lnum < MAXLNUM, "Index value is too high", { + VALIDATE(lnum < MAXLNUM, "%s", "Index out of bounds", { goto end; }); @@ -457,7 +440,7 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ for (size_t i = to_replace; i < new_len; i++) { int64_t lnum = start + (int64_t)i - 1; - VALIDATE(lnum < MAXLNUM, "Index value is too high", { + VALIDATE(lnum < MAXLNUM, "%s", "Index out of bounds", { goto end; }); @@ -546,12 +529,12 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In // check range is ordered and everything! // start_row, end_row within buffer len (except add text past the end?) start_row = normalize_index(buf, start_row, false, &oob); - VALIDATE((!oob), "start_row out of bounds", { + VALIDATE_RANGE((!oob), "start_row", { return; }); end_row = normalize_index(buf, end_row, false, &oob); - VALIDATE((!oob), "end_row out of bounds", { + VALIDATE_RANGE((!oob), "end_row", { return; }); @@ -561,24 +544,24 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In // Another call to ml_get_buf() may free the line, so make a copy. str_at_start = xstrdup(ml_get_buf(buf, (linenr_T)start_row, false)); size_t len_at_start = strlen(str_at_start); - VALIDATE((start_col >= 0 && (size_t)start_col <= len_at_start), "start_col out of bounds", { + VALIDATE_RANGE((start_col >= 0 && (size_t)start_col <= len_at_start), "start_col", { goto early_end; }); // Another call to ml_get_buf() may free the line, so make a copy. str_at_end = xstrdup(ml_get_buf(buf, (linenr_T)end_row, false)); size_t len_at_end = strlen(str_at_end); - VALIDATE((end_col >= 0 && (size_t)end_col <= len_at_end), "end_col out of bounds", { + VALIDATE_RANGE((end_col >= 0 && (size_t)end_col <= len_at_end), "end_col", { goto early_end; }); VALIDATE((start_row <= end_row && !(end_row == start_row && start_col > end_col)), - "start is higher than end", { + "%s", "'start' is higher than 'end'", { goto early_end; }); bool disallow_nl = (channel_id != VIML_INTERNAL_CALL); - if (!check_string_array(replacement, disallow_nl, err)) { + if (!check_string_array(replacement, "replacement string", disallow_nl, err)) { goto early_end; } @@ -681,7 +664,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In for (size_t i = 0; i < to_replace; i++) { int64_t lnum = start_row + (int64_t)i; - VALIDATE((lnum < MAXLNUM), "Index value is too high", { + VALIDATE((lnum < MAXLNUM), "%s", "Index out of bounds", { goto end; }); @@ -698,7 +681,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In for (size_t i = to_replace; i < new_len; i++) { int64_t lnum = start_row + (int64_t)i - 1; - VALIDATE((lnum < MAXLNUM), "Index value is too high", { + VALIDATE((lnum < MAXLNUM), "%s", "Index out of bounds", { goto end; }); @@ -777,7 +760,7 @@ ArrayOf(String) nvim_buf_get_text(uint64_t channel_id, Buffer buffer, { Array rv = ARRAY_DICT_INIT; - VALIDATE((opts.size == 0), "opts dict isn't empty", { + VALIDATE((opts.size == 0), "%s", "opts dict isn't empty", { return rv; }); @@ -796,14 +779,14 @@ ArrayOf(String) nvim_buf_get_text(uint64_t channel_id, Buffer buffer, start_row = normalize_index(buf, start_row, false, &oob); end_row = normalize_index(buf, end_row, false, &oob); - VALIDATE((!oob), "Index out of bounds", { + VALIDATE((!oob), "%s", "Index out of bounds", { return rv; }); // nvim_buf_get_lines doesn't care if the start row is greater than the end // row (it will just return an empty array), but nvim_buf_get_text does in // order to maintain symmetry with nvim_buf_set_text. - VALIDATE((start_row <= end_row), "start is higher than end", { + VALIDATE((start_row <= end_row), "%s", "'start' is higher than 'end'", { return rv; }); @@ -881,7 +864,7 @@ Integer nvim_buf_get_offset(Buffer buffer, Integer index, Error *err) return -1; } - VALIDATE((index >= 0 && index <= buf->b_ml.ml_line_count), "Index out of bounds", { + VALIDATE((index >= 0 && index <= buf->b_ml.ml_line_count), "%s", "Index out of bounds", { return 0; }); diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 0a95833256..cae3927dfd 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -100,7 +100,7 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err) { Dictionary result = ARRAY_DICT_INIT; - VALIDATE((opts.size == 0), "opts dict isn't empty", { + VALIDATE((opts.size == 0), "%s", "opts dict isn't empty", { return result; }); @@ -1021,7 +1021,7 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, name.data, { goto err; }); - VALIDATE((!HAS_KEY(opts->range) || !HAS_KEY(opts->count)), + VALIDATE((!HAS_KEY(opts->range) || !HAS_KEY(opts->count)), "%s", "Cannot use both 'range' and 'count'", { goto err; }); @@ -1065,7 +1065,7 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, }); } - VALIDATE((!HAS_KEY(opts->complete) || argt), "'complete' used without 'nargs'", { + VALIDATE((!HAS_KEY(opts->complete) || argt), "%s", "'complete' used without 'nargs'", { goto err; }); @@ -1086,8 +1086,9 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, def = opts->range.data.integer; addr_type_arg = ADDR_LINES; } else if (HAS_KEY(opts->range)) { - api_set_error(err, kErrorTypeValidation, "Invalid value for 'range'"); - goto err; + VALIDATE_S(false, "range", "", { + goto err; + }); } if (opts->count.type == kObjectTypeBoolean) { @@ -1101,23 +1102,25 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, addr_type_arg = ADDR_OTHER; def = opts->count.data.integer; } else if (HAS_KEY(opts->count)) { - api_set_error(err, kErrorTypeValidation, "Invalid value for 'count'"); - goto err; + VALIDATE_S(false, "count", "", { + goto err; + }); } - if (opts->addr.type == kObjectTypeString) { - if (parse_addr_type_arg(opts->addr.data.string.data, (int)opts->addr.data.string.size, - &addr_type_arg) != OK) { - api_set_error(err, kErrorTypeValidation, "Invalid value for 'addr'"); + if (HAS_KEY(opts->addr)) { + VALIDATE_T("addr", kObjectTypeString, opts->addr.type, { goto err; - } + }); + + VALIDATE_S(OK == parse_addr_type_arg(opts->addr.data.string.data, + (int)opts->addr.data.string.size, &addr_type_arg), "addr", + opts->addr.data.string.data, { + goto err; + }); if (addr_type_arg != ADDR_LINES) { argt |= EX_ZEROR; } - } else if (HAS_KEY(opts->addr)) { - api_set_error(err, kErrorTypeValidation, "Invalid value for 'addr'"); - goto err; } if (api_object_to_bool(opts->bang, "bang", false, err)) { @@ -1153,23 +1156,25 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, compl = EXPAND_USER_LUA; compl_luaref = api_new_luaref(opts->complete.data.luaref); } else if (opts->complete.type == kObjectTypeString) { - if (parse_compl_arg(opts->complete.data.string.data, - (int)opts->complete.data.string.size, &compl, &argt, - &compl_arg) != OK) { - api_set_error(err, kErrorTypeValidation, "Invalid value for 'complete'"); + VALIDATE_S(OK == parse_compl_arg(opts->complete.data.string.data, + (int)opts->complete.data.string.size, &compl, &argt, + &compl_arg), + "complete", opts->complete.data.string.data, { goto err; - } + }); } else if (HAS_KEY(opts->complete)) { - api_set_error(err, kErrorTypeValidation, "Invalid value for 'complete'"); - goto err; + VALIDATE(false, "%s", "Invalid complete: expected Function or String", { + goto err; + }); } - if (opts->preview.type == kObjectTypeLuaRef) { + if (HAS_KEY(opts->preview)) { + VALIDATE_T("preview", kObjectTypeLuaRef, opts->preview.type, { + goto err; + }); + argt |= EX_PREVIEW; preview_luaref = api_new_luaref(opts->preview.data.luaref); - } else if (HAS_KEY(opts->preview)) { - api_set_error(err, kErrorTypeValidation, "Invalid value for 'preview'"); - goto err; } switch (command.type) { @@ -1185,8 +1190,9 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, rep = command.data.string.data; break; default: - api_set_error(err, kErrorTypeValidation, "'command' must be a string or Lua function"); - goto err; + VALIDATE(false, "%s", "Invalid command: expected Function or String", { + goto err; + }); } if (uc_add_command(name.data, name.size, rep, argt, def, flags, compl, compl_arg, compl_luaref, diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 71ba9cfd4c..15f759eddf 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -520,7 +520,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer // For backward compatibility we support "end_line" as an alias for "end_row" if (HAS_KEY(opts->end_line)) { - VALIDATE(!HAS_KEY(opts->end_row), "cannot use both end_row and end_line", { + VALIDATE(!HAS_KEY(opts->end_row), "%s", "cannot use both 'end_row' and 'end_line'", { goto error; }); opts->end_row = opts->end_line; @@ -535,30 +535,29 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer bool strict = true; OPTION_TO_BOOL(strict, strict, true); - if (opts->end_row.type == kObjectTypeInteger) { - Integer val = opts->end_row.data.integer; - VALIDATE((val >= 0 && !(val > buf->b_ml.ml_line_count && strict)), - "end_row value outside range", { + if (HAS_KEY(opts->end_row)) { + VALIDATE_T("end_row", kObjectTypeInteger, opts->end_row.type, { goto error; }); - line2 = (int)val; - } else if (HAS_KEY(opts->end_row)) { - VALIDATE_T("end_row", kObjectTypeInteger, opts->end_row.type, { + + Integer val = opts->end_row.data.integer; + VALIDATE_RANGE((val >= 0 && !(val > buf->b_ml.ml_line_count && strict)), "end_row", { goto error; }); + line2 = (int)val; } colnr_T col2 = -1; - if (opts->end_col.type == kObjectTypeInteger) { - Integer val = opts->end_col.data.integer; - VALIDATE((val >= 0 && val <= MAXCOL), "end_col value outside range", { + if (HAS_KEY(opts->end_col)) { + VALIDATE_T("end_col", kObjectTypeInteger, opts->end_col.type, { goto error; }); - col2 = (int)val; - } else if (HAS_KEY(opts->end_col)) { - VALIDATE_T("end_col", kObjectTypeInteger, opts->end_col.type, { + + Integer val = opts->end_col.data.integer; + VALIDATE_RANGE((val >= 0 && val <= MAXCOL), "end_col", { goto error; }); + col2 = (int)val; } // uncrustify:off @@ -588,33 +587,37 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer } } - if (opts->conceal.type == kObjectTypeString) { + if (HAS_KEY(opts->conceal)) { + VALIDATE_T("conceal", kObjectTypeString, opts->conceal.type, { + goto error; + }); + String c = opts->conceal.data.string; decor.conceal = true; if (c.size) { decor.conceal_char = utf_ptr2char(c.data); } has_decor = true; - } else if (HAS_KEY(opts->conceal)) { - VALIDATE_T("conceal", kObjectTypeString, opts->conceal.type, { + } + + if (HAS_KEY(opts->virt_text)) { + VALIDATE_T("virt_text", kObjectTypeArray, opts->virt_text.type, { goto error; }); - } - if (opts->virt_text.type == kObjectTypeArray) { decor.virt_text = parse_virt_text(opts->virt_text.data.array, err, &decor.virt_text_width); has_decor = true; if (ERROR_SET(err)) { goto error; } - } else if (HAS_KEY(opts->virt_text)) { - VALIDATE_T("virt_text", kObjectTypeArray, opts->virt_text.type, { + } + + if (HAS_KEY(opts->virt_text_pos)) { + VALIDATE_T("virt_text_pos", kObjectTypeString, opts->virt_text_pos.type, { goto error; }); - } - if (opts->virt_text_pos.type == kObjectTypeString) { String str = opts->virt_text_pos.data.string; if (strequal("eol", str.data)) { decor.virt_text_pos = kVTEndOfLine; @@ -627,19 +630,15 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer goto error; }); } - } else if (HAS_KEY(opts->virt_text_pos)) { - VALIDATE_T("virt_text_pos", kObjectTypeString, opts->virt_text_pos.type, { - goto error; - }); } - if (opts->virt_text_win_col.type == kObjectTypeInteger) { - decor.col = (int)opts->virt_text_win_col.data.integer; - decor.virt_text_pos = kVTWinCol; - } else if (HAS_KEY(opts->virt_text_win_col)) { + if (HAS_KEY(opts->virt_text_win_col)) { VALIDATE_T("virt_text_win_col", kObjectTypeInteger, opts->virt_text_win_col.type, { goto error; }); + + decor.col = (int)opts->virt_text_win_col.data.integer; + decor.virt_text_pos = kVTWinCol; } OPTION_TO_BOOL(decor.virt_text_hide, virt_text_hide, false); @@ -667,7 +666,11 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer bool virt_lines_leftcol = false; OPTION_TO_BOOL(virt_lines_leftcol, virt_lines_leftcol, false); - if (opts->virt_lines.type == kObjectTypeArray) { + if (HAS_KEY(opts->virt_lines)) { + VALIDATE_T("virt_lines", kObjectTypeArray, opts->virt_lines.type, { + goto error; + }); + Array a = opts->virt_lines.data.array; for (size_t j = 0; j < a.size; j++) { VALIDATE_T("virt_text_line", kObjectTypeArray, a.items[j].type, { @@ -681,37 +684,33 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer } has_decor = true; } - } else if (HAS_KEY(opts->virt_lines)) { - VALIDATE_T("virt_lines", kObjectTypeArray, opts->virt_lines.type, { - goto error; - }); } OPTION_TO_BOOL(decor.virt_lines_above, virt_lines_above, false); - if (opts->priority.type == kObjectTypeInteger) { + if (HAS_KEY(opts->priority)) { + VALIDATE_T("priority", kObjectTypeInteger, opts->priority.type, { + goto error; + }); + Integer val = opts->priority.data.integer; - VALIDATE_S((val >= 0 && val <= UINT16_MAX), "priority", "(out of range)", { + VALIDATE_RANGE((val >= 0 && val <= UINT16_MAX), "priority", { goto error; }); decor.priority = (DecorPriority)val; - } else if (HAS_KEY(opts->priority)) { - VALIDATE_T("priority", kObjectTypeInteger, opts->priority.type, { + } + + if (HAS_KEY(opts->sign_text)) { + VALIDATE_T("sign_text", kObjectTypeString, opts->sign_text.type, { goto error; }); - } - if (opts->sign_text.type == kObjectTypeString) { VALIDATE_S(init_sign_text(&decor.sign_text, opts->sign_text.data.string.data), "sign_text", "", { goto error; }); has_decor = true; - } else if (HAS_KEY(opts->sign_text)) { - VALIDATE_T("sign_text", kObjectTypeString, opts->sign_text.type, { - goto error; - }); } bool right_gravity = true; @@ -720,7 +719,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer // Only error out if they try to set end_right_gravity without // setting end_col or end_row VALIDATE(!(line2 == -1 && col2 == -1 && HAS_KEY(opts->end_right_gravity)), - "cannot set end_right_gravity without setting end_row or end_col", { + "%s", "cannot set end_right_gravity without end_row or end_col", { goto error; }); @@ -732,7 +731,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer bool ephemeral = false; OPTION_TO_BOOL(ephemeral, ephemeral, false); - if (opts->spell.type == kObjectTypeNil) { + if (!HAS_KEY(opts->spell)) { decor.spell = kNone; } else { bool spell = false; @@ -746,12 +745,12 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer has_decor = true; } - VALIDATE_S((line >= 0), "line", "(out of range)", { + VALIDATE_RANGE((line >= 0), "line", { goto error; }); if (line > buf->b_ml.ml_line_count) { - VALIDATE_S(!strict, "line", "(out of range)", { + VALIDATE_RANGE(!strict, "line", { goto error; }); line = buf->b_ml.ml_line_count; @@ -762,12 +761,12 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer if (col == -1) { col = (Integer)len; } else if (col > (Integer)len) { - VALIDATE_S(!strict, "col", "(out of range)", { + VALIDATE_RANGE(!strict, "col", { goto error; }); col = (Integer)len; } else if (col < -1) { - VALIDATE_S(false, "col", "(out of range)", { + VALIDATE_RANGE(false, "col", { goto error; }); } @@ -783,7 +782,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer line2 = (int)line; } if (col2 > (Integer)len) { - VALIDATE_S(!strict, "end_col", "(out of range)", { + VALIDATE_RANGE(!strict, "end_col", { goto error; }); col2 = (int)len; @@ -886,10 +885,10 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In return 0; } - VALIDATE_S((line >= 0 && line < MAXLNUM), "line number", "(out of range)", { + VALIDATE_RANGE((line >= 0 && line < MAXLNUM), "line number", { return 0; }); - VALIDATE_S((col_start >= 0 && col_start <= MAXCOL), "column", "(out of range)", { + VALIDATE_RANGE((col_start >= 0 && col_start <= MAXCOL), "column", { return 0; }); @@ -948,7 +947,7 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start, return; } - VALIDATE_S((line_start >= 0 && line_start < MAXLNUM), "line number", "(out of range)", { + VALIDATE_RANGE((line_start >= 0 && line_start < MAXLNUM), "line number", { return; }); @@ -1092,7 +1091,7 @@ static bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, in VALIDATE((pos.size == 2 && pos.items[0].type == kObjectTypeInteger && pos.items[1].type == kObjectTypeInteger), - "Invalid position: expected 2 Integer items", { + "%s", "Invalid position: expected 2 Integer items", { return false; }); @@ -1102,7 +1101,7 @@ static bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, in *col = (colnr_T)(pos_col >= 0 ? pos_col : MAXCOL); return true; } else { - VALIDATE(false, "Invalid position: expected mark id Integer or 2-item Array", { + VALIDATE(false, "%s", "Invalid position: expected mark id Integer or 2-item Array", { return false; }); } @@ -1153,7 +1152,7 @@ VirtText parse_virt_text(Array chunks, Error *err, int *width) }); Array chunk = chunks.items[i].data.array; VALIDATE((chunk.size > 0 && chunk.size <= 2 && chunk.items[0].type == kObjectTypeString), - "Invalid chunk: expected Array with 1 or 2 Strings", { + "%s", "Invalid chunk: expected Array with 1 or 2 Strings", { goto free_exit; }); diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index 5b57b49ad6..40720c31c7 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -26,54 +26,54 @@ static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_type, void **from, Error *err) { - if (opts->scope.type == kObjectTypeString) { + if (HAS_KEY(opts->scope)) { + VALIDATE_T("scope", kObjectTypeString, opts->scope.type, { + return FAIL; + }); + if (!strcmp(opts->scope.data.string.data, "local")) { *scope = OPT_LOCAL; } else if (!strcmp(opts->scope.data.string.data, "global")) { *scope = OPT_GLOBAL; } else { - VALIDATE(false, "Invalid scope (expected 'local' or 'global')", { + VALIDATE(false, "%s", "Invalid scope: expected 'local' or 'global'", { return FAIL; }); } - } else if (HAS_KEY(opts->scope)) { - VALIDATE_T("scope", kObjectTypeString, opts->scope.type, { - return FAIL; - }); - return FAIL; } *opt_type = SREQ_GLOBAL; - if (opts->win.type == kObjectTypeInteger) { + if (HAS_KEY(opts->win)) { + VALIDATE_T("win", kObjectTypeInteger, opts->win.type, { + return FAIL; + }); + *opt_type = SREQ_WIN; *from = find_window_by_handle((int)opts->win.data.integer, err); if (ERROR_SET(err)) { return FAIL; } - } else if (HAS_KEY(opts->win)) { - VALIDATE_T("win", kObjectTypeInteger, opts->win.type, { + } + + if (HAS_KEY(opts->buf)) { + VALIDATE_T("buf", kObjectTypeInteger, opts->buf.type, { return FAIL; }); - } - if (opts->buf.type == kObjectTypeInteger) { *scope = OPT_LOCAL; *opt_type = SREQ_BUF; *from = find_buffer_by_handle((int)opts->buf.data.integer, err); if (ERROR_SET(err)) { return FAIL; } - } else if (HAS_KEY(opts->buf)) { - VALIDATE_T("buf", kObjectTypeInteger, opts->buf.type, { - return FAIL; - }); } - VALIDATE((!HAS_KEY(opts->scope) || !HAS_KEY(opts->buf)), "cannot use both 'scope' and 'buf'", { + VALIDATE((!HAS_KEY(opts->scope) || !HAS_KEY(opts->buf)), "%s", + "cannot use both 'scope' and 'buf'", { return FAIL; }); - VALIDATE((!HAS_KEY(opts->win) || !HAS_KEY(opts->buf)), "cannot use both 'buf' and 'win'", { + VALIDATE((!HAS_KEY(opts->win) || !HAS_KEY(opts->buf)), "%s", "cannot use both 'buf' and 'win'", { return FAIL; }); @@ -427,21 +427,21 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object char *stringval = NULL; if (flags & SOPT_BOOL) { - VALIDATE_FMT(value.type == kObjectTypeBoolean, "Option '%s' value must be Boolean", name.data, { + VALIDATE(value.type == kObjectTypeBoolean, "Option '%s' value must be Boolean", name.data, { return; }); numval = value.data.boolean; } else if (flags & SOPT_NUM) { - VALIDATE_FMT(value.type == kObjectTypeInteger, "Option '%s' value must be Integer", name.data, { + VALIDATE(value.type == kObjectTypeInteger, "Option '%s' value must be Integer", name.data, { return; }); - VALIDATE_FMT((value.data.integer <= INT_MAX && value.data.integer >= INT_MIN), - "Option '%s' value is out of range", name.data, { + VALIDATE((value.data.integer <= INT_MAX && value.data.integer >= INT_MIN), + "Option '%s' value is out of range", name.data, { return; }); numval = (int)value.data.integer; } else { - VALIDATE_FMT(value.type == kObjectTypeString, "Option '%s' value must be String", name.data, { + VALIDATE(value.type == kObjectTypeString, "Option '%s' value must be String", name.data, { return; }); stringval = value.data.string.data; diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 6beb3d8683..c996e19eb9 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -821,8 +821,7 @@ int object_to_hl_id(Object obj, const char *what, Error *err) } else if (obj.type == kObjectTypeInteger) { return MAX((int)obj.data.integer, 0); } else { - api_set_error(err, kErrorTypeValidation, - "%s is not a valid highlight", what); + api_set_error(err, kErrorTypeValidation, "Invalid highlight: %s", what); return 0; } } diff --git a/src/nvim/api/private/validate.c b/src/nvim/api/private/validate.c new file mode 100644 index 0000000000..41c9472a39 --- /dev/null +++ b/src/nvim/api/private/validate.c @@ -0,0 +1,28 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/private/validate.c.generated.h" +#endif + +bool check_string_array(Array arr, char *name, bool disallow_nl, Error *err) +{ + snprintf(IObuff, sizeof(IObuff), "'%s' item", name); + for (size_t i = 0; i < arr.size; i++) { + VALIDATE_T(IObuff, kObjectTypeString, arr.items[i].type, { + return false; + }); + // Disallow newlines in the middle of the line. + if (disallow_nl) { + const String l = arr.items[i].data.string; + VALIDATE(!memchr(l.data, NL, l.size), "'%s' item contains newlines", name, { + return false; + }); + } + } + return true; +} diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index 8448b416be..4a1b99408e 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -24,19 +24,11 @@ } \ } while (0) -#define VALIDATE_R(cond, name, code) \ - do { \ - if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, "'" name "' is required"); \ - code; \ - } \ - } while (0) - #define VALIDATE_EXP(cond, name, expected, actual, code) \ do { \ if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, "Invalid " name ": expected %s, got %s", \ - expected, actual); \ + api_set_error(err, kErrorTypeValidation, "Invalid %s: expected %s, got %s", \ + name, expected, actual); \ code; \ } \ } while (0) @@ -50,20 +42,27 @@ } \ } while (0) -#define VALIDATE(cond, msg_, code) \ +#define VALIDATE(cond, fmt_, fmt_arg1, code) \ do { \ if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, "%s", msg_); \ + api_set_error(err, kErrorTypeValidation, fmt_, fmt_arg1); \ code; \ } \ } while (0) -#define VALIDATE_FMT(cond, fmt_, msg_, code) \ +#define VALIDATE_RANGE(cond, name, code) \ do { \ if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, fmt_, msg_); \ + api_set_error(err, kErrorTypeValidation, "Invalid '%s': out of range", name); \ code; \ } \ } while (0) +#define VALIDATE_R(cond, name, code) \ + VALIDATE(cond, "Required: '%s'", name, code); + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/private/validate.h.generated.h" +#endif + #endif // NVIM_API_PRIVATE_VALIDATE_H diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 8f5465db77..61f2c881b3 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -12,6 +12,7 @@ #include "klib/kvec.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/api/ui.h" #include "nvim/autocmd.h" #include "nvim/channel.h" @@ -291,22 +292,20 @@ void nvim_ui_set_option(uint64_t channel_id, String name, Object value, Error *e ui_set_option(ui, false, name, value, error); } -static void ui_set_option(UI *ui, bool init, String name, Object value, Error *error) +static void ui_set_option(UI *ui, bool init, String name, Object value, Error *err) { if (strequal(name.data, "override")) { - if (value.type != kObjectTypeBoolean) { - api_set_error(error, kErrorTypeValidation, "override must be a Boolean"); + VALIDATE_T("override", kObjectTypeBoolean, value.type, { return; - } + }); ui->override = value.data.boolean; return; } if (strequal(name.data, "rgb")) { - if (value.type != kObjectTypeBoolean) { - api_set_error(error, kErrorTypeValidation, "rgb must be a Boolean"); + VALIDATE_T("rgb", kObjectTypeBoolean, value.type, { return; - } + }); ui->rgb = value.data.boolean; // A little drastic, but only takes effect for legacy uis. For linegrid UI // only changes metadata for nvim_list_uis(), no refresh needed. @@ -317,62 +316,56 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e } if (strequal(name.data, "term_name")) { - if (value.type != kObjectTypeString) { - api_set_error(error, kErrorTypeValidation, "term_name must be a String"); + VALIDATE_T("term_name", kObjectTypeString, value.type, { return; - } + }); set_tty_option("term", string_to_cstr(value.data.string)); return; } if (strequal(name.data, "term_colors")) { - if (value.type != kObjectTypeInteger) { - api_set_error(error, kErrorTypeValidation, "term_colors must be a Integer"); + VALIDATE_T("term_colors", kObjectTypeInteger, value.type, { return; - } + }); t_colors = (int)value.data.integer; return; } if (strequal(name.data, "term_background")) { - if (value.type != kObjectTypeString) { - api_set_error(error, kErrorTypeValidation, "term_background must be a String"); + VALIDATE_T("term_background", kObjectTypeString, value.type, { return; - } + }); set_tty_background(value.data.string.data); return; } if (strequal(name.data, "stdin_fd")) { - if (value.type != kObjectTypeInteger || value.data.integer < 0) { - api_set_error(error, kErrorTypeValidation, "stdin_fd must be a non-negative Integer"); + VALIDATE_T("stdin_fd", kObjectTypeInteger, value.type, { return; - } - - if (starting != NO_SCREEN) { - api_set_error(error, kErrorTypeValidation, - "stdin_fd can only be used with first attached ui"); + }); + VALIDATE_INT((value.data.integer >= 0), "stdin_fd", value.data.integer, { return; - } + }); + VALIDATE((starting == NO_SCREEN), "%s", "stdin_fd can only be used with first attached UI", { + return; + }); stdin_fd = (int)value.data.integer; return; } if (strequal(name.data, "stdin_tty")) { - if (value.type != kObjectTypeBoolean) { - api_set_error(error, kErrorTypeValidation, "stdin_tty must be a Boolean"); + VALIDATE_T("stdin_tty", kObjectTypeBoolean, value.type, { return; - } + }); stdin_isatty = value.data.boolean; return; } if (strequal(name.data, "stdout_tty")) { - if (value.type != kObjectTypeBoolean) { - api_set_error(error, kErrorTypeValidation, "stdout_tty must be a Boolean"); + VALIDATE_T("stdout_tty", kObjectTypeBoolean, value.type, { return; - } + }); stdout_isatty = value.data.boolean; return; } @@ -383,17 +376,15 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e for (UIExtension i = 0; i < kUIExtCount; i++) { if (strequal(name.data, ui_ext_names[i]) || (i == kUIPopupmenu && is_popupmenu)) { - if (value.type != kObjectTypeBoolean) { - api_set_error(error, kErrorTypeValidation, "%s must be a Boolean", - name.data); + VALIDATE_EXP((value.type == kObjectTypeBoolean), name.data, "Boolean", + api_typename(value.type), { return; - } + }); bool boolval = value.data.boolean; if (!init && i == kUILinegrid && boolval != ui->ui_ext[i]) { // There shouldn't be a reason for an UI to do this ever // so explicitly don't support this. - api_set_error(error, kErrorTypeValidation, - "ext_linegrid option cannot be changed"); + api_set_error(err, kErrorTypeValidation, "ext_linegrid option cannot be changed"); } ui->ui_ext[i] = boolval; if (!init) { @@ -403,8 +394,7 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e } } - api_set_error(error, kErrorTypeValidation, "No such UI option: %s", - name.data); + api_set_error(err, kErrorTypeValidation, "No such UI option: %s", name.data); } /// Tell Nvim to resize a grid. Triggers a grid_resize event with the requested diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 333749c42f..50683ac403 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -87,10 +87,9 @@ Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Arena *arena, Error *er Dictionary result = ARRAY_DICT_INIT; int id = syn_name2id(name.data); - if (id == 0) { - api_set_error(err, kErrorTypeException, "Invalid highlight name: %s", name.data); + VALIDATE_S((id != 0), "highlight name", name.data, { return result; - } + }); return nvim_get_hl_by_id(id, rgb, arena, err); } @@ -104,10 +103,9 @@ Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Arena *arena, Error *er FUNC_API_SINCE(3) { Dictionary dic = ARRAY_DICT_INIT; - if (syn_get_final_id((int)hl_id) == 0) { - api_set_error(err, kErrorTypeException, "Invalid highlight id: %" PRId64, hl_id); + VALIDATE_INT((syn_get_final_id((int)hl_id) != 0), "highlight id", hl_id, { return dic; - } + }); int attrcode = syn_id2attr((int)hl_id); return hl_get_attr_by_id(attrcode, rgb, arena, err); } @@ -174,10 +172,9 @@ void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err) FUNC_API_SINCE(7) { int hl_id = syn_check_group(name.data, name.size); - if (hl_id == 0) { - api_set_error(err, kErrorTypeException, "Invalid highlight name: %s", name.data); + VALIDATE_S((hl_id != 0), "highlight name", name.data, { return; - } + }); int link_id = -1; HlAttrs attrs = dict2hlattrs(val, true, &link_id, err); @@ -403,11 +400,9 @@ void nvim_input_mouse(String button, String action, String modifier, Integer gri continue; } int mod = name_to_mod_mask(byte); - if (mod == 0) { - api_set_error(err, kErrorTypeValidation, - "invalid modifier %c", byte); + VALIDATE((mod != 0), "Invalid modifier: %c", byte, { return; - } + }); modmask |= mod; } @@ -500,7 +495,7 @@ Object nvim_notify(String msg, Integer log_level, Dictionary opts, Error *err) Integer nvim_strwidth(String text, Error *err) FUNC_API_SINCE(1) { - VALIDATE((text.size <= INT_MAX), "text length (too long)", { + VALIDATE_S((text.size <= INT_MAX), "text length", "(too long)", { return 0; }); @@ -574,8 +569,7 @@ ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, E { bool is_lua = api_object_to_bool(opts->is_lua, "is_lua", false, err); bool source = api_object_to_bool(opts->do_source, "do_source", false, err); - VALIDATE((!source || nlua_is_deferred_safe()), "'do_source' used in fast callback", {}); - + VALIDATE((!source || nlua_is_deferred_safe()), "%s", "'do_source' used in fast callback", {}); if (ERROR_SET(err)) { return (Array)ARRAY_DICT_INIT; } @@ -599,7 +593,7 @@ ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, E void nvim_set_current_dir(String dir, Error *err) FUNC_API_SINCE(1) { - VALIDATE((dir.size < MAXPATHL), "directory name (too long)", { + VALIDATE_S((dir.size < MAXPATHL), "directory name", "(too long)", { return; }); @@ -1067,7 +1061,7 @@ void nvim_chan_send(Integer chan, String data, Error *err) channel_send((uint64_t)chan, data.data, data.size, false, &error); - VALIDATE(!error, error, {}); + VALIDATE(!error, "%s", error, {}); } /// Gets the current list of tabpage handles. @@ -1334,12 +1328,11 @@ Dictionary nvim_get_context(Dict(context) *opts, Error *err) FUNC_API_SINCE(6) { Array types = ARRAY_DICT_INIT; - if (opts->types.type == kObjectTypeArray) { - types = opts->types.data.array; - } else if (opts->types.type != kObjectTypeNil) { + if (HAS_KEY(opts->types)) { VALIDATE_T("types", kObjectTypeArray, opts->types.type, { return (Dictionary)ARRAY_DICT_INIT; }); + types = opts->types.data.array; } int int_types = types.size > 0 ? 0 : kCtxAll; @@ -1643,7 +1636,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er goto theend; }); Array call = calls.items[i].data.array; - VALIDATE((call.size == 2), "Items in calls array must be arrays of size 2", { + VALIDATE((call.size == 2), "%s", "calls item must be a 2-item Array", { goto theend; }); VALIDATE_T("name", kObjectTypeString, call.items[0].type, { @@ -1824,10 +1817,9 @@ Array nvim_get_proc_children(Integer pid, Error *err) Array rvobj = ARRAY_DICT_INIT; int *proc_list = NULL; - if (pid <= 0 || pid > INT_MAX) { - api_set_error(err, kErrorTypeException, "Invalid pid: %" PRId64, pid); + VALIDATE_INT((pid > 0 && pid <= INT_MAX), "pid", pid, { goto end; - } + }); size_t proc_count; int rv = os_proc_children((int)pid, &proc_list, &proc_count); @@ -1866,10 +1858,10 @@ Object nvim_get_proc(Integer pid, Error *err) rvobj.data.dictionary = (Dictionary)ARRAY_DICT_INIT; rvobj.type = kObjectTypeDictionary; - if (pid <= 0 || pid > INT_MAX) { - api_set_error(err, kErrorTypeException, "Invalid pid: %" PRId64, pid); + VALIDATE_INT((pid > 0 && pid <= INT_MAX), "pid", pid, { return NIL; - } + }); + #ifdef MSWIN rvobj.data.dictionary = os_proc_info((int)pid); if (rvobj.data.dictionary.size == 0) { // Process not found. @@ -1911,7 +1903,7 @@ void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Di Error *err) FUNC_API_SINCE(6) { - VALIDATE((opts.size == 0), "opts dict isn't empty", { + VALIDATE((opts.size == 0), "%s", "opts dict isn't empty", { return; }); @@ -2100,7 +2092,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * if (str.size < 2 || memcmp(str.data, "%!", 2) != 0) { const char *const errmsg = check_stl_option(str.data); - VALIDATE(!errmsg, errmsg, { + VALIDATE(!errmsg, "%s", errmsg, { return result; }); } @@ -2119,7 +2111,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * VALIDATE((opts->fillchar.data.string.size != 0 && ((size_t)utf_ptr2len(opts->fillchar.data.string.data) == opts->fillchar.data.string.size)), - "Invalid fillchar (not a single character)", { + "%s", "Invalid fillchar: expected single character", { return result; }); fillchar = utf_ptr2char(opts->fillchar.data.string.data); @@ -2145,10 +2137,9 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * return result; } } - if (use_winbar && use_tabline) { - api_set_error(err, kErrorTypeValidation, "use_winbar and use_tabline are mutually exclusive"); + VALIDATE(!(use_winbar && use_tabline), "%s", "Cannot use both 'use_winbar' and 'use_tabline'", { return result; - } + }); win_T *wp, *ewp; diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 5936e4ff2b..5e53bf273f 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -12,6 +12,7 @@ #include "lauxlib.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/validate.h" #include "nvim/api/ui.h" #include "nvim/decoration_provider.h" #include "nvim/drawscreen.h" @@ -971,35 +972,33 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e return hlattrs; } - if (dict->blend.type == kObjectTypeInteger) { + if (HAS_KEY(dict->blend)) { + VALIDATE_T("blend", kObjectTypeInteger, dict->blend.type, { + return hlattrs; + }); + Integer blend0 = dict->blend.data.integer; - if (blend0 < 0 || blend0 > 100) { - api_set_error(err, kErrorTypeValidation, "'blend' is not between 0 to 100"); - } else { - blend = (int)blend0; - } - } else if (HAS_KEY(dict->blend)) { - api_set_error(err, kErrorTypeValidation, "'blend' must be an integer"); - } - if (ERROR_SET(err)) { - return hlattrs; + VALIDATE_RANGE((blend0 >= 0 && blend0 <= 100), "blend", { + return hlattrs; + }); + blend = (int)blend0; } if (HAS_KEY(dict->link) || HAS_KEY(dict->global_link)) { - if (link_id) { - if (HAS_KEY(dict->global_link)) { - *link_id = object_to_hl_id(dict->global_link, "link", err); - mask |= HL_GLOBAL; - } else { - *link_id = object_to_hl_id(dict->link, "link", err); - } - - if (ERROR_SET(err)) { - return hlattrs; - } - } else { + if (!link_id) { api_set_error(err, kErrorTypeValidation, "Invalid Key: '%s'", HAS_KEY(dict->global_link) ? "global_link" : "link"); + return hlattrs; + } + if (HAS_KEY(dict->global_link)) { + *link_id = object_to_hl_id(dict->global_link, "link", err); + mask |= HL_GLOBAL; + } else { + *link_id = object_to_hl_id(dict->link, "link", err); + } + + if (ERROR_SET(err)) { + return hlattrs; } } @@ -1026,7 +1025,9 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e // TODO(clason): handle via gen_api_dispatch cterm_mask_provided = true; } else if (HAS_KEY(dict->cterm)) { - api_set_error(err, kErrorTypeValidation, "'cterm' must be a Dictionary."); + VALIDATE_T("cterm", kObjectTypeDictionary, dict->cterm.type, { + return hlattrs; + }); } #undef CHECK_FLAG @@ -1083,13 +1084,14 @@ int object_to_color(Object val, char *key, bool rgb, Error *err) } else { color = name_to_ctermcolor(str.data); } - if (color < 0) { - api_set_error(err, kErrorTypeValidation, "'%s' is not a valid color", str.data); - } + VALIDATE_S((color >= 0), "highlight color", str.data, { + return color; + }); return color; } else { - api_set_error(err, kErrorTypeValidation, "'%s' must be string or integer", key); - return 0; + VALIDATE(false, "Invalid %s: expected String or Integer", key, { + return 0; + }); } } -- cgit From 39f8aaeb815c2e31cffec12ef36ad4f25df91602 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Fri, 24 Jan 2020 09:48:58 +0100 Subject: fix(status): handle unprintable chars in the statusline --- src/nvim/buffer.c | 2 +- src/nvim/charset.c | 11 ++++++----- src/nvim/grid.c | 16 ++++++++++++---- src/nvim/statusline.c | 37 +++++++++++++++++-------------------- 4 files changed, 36 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 5dcb10751f..129a8c6fb2 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3311,7 +3311,7 @@ void maketitle(void) buf_p += MIN(size, SPACE_FOR_FNAME); } else { buf_p += transstr_buf((const char *)path_tail(curbuf->b_fname), - buf_p, SPACE_FOR_FNAME + 1, true); + -1, buf_p, SPACE_FOR_FNAME + 1, true); } switch (bufIsChanged(curbuf) diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 5aec9ccf9d..c4c7c5f387 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -354,14 +354,15 @@ size_t transstr_len(const char *const s, bool untab) /// @param[in] untab remove tab characters /// /// @return length of the resulting string, without the NUL byte. -size_t transstr_buf(const char *const s, char *const buf, const size_t len, bool untab) +size_t transstr_buf(const char *const s, const ssize_t slen, char *const buf, const size_t buflen, + bool untab) FUNC_ATTR_NONNULL_ALL { const char *p = s; char *buf_p = buf; - char *const buf_e = buf_p + len - 1; + char *const buf_e = buf_p + buflen - 1; - while (*p != NUL && buf_p < buf_e) { + while ((slen < 0 || (p - s) < slen) && *p != NUL && buf_p < buf_e) { const size_t l = (size_t)utfc_ptr2len(p); if (l > 1) { if (buf_p + l > buf_e) { @@ -416,7 +417,7 @@ char *transstr(const char *const s, bool untab) // multi-byte characters. const size_t len = transstr_len(s, untab) + 1; char *const buf = xmalloc(len); - transstr_buf(s, buf, len, untab); + transstr_buf(s, -1, buf, len, untab); return buf; } @@ -431,7 +432,7 @@ size_t kv_transstr(StringBuilder *str, const char *const s, bool untab) // multi-byte characters. const size_t len = transstr_len(s, untab); kv_ensure_space(*str, len + 1); - transstr_buf(s, str->items + str->size, len + 1, untab); + transstr_buf(s, -1, str->items + str->size, len + 1, untab); str->size += len; // do not include NUL byte return len; } diff --git a/src/nvim/grid.c b/src/nvim/grid.c index 16ebbfbb90..efbeac4f3f 100644 --- a/src/nvim/grid.c +++ b/src/nvim/grid.c @@ -158,9 +158,9 @@ void grid_getbytes(ScreenGrid *grid, int row, int col, char *bytes, int *attrp) /// attributes 'attr', and update chars[] and attrs[]. /// Note: only outputs within one row, message is truncated at grid boundary! /// Note: if grid, row and/or col is invalid, nothing is done. -void grid_puts(ScreenGrid *grid, char *text, int row, int col, int attr) +int grid_puts(ScreenGrid *grid, char *text, int row, int col, int attr) { - grid_puts_len(grid, text, -1, row, col, attr); + return grid_puts_len(grid, text, -1, row, col, attr); } static ScreenGrid *put_dirty_grid = NULL; @@ -197,7 +197,7 @@ void grid_put_schar(ScreenGrid *grid, int row, int col, char *schar, int attr) /// like grid_puts(), but output "text[len]". When "len" is -1 output up to /// a NUL. -void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, int attr) +int grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, int attr) { size_t off; char *ptr = text; @@ -218,7 +218,7 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, if (grid->chars == NULL || row >= grid->rows || row < 0 || col >= grid->cols || col < 0) { - return; + return 0; } if (put_dirty_row == -1) { @@ -230,6 +230,7 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, } } off = grid->line_offset[row] + (size_t)col; + int start_col = col; // When drawing over the right half of a double-wide char clear out the // left half. Only needed in a terminal. @@ -252,6 +253,12 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, ? utfc_ptr2char_len(ptr, u8cc, (int)((text + len) - ptr)) : utfc_ptr2char(ptr, u8cc); int mbyte_cells = utf_char2cells(u8c); + if (mbyte_cells > 2) { + mbyte_cells = 1; + u8c = 0xFFFD; + u8cc[0] = 0; + } + if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c)) { // Do Arabic shaping. if (len >= 0 && (int)(ptr - text) + mbyte_blen >= len) { @@ -336,6 +343,7 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col, if (do_flush) { grid_puts_line_flush(true); } + return col - start_col; } /// End a group of grid_puts_len calls and send the screen buffer to the UI diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 6414b2bb74..c880de5060 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -152,8 +152,8 @@ void win_redr_status(win_T *wp) row = is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp); col = is_stl_global ? 0 : wp->w_wincol; - grid_puts(&default_grid, p, row, col, attr); - grid_fill(&default_grid, row, row + 1, len + col, + int width = grid_puts(&default_grid, p, row, col, attr); + grid_fill(&default_grid, row, row + 1, width + col, this_ru_col + col, fillchar, fillchar, attr); if (get_keymap_str(wp, "<%s>", NameBuff, MAXPATHL) @@ -266,6 +266,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler) int n; int fillchar; char buf[MAXPATHL]; + char transbuf[MAXPATHL]; char *stl; char *opt_name; int opt_scope = 0; @@ -370,34 +371,25 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler) // Make a copy, because the statusline may include a function call that // might change the option value and free the memory. stl = xstrdup(stl); - int width = build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_name, opt_scope, - fillchar, maxwidth, &hltab, &tabtab, NULL); + build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_name, opt_scope, + fillchar, maxwidth, &hltab, &tabtab, NULL); xfree(stl); ewp->w_p_crb = p_crb_save; - // Make all characters printable. - char *p = transstr(buf, true); - int len = (int)xstrlcpy(buf, p, sizeof(buf)); - len = (size_t)len < sizeof(buf) ? len : (int)sizeof(buf) - 1; - xfree(p); - - // fill up with "fillchar" - while (width < maxwidth && len < (int)sizeof(buf) - 1) { - len += utf_char2bytes(fillchar, buf + len); - width++; - } - buf[len] = NUL; + int len = (int)strlen(buf); + int start_col = col; // Draw each snippet with the specified highlighting. grid_puts_line_start(grid, row); int curattr = attr; - p = buf; + char *p = buf; for (n = 0; hltab[n].start != NULL; n++) { int textlen = (int)(hltab[n].start - p); - grid_puts_len(grid, p, textlen, row, col, curattr); - col += vim_strnsize(p, textlen); + // Make all characters printable. + size_t tsize = transstr_buf(p, textlen, transbuf, sizeof transbuf, true); + col += grid_puts_len(grid, transbuf, (int)tsize, row, col, curattr); p = hltab[n].start; if (hltab[n].userhl == 0) { @@ -411,7 +403,12 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler) } } // Make sure to use an empty string instead of p, if p is beyond buf + len. - grid_puts(grid, p >= buf + len ? "" : p, row, col, curattr); + size_t tsize = transstr_buf(p >= buf + len ? "" : p, -1, transbuf, sizeof transbuf, true); + col += grid_puts_len(grid, transbuf, (int)tsize, row, col, curattr); + int maxcol = start_col + maxwidth; + + // fill up with "fillchar" + grid_fill(grid, row, row + 1, col, maxcol, fillchar, fillchar, curattr); grid_puts_line_flush(false); -- cgit From e03ecb7d31c10aab8a8acbfb3cdd7ec558cd49eb Mon Sep 17 00:00:00 2001 From: Enan Ajmain <3nan.ajmain@gmail.com> Date: Wed, 15 Feb 2023 01:15:28 +0600 Subject: fix: uv_tty_set_mode failed in Windows #22264 Problem: uv_tty_set_mode on stdout in Windows exits with error. Cause: Windows cannot set the properties of the output of a tty. Solution: Remove call to uv_tty_set_mode. Ref: #21445 Ref: https://github.com/libuv/libuv/commit/88634c1405097c19582e870d278dd0e29dc55455#r100598822 --- src/nvim/tui/tui.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index f7bc931e21..8df6e49b77 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -359,12 +359,7 @@ static void terminfo_start(TUIData *tui) if (ret) { ELOG("uv_tty_init failed: %s", uv_strerror(ret)); } -#ifdef MSWIN - ret = uv_tty_set_mode(&tui->output_handle.tty, UV_TTY_MODE_RAW); - if (ret) { - ELOG("uv_tty_set_mode failed: %s", uv_strerror(ret)); - } -#else +#ifndef MSWIN int retry_count = 10; // A signal may cause uv_tty_set_mode() to fail (e.g., SIGCONT). Retry a // few times. #12322 -- cgit From 556f8646c01d1751cf39fe4df9c622899dceab9d Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Feb 2023 14:19:28 -0500 Subject: refactor(api): consistent VALIDATE messages #22262 Problem: Validation messages are not consistently formatted. - Parameter names sometimes are NOT quoted. - Descriptive names (non-parameters) sometimes ARE quoted. Solution: Always quote the `name` value passed to a VALIDATE macro _unless_ the value has whitespace. --- src/nvim/api/autocmd.c | 15 ++++++------- src/nvim/api/buffer.c | 4 ++-- src/nvim/api/command.c | 6 ++--- src/nvim/api/extmark.c | 23 ++++++++++--------- src/nvim/api/options.c | 4 ++-- src/nvim/api/private/validate.c | 49 +++++++++++++++++++++++++++++++++++++++++ src/nvim/api/private/validate.h | 32 +++++++++++---------------- src/nvim/api/vim.c | 21 +++++++++--------- src/nvim/highlight.c | 2 +- 9 files changed, 100 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index 36d3e04f54..aff7622dc5 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -108,19 +108,19 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) break; case kObjectTypeString: group = augroup_find(opts->group.data.string.data); - VALIDATE_S((group >= 0), "group", "", { + VALIDATE_S((group >= 0), "group", opts->group.data.string.data, { goto cleanup; }); break; case kObjectTypeInteger: group = (int)opts->group.data.integer; char *name = augroup_name(group); - VALIDATE_S(augroup_exists(name), "group", "", { + VALIDATE_INT(augroup_exists(name), "group", opts->group.data.integer, { goto cleanup; }); break; default: - VALIDATE_S(false, "group (must be string or integer)", "", { + VALIDATE_EXP(false, "group", "String or Integer", api_typename(opts->group.type), { goto cleanup; }); } @@ -142,7 +142,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) event_set[event_nr] = true; }) } else { - VALIDATE_S(false, "event (must be String or Array)", "", { + VALIDATE_EXP(false, "event", "String or Array", NULL, { goto cleanup; }); } @@ -160,11 +160,10 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) pattern_filters[pattern_filter_count] = v.data.string.data; pattern_filter_count += 1; } else if (v.type == kObjectTypeArray) { - if (v.data.array.size > AUCMD_MAX_PATTERNS) { - api_set_error(err, kErrorTypeValidation, "Too many patterns (maximum of %d)", - AUCMD_MAX_PATTERNS); + VALIDATE((v.data.array.size <= AUCMD_MAX_PATTERNS), + "Too many patterns (maximum of %d)", AUCMD_MAX_PATTERNS, { goto cleanup; - } + }); FOREACH_ITEM(v.data.array, item, { VALIDATE_T("pattern", kObjectTypeString, item.type, { diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 9c2d14d30f..bbdb66988b 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -207,7 +207,7 @@ Boolean nvim_buf_attach(uint64_t channel_id, Buffer buffer, Boolean send_buffer, } } - VALIDATE_S(key_used, "key", k.data, { + VALIDATE_S(key_used, "'opts' key", k.data, { goto error; }); } @@ -1074,7 +1074,7 @@ void nvim_buf_delete(Buffer buffer, Dictionary opts, Error *err) } else if (strequal("unload", k.data)) { unload = api_object_to_bool(v, "unload", false, err); } else { - VALIDATE_S(false, "key", k.data, { + VALIDATE_S(false, "'opts' key", k.data, { return; }); } diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index cae3927dfd..81b70b07d0 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -1017,7 +1017,7 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, VALIDATE_S(uc_validate_name(name.data), "command name", name.data, { goto err; }); - VALIDATE_S(!mb_islower(name.data[0]), "command name (must begin with an uppercase letter)", + VALIDATE_S(!mb_islower(name.data[0]), "command name (must start with uppercase)", name.data, { goto err; }); @@ -1163,7 +1163,7 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, goto err; }); } else if (HAS_KEY(opts->complete)) { - VALIDATE(false, "%s", "Invalid complete: expected Function or String", { + VALIDATE_EXP(false, "complete", "Function or String", NULL, { goto err; }); } @@ -1190,7 +1190,7 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, rep = command.data.string.data; break; default: - VALIDATE(false, "%s", "Invalid command: expected Function or String", { + VALIDATE_EXP(false, "command", "Function or String", NULL, { goto err; }); } diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 15f759eddf..91486abf38 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -238,7 +238,7 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id, }); } } else { - VALIDATE_S(false, "key", k.data, { + VALIDATE_S(false, "'opts' key", k.data, { return rv; }); } @@ -329,7 +329,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e }); } } else { - VALIDATE_S(false, "key", k.data, { + VALIDATE_S(false, "'opts' key", k.data, { return rv; }); } @@ -508,12 +508,13 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer }); uint32_t id = 0; - if (opts->id.type == kObjectTypeInteger && opts->id.data.integer > 0) { - id = (uint32_t)opts->id.data.integer; - } else if (HAS_KEY(opts->id)) { - VALIDATE_S(false, "id (must be positive integer)", "", { + if (HAS_KEY(opts->id)) { + VALIDATE_EXP((opts->id.type == kObjectTypeInteger && opts->id.data.integer > 0), + "id", "positive Integer", NULL, { goto error; }); + + id = (uint32_t)opts->id.data.integer; } int line2 = -1; @@ -1088,10 +1089,10 @@ static bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, in // Check if it is a position } else if (obj.type == kObjectTypeArray) { Array pos = obj.data.array; - VALIDATE((pos.size == 2 - && pos.items[0].type == kObjectTypeInteger - && pos.items[1].type == kObjectTypeInteger), - "%s", "Invalid position: expected 2 Integer items", { + VALIDATE_EXP((pos.size == 2 + && pos.items[0].type == kObjectTypeInteger + && pos.items[1].type == kObjectTypeInteger), + "mark position", "2 Integer items", NULL, { return false; }); @@ -1101,7 +1102,7 @@ static bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, in *col = (colnr_T)(pos_col >= 0 ? pos_col : MAXCOL); return true; } else { - VALIDATE(false, "%s", "Invalid position: expected mark id Integer or 2-item Array", { + VALIDATE_EXP(false, "mark position", "mark id Integer or 2-item Array", NULL, { return false; }); } diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index 40720c31c7..ddaed3a254 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -36,7 +36,7 @@ static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_t } else if (!strcmp(opts->scope.data.string.data, "global")) { *scope = OPT_GLOBAL; } else { - VALIDATE(false, "%s", "Invalid scope: expected 'local' or 'global'", { + VALIDATE_EXP(false, "scope", "'local' or 'global'", NULL, { return FAIL; }); } @@ -197,7 +197,7 @@ void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error scope |= OPT_CLEAR; break; default: - VALIDATE_EXP(false, "option type", "Integer, Boolean, or String", api_typename(value.type), { + VALIDATE_EXP(false, name.data, "Integer/Boolean/String", api_typename(value.type), { return; }); } diff --git a/src/nvim/api/private/validate.c b/src/nvim/api/private/validate.c index 41c9472a39..c4dd5bcac8 100644 --- a/src/nvim/api/private/validate.c +++ b/src/nvim/api/private/validate.c @@ -9,6 +9,55 @@ # include "api/private/validate.c.generated.h" #endif +/// Creates "Invalid …" message and sets it on `err`. +void api_err_invalid(Error *err, const char *name, const char *val_s, int64_t val_n, bool quote_val) +{ + ErrorType errtype = kErrorTypeValidation; + // Treat `name` without whitespace as a parameter (surround in quotes). + // Treat `name` with whitespace as a description (no quotes). + char *has_space = strchr(name, ' '); + + // No value. + if (val_s && val_s[0] == '\0') { + api_set_error(err, errtype, has_space ? "Invalid %s" : "Invalid '%s'", name); + return; + } + + // Number value. + if (val_s == NULL) { + api_set_error(err, errtype, has_space ? "Invalid %s: %" PRId64 : "Invalid '%s': %" PRId64, + name, val_n); + return; + } + + // String value. + if (has_space) { + api_set_error(err, errtype, quote_val ? "Invalid %s: '%s'" : "Invalid %s: %s", name, val_s); + } else { + api_set_error(err, errtype, quote_val ? "Invalid '%s': '%s'" : "Invalid '%s': %s", name, val_s); + } +} + +/// Creates "Invalid …: expected …" message and sets it on `err`. +void api_err_exp(Error *err, const char *name, const char *expected, const char *actual) +{ + ErrorType errtype = kErrorTypeValidation; + // Treat `name` without whitespace as a parameter (surround in quotes). + // Treat `name` with whitespace as a description (no quotes). + char *has_space = strchr(name, ' '); + + if (!actual) { + api_set_error(err, errtype, + has_space ? "Invalid %s: expected %s" : "Invalid '%s': expected %s", + name, expected); + return; + } + + api_set_error(err, errtype, + has_space ? "Invalid %s: expected %s, got %s" : "Invalid '%s': expected %s, got %s", + name, expected, actual); +} + bool check_string_array(Array arr, char *name, bool disallow_nl, Error *err) { snprintf(IObuff, sizeof(IObuff), "'%s' item", name); diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index 4a1b99408e..469fed0f83 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -4,48 +4,42 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" -#define VALIDATE_INT(cond, name, val_, code) \ +#define VALIDATE(cond, fmt_, fmt_arg1, code) \ do { \ if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, "Invalid " name ": %" PRId64, val_); \ + api_set_error(err, kErrorTypeValidation, fmt_, fmt_arg1); \ code; \ } \ } while (0) -#define VALIDATE_S(cond, name, val_, code) \ +#define VALIDATE_INT(cond, name, val_, code) \ do { \ if (!(cond)) { \ - if (strequal(val_, "")) { \ - api_set_error(err, kErrorTypeValidation, "Invalid " name); \ - } else { \ - api_set_error(err, kErrorTypeValidation, "Invalid " name ": '%s'", val_); \ - } \ + api_err_invalid(err, name, NULL, val_, false); \ code; \ } \ } while (0) -#define VALIDATE_EXP(cond, name, expected, actual, code) \ +#define VALIDATE_S(cond, name, val_, code) \ do { \ if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, "Invalid %s: expected %s, got %s", \ - name, expected, actual); \ + api_err_invalid(err, name, val_, 0, true); \ code; \ } \ } while (0) -#define VALIDATE_T(name, expected_t, actual_t, code) \ +#define VALIDATE_EXP(cond, name, expected, actual, code) \ do { \ - if (expected_t != actual_t) { \ - api_set_error(err, kErrorTypeValidation, "Invalid %s: expected %s, got %s", \ - name, api_typename(expected_t), api_typename(actual_t)); \ + if (!(cond)) { \ + api_err_exp(err, name, expected, actual); \ code; \ } \ } while (0) -#define VALIDATE(cond, fmt_, fmt_arg1, code) \ +#define VALIDATE_T(name, expected_t, actual_t, code) \ do { \ - if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, fmt_, fmt_arg1); \ + if (expected_t != actual_t) { \ + api_err_exp(err, name, api_typename(expected_t), api_typename(actual_t)); \ code; \ } \ } while (0) @@ -53,7 +47,7 @@ #define VALIDATE_RANGE(cond, name, code) \ do { \ if (!(cond)) { \ - api_set_error(err, kErrorTypeValidation, "Invalid '%s': out of range", name); \ + api_err_invalid(err, name, "out of range", 0, false); \ code; \ } \ } while (0) diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 50683ac403..3a93005841 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -654,12 +654,13 @@ Object nvim_get_var(String name, Error *err) { dictitem_T *di = tv_dict_find(&globvardict, name.data, (ptrdiff_t)name.size); if (di == NULL) { // try to autoload script - VALIDATE_S((script_autoload(name.data, name.size, false) && !aborting()), "key", name.data, { + bool found = script_autoload(name.data, name.size, false) && !aborting(); + VALIDATE(found, "Key not found: %s", name.data, { return (Object)OBJECT_INIT; }); di = tv_dict_find(&globvardict, name.data, (ptrdiff_t)name.size); } - VALIDATE_S((di != NULL), "key (not found)", name.data, { + VALIDATE((di != NULL), "Key not found: %s", name.data, { return (Object)OBJECT_INIT; }); return vim_to_object(&di->di_tv); @@ -986,7 +987,7 @@ Integer nvim_open_term(Buffer buffer, DictionaryOf(LuaRef) opts, Error *err) v->data.luaref = LUA_NOREF; break; } else { - VALIDATE_S(false, "key", k.data, {}); + VALIDATE_S(false, "'opts' key", k.data, {}); } } @@ -1632,18 +1633,18 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er size_t i; // also used for freeing the variables for (i = 0; i < calls.size; i++) { - VALIDATE_T("calls item", kObjectTypeArray, calls.items[i].type, { + VALIDATE_T("'calls' item", kObjectTypeArray, calls.items[i].type, { goto theend; }); Array call = calls.items[i].data.array; - VALIDATE((call.size == 2), "%s", "calls item must be a 2-item Array", { + VALIDATE_EXP((call.size == 2), "'calls' item", "2-item Array", NULL, { goto theend; }); VALIDATE_T("name", kObjectTypeString, call.items[0].type, { goto theend; }); String name = call.items[0].data.string; - VALIDATE_T("args", kObjectTypeArray, call.items[1].type, { + VALIDATE_T("call args", kObjectTypeArray, call.items[1].type, { goto theend; }); Array args = call.items[1].data.array; @@ -2108,10 +2109,10 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error * VALIDATE_T("fillchar", kObjectTypeString, opts->fillchar.type, { return result; }); - VALIDATE((opts->fillchar.data.string.size != 0 - && ((size_t)utf_ptr2len(opts->fillchar.data.string.data) - == opts->fillchar.data.string.size)), - "%s", "Invalid fillchar: expected single character", { + VALIDATE_EXP((opts->fillchar.data.string.size != 0 + && ((size_t)utf_ptr2len(opts->fillchar.data.string.data) + == opts->fillchar.data.string.size)), + "fillchar", "single character", NULL, { return result; }); fillchar = utf_ptr2char(opts->fillchar.data.string.data); diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 5e53bf273f..cf72102b60 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -1089,7 +1089,7 @@ int object_to_color(Object val, char *key, bool rgb, Error *err) }); return color; } else { - VALIDATE(false, "Invalid %s: expected String or Integer", key, { + VALIDATE_EXP(false, key, "String or Integer", NULL, { return 0; }); } -- cgit From 8307ed3a194d0c0420feb0b3e5c2f6919095415f Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 15 Feb 2023 08:51:40 +0100 Subject: revert: "build: remove ENABLE_COMPILER_SUGGESTIONS option" (#22265) This reverts commit 1d6bb0892b58e5a4183e74c0fbd2dc20204e33a4. See: https://github.com/neovim/neovim/pull/22249#issuecomment-1430548550 --- src/nvim/CMakeLists.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 22cbec0d06..a193af6d51 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -105,6 +105,30 @@ if(HAVE_WIMPLICIT_FALLTHROUGH_FLAG) target_compile_options(main_lib INTERFACE -Wimplicit-fallthrough) endif() +option(ENABLE_COMPILER_SUGGESTIONS "Enable -Wsuggest compiler warnings" OFF) +if(ENABLE_COMPILER_SUGGESTIONS) + # Clang doesn't have -Wsuggest-attribute so check for each one. + check_c_compiler_flag(-Wsuggest-attribute=pure HAVE_WSUGGEST_ATTRIBUTE_PURE) + if(HAVE_WSUGGEST_ATTRIBUTE_PURE) + target_compile_options(main_lib INTERFACE -Wsuggest-attribute=pure) + endif() + + check_c_compiler_flag(-Wsuggest-attribute=const HAVE_WSUGGEST_ATTRIBUTE_CONST) + if(HAVE_WSUGGEST_ATTRIBUTE_CONST) + target_compile_options(main_lib INTERFACE -Wsuggest-attribute=const) + endif() + + check_c_compiler_flag(-Wsuggest-attribute=malloc HAVE_WSUGGEST_ATTRIBUTE_MALLOC) + if(HAVE_WSUGGEST_ATTRIBUTE_MALLOC) + target_compile_options(main_lib INTERFACE -Wsuggest-attribute=malloc) + endif() + + check_c_compiler_flag(-Wsuggest-attribute=cold HAVE_WSUGGEST_ATTRIBUTE_COLD) + if(HAVE_WSUGGEST_ATTRIBUTE_COLD) + target_compile_options(main_lib INTERFACE -Wsuggest-attribute=cold) + endif() +endif() + if(MINGW) # Use POSIX compatible stdio in Mingw target_compile_definitions(main_lib INTERFACE __USE_MINGW_ANSI_STDIO) -- cgit From ae7653b74cfd373dbafe84c913f8b1b5a006670d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 15 Feb 2023 16:53:53 +0800 Subject: fix(win_update): don't use unintialized memory in edge case (#22266) This fixes two clang warnings. Using an unintialized "cursorline_fi" without assigning to it is not something that should normally happen, and in case it happens it will likely cause another redraw, but still don't use unintialized memory. --- src/nvim/drawscreen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 2c0b6ea3b0..0ac5220599 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -1552,7 +1552,7 @@ static void win_update(win_T *wp, DecorProviders *providers) wp->w_old_visual_col = 0; } - foldinfo_T cursorline_fi; + foldinfo_T cursorline_fi = { 0 }; wp->w_cursorline = win_cursorline_standout(wp) ? wp->w_cursor.lnum : 0; if (wp->w_p_cul) { // Make sure that the cursorline on a closed fold is redrawn -- cgit From ec782211f2305382b3a6cb72ab0bbfcab0efcdf0 Mon Sep 17 00:00:00 2001 From: Enan Ajmain <3nan.ajmain@gmail.com> Date: Wed, 15 Feb 2023 21:39:23 +0600 Subject: fix(tui): set taskbar, icon in Windows #22270 Problem: After TUI refactor commit, code for setting Windows taskbar icon wasn't being executed because of a backdated conditional. Solution: Update the conditional to take TUI refactor into account. Ref: https://github.com/neovim/neovim/pull/20634#discussion_r1088993820 --- src/nvim/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/main.c b/src/nvim/main.c index 52069a6742..f2aa14e04c 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -589,7 +589,7 @@ int main(int argc, char **argv) } #ifdef MSWIN - if (use_builtin_ui) { + if (use_remote_ui || use_builtin_ui) { os_icon_init(); } os_title_save(); -- cgit From f1c5887377c9ae547a7564ec4fc52d72656a974f Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Thu, 16 Feb 2023 00:15:09 +0100 Subject: ci: add GCC Release testing (#22274) ci: add GCC release testing We currently have no release testing, so it's good to check for any unwanted behavior on release builds as well. Prefer GCC over clang, as GCC release builds seem to create more warnings on release compared to debug. --- src/nvim/CMakeLists.txt | 7 +++++++ src/nvim/marktree.c | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index a193af6d51..d6a53456d7 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -92,6 +92,13 @@ else() -Wmissing-noreturn -Wmissing-format-attribute -Wmissing-prototypes) + + if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(main_lib INTERFACE + $<$:-Wno-unused-result> + $<$:-Wno-unused-result> + $<$:-Wno-unused-result>) + endif() endif() # On FreeBSD 64 math.h uses unguarded C11 extension, which taints clang diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c index 77ba6e6fa4..cb981bb00c 100644 --- a/src/nvim/marktree.c +++ b/src/nvim/marktree.c @@ -1135,7 +1135,7 @@ void marktree_check(MarkTree *b) mtpos_t dummy; bool last_right = false; - size_t nkeys = check_node(b, b->root, &dummy, &last_right); + size_t nkeys = marktree_check_node(b, b->root, &dummy, &last_right); assert(b->n_keys == nkeys); assert(b->n_keys == map_size(b->id2node)); #else @@ -1145,7 +1145,7 @@ void marktree_check(MarkTree *b) } #ifndef NDEBUG -static size_t check_node(MarkTree *b, mtnode_t *x, mtpos_t *last, bool *last_right) +size_t marktree_check_node(MarkTree *b, mtnode_t *x, mtpos_t *last, bool *last_right) { assert(x->n <= 2 * T - 1); // TODO(bfredl): too strict if checking "in repair" post-delete tree. @@ -1154,7 +1154,7 @@ static size_t check_node(MarkTree *b, mtnode_t *x, mtpos_t *last, bool *last_rig for (int i = 0; i < x->n; i++) { if (x->level) { - n_keys += check_node(b, x->ptr[i], last, last_right); + n_keys += marktree_check_node(b, x->ptr[i], last, last_right); } else { *last = (mtpos_t) { 0, 0 }; } @@ -1171,7 +1171,7 @@ static size_t check_node(MarkTree *b, mtnode_t *x, mtpos_t *last, bool *last_rig } if (x->level) { - n_keys += check_node(b, x->ptr[x->n], last, last_right); + n_keys += marktree_check_node(b, x->ptr[x->n], last, last_right); unrelative(x->key[x->n - 1].pos, last); for (int i = 0; i < x->n + 1; i++) { -- cgit From 968cd1ed933c039b8d60b0110bc6b539c71e387d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 16 Feb 2023 07:25:16 +0800 Subject: vim-patch:9.0.1309: scrolling two lines with even line count and 'scrolloff' set Problem: Scrolling two lines with even line count and 'scrolloff' set. Solution: Adjust how the topline is computed. (closes vim/vim#10545) https://github.com/vim/vim/commit/1d6539cf36a7b6d1afe76fb6316fe662f543bf60 Cherry-pick test_scroll_opt.vim changes from patch 8.2.1432. Co-authored-by: Bram Moolenaar --- src/nvim/buffer.c | 2 +- src/nvim/move.c | 79 +++++++++++++++++++++++------------- src/nvim/normal.c | 2 +- src/nvim/testdir/test_scroll_opt.vim | 20 ++++++++- src/nvim/testdir/test_scrollbind.vim | 4 +- 5 files changed, 73 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 129a8c6fb2..98832a98c9 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1676,7 +1676,7 @@ void enter_buffer(buf_T *buf) maketitle(); // when autocmds didn't change it if (curwin->w_topline == 1 && !curwin->w_topline_was_set) { - scroll_cursor_halfway(false); // redisplay at correct position + scroll_cursor_halfway(false, false); // redisplay at correct position } // Change directories when the 'acd' option is set. diff --git a/src/nvim/move.c b/src/nvim/move.c index a946633bf6..8fda73cbec 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -235,7 +235,7 @@ void update_topline(win_T *wp) // cursor in the middle of the window. Otherwise put the cursor // near the top of the window. if (n >= halfheight) { - scroll_cursor_halfway(false); + scroll_cursor_halfway(false, false); } else { scroll_cursor_top(scrolljump_value(), false); check_botline = true; @@ -314,7 +314,7 @@ void update_topline(win_T *wp) if (line_count <= wp->w_height_inner + 1) { scroll_cursor_bot(scrolljump_value(), false); } else { - scroll_cursor_halfway(false); + scroll_cursor_halfway(false, false); } } } @@ -1464,7 +1464,7 @@ void scroll_cursor_top(int min_scroll, int always) // This makes sure we get the same position when using "k" and "j" // in a small window. if (used > curwin->w_height_inner) { - scroll_cursor_halfway(false); + scroll_cursor_halfway(false, false); } else { // If "always" is false, only adjust topline to a lower value, higher // value may happen with wrapping lines @@ -1669,7 +1669,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) // Scroll up if the cursor is off the bottom of the screen a bit. // Otherwise put it at 1/2 of the screen. if (line_count >= curwin->w_height_inner && line_count > min_scroll) { - scroll_cursor_halfway(false); + scroll_cursor_halfway(false, true); } else { scrollup(line_count, true); } @@ -1690,7 +1690,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot) /// /// @param atend if true, also put the cursor halfway to the end of the file. /// -void scroll_cursor_halfway(int atend) +void scroll_cursor_halfway(bool atend, bool prefer_above) { int above = 0; int topfill = 0; @@ -1705,38 +1705,59 @@ void scroll_cursor_halfway(int atend) loff.fill = 0; boff.fill = 0; linenr_T topline = loff.lnum; + while (topline > 1) { - if (below <= above) { // add a line below the cursor first - if (boff.lnum < curbuf->b_ml.ml_line_count) { - botline_forw(curwin, &boff); - used += boff.height; + // This may not be right in the middle if the lines' + // physical height > 1 (e.g. 'wrap' is on). + + // Depending on "prefer_above" we add a line above or below first. + // Loop twice to avoid duplicating code. + bool done = false; + for (int round = 1; round <= 2; round++) { + if (prefer_above + ? (round == 2 && below < above) + : (round == 1 && below <= above)) { + // add a line below the cursor + if (boff.lnum < curbuf->b_ml.ml_line_count) { + botline_forw(curwin, &boff); + used += boff.height; + if (used > curwin->w_height_inner) { + done = true; + break; + } + below += boff.height; + } else { + below++; // count a "~" line + if (atend) { + used++; + } + } + } + + if (prefer_above + ? (round == 1 && below >= above) + : (round == 1 && below > above)) { + // add a line above the cursor + topline_back(curwin, &loff); + if (loff.height == MAXCOL) { + used = MAXCOL; + } else { + used += loff.height; + } if (used > curwin->w_height_inner) { + done = true; break; } - below += boff.height; - } else { - below++; // count a "~" line - if (atend) { - used++; - } + above += loff.height; + topline = loff.lnum; + topfill = loff.fill; } } - - if (below > above) { // add a line above the cursor - topline_back(curwin, &loff); - if (loff.height == MAXCOL) { - used = MAXCOL; - } else { - used += loff.height; - } - if (used > curwin->w_height_inner) { - break; - } - above += loff.height; - topline = loff.lnum; - topfill = loff.fill; + if (done) { + break; } } + if (!hasFolding(topline, &curwin->w_topline, NULL)) { curwin->w_topline = topline; } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index a84d5c73a4..f1226584d7 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -2856,7 +2856,7 @@ static void nv_zet(cmdarg_T *cap) FALLTHROUGH; case 'z': - scroll_cursor_halfway(true); + scroll_cursor_halfway(true, false); redraw_later(curwin, UPD_VALID); set_fraction(curwin); break; diff --git a/src/nvim/testdir/test_scroll_opt.vim b/src/nvim/testdir/test_scroll_opt.vim index 77920eb8b0..64f4ced470 100644 --- a/src/nvim/testdir/test_scroll_opt.vim +++ b/src/nvim/testdir/test_scroll_opt.vim @@ -1,5 +1,4 @@ " Test for reset 'scroll' -" func Test_reset_scroll() let scr = &l:scroll @@ -34,3 +33,22 @@ func Test_reset_scroll() quit! endfunc + +func Test_scolloff_even_line_count() + new + resize 6 + setlocal scrolloff=3 + call setline(1, range(20)) + normal 2j + call assert_equal(1, getwininfo(win_getid())[0].topline) + normal j + call assert_equal(1, getwininfo(win_getid())[0].topline) + normal j + call assert_equal(2, getwininfo(win_getid())[0].topline) + normal j + call assert_equal(3, getwininfo(win_getid())[0].topline) + + bwipe! +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_scrollbind.vim b/src/nvim/testdir/test_scrollbind.vim index 6c5488be05..f67a559c60 100644 --- a/src/nvim/testdir/test_scrollbind.vim +++ b/src/nvim/testdir/test_scrollbind.vim @@ -217,8 +217,8 @@ end of window 2 \ '7 line 02 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02', \ '56789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02', \ 'UTSRQPONMLKJIHGREDCBA9876543210 02', - \ '. line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11', - \ '. line 11 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 11', + \ '. line 10 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 10', + \ '. line 10 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 10', \ ''], getline(1, '$')) enew! -- cgit From a2dd7fa97bab06be2b357e34af0ed0a194774d70 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 16 Feb 2023 07:41:09 +0800 Subject: vim-patch:9.0.1310: 'splitkeep' test has failures Problem: 'splitkeep' test has failures. Solution: Adjust expected cursor line position. https://github.com/vim/vim/commit/fdbd14e89207dca95549f298ee468793da852086 Co-authored-by: Bram Moolenaar --- src/nvim/testdir/test_window_cmd.vim | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim index c25b1f1157..4a8a1b11f1 100644 --- a/src/nvim/testdir/test_window_cmd.vim +++ b/src/nvim/testdir/test_window_cmd.vim @@ -1651,9 +1651,16 @@ func Test_splitkeep_options() call assert_equal(1, line("w0")) call assert_equal(curpos, getcurpos()) - " Scroll when cursor becomes invalid in insert mode + " Scroll when cursor becomes invalid in insert mode. norm Lic - call assert_equal(curpos, getcurpos()) + call assert_equal(curpos[0], getcurpos()[0], 'run ' .. run) + + " The line number might be one less because of round-off. + call assert_inrange(curpos[1] - 1, curpos[1], getcurpos()[1], 'run ' .. run) + + call assert_equal(curpos[2], getcurpos()[2], 'run ' .. run) + call assert_equal(curpos[3], getcurpos()[3], 'run ' .. run) + call assert_equal(curpos[4], getcurpos()[4], 'run ' .. run) " No scroll when topline not equal to 1 only | execute "norm gg5\" | split | wincmd k -- cgit From 0bb3a373d32e150af3909e3873be91f34df211dc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 16 Feb 2023 07:41:39 +0800 Subject: vim-patch:9.0.1312: Cursor position wrong when splitting window in insert mode Problem: Cursor position wrong when splitting window in insert mode. Solution: Pass the actual mode to win_fix_cursor(). (Luuk van Baal, closes vim/vim#11999, https://github.com/vim/vim/commit/bc3dc298b37820a8212e7d839e882e07d6cc98c8 Co-authored-by: Luuk van Baal --- src/nvim/testdir/test_window_cmd.vim | 9 +-------- src/nvim/window.c | 7 +++++-- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim index 4a8a1b11f1..8b9457ae1d 100644 --- a/src/nvim/testdir/test_window_cmd.vim +++ b/src/nvim/testdir/test_window_cmd.vim @@ -1653,14 +1653,7 @@ func Test_splitkeep_options() " Scroll when cursor becomes invalid in insert mode. norm Lic - call assert_equal(curpos[0], getcurpos()[0], 'run ' .. run) - - " The line number might be one less because of round-off. - call assert_inrange(curpos[1] - 1, curpos[1], getcurpos()[1], 'run ' .. run) - - call assert_equal(curpos[2], getcurpos()[2], 'run ' .. run) - call assert_equal(curpos[3], getcurpos()[3], 'run ' .. run) - call assert_equal(curpos[4], getcurpos()[4], 'run ' .. run) + call assert_equal(curpos, getcurpos(), 'run ' .. run) " No scroll when topline not equal to 1 only | execute "norm gg5\" | split | wincmd k diff --git a/src/nvim/window.c b/src/nvim/window.c index c6694cd489..36d422abd5 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4835,7 +4835,9 @@ static void win_enter_ext(win_T *const wp, const int flags) if (*p_spk == 'c') { changed_line_abv_curs(); // assume cursor position needs updating } else { - win_fix_cursor(true); + // Make sure the cursor position is valid, either by moving the cursor + // or by scrolling the text. + win_fix_cursor(get_real_state() & (MODE_NORMAL|MODE_CMDLINE|MODE_TERMINAL)); } fix_current_dir(); @@ -6407,7 +6409,8 @@ void win_fix_scroll(int resize) /// Make sure the cursor position is valid for 'splitkeep'. /// If it is not, put the cursor position in the jumplist and move it. -/// If we are not in normal mode, scroll to make valid instead. +/// If we are not in normal mode ("normal" is zero), make it valid by scrolling +/// instead. static void win_fix_cursor(int normal) { win_T *wp = curwin; -- cgit From e619fb1660595f9e6a0afad8d9a91e37a94f95a3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 16 Feb 2023 10:32:28 +0800 Subject: vim-patch:8.2.0114: info about sourced scripts is scattered Problem: Info about sourced scripts is scattered. Solution: Use scriptitem_T for info about a script, including s: variables. Drop ga_scripts. https://github.com/vim/vim/commit/7ebcba61b20d25d23109fff73d0346ad44ba1b3b Co-authored-by: Bram Moolenaar --- src/nvim/eval.c | 73 ++++++++++++++++++------------------------------------ src/nvim/runtime.c | 14 +++++++++-- src/nvim/runtime.h | 11 +++++++- 3 files changed, 46 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 3ab704e250..a09bd72710 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -109,15 +109,7 @@ static hashtab_T compat_hashtab; /// Used for checking if local variables or arguments used in a lambda. bool *eval_lavars_used = NULL; -/// Array to hold the hashtab with variables local to each sourced script. -/// Each item holds a variable (nameless) that points to the dict_T. -typedef struct { - ScopeDictDictItem sv_var; - dict_T sv_dict; -} scriptvar_T; - -static garray_T ga_scripts = { 0, 0, sizeof(scriptvar_T *), 4, NULL }; -#define SCRIPT_SV(id) (((scriptvar_T **)ga_scripts.ga_data)[(id) - 1]) +#define SCRIPT_SV(id) (SCRIPT_ITEM(id).sn_vars) #define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab) static int echo_attr = 0; // attributes used for ":echo" @@ -473,7 +465,7 @@ void eval_init(void) } #if defined(EXITFREE) -void eval_clear(void) +static void evalvars_clear(void) { for (size_t i = 0; i < ARRAY_SIZE(vimvars); i++) { struct vimvar *p = &vimvars[i]; @@ -488,28 +480,29 @@ void eval_clear(void) hash_init(&vimvarht); // garbage_collect() will access it hash_clear(&compat_hashtab); - free_scriptnames(); + // global variables + vars_clear(&globvarht); + + // Script-local variables. Clear all the variables here. + // The scriptvar_T is cleared later in free_scriptnames(), because a + // variable in one script might hold a reference to the whole scope of + // another script. + for (int i = 1; i <= script_items.ga_len; i++) { + vars_clear(&SCRIPT_VARS(i)); + } +} + +void eval_clear(void) +{ + evalvars_clear(); + free_scriptnames(); // must come after evalvars_clear(). # ifdef HAVE_WORKING_LIBINTL free_locales(); # endif - // global variables - vars_clear(&globvarht); - // autoloaded script names ga_clear_strings(&ga_loaded); - // Script-local variables. First clear all the variables and in a second - // loop free the scriptvar_T, because a variable in one script might hold - // a reference to the whole scope of another script. - for (int i = 1; i <= ga_scripts.ga_len; i++) { - vars_clear(&SCRIPT_VARS(i)); - } - for (int i = 1; i <= ga_scripts.ga_len; i++) { - xfree(SCRIPT_SV(i)); - } - ga_clear(&ga_scripts); - // unreferenced lists and dicts (void)garbage_collect(false); @@ -970,7 +963,7 @@ void list_vim_vars(int *first) /// List script-local variables, if there is a script. void list_script_vars(int *first) { - if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len) { + if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) { list_hashtable_vars(&SCRIPT_VARS(current_sctx.sc_sid), "s:", false, first); } } @@ -4116,7 +4109,7 @@ bool garbage_collect(bool testing) ABORTING(set_ref_in_previous_funccal)(copyID); // script-local variables - for (int i = 1; i <= ga_scripts.ga_len; i++) { + for (int i = 1; i <= script_items.ga_len; i++) { ABORTING(set_ref_in_ht)(&SCRIPT_VARS(i), copyID, NULL); } @@ -7131,7 +7124,7 @@ hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, const char } else if (*name == 's' // script variable && (current_sctx.sc_sid > 0 || current_sctx.sc_sid == SID_STR || current_sctx.sc_sid == SID_LUA) - && current_sctx.sc_sid <= ga_scripts.ga_len) { + && current_sctx.sc_sid <= script_items.ga_len) { // For anonymous scripts without a script item, create one now so script vars can be used if (current_sctx.sc_sid == SID_LUA) { // try to resolve lua filename & line no so it can be shown in lastset messages. @@ -7182,27 +7175,9 @@ hashtab_T *find_var_ht(const char *name, const size_t name_len, const char **var /// sourcing this script and when executing functions defined in the script. void new_script_vars(scid_T id) { - scriptvar_T *sv; - - ga_grow(&ga_scripts, id - ga_scripts.ga_len); - - // Re-allocating ga_data means that an ht_array pointing to - // ht_smallarray becomes invalid. We can recognize this: ht_mask is - // at its init value. Also reset "v_dict", it's always the same. - for (int i = 1; i <= ga_scripts.ga_len; i++) { - hashtab_T *ht = &SCRIPT_VARS(i); - if (ht->ht_mask == HT_INIT_SIZE - 1) { - ht->ht_array = ht->ht_smallarray; - } - sv = SCRIPT_SV(i); - sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict; - } - - while (ga_scripts.ga_len < id) { - sv = SCRIPT_SV(ga_scripts.ga_len + 1) = xcalloc(1, sizeof(scriptvar_T)); - init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); - ga_scripts.ga_len++; - } + scriptvar_T *sv = xcalloc(1, sizeof(scriptvar_T)); + init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); + SCRIPT_ITEM(id).sn_vars = sv; } /// Initialize dictionary "dict" as a scope and set variable "dict_var" to diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index cff0f886ce..e8b0492f35 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -1846,10 +1846,13 @@ scriptitem_T *new_script_item(char *const name, scid_T *const sid_out) while (script_items.ga_len < sid) { script_items.ga_len++; SCRIPT_ITEM(script_items.ga_len).sn_name = NULL; + + // Allocate the local script variables to use for this script. + new_script_vars(script_items.ga_len); + SCRIPT_ITEM(script_items.ga_len).sn_prof_on = false; } SCRIPT_ITEM(sid).sn_name = name; - new_script_vars(sid); // Allocate the local script variables to use for this script. return &SCRIPT_ITEM(sid); } @@ -2305,7 +2308,14 @@ void free_scriptnames(void) { profile_reset(); -# define FREE_SCRIPTNAME(item) xfree((item)->sn_name) +# define FREE_SCRIPTNAME(item) \ + do { \ + /* the variables themselves are cleared in evalvars_clear() */ \ + xfree((item)->sn_vars); \ + xfree((item)->sn_name); \ + ga_clear(&(item)->sn_prl_ga); \ + } while (0) \ + GA_DEEP_CLEAR(&script_items, scriptitem_T, FREE_SCRIPTNAME); } #endif diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h index 97063b900c..0812355716 100644 --- a/src/nvim/runtime.h +++ b/src/nvim/runtime.h @@ -55,7 +55,16 @@ typedef enum { ESTACK_SCRIPT, } estack_arg_T; -typedef struct scriptitem_S { +/// Holds the hashtab with variables local to each sourced script. +/// Each item holds a variable (nameless) that points to the dict_T. +typedef struct { + ScopeDictDictItem sv_var; + dict_T sv_dict; +} scriptvar_T; + +typedef struct { + scriptvar_T *sn_vars; ///< stores s: variables for this script + char *sn_name; bool sn_prof_on; ///< true when script is/was profiled bool sn_pr_force; ///< forceit: profile functions in this script -- cgit From 0cbbe27e93e87a5336673e0529b011313c51a123 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 16 Feb 2023 11:00:48 +0800 Subject: vim-patch:8.2.0154: reallocating the list of scripts is inefficient Problem: Reallocating the list of scripts is inefficient. Solution: Instead of using a growarray of scriptitem_T, store pointers and allocate each scriptitem_T separately. Also avoids that the growarray pointers change when sourcing a new script. https://github.com/vim/vim/commit/21b9e9773d64de40994f8762173bdd8befa6acf7 Co-authored-by: Bram Moolenaar --- src/nvim/cmdexpand.c | 2 +- src/nvim/eval.c | 4 ++-- src/nvim/profile.c | 22 ++++++++-------------- src/nvim/runtime.c | 40 ++++++++++++++++++++++------------------ src/nvim/runtime.h | 2 +- 5 files changed, 34 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index 97feab2978..fcd6a73b2d 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -2524,7 +2524,7 @@ static char *get_scriptnames_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx) return NULL; } - scriptitem_T *si = &SCRIPT_ITEM(idx + 1); + scriptitem_T *si = SCRIPT_ITEM(idx + 1); home_replace(NULL, si->sn_name, NameBuff, MAXPATHL, true); return NameBuff; } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index a09bd72710..92a8ffd646 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -109,7 +109,7 @@ static hashtab_T compat_hashtab; /// Used for checking if local variables or arguments used in a lambda. bool *eval_lavars_used = NULL; -#define SCRIPT_SV(id) (SCRIPT_ITEM(id).sn_vars) +#define SCRIPT_SV(id) (SCRIPT_ITEM(id)->sn_vars) #define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab) static int echo_attr = 0; // attributes used for ":echo" @@ -7177,7 +7177,7 @@ void new_script_vars(scid_T id) { scriptvar_T *sv = xcalloc(1, sizeof(scriptvar_T)); init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); - SCRIPT_ITEM(id).sn_vars = sv; + SCRIPT_ITEM(id)->sn_vars = sv; } /// Initialize dictionary "dict" as a scope and set variable "dict_var" to diff --git a/src/nvim/profile.c b/src/nvim/profile.c index 173332a428..6b841bd961 100644 --- a/src/nvim/profile.c +++ b/src/nvim/profile.c @@ -232,7 +232,7 @@ void profile_reset(void) { // Reset sourced files. for (int id = 1; id <= script_items.ga_len; id++) { - scriptitem_T *si = &SCRIPT_ITEM(id); + scriptitem_T *si = SCRIPT_ITEM(id); if (si->sn_prof_on) { si->sn_prof_on = false; si->sn_pr_force = false; @@ -407,7 +407,7 @@ bool prof_def_func(void) FUNC_ATTR_PURE { if (current_sctx.sc_sid > 0) { - return SCRIPT_ITEM(current_sctx.sc_sid).sn_pr_force; + return SCRIPT_ITEM(current_sctx.sc_sid)->sn_pr_force; } return false; } @@ -690,7 +690,7 @@ void profile_init(scriptitem_T *si) void script_prof_save(proftime_T *tm) { if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) { - scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_pr_nest++ == 0) { si->sn_pr_child = profile_start(); } @@ -705,7 +705,7 @@ void script_prof_restore(const proftime_T *tm) return; } - scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && --si->sn_pr_nest == 0) { si->sn_pr_child = profile_end(si->sn_pr_child); // don't count wait time @@ -722,7 +722,7 @@ static void script_dump_profile(FILE *fd) sn_prl_T *pp; for (int id = 1; id <= script_items.ga_len; id++) { - scriptitem_T *si = &SCRIPT_ITEM(id); + scriptitem_T *si = SCRIPT_ITEM(id); if (si->sn_prof_on) { fprintf(fd, "SCRIPT %s\n", si->sn_name); if (si->sn_pr_count == 1) { @@ -804,12 +804,10 @@ void profile_dump(void) /// until later and we need to store the time now. void script_line_start(void) { - scriptitem_T *si; - if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) { return; } - si = &SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && SOURCING_LNUM >= 1) { // Grow the array before starting the timer, so that the time spent // here isn't counted. @@ -834,12 +832,10 @@ void script_line_start(void) /// Called when actually executing a function line. void script_line_exec(void) { - scriptitem_T *si; - if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) { return; } - si = &SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_prl_idx >= 0) { si->sn_prl_execed = true; } @@ -848,12 +844,10 @@ void script_line_exec(void) /// Called when done with a function line. void script_line_end(void) { - scriptitem_T *si; - if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) { return; } - si = &SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_prl_idx >= 0 && si->sn_prl_idx < si->sn_prl_ga.ga_len) { if (si->sn_prl_execed) { diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index e8b0492f35..9dc213d718 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -73,7 +73,7 @@ struct source_cookie { #endif garray_T exestack = { 0, 0, sizeof(estack_T), 50, NULL }; -garray_T script_items = { 0, 0, sizeof(scriptitem_T), 4, NULL }; +garray_T script_items = { 0, 0, sizeof(scriptitem_T *), 20, NULL }; /// Initialize the execution stack. void estack_init(void) @@ -144,7 +144,7 @@ char *estack_sfile(estack_arg_T which) ? &entry->es_info.ufunc->uf_script_ctx : &entry->es_info.aucmd->script_ctx); return def_ctx->sc_sid > 0 - ? xstrdup((SCRIPT_ITEM(def_ctx->sc_sid).sn_name)) + ? xstrdup((SCRIPT_ITEM(def_ctx->sc_sid)->sn_name)) : NULL; } else if (entry->es_type == ETYPE_SCRIPT) { return xstrdup(entry->es_name); @@ -1844,16 +1844,18 @@ scriptitem_T *new_script_item(char *const name, scid_T *const sid_out) } ga_grow(&script_items, sid - script_items.ga_len); while (script_items.ga_len < sid) { + scriptitem_T *si = xcalloc(1, sizeof(scriptitem_T)); script_items.ga_len++; - SCRIPT_ITEM(script_items.ga_len).sn_name = NULL; + SCRIPT_ITEM(script_items.ga_len) = si; + si->sn_name = NULL; // Allocate the local script variables to use for this script. new_script_vars(script_items.ga_len); - SCRIPT_ITEM(script_items.ga_len).sn_prof_on = false; + si->sn_prof_on = false; } - SCRIPT_ITEM(sid).sn_name = name; - return &SCRIPT_ITEM(sid); + SCRIPT_ITEM(sid)->sn_name = name; + return SCRIPT_ITEM(sid); } static int source_using_linegetter(void *cookie, LineGetter fgetline, const char *traceback_name) @@ -2121,7 +2123,7 @@ int do_source(char *fname, int check_other, int is_vimrc) if (l_do_profiling == PROF_YES) { // Get "si" again, "script_items" may have been reallocated. - si = &SCRIPT_ITEM(current_sctx.sc_sid); + si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on) { si->sn_pr_start = profile_end(si->sn_pr_start); si->sn_pr_start = profile_sub_wait(wait_start, si->sn_pr_start); @@ -2201,7 +2203,7 @@ scriptitem_T *get_current_script_id(char **fnamep, sctx_T *ret_sctx) // inode number, even though to the user it is the same script. // - If a script is deleted and another script is written, with a // different name, the inode may be re-used. - si = &SCRIPT_ITEM(script_sctx.sc_sid); + si = SCRIPT_ITEM(script_sctx.sc_sid); if (si->sn_name != NULL && path_fnamecmp(si->sn_name, *fnamep) == 0) { // Found it! break; @@ -2227,7 +2229,7 @@ void ex_scriptnames(exarg_T *eap) emsg(_(e_invarg)); } else { if (eap->addr_count > 0) { - eap->arg = SCRIPT_ITEM(eap->line2).sn_name; + eap->arg = SCRIPT_ITEM(eap->line2)->sn_name; } else { expand_env(eap->arg, NameBuff, MAXPATHL); eap->arg = NameBuff; @@ -2238,8 +2240,8 @@ void ex_scriptnames(exarg_T *eap) } for (int i = 1; i <= script_items.ga_len && !got_int; i++) { - if (SCRIPT_ITEM(i).sn_name != NULL) { - home_replace(NULL, SCRIPT_ITEM(i).sn_name, NameBuff, MAXPATHL, true); + if (SCRIPT_ITEM(i)->sn_name != NULL) { + home_replace(NULL, SCRIPT_ITEM(i)->sn_name, NameBuff, MAXPATHL, true); vim_snprintf(IObuff, IOSIZE, "%3d: %s", i, NameBuff); if (!message_filtered(IObuff)) { msg_putchar('\n'); @@ -2255,8 +2257,8 @@ void ex_scriptnames(exarg_T *eap) void scriptnames_slash_adjust(void) { for (int i = 1; i <= script_items.ga_len; i++) { - if (SCRIPT_ITEM(i).sn_name != NULL) { - slash_adjust(SCRIPT_ITEM(i).sn_name); + if (SCRIPT_ITEM(i)->sn_name != NULL) { + slash_adjust(SCRIPT_ITEM(i)->sn_name); } } } @@ -2290,7 +2292,7 @@ char *get_scriptname(LastSet last_set, bool *should_free) case SID_STR: return _("anonymous :source"); default: { - char *const sname = SCRIPT_ITEM(last_set.script_ctx.sc_sid).sn_name; + char *const sname = SCRIPT_ITEM(last_set.script_ctx.sc_sid)->sn_name; if (sname == NULL) { snprintf(IObuff, IOSIZE, _("anonymous :source (script id %d)"), last_set.script_ctx.sc_sid); @@ -2310,13 +2312,15 @@ void free_scriptnames(void) # define FREE_SCRIPTNAME(item) \ do { \ + scriptitem_T *_si = *(item); \ /* the variables themselves are cleared in evalvars_clear() */ \ - xfree((item)->sn_vars); \ - xfree((item)->sn_name); \ - ga_clear(&(item)->sn_prl_ga); \ + xfree(_si->sn_vars); \ + xfree(_si->sn_name); \ + ga_clear(&_si->sn_prl_ga); \ + xfree(_si); \ } while (0) \ - GA_DEEP_CLEAR(&script_items, scriptitem_T, FREE_SCRIPTNAME); + GA_DEEP_CLEAR(&script_items, scriptitem_T *, FREE_SCRIPTNAME); } #endif diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h index 0812355716..9a810298f8 100644 --- a/src/nvim/runtime.h +++ b/src/nvim/runtime.h @@ -87,7 +87,7 @@ typedef struct { /// Growarray to store info about already sourced scripts. extern garray_T script_items; -#define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1]) +#define SCRIPT_ITEM(id) (((scriptitem_T **)script_items.ga_data)[(id) - 1]) #define SCRIPT_ID_VALID(id) ((id) > 0 && (id) <= script_items.ga_len) typedef void (*DoInRuntimepathCB)(char *, void *); -- cgit From d34c64e342dfba9248d1055e702d02620a1b31a8 Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Thu, 16 Feb 2023 13:15:02 +0100 Subject: feat: $NVIM_APPNAME #22128 This commit implements the ability to control all of the XDG paths Neovim should use. This is done by setting an environment variable named NVIM_APPNAME. For example, setting $NVIM_APPNAME makes Neovim look for its configuration directory in $XDG_CONFIG_HOME/$NVIM_APPNAME instead of $XDG_CONFIG_HOME/nvim. If NVIM_APPNAME is not set or is an empty string, "nvim" will be used as default. The usecase for this feature is to enable an easy way to switch from configuration to configuration. One might argue that the various $XDG environment variables can already be used for this usecase. However, setting $XDG environment variables also affects tools spawned by Neovim. For example, while setting $XDG_CONFIG_HOME will enable Neovim to use a different configuration directory, it will also prevent Git from finding its "default" configuration. Closes https://github.com/neovim/neovim/issues/21691 --- src/nvim/eval.c | 3 ++- src/nvim/fileio.c | 5 ++++- src/nvim/msgpack_rpc/server.c | 5 +++-- src/nvim/os/stdpaths.c | 39 +++++++++++++++++++++++++++------------ src/nvim/runtime.c | 41 +++++++++++++++++++++++------------------ 5 files changed, 59 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 92a8ffd646..ccea4f4951 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5368,13 +5368,14 @@ void get_xdg_var_list(const XDGVarType xdg, typval_T *rettv) return; } const void *iter = NULL; + const char *appname = get_appname(); do { size_t dir_len; const char *dir; iter = vim_env_iter(ENV_SEPCHAR, dirs, iter, &dir, &dir_len); if (dir != NULL && dir_len > 0) { char *dir_with_nvim = xmemdupz(dir, dir_len); - dir_with_nvim = concat_fnames_realloc(dir_with_nvim, "nvim", true); + dir_with_nvim = concat_fnames_realloc(dir_with_nvim, appname, true); tv_list_append_string(list, dir_with_nvim, (ssize_t)strlen(dir_with_nvim)); xfree(dir_with_nvim); } diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index a3cdd2bb23..755b8e0834 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -5181,7 +5181,10 @@ static void vim_mktempdir(void) // "/tmp/" exists, now try to create "/tmp/nvim./". add_pathsep(tmp); - xstrlcat(tmp, "nvim.", sizeof(tmp)); + + const char *appname = get_appname(); + xstrlcat(tmp, appname, sizeof(tmp)); + xstrlcat(tmp, ".", sizeof(tmp)); xstrlcat(tmp, user, sizeof(tmp)); (void)os_mkdir(tmp, 0700); // Always create, to avoid a race. bool owned = os_file_owned(tmp); diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index 1d75c208be..c6a0a4d8cc 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -91,13 +91,14 @@ char *server_address_new(const char *name) { static uint32_t count = 0; char fmt[ADDRESS_MAX_SIZE]; + const char *appname = get_appname(); #ifdef MSWIN int r = snprintf(fmt, sizeof(fmt), "\\\\.\\pipe\\%s.%" PRIu64 ".%" PRIu32, - name ? name : "nvim", os_get_pid(), count++); + name ? name : appname, os_get_pid(), count++); #else char *dir = stdpaths_get_xdg_var(kXDGRuntimeDir); int r = snprintf(fmt, sizeof(fmt), "%s/%s.%" PRIu64 ".%" PRIu32, - dir, name ? name : "nvim", os_get_pid(), count++); + dir, name ? name : appname, os_get_pid(), count++); xfree(dir); #endif if ((size_t)r >= sizeof(fmt)) { diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c index 6b07b6ef70..5235828f7a 100644 --- a/src/nvim/os/stdpaths.c +++ b/src/nvim/os/stdpaths.c @@ -57,6 +57,18 @@ static const char *const xdg_defaults[] = { #endif }; +/// Get the value of $NVIM_APPNAME or "nvim" if not set. +/// +/// @return $NVIM_APPNAME value +const char *get_appname(void) +{ + const char *env_val = os_getenv("NVIM_APPNAME"); + if (env_val == NULL || *env_val == '\0') { + env_val = "nvim"; + } + return env_val; +} + /// Return XDG variable value /// /// @param[in] idx XDG variable to use. @@ -100,25 +112,28 @@ char *stdpaths_get_xdg_var(const XDGVarType idx) /// Return Nvim-specific XDG directory subpath. /// -/// Windows: Uses "…/nvim-data" for kXDGDataHome to avoid storing +/// Windows: Uses "…/$NVIM_APPNAME-data" for kXDGDataHome to avoid storing /// configuration and data files in the same path. #4403 /// /// @param[in] idx XDG directory to use. /// -/// @return [allocated] "{xdg_directory}/nvim" +/// @return [allocated] "{xdg_directory}/$NVIM_APPNAME" char *get_xdg_home(const XDGVarType idx) FUNC_ATTR_WARN_UNUSED_RESULT { char *dir = stdpaths_get_xdg_var(idx); + const char *appname = get_appname(); + size_t appname_len = strlen(appname); + assert(appname_len < (IOSIZE - sizeof("-data"))); + if (dir) { + xstrlcpy(IObuff, appname, appname_len + 1); #if defined(MSWIN) - dir = concat_fnames_realloc(dir, - ((idx == kXDGDataHome - || idx == kXDGStateHome) ? "nvim-data" : "nvim"), - true); -#else - dir = concat_fnames_realloc(dir, "nvim", true); + if (idx == kXDGDataHome || idx == kXDGStateHome) { + STRCAT(IObuff, "-data"); + } #endif + dir = concat_fnames_realloc(dir, IObuff, true); #ifdef BACKSLASH_IN_FILENAME slash_adjust(dir); @@ -131,7 +146,7 @@ char *get_xdg_home(const XDGVarType idx) /// /// @param[in] fname New component of the path. /// -/// @return [allocated] `$XDG_CACHE_HOME/nvim/{fname}` +/// @return [allocated] `$XDG_CACHE_HOME/$NVIM_APPNAME/{fname}` char *stdpaths_user_cache_subpath(const char *fname) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { @@ -142,7 +157,7 @@ char *stdpaths_user_cache_subpath(const char *fname) /// /// @param[in] fname New component of the path. /// -/// @return [allocated] `$XDG_CONFIG_HOME/nvim/{fname}` +/// @return [allocated] `$XDG_CONFIG_HOME/$NVIM_APPNAME/{fname}` char *stdpaths_user_conf_subpath(const char *fname) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { @@ -153,7 +168,7 @@ char *stdpaths_user_conf_subpath(const char *fname) /// /// @param[in] fname New component of the path. /// -/// @return [allocated] `$XDG_DATA_HOME/nvim/{fname}` +/// @return [allocated] `$XDG_DATA_HOME/$NVIM_APPNAME/{fname}` char *stdpaths_user_data_subpath(const char *fname) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { @@ -166,7 +181,7 @@ char *stdpaths_user_data_subpath(const char *fname) /// @param[in] trailing_pathseps Amount of trailing path separators to add. /// @param[in] escape_commas If true, all commas will be escaped. /// -/// @return [allocated] `$XDG_STATE_HOME/nvim/{fname}`. +/// @return [allocated] `$XDG_STATE_HOME/$NVIM_APPNAME/{fname}`. char *stdpaths_user_state_subpath(const char *fname, const size_t trailing_pathseps, const bool escape_commas) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 9dc213d718..3487a8d7a2 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -1435,7 +1435,6 @@ static inline size_t compute_double_env_sep_len(const char *const val, const siz return ret; } -#define NVIM_SIZE (sizeof("nvim") - 1) /// Add directories to a ENV_SEPCHAR-separated array from a colon-separated one /// /// Commas are escaped in process. To each item PATHSEP "nvim" is appended in @@ -1464,6 +1463,8 @@ static inline char *add_env_sep_dirs(char *dest, const char *const val, const ch return dest; } const void *iter = NULL; + const char *appname = get_appname(); + const size_t appname_len = strlen(appname); do { size_t dir_len; const char *dir; @@ -1474,8 +1475,8 @@ static inline char *add_env_sep_dirs(char *dest, const char *const val, const ch if (!after_pathsep(dest - 1, dest)) { *dest++ = PATHSEP; } - memmove(dest, "nvim", NVIM_SIZE); - dest += NVIM_SIZE; + memmove(dest, appname, appname_len); + dest += appname_len; if (suf1 != NULL) { *dest++ = PATHSEP; memmove(dest, suf1, len1); @@ -1529,14 +1530,18 @@ static inline char *add_dir(char *dest, const char *const dir, const size_t dir_ if (!after_pathsep(dest - 1, dest)) { *dest++ = PATHSEP; } + const char *appname = get_appname(); + size_t appname_len = strlen(appname); + assert(appname_len < (IOSIZE - sizeof("-data"))); + xstrlcpy(IObuff, appname, appname_len + 1); #if defined(MSWIN) - size_t size = (type == kXDGDataHome ? sizeof("nvim-data") - 1 : NVIM_SIZE); - memmove(dest, (type == kXDGDataHome ? "nvim-data" : "nvim"), size); - dest += size; -#else - memmove(dest, "nvim", NVIM_SIZE); - dest += NVIM_SIZE; + if (type == kXDGDataHome || type == kXDGStateHome) { + STRCAT(IObuff, "-data"); + appname_len += 5; + } #endif + xstrlcpy(dest, IObuff, appname_len + 1); + dest += appname_len; if (suf1 != NULL) { *dest++ = PATHSEP; memmove(dest, suf1, len1); @@ -1596,16 +1601,17 @@ char *runtimepath_default(bool clean_arg) size_t config_len = 0; size_t vimruntime_len = 0; size_t libdir_len = 0; + const char *appname = get_appname(); + size_t appname_len = strlen(appname); if (data_home != NULL) { data_len = strlen(data_home); - if (data_len != 0) { + size_t nvim_data_size = appname_len; #if defined(MSWIN) - size_t nvim_size = (sizeof("nvim-data") - 1); -#else - size_t nvim_size = NVIM_SIZE; + nvim_data_size += sizeof("-data"); #endif + if (data_len != 0) { rtp_size += ((data_len + memcnt(data_home, ',', data_len) - + nvim_size + 1 + SITE_SIZE + 1 + + nvim_data_size + 1 + SITE_SIZE + 1 + !after_pathsep(data_home, data_home + data_len)) * 2 + AFTER_SIZE + 1); } @@ -1614,7 +1620,7 @@ char *runtimepath_default(bool clean_arg) config_len = strlen(config_home); if (config_len != 0) { rtp_size += ((config_len + memcnt(config_home, ',', config_len) - + NVIM_SIZE + 1 + + appname_len + 1 + !after_pathsep(config_home, config_home + config_len)) * 2 + AFTER_SIZE + 1); } @@ -1632,9 +1638,9 @@ char *runtimepath_default(bool clean_arg) } } rtp_size += compute_double_env_sep_len(data_dirs, - NVIM_SIZE + 1 + SITE_SIZE + 1, + appname_len + 1 + SITE_SIZE + 1, AFTER_SIZE + 1); - rtp_size += compute_double_env_sep_len(config_dirs, NVIM_SIZE + 1, + rtp_size += compute_double_env_sep_len(config_dirs, appname_len + 1, AFTER_SIZE + 1); char *rtp = NULL; if (rtp_size == 0) { @@ -1675,7 +1681,6 @@ freeall: return rtp; } -#undef NVIM_SIZE static void cmd_source(char *fname, exarg_T *eap) { -- cgit From 09b3432eaff3abcadb56d61b6f247f992b80b63f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 16 Feb 2023 10:07:18 -0500 Subject: fix(api): allow empty Lua table for nested dicts #22268 Problem: The Lua-API bridge allows Dict params to be empty Lua (list) tables at the function-signature level. But not for _nested_ Dicts, because they are not modeled: https://github.com/neovim/neovim/blob/fae754073289566051433fae74ec65783f9e7a6a/src/nvim/api/keysets.lua#L184 Some API functions like nvim_cmd check for kObjectTypeDictionary and don't handle the case of empty Lua tables (treated as "Array"). Solution: Introduce VALIDATE_T_DICT and use it in places where kObjectTypeDictionary was being checked directly. fixes #21005 --- src/nvim/api/command.c | 175 +++++++++++++++++++++------------------- src/nvim/api/private/validate.h | 23 ++++++ src/nvim/highlight.c | 2 +- 3 files changed, 117 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 81b70b07d0..6d63ae5e24 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -350,20 +350,24 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error } \ } while (0) -#define VALIDATION_ERROR(...) \ +#define VALIDATE_MOD(cond, mod_, name_) \ do { \ - api_set_error(err, kErrorTypeValidation, __VA_ARGS__); \ - goto end; \ + if (!(cond)) { \ + api_set_error(err, kErrorTypeValidation, "Command cannot accept %s: %s", (mod_), (name_)); \ + goto end; \ + } \ } while (0) bool output; OBJ_TO_BOOL(output, opts->output, false, "'output'"); - // First, parse the command name and check if it exists and is valid. - if (!HAS_KEY(cmd->cmd) || cmd->cmd.type != kObjectTypeString - || cmd->cmd.data.string.data[0] == NUL) { - VALIDATION_ERROR("'cmd' must be a non-empty String"); - } + VALIDATE_R(HAS_KEY(cmd->cmd), "cmd", { + goto end; + }); + VALIDATE_EXP((cmd->cmd.type == kObjectTypeString && cmd->cmd.data.string.data[0] != NUL), + "cmd", "non-empty String", NULL, { + goto end; + }); cmdname = string_to_cstr(cmd->cmd.data.string); ea.cmd = cmdname; @@ -382,12 +386,12 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error p = (ret && !aborting()) ? find_ex_command(&ea, NULL) : ea.cmd; } - if (p == NULL || ea.cmdidx == CMD_SIZE) { - VALIDATION_ERROR("Command not found: %s", cmdname); - } - if (is_cmd_ni(ea.cmdidx)) { - VALIDATION_ERROR("Command not implemented: %s", cmdname); - } + VALIDATE((p != NULL && ea.cmdidx != CMD_SIZE), "Command not found: %s", cmdname, { + goto end; + }); + VALIDATE(!is_cmd_ni(ea.cmdidx), "Command not implemented: %s", cmdname, { + goto end; + }); // Get the command flags so that we can know what type of arguments the command uses. // Not required for a user command since `find_ex_command` already deals with it in that case. @@ -397,9 +401,9 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error // Parse command arguments since it's needed to get the command address type. if (HAS_KEY(cmd->args)) { - if (cmd->args.type != kObjectTypeArray) { - VALIDATION_ERROR("'args' must be an Array"); - } + VALIDATE_T("args", kObjectTypeArray, cmd->args.type, { + goto end; + }); // Process all arguments. Convert non-String arguments to String and check if String arguments // have non-whitespace characters. @@ -421,14 +425,15 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error snprintf(data_str, NUMBUFLEN, "%" PRId64, elem.data.integer); break; case kObjectTypeString: - if (string_iswhite(elem.data.string)) { - VALIDATION_ERROR("String command argument must have at least one non-whitespace " - "character"); - } + VALIDATE_EXP(!string_iswhite(elem.data.string), "command arg", "non-whitespace", NULL, { + goto end; + }); data_str = xstrndup(elem.data.string.data, elem.data.string.size); break; default: - VALIDATION_ERROR("Invalid type for command argument"); + VALIDATE_EXP(false, "command arg", "valid type", api_typename(elem.type), { + goto end; + }); break; } @@ -456,9 +461,9 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error break; } - if (!argc_valid) { - VALIDATION_ERROR("Incorrect number of arguments supplied"); - } + VALIDATE(argc_valid, "%s", "Wrong number of arguments", { + goto end; + }); } // Simply pass the first argument (if it exists) as the arg pointer to `set_cmd_addr_type()` @@ -466,22 +471,23 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error set_cmd_addr_type(&ea, args.size > 0 ? args.items[0].data.string.data : NULL); if (HAS_KEY(cmd->range)) { - if (!(ea.argt & EX_RANGE)) { - VALIDATION_ERROR("Command cannot accept a range"); - } else if (cmd->range.type != kObjectTypeArray) { - VALIDATION_ERROR("'range' must be an Array"); - } else if (cmd->range.data.array.size > 2) { - VALIDATION_ERROR("'range' cannot contain more than two elements"); - } + VALIDATE_MOD((ea.argt & EX_RANGE), "range", cmd->cmd.data.string.data); + VALIDATE_T("range", kObjectTypeArray, cmd->range.type, { + goto end; + }); + VALIDATE_EXP((cmd->range.data.array.size <= 2), "range", "<=2 elements", NULL, { + goto end; + }); Array range = cmd->range.data.array; ea.addr_count = (int)range.size; for (size_t i = 0; i < range.size; i++) { Object elem = range.items[i]; - if (elem.type != kObjectTypeInteger || elem.data.integer < 0) { - VALIDATION_ERROR("'range' element must be a non-negative Integer"); - } + VALIDATE_EXP((elem.type == kObjectTypeInteger && elem.data.integer >= 0), + "range element", "non-negative Integer", NULL, { + goto end; + }); } if (range.size > 0) { @@ -489,9 +495,9 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error ea.line2 = (linenr_T)range.items[range.size - 1].data.integer; } - if (invalid_range(&ea) != NULL) { - VALIDATION_ERROR("Invalid range provided"); - } + VALIDATE_S((invalid_range(&ea) == NULL), "range", "", { + goto end; + }); } if (ea.addr_count == 0) { if (ea.argt & EX_DFLALL) { @@ -507,38 +513,38 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error } if (HAS_KEY(cmd->count)) { - if (!(ea.argt & EX_COUNT)) { - VALIDATION_ERROR("Command cannot accept a count"); - } else if (cmd->count.type != kObjectTypeInteger || cmd->count.data.integer < 0) { - VALIDATION_ERROR("'count' must be a non-negative Integer"); - } + VALIDATE_MOD((ea.argt & EX_COUNT), "count", cmd->cmd.data.string.data); + VALIDATE_EXP((cmd->count.type == kObjectTypeInteger && cmd->count.data.integer >= 0), + "count", "non-negative Integer", NULL, { + goto end; + }); set_cmd_count(&ea, (linenr_T)cmd->count.data.integer, true); } if (HAS_KEY(cmd->reg)) { - if (!(ea.argt & EX_REGSTR)) { - VALIDATION_ERROR("Command cannot accept a register"); - } else if (cmd->reg.type != kObjectTypeString || cmd->reg.data.string.size != 1) { - VALIDATION_ERROR("'reg' must be a single character"); - } + VALIDATE_MOD((ea.argt & EX_REGSTR), "register", cmd->cmd.data.string.data); + VALIDATE_EXP((cmd->reg.type == kObjectTypeString && cmd->reg.data.string.size == 1), + "reg", "single character", cmd->reg.data.string.data, { + goto end; + }); char regname = cmd->reg.data.string.data[0]; - if (regname == '=') { - VALIDATION_ERROR("Cannot use register \"="); - } else if (!valid_yank_reg(regname, ea.cmdidx != CMD_put && !IS_USER_CMDIDX(ea.cmdidx))) { - VALIDATION_ERROR("Invalid register: \"%c", regname); - } + VALIDATE((regname != '='), "%s", "Cannot use register \"=", { + goto end; + }); + VALIDATE(valid_yank_reg(regname, ea.cmdidx != CMD_put && !IS_USER_CMDIDX(ea.cmdidx)), + "Invalid register: \"%c", regname, { + goto end; + }); ea.regname = (uint8_t)regname; } OBJ_TO_BOOL(ea.forceit, cmd->bang, false, "'bang'"); - if (ea.forceit && !(ea.argt & EX_BANG)) { - VALIDATION_ERROR("Command cannot accept a bang"); - } + VALIDATE_MOD((!ea.forceit || (ea.argt & EX_BANG)), "bang", cmd->cmd.data.string.data); if (HAS_KEY(cmd->magic)) { - if (cmd->magic.type != kObjectTypeDictionary) { - VALIDATION_ERROR("'magic' must be a Dictionary"); - } + VALIDATE_T_DICT("magic", cmd->magic, { + goto end; + }); Dict(cmd_magic) magic = { 0 }; if (!api_dict_to_keydict(&magic, KeyDict_cmd_magic_get_field, @@ -559,9 +565,9 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error } if (HAS_KEY(cmd->mods)) { - if (cmd->mods.type != kObjectTypeDictionary) { - VALIDATION_ERROR("'mods' must be a Dictionary"); - } + VALIDATE_T_DICT("mods", cmd->mods, { + goto end; + }); Dict(cmd_mods) mods = { 0 }; if (!api_dict_to_keydict(&mods, KeyDict_cmd_mods_get_field, cmd->mods.data.dictionary, err)) { @@ -569,9 +575,9 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error } if (HAS_KEY(mods.filter)) { - if (mods.filter.type != kObjectTypeDictionary) { - VALIDATION_ERROR("'mods.filter' must be a Dictionary"); - } + VALIDATE_T_DICT("mods.filter", mods.filter, { + goto end; + }); Dict(cmd_mods_filter) filter = { 0 }; @@ -581,9 +587,9 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error } if (HAS_KEY(filter.pattern)) { - if (filter.pattern.type != kObjectTypeString) { - VALIDATION_ERROR("'mods.filter.pattern' must be a String"); - } + VALIDATE_T2(filter.pattern, kObjectTypeString, { + goto end; + }); OBJ_TO_BOOL(cmdinfo.cmdmod.cmod_filter_force, filter.force, false, "'mods.filter.force'"); @@ -598,18 +604,20 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error } if (HAS_KEY(mods.tab)) { - if (mods.tab.type != kObjectTypeInteger) { - VALIDATION_ERROR("'mods.tab' must be an Integer"); - } else if ((int)mods.tab.data.integer >= 0) { + VALIDATE_T2(mods.tab, kObjectTypeInteger, { + goto end; + }); + if ((int)mods.tab.data.integer >= 0) { // Silently ignore negative integers to allow mods.tab to be set to -1. cmdinfo.cmdmod.cmod_tab = (int)mods.tab.data.integer + 1; } } if (HAS_KEY(mods.verbose)) { - if (mods.verbose.type != kObjectTypeInteger) { - VALIDATION_ERROR("'mods.verbose' must be an Integer"); - } else if ((int)mods.verbose.data.integer >= 0) { + VALIDATE_T2(mods.verbose, kObjectTypeInteger, { + goto end; + }); + if ((int)mods.verbose.data.integer >= 0) { // Silently ignore negative integers to allow mods.verbose to be set to -1. cmdinfo.cmdmod.cmod_verbose = (int)mods.verbose.data.integer + 1; } @@ -624,9 +632,9 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error cmdinfo.cmdmod.cmod_split |= (horizontal ? WSP_HOR : 0); if (HAS_KEY(mods.split)) { - if (mods.split.type != kObjectTypeString) { - VALIDATION_ERROR("'mods.split' must be a String"); - } + VALIDATE_T2(mods.split, kObjectTypeString, { + goto end; + }); if (*mods.split.data.string.data == NUL) { // Empty string, do nothing. @@ -641,7 +649,9 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error } else if (strcmp(mods.split.data.string.data, "botright") == 0) { cmdinfo.cmdmod.cmod_split |= WSP_BOT; } else { - VALIDATION_ERROR("Invalid value for 'mods.split'"); + VALIDATE_S(false, "mods.split", "", { + goto end; + }); } } @@ -666,9 +676,10 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error cmdinfo.cmdmod.cmod_flags |= CMOD_SILENT; } - if ((cmdinfo.cmdmod.cmod_flags & CMOD_SANDBOX) && !(ea.argt & EX_SBOXOK)) { - VALIDATION_ERROR("Command cannot be run in sandbox"); - } + VALIDATE(!((cmdinfo.cmdmod.cmod_flags & CMOD_SANDBOX) && !(ea.argt & EX_SBOXOK)), + "%s", "Command cannot be run in sandbox", { + goto end; + }); } // Finally, build the command line string that will be stored inside ea.cmdlinep. @@ -739,7 +750,7 @@ end: #undef OBJ_TO_BOOL #undef OBJ_TO_CMOD_FLAG -#undef VALIDATION_ERROR +#undef VALIDATE_MOD } /// Check if a string contains only whitespace characters. diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index 469fed0f83..91a92c2762 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -38,12 +38,35 @@ #define VALIDATE_T(name, expected_t, actual_t, code) \ do { \ + STATIC_ASSERT(expected_t != kObjectTypeDictionary, "use VALIDATE_T_DICT"); \ if (expected_t != actual_t) { \ api_err_exp(err, name, api_typename(expected_t), api_typename(actual_t)); \ code; \ } \ } while (0) +/// Checks that `obj_` has type `expected_t`. +#define VALIDATE_T2(obj_, expected_t, code) \ + do { \ + STATIC_ASSERT(expected_t != kObjectTypeDictionary, "use VALIDATE_T_DICT"); \ + if ((obj_).type != expected_t) { \ + api_err_exp(err, STR(obj_), api_typename(expected_t), api_typename((obj_).type)); \ + code; \ + } \ + } while (0) + +/// Checks that `obj_` has Dict type. Also allows empty Array in a Lua context. +#define VALIDATE_T_DICT(name, obj_, code) \ + do { \ + if ((obj_).type != kObjectTypeDictionary \ + && !(channel_id == LUA_INTERNAL_CALL \ + && (obj_).type == kObjectTypeArray \ + && (obj_).data.array.size == 0)) { \ + api_err_exp(err, name, api_typename(kObjectTypeDictionary), api_typename((obj_).type)); \ + code; \ + } \ + } while (0) + #define VALIDATE_RANGE(cond, name, code) \ do { \ if (!(cond)) { \ diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index cf72102b60..72da66cfc2 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -1025,7 +1025,7 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e // TODO(clason): handle via gen_api_dispatch cterm_mask_provided = true; } else if (HAS_KEY(dict->cterm)) { - VALIDATE_T("cterm", kObjectTypeDictionary, dict->cterm.type, { + VALIDATE_EXP(false, "cterm", "Dict", api_typename(dict->cterm.type), { return hlattrs; }); } -- cgit From b5922bc6e6092cd44e032d4fff8d27955adf9c5c Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 16 Feb 2023 15:47:50 +0000 Subject: refactor(drawline.c): leadcol/trailcol --- src/nvim/drawline.c | 74 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 3cedb04bcb..57d586cd1e 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -567,6 +567,43 @@ static bool check_mb_utf8(int *c, int *u8cc) return false; } +static colnr_T get_trailcol(win_T *wp, const char *ptr, const char *line) +{ + colnr_T trailcol = MAXCOL; + // find start of trailing whitespace + if (wp->w_p_lcs_chars.trail) { + trailcol = (colnr_T)strlen(ptr); + while (trailcol > 0 && ascii_iswhite(ptr[trailcol - 1])) { + trailcol--; + } + trailcol += (colnr_T)(ptr - line); + } + + return trailcol; +} + +static colnr_T get_leadcol(win_T *wp, const char *ptr, const char *line) +{ + colnr_T leadcol = 0; + + // find end of leading whitespace + if (wp->w_p_lcs_chars.lead || wp->w_p_lcs_chars.leadmultispace != NULL) { + leadcol = 0; + while (ascii_iswhite(ptr[leadcol])) { + leadcol++; + } + if (ptr[leadcol] == NUL) { + // in a line full of spaces all of them are treated as trailing + leadcol = 0; + } else { + // keep track of the first column not filled with spaces + leadcol += (colnr_T)(ptr - line + 1); + } + } + + return leadcol; +} + /// Display line "lnum" of window 'wp' on the screen. /// wp->w_virtcol needs to be valid. /// @@ -603,8 +640,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int extra_attr = 0; // attributes when n_extra != 0 static char *at_end_str = ""; // used for p_extra when displaying curwin->w_p_lcs_chars.eol // at end-of-line - int lcs_eol_one = wp->w_p_lcs_chars.eol; // 'eol' until it's been used - int lcs_prec_todo = wp->w_p_lcs_chars.prec; // 'prec' until it's been used bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0; // saved "extra" items for when draw_state becomes WL_LINE (again) @@ -667,8 +702,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, hlf_T diff_hlf = (hlf_T)0; // type of diff highlighting int change_start = MAXCOL; // first col of changed area int change_end = -1; // last col of changed area - colnr_T trailcol = MAXCOL; // start of trailing spaces - colnr_T leadcol = 0; // start of leading spaces bool in_multispace = false; // in multiple consecutive spaces int multispace_pos = 0; // position in lcs-multispace string bool need_showbreak = false; // overlong line, skip first x chars @@ -997,6 +1030,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } } + colnr_T trailcol = MAXCOL; // start of trailing spaces + colnr_T leadcol = 0; // start of leading spaces + + int lcs_eol_one = wp->w_p_lcs_chars.eol; // 'eol' until it's been used + int lcs_prec_todo = wp->w_p_lcs_chars.prec; // 'prec' until it's been used + if (wp->w_p_list && !has_fold && !end_fill) { if (wp->w_p_lcs_chars.space || wp->w_p_lcs_chars.multispace != NULL @@ -1006,28 +1045,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, || wp->w_p_lcs_chars.nbsp) { extra_check = true; } - // find start of trailing whitespace - if (wp->w_p_lcs_chars.trail) { - trailcol = (colnr_T)strlen(ptr); - while (trailcol > (colnr_T)0 && ascii_iswhite(ptr[trailcol - 1])) { - trailcol--; - } - trailcol += (colnr_T)(ptr - line); - } - // find end of leading whitespace - if (wp->w_p_lcs_chars.lead || wp->w_p_lcs_chars.leadmultispace != NULL) { - leadcol = 0; - while (ascii_iswhite(ptr[leadcol])) { - leadcol++; - } - if (ptr[leadcol] == NUL) { - // in a line full of spaces all of them are treated as trailing - leadcol = (colnr_T)0; - } else { - // keep track of the first column not filled with spaces - leadcol += (colnr_T)(ptr - line) + 1; - } - } + } + + if (wp->w_p_list && !has_fold && !end_fill) { + trailcol = get_trailcol(wp, ptr, line); + leadcol = get_leadcol(wp, ptr, line); } // 'nowrap' or 'wrap' and a single line that doesn't fit: Advance to the -- cgit From bb377afd32cb4de2655ec0b28813f5237b66ed97 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Thu, 16 Feb 2023 13:52:41 -0700 Subject: build: use custom command to create single versiondef (#22290) When using a multi config generator, CMake generates an output file for each configuration when using file(GENERATE). When the contents of the file for each configuration are different, CMake fails. Instead, create separate files for each configuration and add a build time step to copy the configuration specific file to the generic path "auto/versiondef.h" which is included at build time. --- src/nvim/CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index d6a53456d7..04fe8aec5e 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -466,6 +466,15 @@ add_custom_target(update_version_stamp -P ${PROJECT_SOURCE_DIR}/cmake/GenerateVersion.cmake BYPRODUCTS ${NVIM_VERSION_GIT_H}) +set(NVIM_VERSION_DEF_H ${PROJECT_BINARY_DIR}/cmake.config/auto/versiondef.h) +add_custom_command( + OUTPUT "${NVIM_VERSION_DEF_H}" + COMMAND "${CMAKE_COMMAND}" + -E copy + "${PROJECT_BINARY_DIR}/cmake.config/auto/versiondef-$.h" + "${NVIM_VERSION_DEF_H}" + DEPENDS "${PROJECT_BINARY_DIR}/cmake.config/auto/versiondef-$.h") + # NVIM_GENERATED_FOR_HEADERS: generated headers to be included in headers # NVIM_GENERATED_FOR_SOURCES: generated headers to be included in sources # NVIM_GENERATED_SOURCES: generated source files @@ -503,7 +512,7 @@ foreach(sfile ${NVIM_SOURCES} set(depends "${HEADER_GENERATOR}" "${sfile}") if("${f}" STREQUAL "version.c") # Ensure auto/versiondef_git.h exists after "make clean". - list(APPEND depends update_version_stamp "${NVIM_VERSION_GIT_H}") + list(APPEND depends update_version_stamp "${NVIM_VERSION_GIT_H}" "${NVIM_VERSION_DEF_H}") endif() add_custom_command( OUTPUT "${gf_c_h}" "${gf_h_h}" -- cgit From 6dfabd0145c712e1419dcd6d5ce9192d766adbe3 Mon Sep 17 00:00:00 2001 From: ii14 <59243201+ii14@users.noreply.github.com> Date: Thu, 16 Feb 2023 22:09:05 +0100 Subject: build: use libuv config file (#22209) Libuv's recent changes in their pc file breaks cmake; they are using -l:libuv.a for the linker, and it seems cmake can't resolve that. Prefer using their cmake config file instead instead, and use the find module as a fall-back in case it fails. Closes https://github.com/neovim/neovim/issues/22271. --- src/nvim/CMakeLists.txt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 04fe8aec5e..11f2c3dc6d 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -2,9 +2,15 @@ add_library(main_lib INTERFACE) add_executable(nvim main.c) add_library(libuv_lib INTERFACE) -find_package(LibUV 1.28.0 REQUIRED) -target_include_directories(libuv_lib SYSTEM BEFORE INTERFACE ${LIBUV_INCLUDE_DIRS}) -target_link_libraries(libuv_lib INTERFACE ${LIBUV_LIBRARIES}) +find_package(libuv CONFIG) +if(TARGET libuv::uv_a) + target_link_libraries(libuv_lib INTERFACE libuv::uv_a) +else() + # Fallback to find module for older libuv versions, that don't provide the cmake package + find_package(LibUV 1.28.0 REQUIRED MODULE) + target_include_directories(libuv_lib SYSTEM BEFORE INTERFACE ${LIBUV_INCLUDE_DIRS}) + target_link_libraries(libuv_lib INTERFACE ${LIBUV_LIBRARIES}) +endif() find_package(Msgpack 1.0.0 REQUIRED) target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${MSGPACK_INCLUDE_DIRS}) -- cgit From 0326ef2f41a5c18c6cfd2c1b1dda95f7b309a5c4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 17 Feb 2023 07:15:24 +0800 Subject: vim-patch:9.0.1314: :messages behavior depends on 'fileformat' of current buffer (#22286) Problem: :messages behavior depends on 'fileformat' of current buffer. Solution: Pass the buffer pointer to where it is used. (Mirko Ceroni, closes vim/vim#11995) https://github.com/vim/vim/commit/1d87e11a1ef201b26ed87585fba70182ad0c468a Co-authored-by: cero1988 --- src/nvim/charset.c | 25 ++++++++++++++++++------- src/nvim/message.c | 12 ++++++------ 2 files changed, 24 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/nvim/charset.c b/src/nvim/charset.c index c4c7c5f387..1cfb5350f3 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -547,7 +547,6 @@ char *transchar(int c) } char_u *transchar_buf(const buf_T *buf, int c) - FUNC_ATTR_NONNULL_ALL { int i = 0; if (IS_SPECIAL(c)) { @@ -571,21 +570,34 @@ char_u *transchar_buf(const buf_T *buf, int c) return transchar_charbuf; } -/// Like transchar(), but called with a byte instead of a character +/// Like transchar(), but called with a byte instead of a character. /// -/// Checks for an illegal UTF-8 byte. +/// Checks for an illegal UTF-8 byte. Uses 'fileformat' of the current buffer. /// /// @param[in] c Byte to translate. /// /// @return pointer to translated character in transchar_charbuf. char_u *transchar_byte(const int c) FUNC_ATTR_WARN_UNUSED_RESULT +{ + return transchar_byte_buf(curbuf, c); +} + +/// Like transchar_buf(), but called with a byte instead of a character. +/// +/// Checks for an illegal UTF-8 byte. Uses 'fileformat' of "buf", unless it is NULL. +/// +/// @param[in] c Byte to translate. +/// +/// @return pointer to translated character in transchar_charbuf. +char_u *transchar_byte_buf(const buf_T *buf, const int c) + FUNC_ATTR_WARN_UNUSED_RESULT { if (c >= 0x80) { - transchar_nonprint(curbuf, transchar_charbuf, c); + transchar_nonprint(buf, transchar_charbuf, c); return transchar_charbuf; } - return (char_u *)transchar(c); + return transchar_buf(buf, c); } /// Convert non-printable characters to 2..4 printable ones @@ -598,12 +610,11 @@ char_u *transchar_byte(const int c) /// @param[in] c Character to convert. NUL is assumed to be NL according to /// `:h NL-used-for-NUL`. void transchar_nonprint(const buf_T *buf, char_u *charbuf, int c) - FUNC_ATTR_NONNULL_ALL { if (c == NL) { // we use newline in place of a NUL c = NUL; - } else if ((c == CAR) && (get_fileformat(buf) == EOL_MAC)) { + } else if (buf != NULL && c == CAR && get_fileformat(buf) == EOL_MAC) { // we use CR in place of NL in this case c = NL; } diff --git a/src/nvim/message.c b/src/nvim/message.c index 4904bde095..dc88c53392 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -773,7 +773,7 @@ bool emsg(const char *s) void emsg_invreg(int name) { - semsg(_("E354: Invalid register name: '%s'"), transchar(name)); + semsg(_("E354: Invalid register name: '%s'"), transchar_buf(NULL, name)); } /// Print an error message with unknown number of arguments @@ -1531,7 +1531,7 @@ char *msg_outtrans_one(char *p, int attr) msg_outtrans_len_attr(p, l, attr); return p + l; } - msg_puts_attr((const char *)transchar_byte((uint8_t)(*p)), attr); + msg_puts_attr((const char *)transchar_byte_buf(NULL, (uint8_t)(*p)), attr); return p + 1; } @@ -1576,14 +1576,14 @@ int msg_outtrans_len_attr(const char *msgstr, int len, int attr) msg_puts_attr_len(plain_start, str - plain_start, attr); } plain_start = str + mb_l; - msg_puts_attr((const char *)transchar(c), + msg_puts_attr((const char *)transchar_buf(NULL, c), (attr == 0 ? HL_ATTR(HLF_8) : attr)); retval += char2cells(c); } len -= mb_l - 1; str += mb_l; } else { - s = (char *)transchar_byte((uint8_t)(*str)); + s = (char *)transchar_byte_buf(NULL, (uint8_t)(*str)); if (s[1] != NUL) { // Unprintable char: print the printable chars so far and the // translation of the unprintable char. @@ -1665,7 +1665,7 @@ int msg_outtrans_special(const char *strstart, bool from, int maxlen) } if (text[0] != NUL && text[1] == NUL) { // single-byte character or illegal byte - text = (char *)transchar_byte((uint8_t)text[0]); + text = (char *)transchar_byte_buf(NULL, (uint8_t)text[0]); } const int len = vim_strsize((char *)text); if (maxlen > 0 && retval + len >= maxlen) { @@ -1911,7 +1911,7 @@ void msg_prt_line(char *s, int list) s--; } else if (c != NUL && (n = byte2cells(c)) > 1) { n_extra = n - 1; - p_extra = (char *)transchar_byte(c); + p_extra = (char *)transchar_byte_buf(NULL, c); c_extra = NUL; c_final = NUL; c = (unsigned char)(*p_extra++); -- cgit From dea311b33d7be6c76ba2a48e604a112ae1dc61d6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 17 Feb 2023 08:14:24 +0800 Subject: test(old): run some part of 'cpoptions' tests --- src/nvim/testdir/test_cpoptions.vim | 78 +++++++++++++-------------- src/nvim/testdir/test_normal.vim | 100 ++++++++++++++++++----------------- src/nvim/testdir/test_substitute.vim | 23 ++++---- 3 files changed, 102 insertions(+), 99 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_cpoptions.vim b/src/nvim/testdir/test_cpoptions.vim index b9307ab30b..1427c8accc 100644 --- a/src/nvim/testdir/test_cpoptions.vim +++ b/src/nvim/testdir/test_cpoptions.vim @@ -217,33 +217,33 @@ endfunc " Test for the 'g' flag in 'cpo' (jump to line 1 when re-editing a file) func Test_cpo_g() - throw 'Skipped: Nvim does not support cpoptions flag "g"' let save_cpo = &cpo new test_cpoptions.vim set cpo-=g normal 20G edit call assert_equal(20, line('.')) - set cpo+=g - edit - call assert_equal(1, line('.')) + " Nvim: no "g" flag in 'cpoptions'. + " set cpo+=g + " edit + " call assert_equal(1, line('.')) close! let &cpo = save_cpo endfunc " Test for inserting text in a line with only spaces ('H' flag in 'cpoptions') func Test_cpo_H() - throw 'Skipped: Nvim does not support cpoptions flag "H"' let save_cpo = &cpo new set cpo-=H call setline(1, ' ') normal! Ia call assert_equal(' a', getline(1)) - set cpo+=H - call setline(1, ' ') - normal! Ia - call assert_equal(' a ', getline(1)) + " Nvim: no "H" flag in 'cpoptions'. + " set cpo+=H + " call setline(1, ' ') + " normal! Ia + " call assert_equal(' a ', getline(1)) close! let &cpo = save_cpo endfunc @@ -560,15 +560,15 @@ endfunc " Test for the 'w' flag in 'cpo' ('cw' on a blank character changes only one " character) func Test_cpo_w() - throw 'Skipped: Nvim does not support cpoptions flag "w"' let save_cpo = &cpo new - set cpo+=w - call setline(1, 'here are some words') - norm! 1gg0elcwZZZ - call assert_equal('hereZZZ are some words', getline('.')) - norm! 1gg2elcWYYY - call assert_equal('hereZZZ areYYY some words', getline('.')) + " Nvim: no "w" flag in 'cpoptions'. + " set cpo+=w + " call setline(1, 'here are some words') + " norm! 1gg0elcwZZZ + " call assert_equal('hereZZZ are some words', getline('.')) + " norm! 1gg2elcWYYY + " call assert_equal('hereZZZ areYYY some words', getline('.')) set cpo-=w call setline(1, 'here are some words') norm! 1gg0elcwZZZ @@ -745,16 +745,16 @@ endfunc " Test for the '*' flag in 'cpo' (':*' is same as ':@') func Test_cpo_star() - throw 'Skipped: Nvim does not support cpoptions flag "*"' let save_cpo = &cpo let x = 0 new set cpo-=* let @a = 'let x += 1' call assert_fails('*a', 'E20:') - set cpo+=* - *a - call assert_equal(1, x) + " Nvim: no "*" flag in 'cpoptions'. + " set cpo+=* + " *a + " call assert_equal(1, x) close! let &cpo = save_cpo endfunc @@ -815,7 +815,6 @@ endfunc " Test for the '#' flag in 'cpo' (count before 'D', 'o' and 'O' operators) func Test_cpo_hash() - throw 'Skipped: Nvim does not support cpoptions flag "#"' let save_cpo = &cpo new set cpo-=# @@ -827,14 +826,15 @@ func Test_cpo_hash() normal gg2Otwo call assert_equal(['two', 'two', 'three', 'four', 'four'], getline(1, '$')) %d - set cpo+=# - call setline(1, ['one', 'two', 'three']) - normal gg2D - call assert_equal(['', 'two', 'three'], getline(1, '$')) - normal gg2oone - call assert_equal(['', 'one', 'two', 'three'], getline(1, '$')) - normal gg2Ozero - call assert_equal(['zero', '', 'one', 'two', 'three'], getline(1, '$')) + " Nvim: no "#" flag in 'cpoptions'. + " set cpo+=# + " call setline(1, ['one', 'two', 'three']) + " normal gg2D + " call assert_equal(['', 'two', 'three'], getline(1, '$')) + " normal gg2oone + " call assert_equal(['', 'one', 'two', 'three'], getline(1, '$')) + " normal gg2Ozero + " call assert_equal(['zero', '', 'one', 'two', 'three'], getline(1, '$')) close! let &cpo = save_cpo endfunc @@ -858,16 +858,16 @@ endfunc " Test for the '\' flag in 'cpo' (backslash in a [] range in a search pattern) func Test_cpo_backslash() - throw 'Skipped: Nvim does not support cpoptions flag "\"' let save_cpo = &cpo new call setline(1, ['', " \\-string"]) set cpo-=\ exe 'normal gg/[ \-]' .. "\n" call assert_equal(3, col('.')) - set cpo+=\ - exe 'normal gg/[ \-]' .. "\n" - call assert_equal(2, col('.')) + " Nvim: no "\" flag in 'cpoptions'. + " set cpo+=\ + " exe 'normal gg/[ \-]' .. "\n" + " call assert_equal(2, col('.')) close! let &cpo = save_cpo endfunc @@ -877,7 +877,6 @@ endfunc " Test for the '{' flag in 'cpo' (the "{" and "}" commands stop at a { " character at the start of a line) func Test_cpo_brace() - throw 'Skipped: Nvim does not support cpoptions flag "{"' let save_cpo = &cpo new call setline(1, ['', '{', ' int i;', '}', '']) @@ -886,11 +885,12 @@ func Test_cpo_brace() call assert_equal(5, line('.')) normal G{ call assert_equal(1, line('.')) - set cpo+={ - normal gg} - call assert_equal(2, line('.')) - normal G{ - call assert_equal(2, line('.')) + " Nvim: no "{" flag in 'cpoptions'. + " set cpo+={ + " normal gg} + " call assert_equal(2, line('.')) + " normal G{ + " call assert_equal(2, line('.')) close! let &cpo = save_cpo endfunc diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index 2aaa1ff830..390e179f13 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -2254,61 +2254,63 @@ func Test_normal29_brace() " set cpo+={ " 1 " norm! 0d2} - " let expected =<< trim [DATA] - " { - " This is no paragraph - " unless the '{' is set - " in 'cpoptions' - " } - " .IP - " The nroff macros IP separates a paragraph - " That means, it must be a '.' - " followed by IP - " .LPIt does not matter, if afterwards some - " more characters follow. - " .SHAlso section boundaries from the nroff - " macros terminate a paragraph. That means - " a character like this: - " .NH - " End of text here - " - " [DATA] + + let expected =<< trim [DATA] + { + This is no paragraph + unless the '{' is set + in 'cpoptions' + } + .IP + The nroff macros IP separates a paragraph + That means, it must be a '.' + followed by IP + .LPIt does not matter, if afterwards some + more characters follow. + .SHAlso section boundaries from the nroff + macros terminate a paragraph. That means + a character like this: + .NH + End of text here + + [DATA] " call assert_equal(expected, getline(1, '$')) - " + " $ " norm! d} - " let expected =<< trim [DATA] - " { - " This is no paragraph - " unless the '{' is set - " in 'cpoptions' - " } - " .IP - " The nroff macros IP separates a paragraph - " That means, it must be a '.' - " followed by IP - " .LPIt does not matter, if afterwards some - " more characters follow. - " .SHAlso section boundaries from the nroff - " macros terminate a paragraph. That means - " a character like this: - " .NH - " End of text here - " - " [DATA] + + let expected =<< trim [DATA] + { + This is no paragraph + unless the '{' is set + in 'cpoptions' + } + .IP + The nroff macros IP separates a paragraph + That means, it must be a '.' + followed by IP + .LPIt does not matter, if afterwards some + more characters follow. + .SHAlso section boundaries from the nroff + macros terminate a paragraph. That means + a character like this: + .NH + End of text here + + [DATA] " call assert_equal(expected, getline(1, '$')) - " + " norm! gg} " norm! d5} - " - " let expected =<< trim [DATA] - " { - " This is no paragraph - " unless the '{' is set - " in 'cpoptions' - " } - - " [DATA] + + let expected =<< trim [DATA] + { + This is no paragraph + unless the '{' is set + in 'cpoptions' + } + + [DATA] " call assert_equal(expected, getline(1, '$')) " Jumping to a fold should open the fold diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim index c99a0d456d..b2abbae168 100644 --- a/src/nvim/testdir/test_substitute.vim +++ b/src/nvim/testdir/test_substitute.vim @@ -296,15 +296,15 @@ endfunc " Test for *:s%* on :substitute. func Test_sub_cmd_6() - throw 'Skipped: Nvim does not support cpoptions flag "/"' set magic& - set cpo+=/ + " Nvim: no "/" flag in 'cpoptions'. + " set cpo+=/ " List entry format: [input, cmd, output] let tests = [ ['A', 's/A/a/', ['a']], \ ['B', 's/B/%/', ['a']], \ ] - call Run_SubCmd_Tests(tests) + " call Run_SubCmd_Tests(tests) set cpo-=/ let tests = [ ['C', 's/C/c/', ['c']], @@ -585,10 +585,11 @@ endfunc func Test_sub_replace_6() set magic& + " Nvim: no "/" flag in 'cpoptions'. " set cpo+=/ call assert_equal('a', substitute('A', 'A', 'a', '')) call assert_equal('%', substitute('B', 'B', '%', '')) - " set cpo-=/ + set cpo-=/ call assert_equal('c', substitute('C', 'C', 'c', '')) call assert_equal('%', substitute('D', 'D', '%', '')) endfunc @@ -853,13 +854,13 @@ func Test_sub_with_no_last_pat() call assert_equal([], readfile('Xresult')) endif - " Nvim does not support cpoptions flag "/"' - " let lines =<< trim [SCRIPT] - " set cpo+=/ - " call assert_fails('s/abc/%/', 'E33:') - " call writefile(v:errors, 'Xresult') - " qall! - " [SCRIPT] + let lines =<< trim [SCRIPT] + set cpo+=/ + call assert_fails('s/abc/%/', 'E33:') + call writefile(v:errors, 'Xresult') + qall! + [SCRIPT] + " Nvim: no "/" flag in 'cpoptions'. " call writefile(lines, 'Xscript') " if RunVim([], [], '--clean -S Xscript') " call assert_equal([], readfile('Xresult')) -- cgit From df666521ac4dd338b59082b1100a4673acde9e64 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 17 Feb 2023 08:41:04 +0800 Subject: fix(mappings): fix check for cpo-B inverted in completion --- src/nvim/mapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index c740fb41bc..0b2cf6ea47 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -1167,7 +1167,7 @@ static char *translate_mapping(char_u *str, int cpo_flags) garray_T ga; ga_init(&ga, 1, 40); - bool cpo_bslash = !(cpo_flags&FLAG_CPO_BSLASH); + bool cpo_bslash = cpo_flags & FLAG_CPO_BSLASH; for (; *str; str++) { int c = *str; -- cgit From f6a6db3e248dd6360dbd55574321ddc216848c13 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 17 Feb 2023 07:59:22 +0800 Subject: vim-patch:8.2.0148: mapping related function in wrong source file Problem: Mapping related function in wrong source file. Solution: Move the function. Add a few more test cases. (Yegappan Lakshmanan, closes vim/vim#5528) https://github.com/vim/vim/commit/7f51bbe0d19f1f0cb0321326f45a17b4f5155f89 Co-authored-by: Bram Moolenaar --- src/nvim/testdir/setup.vim | 8 +++++--- src/nvim/testdir/test_mapping.vim | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/setup.vim b/src/nvim/testdir/setup.vim index f895287469..25ac2d1239 100644 --- a/src/nvim/testdir/setup.vim +++ b/src/nvim/testdir/setup.vim @@ -26,9 +26,11 @@ if exists('s:did_load') set viewoptions& set viewoptions+=options set switchbuf= - " Make "Q" switch to Ex mode. - " This does not work for all tests. - nnoremap Q gQ + if g:testname !~ 'test_mapping.vim$' + " Make "Q" switch to Ex mode. + " This does not work for all tests. + nnoremap Q gQ + endif endif " Common preparations for running tests. diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim index 5c5a65d4ca..6cf19306ec 100644 --- a/src/nvim/testdir/test_mapping.vim +++ b/src/nvim/testdir/test_mapping.vim @@ -934,6 +934,39 @@ func Test_abbr_remove() call assert_equal({}, maparg('foo', 'i', 1, 1)) endfunc +" Trigger an abbreviation using a special key +func Test_abbr_trigger_special() + new + iabbr teh the + call feedkeys("iteh\\", 'xt') + call assert_equal('the', getline(1)) + iunab teh + close! +endfunc + +" Test for '<' in 'cpoptions' +func Test_map_cpo_special_keycode() + set cpo-=< + imap xk Test + let d = maparg('xk', 'i', 0, 1) + call assert_equal(['x\k', 'Test', 'i'], [d.lhs, d.rhs, d.mode]) + call feedkeys(":imap x\\\"\", 'tx') + call assert_equal('"imap x\k', @:) + iunmap xk + " Nvim: no "<" flag in 'cpoptions'. + " set cpo+=< + " imap xk Test + " let d = maparg('xk', 'i', 0, 1) + " call assert_equal(['xk', 'Test', 'i'], [d.lhs, d.rhs, d.mode]) + " call feedkeys(":imap x\\\"\", 'tx') + " call assert_equal('"imap xk', @:) + " iunmap xk + set cpo-=< + " Modifying 'cpo' above adds some default mappings, remove them + mapclear + mapclear! +endfunc + func Test_map_cmdkey_redo() func SelectDash() call search('^---\n\zs', 'bcW') -- cgit From 371a74e4e1685f21e83c70eb8f0bd05c2ce24e49 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 17 Feb 2023 11:19:40 +0800 Subject: fix(tui): only forward stdin_fd on first attach (#22293) --- src/nvim/ui_client.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index df0a26c6ee..0bd9490368 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -93,6 +93,7 @@ void ui_client_attach(int width, int height, char *term) PUT_C(opts, "stdout_tty", BOOLEAN_OBJ(stdout_isatty)); if (ui_client_forward_stdin) { PUT_C(opts, "stdin_fd", INTEGER_OBJ(UI_CLIENT_STDIN_FD)); + ui_client_forward_stdin = false; // stdin shouldn't be forwarded again #22292 } } ADD_C(args, DICTIONARY_OBJ(opts)); -- cgit From 75dab3cf0781f664ac866f511df2fb2c06aa7d17 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 18 Feb 2023 06:52:56 +0800 Subject: fix(mappings): make "<" escaping in completion match Vim --- src/nvim/mapping.c | 2 +- src/nvim/testdir/test_autocmd.vim | 2 +- src/nvim/testdir/test_cmdline.vim | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 0b2cf6ea47..ce4c0586e3 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -1194,7 +1194,7 @@ static char *translate_mapping(char_u *str, int cpo_flags) } if (c == ' ' || c == '\t' || c == Ctrl_J || c == Ctrl_V - || (c == '\\' && !cpo_bslash)) { + || c == '<' || (c == '\\' && !cpo_bslash)) { ga_append(&ga, cpo_bslash ? Ctrl_V : '\\'); } diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 30d30c8b29..6d7f1649b3 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -2720,7 +2720,7 @@ func Test_autocmd_bufreadpre() close close call delete('XAutocmdBufReadPre.txt') - " set cpo-=g + set cpo-=g endfunc " FileChangedShell tested in test_filechanged.vim diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index cf1d56ae38..64bfb142e7 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -340,7 +340,7 @@ func Test_map_completion() call feedkeys(":map \\"\", 'xt') call assert_equal('"map ', getreg(':')) call feedkeys(":map \\"\", 'xt') - " call assert_equal("\"map ", getreg(':')) + call assert_equal("\"map ", getreg(':')) unmap " set cpo+=< @@ -369,7 +369,7 @@ func Test_map_completion() call feedkeys(":map \\"\", 'xt') call assert_equal('"map ', getreg(':')) unmap - " set cpo-=k + set cpo-=k call assert_fails('call feedkeys(":map \\\\%(\\\"\", "xt")', 'E53:') -- cgit From afe34d92a7f28245a96748d70b5e073715b94e22 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 18 Feb 2023 06:50:58 +0800 Subject: vim-patch:9.0.1315: escaping for completion of map command not properly tested Problem: Escaping for completion of map command not properly tested. Solution: Add a few test cases. (closes vim/vim#12009) https://github.com/vim/vim/commit/c3a26c6bff666a368b0a22d35d2e00aa62770f8c --- src/nvim/testdir/test_cmdline.vim | 6 +++++- src/nvim/testdir/test_cpoptions.vim | 13 ++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 64bfb142e7..d568b5d425 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -330,17 +330,21 @@ func Test_map_completion() call assert_equal('"map ', getreg(':')) call feedkeys(":map \\\"\", 'xt') call assert_equal("\"map \", getreg(':')) + call feedkeys(":map \\\"\", 'xt') + call assert_equal("\"map x", getreg(':')) unmap ,f unmap ,g unmap unmap x - set cpo-=< cpo-=B cpo-=k + set cpo-=< cpo-=k map left call feedkeys(":map \\"\", 'xt') call assert_equal('"map ', getreg(':')) call feedkeys(":map \\"\", 'xt') call assert_equal("\"map ", getreg(':')) + call feedkeys(":map \\\\"\", 'xt') + call assert_equal("\"map \x", getreg(':')) unmap " set cpo+=< diff --git a/src/nvim/testdir/test_cpoptions.vim b/src/nvim/testdir/test_cpoptions.vim index 1427c8accc..846671a646 100644 --- a/src/nvim/testdir/test_cpoptions.vim +++ b/src/nvim/testdir/test_cpoptions.vim @@ -68,15 +68,20 @@ endfunc func Test_cpo_B() let save_cpo = &cpo new + imap xk Test set cpo-=B iabbr abc ab\d exe "normal iabc " call assert_equal('abd ', getline(1)) + call feedkeys(":imap x\\\"\", 'tx') + call assert_equal('"imap x\\k', @:) %d set cpo+=B iabbr abc ab\d exe "normal iabc " call assert_equal('abd ', getline(1)) + call feedkeys(":imap x\\\"\", 'tx') + call assert_equal('"imap x\k', @:) close! let &cpo = save_cpo endfunc @@ -195,7 +200,8 @@ func Test_cpo_f() set cpo+=f read test_cpoptions.vim call assert_equal('test_cpoptions.vim', @%) - close! + + bwipe! let &cpo = save_cpo endfunc @@ -428,7 +434,7 @@ func Test_cpo_O() let &cpo = save_cpo endfunc -" Test for the 'p' flag in 'cpo' is in the test_lispwords.vim file. +" Test for the 'p' flag in 'cpo' is in the test_lispindent.vim file. " Test for the 'P' flag in 'cpo' (appending to a file sets the current file " name) @@ -444,7 +450,8 @@ func Test_cpo_P() set cpo+=P write >> XfileCpoP call assert_equal('XfileCpoP', @%) - close! + + bwipe! call delete('XfileCpoP') let &cpo = save_cpo endfunc -- cgit From 9301abdf748b54fa3d41375cc4659ca9f4b57dd8 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 18 Feb 2023 17:43:39 +0100 Subject: ci: enable CI_BUILD automatically if environment variable CI is true (#22312) Having to specify CI_BUILD for every CI job requires boilerplate. More importantly, it's easy to forget to enable CI_BUILD, as seen by 8a20f9f98a90a7a43aea08fcde2c40a5356b4f7b. It's simpler to remember to turn CI_BUILD off when a job errors instead of remembering that every new job should have CI_BUILD on. --- src/nvim/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 11f2c3dc6d..7d75b8038e 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -170,7 +170,11 @@ if(HAS_DIAG_COLOR_FLAG) endif() endif() -option(CI_BUILD "CI, extra flags will be set" OFF) +if($ENV{CI}) + option(CI_BUILD "CI, extra flags will be set" ON) +else() + option(CI_BUILD "CI, extra flags will be set" OFF) +endif() if(CI_BUILD) message(STATUS "CI build enabled") if(MSVC) -- cgit From db849517c613733fb2959d43e6d10d5d98d5033d Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 18 Feb 2023 19:06:38 +0100 Subject: fix: remove "Features" section from --version/:version (#22315) Neovim doesn not have any optional features. --- src/nvim/version.c | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) (limited to 'src') diff --git a/src/nvim/version.c b/src/nvim/version.c index 3324ac2a94..8ae43cb488 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -57,17 +57,6 @@ char *version_cflags = "Compilation: " NVIM_VERSION_CFLAGS; # include "version.c.generated.h" #endif -static char *features[] = { -#ifdef HAVE_ACL - "+acl", -#else - "-acl", -#endif - - "+tui", - NULL -}; - // clang-format off static const int included_patches[] = { 2424, @@ -2619,21 +2608,6 @@ static void version_msg(char *s) version_msg_wrap(s, false); } -/// List all features. -/// This does not use list_in_columns (as in Vim), because there are only a -/// few, and we do not start at a new line. -static void list_features(void) -{ - version_msg(_("\n\nFeatures: ")); - for (int i = 0; features[i] != NULL; i++) { - version_msg(features[i]); - if (features[i + 1] != NULL) { - version_msg(" "); - } - } - version_msg("\nSee \":help feature-compile\"\n\n"); -} - /// List string items nicely aligned in columns. /// When "size" is < 0 then the last entry is marked with NULL. /// The entry with index "current" is inclosed in []. @@ -2742,7 +2716,7 @@ void list_version(void) } #endif // ifdef HAVE_PATHDEF - list_features(); + version_msg("\n\n"); #ifdef SYS_VIMRC_FILE version_msg(_(" system vimrc file: \"")); -- cgit From 458299df796572c8b7cbb6b6af03f4642cf03215 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 18 Feb 2023 20:10:00 +0100 Subject: fix: remove "Compiled by:" from :version/--version (#22316) The :version output is already crowded as is, the last thing we need is extraneous messages about who compiled it. --- src/nvim/globals.h | 2 -- src/nvim/version.c | 17 ----------------- 2 files changed, 19 deletions(-) (limited to 'src') diff --git a/src/nvim/globals.h b/src/nvim/globals.h index df4ae05522..94448eb7d7 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -806,8 +806,6 @@ enum { extern char *default_vim_dir; extern char *default_vimruntime_dir; extern char *default_lib_dir; -extern char *compiled_user; -extern char *compiled_sys; #endif // When a window has a local directory, the absolute path of the global diff --git a/src/nvim/version.c b/src/nvim/version.c index 8ae43cb488..a9d72bf017 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -2699,23 +2699,6 @@ void list_version(void) msg(version_cflags); #endif -#ifdef HAVE_PATHDEF - - if ((*compiled_user != NUL) || (*compiled_sys != NUL)) { - msg_puts(_("\nCompiled ")); - - if (*compiled_user != NUL) { - msg_puts(_("by ")); - msg_puts((const char *)compiled_user); - } - - if (*compiled_sys != NUL) { - msg_puts("@"); - msg_puts((const char *)compiled_sys); - } - } -#endif // ifdef HAVE_PATHDEF - version_msg("\n\n"); #ifdef SYS_VIMRC_FILE -- cgit From 53841df58d44b64637d6400abd7d4ace9c018be8 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Sat, 18 Feb 2023 21:35:27 +0100 Subject: fix: Add missing void as function argument (#22317) --- src/cjson/fpconv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cjson/fpconv.c b/src/cjson/fpconv.c index b2f7a214c2..0ef7f18cbe 100644 --- a/src/cjson/fpconv.c +++ b/src/cjson/fpconv.c @@ -202,7 +202,7 @@ int fpconv_g_fmt(char *str, double num, int precision) return len; } -void fpconv_init() +void fpconv_init(void) { fpconv_update_locale(); } -- cgit From 2f6413797499a1bdac28c20a491e8ea3be33bda3 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Sun, 19 Feb 2023 01:27:32 +0100 Subject: vim-patch:9.0.1319: PRQL files are not recognized (#22319) Problem: PRQL files are not recognized. Solution: Add a filetype pattern for PRQL files. (Matthias Queitsch, closes vim/vim#12018) https://github.com/vim/vim/commit/9de960ace0f017fcfeaf64a2f6492f0f88b11fdb Co-authored-by: Matthias Queitsch --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 0264e203d9..576f2c9f2b 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -550,6 +550,7 @@ let s:filename_checks = { \ 'spyce': ['file.spy', 'file.spi'], \ 'sql': ['file.tyb', 'file.typ', 'file.tyc', 'file.pkb', 'file.pks'], \ 'sqlj': ['file.sqlj'], + \ 'prql': ['file.prql'], \ 'sqr': ['file.sqr', 'file.sqi'], \ 'squid': ['squid.conf'], \ 'squirrel': ['file.nut'], -- cgit From cbd4480f97a913e0e356ec02f652b693b0195767 Mon Sep 17 00:00:00 2001 From: luukvbaal <31730729+luukvbaal@users.noreply.github.com> Date: Sun, 19 Feb 2023 01:33:02 +0100 Subject: vim-patch:9.0.1324: "gj" and "gk" do not move correctly over a closed fold (#22320) Problem: "gj" and "gk" do not move correctly over a closed fold. Solution: Use the same code as used for "j"/"k" to go to the next/previous line. (Luuk van Baal, closes vim/vim#12007) https://github.com/vim/vim/commit/441a7a94482f704b66253b8d08130f27b6b13736 --- src/nvim/normal.c | 18 ++---------------- src/nvim/testdir/test_fold.vim | 7 +++++++ 2 files changed, 9 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/nvim/normal.c b/src/nvim/normal.c index f1226584d7..5677c627a7 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -2479,19 +2479,10 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist) curwin->w_curswant -= width2; } else { // to previous line - - // Move to the start of a closed fold. Don't do that when - // 'foldopen' contains "all": it will open in a moment. - if (!(fdo_flags & FDO_ALL)) { - (void)hasFolding(curwin->w_cursor.lnum, - &curwin->w_cursor.lnum, NULL); - } - if (curwin->w_cursor.lnum == 1) { + if (!cursor_up_inner(curwin, 1)) { retval = false; break; } - curwin->w_cursor.lnum--; - linelen = linetabsize(get_cursor_line_ptr()); if (linelen > width1) { int w = (((linelen - width1 - 1) / width2) + 1) * width2; @@ -2511,15 +2502,10 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist) curwin->w_curswant += width2; } else { // to next line - - // Move to the end of a closed fold. - (void)hasFolding(curwin->w_cursor.lnum, NULL, - &curwin->w_cursor.lnum); - if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) { + if (!cursor_down_inner(curwin, 1)) { retval = false; break; } - curwin->w_cursor.lnum++; curwin->w_curswant %= width2; // Check if the cursor has moved below the number display // when width1 < width2 (with cpoptions+=n). Subtract width2 diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim index 9014948fb4..2f5c93ca2d 100644 --- a/src/nvim/testdir/test_fold.vim +++ b/src/nvim/testdir/test_fold.vim @@ -1548,4 +1548,11 @@ func Test_expand_fold_at_bottom_of_buffer() bwipe! endfunc +func Test_fold_screenrow_motion() + call setline(1, repeat(['aaaa'], 5)) + 1,4fold + norm Ggkzo + call assert_equal(1, line('.')) +endfunc + " vim: shiftwidth=2 sts=2 expandtab -- cgit From c726585ce1a5a8776e747fe20bead0acec88edf4 Mon Sep 17 00:00:00 2001 From: Ghjuvan Lacambre Date: Sun, 19 Feb 2023 13:25:29 +0100 Subject: fix: windows assertion failure due to incorrect path length (#22324) This commit fixes an assertion failure on windows debug builds that was introduced in https://github.com/neovim/neovim/pull/22128 . --- src/nvim/runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index 3487a8d7a2..a6ed95ec64 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -1607,7 +1607,7 @@ char *runtimepath_default(bool clean_arg) data_len = strlen(data_home); size_t nvim_data_size = appname_len; #if defined(MSWIN) - nvim_data_size += sizeof("-data"); + nvim_data_size += sizeof("-data") - 1; // -1: NULL byte should be ignored #endif if (data_len != 0) { rtp_size += ((data_len + memcnt(data_home, ',', data_len) -- cgit From 40287319002ff6ced3d280657c276fb7c9ef4df5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 19 Feb 2023 20:56:15 +0800 Subject: fix(tui): properly check if stdin is a tty (#22321) After #21831 `in_fd` is no longer set to stderr when starting TUI, so check for `stdin_isatty` instead. Fix #22259. --- src/nvim/tui/tui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 8df6e49b77..fee1d21672 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -1147,7 +1147,7 @@ void tui_mode_change(TUIData *tui, String mode, Integer mode_idx) // If stdin is not a TTY, the LHS of pipe may change the state of the TTY // after calling uv_tty_set_mode. So, set the mode of the TTY again here. // #13073 - if (tui->is_starting && tui->input.in_fd == STDERR_FILENO) { + if (tui->is_starting && !stdin_isatty) { int ret = uv_tty_set_mode(&tui->output_handle.tty, UV_TTY_MODE_NORMAL); if (ret) { ELOG("uv_tty_set_mode failed: %s", uv_strerror(ret)); -- cgit From 8784f064f15e5ae0b6bc85c2972ec16c64656e2b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 20 Feb 2023 08:24:49 +0800 Subject: vim-patch:9.0.1329: completion of map includes simplified ones (#22335) Problem: Completion of map includes simplified ones. Solution: Do not complete simplified mappings. (closes vim/vim#12013) https://github.com/vim/vim/commit/997b8a015cd39141866e953651d55c705275cbd6 --- src/nvim/mapping.c | 2 +- src/nvim/testdir/test_mapping.vim | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index ce4c0586e3..3840a00981 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -1342,7 +1342,7 @@ int ExpandMappings(char *pat, regmatch_T *regmatch, int *numMatches, char ***mat mp = maphash[hash]; } for (; mp; mp = mp->m_next) { - if (!(mp->m_mode & expand_mapmodes)) { + if (mp->m_simplified || !(mp->m_mode & expand_mapmodes)) { continue; } diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim index 6cf19306ec..e25c3c333e 100644 --- a/src/nvim/testdir/test_mapping.vim +++ b/src/nvim/testdir/test_mapping.vim @@ -759,11 +759,12 @@ func Test_mapcomplete() call feedkeys(":abbr! \\\"\", 'tx') call assert_equal("\"abbr! \x01", @:) - " Multiple matches for a map - nmap ,f /H - omap ,f /H + " When multiple matches have the same {lhs}, it should only appear once. + " The simplified form should also not be included. + nmap , /H + omap , /H call feedkeys(":map ,\\\"\", 'tx') - call assert_equal('"map ,f', @:) + call assert_equal('"map ,', @:) mapclear endfunc -- cgit From b62c0c8d9c22ae7fc9ee200733f8312efa6dbced Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 20 Feb 2023 08:12:59 +0100 Subject: docs: fix typos (#21961) Co-authored-by: Ben Morgan --- src/nvim/CMakeLists.txt | 2 +- src/nvim/api/ui.c | 2 +- src/nvim/edit.c | 2 +- src/nvim/garray.h | 2 +- src/nvim/main.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 7d75b8038e..329e831b2e 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -6,7 +6,7 @@ find_package(libuv CONFIG) if(TARGET libuv::uv_a) target_link_libraries(libuv_lib INTERFACE libuv::uv_a) else() - # Fallback to find module for older libuv versions, that don't provide the cmake package + # Fall back to find module for older libuv versions that don't provide config file find_package(LibUV 1.28.0 REQUIRED MODULE) target_include_directories(libuv_lib SYSTEM BEFORE INTERFACE ${LIBUV_INCLUDE_DIRS}) target_link_libraries(libuv_lib INTERFACE ${LIBUV_LIBRARIES}) diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 61f2c881b3..3c3c3008f4 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -254,7 +254,7 @@ void nvim_ui_detach(uint64_t channel_id, Error *err) remote_ui_disconnect(channel_id); } -// TODO(bfredl): use me to detach a specifc ui from the server +// TODO(bfredl): use me to detach a specific ui from the server void remote_ui_stop(UI *ui) {} diff --git a/src/nvim/edit.c b/src/nvim/edit.c index ff7899d0eb..8b74593360 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -2791,7 +2791,7 @@ static char_u *replace_stack = NULL; static ssize_t replace_stack_nr = 0; // next entry in replace stack static ssize_t replace_stack_len = 0; // max. number of entries -/// Push character that is replaced onto the the replace stack. +/// Push character that is replaced onto the replace stack. /// /// replace_offset is normally 0, in which case replace_push will add a new /// character at the end of the stack. If replace_offset is not 0, that many diff --git a/src/nvim/garray.h b/src/nvim/garray.h index 1623c4db7b..d3e04cd761 100644 --- a/src/nvim/garray.h +++ b/src/nvim/garray.h @@ -52,7 +52,7 @@ static inline void *ga_append_via_ptr(garray_T *gap, size_t item_size) /// /// @param gap the garray to be freed /// @param item_type type of the item in the garray -/// @param free_item_fn free function that takes (*item_type) as parameter +/// @param free_item_fn free function that takes (item_type *) as parameter #define GA_DEEP_CLEAR(gap, item_type, free_item_fn) \ do { \ garray_T *_gap = (gap); \ diff --git a/src/nvim/main.c b/src/nvim/main.c index f2aa14e04c..0ecb5f742d 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -182,7 +182,7 @@ void early_init(mparm_T *paramp) #ifdef MSWIN OSVERSIONINFO ovi; ovi.dwOSVersionInfoSize = sizeof(ovi); - // Disable warning about GetVersionExA being deprecated. There doesn't seem to be a conventient + // Disable warning about GetVersionExA being deprecated. There doesn't seem to be a convenient // replacement that doesn't add a ton of extra code as of writing this. # pragma warning(suppress : 4996) GetVersionEx(&ovi); -- cgit From f1816f9ee2a8b811fd6ce4e60a843087f855f97d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 20 Feb 2023 15:13:55 +0800 Subject: refactor(main.c): remove unreachable use_builtin_ui conditions (#22338) When use_builtin_ui is true, Nvim will exit before line 385 is reached. --- src/nvim/main.c | 7 ++++--- src/nvim/tui/input.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/main.c b/src/nvim/main.c index 0ecb5f742d..5f4e639b06 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -383,6 +383,7 @@ int main(int argc, char **argv) if (ui_client_channel_id) { ui_client_run(remote_ui); // NORETURN } + assert(!ui_client_channel_id && !use_builtin_ui); // Wait for UIs to set up Nvim or show early messages // and prompts (--cmd, swapfile dialog, …). @@ -583,13 +584,13 @@ int main(int argc, char **argv) set_vim_var_nr(VV_VIM_DID_ENTER, 1L); apply_autocmds(EVENT_VIMENTER, NULL, NULL, false, curbuf); TIME_MSG("VimEnter autocommands"); - if (use_remote_ui || use_builtin_ui) { - do_autocmd_uienter(use_remote_ui ? CHAN_STDIO : 0, true); + if (use_remote_ui) { + do_autocmd_uienter(CHAN_STDIO, true); TIME_MSG("UIEnter autocommands"); } #ifdef MSWIN - if (use_remote_ui || use_builtin_ui) { + if (use_remote_ui) { os_icon_init(); } os_title_save(); diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index c992253e1f..cb687d4f65 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -208,7 +208,7 @@ static void tinput_wait_enqueue(void **argv) input->paste = 2; } rbuffer_reset(input->key_buffer); - } else { // enqueue input for the main thread or Nvim server + } else { // enqueue input RBUFFER_UNTIL_EMPTY(input->key_buffer, buf, len) { const String keys = { .data = buf, .size = len }; MAXSIZE_TEMP_ARRAY(args, 1); -- cgit From 93c627b90b4955967943b7a47fe63b094a0c50e6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 20 Feb 2023 23:02:05 +0800 Subject: vim-patch:9.0.1331: illegal memory access when using :ball in Visual mode (#22343) Problem: Illegal memory access when using :ball in Visual mode. Solution: Stop Visual mode when using :ball. (Pavel Mayorov, closes vim/vim#11923) https://github.com/vim/vim/commit/e1121b139480f53d1b06f84f3e4574048108fa0b Co-authored-by: Pavel Mayorov --- src/nvim/buffer.c | 4 ++++ src/nvim/testdir/test_visual.vim | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) (limited to 'src') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 98832a98c9..7a4e5d3eeb 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3600,6 +3600,10 @@ void ex_buffer_all(exarg_T *eap) all = true; } + // Stop Visual mode, the cursor and "VIsual" may very well be invalid after + // switching to another buffer. + reset_VIsual_and_resel(); + setpcmark(); // Close superfluous windows (two windows for the same buffer). diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim index 1e9629c2c4..350c69fe4e 100644 --- a/src/nvim/testdir/test_visual.vim +++ b/src/nvim/testdir/test_visual.vim @@ -1536,4 +1536,25 @@ func Test_switch_buffer_ends_visual_mode() exe 'bwipe!' buf2 endfunc +" Check fix for the heap-based buffer overflow bug found in the function +" utfc_ptr2len and reported at +" https://huntr.dev/bounties/ae933869-a1ec-402a-bbea-d51764c6618e +func Test_heap_buffer_overflow() + enew + set updatecount=0 + + norm R0 + split other + norm R000 + exe "norm \l" + ball + call assert_equal(getpos("."), getpos("v")) + call assert_equal('n', mode()) + norm zW + + %bwipe! + set updatecount& +endfunc + + " vim: shiftwidth=2 sts=2 expandtab -- cgit From 3507474611a03d88137a1d97666515b551c39cb3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 20 Feb 2023 23:55:42 +0800 Subject: vim-patch:9.0.1332: crash when using buffer-local user command in cmdline window (#22346) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Crash when using buffer-local user command in cmdline window. (Karl Yngve Lervåg) Solution: Use the right buffer to find the user command. (closes vim/vim#12030, closes vim/vim#12029) https://github.com/vim/vim/commit/b444ee761a2956a996a75d923281c51fa1a759f3 --- src/nvim/testdir/test_usercommands.vim | 9 +++++++++ src/nvim/usercmd.c | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/testdir/test_usercommands.vim b/src/nvim/testdir/test_usercommands.vim index 6910361345..898f7a59f1 100644 --- a/src/nvim/testdir/test_usercommands.vim +++ b/src/nvim/testdir/test_usercommands.vim @@ -736,6 +736,15 @@ func Test_buflocal_ambiguous_usercmd() bw! endfunc +" Test for using buffer-local user command from cmdwin. +func Test_buflocal_usercmd_cmdwin() + new + command -buffer TestCmd edit Test + " This used to crash Vim + call assert_fails("norm q::TestCmd\", 'E11:') + bw! +endfunc + " Test for using a multibyte character in a user command func Test_multibyte_in_usercmd() command SubJapanesePeriodToDot exe "%s/\u3002/./g" diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c index 3a5a4c3e91..6869f7eaf9 100644 --- a/src/nvim/usercmd.c +++ b/src/nvim/usercmd.c @@ -1625,7 +1625,7 @@ int do_ucmd(exarg_T *eap, bool preview) if (eap->cmdidx == CMD_USER) { cmd = USER_CMD(eap->useridx); } else { - cmd = USER_CMD_GA(&curbuf->b_ucmds, eap->useridx); + cmd = USER_CMD_GA(&prevwin_curwin()->w_buffer->b_ucmds, eap->useridx); } if (preview) { -- cgit From 286777c3335d9a4d2c30bfda23ba507fead02aee Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 21 Feb 2023 08:01:16 +0800 Subject: refactor(tui/input.c): remove unused multithreading code (#22342) --- src/nvim/tui/input.c | 26 +++++++------------------- src/nvim/tui/input.h | 3 --- 2 files changed, 7 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index cb687d4f65..730dc9c27b 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -133,8 +133,6 @@ void tinput_init(TermInput *input, Loop *loop) input->ttimeout = (bool)p_ttimeout; input->ttimeoutlen = p_ttm; input->key_buffer = rbuffer_new(KEY_BUFFER_SIZE); - uv_mutex_init(&input->key_buffer_mutex); - uv_cond_init(&input->key_buffer_cond); for (size_t i = 0; i < ARRAY_SIZE(kitty_key_map_entry); i++) { map_put(KittyKey, cstr_t)(&kitty_key_map, kitty_key_map_entry[i].key, @@ -166,8 +164,6 @@ void tinput_destroy(TermInput *input) { map_destroy(KittyKey, cstr_t)(&kitty_key_map); rbuffer_free(input->key_buffer); - uv_mutex_destroy(&input->key_buffer_mutex); - uv_cond_destroy(&input->key_buffer_cond); time_watcher_close(&input->timer_handle, NULL); stream_close(&input->read_stream, NULL, NULL); termkey_destroy(input->tk); @@ -190,9 +186,9 @@ static void tinput_done_event(void **argv) os_exit(1); } -static void tinput_wait_enqueue(void **argv) +/// Send all pending input to Nvim server. +static void tinput_flush(TermInput *input) { - TermInput *input = argv[0]; if (input->paste) { // produce exactly one paste event const size_t len = rbuffer_size(input->key_buffer); String keys = { .data = xmallocz(len), .size = len }; @@ -222,21 +218,13 @@ static void tinput_wait_enqueue(void **argv) } } -static void tinput_flush(TermInput *input, bool wait_until_empty) -{ - size_t drain_boundary = wait_until_empty ? 0 : 0xff; - do { - tinput_wait_enqueue((void **)&input); - } while (rbuffer_size(input->key_buffer) > drain_boundary); -} - static void tinput_enqueue(TermInput *input, char *buf, size_t size) { if (rbuffer_size(input->key_buffer) > rbuffer_capacity(input->key_buffer) - 0xff) { // don't ever let the buffer get too full or we risk putting incomplete keys // into it - tinput_flush(input, false); + tinput_flush(input); } rbuffer_write(input->key_buffer, buf, size); } @@ -487,7 +475,7 @@ static void tinput_timer_cb(TimeWatcher *watcher, void *data) handle_raw_buffer(input, true); } tk_getkeys(input, true); - tinput_flush(input, true); + tinput_flush(input); } /// Handle focus events. @@ -535,13 +523,13 @@ static HandleState handle_bracketed_paste(TermInput *input) if (enable) { // Flush before starting paste. - tinput_flush(input, true); + tinput_flush(input); // Paste phase: "first-chunk". input->paste = 1; } else if (input->paste) { // Paste phase: "last-chunk". input->paste = input->paste == 2 ? 3 : -1; - tinput_flush(input, true); + tinput_flush(input); // Paste phase: "disabled". input->paste = 0; } @@ -735,7 +723,7 @@ static void tinput_read_cb(Stream *stream, RBuffer *buf, size_t count_, void *da } handle_raw_buffer(input, false); - tinput_flush(input, true); + tinput_flush(input); // An incomplete sequence was found. Leave it in the raw buffer and wait for // the next input. diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h index d33cea6383..da565fbb6f 100644 --- a/src/nvim/tui/input.h +++ b/src/nvim/tui/input.h @@ -23,7 +23,6 @@ typedef struct term_input { int in_fd; // Phases: -1=all 0=disabled 1=first-chunk 2=continue 3=last-chunk int8_t paste; - bool waiting; bool ttimeout; int8_t waiting_for_bg_response; int8_t waiting_for_csiu_response; @@ -35,8 +34,6 @@ typedef struct term_input { Loop *loop; Stream read_stream; RBuffer *key_buffer; - uv_mutex_t key_buffer_mutex; - uv_cond_t key_buffer_cond; TUIData *tui_data; } TermInput; -- cgit From fec1181ecde75de1754f1d27a7ba7cbf2b9f43d6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 21 Feb 2023 17:43:53 +0800 Subject: test(legacy/prompt_buffer_spec): align script with oldtest more (#22354) --- src/nvim/testdir/test_prompt_buffer.vim | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_prompt_buffer.vim b/src/nvim/testdir/test_prompt_buffer.vim index b8f6c5240c..b1288b4892 100644 --- a/src/nvim/testdir/test_prompt_buffer.vim +++ b/src/nvim/testdir/test_prompt_buffer.vim @@ -10,8 +10,7 @@ source screendump.vim func CanTestPromptBuffer() " We need to use a terminal window to be able to feed keys without leaving " Insert mode. - " Nvim's terminal implementation differs from Vim's - " CheckFeature terminal + CheckFeature terminal " TODO: make the tests work on MS-Windows CheckNotMSWindows @@ -56,7 +55,6 @@ func WriteScript(name) endfunc func Test_prompt_basic() - throw 'skipped: TODO' call CanTestPromptBuffer() let scriptName = 'XpromptscriptBasic' call WriteScript(scriptName) @@ -77,7 +75,6 @@ func Test_prompt_basic() endfunc func Test_prompt_editing() - throw 'skipped: TODO' call CanTestPromptBuffer() let scriptName = 'XpromptscriptEditing' call WriteScript(scriptName) @@ -108,7 +105,6 @@ func Test_prompt_editing() endfunc func Test_prompt_switch_windows() - throw 'skipped: TODO' call CanTestPromptBuffer() let scriptName = 'XpromptSwitchWindows' call WriteScript(scriptName) @@ -226,7 +222,6 @@ func Test_prompt_buffer_getbufinfo() endfunc func Test_prompt_while_writing_to_hidden_buffer() - throw 'skipped: TODO' call CanTestPromptBuffer() CheckUnix -- cgit From 344a1ee8e6b7d78120f8393d1babfd285e866334 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 22 Feb 2023 00:07:26 +0800 Subject: docs: fix typos (#22353) --- src/nvim/api/extmark.c | 2 +- src/nvim/api/ui.c | 2 +- src/nvim/tui/input.c | 2 +- src/nvim/ui_client.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 91486abf38..845a4c7dbe 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -445,7 +445,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e /// buffer. /// - right_gravity : boolean that indicates the direction /// the extmark will be shifted in when new text is inserted -/// (true for right, false for left). defaults to true. +/// (true for right, false for left). Defaults to true. /// - end_right_gravity : boolean that indicates the direction /// the extmark end position (if it exists) will be shifted /// in when new text is inserted (true for right, false diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 3c3c3008f4..f6dee066dc 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -382,7 +382,7 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e }); bool boolval = value.data.boolean; if (!init && i == kUILinegrid && boolval != ui->ui_ext[i]) { - // There shouldn't be a reason for an UI to do this ever + // There shouldn't be a reason for a UI to do this ever // so explicitly don't support this. api_set_error(err, kErrorTypeValidation, "ext_linegrid option cannot be changed"); } diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 730dc9c27b..73ed7b6096 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -186,7 +186,7 @@ static void tinput_done_event(void **argv) os_exit(1); } -/// Send all pending input to Nvim server. +/// Send all pending input in key buffer to Nvim server. static void tinput_flush(TermInput *input) { if (input->paste) { // produce exactly one paste event diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 0bd9490368..8262293ec5 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -153,7 +153,7 @@ UIClientHandler ui_client_get_redraw_handler(const char *name, size_t name_len, /// Placeholder for _sync_ requests with 'redraw' method name /// -/// async 'redraw' events, which are expected when nvim acts as an ui client. +/// async 'redraw' events, which are expected when nvim acts as a ui client. /// get handled in msgpack_rpc/unpacker.c and directly dispatched to handlers /// of specific ui events, like ui_client_event_grid_resize and so on. Object handle_ui_client_redraw(uint64_t channel_id, Array args, Arena *arena, Error *error) -- cgit From d1b34b74580fc09d86144c35e24a1a8a0d531b36 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Wed, 22 Feb 2023 10:58:15 +0100 Subject: vim-patch:9.0.1337: yuck files are not recognized (#22358) Problem: Yuck files are not recognized. Solution: Add a filetype pattern for yuck files. (Amaan Qureshi, closes vim/vim#12033) https://github.com/vim/vim/commit/cfce5cf542db20c7beba5b4211c0ae3305a64a43 Co-authored-by: Amaan Qureshi --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 576f2c9f2b..af33b5b051 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -665,6 +665,7 @@ let s:filename_checks = { \ 'yacc': ['file.yy', 'file.yxx', 'file.y++'], \ 'yaml': ['file.yaml', 'file.yml', '.clangd', '.clang-format', '.clang-tidy'], \ 'yang': ['file.yang'], + \ 'yuck': ['file.yuck'], \ 'z8a': ['file.z8a'], \ 'zig': ['file.zig'], \ 'zimbu': ['file.zu'], -- cgit From 6752f1005d26c93a033d856a60b7b296f3e51634 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 14 Dec 2022 19:58:18 +0100 Subject: docs: naming conventions, guidelines close #21063 --- src/nvim/README.md | 7 +++++++ src/nvim/api/command.c | 29 ++++++++++++++--------------- src/nvim/api/vim.c | 17 ++++++++--------- 3 files changed, 29 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/nvim/README.md b/src/nvim/README.md index 712fda87ba..0951142555 100644 --- a/src/nvim/README.md +++ b/src/nvim/README.md @@ -81,6 +81,13 @@ Logs will be written to `${HOME}/logs/*san.PID` then. For more information: https://github.com/google/sanitizers/wiki/SanitizerCommonFlags +Reproducible build +------------------ + +To make a reproducible build of Nvim, set cmake variable `LUA_GEN_PRG` to +a LuaJIT binary built with `LUAJIT_SECURITY_PRN=0`. See commit +cb757f2663e6950e655c6306d713338dfa66b18d. + Debug: Performance ------------------ diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 6d63ae5e24..32378ed244 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -899,15 +899,13 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin } } -/// Create a new user command |user-commands| +/// Creates a global |user-commands| command. /// -/// {name} is the name of the new command. The name must begin with an uppercase letter. -/// -/// {command} is the replacement text or Lua function to execute. +/// For Lua usage see |lua-guide-commands-create|. /// /// Example: ///
vim
-///    :call nvim_create_user_command('SayHello', 'echo "Hello world!"', {})
+///    :call nvim_create_user_command('SayHello', 'echo "Hello world!"', {'bang': v:true})
 ///    :SayHello
 ///    Hello world!
 /// 
@@ -929,15 +927,16 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin /// - mods: (string) Command modifiers, if any || /// - smods: (table) Command modifiers in a structured format. Has the same /// structure as the "mods" key of |nvim_parse_cmd()|. -/// @param opts Optional command attributes. See |command-attributes| for more details. To use -/// boolean attributes (such as |:command-bang| or |:command-bar|) set the value to -/// "true". In addition to the string options listed in |:command-complete|, the -/// "complete" key also accepts a Lua function which works like the "customlist" -/// completion mode |:command-completion-customlist|. Additional parameters: -/// - desc: (string) Used for listing the command when a Lua function is used for -/// {command}. -/// - force: (boolean, default true) Override any previous definition. -/// - preview: (function) Preview callback for 'inccommand' |:command-preview| +/// @param opts Optional |command-attributes|. +/// - Set boolean attributes such as |:command-bang| or |:command-bar| to true (but +/// not |:command-buffer|, use |nvim_buf_create_user_command()| instead). +/// - "complete" |:command-complete| also accepts a Lua function which works like +/// |:command-completion-customlist|. +/// - Other parameters: +/// - desc: (string) Used for listing the command when a Lua function is used for +/// {command}. +/// - force: (boolean, default true) Override any previous definition. +/// - preview: (function) Preview callback for 'inccommand' |:command-preview| /// @param[out] err Error details, if any. void nvim_create_user_command(String name, Object command, Dict(user_command) *opts, Error *err) FUNC_API_SINCE(9) @@ -955,7 +954,7 @@ void nvim_del_user_command(String name, Error *err) nvim_buf_del_user_command(-1, name, err); } -/// Create a new user command |user-commands| in the given buffer. +/// Creates a buffer-local command |user-commands|. /// /// @param buffer Buffer handle, or 0 for current buffer. /// @param[out] err Error details, if any. diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 3a93005841..0f27040fd3 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1442,15 +1442,14 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode) /// or "!" for |:map!|, or empty string for |:map|. /// @param lhs Left-hand-side |{lhs}| of the mapping. /// @param rhs Right-hand-side |{rhs}| of the mapping. -/// @param opts Optional parameters map: keys are |:map-arguments|, values are booleans (default -/// false). Accepts all |:map-arguments| as keys excluding || but including -/// |:noremap| and "desc". Unknown key is an error. -/// "desc" can be used to give a description to the mapping. -/// When called from Lua, also accepts a "callback" key that takes a Lua function to -/// call when the mapping is executed. -/// When "expr" is true, "replace_keycodes" (boolean) can be used to replace keycodes -/// in the resulting string (see |nvim_replace_termcodes()|), and a Lua callback -/// returning `nil` is equivalent to returning an empty string. +/// @param opts Optional parameters map: Accepts all |:map-arguments| as keys except ||, +/// values are booleans (default false). Also: +/// - "noremap" non-recursive mapping |:noremap| +/// - "desc" human-readable description. +/// - "callback" Lua function called when the mapping is executed. +/// - "replace_keycodes" (boolean) When "expr" is true, replace keycodes in the +/// resulting string (see |nvim_replace_termcodes()|). Returning nil from the Lua +/// "callback" is equivalent to returning an empty string. /// @param[out] err Error details, if any. void nvim_set_keymap(uint64_t channel_id, String mode, String lhs, String rhs, Dict(keymap) *opts, Error *err) -- cgit From 799edca18a4ddcf8edcb63dd391219e01e187f0d Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 28 Nov 2022 22:43:10 +0100 Subject: feat(lua): make sure require'bit' always works, even with PUC lua 5.1 --- src/bit.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++ src/bit.h | 3 + src/nvim/CMakeLists.txt | 12 ++- src/nvim/lua/stdlib.c | 11 +++ 4 files changed, 214 insertions(+), 3 deletions(-) create mode 100644 src/bit.c create mode 100644 src/bit.h (limited to 'src') diff --git a/src/bit.c b/src/bit.c new file mode 100644 index 0000000000..85d2414582 --- /dev/null +++ b/src/bit.c @@ -0,0 +1,191 @@ +/* +** Lua BitOp -- a bit operations library for Lua 5.1/5.2. +** http://bitop.luajit.org/ +** +** Copyright (C) 2008-2012 Mike Pall. All rights reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining +** a copy of this software and associated documentation files (the +** "Software"), to deal in the Software without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Software, and to +** permit persons to whom the Software is furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] +*/ + +#define LUA_BITOP_VERSION "1.0.2" + +#define LUA_LIB +#include "lua.h" +#include "lauxlib.h" + +#include "bit.h" + +#ifdef _MSC_VER +/* MSVC is stuck in the last century and doesn't have C99's stdint.h. */ +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#else +#include +#endif + +typedef int32_t SBits; +typedef uint32_t UBits; + +typedef union { + lua_Number n; +#ifdef LUA_NUMBER_DOUBLE + uint64_t b; +#else + UBits b; +#endif +} BitNum; + +/* Convert argument to bit type. */ +static UBits barg(lua_State *L, int idx) +{ + BitNum bn; + UBits b; +#if LUA_VERSION_NUM < 502 + bn.n = lua_tonumber(L, idx); +#else + bn.n = luaL_checknumber(L, idx); +#endif +#if defined(LUA_NUMBER_DOUBLE) + bn.n += 6755399441055744.0; /* 2^52+2^51 */ +#ifdef SWAPPED_DOUBLE + b = (UBits)(bn.b >> 32); +#else + b = (UBits)bn.b; +#endif +#elif defined(LUA_NUMBER_INT) || defined(LUA_NUMBER_LONG) || \ + defined(LUA_NUMBER_LONGLONG) || defined(LUA_NUMBER_LONG_LONG) || \ + defined(LUA_NUMBER_LLONG) + if (sizeof(UBits) == sizeof(lua_Number)) + b = bn.b; + else + b = (UBits)(SBits)bn.n; +#elif defined(LUA_NUMBER_FLOAT) +#error "A 'float' lua_Number type is incompatible with this library" +#else +#error "Unknown number type, check LUA_NUMBER_* in luaconf.h" +#endif +#if LUA_VERSION_NUM < 502 + if (b == 0 && !lua_isnumber(L, idx)) { + luaL_typerror(L, idx, "number"); + } +#endif + return b; +} + +/* Return bit type. */ +#define BRET(b) lua_pushnumber(L, (lua_Number)(SBits)(b)); return 1; + +static int bit_tobit(lua_State *L) { BRET(barg(L, 1)) } +static int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) } + +#define BIT_OP(func, opr) \ + static int func(lua_State *L) { int i; UBits b = barg(L, 1); \ + for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) } +BIT_OP(bit_band, &=) +BIT_OP(bit_bor, |=) +BIT_OP(bit_bxor, ^=) + +#define bshl(b, n) (b << n) +#define bshr(b, n) (b >> n) +#define bsar(b, n) ((SBits)b >> n) +#define brol(b, n) ((b << n) | (b >> (32-n))) +#define bror(b, n) ((b << (32-n)) | (b >> n)) +#define BIT_SH(func, fn) \ + static int func(lua_State *L) { \ + UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) } +BIT_SH(bit_lshift, bshl) +BIT_SH(bit_rshift, bshr) +BIT_SH(bit_arshift, bsar) +BIT_SH(bit_rol, brol) +BIT_SH(bit_ror, bror) + +static int bit_bswap(lua_State *L) +{ + UBits b = barg(L, 1); + b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24); + BRET(b) +} + +static int bit_tohex(lua_State *L) +{ + UBits b = barg(L, 1); + SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2); + const char *hexdigits = "0123456789abcdef"; + char buf[8]; + int i; + if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } + if (n > 8) n = 8; + for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } + lua_pushlstring(L, buf, (size_t)n); + return 1; +} + +static const struct luaL_Reg bit_funcs[] = { + { "tobit", bit_tobit }, + { "bnot", bit_bnot }, + { "band", bit_band }, + { "bor", bit_bor }, + { "bxor", bit_bxor }, + { "lshift", bit_lshift }, + { "rshift", bit_rshift }, + { "arshift", bit_arshift }, + { "rol", bit_rol }, + { "ror", bit_ror }, + { "bswap", bit_bswap }, + { "tohex", bit_tohex }, + { NULL, NULL } +}; + +/* Signed right-shifts are implementation-defined per C89/C99. +** But the de facto standard are arithmetic right-shifts on two's +** complement CPUs. This behaviour is required here, so test for it. +*/ +#define BAD_SAR (bsar(-8, 2) != (SBits)-2) + +LUALIB_API int luaopen_bit(lua_State *L) +{ + UBits b; + lua_pushnumber(L, (lua_Number)1437217655L); + b = barg(L, -1); + if (b != (UBits)1437217655L || BAD_SAR) { /* Perform a simple self-test. */ + const char *msg = "compiled with incompatible luaconf.h"; +#ifdef LUA_NUMBER_DOUBLE +#ifdef _WIN32 + if (b == (UBits)1610612736L) + msg = "use D3DCREATE_FPU_PRESERVE with DirectX"; +#endif + if (b == (UBits)1127743488L) + msg = "not compiled with SWAPPED_DOUBLE"; +#endif + if (BAD_SAR) + msg = "arithmetic right-shift broken"; + luaL_error(L, "bit library self-test failed (%s)", msg); + } +#if LUA_VERSION_NUM < 502 + luaL_register(L, "bit", bit_funcs); +#else + luaL_newlib(L, bit_funcs); +#endif + return 1; +} + diff --git a/src/bit.h b/src/bit.h new file mode 100644 index 0000000000..7e54e6d519 --- /dev/null +++ b/src/bit.h @@ -0,0 +1,3 @@ +#include + +int luaopen_bit(lua_State *L); diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 329e831b2e..8884273649 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -367,6 +367,12 @@ glob_wrapper(NVIM_HEADERS *.h) glob_wrapper(EXTERNAL_SOURCES ../xdiff/*.c ../mpack/*.c ../cjson/*.c ../klib/*.c) glob_wrapper(EXTERNAL_HEADERS ../xdiff/*.h ../mpack/*.h ../cjson/*.h ../klib/*.h) +if(PREFER_LUA) + # luajit not used, use a vendored copy of the bit module + list(APPEND EXTERNAL_SOURCES ${PROJECT_SOURCE_DIR}/src/bit.c) + target_compile_definitions(main_lib INTERFACE NVIM_VENDOR_BIT) +endif() + foreach(subdir os api @@ -425,7 +431,7 @@ if(MSVC) ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -wd4090 -wd4244 -wd4267") else() set_source_files_properties( - ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion -Wno-strict-prototypes") + ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion -Wno-strict-prototypes -Wno-misleading-indentation") endif() # Log level (MIN_LOG_LEVEL in log.h) @@ -684,8 +690,8 @@ if(UNIX) endif() endif() -if(NOT LUAJIT_FOUND) - message(STATUS "luajit not found, skipping unit tests") +if(PREFER_LUA) + message(STATUS "luajit not used, skipping unit tests") else() glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c) target_sources(nvim PRIVATE $<$:${UNIT_TEST_FIXTURES}>) diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c index 5aeff4de98..d9682ff63d 100644 --- a/src/nvim/lua/stdlib.c +++ b/src/nvim/lua/stdlib.c @@ -11,6 +11,10 @@ #include #include +#ifdef NVIM_VENDOR_BIT +# include "bit.h" +#endif + #include "auto/config.h" #include "cjson/lua_cjson.h" #include "mpack/lmpack.h" @@ -596,6 +600,13 @@ void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread) // vim.json lua_cjson_new(lstate); lua_setfield(lstate, -2, "json"); + +#ifdef NVIM_VENDOR_BIT + // if building with puc lua, use internal fallback for require'bit' + int top = lua_gettop(lstate); + luaopen_bit(lstate); + lua_settop(lstate, top); +#endif } /// like luaL_error, but allow cleanup -- cgit From 524e1a06432ed7a88c1e183d81812dd48dc18cfb Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 23 Feb 2023 16:15:04 +0800 Subject: fix(highlight): avoid ORing underline flags (#22372) When combining attributes use the one that takes priority. For :highlight command use the last one specified. For API use a hard-coded order same as the order in docs. --- src/nvim/highlight.c | 21 +++++++++++++++++---- src/nvim/highlight_group.c | 3 +++ 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 72da66cfc2..305e84276c 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -507,6 +507,16 @@ void hl_invalidate_blends(void) update_window_hl(curwin, true); } +/// Combine HlAttrFlags. +/// The underline attribute in "prim_ae" overrules the one in "char_ae" if both are present. +static int16_t hl_combine_ae(int16_t char_ae, int16_t prim_ae) +{ + int16_t char_ul = char_ae & HL_UNDERLINE_MASK; + int16_t prim_ul = prim_ae & HL_UNDERLINE_MASK; + int16_t new_ul = prim_ul ? prim_ul : char_ul; + return (char_ae & ~HL_UNDERLINE_MASK) | (prim_ae & ~HL_UNDERLINE_MASK) | new_ul; +} + // Combine special attributes (e.g., for spelling) with other attributes // (e.g., for syntax highlighting). // "prim_attr" overrules "char_attr". @@ -537,12 +547,12 @@ int hl_combine_attr(int char_attr, int prim_attr) if (prim_aep.cterm_ae_attr & HL_NOCOMBINE) { new_en.cterm_ae_attr = prim_aep.cterm_ae_attr; } else { - new_en.cterm_ae_attr |= prim_aep.cterm_ae_attr; + new_en.cterm_ae_attr = hl_combine_ae(new_en.cterm_ae_attr, prim_aep.cterm_ae_attr); } if (prim_aep.rgb_ae_attr & HL_NOCOMBINE) { new_en.rgb_ae_attr = prim_aep.rgb_ae_attr; } else { - new_en.rgb_ae_attr |= prim_aep.rgb_ae_attr; + new_en.rgb_ae_attr = hl_combine_ae(new_en.rgb_ae_attr, prim_aep.rgb_ae_attr); } if (prim_aep.cterm_fg_color > 0) { @@ -664,7 +674,7 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through) } else { cattrs = fattrs; if (ratio >= 50) { - cattrs.rgb_ae_attr |= battrs.rgb_ae_attr; + cattrs.rgb_ae_attr = hl_combine_ae(battrs.rgb_ae_attr, cattrs.rgb_ae_attr); } cattrs.rgb_fg_color = rgb_blend(ratio/2, battrs.rgb_fg_color, fattrs.rgb_fg_color); @@ -924,7 +934,10 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e #define CHECK_FLAG(d, m, name, extra, flag) \ if (api_object_to_bool(d->name##extra, #name, false, err)) { \ - m = m | flag; \ + if (flag & HL_UNDERLINE_MASK) { \ + m &= ~HL_UNDERLINE_MASK; \ + } \ + m |= flag; \ } CHECK_FLAG(dict, mask, reverse, , HL_INVERSE); diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index e34c13abc1..d2f5b60dc6 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -1124,6 +1124,9 @@ void do_highlight(const char *line, const bool forceit, const bool init) for (i = ARRAY_SIZE(hl_attr_table); --i >= 0;) { int len = (int)strlen(hl_name_table[i]); if (STRNICMP(arg + off, hl_name_table[i], len) == 0) { + if (hl_attr_table[i] & HL_UNDERLINE_MASK) { + attr &= ~HL_UNDERLINE_MASK; + } attr |= hl_attr_table[i]; off += len; break; -- cgit From 86807157438240757199f925f538d7ad02322754 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 23 Feb 2023 15:08:39 +0000 Subject: fix: resolve error from -Werror=maybe-uninitialized --- src/nvim/channel.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/channel.c b/src/nvim/channel.c index 7f8e1c9fd1..5f1ad6cb67 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -372,7 +372,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, CallbackReader proc->overlapped = overlapped; char *cmd = xstrdup(proc->argv[0]); - bool has_in, has_out, has_err; + bool has_out, has_err; if (proc->type == kProcessTypePty) { has_out = true; has_err = false; @@ -382,14 +382,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, CallbackReader proc->fwd_err = chan->on_stderr.fwd_err; } - switch (stdin_mode) { - case kChannelStdinPipe: - has_in = true; - break; - case kChannelStdinNull: - has_in = false; - break; - } + bool has_in = stdin_mode == kChannelStdinPipe; int status = process_spawn(proc, has_in, has_out, has_err); if (status) { -- cgit From 8c339aa04b2a1ca99a297b2eada8ebc6218f5f1c Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Thu, 23 Feb 2023 17:52:33 +0100 Subject: vim-patch:9.0.1346: Starlark files are not recognized (#22380) Problem: Starlark files are not recognized. Solution: Add patterns for Starlark files. (Amaan Qureshi, closes vim/vim#12049) https://github.com/vim/vim/commit/ca06b30073de22dc120b532e90fbee2a10ef9772 Co-authored-by: Amaan Qureshi --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index af33b5b051..a69ac5462e 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -560,6 +560,7 @@ let s:filename_checks = { \ 'sshconfig': ['ssh_config', '/.ssh/config', '/etc/ssh/ssh_config.d/file.conf', 'any/etc/ssh/ssh_config.d/file.conf', 'any/.ssh/config', 'any/.ssh/file.conf'], \ 'sshdconfig': ['sshd_config', '/etc/ssh/sshd_config.d/file.conf', 'any/etc/ssh/sshd_config.d/file.conf'], \ 'st': ['file.st'], + \ 'starlark': ['file.ipd', 'file.star', 'file.starlark'], \ 'stata': ['file.ado', 'file.do', 'file.imata', 'file.mata'], \ 'stp': ['file.stp'], \ 'sudoers': ['any/etc/sudoers', 'sudoers.tmp', '/etc/sudoers', 'any/etc/sudoers.d/file'], -- cgit From 5e1308b7caa89b458cc97d2db956379aa54ed68a Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Thu, 23 Feb 2023 16:12:01 -0500 Subject: vim-patch:9.0.1348: Un-grammar files are not recognized (#22383) Problem: Un-grammar files are not recognized. Solution: Add patterns for Un-grammar files. (Amaan Qureshi, closes vim/vim#12034) https://github.com/vim/vim/commit/44e08c1cf83f5a50f8b21613551304a6651c1161 --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index a69ac5462e..d37a194f50 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -609,6 +609,7 @@ let s:filename_checks = { \ 'typescript': ['file.mts', 'file.cts'], \ 'typescript.glimmer': ['file.gts'], \ 'typescriptreact': ['file.tsx'], + \ 'ungrammar': ['file.ungram'], \ 'uc': ['file.uc'], \ 'udevconf': ['/etc/udev/udev.conf', 'any/etc/udev/udev.conf'], \ 'udevperm': ['/etc/udev/permissions.d/file.permissions', 'any/etc/udev/permissions.d/file.permissions'], -- cgit From 47bc297d81cf7dab5a28608657ddab3c09f794d0 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Feb 2023 12:35:06 +0800 Subject: vim-patch:8.2.4318: various comment and indent mistakes, returning wrong zero (#22385) Problem: Various comment and indent mistakes, returning wrong zero. Solution: Fix the mistakes. Return NULL instead of FAIL. https://github.com/vim/vim/commit/54969f4ef5825205ecde09ea80f4087fc3b68e5d N/A patches for version.c: vim-patch:8.2.3781: the option window script is outdated Problem: The option window script is outdated. Solution: Add several changes. https://github.com/vim/vim/commit/a416861c643b03fe5dec9f3bf8c1c9e054b5a9c7 Co-authored-by: Bram Moolenaar --- src/nvim/eval.c | 2 +- src/nvim/window.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index ccea4f4951..841588d4c3 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -2572,7 +2572,7 @@ static int eval4(char **arg, typval_T *rettv, int evaluate) } /// Handle fourth level expression: -/// + number addition +/// + number addition, concatenation of list or blob /// - number subtraction /// . string concatenation /// .. string concatenation diff --git a/src/nvim/window.c b/src/nvim/window.c index 36d422abd5..0a4d36acb2 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1000,7 +1000,7 @@ void ui_ext_win_viewport(win_T *wp) } } -/// If "split_disallowed" is set given an error and return FAIL. +/// If "split_disallowed" is set give an error and return FAIL. /// Otherwise return OK. static int check_split_disallowed(void) { -- cgit From 904d0995837a2569ae640f5253da3dd4569fec6f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Feb 2023 15:03:28 +0800 Subject: vim-patch:8.2.2449: Vim9: flatten() always changes the list type Problem: Vim9: flatten() always changes the list type. Solution: Disallow using flatten() and add flattennew(). https://github.com/vim/vim/commit/3b690069730805a147d45d92eaca4dc838272d1d Co-authored-by: Bram Moolenaar --- src/nvim/eval.lua | 1 + src/nvim/eval/funcs.c | 41 +++++++++++++++++++++++++++++++-------- src/nvim/eval/typval.c | 9 ++++----- src/nvim/testdir/test_flatten.vim | 11 +++++++++++ 4 files changed, 49 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 9a5ab51c71..a1caeea95a 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -128,6 +128,7 @@ return { finddir={args={1, 3}, base=1}, findfile={args={1, 3}, base=1}, flatten={args={1, 2}, base=1}, + flattennew={args={1, 2}, base=1}, float2nr={args=1, base=1}, floor={args=1, base=1, float_func="floor"}, fmod={args=2, base=1}, diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 6f983d3208..3a58b90f96 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1870,8 +1870,8 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_string = cmdstr; } -/// "flatten(list[, {maxdepth}])" function -static void f_flatten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +/// "flatten()" and "flattennew()" functions +static void flatten_common(typval_T *argvars, typval_T *rettv, bool make_copy) { bool error = false; @@ -1895,13 +1895,38 @@ static void f_flatten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } list_T *list = argvars[0].vval.v_list; - if (list != NULL - && !value_check_lock(tv_list_locked(list), - N_("flatten() argument"), - TV_TRANSLATE) - && tv_list_flatten(list, maxdepth) == OK) { - tv_copy(&argvars[0], rettv); + rettv->v_type = VAR_LIST; + rettv->vval.v_list = list; + if (list == NULL) { + return; } + + if (make_copy) { + list = tv_list_copy(NULL, list, true, get_copyID()); + rettv->vval.v_list = list; + if (list == NULL) { + return; + } + } else { + if (value_check_lock(tv_list_locked(list), N_("flatten() argument"), TV_TRANSLATE)) { + return; + } + tv_list_ref(list); + } + + tv_list_flatten(list, maxdepth); +} + +/// "flatten(list[, {maxdepth}])" function +static void f_flatten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + flatten_common(argvars, rettv, false); +} + +/// "flattennew(list[, {maxdepth}])" function +static void f_flattennew(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + flatten_common(argvars, rettv, true); } /// "extend(list, list [, idx])" function diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 9a3a1c3c0f..ab4245b59a 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -654,14 +654,14 @@ tv_list_copy_error: /// @param[in] maxdepth Maximum depth that will be flattened /// /// @return OK or FAIL -int tv_list_flatten(list_T *list, long maxdepth) - FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT +void tv_list_flatten(list_T *list, long maxdepth) + FUNC_ATTR_NONNULL_ARG(1) { listitem_T *item; listitem_T *to_free; int n; if (maxdepth == 0) { - return OK; + return; } n = 0; @@ -669,7 +669,7 @@ int tv_list_flatten(list_T *list, long maxdepth) while (item != NULL) { fast_breakcheck(); if (got_int) { - return FAIL; + return; } if (item->li_tv.v_type == VAR_LIST) { listitem_T *next = item->li_next; @@ -695,7 +695,6 @@ int tv_list_flatten(list_T *list, long maxdepth) item = item->li_next; } } - return OK; } /// Extend first list with the second diff --git a/src/nvim/testdir/test_flatten.vim b/src/nvim/testdir/test_flatten.vim index 99086611e1..d8abc1ad68 100644 --- a/src/nvim/testdir/test_flatten.vim +++ b/src/nvim/testdir/test_flatten.vim @@ -79,3 +79,14 @@ func Test_flatten() call assert_equal([1, 2, 1, 2], flatten(l:x, 2)) call assert_equal([2, l:x], l:y) endfunc + +func Test_flattennew() + let l = [1, [2, [3, 4]], 5] + call assert_equal([1, 2, 3, 4, 5], flattennew(l)) + call assert_equal([1, [2, [3, 4]], 5], l) + + call assert_equal([1, 2, [3, 4], 5], flattennew(l, 1)) + call assert_equal([1, [2, [3, 4]], 5], l) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab -- cgit From d9263688bf0282918f5a9801dae8b85e4c85bd7e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Feb 2023 15:24:38 +0800 Subject: vim-patch:8.2.4627: flatten() does not use maxdepth correctly Problem: flatten() does not use maxdepth correctly. Solution: Use a recursive implementation. (closes vim/vim#10020) https://github.com/vim/vim/commit/acf7d73a7f5cdd63b34de777a4ce5eb3e2ba0ab3 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/typval.c | 42 ++++++++++++++++++++------------------- src/nvim/testdir/test_flatten.vim | 16 +++++++++++++++ 3 files changed, 39 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 3a58b90f96..6ac94706c7 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1914,7 +1914,7 @@ static void flatten_common(typval_T *argvars, typval_T *rettv, bool make_copy) tv_list_ref(list); } - tv_list_flatten(list, maxdepth); + tv_list_flatten(list, NULL, tv_list_len(list), maxdepth); } /// "flatten(list[, {maxdepth}])" function diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index ab4245b59a..125a4310d8 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -647,53 +647,55 @@ tv_list_copy_error: return NULL; } -/// Flatten "list" in place to depth "maxdepth". +/// Flatten up to "maxitems" in "list", starting at "first" to depth "maxdepth". +/// When "first" is NULL use the first item. /// Does nothing if "maxdepth" is 0. /// /// @param[in,out] list List to flatten /// @param[in] maxdepth Maximum depth that will be flattened /// /// @return OK or FAIL -void tv_list_flatten(list_T *list, long maxdepth) +void tv_list_flatten(list_T *list, listitem_T *first, long maxitems, long maxdepth) FUNC_ATTR_NONNULL_ARG(1) { listitem_T *item; listitem_T *to_free; - int n; + int done = 0; if (maxdepth == 0) { return; } - n = 0; - item = list->lv_first; - while (item != NULL) { + if (first == NULL) { + item = list->lv_first; + } else { + item = first; + } + + while (item != NULL && done < maxitems) { + listitem_T *next = item->li_next; + fast_breakcheck(); if (got_int) { return; } if (item->li_tv.v_type == VAR_LIST) { - listitem_T *next = item->li_next; + list_T *itemlist = item->li_tv.vval.v_list; tv_list_drop_items(list, item, item); - tv_list_extend(list, item->li_tv.vval.v_list, next); + tv_list_extend(list, itemlist, next); tv_clear(&item->li_tv); to_free = item; - if (item->li_prev == NULL) { - item = list->lv_first; - } else { - item = item->li_prev->li_next; + if (maxdepth > 0) { + tv_list_flatten(list, + item->li_prev == NULL ? list->lv_first : item->li_prev->li_next, + itemlist->lv_len, maxdepth - 1); } xfree(to_free); - - if (++n >= maxdepth) { - n = 0; - item = next; - } - } else { - n = 0; - item = item->li_next; } + + done++; + item = next; } } diff --git a/src/nvim/testdir/test_flatten.vim b/src/nvim/testdir/test_flatten.vim index d8abc1ad68..aa91060313 100644 --- a/src/nvim/testdir/test_flatten.vim +++ b/src/nvim/testdir/test_flatten.vim @@ -78,6 +78,14 @@ func Test_flatten() call add(y, x) " l:y = [2, [1, [...]]] call assert_equal([1, 2, 1, 2], flatten(l:x, 2)) call assert_equal([2, l:x], l:y) + + let l4 = [ 1, [ 11, [ 101, [ 1001 ] ] ] ] + call assert_equal(l4, flatten(deepcopy(l4), 0)) + call assert_equal([1, 11, [101, [1001]]], flatten(deepcopy(l4), 1)) + call assert_equal([1, 11, 101, [1001]], flatten(deepcopy(l4), 2)) + call assert_equal([1, 11, 101, 1001], flatten(deepcopy(l4), 3)) + call assert_equal([1, 11, 101, 1001], flatten(deepcopy(l4), 4)) + call assert_equal([1, 11, 101, 1001], flatten(deepcopy(l4))) endfunc func Test_flattennew() @@ -87,6 +95,14 @@ func Test_flattennew() call assert_equal([1, 2, [3, 4], 5], flattennew(l, 1)) call assert_equal([1, [2, [3, 4]], 5], l) + + let l4 = [ 1, [ 11, [ 101, [ 1001 ] ] ] ] + call assert_equal(l4, flatten(deepcopy(l4), 0)) + call assert_equal([1, 11, [101, [1001]]], flattennew(l4, 1)) + call assert_equal([1, 11, 101, [1001]], flattennew(l4, 2)) + call assert_equal([1, 11, 101, 1001], flattennew(l4, 3)) + call assert_equal([1, 11, 101, 1001], flattennew(l4, 4)) + call assert_equal([1, 11, 101, 1001], flattennew(l4)) endfunc " vim: shiftwidth=2 sts=2 expandtab -- cgit From ec2557236710f3e062164e7ff4b137b2a0d8dfa4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Feb 2023 15:31:43 +0800 Subject: vim-patch:8.2.4629: flattennew() makes a deep copy unnecessarily Problem: flattennew() makes a deep copy unnecessarily. Solution: Use a shallow copy. (issue vim/vim#10012) https://github.com/vim/vim/commit/c6c1ec4da53db9d292fa3dd081c20123f8261178 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/typval.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 6ac94706c7..f1852f1b6d 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1902,7 +1902,7 @@ static void flatten_common(typval_T *argvars, typval_T *rettv, bool make_copy) } if (make_copy) { - list = tv_list_copy(NULL, list, true, get_copyID()); + list = tv_list_copy(NULL, list, false, get_copyID()); rettv->vval.v_list = list; if (list == NULL) { return; diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 125a4310d8..9faf19c364 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -659,7 +659,6 @@ void tv_list_flatten(list_T *list, listitem_T *first, long maxitems, long maxdep FUNC_ATTR_NONNULL_ARG(1) { listitem_T *item; - listitem_T *to_free; int done = 0; if (maxdepth == 0) { return; @@ -684,14 +683,13 @@ void tv_list_flatten(list_T *list, listitem_T *first, long maxitems, long maxdep tv_list_drop_items(list, item, item); tv_list_extend(list, itemlist, next); tv_clear(&item->li_tv); - to_free = item; if (maxdepth > 0) { tv_list_flatten(list, item->li_prev == NULL ? list->lv_first : item->li_prev->li_next, itemlist->lv_len, maxdepth - 1); } - xfree(to_free); + xfree(item); } done++; -- cgit From c76dfe14b1422a1caccf13c3bc86754902eb0302 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Feb 2023 15:33:51 +0800 Subject: vim-patch:8.2.4632: using freed memory in flatten() Problem: Using freed memory in flatten(). Solution: Clear typval after recursing into list. https://github.com/vim/vim/commit/f3980dc5d0a5f873cf764b8ba3e567e42259e4e5 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 9faf19c364..17499480ed 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -682,13 +682,13 @@ void tv_list_flatten(list_T *list, listitem_T *first, long maxitems, long maxdep tv_list_drop_items(list, item, item); tv_list_extend(list, itemlist, next); - tv_clear(&item->li_tv); if (maxdepth > 0) { tv_list_flatten(list, item->li_prev == NULL ? list->lv_first : item->li_prev->li_next, itemlist->lv_len, maxdepth - 1); } + tv_clear(&item->li_tv); xfree(item); } -- cgit From 04a6369da530232eda4f5daa2addac8eb16eb126 Mon Sep 17 00:00:00 2001 From: Mark Naughton <42555851+Naught00@users.noreply.github.com> Date: Fri, 24 Feb 2023 11:05:39 +0000 Subject: refactor(PVS/V581): merge identical if statements (#22390) --- src/nvim/drawline.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 57d586cd1e..cd815da458 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1045,9 +1045,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, || wp->w_p_lcs_chars.nbsp) { extra_check = true; } - } - - if (wp->w_p_list && !has_fold && !end_fill) { trailcol = get_trailcol(wp, ptr, line); leadcol = get_leadcol(wp, ptr, line); } -- cgit From 4297127f14fa1b9062db7de0d63981887ebed063 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 24 Feb 2023 15:34:52 +0100 Subject: vim-patch:9.0.1350: CPON files are not recognized (#22392) Problem: CPON files are not recognized. Solution: Add patterns for CPON files. (Amaan Qureshi, closes vim/vim#12053) https://github.com/vim/vim/commit/c2254764bcada43eea894eb5852a26d5ac5ca8b0 Co-authored-by: Amaan Qureshi --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index d37a194f50..f77c926319 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -126,6 +126,7 @@ let s:filename_checks = { \ 'confini': ['/etc/pacman.conf', 'any/etc/pacman.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials', 'file.nmconnection'], \ 'context': ['tex/context/any/file.tex', 'file.mkii', 'file.mkiv', 'file.mkvi', 'file.mkxl', 'file.mklx'], \ 'cook': ['file.cook'], + \ 'cpon': ['file.cpon'], \ 'cpp': ['file.cxx', 'file.c++', 'file.hh', 'file.hxx', 'file.hpp', 'file.ipp', 'file.moc', 'file.tcc', 'file.inl', 'file.tlh'], \ 'cqlang': ['file.cql'], \ 'crm': ['file.crm'], -- cgit From 15cce77b383d0b0bfdaa1415cdde005cc43267d0 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 24 Feb 2023 17:50:37 +0100 Subject: vim-patch:9.0.1351: Dhall files are not recognized (#22393) Problem: Dhall files are not recognized. Solution: Add patterns for Dhall files. (Amaan Qureshi, closes vim/vim#12052) https://github.com/vim/vim/commit/def5521752abefe12db8cc3111a3b205ad1ac929 Co-authored-by: Amaan Qureshi --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index f77c926319..96ab5620ec 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -157,6 +157,7 @@ let s:filename_checks = { \ 'denyhosts': ['denyhosts.conf'], \ 'desc': ['file.desc'], \ 'desktop': ['file.desktop', '.directory', 'file.directory'], + \ 'dhall': ['file.dhall'], \ 'dictconf': ['dict.conf', '.dictrc'], \ 'dictdconf': ['dictd.conf', 'dictdfile.conf', 'dictd-file.conf'], \ 'diff': ['file.diff', 'file.rej'], -- cgit From 6942528a54eacbcdcb5b40fa27f9e37ae9e80915 Mon Sep 17 00:00:00 2001 From: bfredl Date: Sat, 25 Feb 2023 21:04:52 +0100 Subject: refactor(ui): ui_log() can now just be a function --- src/nvim/generators/gen_api_ui_events.lua | 1 - src/nvim/ui.c | 42 ++++++++++++++++--------------- 2 files changed, 22 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua index 827097f69d..bbc6252f14 100755 --- a/src/nvim/generators/gen_api_ui_events.lua +++ b/src/nvim/generators/gen_api_ui_events.lua @@ -120,7 +120,6 @@ for i = 1, #events do if ev.remote_only then call_output:write(' Array args = call_buf;\n') write_arglist(call_output, ev) - call_output:write(' UI_LOG('..ev.name..');\n') call_output:write(' ui_call_event("'..ev.name..'", args);\n') elseif ev.compositor_impl then call_output:write(' ui_comp_'..ev.name) diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 1693595ce8..a2c6d9431c 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -64,31 +64,31 @@ static int pending_has_mouse = -1; static Array call_buf = ARRAY_DICT_INIT; #if MIN_LOG_LEVEL > LOGLVL_DBG -# define UI_LOG(funname) +# define ui_log(funname) #else static size_t uilog_seen = 0; -static char uilog_last_event[1024] = { 0 }; +static const char *uilog_last_event = NULL; +static void ui_log(const char *funname) +{ # ifndef EXITFREE -# define entered_free_all_mem false + if (entered_free_all_mem) { + return; // do nothing, we cannot log now + } # endif -# define UI_LOG(funname) \ - do { \ - if (entered_free_all_mem) { \ - /* do nothing, we cannot log now */ \ - } else if (strequal(uilog_last_event, STR(funname))) { \ - uilog_seen++; \ - } else { \ - if (uilog_seen > 0) { \ - logmsg(LOGLVL_DBG, "UI: ", NULL, -1, true, \ - "%s (+%zu times...)", uilog_last_event, uilog_seen); \ - } \ - logmsg(LOGLVL_DBG, "UI: ", NULL, -1, true, STR(funname)); \ - uilog_seen = 0; \ - xstrlcpy(uilog_last_event, STR(funname), sizeof(uilog_last_event)); \ - } \ - } while (0) + if (uilog_last_event == funname) { + uilog_seen++; + } else { + if (uilog_seen > 0) { + logmsg(LOGLVL_DBG, "UI: ", NULL, -1, true, + "%s (+%zu times...)", uilog_last_event, uilog_seen); + } + logmsg(LOGLVL_DBG, "UI: ", NULL, -1, true, "%s", funname); + uilog_seen = 0; + uilog_last_event = funname; + } +} #endif // UI_CALL invokes a function on all registered UI instances. @@ -105,7 +105,7 @@ static char uilog_last_event[1024] = { 0 }; } \ } \ if (any_call) { \ - UI_LOG(funname); \ + ui_log(STR(funname)); \ } \ } while (0) @@ -654,6 +654,8 @@ void ui_call_event(char *name, Array args) if (!handled) { UI_CALL(true, event, ui, name, args); } + + ui_log(name); } void ui_cb_update_ext(void) -- cgit From 1d8b77da6b0abe6dccd6ce64e283b7208f873d57 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 26 Feb 2023 01:12:41 +0100 Subject: fix(MSVC): set the active code page to utf-8 (#22384) Neovim expects character encoding to be UTF-8, and deviation from this causes bugs such as lua files not being recognized for non-ascii paths. This changes the behavior of fopen, which defaults to using the currently active codepage. Closes: https://github.com/neovim/neovim/issues/18122 --- src/nvim/os/nvim.manifest | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/nvim/os/nvim.manifest b/src/nvim/os/nvim.manifest index 8878822a5d..571b7f4580 100644 --- a/src/nvim/os/nvim.manifest +++ b/src/nvim/os/nvim.manifest @@ -17,4 +17,9 @@ + + + UTF-8 + + -- cgit From 659234c95a23307486a4b7496f3f4391a4bdbe58 Mon Sep 17 00:00:00 2001 From: bfredl Date: Sun, 26 Feb 2023 13:55:29 +0100 Subject: fix(build): fix invalid use of EXITFREE fixup 6942528 refactor(ui): ui_log() can now just be a function --- src/nvim/ui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/ui.c b/src/nvim/ui.c index a2c6d9431c..73545441d3 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -71,7 +71,7 @@ static const char *uilog_last_event = NULL; static void ui_log(const char *funname) { -# ifndef EXITFREE +# ifdef EXITFREE if (entered_free_all_mem) { return; // do nothing, we cannot log now } -- cgit From 5e846978e3bf85ea5ae5b505af267c01e98f6135 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 26 Feb 2023 08:32:20 +0800 Subject: vim-patch:9.0.1354: "gr CTRL-G" stays in virtual replace mode Problem: "gr CTRL-G" stays in virtual replace mode. (Pierre Ganty) Solution: Prepend CTRL-V before control characters. (closes vim/vim#12045) https://github.com/vim/vim/commit/d6a4ea3aa0d3f4a886ea900e94bf4e8ca8ae8d63 Cherry-pick Test_edit_gr_special() from patch 9.0.1347. Co-authored-by: Bram Moolenaar --- src/nvim/edit.c | 4 ++++ src/nvim/normal.c | 5 +++++ src/nvim/testdir/test_edit.vim | 14 ++++++++++++++ 3 files changed, 23 insertions(+) (limited to 'src') diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 8b74593360..8143af7d1f 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -3444,6 +3444,10 @@ static void ins_ctrl_g(void) dont_sync_undo = kNone; break; + case ESC: + // Esc after CTRL-G cancels it. + break; + // Unknown CTRL-G command, reserved for future expansion. default: vim_beep(BO_CTRLG); diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 5677c627a7..33d04f76af 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -4720,6 +4720,11 @@ static void nv_vreplace(cmdarg_T *cap) if (cap->extra_char == Ctrl_V) { // get another character cap->extra_char = get_literal(false); } + if (cap->extra_char < ' ') { + // Prefix a control character with CTRL-V to avoid it being used as + // a command. + stuffcharReadbuff(Ctrl_V); + } stuffcharReadbuff(cap->extra_char); stuffcharReadbuff(ESC); if (virtual_active()) { diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim index 89a9179e60..58e0232f29 100644 --- a/src/nvim/testdir/test_edit.vim +++ b/src/nvim/testdir/test_edit.vim @@ -2080,6 +2080,20 @@ func Test_edit_CTRL_hat() bwipe! endfunc +" Test "gr" followed by an Insert mode command does get out of Insert mode. +func Test_edit_gr_special() + enew + call setline(1, ['abcdef', 'xxxxxx']) + exe "normal! gr\lx" + call assert_equal("\def", getline(1)) + + call setline(1, 'abcdef') + exe "normal! 0gr\lx" + call assert_equal("\def", getline(1)) + + bwipe! +endfunc + " Weird long file name was going over the end of NameBuff func Test_edit_overlong_file_name() CheckUnix -- cgit From 6644742c26e4d8da999cf00754b6e6ee0ba0618f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 26 Feb 2023 23:02:01 +0800 Subject: vim-patch:9.0.1356: cannot cancel "gr" with Esc Problem: Cannot cancel "gr" with Esc. Solution: Make "gr" do nothing. (closes vim/vim#12064) https://github.com/vim/vim/commit/4f026ea9f1ad9db262f0dba522768c84e5ae37b4 N/A patches for version.c: vim-patch:9.0.1347: "gr CTRL-O" stays in Insert mode Problem: "gr CTRL-O" stays in Insert mode. (Pierre Ganty) Solution: Do not set restart_edit when "cmdchar" is 'v'. (closes vim/vim#12045) https://github.com/vim/vim/commit/2824d1ee325ea61855c26f77e7a4e095b9606720 vim-patch:9.0.1349: "gr" with a count fails Problem: "gr" with a count fails. Solution: Break out of the loop only after using the count. https://github.com/vim/vim/commit/3ddb1182b7b8d376e59b444f6b3e213f0dcd3417 --- src/nvim/normal.c | 2 +- src/nvim/testdir/test_edit.vim | 15 +-------------- src/nvim/testdir/test_normal.vim | 23 +++++++++++++++++++++-- 3 files changed, 23 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 33d04f76af..ef8f6e7b0f 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -4710,7 +4710,7 @@ static void nv_vreplace(cmdarg_T *cap) return; } - if (checkclearopq(cap->oap)) { + if (checkclearopq(cap->oap) || cap->extra_char == ESC) { return; } diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim index 58e0232f29..b6078a1e22 100644 --- a/src/nvim/testdir/test_edit.vim +++ b/src/nvim/testdir/test_edit.vim @@ -580,6 +580,7 @@ func Test_edit_CTRL_G() call assert_equal([0, 3, 7, 0], getpos('.')) call feedkeys("i\j\", 'tnix') call assert_equal([0, 3, 6, 0], getpos('.')) + call assert_nobeep("normal! i\\") bw! endfunc @@ -2080,20 +2081,6 @@ func Test_edit_CTRL_hat() bwipe! endfunc -" Test "gr" followed by an Insert mode command does get out of Insert mode. -func Test_edit_gr_special() - enew - call setline(1, ['abcdef', 'xxxxxx']) - exe "normal! gr\lx" - call assert_equal("\def", getline(1)) - - call setline(1, 'abcdef') - exe "normal! 0gr\lx" - call assert_equal("\def", getline(1)) - - bwipe! -endfunc - " Weird long file name was going over the end of NameBuff func Test_edit_overlong_file_name() CheckUnix diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index 390e179f13..5d8e1913a2 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -3283,9 +3283,9 @@ func Test_delete_until_paragraph() endfunc " Test for the gr (virtual replace) command -" Test for the bug fixed by 7.4.387 func Test_gr_command() enew! + " Test for the bug fixed by 7.4.387 let save_cpo = &cpo call append(0, ['First line', 'Second line', 'Third line']) exe "normal i\u" @@ -3298,10 +3298,12 @@ 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\122" call assert_equal('zxxxx line', getline(1)) + set virtualedit=all normal! 15|grl call assert_equal('zxxxx line l', getline(1)) @@ -3309,8 +3311,25 @@ func Test_gr_command() set nomodifiable call assert_fails('normal! grx', 'E21:') call assert_fails('normal! gRx', 'E21:') + call assert_nobeep("normal! gr\") set modifiable& - enew! + + call assert_nobeep("normal! gr\") + call assert_beeps("normal! cgr\") + + call assert_equal('zxxxx line l', getline(1)) + exe "normal! 2|gr\\" + call assert_equal("z\xx line l", getline(1)) + + call setline(1, 'abcdef') + exe "normal! 0gr\lx" + call assert_equal("\def", getline(1)) + + call setline(1, 'abcdef') + exe "normal! 0gr\lx" + call assert_equal("\def", getline(1)) + + bwipe! endfunc func Test_nv_hat_count() -- cgit From 774e59f3f9bf50c8350857c6722bb58df2dd940a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sun, 26 Feb 2023 16:53:33 +0000 Subject: feat(treesitter): expand the API --- src/nvim/lua/treesitter.c | 138 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 123 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 5248ebed14..d72e7a1825 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -51,8 +51,11 @@ static struct luaL_Reg parser_meta[] = { { "__gc", parser_gc }, { "__tostring", parser_tostring }, { "parse", parser_parse }, + { "reset", parser_reset }, { "set_included_ranges", parser_set_ranges }, { "included_ranges", parser_get_ranges }, + { "set_timeout", parser_set_timeout }, + { "timeout", parser_get_timeout }, { NULL, NULL } }; @@ -78,6 +81,8 @@ static struct luaL_Reg node_meta[] = { { "field", node_field }, { "named", node_named }, { "missing", node_missing }, + { "extra", node_extra }, + { "has_changes", node_has_changes }, { "has_error", node_has_error }, { "sexpr", node_sexpr }, { "child_count", node_child_count }, @@ -95,7 +100,9 @@ static struct luaL_Reg node_meta[] = { { "prev_named_sibling", node_prev_named_sibling }, { "named_children", node_named_children }, { "root", node_root }, + { "tree", node_tree }, { "byte_length", node_byte_length }, + { "equal", node_equal }, { NULL, NULL } }; @@ -446,6 +453,16 @@ static int parser_parse(lua_State *L) return 2; } +static int parser_reset(lua_State *L) +{ + TSParser **p = parser_check(L, 1); + if (p && *p) { + ts_parser_reset(*p); + } + + return 0; +} + static int tree_copy(lua_State *L) { TSTree **tree = tree_check(L, 1); @@ -597,6 +614,33 @@ static int parser_get_ranges(lua_State *L) return 1; } +static int parser_set_timeout(lua_State *L) +{ + TSParser **p = parser_check(L, 1); + if (!p) { + return 0; + } + + if (lua_gettop(L) < 2) { + luaL_error(L, "integer expected"); + } + + uint32_t timeout = (uint32_t)luaL_checkinteger(L, 2); + ts_parser_set_timeout_micros(*p, timeout); + return 0; +} + +static int parser_get_timeout(lua_State *L) +{ + TSParser **p = parser_check(L, 1); + if (!p) { + return 0; + } + + lua_pushinteger(L, (long)ts_parser_timeout_micros(*p)); + return 0; +} + // Tree methods /// push tree interface on lua stack. @@ -740,12 +784,29 @@ static int node_range(lua_State *L) if (!node_check(L, 1, &node)) { return 0; } + + bool include_bytes = false; + if (lua_gettop(L) >= 2) { + include_bytes = lua_toboolean(L, 2); + } + TSPoint start = ts_node_start_point(node); TSPoint end = ts_node_end_point(node); - lua_pushnumber(L, start.row); - lua_pushnumber(L, start.column); - lua_pushnumber(L, end.row); - lua_pushnumber(L, end.column); + + if (include_bytes) { + lua_pushinteger(L, start.row); + lua_pushinteger(L, start.column); + lua_pushinteger(L, ts_node_start_byte(node)); + lua_pushinteger(L, end.row); + lua_pushinteger(L, end.column); + lua_pushinteger(L, ts_node_end_byte(node)); + return 6; + } + + lua_pushinteger(L, start.row); + lua_pushinteger(L, start.column); + lua_pushinteger(L, end.row); + lua_pushinteger(L, end.column); return 4; } @@ -757,9 +818,9 @@ static int node_start(lua_State *L) } TSPoint start = ts_node_start_point(node); uint32_t start_byte = ts_node_start_byte(node); - lua_pushnumber(L, start.row); - lua_pushnumber(L, start.column); - lua_pushnumber(L, start_byte); + lua_pushinteger(L, start.row); + lua_pushinteger(L, start.column); + lua_pushinteger(L, start_byte); return 3; } @@ -771,9 +832,9 @@ static int node_end(lua_State *L) } TSPoint end = ts_node_end_point(node); uint32_t end_byte = ts_node_end_byte(node); - lua_pushnumber(L, end.row); - lua_pushnumber(L, end.column); - lua_pushnumber(L, end_byte); + lua_pushinteger(L, end.row); + lua_pushinteger(L, end.column); + lua_pushinteger(L, end_byte); return 3; } @@ -784,7 +845,7 @@ static int node_child_count(lua_State *L) return 0; } uint32_t count = ts_node_child_count(node); - lua_pushnumber(L, count); + lua_pushinteger(L, count); return 1; } @@ -795,7 +856,7 @@ static int node_named_child_count(lua_State *L) return 0; } uint32_t count = ts_node_named_child_count(node); - lua_pushnumber(L, count); + lua_pushinteger(L, count); return 1; } @@ -816,7 +877,7 @@ static int node_symbol(lua_State *L) return 0; } TSSymbol symbol = ts_node_symbol(node); - lua_pushnumber(L, symbol); + lua_pushinteger(L, symbol); return 1; } @@ -882,6 +943,26 @@ static int node_missing(lua_State *L) return 1; } +static int node_extra(lua_State *L) +{ + TSNode node; + if (!node_check(L, 1, &node)) { + return 0; + } + lua_pushboolean(L, ts_node_is_extra(node)); + return 1; +} + +static int node_has_changes(lua_State *L) +{ + TSNode node; + if (!node_check(L, 1, &node)) { + return 0; + } + lua_pushboolean(L, ts_node_has_changes(node)); + return 1; +} + static int node_has_error(lua_State *L) { TSNode node; @@ -1108,6 +1189,17 @@ static int node_root(lua_State *L) return 1; } +static int node_tree(lua_State *L) +{ + TSNode node; + if (!node_check(L, 1, &node)) { + return 0; + } + + push_tree(L, (TSTree *)node.tree, false); + return 1; +} + static int node_byte_length(lua_State *L) { TSNode node; @@ -1118,7 +1210,23 @@ static int node_byte_length(lua_State *L) uint32_t start_byte = ts_node_start_byte(node); uint32_t end_byte = ts_node_end_byte(node); - lua_pushnumber(L, end_byte - start_byte); + lua_pushinteger(L, end_byte - start_byte); + return 1; +} + +static int node_equal(lua_State *L) +{ + TSNode node1; + if (!node_check(L, 1, &node1)) { + return 0; + } + + TSNode node2; + if (!node_check(L, 2, &node2)) { + return luaL_error(L, "TSNode expected"); + } + + lua_pushboolean(L, ts_node_eq(node1, node2)); return 1; } @@ -1367,7 +1475,7 @@ static int query_inspect(lua_State *L) &strlen); lua_pushlstring(L, str, strlen); // [retval, patterns, pat, pred, item] } else if (step[k].type == TSQueryPredicateStepTypeCapture) { - lua_pushnumber(L, step[k].value_id + 1); // [..., pat, pred, item] + lua_pushinteger(L, step[k].value_id + 1); // [..., pat, pred, item] } else { abort(); } -- cgit From 0972d7a12468d6914a70e453af85c307b167c55b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 26 Feb 2023 23:13:12 +0800 Subject: vim-patch:9.0.0196: finding value in list may require a for loop Problem: Finding value in list may require a for loop. Solution: Add indexof(). (Yegappan Lakshmanan, closes vim/vim#10903) https://github.com/vim/vim/commit/b218655d5a485f5b193fb18d7240837d42b89812 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval.lua | 1 + src/nvim/eval/funcs.c | 109 +++++++++++++++++++++++++++++++++++++ src/nvim/eval/typval.c | 50 +++++++++++++++++ src/nvim/testdir/test_blob.vim | 27 +++++++++ src/nvim/testdir/test_listdict.vim | 46 ++++++++++++++++ 5 files changed, 233 insertions(+) (limited to 'src') diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index a1caeea95a..0c6912a702 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -213,6 +213,7 @@ return { iconv={args=3, base=1, fast=true}, indent={args=1, base=1}, index={args={2, 4}, base=1}, + indexof={args={2, 3}, base=1}, input={args={1, 3}, base=1}, inputdialog={args={1, 3}, base=1}, inputlist={args=1, base=1}, diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index f1852f1b6d..980a9fffa3 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3488,6 +3488,115 @@ static void f_index(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } +/// Evaluate "expr" with the v:key and v:val arguments and return the result. +/// The expression is expected to return a boolean value. The caller should set +/// the VV_KEY and VV_VAL vim variables before calling this function. +static varnumber_T indexof_eval_expr(typval_T *expr) +{ + typval_T argv[3]; + argv[0] = *get_vim_var_tv(VV_KEY); + argv[1] = *get_vim_var_tv(VV_VAL); + typval_T newtv; + newtv.v_type = VAR_UNKNOWN; + + if (eval_expr_typval(expr, argv, 2, &newtv) == FAIL) { + return false; + } + + bool error = false; + varnumber_T found = tv_get_bool_chk(&newtv, &error); + + return error ? false : found; +} + +/// "indexof()" function +static void f_indexof(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = -1; + + if (tv_check_for_list_or_blob_arg(argvars, 0) == FAIL + || tv_check_for_string_or_func_arg(argvars, 1) == FAIL + || tv_check_for_opt_dict_arg(argvars, 2) == FAIL) { + return; + } + + if ((argvars[1].v_type == VAR_STRING && argvars[1].vval.v_string == NULL) + || (argvars[1].v_type == VAR_FUNC && argvars[1].vval.v_partial == NULL)) { + return; + } + + varnumber_T startidx = 0; + varnumber_T idx = 0; + if (argvars[2].v_type == VAR_DICT) { + startidx = tv_dict_get_number_def(argvars[2].vval.v_dict, "startidx", 0); + } + + typval_T save_val; + typval_T save_key; + prepare_vimvar(VV_VAL, &save_val); + prepare_vimvar(VV_KEY, &save_key); + + // We reset "did_emsg" to be able to detect whether an error occurred + // during evaluation of the expression. + const int save_did_emsg = did_emsg; + did_emsg = false; + + if (argvars[0].v_type == VAR_BLOB) { + blob_T *const b = argvars[0].vval.v_blob; + if (b == NULL) { + goto theend; + } + if (startidx < 0) { + startidx = tv_blob_len(b) + startidx; + if (startidx < 0) { + startidx = 0; + } + } + + for (idx = startidx; idx < tv_blob_len(b); idx++) { + set_vim_var_nr(VV_KEY, idx); + set_vim_var_nr(VV_VAL, tv_blob_get(b, (int)idx)); + + if (indexof_eval_expr(&argvars[1])) { + rettv->vval.v_number = idx; + break; + } + } + } else { + list_T *const l = argvars[0].vval.v_list; + if (l == NULL) { + goto theend; + } + + listitem_T *item; + if (startidx == 0) { + item = tv_list_first(l); + } else { + // Start at specified item. Use the cached index that list_find() + // sets, so that a negative number also works. + item = tv_list_find(l, (int)startidx); + if (item != NULL) { + idx = l->lv_idx; + } + } + + for (; item != NULL; item = TV_LIST_ITEM_NEXT(l, item), idx++) { + set_vim_var_nr(VV_KEY, idx); + tv_copy(TV_LIST_ITEM_TV(item), get_vim_var_tv(VV_VAL)); + + if (indexof_eval_expr(&argvars[1])) { + rettv->vval.v_number = idx; + break; + } + } + } + +theend: + restore_vimvar(VV_KEY, &save_key); + restore_vimvar(VV_VAL, &save_val); + did_emsg |= save_did_emsg; +} + static bool inputsecret_flag = false; /// "input()" function diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 17499480ed..0a30cdb62e 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -44,10 +44,16 @@ static char e_string_required_for_argument_nr[] = N_("E1174: String required for argument %d"); static char e_non_empty_string_required_for_argument_nr[] = N_("E1175: Non-empty string required for argument %d"); +static char e_dict_required_for_argument_nr[] + = N_("E1206: Dictionary required for argument %d"); static char e_number_required_for_argument_nr[] = N_("E1210: Number required for argument %d"); static char e_string_or_list_required_for_argument_nr[] = N_("E1222: String or List required for argument %d"); +static char e_list_or_blob_required_for_argument_nr[] + = N_("E1226: List or Blob required for argument %d"); +static char e_string_or_function_required_for_argument_nr[] + = N_("E1256: String or function required for argument %d"); bool tv_in_free_unref_items = false; @@ -3905,6 +3911,25 @@ int tv_check_for_opt_number_arg(const typval_T *const args, const int idx) || tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL; } +/// Give an error and return FAIL unless "args[idx]" is a dict. +int tv_check_for_dict_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_DICT) { + semsg(_(e_dict_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + +/// Check for an optional dict argument at "idx" +int tv_check_for_opt_dict_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + return (args[idx].v_type == VAR_UNKNOWN + || tv_check_for_dict_arg(args, idx) != FAIL) ? OK : FAIL; +} + /// Give an error and return FAIL unless "args[idx]" is a string or a list. int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE @@ -3916,6 +3941,31 @@ int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx) return OK; } +/// Give an error and return FAIL unless "args[idx]" is a string +/// or a function reference. +int tv_check_for_string_or_func_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_PARTIAL + && args[idx].v_type != VAR_FUNC + && args[idx].v_type != VAR_STRING) { + semsg(_(e_string_or_function_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + +/// Give an error and return FAIL unless "args[idx]" is a list or a blob. +int tv_check_for_list_or_blob_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_LIST && args[idx].v_type != VAR_BLOB) { + semsg(_(e_list_or_blob_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + /// Get the string value of a "stringish" VimL object. /// /// @param[in] tv Object to get value of. diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index 046acb81e1..4c5632c81f 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -364,4 +364,31 @@ func Test_blob2string() call assert_equal(v, string(b)) endfunc +" Test for the indexof() function +func Test_indexof() + let b = 0zdeadbeef + call assert_equal(0, indexof(b, {i, v -> v == 0xde})) + call assert_equal(3, indexof(b, {i, v -> v == 0xef})) + call assert_equal(-1, indexof(b, {i, v -> v == 0x1})) + call assert_equal(1, indexof(b, "v:val == 0xad")) + call assert_equal(-1, indexof(b, "v:val == 0xff")) + + call assert_equal(-1, indexof(0z, "v:val == 0x0")) + call assert_equal(-1, indexof(v:_null_blob, "v:val == 0xde")) + call assert_equal(-1, indexof(b, v:_null_string)) + " Nvim doesn't have null functions + " call assert_equal(-1, indexof(b, test_null_function())) + + let b = 0z01020102 + call assert_equal(1, indexof(b, "v:val == 0x02", #{startidx: 0})) + call assert_equal(2, indexof(b, "v:val == 0x01", #{startidx: -2})) + call assert_equal(-1, indexof(b, "v:val == 0x01", #{startidx: 5})) + call assert_equal(0, indexof(b, "v:val == 0x01", #{startidx: -5})) + call assert_equal(0, indexof(b, "v:val == 0x01", v:_null_dict)) + + " failure cases + call assert_fails('let i = indexof(b, "val == 0xde")', 'E121:') + call assert_fails('let i = indexof(b, {})', 'E1256:') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_listdict.vim b/src/nvim/testdir/test_listdict.vim index 9ecd83265a..4c51119d16 100644 --- a/src/nvim/testdir/test_listdict.vim +++ b/src/nvim/testdir/test_listdict.vim @@ -1067,4 +1067,50 @@ func Test_null_dict() call assert_equal({}, {}) endfunc +" Test for the indexof() function +func Test_indexof() + let l = [#{color: 'red'}, #{color: 'blue'}, #{color: 'green'}] + call assert_equal(0, indexof(l, {i, v -> v.color == 'red'})) + call assert_equal(2, indexof(l, {i, v -> v.color == 'green'})) + call assert_equal(-1, indexof(l, {i, v -> v.color == 'grey'})) + call assert_equal(1, indexof(l, "v:val.color == 'blue'")) + call assert_equal(-1, indexof(l, "v:val.color == 'cyan'")) + + let l = [#{n: 10}, #{n: 10}, #{n: 20}] + call assert_equal(0, indexof(l, "v:val.n == 10", #{startidx: 0})) + call assert_equal(1, indexof(l, "v:val.n == 10", #{startidx: -2})) + call assert_equal(-1, indexof(l, "v:val.n == 10", #{startidx: 4})) + call assert_equal(-1, indexof(l, "v:val.n == 10", #{startidx: -4})) + call assert_equal(0, indexof(l, "v:val.n == 10", v:_null_dict)) + + call assert_equal(-1, indexof([], {i, v -> v == 'a'})) + call assert_equal(-1, indexof(v:_null_list, {i, v -> v == 'a'})) + call assert_equal(-1, indexof(l, v:_null_string)) + " Nvim doesn't have null functions + " call assert_equal(-1, indexof(l, test_null_function())) + + " failure cases + call assert_fails('let i = indexof(l, "v:val == ''cyan''")', 'E735:') + call assert_fails('let i = indexof(l, "color == ''cyan''")', 'E121:') + call assert_fails('let i = indexof(l, {})', 'E1256:') + call assert_fails('let i = indexof({}, "v:val == 2")', 'E1226:') + call assert_fails('let i = indexof([], "v:val == 2", [])', 'E1206:') + + func TestIdx(k, v) + return a:v.n == 20 + endfunc + call assert_equal(2, indexof(l, function("TestIdx"))) + delfunc TestIdx + func TestIdx(k, v) + return {} + endfunc + call assert_fails('let i = indexof(l, function("TestIdx"))', 'E728:') + delfunc TestIdx + func TestIdx(k, v) + throw "IdxError" + endfunc + call assert_fails('let i = indexof(l, function("TestIdx"))', 'E605:') + delfunc TestIdx +endfunc + " vim: shiftwidth=2 sts=2 expandtab -- cgit From 13da3d469ae10201de00ae89277c53c40342f4df Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 26 Feb 2023 23:50:35 +0800 Subject: vim-patch:partial:9.0.0202: code and help for indexof() is not ideal Problem: Code and help for indexof() is not ideal. Solution: Refactor the code, improve the help. (Yegappan Lakshmanan, closes vim/vim#10908) https://github.com/vim/vim/commit/3fbf6cd355de2212e9227f57d545592aae3f688f Skip CHECK_LIST_MATERIALIZE and set_vim_var_type(). Use tv_list_uidx() instead of lv_idx. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 115 +++++++++++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 980a9fffa3..8070dacc48 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3509,6 +3509,71 @@ static varnumber_T indexof_eval_expr(typval_T *expr) return error ? false : found; } +/// Evaluate "expr" for each byte in the Blob "b" starting with the byte at +/// "startidx" and return the index of the byte where "expr" is TRUE. Returns +/// -1 if "expr" doesn't evaluate to TRUE for any of the bytes. +static varnumber_T indexof_blob(blob_T *b, varnumber_T startidx, typval_T *expr) +{ + if (b == NULL) { + return -1; + } + + if (startidx < 0) { + // negative index: index from the last byte + startidx = tv_blob_len(b) + startidx; + if (startidx < 0) { + startidx = 0; + } + } + + for (varnumber_T idx = startidx; idx < tv_blob_len(b); idx++) { + set_vim_var_nr(VV_KEY, idx); + set_vim_var_nr(VV_VAL, tv_blob_get(b, (int)idx)); + + if (indexof_eval_expr(expr)) { + return idx; + } + } + + return -1; +} + +/// Evaluate "expr" for each item in the List "l" starting with the item at +/// "startidx" and return the index of the item where "expr" is TRUE. Returns +/// -1 if "expr" doesn't evaluate to TRUE for any of the items. +static varnumber_T indexof_list(list_T *l, varnumber_T startidx, typval_T *expr) +{ + if (l == NULL) { + return -1; + } + + listitem_T *item; + varnumber_T idx = 0; + if (startidx == 0) { + item = tv_list_first(l); + } else { + // Start at specified item. + idx = tv_list_uidx(l, (int)startidx); + if (idx == -1) { + item = NULL; + } else { + item = tv_list_find(l, (int)idx); + assert(item != NULL); + } + } + + for (; item != NULL; item = TV_LIST_ITEM_NEXT(l, item), idx++) { + set_vim_var_nr(VV_KEY, idx); + tv_copy(TV_LIST_ITEM_TV(item), get_vim_var_tv(VV_VAL)); + + if (indexof_eval_expr(expr)) { + return idx; + } + } + + return -1; +} + /// "indexof()" function static void f_indexof(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -3526,7 +3591,6 @@ static void f_indexof(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } varnumber_T startidx = 0; - varnumber_T idx = 0; if (argvars[2].v_type == VAR_DICT) { startidx = tv_dict_get_number_def(argvars[2].vval.v_dict, "startidx", 0); } @@ -3542,56 +3606,11 @@ static void f_indexof(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) did_emsg = false; if (argvars[0].v_type == VAR_BLOB) { - blob_T *const b = argvars[0].vval.v_blob; - if (b == NULL) { - goto theend; - } - if (startidx < 0) { - startidx = tv_blob_len(b) + startidx; - if (startidx < 0) { - startidx = 0; - } - } - - for (idx = startidx; idx < tv_blob_len(b); idx++) { - set_vim_var_nr(VV_KEY, idx); - set_vim_var_nr(VV_VAL, tv_blob_get(b, (int)idx)); - - if (indexof_eval_expr(&argvars[1])) { - rettv->vval.v_number = idx; - break; - } - } + rettv->vval.v_number = indexof_blob(argvars[0].vval.v_blob, startidx, &argvars[1]); } else { - list_T *const l = argvars[0].vval.v_list; - if (l == NULL) { - goto theend; - } - - listitem_T *item; - if (startidx == 0) { - item = tv_list_first(l); - } else { - // Start at specified item. Use the cached index that list_find() - // sets, so that a negative number also works. - item = tv_list_find(l, (int)startidx); - if (item != NULL) { - idx = l->lv_idx; - } - } - - for (; item != NULL; item = TV_LIST_ITEM_NEXT(l, item), idx++) { - set_vim_var_nr(VV_KEY, idx); - tv_copy(TV_LIST_ITEM_TV(item), get_vim_var_tv(VV_VAL)); - - if (indexof_eval_expr(&argvars[1])) { - rettv->vval.v_number = idx; - break; - } - } + rettv->vval.v_number = indexof_list(argvars[0].vval.v_list, startidx, &argvars[1]); } -theend: restore_vimvar(VV_KEY, &save_key); restore_vimvar(VV_VAL, &save_val); did_emsg |= save_did_emsg; -- cgit From 1f8cef53deb4b91a7249affca77bfb89ce0949b4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 27 Feb 2023 00:00:01 +0800 Subject: vim-patch:9.0.0204: indexof() may leak memory Problem: indexof() may leak memory. Solution: Free allocated values. (Yegappan Lakshmanan, closes vim/vim#10916) https://github.com/vim/vim/commit/63acae13f57c5ad4c8ec3146d0c458550b9e984e Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 6 +++++- src/nvim/testdir/test_blob.vim | 1 + src/nvim/testdir/test_listdict.vim | 6 ++++++ 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8070dacc48..13d8f52768 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3505,6 +3505,7 @@ static varnumber_T indexof_eval_expr(typval_T *expr) bool error = false; varnumber_T found = tv_get_bool_chk(&newtv, &error); + tv_clear(&newtv); return error ? false : found; } @@ -3566,7 +3567,10 @@ static varnumber_T indexof_list(list_T *l, varnumber_T startidx, typval_T *expr) set_vim_var_nr(VV_KEY, idx); tv_copy(TV_LIST_ITEM_TV(item), get_vim_var_tv(VV_VAL)); - if (indexof_eval_expr(expr)) { + bool found = indexof_eval_expr(expr); + tv_clear(get_vim_var_tv(VV_VAL)); + + if (found) { return idx; } } diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index 4c5632c81f..cf03d2011c 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -372,6 +372,7 @@ func Test_indexof() call assert_equal(-1, indexof(b, {i, v -> v == 0x1})) call assert_equal(1, indexof(b, "v:val == 0xad")) call assert_equal(-1, indexof(b, "v:val == 0xff")) + call assert_equal(-1, indexof(b, {_, v -> "v == 0xad"})) call assert_equal(-1, indexof(0z, "v:val == 0x0")) call assert_equal(-1, indexof(v:_null_blob, "v:val == 0xde")) diff --git a/src/nvim/testdir/test_listdict.vim b/src/nvim/testdir/test_listdict.vim index 4c51119d16..37c1ee8307 100644 --- a/src/nvim/testdir/test_listdict.vim +++ b/src/nvim/testdir/test_listdict.vim @@ -1083,7 +1083,13 @@ func Test_indexof() call assert_equal(-1, indexof(l, "v:val.n == 10", #{startidx: -4})) call assert_equal(0, indexof(l, "v:val.n == 10", v:_null_dict)) + let s = ["a", "b", "c"] + call assert_equal(2, indexof(s, {_, v -> v == 'c'})) + call assert_equal(-1, indexof(s, {_, v -> v == 'd'})) + call assert_equal(-1, indexof(s, {_, v -> "v == 'd'"})) + call assert_equal(-1, indexof([], {i, v -> v == 'a'})) + call assert_equal(-1, indexof([1, 2, 3], {_, v -> "v == 2"})) call assert_equal(-1, indexof(v:_null_list, {i, v -> v == 'a'})) call assert_equal(-1, indexof(l, v:_null_string)) " Nvim doesn't have null functions -- cgit From 2c9fbe34b20266ef5ab54f6ed14fb38eef60430d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 27 Feb 2023 10:10:42 +0800 Subject: vim-patch:8.2.2336: Vim9: not possible to extend dictionary with different type (#22425) Problem: Vim9: it is not possible to extend a dictionary with different item types. Solution: Add extendnew(). (closes vim/vim#7666) https://github.com/vim/vim/commit/b0e6b513648db7035046613431a4aa9d71ef4653 Co-authored-by: Bram Moolenaar --- src/nvim/eval.lua | 1 + src/nvim/eval/funcs.c | 70 ++++++++++++++++++++++++++++++-------- src/nvim/testdir/test_listdict.vim | 12 +++++++ 3 files changed, 69 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 0c6912a702..a476e20339 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -120,6 +120,7 @@ return { expand={args={1, 3}, base=1}, expandcmd={args={1, 2}, base=1}, extend={args={2, 3}, base=1}, + extendnew={args={2, 3}, base=1}, feedkeys={args={1, 2}, base=1}, file_readable={args=1, base=1, func='f_filereadable'}, -- obsolete filereadable={args=1, base=1, fast=true}, diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 13d8f52768..1baf96e281 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1929,18 +1929,22 @@ static void f_flattennew(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) flatten_common(argvars, rettv, true); } -/// "extend(list, list [, idx])" function -/// "extend(dict, dict [, action])" function -static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +/// "extend()" or "extendnew()" function. "is_new" is true for extendnew(). +static void extend(typval_T *argvars, typval_T *rettv, char *arg_errmsg, bool is_new) { - const char *const arg_errmsg = N_("extend() argument"); - if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) { bool error = false; - list_T *const l1 = argvars[0].vval.v_list; + list_T *l1 = argvars[0].vval.v_list; list_T *const l2 = argvars[1].vval.v_list; - if (!value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) { + if (is_new || !value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) { + if (is_new) { + l1 = tv_list_copy(NULL, l1, false, get_copyID()); + if (l1 == NULL) { + return; + } + } + listitem_T *item; if (argvars[2].v_type != VAR_UNKNOWN) { long before = (long)tv_get_number_chk(&argvars[2], &error); @@ -1962,11 +1966,18 @@ static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } tv_list_extend(l1, l2, item); - tv_copy(&argvars[0], rettv); + if (is_new) { + *rettv = (typval_T){ + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval.v_list = l1, + }; + } else { + tv_copy(&argvars[0], rettv); + } } - } else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == - VAR_DICT) { - dict_T *const d1 = argvars[0].vval.v_dict; + } else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT) { + dict_T *d1 = argvars[0].vval.v_dict; dict_T *const d2 = argvars[1].vval.v_dict; if (d1 == NULL) { const bool locked = value_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE); @@ -1975,7 +1986,14 @@ static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } else if (d2 == NULL) { // Do nothing tv_copy(&argvars[0], rettv); - } else if (!value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { + } else if (is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { + if (is_new) { + d1 = tv_dict_copy(NULL, d1, false, get_copyID()); + if (d1 == NULL) { + return; + } + } + const char *action = "force"; // Check the third argument. if (argvars[2].v_type != VAR_UNKNOWN) { @@ -1999,13 +2017,37 @@ static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tv_dict_extend(d1, d2, action); - tv_copy(&argvars[0], rettv); + if (is_new) { + *rettv = (typval_T){ + .v_type = VAR_DICT, + .v_lock = VAR_UNLOCKED, + .vval.v_dict = d1, + }; + } else { + tv_copy(&argvars[0], rettv); + } } } else { - semsg(_(e_listdictarg), "extend()"); + semsg(_(e_listdictarg), is_new ? "extendnew()" : "extend()"); } } +/// "extend(list, list [, idx])" function +/// "extend(dict, dict [, action])" function +static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + char *errmsg = N_("extend() argument"); + extend(argvars, rettv, errmsg, false); +} + +/// "extendnew(list, list [, idx])" function +/// "extendnew(dict, dict [, action])" function +static void f_extendnew(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + char *errmsg = N_("extendnew() argument"); + extend(argvars, rettv, errmsg, true); +} + /// "feedkeys()" function static void f_feedkeys(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { diff --git a/src/nvim/testdir/test_listdict.vim b/src/nvim/testdir/test_listdict.vim index 37c1ee8307..fa22bad0cb 100644 --- a/src/nvim/testdir/test_listdict.vim +++ b/src/nvim/testdir/test_listdict.vim @@ -881,6 +881,18 @@ func Test_listdict_extend() call assert_equal([1, 5, 7, 1, 5, 7], l) endfunc +func Test_listdict_extendnew() + " Test extendnew() with lists + let l = [1, 2, 3] + call assert_equal([1, 2, 3, 4, 5], extendnew(l, [4, 5])) + call assert_equal([1, 2, 3], l) + + " Test extend() with dictionaries. + let d = {'a': {'b': 'B'}} + call assert_equal({'a': {'b': 'B'}, 'c': 'cc'}, extendnew(d, {'c': 'cc'})) + call assert_equal({'a': {'b': 'B'}}, d) +endfunc + func s:check_scope_dict(x, fixed) func s:gen_cmd(cmd, x) return substitute(a:cmd, '\ Date: Mon, 27 Feb 2023 23:27:09 +0800 Subject: vim-patch:9.0.1361: extendnew() not sufficiently tested (#22434) Problem: extendnew() not sufficiently tested. Solution: Add a few more test cases for extendnew(). (closes vim/vim#12075) https://github.com/vim/vim/commit/341f3876b34f47fdb1c82b0ad9bae448be73a220 --- src/nvim/testdir/test_listdict.vim | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/testdir/test_listdict.vim b/src/nvim/testdir/test_listdict.vim index fa22bad0cb..a6a1c736c4 100644 --- a/src/nvim/testdir/test_listdict.vim +++ b/src/nvim/testdir/test_listdict.vim @@ -886,11 +886,15 @@ func Test_listdict_extendnew() let l = [1, 2, 3] call assert_equal([1, 2, 3, 4, 5], extendnew(l, [4, 5])) call assert_equal([1, 2, 3], l) + lockvar l + call assert_equal([1, 2, 3, 4, 5], extendnew(l, [4, 5])) - " Test extend() with dictionaries. + " Test extendnew() with dictionaries. let d = {'a': {'b': 'B'}} call assert_equal({'a': {'b': 'B'}, 'c': 'cc'}, extendnew(d, {'c': 'cc'})) call assert_equal({'a': {'b': 'B'}}, d) + lockvar d + call assert_equal({'a': {'b': 'B'}, 'c': 'cc'}, extendnew(d, {'c': 'cc'})) endfunc func s:check_scope_dict(x, fixed) -- cgit From 7f424e2b65779c59fc0cac3cc7508ba2ec07f200 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 23 Feb 2023 18:29:36 +0100 Subject: feat(api): more fields in nvim_list_uis Problem: nvim_list_uis does not report all ":help ui-option" fields. Solution: Store ":help ui-option" fields on the `UI` object and update ui_array. --- src/nvim/api/ui.c | 16 ++++++++++------ src/nvim/ui.c | 9 +++++++++ src/nvim/ui.h | 8 ++++++++ src/nvim/ui_client.c | 2 ++ 4 files changed, 29 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index f6dee066dc..00fd2781ff 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -113,6 +113,10 @@ void remote_ui_disconnect(uint64_t channel_id) kv_destroy(data->call_buf); pmap_del(uint64_t)(&connected_uis, channel_id); ui_detach_impl(ui, channel_id); + + // Destroy `ui`. + XFREE_CLEAR(ui->term_name); + XFREE_CLEAR(ui->term_background); xfree(ui); } @@ -163,15 +167,9 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona UI *ui = xcalloc(1, sizeof(UI)); ui->width = (int)width; ui->height = (int)height; - ui->pum_nlines = 0; - ui->pum_pos = false; - ui->pum_width = 0.0; - ui->pum_height = 0.0; ui->pum_row = -1.0; ui->pum_col = -1.0; ui->rgb = true; - ui->override = false; - CLEAR_FIELD(ui->ui_ext); for (size_t i = 0; i < options.size; i++) { @@ -320,6 +318,7 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e return; }); set_tty_option("term", string_to_cstr(value.data.string)); + ui->term_name = string_to_cstr(value.data.string); return; } @@ -328,6 +327,7 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e return; }); t_colors = (int)value.data.integer; + ui->term_colors = (int)value.data.integer; return; } @@ -336,6 +336,7 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e return; }); set_tty_background(value.data.string.data); + ui->term_background = string_to_cstr(value.data.string); return; } @@ -351,6 +352,7 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e }); stdin_fd = (int)value.data.integer; + ui->stdin_fd = (int)value.data.integer; return; } @@ -359,6 +361,7 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e return; }); stdin_isatty = value.data.boolean; + ui->stdin_tty = value.data.boolean; return; } @@ -367,6 +370,7 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e return; }); stdout_isatty = value.data.boolean; + ui->stdout_tty = value.data.boolean; return; } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 73545441d3..6c95579b47 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -598,6 +598,15 @@ Array ui_array(void) PUT(info, "height", INTEGER_OBJ(ui->height)); PUT(info, "rgb", BOOLEAN_OBJ(ui->rgb)); PUT(info, "override", BOOLEAN_OBJ(ui->override)); + + // TUI fields. + PUT(info, "term_name", STRING_OBJ(cstr_to_string(ui->term_name))); + PUT(info, "term_background", STRING_OBJ(cstr_to_string(ui->term_background))); + PUT(info, "term_colors", INTEGER_OBJ(ui->term_colors)); + PUT(info, "stdin_fd", INTEGER_OBJ(ui->stdin_fd)); + PUT(info, "stdin_tty", BOOLEAN_OBJ(ui->stdin_tty)); + PUT(info, "stdout_tty", BOOLEAN_OBJ(ui->stdout_tty)); + for (UIExtension j = 0; j < kUIExtCount; j++) { if (ui_ext_names[j][0] != '_' || ui->ui_ext[j]) { PUT(info, ui_ext_names[j], BOOLEAN_OBJ(ui->ui_ext[j])); diff --git a/src/nvim/ui.h b/src/nvim/ui.h index e83f93eb07..c1377f56b4 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -103,6 +103,14 @@ struct ui_t { double pum_height; double pum_width; + // TUI fields. + char *term_name; + char *term_background; + int term_colors; + int stdin_fd; + bool stdin_tty; + bool stdout_tty; + // TODO(bfredl): integrate into struct! UIData data[1]; }; diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 8262293ec5..25ff63ea2d 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -1,6 +1,8 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +/// Nvim's own UI client, which attaches to a child or remote Nvim server. + #include #include #include -- cgit From ce597235a26839826de88ecd8b949ec54c310fbd Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 27 Feb 2023 16:31:05 +0100 Subject: feat(ui): restore has('gui_running') Problem: has('gui_running') is still common in the wild and our answer has changed over time, causing frustration. https://github.com/vimpostor/vim-tpipeline/commit/95a6ccbe9f33bc42dd4cee45731d8bc3fbcd92d1 Solution: Use stdin_tty/stdout_tty to decide if a UI is (not) a GUI. --- src/nvim/api/ui.c | 1 - src/nvim/eval/funcs.c | 4 +++- src/nvim/ui.c | 16 ++++++++++++++-- src/nvim/ui.h | 1 - 4 files changed, 17 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 00fd2781ff..a8f5d2e070 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -352,7 +352,6 @@ static void ui_set_option(UI *ui, bool init, String name, Object value, Error *e }); stdin_fd = (int)value.data.integer; - ui->stdin_fd = (int)value.data.integer; return; } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 1baf96e281..d97f7b6d35 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3228,7 +3228,9 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } if (!n) { - if (STRNICMP(name, "patch", 5) == 0) { + if (STRNICMP(name, "gui_running", 11) == 0) { + n = ui_gui_attached(); + } else if (STRNICMP(name, "patch", 5) == 0) { if (name[5] == '-' && strlen(name) >= 11 && ascii_isdigit(name[6]) diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 6c95579b47..ce1a57350a 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -134,6 +134,7 @@ void ui_free_all_mem(void) } #endif +/// Returns true if any `rgb=true` UI is attached. bool ui_rgb_attached(void) { if (!headless_mode && p_tgc) { @@ -147,6 +148,18 @@ bool ui_rgb_attached(void) return false; } +/// Returns true if a GUI is attached. +bool ui_gui_attached(void) +{ + for (size_t i = 0; i < ui_count; i++) { + bool tui = uis[i]->stdin_tty || uis[i]->stdout_tty; + if (!tui) { + return true; + } + } + return false; +} + /// Returns true if any UI requested `override=true`. bool ui_override(void) { @@ -599,11 +612,10 @@ Array ui_array(void) PUT(info, "rgb", BOOLEAN_OBJ(ui->rgb)); PUT(info, "override", BOOLEAN_OBJ(ui->override)); - // TUI fields. + // TUI fields. (`stdin_fd` is intentionally omitted.) PUT(info, "term_name", STRING_OBJ(cstr_to_string(ui->term_name))); PUT(info, "term_background", STRING_OBJ(cstr_to_string(ui->term_background))); PUT(info, "term_colors", INTEGER_OBJ(ui->term_colors)); - PUT(info, "stdin_fd", INTEGER_OBJ(ui->stdin_fd)); PUT(info, "stdin_tty", BOOLEAN_OBJ(ui->stdin_tty)); PUT(info, "stdout_tty", BOOLEAN_OBJ(ui->stdout_tty)); diff --git a/src/nvim/ui.h b/src/nvim/ui.h index c1377f56b4..dc0ccc73ea 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -107,7 +107,6 @@ struct ui_t { char *term_name; char *term_background; int term_colors; - int stdin_fd; bool stdin_tty; bool stdout_tty; -- cgit From 2a8e6a2f1a8e047a8efd84764d9a332bbd6ae96d Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Mon, 27 Feb 2023 15:08:31 -0500 Subject: vim-patch:9.0.1360: Cue files are not recognized (#22439) Problem: Cue files are not recognized. Solution: Add patterns for Cue files. (Amaan Qureshi, closes vim/vim#12067) https://github.com/vim/vim/commit/80c5b2c0f78b24e52c73bb162dda3ad85acd7e82 --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 96ab5620ec..148f8b6d42 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -140,6 +140,7 @@ let s:filename_checks = { \ 'csv': ['file.csv'], \ 'cucumber': ['file.feature'], \ 'cuda': ['file.cu', 'file.cuh'], + \ 'cue': ['file.cue'], \ 'cupl': ['file.pld'], \ 'cuplsim': ['file.si'], \ 'cvs': ['cvs123'], -- cgit From b50ee4a8dc4306e4be78ac33fb74b21dc6be5538 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Tue, 28 Feb 2023 07:09:12 +0900 Subject: fix(diff): adjust extmarks after diffput/diffget (#22440) Problem: on_bytes is not triggered by diffput/diffget if the line count does not change. --- src/nvim/diff.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/nvim/diff.c b/src/nvim/diff.c index c5b28822d0..289939b2ca 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -31,6 +31,7 @@ #include "nvim/ex_cmds.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" +#include "nvim/extmark.h" #include "nvim/extmark_defs.h" #include "nvim/fileio.h" #include "nvim/fold.h" @@ -3102,6 +3103,9 @@ static void diffgetput(const int addr_count, const int idx_cur, const int idx_fr if (buf_empty && (curbuf->b_ml.ml_line_count == 2)) { // Added the first line into an empty buffer, need to // delete the dummy empty line. + // This has a side effect of incrementing curbuf->deleted_bytes, + // which results in inaccurate reporting of the byte count of + // previous contents in buffer-update events. buf_empty = false; ml_delete((linenr_T)2, false); } @@ -3143,6 +3147,7 @@ static void diffgetput(const int addr_count, const int idx_cur, const int idx_fr } } } + extmark_adjust(curbuf, lnum, lnum + count - 1, (long)MAXLNUM, added, kExtmarkUndo); changed_lines(lnum, 0, lnum + count, added, true); if (did_free) { -- cgit From 8ecd129f1ef92aefea506247677f2693c5db9efd Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 27 Feb 2023 22:16:12 +0000 Subject: fix: address -Wmaybe-uninitialized warnings (#22436) --- src/nvim/ex_getln.c | 2 +- src/nvim/spellsuggest.c | 2 +- src/nvim/window.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index af26fe8a1c..a7f488458e 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2456,7 +2456,7 @@ static bool cmdpreview_may_show(CommandLineState *s) CpInfo cpinfo; bool icm_split = *p_icm == 's'; // inccommand=split buf_T *cmdpreview_buf; - win_T *cmdpreview_win; + win_T *cmdpreview_win = NULL; emsg_silent++; // Block error reporting as the command may be incomplete, // but still update v:errmsg diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c index d176a65228..ea2d5e6ff7 100644 --- a/src/nvim/spellsuggest.c +++ b/src/nvim/spellsuggest.c @@ -1209,7 +1209,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // The loop may take an indefinite amount of time. Break out after some // time. - proftime_T time_limit; + proftime_T time_limit = 0; if (spell_suggest_timeout > 0) { time_limit = profile_setlimit(spell_suggest_timeout); } diff --git a/src/nvim/window.c b/src/nvim/window.c index 0a4d36acb2..6a8d1cf740 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1899,8 +1899,8 @@ static void win_rotate(bool upwards, int count) } } - win_T *wp1; - win_T *wp2; + win_T *wp1 = NULL; + win_T *wp2 = NULL; while (count--) { if (upwards) { // first window becomes last window -- cgit From 2630341db65772e0a636c2a1cfbd6bba8ca9b28d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 07:19:03 +0800 Subject: fix(tui): avoid stack-use-after-scope with cursor color (#22435) --- src/nvim/tui/tui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index fee1d21672..48dc860ebd 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -1109,8 +1109,8 @@ void tui_set_mode(TUIData *tui, ModeShape mode) // Hopefully the user's default cursor color is inverse. unibi_out_ext(tui, tui->unibi_ext.reset_cursor_color); } else { + char hexbuf[8]; if (tui->set_cursor_color_as_str) { - char hexbuf[8]; snprintf(hexbuf, 7 + 1, "#%06x", aep.rgb_bg_color); UNIBI_SET_STR_VAR(tui->params[0], hexbuf); } else { -- cgit From 1b632e99f231baca8a640502a352aa68aee0568a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 08:26:00 +0800 Subject: vim-patch:9.0.1362: ml_get error when going to another tab (#22443) Problem: ml_get error when going to another tab. (Daniel J. Perry) Solution: Do not call update_topline() if "curwin" is invalid. (closes vim/vim#11907) https://github.com/vim/vim/commit/99ad3a8bb95c6f860545a050472b6181e33bac1a Co-authored-by: Bram Moolenaar --- src/nvim/testdir/test_tabpage.vim | 15 +++++++++++++++ src/nvim/window.c | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/testdir/test_tabpage.vim b/src/nvim/testdir/test_tabpage.vim index b97aa409d8..c20c798c49 100644 --- a/src/nvim/testdir/test_tabpage.vim +++ b/src/nvim/testdir/test_tabpage.vim @@ -846,4 +846,19 @@ func Test_lastused_tabpage() tabonly! endfunc +" this was giving ml_get errors +func Test_tabpage_last_line() + enew + call setline(1, repeat(['a'], &lines + 5)) + $ + tabnew + call setline(1, repeat(['b'], &lines + 20)) + $ + tabNext + call assert_equal('a', getline('.')) + + bwipe! + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/window.c b/src/nvim/window.c index 6a8d1cf740..38b7326363 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4813,7 +4813,7 @@ static void win_enter_ext(win_T *const wp, const int flags) // Might need to scroll the old window before switching, e.g., when the // cursor was moved. - if (*p_spk == 'c') { + if (*p_spk == 'c' && !curwin_invalid) { update_topline(curwin); } -- cgit From f113cba3ec127201f54094f9174b50ee3001fbee Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 08:49:02 +0800 Subject: refactor(getchar.c): change most char_u to uint8_t (#22444) --- src/nvim/ex_getln.c | 2 +- src/nvim/getchar.c | 97 ++++++++++++++++++++++++++--------------------------- src/nvim/globals.h | 4 +-- src/nvim/input.c | 16 ++++----- src/nvim/mapping.c | 10 +++--- 5 files changed, 63 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index a7f488458e..a3e0e650fa 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2693,7 +2693,7 @@ char *getcmdline_prompt(const int firstc, const char *const prompt, const int at /// Read the 'wildmode' option, fill wim_flags[]. int check_opt_wim(void) { - char_u new_wim_flags[4]; + uint8_t new_wim_flags[4]; int i; int idx = 0; diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 37840f8875..183fd5e19f 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -125,8 +125,8 @@ static int KeyNoremap = 0; // remapping flags // middle for typeahead and room for new characters (which needs to be 3 * // MAXMAPLEN for the Amiga). #define TYPELEN_INIT (5 * (MAXMAPLEN + 3)) -static char_u typebuf_init[TYPELEN_INIT]; // initial typebuf.tb_buf -static char_u noremapbuf_init[TYPELEN_INIT]; // initial typebuf.tb_noremap +static uint8_t typebuf_init[TYPELEN_INIT]; // initial typebuf.tb_buf +static uint8_t noremapbuf_init[TYPELEN_INIT]; // initial typebuf.tb_noremap static size_t last_recorded_len = 0; // number of last recorded chars @@ -337,14 +337,12 @@ static int read_readbuffers(int advance) static int read_readbuf(buffheader_T *buf, int advance) { - char_u c; - if (buf->bh_first.b_next == NULL) { // buffer is empty return NUL; } buffblock_T *const curr = buf->bh_first.b_next; - c = (char_u)curr->b_str[buf->bh_index]; + uint8_t c = (uint8_t)curr->b_str[buf->bh_index]; if (advance) { if (curr->b_str[++buf->bh_index] == NUL) { @@ -657,17 +655,17 @@ void stuffescaped(const char *arg, bool literally) static int read_redo(bool init, bool old_redo) { static buffblock_T *bp; - static char_u *p; + static uint8_t *p; int c; int n; - char_u buf[MB_MAXBYTES + 1]; + uint8_t buf[MB_MAXBYTES + 1]; if (init) { bp = old_redo ? old_redobuff.bh_first.b_next : redobuff.bh_first.b_next; if (bp == NULL) { return FAIL; } - p = (char_u *)bp->b_str; + p = (uint8_t *)bp->b_str; return OK; } if ((c = *p) == NUL) { @@ -688,9 +686,9 @@ static int read_redo(bool init, bool old_redo) } if (*++p == NUL && bp->b_next != NULL) { bp = bp->b_next; - p = (char_u *)bp->b_str; + p = (uint8_t *)bp->b_str; } - buf[i] = (char_u)c; + buf[i] = (uint8_t)c; if (i == n - 1) { // last byte of a character if (n != 1) { c = utf_ptr2char((char *)buf); @@ -854,7 +852,7 @@ bool noremap_keys(void) // return FAIL for failure, OK otherwise int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent) { - char_u *s1, *s2; + uint8_t *s1, *s2; int addlen; int val; int nrm; @@ -975,11 +973,11 @@ int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent) /// @return the length of what was inserted int ins_char_typebuf(int c, int modifiers) { - char_u buf[MB_MAXBYTES * 3 + 4]; - unsigned int len = special_to_buf(c, modifiers, true, (char *)buf); + char buf[MB_MAXBYTES * 3 + 4]; + unsigned int len = special_to_buf(c, modifiers, true, buf); assert(len < sizeof(buf)); buf[len] = NUL; - (void)ins_typebuf((char *)buf, KeyNoremap, 0, !KeyTyped, cmd_silent); + (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent); return (int)len; } @@ -1081,11 +1079,11 @@ void del_typebuf(int len, int offset) // Write typed characters to script file. // If recording is on put the character in the recordbuffer. -static void gotchars(const char_u *chars, size_t len) +static void gotchars(const uint8_t *chars, size_t len) FUNC_ATTR_NONNULL_ALL { - const char_u *s = chars; - static char_u buf[4] = { 0 }; + const uint8_t *s = chars; + static uint8_t buf[4] = { 0 }; static size_t buflen = 0; size_t todo = len; @@ -1404,7 +1402,7 @@ int merge_modifiers(int c_arg, int *modifiers) int vgetc(void) { int c; - char_u buf[MB_MAXBYTES + 1]; + uint8_t buf[MB_MAXBYTES + 1]; // Do garbage collection when garbagecollect() was called previously and // we are now at the toplevel. @@ -1548,9 +1546,9 @@ int vgetc(void) // Note: This will loop until enough bytes are received! if ((n = MB_BYTE2LEN_CHECK(c)) > 1) { no_mapping++; - buf[0] = (char_u)c; + buf[0] = (uint8_t)c; for (int i = 1; i < n; i++) { - buf[i] = (char_u)vgetorpeek(true); + buf[i] = (uint8_t)vgetorpeek(true); if (buf[i] == K_SPECIAL) { // Must be a K_SPECIAL - KS_SPECIAL - KE_FILLER sequence, // which represents a K_SPECIAL (0x80). @@ -1815,7 +1813,7 @@ typedef enum { /// Put "string[new_slen]" in typebuf. /// Remove "slen" bytes. /// @return FAIL for error, OK otherwise. -static int put_string_in_typebuf(int offset, int slen, char_u *string, int new_slen) +static int put_string_in_typebuf(int offset, int slen, uint8_t *string, int new_slen) { int extra = new_slen - slen; string[new_slen] = NUL; @@ -1838,7 +1836,7 @@ static int put_string_in_typebuf(int offset, int slen, char_u *string, int new_s /// in Insert mode completion. This includes the form with a CTRL modifier. static bool at_ins_compl_key(void) { - char_u *p = typebuf.tb_buf + typebuf.tb_off; + uint8_t *p = typebuf.tb_buf + typebuf.tb_off; int c = *p; if (typebuf.tb_len > 3 && c == K_SPECIAL && p[1] == KS_MODIFIER && (p[2] & MOD_MASK_CTRL)) { @@ -1858,7 +1856,7 @@ static int check_simplify_modifier(int max_offset) if (offset + 3 >= typebuf.tb_len) { break; } - char_u *tp = typebuf.tb_buf + typebuf.tb_off + offset; + uint8_t *tp = typebuf.tb_buf + typebuf.tb_off + offset; if (tp[0] == K_SPECIAL && tp[1] == KS_MODIFIER) { // A modifier was not used for a mapping, apply it to ASCII // keys. Shift would already have been applied. @@ -1874,12 +1872,12 @@ static int check_simplify_modifier(int max_offset) vgetc_char = c; vgetc_mod_mask = tp[2]; } - char_u new_string[MB_MAXBYTES]; + uint8_t new_string[MB_MAXBYTES]; int len; if (IS_SPECIAL(new_c)) { new_string[0] = K_SPECIAL; - new_string[1] = (char_u)K_SECOND(new_c); - new_string[2] = (char_u)K_THIRD(new_c); + new_string[1] = (uint8_t)K_SECOND(new_c); + new_string[2] = (uint8_t)K_THIRD(new_c); len = 3; } else { len = utf_char2bytes(new_c, (char *)new_string); @@ -1889,7 +1887,7 @@ static int check_simplify_modifier(int max_offset) return -1; } } else { - tp[2] = (char_u)modifier; + tp[2] = (uint8_t)modifier; if (put_string_in_typebuf(offset + 3, 1, new_string, len) == FAIL) { return -1; } @@ -2010,10 +2008,10 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) // Don't allow mapping the first byte(s) of a multi-byte char. // Happens when mapping and then changing 'encoding'. // Beware that 0x80 is escaped. - char_u *p1 = (char_u *)mp->m_keys; - char_u *p2 = (char_u *)mb_unescape((const char **)&p1); + char *p1 = mp->m_keys; + char *p2 = (char *)mb_unescape((const char **)&p1); - if (p2 != NULL && MB_BYTE2LEN(tb_c1) > utfc_ptr2len((char *)p2)) { + if (p2 != NULL && MB_BYTE2LEN(tb_c1) > utfc_ptr2len(p2)) { mlen = 0; } @@ -2077,7 +2075,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) // Check for match with 'pastetoggle' if (*p_pt != NUL && mp == NULL && (State & (MODE_INSERT | MODE_NORMAL))) { - bool match = typebuf_match_len((char_u *)p_pt, &mlen); + bool match = typebuf_match_len((uint8_t *)p_pt, &mlen); if (match) { // write chars to script file(s) if (mlen > typebuf.tb_maplen) { @@ -2267,7 +2265,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) // If this is a LANGMAP mapping, then we didn't record the keys // at the start of the function and have to record them now. if (keylen > typebuf.tb_maplen && (mp->m_mode & MODE_LANGMAP) != 0) { - gotchars((char_u *)map_str, strlen(map_str)); + gotchars((uint8_t *)map_str, strlen(map_str)); } if (save_m_noremap != REMAP_YES) { @@ -2442,7 +2440,7 @@ static int vgetorpeek(bool advance) if (advance) { // Also record this character, it might be needed to // get out of Insert mode. - *typebuf.tb_buf = (char_u)c; + *typebuf.tb_buf = (uint8_t)c; gotchars(typebuf.tb_buf, 1); } cmd_silent = false; @@ -2515,7 +2513,7 @@ static int vgetorpeek(bool advance) // move cursor left, if possible if (curwin->w_cursor.col != 0) { colnr_T col = 0; - char_u *ptr; + char *ptr; if (curwin->w_wcol > 0) { // After auto-indenting and no text is following, // we are expecting to truncate the trailing @@ -2524,11 +2522,10 @@ static int vgetorpeek(bool advance) if (did_ai && *skipwhite(get_cursor_line_ptr() + curwin->w_cursor.col) == NUL) { curwin->w_wcol = 0; - ptr = (char_u *)get_cursor_line_ptr(); + ptr = get_cursor_line_ptr(); chartabsize_T cts; - init_chartabsize_arg(&cts, curwin, - curwin->w_cursor.lnum, 0, (char *)ptr, (char *)ptr); - while ((char_u *)cts.cts_ptr < ptr + curwin->w_cursor.col) { + init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum, 0, ptr, ptr); + while (cts.cts_ptr < ptr + curwin->w_cursor.col) { if (!ascii_iswhite(*cts.cts_ptr)) { curwin->w_wcol = cts.cts_vcol; } @@ -2554,9 +2551,9 @@ static int vgetorpeek(bool advance) if (col > 0 && curwin->w_wcol > 0) { // Correct when the cursor is on the right halve // of a double-wide character. - ptr = (char_u *)get_cursor_line_ptr(); - col -= utf_head_off((char *)ptr, (char *)ptr + col); - if (utf_ptr2cells((char *)ptr + col) > 1) { + ptr = get_cursor_line_ptr(); + col -= utf_head_off(ptr, ptr + col); + if (utf_ptr2cells(ptr + col) > 1) { curwin->w_wcol--; } } @@ -2760,7 +2757,7 @@ static int vgetorpeek(bool advance) } if (timedout && c == ESC) { - char_u nop_buf[3]; + uint8_t nop_buf[3]; // When recording there will be no timeout. Add a after the ESC // to avoid that it forms a key code with following characters. @@ -2798,7 +2795,7 @@ static int vgetorpeek(bool advance) /// Return -1 when end of input script reached. /// /// @param wait_time milliseconds -int inchar(char_u *buf, int maxlen, long wait_time) +int inchar(uint8_t *buf, int maxlen, long wait_time) { int len = 0; // Init for GCC. int retesc = false; // Return ESC with gotint. @@ -2837,7 +2834,7 @@ int inchar(char_u *buf, int maxlen, long wait_time) return -1; } } else { - buf[0] = (char_u)script_char; + buf[0] = (uint8_t)script_char; len = 1; } } @@ -2851,7 +2848,7 @@ int inchar(char_u *buf, int maxlen, long wait_time) // and buf may be pointing inside typebuf.tb_buf[]. if (got_int) { #define DUM_LEN (MAXMAPLEN * 3 + 3) - char_u dum[DUM_LEN + 1]; + uint8_t dum[DUM_LEN + 1]; for (;;) { len = os_inchar(dum, DUM_LEN, 0L, 0, NULL); @@ -2884,13 +2881,13 @@ int inchar(char_u *buf, int maxlen, long wait_time) typebuf.tb_change_cnt = 1; } - return fix_input_buffer((char *)buf, len); + return fix_input_buffer(buf, len); } // Fix typed characters for use by vgetc() and check_termcode(). // "buf[]" must have room to triple the number of bytes! // Returns the new length. -int fix_input_buffer(char *buf, int len) +int fix_input_buffer(uint8_t *buf, int len) FUNC_ATTR_NONNULL_ALL { if (!using_script()) { @@ -2901,7 +2898,7 @@ int fix_input_buffer(char *buf, int len) } // Reading from script, need to process special bytes - char_u *p = (char_u *)buf; + uint8_t *p = buf; // Two characters are special: NUL and K_SPECIAL. // Replace NUL by K_SPECIAL KS_ZERO KE_FILLER @@ -2911,8 +2908,8 @@ int fix_input_buffer(char *buf, int len) || (p[0] == K_SPECIAL && (i < 2 || p[1] != KS_EXTRA))) { memmove(p + 3, p + 1, (size_t)i); - p[2] = (char_u)K_THIRD(p[0]); - p[1] = (char_u)K_SECOND(p[0]); + p[2] = (uint8_t)K_THIRD(p[0]); + p[1] = (uint8_t)K_SECOND(p[0]); p[0] = K_SPECIAL; p += 2; len += 2; diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 94448eb7d7..f3bfbdabf6 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -789,7 +789,7 @@ EXTERN int redir_reg INIT(= 0); // message redirection register EXTERN int redir_vname INIT(= 0); // message redirection variable EXTERN garray_T *capture_ga INIT(= NULL); // captured output for execute() -EXTERN char_u langmap_mapchar[256]; // mapping for language keys +EXTERN uint8_t langmap_mapchar[256]; // mapping for language keys EXTERN int save_p_ls INIT(= -1); // Save 'laststatus' setting EXTERN int save_p_wmh INIT(= -1); // Save 'winminheight' setting @@ -832,7 +832,7 @@ EXTERN long sub_nsubs; // total number of substitutions EXTERN linenr_T sub_nlines; // total number of lines changed // table to store parsed 'wildmode' -EXTERN char_u wim_flags[4]; +EXTERN uint8_t wim_flags[4]; // whether titlestring and iconstring contains statusline syntax #define STL_IN_ICON 1 diff --git a/src/nvim/input.c b/src/nvim/input.c index 5b9b866778..fa55c02a24 100644 --- a/src/nvim/input.c +++ b/src/nvim/input.c @@ -86,7 +86,7 @@ int ask_yesno(const char *const str, const bool direct) /// Translates the interrupt character for unix to ESC. int get_keystroke(MultiQueue *events) { - char *buf = NULL; + uint8_t *buf = NULL; int buflen = 150; int len = 0; int n; @@ -112,7 +112,7 @@ int get_keystroke(MultiQueue *events) // First time: blocking wait. Second time: wait up to 100ms for a // terminal code to complete. - n = os_inchar((uint8_t *)buf + len, maxlen, len == 0 ? -1L : 100L, 0, events); + n = os_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0, events); if (n > 0) { // Replace zero and K_SPECIAL by a special key code. n = fix_input_buffer(buf + len, n); @@ -127,14 +127,14 @@ int get_keystroke(MultiQueue *events) } // Handle modifier and/or special key code. - n = (uint8_t)buf[0]; + n = buf[0]; if (n == K_SPECIAL) { - n = TO_SPECIAL((uint8_t)buf[1], (uint8_t)buf[2]); - if ((uint8_t)buf[1] == KS_MODIFIER + n = TO_SPECIAL(buf[1], buf[2]); + if (buf[1] == KS_MODIFIER || n == K_IGNORE || (is_mouse_key(n) && n != K_LEFTMOUSE)) { - if ((uint8_t)buf[1] == KS_MODIFIER) { - mod_mask = (uint8_t)buf[2]; + if (buf[1] == KS_MODIFIER) { + mod_mask = buf[2]; } len -= 3; if (len > 0) { @@ -149,7 +149,7 @@ int get_keystroke(MultiQueue *events) continue; } buf[len >= buflen ? buflen - 1 : len] = NUL; - n = utf_ptr2char(buf); + n = utf_ptr2char((char *)buf); break; } xfree(buf); diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 3840a00981..60524b9fb7 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -323,7 +323,7 @@ static void set_maparg_rhs(const char *const orig_rhs, const size_t orig_rhs_len mapargs->orig_rhs_len = 0; // stores ref_no in map_str mapargs->rhs_len = (size_t)vim_snprintf(S_LEN(tmp_buf), "%c%c%c%d\r", K_SPECIAL, - (char_u)KS_EXTRA, KE_LUA, rhs_lua); + KS_EXTRA, KE_LUA, rhs_lua); mapargs->rhs = xstrdup(tmp_buf); } } @@ -1879,7 +1879,7 @@ int makemap(FILE *fd, buf_T *buf) // return FAIL for failure, OK otherwise int put_escstr(FILE *fd, char *strstart, int what) { - char_u *str = (char_u *)strstart; + uint8_t *str = (uint8_t *)strstart; int c; // :map xx @@ -1956,7 +1956,7 @@ int put_escstr(FILE *fd, char *strstart, int what) } } else if (c < ' ' || c > '~' || c == '|' || (what == 0 && c == ' ') - || (what == 1 && str == (char_u *)strstart && c == ' ') + || (what == 1 && str == (uint8_t *)strstart && c == ' ') || (what != 2 && c == '<')) { if (putc(Ctrl_V, fd) < 0) { return FAIL; @@ -2383,7 +2383,7 @@ int langmap_adjust_mb(int c) void langmap_init(void) { for (int i = 0; i < 256; i++) { - langmap_mapchar[i] = (char_u)i; // we init with a one-to-one map + langmap_mapchar[i] = (uint8_t)i; // we init with a one-to-one map } ga_init(&langmap_mapga, sizeof(langmap_entry_T), 8); } @@ -2447,7 +2447,7 @@ void langmap_set(void) langmap_set_entry(from, to); } else { assert(to <= UCHAR_MAX); - langmap_mapchar[from & 255] = (char_u)to; + langmap_mapchar[from & 255] = (uint8_t)to; } // Advance to next pair -- cgit From 9a271f6afd7a9b1c17d694b57ee1f489496000aa Mon Sep 17 00:00:00 2001 From: luukvbaal <31730729+luukvbaal@users.noreply.github.com> Date: Tue, 28 Feb 2023 03:19:58 +0100 Subject: fix(column): cmdwin cursor is offset with 'statuscolumn' (#22445) --- src/nvim/drawline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index cd815da458..bf8649afe0 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1199,7 +1199,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, statuscol.draw = true; statuscol.sattrs = sattrs; statuscol.foldinfo = foldinfo; - statuscol.width = win_col_off(wp); + statuscol.width = win_col_off(wp) - (cmdwin_type != 0 && wp == curwin); statuscol.use_cul = use_cursor_line_sign(wp, lnum); statuscol.sign_cul_attr = statuscol.use_cul ? sign_cul_attr : 0; statuscol.num_attr = sign_num_attr ? sign_num_attr -- cgit From adfa55ba99febaa1eb5ebe1800ec5f94c4b4b664 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Feb 2023 14:36:20 +0800 Subject: vim-patch:8.2.2757: Vim9: blob tests for legacy and Vim9 script are separate Problem: Vim9: blob tests for legacy and Vim9 script are separate. Solution: Add CheckLegacyAndVim9Success(). Make blob index assign work. https://github.com/vim/vim/commit/68452177ca4cda4a9d5f93892e437447cf9404c8 Co-authored-by: Bram Moolenaar --- src/nvim/eval.c | 10 +--- src/nvim/eval/typval.c | 16 +++++ src/nvim/testdir/test_blob.vim | 130 ++++++++++++++++++++++------------------- 3 files changed, 87 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 841588d4c3..ebd13034d7 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1620,17 +1620,9 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool lp->ll_n2 = tv_blob_len(lp->ll_blob) - 1; } - if (lp->ll_n2 - lp->ll_n1 + 1 != tv_blob_len(rettv->vval.v_blob)) { - emsg(_("E972: Blob value does not have the right number of bytes")); + if (tv_blob_set_range(lp->ll_blob, lp->ll_n1, lp->ll_n2, rettv) == FAIL) { return; } - if (lp->ll_empty2) { - lp->ll_n2 = tv_blob_len(lp->ll_blob); - } - - for (int il = (int)lp->ll_n1, ir = 0; il <= (int)lp->ll_n2; il++) { - tv_blob_set(lp->ll_blob, il, tv_blob_get(rettv->vval.v_blob, ir++)); - } } else { bool error = false; const char val = (char)tv_get_number_chk(rettv, &error); diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 0a30cdb62e..476faafb77 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2710,6 +2710,22 @@ bool tv_blob_equal(const blob_T *const b1, const blob_T *const b2) return true; } +/// Set bytes "n1" to "n2" (inclusive) in "dest" to the value of "src". +/// Caller must make sure "src" is a blob. +/// Returns FAIL if the number of bytes does not match. +int tv_blob_set_range(blob_T *dest, long n1, long n2, typval_T *src) +{ + if (n2 - n1 + 1 != tv_blob_len(src->vval.v_blob)) { + emsg(_("E972: Blob value does not have the right number of bytes")); + return FAIL; + } + + for (int il = (int)n1, ir = 0; il <= (int)n2; il++) { + tv_blob_set(dest, il, tv_blob_get(src->vval.v_blob, ir++)); + } + return OK; +} + /// "remove({blob})" function void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) { diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index cf03d2011c..6c3558e273 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -1,5 +1,7 @@ " Tests for the Blob types +source vim9.vim + func TearDown() " Run garbage collection after every test call test_garbagecollect_now() @@ -9,73 +11,81 @@ endfunc " Blob creation from constant func Test_blob_create() - let b = 0zDEADBEEF - call assert_equal(v:t_blob, type(b)) - call assert_equal(4, len(b)) - call assert_equal(0xDE, b[0]) - call assert_equal(0xAD, b[1]) - call assert_equal(0xBE, b[2]) - call assert_equal(0xEF, b[3]) - call assert_fails('let x = b[4]') - - call assert_equal(0xDE, get(b, 0)) - call assert_equal(0xEF, get(b, 3)) - - call assert_fails('let b = 0z1', 'E973:') - call assert_fails('let b = 0z1x', 'E973:') - call assert_fails('let b = 0z12345', 'E973:') - - call assert_equal(0z, v:_null_blob) - - let b = 0z001122.33445566.778899.aabbcc.dd - call assert_equal(0z00112233445566778899aabbccdd, b) - call assert_fails('let b = 0z1.1') - call assert_fails('let b = 0z.') - call assert_fails('let b = 0z001122.') - call assert_fails('call get("", 1)', 'E896:') - call assert_equal(0, len(v:_null_blob)) + let lines =<< trim END + VAR b = 0zDEADBEEF + call assert_equal(v:t_blob, type(b)) + call assert_equal(4, len(b)) + call assert_equal(0xDE, b[0]) + call assert_equal(0xAD, b[1]) + call assert_equal(0xBE, b[2]) + call assert_equal(0xEF, b[3]) + call assert_fails('VAR x = b[4]') + + call assert_equal(0xDE, get(b, 0)) + call assert_equal(0xEF, get(b, 3)) + + call assert_fails('VAR b = 0z1', 'E973:') + call assert_fails('VAR b = 0z1x', 'E973:') + call assert_fails('VAR b = 0z12345', 'E973:') + + call assert_equal(0z, v:_null_blob) + + LET b = 0z001122.33445566.778899.aabbcc.dd + call assert_equal(0z00112233445566778899aabbccdd, b) + call assert_fails('VAR b = 0z1.1') + call assert_fails('VAR b = 0z.') + call assert_fails('VAR b = 0z001122.') + call assert_fails('call get("", 1)', 'E896:') + call assert_equal(0, len(v:_null_blob)) + END + call CheckLegacyAndVim9Success(lines) endfunc " assignment to a blob func Test_blob_assign() + let lines =<< trim END + VAR b = 0zDEADBEEF + VAR b2 = b[1 : 2] + call assert_equal(0zADBE, b2) + + VAR bcopy = b[:] + call assert_equal(b, bcopy) + call assert_false(b is bcopy) + + LET b = 0zDEADBEEF + LET b2 = b + call assert_true(b is b2) + LET b[:] = 0z11223344 + call assert_equal(0z11223344, b) + call assert_equal(0z11223344, b2) + call assert_true(b is b2) + + LET b = 0zDEADBEEF + LET b[3 :] = 0z66 + call assert_equal(0zDEADBE66, b) + LET b[: 1] = 0z8899 + call assert_equal(0z8899BE66, b) + + LET b = 0zDEADBEEF + LET b += 0z99 + call assert_equal(0zDEADBEEF99, b) + + VAR l = [0z12] + VAR m = deepcopy(l) + LET m[0] = 0z34 #" E742 or E741 should not occur. + END + call CheckLegacyAndVim9Success(lines) + + " TODO: move to above once it works let b = 0zDEADBEEF - let b2 = b[1:2] - call assert_equal(0zADBE, b2) - - let bcopy = b[:] - call assert_equal(b, bcopy) - call assert_false(b is bcopy) - - let b = 0zDEADBEEF - let b2 = b - call assert_true(b is b2) - let b[:] = 0z11223344 - call assert_equal(0z11223344, b) - call assert_equal(0z11223344, b2) - call assert_true(b is b2) + call assert_fails('let b[2 : 3] = 0z112233', 'E972:') + call assert_fails('let b[2 : 3] = 0z11', 'E972:') + call assert_fails('let b[3 : 2] = 0z', 'E979:') - let b = 0zDEADBEEF - let b[3:] = 0z66 - call assert_equal(0zDEADBE66, b) - let b[:1] = 0z8899 - call assert_equal(0z8899BE66, b) - - call assert_fails('let b[2:3] = 0z112233', 'E972:') - call assert_fails('let b[2:3] = 0z11', 'E972:') - call assert_fails('let b[3:2] = 0z', 'E979:') - - let b = 0zDEADBEEF - let b += 0z99 - call assert_equal(0zDEADBEEF99, b) - - call assert_fails('let b .= 0z33', 'E734:') - call assert_fails('let b .= "xx"', 'E734:') + call assert_fails('let b ..= 0z33', 'E734:') + call assert_fails('let b ..= "xx"', 'E734:') call assert_fails('let b += "xx"', 'E734:') - call assert_fails('let b[1:1] .= 0z55', 'E734:') - - let l = [0z12] - let m = deepcopy(l) - let m[0] = 0z34 " E742 or E741 should not occur. + call assert_fails('let b[1 : 1] ..= 0z55', 'E734:') endfunc func Test_blob_get_range() -- cgit From c554e989786be30fa306efcd7e504ba7cb97cb3b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 13:30:08 +0800 Subject: vim-patch:8.2.2765: Vim9: not all blob operations work Problem: Vim9: not all blob operations work. Solution: Run more tests also with Vim9 script and :def functions. Fix what doesn't work. https://github.com/vim/vim/commit/0e3ff1919603ee4c4a347fdf761dbdbdeb068015 Co-authored-by: Bram Moolenaar --- src/nvim/eval.c | 11 ++------- src/nvim/eval/typval.c | 24 ++++++++++++++++++++ src/nvim/testdir/test_blob.vim | 51 +++++++++++++++++++++++++++++++++--------- src/nvim/testdir/vim9.vim | 4 ++-- 4 files changed, 69 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index ebd13034d7..9fa2eca1da 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1498,21 +1498,14 @@ char *get_lval(char *const name, typval_T *const rettv, lval_T *const lp, const tv_clear(&var1); const int bloblen = tv_blob_len(lp->ll_tv->vval.v_blob); - if (lp->ll_n1 < 0 || lp->ll_n1 > bloblen - || (lp->ll_range && lp->ll_n1 == bloblen)) { - if (!quiet) { - semsg(_(e_blobidx), (int64_t)lp->ll_n1); - } + if (tv_blob_check_index(bloblen, lp->ll_n1, lp->ll_range, quiet) == FAIL) { tv_clear(&var2); return NULL; } if (lp->ll_range && !lp->ll_empty2) { lp->ll_n2 = (long)tv_get_number(&var2); tv_clear(&var2); - if (lp->ll_n2 < 0 || lp->ll_n2 >= bloblen || lp->ll_n2 < lp->ll_n1) { - if (!quiet) { - semsg(_(e_blobidx), (int64_t)lp->ll_n2); - } + if (tv_blob_check_range(bloblen, lp->ll_n1, lp->ll_n2, quiet) == FAIL) { return NULL; } } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 476faafb77..878b85c49c 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2710,6 +2710,30 @@ bool tv_blob_equal(const blob_T *const b1, const blob_T *const b2) return true; } +/// Check if "n1" is a valid index for a blob with length "bloblen". +int tv_blob_check_index(int bloblen, varnumber_T n1, int is_range, bool quiet) +{ + if (n1 < 0 || n1 > bloblen) { + if (!quiet) { + semsg(_(e_blobidx), n1); + } + return FAIL; + } + return OK; +} + +/// Check if "n1"-"n2" is a valid range for a blob with length "bloblen". +int tv_blob_check_range(int bloblen, varnumber_T n1, varnumber_T n2, bool quiet) +{ + if (n2 < 0 || n2 >= bloblen || n2 < n1) { + if (!quiet) { + semsg(_(e_blobidx), n2); + } + return FAIL; + } + return OK; +} + /// Set bytes "n1" to "n2" (inclusive) in "dest" to the value of "src". /// Caller must make sure "src" is a blob. /// Returns FAIL if the number of bytes does not match. diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index 6c3558e273..86e16b372b 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -76,16 +76,47 @@ func Test_blob_assign() END call CheckLegacyAndVim9Success(lines) - " TODO: move to above once it works - let b = 0zDEADBEEF - call assert_fails('let b[2 : 3] = 0z112233', 'E972:') - call assert_fails('let b[2 : 3] = 0z11', 'E972:') - call assert_fails('let b[3 : 2] = 0z', 'E979:') - - call assert_fails('let b ..= 0z33', 'E734:') - call assert_fails('let b ..= "xx"', 'E734:') - call assert_fails('let b += "xx"', 'E734:') - call assert_fails('let b[1 : 1] ..= 0z55', 'E734:') + let lines =<< trim END + VAR b = 0zDEADBEEF + LET b[2 : 3] = 0z112233 + END + call CheckLegacyAndVim9Failure(lines, 'E972:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + LET b[2 : 3] = 0z11 + END + call CheckLegacyAndVim9Failure(lines, 'E972:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + LET b[3 : 2] = 0z + END + call CheckLegacyAndVim9Failure(lines, 'E979:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + LET b ..= 0z33 + END + call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1019:', 'E734:']) + + let lines =<< trim END + VAR b = 0zDEADBEEF + LET b ..= "xx" + END + call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1019:', 'E734:']) + + let lines =<< trim END + VAR b = 0zDEADBEEF + LET b += "xx" + END + call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:']) + + let lines =<< trim END + VAR b = 0zDEADBEEF + LET b[1 : 1] ..= 0z55 + END + call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1183:', 'E734:']) endfunc func Test_blob_get_range() diff --git a/src/nvim/testdir/vim9.vim b/src/nvim/testdir/vim9.vim index 3c0ff2b2dd..e1343d51f1 100644 --- a/src/nvim/testdir/vim9.vim +++ b/src/nvim/testdir/vim9.vim @@ -98,9 +98,9 @@ endfunc " Use ' #"' for a comment func CheckLegacyAndVim9Failure(lines, error) if type(a:error) == type('string') - let legacyError = error + let legacyError = a:error else - let legacyError = error[0] + let legacyError = a:error[0] endif let legacylines = a:lines->deepcopy()->map({_, v -> -- cgit From 1f1227f12b69616484cc0f8b49d555df4a94678b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 13:39:59 +0800 Subject: vim-patch:8.2.2767: compiler warning for unused argument Problem: Compiler warning for unused argument. Solution: Remove the argument. https://github.com/vim/vim/commit/bd6406f15db210b78fa24dece3bd021a7ac085dc Co-authored-by: Bram Moolenaar --- src/nvim/eval.c | 2 +- src/nvim/eval/typval.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 9fa2eca1da..cce7b9a13c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1498,7 +1498,7 @@ char *get_lval(char *const name, typval_T *const rettv, lval_T *const lp, const tv_clear(&var1); const int bloblen = tv_blob_len(lp->ll_tv->vval.v_blob); - if (tv_blob_check_index(bloblen, lp->ll_n1, lp->ll_range, quiet) == FAIL) { + if (tv_blob_check_index(bloblen, lp->ll_n1, quiet) == FAIL) { tv_clear(&var2); return NULL; } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 878b85c49c..7e94e03823 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2711,7 +2711,7 @@ bool tv_blob_equal(const blob_T *const b1, const blob_T *const b2) } /// Check if "n1" is a valid index for a blob with length "bloblen". -int tv_blob_check_index(int bloblen, varnumber_T n1, int is_range, bool quiet) +int tv_blob_check_index(int bloblen, varnumber_T n1, bool quiet) { if (n1 < 0 || n1 > bloblen) { if (!quiet) { -- cgit From 99faac86444a7f4c0790d150307c67d98db7c62e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 15:05:40 +0800 Subject: vim-patch:8.2.1890: Vim9: strange error for subtracting from a list Problem: Vim9: strange error for subtracting from a list. Solution: Check getting a number, not a string. (closes vim/vim#7167) https://github.com/vim/vim/commit/081db1a66d17e46ac3b03b7514f11a004a35009a Cherry-pick eval_addblob() and eval_addlist() from patch 8.2.0149. Co-authored-by: Bram Moolenaar --- src/nvim/eval.c | 66 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index cce7b9a13c..f8110aa545 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -2556,6 +2556,39 @@ static int eval4(char **arg, typval_T *rettv, int evaluate) return OK; } +/// Make a copy of blob "tv1" and append blob "tv2". +static void eval_addblob(typval_T *tv1, typval_T *tv2) +{ + const blob_T *const b1 = tv1->vval.v_blob; + const blob_T *const b2 = tv2->vval.v_blob; + blob_T *const b = tv_blob_alloc(); + + for (int i = 0; i < tv_blob_len(b1); i++) { + ga_append(&b->bv_ga, tv_blob_get(b1, i)); + } + for (int i = 0; i < tv_blob_len(b2); i++) { + ga_append(&b->bv_ga, tv_blob_get(b2, i)); + } + + tv_clear(tv1); + tv_blob_set_ret(tv1, b); +} + +/// Make a copy of list "tv1" and append list "tv2". +static int eval_addlist(typval_T *tv1, typval_T *tv2) +{ + typval_T var3; + // Concatenate Lists. + if (tv_list_concat(tv1->vval.v_list, tv2->vval.v_list, &var3) == FAIL) { + tv_clear(tv1); + tv_clear(tv2); + return FAIL; + } + tv_clear(tv1); + *tv1 = var3; + return OK; +} + /// Handle fourth level expression: /// + number addition, concatenation of list or blob /// - number subtraction @@ -2569,7 +2602,6 @@ static int eval4(char **arg, typval_T *rettv, int evaluate) static int eval5(char **arg, typval_T *rettv, int evaluate) { typval_T var2; - typval_T var3; varnumber_T n1, n2; float_T f1 = 0, f2 = 0; char *p; @@ -2587,7 +2619,7 @@ static int eval5(char **arg, typval_T *rettv, int evaluate) } if ((op != '+' || (rettv->v_type != VAR_LIST && rettv->v_type != VAR_BLOB)) - && (op == '.' || rettv->v_type != VAR_FLOAT)) { + && (op == '.' || rettv->v_type != VAR_FLOAT) && evaluate) { // For "list + ...", an illegal use of the first operand as // a number cannot be determined before evaluating the 2nd // operand: if this is also a list, all is ok. @@ -2595,7 +2627,7 @@ static int eval5(char **arg, typval_T *rettv, int evaluate) // we know that the first operand needs to be a string or number // without evaluating the 2nd operand. So check before to avoid // side effects after an error. - if (evaluate && !tv_check_str(rettv)) { + if ((op == '.' && !tv_check_str(rettv)) || (op != '.' && !tv_check_num(rettv))) { tv_clear(rettv); return FAIL; } @@ -2628,32 +2660,12 @@ static int eval5(char **arg, typval_T *rettv, int evaluate) tv_clear(rettv); rettv->v_type = VAR_STRING; rettv->vval.v_string = p; - } else if (op == '+' && rettv->v_type == VAR_BLOB - && var2.v_type == VAR_BLOB) { - const blob_T *const b1 = rettv->vval.v_blob; - const blob_T *const b2 = var2.vval.v_blob; - blob_T *const b = tv_blob_alloc(); - - for (int i = 0; i < tv_blob_len(b1); i++) { - ga_append(&b->bv_ga, tv_blob_get(b1, i)); - } - for (int i = 0; i < tv_blob_len(b2); i++) { - ga_append(&b->bv_ga, tv_blob_get(b2, i)); - } - - tv_clear(rettv); - tv_blob_set_ret(rettv, b); - } else if (op == '+' && rettv->v_type == VAR_LIST - && var2.v_type == VAR_LIST) { - // Concatenate Lists. - if (tv_list_concat(rettv->vval.v_list, var2.vval.v_list, &var3) - == FAIL) { - tv_clear(rettv); - tv_clear(&var2); + } else if (op == '+' && rettv->v_type == VAR_BLOB && var2.v_type == VAR_BLOB) { + eval_addblob(rettv, &var2); + } else if (op == '+' && rettv->v_type == VAR_LIST && var2.v_type == VAR_LIST) { + if (eval_addlist(rettv, &var2) == FAIL) { return FAIL; } - tv_clear(rettv); - *rettv = var3; } else { bool error = false; -- cgit From 761a559dbfed99e588d7f306c89331907b2d5a92 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 14:27:47 +0800 Subject: vim-patch:8.2.2777: Vim9: blob operations not tested in all ways Problem: Vim9: blob operations not tested in all ways. Solution: Run tests with CheckLegacyAndVim9Success(). Make blob assign with index work. https://github.com/vim/vim/commit/51e933261b984db014e858d79387a826d2626fb6 Cherry-pick related changes from patches 8.2.{0633,0634}. N/A patches for version.c: vim-patch:8.2.2779: memory access error in remove() for blob Problem: Memory access error in remove() for blob. Solution: Adjust length for memmove(). https://github.com/vim/vim/commit/f7e92aae1581203306a340b4c0059cc74adea9d6 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 17 ++++ src/nvim/eval/typval.h | 6 +- src/nvim/testdir/test_blob.vim | 214 ++++++++++++++++++++++++++++------------- 3 files changed, 167 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 7e94e03823..d56efe30da 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2750,6 +2750,23 @@ int tv_blob_set_range(blob_T *dest, long n1, long n2, typval_T *src) return OK; } +/// Store one byte "byte" in blob "blob" at "idx". +/// Append one byte if needed. +void tv_blob_set_append(blob_T *blob, int idx, uint8_t byte) +{ + garray_T *gap = &blob->bv_ga; + + // Allow for appending a byte. Setting a byte beyond + // the end is an error otherwise. + if (idx <= gap->ga_len) { + if (idx == gap->ga_len) { + ga_grow(gap, 1); + gap->ga_len++; + } + tv_blob_set(blob, idx, byte); + } +} + /// "remove({blob})" function void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) { diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 3f59cd3547..4a2654f03e 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -372,7 +372,7 @@ static inline uint8_t tv_blob_get(const blob_T *const b, int idx) return ((uint8_t *)b->bv_ga.ga_data)[idx]; } -static inline void tv_blob_set(blob_T *b, int idx, uint8_t c) +static inline void tv_blob_set(blob_T *blob, int idx, uint8_t c) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL; /// Store the byte `c` at index `idx` in the blob. @@ -380,9 +380,9 @@ static inline void tv_blob_set(blob_T *b, int idx, uint8_t c) /// @param[in] b Blob to index. Cannot be NULL. /// @param[in] idx Index in a blob. Must be valid. /// @param[in] c Value to store. -static inline void tv_blob_set(blob_T *const b, int idx, uint8_t c) +static inline void tv_blob_set(blob_T *const blob, int idx, uint8_t c) { - ((uint8_t *)b->bv_ga.ga_data)[idx] = c; + ((uint8_t *)blob->bv_ga.ga_data)[idx] = c; } /// Initialize VimL object diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index 86e16b372b..e9d694e4c6 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -120,86 +120,166 @@ func Test_blob_assign() endfunc func Test_blob_get_range() + let lines =<< trim END + VAR b = 0z0011223344 + call assert_equal(0z2233, b[2 : 3]) + call assert_equal(0z223344, b[2 : -1]) + call assert_equal(0z00, b[0 : -5]) + call assert_equal(0z, b[0 : -11]) + call assert_equal(0z44, b[-1 :]) + call assert_equal(0z0011223344, b[:]) + call assert_equal(0z0011223344, b[: -1]) + call assert_equal(0z, b[5 : 6]) + call assert_equal(0z0011, b[-10 : 1]) + END + call CheckLegacyAndVim9Success(lines) + + " legacy script white space let b = 0z0011223344 call assert_equal(0z2233, b[2:3]) - call assert_equal(0z223344, b[2:-1]) - call assert_equal(0z00, b[0:-5]) - call assert_equal(0z, b[0:-11]) - call assert_equal(0z44, b[-1:]) - call assert_equal(0z0011223344, b[:]) - call assert_equal(0z0011223344, b[:-1]) - call assert_equal(0z, b[5:6]) - call assert_equal(0z0011, b[-10:1]) endfunc func Test_blob_get() - let b = 0z0011223344 - call assert_equal(0x00, get(b, 0)) - call assert_equal(0x22, get(b, 2, 999)) - call assert_equal(0x44, get(b, 4)) - call assert_equal(0x44, get(b, -1)) - call assert_equal(-1, get(b, 5)) - call assert_equal(999, get(b, 5, 999)) - call assert_equal(-1, get(b, -8)) - call assert_equal(999, get(b, -8, 999)) - call assert_equal(10, get(v:_null_blob, 2, 10)) - - call assert_equal(0x00, b[0]) - call assert_equal(0x22, b[2]) - call assert_equal(0x44, b[4]) - call assert_equal(0x44, b[-1]) - call assert_fails('echo b[5]', 'E979:') - call assert_fails('echo b[-8]', 'E979:') + let lines =<< trim END + VAR b = 0z0011223344 + call assert_equal(0x00, get(b, 0)) + call assert_equal(0x22, get(b, 2, 999)) + call assert_equal(0x44, get(b, 4)) + call assert_equal(0x44, get(b, -1)) + call assert_equal(-1, get(b, 5)) + call assert_equal(999, get(b, 5, 999)) + call assert_equal(-1, get(b, -8)) + call assert_equal(999, get(b, -8, 999)) + call assert_equal(10, get(v:_null_blob, 2, 10)) + + call assert_equal(0x00, b[0]) + call assert_equal(0x22, b[2]) + call assert_equal(0x44, b[4]) + call assert_equal(0x44, b[-1]) + END + call CheckLegacyAndVim9Success(lines) + + let lines =<< trim END + VAR b = 0z0011223344 + echo b[5] + END + call CheckLegacyAndVim9Failure(lines, 'E979:') + + let lines =<< trim END + VAR b = 0z0011223344 + echo b[-8] + END + call CheckLegacyAndVim9Failure(lines, 'E979:') endfunc func Test_blob_to_string() - let b = 0z00112233445566778899aabbccdd - call assert_equal('0z00112233.44556677.8899AABB.CCDD', string(b)) - call assert_equal(b, eval(string(b))) - call remove(b, 4, -1) - call assert_equal('0z00112233', string(b)) - call remove(b, 0, 3) - call assert_equal('0z', string(b)) + let lines =<< trim END + VAR b = 0z00112233445566778899aabbccdd + call assert_equal('0z00112233.44556677.8899AABB.CCDD', string(b)) + call assert_equal(b, eval(string(b))) + call remove(b, 4, -1) + call assert_equal('0z00112233', string(b)) + call remove(b, 0, 3) + call assert_equal('0z', string(b)) + call assert_equal('0z', string(v:_null_blob)) + END + call CheckLegacyAndVim9Success(lines) endfunc func Test_blob_compare() - let b1 = 0z0011 - let b2 = 0z1100 - let b3 = 0z001122 - call assert_true(b1 == b1) - call assert_false(b1 == b2) - call assert_false(b1 == b3) - call assert_true(b1 != b2) - call assert_true(b1 != b3) - call assert_true(b1 == 0z0011) - call assert_fails('echo b1 == 9', 'E977:') - call assert_fails('echo b1 != 9', 'E977:') - - call assert_false(b1 is b2) - let b2 = b1 - call assert_true(b1 == b2) - call assert_true(b1 is b2) - let b2 = copy(b1) - call assert_true(b1 == b2) - call assert_false(b1 is b2) - let b2 = b1[:] - call assert_true(b1 == b2) - call assert_false(b1 is b2) - - call assert_fails('let x = b1 > b2') - call assert_fails('let x = b1 < b2') - call assert_fails('let x = b1 - b2') - call assert_fails('let x = b1 / b2') - call assert_fails('let x = b1 * b2') + let lines =<< trim END + VAR b1 = 0z0011 + VAR b2 = 0z1100 + VAR b3 = 0z001122 + call assert_true(b1 == b1) + call assert_false(b1 == b2) + call assert_false(b1 == b3) + call assert_true(b1 != b2) + call assert_true(b1 != b3) + call assert_true(b1 == 0z0011) + + call assert_false(b1 is b2) + LET b2 = b1 + call assert_true(b1 == b2) + call assert_true(b1 is b2) + LET b2 = copy(b1) + call assert_true(b1 == b2) + call assert_false(b1 is b2) + LET b2 = b1[:] + call assert_true(b1 == b2) + call assert_false(b1 is b2) + call assert_true(b1 isnot b2) + END + call CheckLegacyAndVim9Success(lines) + + let lines =<< trim END + VAR b1 = 0z0011 + echo b1 == 9 + END + call CheckLegacyAndVim9Failure(lines, ['E977:', 'E1072', 'E1072']) + + let lines =<< trim END + VAR b1 = 0z0011 + echo b1 != 9 + END + call CheckLegacyAndVim9Failure(lines, ['E977:', 'E1072', 'E1072']) + + let lines =<< trim END + VAR b1 = 0z0011 + VAR b2 = 0z1100 + VAR x = b1 > b2 + END + call CheckLegacyAndVim9Failure(lines, ['E978:', 'E1072:', 'E1072:']) + + let lines =<< trim END + VAR b1 = 0z0011 + VAR b2 = 0z1100 + VAR x = b1 < b2 + END + call CheckLegacyAndVim9Failure(lines, ['E978:', 'E1072:', 'E1072:']) + + let lines =<< trim END + VAR b1 = 0z0011 + VAR b2 = 0z1100 + VAR x = b1 - b2 + END + call CheckLegacyAndVim9Failure(lines, ['E974:', 'E1036:', 'E974:']) + + let lines =<< trim END + VAR b1 = 0z0011 + VAR b2 = 0z1100 + VAR x = b1 / b2 + END + call CheckLegacyAndVim9Failure(lines, ['E974:', 'E1036:', 'E974:']) + + let lines =<< trim END + VAR b1 = 0z0011 + VAR b2 = 0z1100 + VAR x = b1 * b2 + END + call CheckLegacyAndVim9Failure(lines, ['E974:', 'E1036:', 'E974:']) endfunc -" test for range assign -func Test_blob_range_assign() - let b = 0z00 - let b[1] = 0x11 - let b[2] = 0x22 - call assert_equal(0z001122, b) - call assert_fails('let b[4] = 0x33', 'E979:') +func Test_blob_index_assign() + let lines =<< trim END + VAR b = 0z00 + LET b[1] = 0x11 + LET b[2] = 0x22 + call assert_equal(0z001122, b) + END + call CheckLegacyAndVim9Success(lines) + + let lines =<< trim END + VAR b = 0z00 + LET b[2] = 0x33 + END + call CheckLegacyAndVim9Failure(lines, 'E979:') + + let lines =<< trim END + VAR b = 0z00 + LET b[-2] = 0x33 + END + call CheckLegacyAndVim9Failure(lines, 'E979:') endfunc func Test_blob_for_loop() -- cgit From 0ded757c31bf02d6cd27fc7b580e85ff7953604e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 15:46:53 +0800 Subject: vim-patch:8.2.2780: Vim9: for loop over blob doesn't work Problem: Vim9: for loop over blob doesn't work. Solution: Make it work. https://github.com/vim/vim/commit/d551d6c268e435e2fbba22775510fbd0a54477f6 Co-authored-by: Bram Moolenaar --- src/nvim/testdir/test_blob.vim | 55 ++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index e9d694e4c6..454be05363 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -283,33 +283,36 @@ func Test_blob_index_assign() endfunc func Test_blob_for_loop() - let blob = 0z00010203 - let i = 0 - for byte in blob - call assert_equal(i, byte) - let i += 1 - endfor - call assert_equal(4, i) - - let blob = 0z00 - call remove(blob, 0) - call assert_equal(0, len(blob)) - for byte in blob - call assert_error('loop over empty blob') - endfor - - let blob = 0z0001020304 - let i = 0 - for byte in blob - call assert_equal(i, byte) - if i == 1 + let lines =<< trim END + VAR blob = 0z00010203 + VAR i = 0 + for byte in blob + call assert_equal(i, byte) + LET i += 1 + endfor + call assert_equal(4, i) + + LET blob = 0z00 call remove(blob, 0) - elseif i == 3 - call remove(blob, 3) - endif - let i += 1 - endfor - call assert_equal(5, i) + call assert_equal(0, len(blob)) + for byte in blob + call assert_report('loop over empty blob') + endfor + + LET blob = 0z0001020304 + LET i = 0 + for byte in blob + call assert_equal(i, byte) + if i == 1 + call remove(blob, 0) + elseif i == 3 + call remove(blob, 3) + endif + LET i += 1 + endfor + call assert_equal(5, i) + END + call CheckLegacyAndVim9Success(lines) endfunc func Test_blob_concatenate() -- cgit From 88b70e7d4650795210222a598cbb233bf7fc98f8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 15:50:35 +0800 Subject: vim-patch:8.2.2782: Vim9: blob operations not fully tested Problem: Vim9: blob operations not fully tested. Solution: Make more blob tests run in Vim9 script. Fix filter(). Make insert() give an error for a null blob, like add(). https://github.com/vim/vim/commit/39211cba723a2cb58a97c7e08826713164b86efc vim-patch:8.2.3284: no error for insert() or remove() changing a locked blob Problem: No error for insert() or remove() changing a locked blob. Solution: Check a blob is not locked before changing it. (Sean Dewar, closes vim/vim#8696) https://github.com/vim/vim/commit/80d7395dcfe96158428da6bb3d28a6eee1244e28 Co-authored-by: Bram Moolenaar Co-authored-by: Sean Dewar --- src/nvim/eval.c | 2 +- src/nvim/eval/funcs.c | 9 +- src/nvim/testdir/test_blob.vim | 337 ++++++++++++++++++++++++++++++----------- src/nvim/testdir/vim9.vim | 4 + 4 files changed, 257 insertions(+), 95 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index f8110aa545..37029e0dd7 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -4861,7 +4861,7 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map) if (filter_map_one(&tv, expr, map, &rem) == FAIL || did_emsg) { break; } - if (tv.v_type != VAR_NUMBER) { + if (tv.v_type != VAR_NUMBER && tv.v_type != VAR_BOOL) { emsg(_(e_invalblob)); return; } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 1baf96e281..20e590a30c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3743,7 +3743,6 @@ static void f_inputsecret(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "insert()" function static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - list_T *l; bool error = false; if (argvars[0].v_type == VAR_BLOB) { @@ -3786,8 +3785,12 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tv_copy(&argvars[0], rettv); } else if (argvars[0].v_type != VAR_LIST) { semsg(_(e_listblobarg), "insert()"); - } else if (!value_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), - N_("insert() argument"), TV_TRANSLATE)) { + } else { + list_T *l = argvars[0].vval.v_list; + if (value_check_lock(tv_list_locked(l), N_("insert() argument"), TV_TRANSLATE)) { + return; + } + int64_t before = 0; if (argvars[2].v_type != VAR_UNKNOWN) { before = tv_get_number_chk(&argvars[2], &error); diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index 454be05363..99b8c6083a 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -347,51 +347,101 @@ endfunc " Test removing items in blob func Test_blob_func_remove() - " Test removing 1 element - let b = 0zDEADBEEF - call assert_equal(0xDE, remove(b, 0)) - call assert_equal(0zADBEEF, b) + let lines =<< trim END + #" Test removing 1 element + VAR b = 0zDEADBEEF + call assert_equal(0xDE, remove(b, 0)) + call assert_equal(0zADBEEF, b) - let b = 0zDEADBEEF - call assert_equal(0xEF, remove(b, -1)) - call assert_equal(0zDEADBE, b) + LET b = 0zDEADBEEF + call assert_equal(0xEF, remove(b, -1)) + call assert_equal(0zDEADBE, b) - let b = 0zDEADBEEF - call assert_equal(0xAD, remove(b, 1)) - call assert_equal(0zDEBEEF, b) + LET b = 0zDEADBEEF + call assert_equal(0xAD, remove(b, 1)) + call assert_equal(0zDEBEEF, b) - " Test removing range of element(s) - let b = 0zDEADBEEF - call assert_equal(0zBE, remove(b, 2, 2)) - call assert_equal(0zDEADEF, b) + #" Test removing range of element(s) + LET b = 0zDEADBEEF + call assert_equal(0zBE, remove(b, 2, 2)) + call assert_equal(0zDEADEF, b) - let b = 0zDEADBEEF - call assert_equal(0zADBE, remove(b, 1, 2)) - call assert_equal(0zDEEF, b) + LET b = 0zDEADBEEF + call assert_equal(0zADBE, remove(b, 1, 2)) + call assert_equal(0zDEEF, b) + END + call CheckLegacyAndVim9Success(lines) " Test invalid cases - let b = 0zDEADBEEF - call assert_fails("call remove(b, 5)", 'E979:') - call assert_fails("call remove(b, 1, 5)", 'E979:') - call assert_fails("call remove(b, 3, 2)", 'E979:') - call assert_fails("call remove(1, 0)", 'E896:') - call assert_fails("call remove(b, b)", 'E974:') - call assert_fails("call remove(b, 1, [])", 'E745:') - call assert_fails("call remove(v:_null_blob, 1, 2)", 'E979:') - - " Translated from v8.2.3284 - let b = 0zDEADBEEF - lockvar b - call assert_fails('call remove(b, 0)', 'E741:') - unlockvar b + let lines =<< trim END + VAR b = 0zDEADBEEF + call remove(b, 5) + END + call CheckLegacyAndVim9Failure(lines, 'E979:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + call remove(b, 1, 5) + END + call CheckLegacyAndVim9Failure(lines, 'E979:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + call remove(b, 3, 2) + END + call CheckLegacyAndVim9Failure(lines, 'E979:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + call remove(1, 0) + END + call CheckLegacyAndVim9Failure(lines, 'E896:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + call remove(b, b) + END + call CheckLegacyAndVim9Failure(lines, 'E974:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + call remove(b, 1, []) + END + call CheckLegacyAndVim9Failure(lines, 'E745:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + call remove(v:_null_blob, 1, 2) + END + call CheckLegacyAndVim9Failure(lines, 'E979:') + + let lines =<< trim END + let b = 0zDEADBEEF + lockvar b + call remove(b, 0) + unlockvar b + END + call CheckScriptFailure(lines, 'E741:') + + " can only check at script level, not in a :def function + let lines =<< trim END + vim9script + var b = 0zDEADBEEF + lockvar b + remove(b, 0) + END + call CheckScriptFailure(lines, 'E741:') endfunc func Test_blob_read_write() - let b = 0zDEADBEEF - call writefile(b, 'Xblob') - let br = readfile('Xblob', 'B') - call assert_equal(b, br) - call delete('Xblob') + let lines =<< trim END + VAR b = 0zDEADBEEF + call writefile(b, 'Xblob') + VAR br = readfile('Xblob', 'B') + call assert_equal(b, br) + call delete('Xblob') + END + call CheckLegacyAndVim9Success(lines) " This was crashing when calling readfile() with a directory. call assert_fails("call readfile('.', 'B')", 'E17: "." is a directory') @@ -399,85 +449,190 @@ endfunc " filter() item in blob func Test_blob_filter() - call assert_equal(v:_null_blob, filter(v:_null_blob, '0')) - call assert_equal(0z, filter(0zDEADBEEF, '0')) - call assert_equal(0zADBEEF, filter(0zDEADBEEF, 'v:val != 0xDE')) - call assert_equal(0zDEADEF, filter(0zDEADBEEF, 'v:val != 0xBE')) - call assert_equal(0zDEADBE, filter(0zDEADBEEF, 'v:val != 0xEF')) - call assert_equal(0zDEADBEEF, filter(0zDEADBEEF, '1')) - call assert_equal(0z01030103, filter(0z010203010203, 'v:val != 0x02')) - call assert_equal(0zADEF, filter(0zDEADBEEF, 'v:key % 2')) + let lines =<< trim END + call assert_equal(v:_null_blob, filter(v:_null_blob, '0')) + call assert_equal(0z, filter(0zDEADBEEF, '0')) + call assert_equal(0zADBEEF, filter(0zDEADBEEF, 'v:val != 0xDE')) + call assert_equal(0zDEADEF, filter(0zDEADBEEF, 'v:val != 0xBE')) + call assert_equal(0zDEADBE, filter(0zDEADBEEF, 'v:val != 0xEF')) + call assert_equal(0zDEADBEEF, filter(0zDEADBEEF, '1')) + call assert_equal(0z01030103, filter(0z010203010203, 'v:val != 0x02')) + call assert_equal(0zADEF, filter(0zDEADBEEF, 'v:key % 2')) + END + call CheckLegacyAndVim9Success(lines) endfunc " map() item in blob func Test_blob_map() - call assert_equal(0zDFAEBFF0, map(0zDEADBEEF, 'v:val + 1')) - call assert_equal(0z00010203, map(0zDEADBEEF, 'v:key')) - call assert_equal(0zDEAEC0F2, map(0zDEADBEEF, 'v:key + v:val')) + let lines =<< trim END + call assert_equal(0zDFAEBFF0, map(0zDEADBEEF, 'v:val + 1')) + call assert_equal(0z00010203, map(0zDEADBEEF, 'v:key')) + call assert_equal(0zDEAEC0F2, map(0zDEADBEEF, 'v:key + v:val')) + END + call CheckLegacyAndVim9Success(lines) - call assert_fails("call map(0z00, '[9]')", 'E978:') + let lines =<< trim END + call map(0z00, '[9]') + END + call CheckLegacyAndVim9Failure(lines, 'E978:') endfunc func Test_blob_index() - call assert_equal(2, index(0zDEADBEEF, 0xBE)) - call assert_equal(-1, index(0zDEADBEEF, 0)) - call assert_equal(2, index(0z11111111, 0x11, 2)) - call assert_equal(3, 0z11110111->index(0x11, 2)) - call assert_equal(2, index(0z11111111, 0x11, -2)) - call assert_equal(3, index(0z11110111, 0x11, -2)) - call assert_equal(0, index(0z11110111, 0x11, -10)) - call assert_fails("echo index(0z11110111, 0x11, [])", 'E745:') - call assert_equal(-1, index(v:_null_blob, 1)) - - call assert_fails('call index("asdf", 0)', 'E897:') + let lines =<< trim END + call assert_equal(2, index(0zDEADBEEF, 0xBE)) + call assert_equal(-1, index(0zDEADBEEF, 0)) + call assert_equal(2, index(0z11111111, 0x11, 2)) + call assert_equal(3, 0z11110111->index(0x11, 2)) + call assert_equal(2, index(0z11111111, 0x11, -2)) + call assert_equal(3, index(0z11110111, 0x11, -2)) + call assert_equal(0, index(0z11110111, 0x11, -10)) + call assert_equal(-1, index(v:_null_blob, 1)) + END + call CheckLegacyAndVim9Success(lines) + + let lines =<< trim END + echo index(0z11110111, 0x11, []) + END + call CheckLegacyAndVim9Failure(lines, 'E745:') + + let lines =<< trim END + call index("asdf", 0) + END + call CheckLegacyAndVim9Failure(lines, 'E897:') endfunc func Test_blob_insert() - let b = 0zDEADBEEF - call insert(b, 0x33) - call assert_equal(0z33DEADBEEF, b) - - let b = 0zDEADBEEF - call insert(b, 0x33, 2) - call assert_equal(0zDEAD33BEEF, b) - - call assert_fails('call insert(b, -1)', 'E475:') - call assert_fails('call insert(b, 257)', 'E475:') - call assert_fails('call insert(b, 0, [9])', 'E745:') - call assert_fails('call insert(b, 0, -20)', 'E475:') - call assert_fails('call insert(b, 0, 20)', 'E475:') - call assert_fails('call insert(b, [])', 'E745:') + let lines =<< trim END + VAR b = 0zDEADBEEF + call insert(b, 0x33) + call assert_equal(0z33DEADBEEF, b) + + LET b = 0zDEADBEEF + call insert(b, 0x33, 2) + call assert_equal(0zDEAD33BEEF, b) + END + call CheckLegacyAndVim9Success(lines) + + " only works in legacy script call assert_equal(0, insert(v:_null_blob, 0x33)) - " Translated from v8.2.3284 - let b = 0zDEADBEEF - lockvar b - call assert_fails('call insert(b, 3)', 'E741:') - unlockvar b + let lines =<< trim END + VAR b = 0zDEADBEEF + call insert(b, -1) + END + call CheckLegacyAndVim9Failure(lines, 'E475:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + call insert(b, 257) + END + call CheckLegacyAndVim9Failure(lines, 'E475:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + call insert(b, 0, [9]) + END + call CheckLegacyAndVim9Failure(lines, ['E745:', 'E1013:', 'E745:']) + + let lines =<< trim END + VAR b = 0zDEADBEEF + call insert(b, 0, -20) + END + call CheckLegacyAndVim9Failure(lines, 'E475:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + call insert(b, 0, 20) + END + call CheckLegacyAndVim9Failure(lines, 'E475:') + + let lines =<< trim END + VAR b = 0zDEADBEEF + call insert(b, []) + END + call CheckLegacyAndVim9Failure(lines, ['E745:', 'E1013:', 'E745:']) + + let lines =<< trim END + insert(v:_null_blob, 0x33) + END + call CheckDefExecAndScriptFailure(lines, 'E1131:') + + let lines =<< trim END + let b = 0zDEADBEEF + lockvar b + call insert(b, 3) + unlockvar b + END + call CheckScriptFailure(lines, 'E741:') + + let lines =<< trim END + vim9script + var b = 0zDEADBEEF + lockvar b + insert(b, 3) + END + call CheckScriptFailure(lines, 'E741:') endfunc func Test_blob_reverse() - call assert_equal(0zEFBEADDE, reverse(0zDEADBEEF)) - call assert_equal(0zBEADDE, reverse(0zDEADBE)) - call assert_equal(0zADDE, reverse(0zDEAD)) - call assert_equal(0zDE, reverse(0zDE)) - call assert_equal(0z, reverse(v:_null_blob)) + let lines =<< trim END + call assert_equal(0zEFBEADDE, reverse(0zDEADBEEF)) + call assert_equal(0zBEADDE, reverse(0zDEADBE)) + call assert_equal(0zADDE, reverse(0zDEAD)) + call assert_equal(0zDE, reverse(0zDE)) + call assert_equal(0z, reverse(v:_null_blob)) + END + call CheckLegacyAndVim9Success(lines) +endfunc + +func Test_blob_json_encode() + let lines =<< trim END + #" call assert_equal('[222,173,190,239]', json_encode(0zDEADBEEF)) + call assert_equal('[222, 173, 190, 239]', json_encode(0zDEADBEEF)) + call assert_equal('[]', json_encode(0z)) + END + call CheckLegacyAndVim9Success(lines) endfunc func Test_blob_lock() - let b = 0z112233 - lockvar b - call assert_fails('let b = 0z44', 'E741:') - unlockvar b - let b = 0z44 + let lines =<< trim END + let b = 0z112233 + lockvar b + unlockvar b + let b = 0z44 + END + call CheckScriptSuccess(lines) + + let lines =<< trim END + vim9script + var b = 0z112233 + lockvar b + unlockvar b + b = 0z44 + END + call CheckScriptSuccess(lines) + + let lines =<< trim END + let b = 0z112233 + lockvar b + let b = 0z44 + END + call CheckScriptFailure(lines, 'E741:') + + let lines =<< trim END + vim9script + var b = 0z112233 + lockvar b + b = 0z44 + END + call CheckScriptFailure(lines, 'E741:') endfunc func Test_blob_sort() if has('float') - call assert_fails('call sort([1.0, 0z11], "f")', 'E975:') - else - call assert_fails('call sort(["abc", 0z11], "f")', 'E702:') + call CheckLegacyAndVim9Failure(['call sort([1.0, 0z11], "f")'], 'E975:') endif + call CheckLegacyAndVim9Failure(['call sort(["abc", 0z11], "f")'], 'E892:') endfunc " The following used to cause an out-of-bounds memory access diff --git a/src/nvim/testdir/vim9.vim b/src/nvim/testdir/vim9.vim index e1343d51f1..2cc3d88aa8 100644 --- a/src/nvim/testdir/vim9.vim +++ b/src/nvim/testdir/vim9.vim @@ -34,6 +34,10 @@ func CheckScriptSuccess(lines) endtry endfunc +func CheckDefExecAndScriptFailure(lines, error, lnum = -3) + return +endfunc + " Check that "lines" inside a legacy function has no error. func CheckLegacySuccess(lines) let cwd = getcwd() -- cgit From 55d30c459c878224507e90f2a6c1657cdd070668 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 16:06:56 +0800 Subject: vim-patch:8.2.2783: duplicate code for setting byte in blob, blob test may fail Problem: Duplicate code for setting byte in blob, blob test may fail. Solution: Call blob_set_append(). Test sort failure with "N". https://github.com/vim/vim/commit/e8209b91b9974da95899b51dba4058b411d04d5b Co-authored-by: Bram Moolenaar --- src/nvim/eval.c | 13 +------------ src/nvim/testdir/test_blob.vim | 2 +- 2 files changed, 2 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 37029e0dd7..698172442e 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1620,18 +1620,7 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool bool error = false; const char val = (char)tv_get_number_chk(rettv, &error); if (!error) { - garray_T *const gap = &lp->ll_blob->bv_ga; - - // Allow for appending a byte. Setting a byte beyond - // the end is an error otherwise. - if (lp->ll_n1 < gap->ga_len || lp->ll_n1 == gap->ga_len) { - ga_grow(&lp->ll_blob->bv_ga, 1); - tv_blob_set(lp->ll_blob, (int)lp->ll_n1, (uint8_t)val); - if (lp->ll_n1 == gap->ga_len) { - gap->ga_len++; - } - } - // error for invalid range was already given in get_lval() + tv_blob_set_append(lp->ll_blob, (int)lp->ll_n1, (uint8_t)val); } } } else if (op != NULL && *op != '=') { diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index 99b8c6083a..b1859f9dfe 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -632,7 +632,7 @@ func Test_blob_sort() if has('float') call CheckLegacyAndVim9Failure(['call sort([1.0, 0z11], "f")'], 'E975:') endif - call CheckLegacyAndVim9Failure(['call sort(["abc", 0z11], "f")'], 'E892:') + call CheckLegacyAndVim9Failure(['call sort([11, 0z11], "N")'], 'E974:') endfunc " The following used to cause an out-of-bounds memory access -- cgit From bfa0bc7df0ca527fcec49dbd2055f1bac438663e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 19:04:32 +0800 Subject: vim-patch:9.0.0795: readblob() always reads the whole file Problem: readblob() always reads the whole file. Solution: Add arguments to read part of the file. (Ken Takata, closes vim/vim#11402) https://github.com/vim/vim/commit/11df3aeee548b959ccd4b9a4d3c44651eab6b3ce Remove trailing whitespace in test as done in patch 9.0.1257. Move the help for rand() before range(). Co-authored-by: K.Takata --- src/nvim/eval.c | 50 +++++++++++++++++++++++++++++++++--------- src/nvim/eval.lua | 2 +- src/nvim/eval/funcs.c | 28 +++++++++++++---------- src/nvim/testdir/test_blob.vim | 19 ++++++++++++++++ 4 files changed, 77 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 698172442e..c2f84735b2 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5859,27 +5859,57 @@ write_blob_error: return false; } -/// Read a blob from a file `fd`. +/// Read blob from file "fd". +/// Caller has allocated a blob in "rettv". /// /// @param[in] fd File to read from. -/// @param[in,out] blob Blob to write to. +/// @param[in,out] rettv Blob to write to. +/// @param[in] offset Read the file from the specified offset. +/// @param[in] size Read the specified size, or -1 if no limit. /// -/// @return true on success, or false on failure. -bool read_blob(FILE *const fd, blob_T *const blob) +/// @return OK on success, or FAIL on failure. +int read_blob(FILE *const fd, typval_T *rettv, off_T offset, off_T size_arg) FUNC_ATTR_NONNULL_ALL { + blob_T *const blob = rettv->vval.v_blob; FileInfo file_info; if (!os_fileinfo_fd(fileno(fd), &file_info)) { - return false; + return FAIL; // can't read the file, error + } + + int whence; + off_T size = size_arg; + if (offset >= 0) { + if (size == -1) { + // size may become negative, checked below + size = (off_T)os_fileinfo_size(&file_info) - offset; + } + whence = SEEK_SET; + } else { + if (size == -1) { + size = -offset; + } + whence = SEEK_END; + } + // Trying to read bytes that aren't there results in an empty blob, not an + // error. + if (size < 0 || size > (off_T)os_fileinfo_size(&file_info)) { + return OK; + } + if (vim_fseek(fd, offset, whence) != 0) { + return OK; } - const int size = (int)os_fileinfo_size(&file_info); - ga_grow(&blob->bv_ga, size); - blob->bv_ga.ga_len = size; + + ga_grow(&blob->bv_ga, (int)size); + blob->bv_ga.ga_len = (int)size; if (fread(blob->bv_ga.ga_data, 1, (size_t)blob->bv_ga.ga_len, fd) < (size_t)blob->bv_ga.ga_len) { - return false; + // An empty blob is returned on error. + tv_blob_free(rettv->vval.v_blob); + rettv->vval.v_blob = NULL; + return FAIL; } - return true; + return OK; } /// Saves a typval_T as a string. diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index a476e20339..24263d9aee 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -296,7 +296,7 @@ return { perleval={args=1, base=1}, rand={args={0, 1}, base=1}, range={args={1, 3}, base=1}, - readblob={args=1, base=1}, + readblob={args={1, 3}, base=1}, readdir={args={1, 2}, base=1}, readfile={args={1, 3}, base=1}, reduce={args={2, 3}, base=1}, diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d3bac14754..5da6233e38 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5592,15 +5592,24 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl ptrdiff_t prevlen = 0; // length of data in prev ptrdiff_t prevsize = 0; // size of prev buffer int64_t maxline = MAXLNUM; + off_T offset = 0; + off_T size = -1; if (argvars[1].v_type != VAR_UNKNOWN) { - if (strcmp(tv_get_string(&argvars[1]), "b") == 0) { - binary = true; - } else if (strcmp(tv_get_string(&argvars[1]), "B") == 0) { - blob = true; - } - if (argvars[2].v_type != VAR_UNKNOWN) { - maxline = tv_get_number(&argvars[2]); + if (always_blob) { + offset = (off_T)tv_get_number(&argvars[1]); + if (argvars[2].v_type != VAR_UNKNOWN) { + size = (off_T)tv_get_number(&argvars[2]); + } + } else { + if (strcmp(tv_get_string(&argvars[1]), "b") == 0) { + binary = true; + } else if (strcmp(tv_get_string(&argvars[1]), "B") == 0) { + blob = true; + } + if (argvars[2].v_type != VAR_UNKNOWN) { + maxline = tv_get_number(&argvars[2]); + } } } @@ -5619,11 +5628,8 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl if (blob) { tv_blob_alloc_ret(rettv); - if (!read_blob(fd, rettv->vval.v_blob)) { + if (read_blob(fd, rettv, offset, size) == FAIL) { semsg(_(e_notread), fname); - // An empty blob is returned on error. - tv_blob_free(rettv->vval.v_blob); - rettv->vval.v_blob = NULL; } fclose(fd); return; diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index b1859f9dfe..dd37fb2f11 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -439,10 +439,29 @@ func Test_blob_read_write() call writefile(b, 'Xblob') VAR br = readfile('Xblob', 'B') call assert_equal(b, br) + VAR br2 = readblob('Xblob') + call assert_equal(b, br2) + VAR br3 = readblob('Xblob', 1) + call assert_equal(b[1 :], br3) + VAR br4 = readblob('Xblob', 1, 2) + call assert_equal(b[1 : 2], br4) + VAR br5 = readblob('Xblob', -3) + call assert_equal(b[-3 :], br5) + VAR br6 = readblob('Xblob', -3, 2) + call assert_equal(b[-3 : -2], br6) + + VAR br1e = readblob('Xblob', 10000) + call assert_equal(0z, br1e) + VAR br2e = readblob('Xblob', -10000) + call assert_equal(0z, br2e) + call delete('Xblob') END call CheckLegacyAndVim9Success(lines) + call assert_fails("call readblob('notexist')", 'E484:') + " TODO: How do we test for the E485 error? + " This was crashing when calling readfile() with a directory. call assert_fails("call readfile('.', 'B')", 'E17: "." is a directory') endfunc -- cgit From 4bd0611d7b07b56fc5a9e121669a313166ba540f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 19:23:28 +0800 Subject: vim-patch:9.0.0803: readblob() cannot read from character device Problem: readblob() cannot read from character device. Solution: Use S_ISCHR() to not check the size. (Ken Takata, closes vim/vim#11407) https://github.com/vim/vim/commit/43625762a9751cc6e6e4d8f54fbc8b82d98fb20d S_ISCHR is always defined in Nvim. Co-authored-by: K.Takata --- src/nvim/eval.c | 5 +++-- src/nvim/testdir/test_blob.vim | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index c2f84735b2..92fd8a8de3 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5893,10 +5893,11 @@ int read_blob(FILE *const fd, typval_T *rettv, off_T offset, off_T size_arg) } // Trying to read bytes that aren't there results in an empty blob, not an // error. - if (size < 0 || size > (off_T)os_fileinfo_size(&file_info)) { + if (size < 0 || (!S_ISCHR(file_info.stat.st_mode) + && size > (off_T)os_fileinfo_size(&file_info))) { return OK; } - if (vim_fseek(fd, offset, whence) != 0) { + if (offset != 0 && vim_fseek(fd, offset, whence) != 0) { return OK; } diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index dd37fb2f11..5fc232119c 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -459,6 +459,11 @@ func Test_blob_read_write() END call CheckLegacyAndVim9Success(lines) + if filereadable('/dev/random') + let b = readblob('/dev/random', 0, 10) + call assert_equal(10, len(b)) + endif + call assert_fails("call readblob('notexist')", 'E484:') " TODO: How do we test for the E485 error? -- cgit From 7aad75e293e3a01e292308ca2058e35083b83280 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 19:29:59 +0800 Subject: vim-patch:9.0.0810: readblob() returns empty when trying to read too much Problem: readblob() returns empty when trying to read too much. Solution: Return what is available. https://github.com/vim/vim/commit/5b2a3d77d320d76f12b1666938a9d58c2a848205 Co-authored-by: Bram Moolenaar --- src/nvim/eval.c | 17 +++++++++++------ src/nvim/testdir/test_blob.vim | 11 +++++++++-- 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 92fd8a8de3..b81384266c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -5879,22 +5879,27 @@ int read_blob(FILE *const fd, typval_T *rettv, off_T offset, off_T size_arg) int whence; off_T size = size_arg; + const off_T file_size = (off_T)os_fileinfo_size(&file_info); if (offset >= 0) { - if (size == -1) { + // The size defaults to the whole file. If a size is given it is + // limited to not go past the end of the file. + if (size == -1 || (size > file_size - offset && !S_ISCHR(file_info.stat.st_mode))) { // size may become negative, checked below size = (off_T)os_fileinfo_size(&file_info) - offset; } whence = SEEK_SET; } else { - if (size == -1) { + // limit the offset to not go before the start of the file + if (-offset > file_size && !S_ISCHR(file_info.stat.st_mode)) { + offset = -file_size; + } + // Size defaults to reading until the end of the file. + if (size == -1 || size > -offset) { size = -offset; } whence = SEEK_END; } - // Trying to read bytes that aren't there results in an empty blob, not an - // error. - if (size < 0 || (!S_ISCHR(file_info.stat.st_mode) - && size > (off_T)os_fileinfo_size(&file_info))) { + if (size <= 0) { return OK; } if (offset != 0 && vim_fseek(fd, offset, whence) != 0) { diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index 5fc232119c..b01d9309fa 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -450,10 +450,17 @@ func Test_blob_read_write() VAR br6 = readblob('Xblob', -3, 2) call assert_equal(b[-3 : -2], br6) + #" reading past end of file, empty result VAR br1e = readblob('Xblob', 10000) call assert_equal(0z, br1e) - VAR br2e = readblob('Xblob', -10000) - call assert_equal(0z, br2e) + + #" reading too much, result is truncated + VAR blong = readblob('Xblob', -1000) + call assert_equal(b, blong) + LET blong = readblob('Xblob', -10, 8) + call assert_equal(b, blong) + LET blong = readblob('Xblob', 0, 10) + call assert_equal(b, blong) call delete('Xblob') END -- cgit From 7e19cabeb192d2e7f20d7bb965a3f62e1543d2ac Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 28 Feb 2023 12:38:33 +0100 Subject: perf(lsp): only redraw the windows containing LSP tokens redraw! redraws the entire screen instead of just the windows with the buffer which were actually changed. I considered trying to calculating the range for the delta but it looks tricky. Could a follow-up. --- src/nvim/api/buffer.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index bbdb66988b..ca3cf76388 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -248,6 +248,9 @@ void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, Error *e if (!buf) { return; } + if (last < 0) { + last = buf->b_ml.ml_line_count; + } redraw_buf_range_later(buf, (linenr_T)first + 1, (linenr_T)last); } -- cgit From f6b9791212e86bac3e8128035dec2bfc5016927f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 20:18:52 +0800 Subject: vim-patch:8.2.3438: cannot manipulate blobs Problem: Cannot manipulate blobs. Solution: Add blob2list() and list2blob(). (Yegappan Lakshmanan, closes vim/vim#8868) https://github.com/vim/vim/commit/5dfe467432638fac2e0156a2f9cd0d9eb569fb39 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval.lua | 2 ++ src/nvim/eval/typval.c | 73 ++++++++++++++++++++++++++++++++++++++++++ src/nvim/testdir/test_blob.vim | 39 ++++++++++++++++++++++ 3 files changed, 114 insertions(+) (limited to 'src') diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 24263d9aee..ae10a7e035 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -49,6 +49,7 @@ return { assert_true={args={1, 2}, base=1}, atan={args=1, base=1, float_func="atan"}, atan2={args=2, base=1}, + blob2list={args=1, base=1}, browse={args=4}, browsedir={args=2}, bufadd={args=1, base=1}, @@ -249,6 +250,7 @@ return { line={args={1, 2}, base=1}, line2byte={args=1, base=1}, lispindent={args=1, base=1}, + list2blob={args=1, base=1}, list2str={args={1, 2}, base=1}, localtime={}, log={args=1, base=1, float_func="log"}, diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index d56efe30da..6037536548 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -48,10 +48,16 @@ static char e_dict_required_for_argument_nr[] = N_("E1206: Dictionary required for argument %d"); static char e_number_required_for_argument_nr[] = N_("E1210: Number required for argument %d"); +static char e_list_required_for_argument_nr[] + = N_("E1211: List required for argument %d"); static char e_string_or_list_required_for_argument_nr[] = N_("E1222: String or List required for argument %d"); static char e_list_or_blob_required_for_argument_nr[] = N_("E1226: List or Blob required for argument %d"); +static char e_blob_required_for_argument_nr[] + = N_("E1238: Blob required for argument %d"); +static char e_invalid_value_for_blob_nr[] + = N_("E1239: Invalid value for blob: %d"); static char e_string_or_function_required_for_argument_nr[] = N_("E1256: String or function required for argument %d"); @@ -2826,6 +2832,51 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) } } +/// blob2list() function +void f_blob2list(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_list_alloc_ret(rettv, kListLenMayKnow); + + if (tv_check_for_blob_arg(argvars, 0) == FAIL) { + return; + } + + blob_T *const blob = argvars->vval.v_blob; + list_T *const l = rettv->vval.v_list; + for (int i = 0; i < tv_blob_len(blob); i++) { + tv_list_append_number(l, tv_blob_get(blob, i)); + } +} + +/// list2blob() function +void f_list2blob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_blob_alloc_ret(rettv); + blob_T *const blob = rettv->vval.v_blob; + + if (tv_check_for_list_arg(argvars, 0) == FAIL) { + return; + } + + list_T *const l = argvars->vval.v_list; + if (l == NULL) { + return; + } + + TV_LIST_ITER_CONST(l, li, { + bool error = false; + varnumber_T n = tv_get_number_chk(TV_LIST_ITEM_TV(li), &error); + if (error || n < 0 || n > 255) { + if (!error) { + semsg(_(e_invalid_value_for_blob_nr), n); + } + ga_clear(&blob->bv_ga); + return; + } + ga_append(&blob->bv_ga, (uint8_t)n); + }); +} + //{{{1 Generic typval operations //{{{2 Init/alloc/clear //{{{3 Alloc @@ -3968,6 +4019,28 @@ int tv_check_for_opt_number_arg(const typval_T *const args, const int idx) || tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL; } +/// Give an error and return FAIL unless "args[idx]" is a blob. +int tv_check_for_blob_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_BLOB) { + semsg(_(e_blob_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + +/// Give an error and return FAIL unless "args[idx]" is a list. +int tv_check_for_list_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_LIST) { + semsg(_(e_list_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + /// Give an error and return FAIL unless "args[idx]" is a dict. int tv_check_for_dict_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index b01d9309fa..28df120b78 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -666,6 +666,45 @@ func Test_blob_sort() call CheckLegacyAndVim9Failure(['call sort([11, 0z11], "N")'], 'E974:') endfunc +" Tests for the blob2list() function +func Test_blob2list() + call assert_fails('let v = blob2list(10)', 'E1238: Blob required for argument 1') + eval 0zFFFF->blob2list()->assert_equal([255, 255]) + let tests = [[0z0102, [1, 2]], + \ [0z00, [0]], + \ [0z, []], + \ [0z00000000, [0, 0, 0, 0]], + \ [0zAABB.CCDD, [170, 187, 204, 221]]] + for t in tests + call assert_equal(t[0]->blob2list(), t[1]) + endfor + exe 'let v = 0z' .. repeat('000102030405060708090A0B0C0D0E0F', 64) + call assert_equal(1024, blob2list(v)->len()) + call assert_equal([4, 8, 15], [v[100], v[1000], v[1023]]) + call assert_equal([], blob2list(v:_null_blob)) +endfunc + +" Tests for the list2blob() function +func Test_list2blob() + call assert_fails('let b = list2blob(0z10)', 'E1211: List required for argument 1') + let tests = [[[1, 2], 0z0102], + \ [[0], 0z00], + \ [[], 0z], + \ [[0, 0, 0, 0], 0z00000000], + \ [[170, 187, 204, 221], 0zAABB.CCDD], + \ ] + for t in tests + call assert_equal(t[0]->list2blob(), t[1]) + endfor + call assert_fails('let b = list2blob([1, []])', 'E745:') + call assert_fails('let b = list2blob([-1])', 'E1239:') + call assert_fails('let b = list2blob([256])', 'E1239:') + let b = range(16)->repeat(64)->list2blob() + call assert_equal(1024, b->len()) + call assert_equal([4, 8, 15], [b[100], b[1000], b[1023]]) + call assert_equal(0z, list2blob(v:_null_list)) +endfunc + " The following used to cause an out-of-bounds memory access func Test_blob2string() let v = '0z' .. repeat('01010101.', 444) -- cgit From ccac34af766bee70d4f2a3cd69b54977849f567d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 20:38:16 +0800 Subject: vim-patch:8.2.3446: not enough tests for empty string arguments Problem: Not enough tests for empty string arguments. Solution: Add tests, fix type check. (Yegappan Lakshmanan, closes vim/vim#8881) https://github.com/vim/vim/commit/820d5525cae707f39571c6abc2aa6a9e66ed171e Co-authored-by: Yegappan Lakshmanan --- src/nvim/testdir/test_blob.vim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index 28df120b78..f889da987a 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -691,10 +691,11 @@ func Test_list2blob() \ [[0], 0z00], \ [[], 0z], \ [[0, 0, 0, 0], 0z00000000], + \ [[255, 255], 0zFFFF], \ [[170, 187, 204, 221], 0zAABB.CCDD], \ ] for t in tests - call assert_equal(t[0]->list2blob(), t[1]) + call assert_equal(t[1], t[0]->list2blob()) endfor call assert_fails('let b = list2blob([1, []])', 'E745:') call assert_fails('let b = list2blob([-1])', 'E1239:') -- cgit From 65af4241996021b2067d2adc97cc2c83c616cbb6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 20:59:59 +0800 Subject: vim-patch:8.2.4668: buffer allocation failures insufficiently tested Problem: Buffer allocation failures insufficiently tested. Solution: Add tests for memory allocation failures. (Yegappan Lakshmanan, closes vim/vim#10064) https://github.com/vim/vim/commit/0dac1ab5791819ee9a496273eea38f69a217ac45 Co-authored-by: Yegappan Lakshmanan --- src/nvim/testdir/test_buffer.vim | 71 ++++++++++++++++++++++++++++++++++++++++ src/nvim/testdir/test_swap.vim | 1 - 2 files changed, 71 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/testdir/test_buffer.vim b/src/nvim/testdir/test_buffer.vim index 9220cc17b9..90e97ae167 100644 --- a/src/nvim/testdir/test_buffer.vim +++ b/src/nvim/testdir/test_buffer.vim @@ -451,4 +451,75 @@ func Test_buffer_maxmem() " set maxmem& maxmemtot& endfunc +" Test for a allocation failure when adding a new buffer +func Test_buflist_alloc_failure() + CheckFunction test_alloc_fail + %bw! + + edit Xfile1 + call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call assert_fails('edit Xfile2', 'E342:') + + " test for bufadd() + call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call assert_fails('call bufadd("Xbuffer")', 'E342:') + + " test for setting the arglist + edit Xfile2 + call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call assert_fails('next Xfile3', 'E342:') + + " test for setting the alternate buffer name when writing a file + call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call assert_fails('write Xother', 'E342:') + call delete('Xother') + + " test for creating a buffer using bufnr() + call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call assert_fails("call bufnr('Xnewbuf', v:true)", 'E342:') + + " test for renaming buffer using :file + call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call assert_fails('file Xnewfile', 'E342:') + + " test for creating a buffer for a popup window + call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call assert_fails('call popup_create("mypop", {})', 'E342:') + + if has('terminal') + " test for creating a buffer for a terminal window + call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call assert_fails('call term_start(&shell)', 'E342:') + %bw! + endif + + " test for loading a new buffer after wiping out all the buffers + edit Xfile4 + call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call assert_fails('%bw!', 'E342:') + + " test for :checktime loading the buffer + call writefile(['one'], 'Xfile5') + if has('unix') + edit Xfile5 + " sleep for some time to make sure the timestamp is different + sleep 200m + call writefile(['two'], 'Xfile5') + set autoread + call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call assert_fails('checktime', 'E342:') + set autoread& + bw! + endif + + " test for :vimgrep loading a dummy buffer + call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call assert_fails('vimgrep two Xfile5', 'E342:') + call delete('Xfile5') + + " test for quickfix command loading a buffer + call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call assert_fails('cexpr "Xfile6:10:Line10"', 'E342:') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_swap.vim b/src/nvim/testdir/test_swap.vim index cf46b4c5bd..ceadc1d85a 100644 --- a/src/nvim/testdir/test_swap.vim +++ b/src/nvim/testdir/test_swap.vim @@ -235,7 +235,6 @@ func Test_swap_recover() autocmd SwapExists * let v:swapchoice = 'r' augroup END - call mkdir('Xswap') let $Xswap = 'foo' " Check for issue #4369. set dir=Xswap// -- cgit From 1e513fd112767e57f2b39dfaa395c83cb4f6a9f7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 21:01:36 +0800 Subject: vim-patch:8.2.4670: memory allocation failures for new tab page not tested Problem: Memory allocation failures for new tab page not tested. Solution: Add tests with failing memory allocation. (Yegappan Lakshmanan, closes vim/vim#10067) https://github.com/vim/vim/commit/72bb47e38f6805050ed6d969f17591bed71f83d4 Co-authored-by: Yegappan Lakshmanan --- src/nvim/testdir/test_blob.vim | 41 ++++++++++++++++++++++++++++++++ src/nvim/testdir/test_buffer.vim | 26 ++++++++++---------- src/nvim/testdir/test_tabpage.vim | 24 +++++++++++++++++++ src/nvim/testdir/test_window_cmd.vim | 46 ++++++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index f889da987a..310582240c 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -1,5 +1,6 @@ " Tests for the Blob types +source check.vim source vim9.vim func TearDown() @@ -714,6 +715,46 @@ func Test_blob2string() call assert_equal(v, string(b)) endfunc +" Test for blob allocation failure +func Test_blob_alloc_failure() + CheckFunction test_alloc_fail + " blob variable + call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) + call assert_fails('let v = 0z10', 'E342:') + + " blob slice + let v = 0z1020 + call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) + call assert_fails('let x = v[0:0]', 'E342:') + call assert_equal(0z1020, x) + + " blob remove() + let v = 0z10203040 + call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) + call assert_fails('let x = remove(v, 1, 2)', 'E342:') + call assert_equal(0, x) + + " list2blob() + call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) + call assert_fails('let a = list2blob([1, 2, 4])', 'E342:') + call assert_equal(0, a) + + " mapnew() + call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) + call assert_fails('let x = mapnew(0z1234, {_, v -> 1})', 'E342:') + call assert_equal(0, x) + + " copy() + call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) + call assert_fails('let x = copy(v)', 'E342:') + call assert_equal(0z, x) + + " readblob() + call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) + call assert_fails('let x = readblob("test_blob.vim")', 'E342:') + call assert_equal(0, x) +endfunc + " Test for the indexof() function func Test_indexof() let b = 0zdeadbeef diff --git a/src/nvim/testdir/test_buffer.vim b/src/nvim/testdir/test_buffer.vim index 90e97ae167..98eba83f73 100644 --- a/src/nvim/testdir/test_buffer.vim +++ b/src/nvim/testdir/test_buffer.vim @@ -451,51 +451,51 @@ func Test_buffer_maxmem() " set maxmem& maxmemtot& endfunc -" Test for a allocation failure when adding a new buffer +" Test for buffer allocation failure func Test_buflist_alloc_failure() CheckFunction test_alloc_fail %bw! edit Xfile1 - call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) call assert_fails('edit Xfile2', 'E342:') " test for bufadd() - call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) call assert_fails('call bufadd("Xbuffer")', 'E342:') " test for setting the arglist edit Xfile2 - call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) call assert_fails('next Xfile3', 'E342:') " test for setting the alternate buffer name when writing a file - call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) call assert_fails('write Xother', 'E342:') call delete('Xother') " test for creating a buffer using bufnr() - call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) call assert_fails("call bufnr('Xnewbuf', v:true)", 'E342:') " test for renaming buffer using :file - call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) call assert_fails('file Xnewfile', 'E342:') " test for creating a buffer for a popup window - call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) call assert_fails('call popup_create("mypop", {})', 'E342:') if has('terminal') " test for creating a buffer for a terminal window - call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) call assert_fails('call term_start(&shell)', 'E342:') %bw! endif " test for loading a new buffer after wiping out all the buffers edit Xfile4 - call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) call assert_fails('%bw!', 'E342:') " test for :checktime loading the buffer @@ -506,19 +506,19 @@ func Test_buflist_alloc_failure() sleep 200m call writefile(['two'], 'Xfile5') set autoread - call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) call assert_fails('checktime', 'E342:') set autoread& bw! endif " test for :vimgrep loading a dummy buffer - call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) call assert_fails('vimgrep two Xfile5', 'E342:') call delete('Xfile5') " test for quickfix command loading a buffer - call test_alloc_fail(GetAllocId('buflistnew_bvars'), 0, 0) + call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) call assert_fails('cexpr "Xfile6:10:Line10"', 'E342:') endfunc diff --git a/src/nvim/testdir/test_tabpage.vim b/src/nvim/testdir/test_tabpage.vim index c20c798c49..db23a36dd4 100644 --- a/src/nvim/testdir/test_tabpage.vim +++ b/src/nvim/testdir/test_tabpage.vim @@ -846,6 +846,30 @@ func Test_lastused_tabpage() tabonly! endfunc +" Test for tabpage allocation failure +func Test_tabpage_alloc_failure() + CheckFunction test_alloc_fail + call test_alloc_fail(GetAllocId('newtabpage_tvars'), 0, 0) + call assert_fails('tabnew', 'E342:') + + call test_alloc_fail(GetAllocId('newtabpage_tvars'), 0, 0) + edit Xfile1 + call assert_fails('tabedit Xfile2', 'E342:') + call assert_equal(1, winnr('$')) + call assert_equal(1, tabpagenr('$')) + call assert_equal('Xfile1', @%) + + new + call test_alloc_fail(GetAllocId('newtabpage_tvars'), 0, 0) + call assert_fails('wincmd T', 'E342:') + bw! + + call test_alloc_fail(GetAllocId('newtabpage_tvars'), 0, 0) + call assert_fails('tab split', 'E342:') + call assert_equal(2, winnr('$')) + call assert_equal(1, tabpagenr('$')) +endfunc + " this was giving ml_get errors func Test_tabpage_last_line() enew diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim index 8b9457ae1d..34614832a9 100644 --- a/src/nvim/testdir/test_window_cmd.vim +++ b/src/nvim/testdir/test_window_cmd.vim @@ -1525,6 +1525,52 @@ func Test_win_move_statusline() %bwipe! endfunc +" Test for window allocation failure +func Test_window_alloc_failure() + CheckFunction test_alloc_fail + %bw! + + " test for creating a new window above current window + call test_alloc_fail(GetAllocId('newwin_wvars'), 0, 0) + call assert_fails('above new', 'E342:') + call assert_equal(1, winnr('$')) + + " test for creating a new window below current window + call test_alloc_fail(GetAllocId('newwin_wvars'), 0, 0) + call assert_fails('below new', 'E342:') + call assert_equal(1, winnr('$')) + + " test for popup window creation failure + call test_alloc_fail(GetAllocId('newwin_wvars'), 0, 0) + call assert_fails('call popup_create("Hello", {})', 'E342:') + call assert_equal([], popup_list()) + + call test_alloc_fail(GetAllocId('newwin_wvars'), 0, 0) + call assert_fails('split', 'E342:') + call assert_equal(1, winnr('$')) + + edit Xfile1 + edit Xfile2 + call test_alloc_fail(GetAllocId('newwin_wvars'), 0, 0) + call assert_fails('sb Xfile1', 'E342:') + call assert_equal(1, winnr('$')) + call assert_equal('Xfile2', @%) + %bw! + + " FIXME: The following test crashes Vim + " test for new tabpage creation failure + " call test_alloc_fail(GetAllocId('newwin_wvars'), 0, 0) + " call assert_fails('tabnew', 'E342:') + " call assert_equal(1, tabpagenr('$')) + " call assert_equal(1, winnr('$')) + + " This test messes up the internal Vim window/frame information. So the + " Test_window_cmd_cmdwin_with_vsp() test fails after running this test. + " Open a new tab and close everything else to fix this issue. + tabnew + tabonly +endfunc + func Test_win_equal_last_status() let save_lines = &lines set lines=20 -- cgit From 278aeee3aed753d1084597378e653395bd472c42 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 21:07:56 +0800 Subject: vim-patch:9.0.0430: cannot use repeat() with a blob Problem: Cannot use repeat() with a blob. Solution: Implement blob repeat. (closes vim/vim#11090) https://github.com/vim/vim/commit/375141e1f80dced9be738568a3418f65813f4a2f Co-authored-by: Bakudankun --- src/nvim/eval.c | 4 +++- src/nvim/eval/funcs.c | 31 +++++++++++++++++++++++++++++++ src/nvim/eval/typval.c | 4 ++-- src/nvim/testdir/test_blob.vim | 12 ++++++++++++ 4 files changed, 48 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index b81384266c..0fbf31a8cd 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1613,7 +1613,7 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool lp->ll_n2 = tv_blob_len(lp->ll_blob) - 1; } - if (tv_blob_set_range(lp->ll_blob, lp->ll_n1, lp->ll_n2, rettv) == FAIL) { + if (tv_blob_set_range(lp->ll_blob, (int)lp->ll_n1, (int)lp->ll_n2, rettv) == FAIL) { return; } } else { @@ -4938,6 +4938,8 @@ theend: return retval; } +/// "function()" function +/// "funcref()" function void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref) { char *s; diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 5da6233e38..4208c5ca46 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5976,6 +5976,37 @@ static void f_repeat(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) while (n-- > 0) { tv_list_extend(rettv->vval.v_list, argvars[0].vval.v_list, NULL); } + } else if (argvars[0].v_type == VAR_BLOB) { + tv_blob_alloc_ret(rettv); + if (argvars[0].vval.v_blob == NULL || n <= 0) { + return; + } + + const int slen = argvars[0].vval.v_blob->bv_ga.ga_len; + const int len = (int)(slen * n); + if (len <= 0) { + return; + } + + ga_grow(&rettv->vval.v_blob->bv_ga, len); + + rettv->vval.v_blob->bv_ga.ga_len = len; + + int i; + for (i = 0; i < slen; i++) { + if (tv_blob_get(argvars[0].vval.v_blob, i) != 0) { + break; + } + } + + if (i == slen) { + // No need to copy since all bytes are already zero + return; + } + + for (i = 0; i < n; i++) { + tv_blob_set_range(rettv->vval.v_blob, i * slen, (i + 1) * slen - 1, argvars); + } } else { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 6037536548..7d49049b0c 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2743,14 +2743,14 @@ int tv_blob_check_range(int bloblen, varnumber_T n1, varnumber_T n2, bool quiet) /// Set bytes "n1" to "n2" (inclusive) in "dest" to the value of "src". /// Caller must make sure "src" is a blob. /// Returns FAIL if the number of bytes does not match. -int tv_blob_set_range(blob_T *dest, long n1, long n2, typval_T *src) +int tv_blob_set_range(blob_T *dest, int n1, int n2, typval_T *src) { if (n2 - n1 + 1 != tv_blob_len(src->vval.v_blob)) { emsg(_("E972: Blob value does not have the right number of bytes")); return FAIL; } - for (int il = (int)n1, ir = 0; il <= (int)n2; il++) { + for (int il = n1, ir = 0; il <= n2; il++) { tv_blob_set(dest, il, tv_blob_get(src->vval.v_blob, ir++)); } return OK; diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index 310582240c..2c145f2019 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -715,6 +715,18 @@ func Test_blob2string() call assert_equal(v, string(b)) endfunc +func Test_blob_repeat() + call assert_equal(0z, repeat(0z00, 0)) + call assert_equal(0z00, repeat(0z00, 1)) + call assert_equal(0z0000, repeat(0z00, 2)) + call assert_equal(0z00000000, repeat(0z0000, 2)) + + call assert_equal(0z, repeat(0z12, 0)) + call assert_equal(0z, repeat(0z1234, 0)) + call assert_equal(0z1234, repeat(0z1234, 1)) + call assert_equal(0z12341234, repeat(0z1234, 2)) +endfunc + " Test for blob allocation failure func Test_blob_alloc_failure() CheckFunction test_alloc_fail -- cgit From cf07f2baabd3a1a072102e0cacb6d70509ada044 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 27 Feb 2023 12:29:20 +0100 Subject: feat(edit)!: remove old c implementation of hebrew keymap This feature has long been obsolete. The 'keymap' option can be used to support language keymaps, including hebrew and hebrewp (phonetic mapping). There is no need to keep the old c code with hardcoded keymaps for some languages. --- src/nvim/edit.c | 105 +---------------------------------- src/nvim/ex_getln.c | 11 ---- src/nvim/main.c | 4 +- src/nvim/normal.c | 4 -- src/nvim/option.c | 4 -- src/nvim/option_defs.h | 3 - src/nvim/options.lua | 10 ++-- src/nvim/screen.c | 3 - src/nvim/testdir/test_charsearch.vim | 1 + src/nvim/testdir/test_cmdline.vim | 3 +- src/nvim/testdir/test_edit.vim | 4 +- src/nvim/testdir/test_paste.vim | 7 ++- src/nvim/testdir/test_startup.vim | 8 +-- 13 files changed, 21 insertions(+), 146 deletions(-) (limited to 'src') diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 8143af7d1f..7522cc202e 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -523,10 +523,6 @@ static int insert_execute(VimState *state, int key) did_cursorhold = true; } - if (p_hkmap && KeyTyped) { - s->c = hkmap(s->c); // Hebrew mode mapping - } - // Special handling of keys while the popup menu is visible or wanted // and the cursor is still in the completed word. Only when there is // a match, skip this when no matches were found. @@ -2140,9 +2136,6 @@ void insertchar(int c, int flags, int second_indent) || (virtcol += byte2cells((uint8_t)buf[i - 1])) < (colnr_T)textwidth) && !(!no_abbr && !vim_iswordc(c) && vim_iswordc((uint8_t)buf[i - 1]))) { c = vgetc(); - if (p_hkmap && KeyTyped) { - c = hkmap(c); // Hebrew mode mapping - } buf[i++] = (char)c; } @@ -3212,101 +3205,6 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) return false; } -// Map Hebrew keyboard when in hkmap mode. -int hkmap(int c) - FUNC_ATTR_PURE -{ - if (p_hkmapp) { // phonetic mapping, by Ilya Dogolazky - enum { - hALEF = 0, BET, GIMEL, DALET, HEI, VAV, ZAIN, HET, TET, IUD, - KAFsofit, hKAF, LAMED, MEMsofit, MEM, NUNsofit, NUN, SAMEH, AIN, - PEIsofit, PEI, ZADIsofit, ZADI, KOF, RESH, hSHIN, TAV, - }; - static char_u map[26] = { - (char_u)hALEF, // a - (char_u)BET, // b - (char_u)hKAF, // c - (char_u)DALET, // d - (char_u) - 1, // e - (char_u)PEIsofit, // f - (char_u)GIMEL, // g - (char_u)HEI, // h - (char_u)IUD, // i - (char_u)HET, // j - (char_u)KOF, // k - (char_u)LAMED, // l - (char_u)MEM, // m - (char_u)NUN, // n - (char_u)SAMEH, // o - (char_u)PEI, // p - (char_u) - 1, // q - (char_u)RESH, // r - (char_u)ZAIN, // s - (char_u)TAV, // t - (char_u)TET, // u - (char_u)VAV, // v - (char_u)hSHIN, // w - (char_u) - 1, // x - (char_u)AIN, // y - (char_u)ZADI, // z - }; - - if (c == 'N' || c == 'M' || c == 'P' || c == 'C' || c == 'Z') { - return (int)(map[CHAR_ORD(c)] - 1 + p_aleph); - } else if (c == 'x') { // '-1'='sofit' - return 'X'; - } else if (c == 'q') { - return '\''; // {geresh}={'} - } else if (c == 246) { - return ' '; // \"o --> ' ' for a german keyboard - } else if (c == 228) { - return ' '; // \"a --> ' ' -- / -- - } else if (c == 252) { - return ' '; // \"u --> ' ' -- / -- - } else if (c >= 'a' && c <= 'z') { - // NOTE: islower() does not do the right thing for us on Linux so we - // do this the same was as 5.7 and previous, so it works correctly on - // all systems. Specifically, the e.g. Delete and Arrow keys are - // munged and won't work if e.g. searching for Hebrew text. - return (int)(map[CHAR_ORD_LOW(c)] + p_aleph); - } else { - return c; - } - } else { - switch (c) { - case '`': - return ';'; - case '/': - return '.'; - case '\'': - return ','; - case 'q': - return '/'; - case 'w': - return '\''; - - // Hebrew letters - set offset from 'a' - case ',': - c = '{'; break; - case '.': - c = 'v'; break; - case ';': - c = 't'; break; - default: { - static char_u str[] = "zqbcxlsjphmkwonu ydafe rig"; - - if (c < 'a' || c > 'z') { - return c; - } - c = str[CHAR_ORD_LOW(c)]; - break; - } - } - - return (int)(CHAR_ORD_LOW(c) + p_aleph); - } -} - static void ins_reg(void) { bool need_redraw = false; @@ -3581,7 +3479,7 @@ static bool ins_esc(long *count, int cmdchar, bool nomove) return true; } -// Toggle language: hkmap and revins_on. +// Toggle language: revins_on. // Move to end of reverse inserted text. static void ins_ctrl_(void) { @@ -3600,7 +3498,6 @@ static void ins_ctrl_(void) } else { revins_scol = -1; } - p_hkmap = curwin->w_p_rl ^ p_ri; // be consistent! showmode(); } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index af26fe8a1c..376352a13b 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -189,8 +189,6 @@ static int cedit_key = -1; ///< key value of 'cedit' option static handle_T cmdpreview_bufnr = 0; static long cmdpreview_ns = 0; -static int cmd_hkmap = 0; // Hebrew mapping during command line - static void save_viewstate(win_T *wp, viewstate_T *vs) FUNC_ATTR_NONNULL_ALL { @@ -680,11 +678,6 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea s->break_ctrl_c = true; } - // start without Hebrew mapping for a command line - if (s->firstc == ':' || s->firstc == '=' || s->firstc == '>') { - cmd_hkmap = 0; - } - init_ccline(s->firstc, s->indent); ccline.prompt_id = last_prompt_id++; ccline.level = cmdline_level; @@ -1166,9 +1159,6 @@ static int command_line_execute(VimState *state, int key) if (KeyTyped) { s->some_key_typed = true; - if (cmd_hkmap) { - s->c = hkmap(s->c); - } if (cmdmsg_rl && !KeyStuffed) { // Invert horizontal movements and operations. Only when @@ -2101,7 +2091,6 @@ static int command_line_handle_key(CommandLineState *s) if (!p_ari) { break; } - cmd_hkmap = !cmd_hkmap; return command_line_not_changed(s); default: diff --git a/src/nvim/main.c b/src/nvim/main.c index 5f4e639b06..975772169b 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1147,8 +1147,8 @@ static void command_line_scan(mparm_T *parmp) case 'h': // "-h" give help message usage(); os_exit(0); - case 'H': // "-H" start in Hebrew mode: rl + hkmap set. - p_hkmap = true; + case 'H': // "-H" start in Hebrew mode: rl + keymap=hebrew set. + set_option_value_give_err("keymap", 0L, "hebrew", 0); set_option_value_give_err("rl", 1L, NULL, 0); break; case 'M': // "-M" no changes or writing of files diff --git a/src/nvim/normal.c b/src/nvim/normal.c index ef8f6e7b0f..f7c99d5991 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -769,10 +769,6 @@ static void normal_get_additional_char(NormalState *s) // adjust chars > 127, except after "tTfFr" commands LANGMAP_ADJUST(*cp, !lang); - // adjust Hebrew mapped char - if (p_hkmap && lang && KeyTyped) { - *cp = hkmap(*cp); - } } // When the next character is CTRL-\ a following CTRL-N means the diff --git a/src/nvim/option.c b/src/nvim/option.c index 069304d9e1..0303f0bccd 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -5026,7 +5026,6 @@ static void paste_option_changed(void) static int save_sta = 0; static int save_ru = 0; static int save_ri = 0; - static int save_hkmap = 0; if (p_paste) { // Paste switched from off to on. @@ -5052,7 +5051,6 @@ static void paste_option_changed(void) save_sta = p_sta; save_ru = p_ru; save_ri = p_ri; - save_hkmap = p_hkmap; // save global values for local buffer options p_ai_nopaste = p_ai; p_et_nopaste = p_et; @@ -5089,7 +5087,6 @@ static void paste_option_changed(void) } p_ru = 0; // no ruler p_ri = 0; // no reverse insert - p_hkmap = 0; // no Hebrew keyboard // set global values for local buffer options p_tw = 0; p_wm = 0; @@ -5129,7 +5126,6 @@ static void paste_option_changed(void) } p_ru = save_ru; p_ri = save_ri; - p_hkmap = save_hkmap; // set global values for local buffer options p_ai = p_ai_nopaste; p_et = p_et_nopaste; diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 0e0cc4c983..0c78d7ada5 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -386,7 +386,6 @@ enum { // The following are actual variables for the options -EXTERN long p_aleph; // 'aleph' EXTERN char *p_ambw; ///< 'ambiwidth' EXTERN int p_acd; ///< 'autochdir' EXTERN int p_ai; ///< 'autoindent' @@ -544,8 +543,6 @@ EXTERN int p_hid; // 'hidden' EXTERN char *p_hl; // 'highlight' EXTERN int p_hls; // 'hlsearch' EXTERN long p_hi; // 'history' -EXTERN int p_hkmap; // 'hkmap' -EXTERN int p_hkmapp; // 'hkmapp' EXTERN int p_arshape; // 'arabicshape' EXTERN int p_icon; // 'icon' EXTERN char *p_iconstring; // 'iconstring' diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 387ccd0888..a4ee114f39 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -55,8 +55,6 @@ return { full_name='aleph', abbreviation='al', short_desc=N_("ASCII code of the letter Aleph (Hebrew)"), type='number', scope={'global'}, - redraw={'curswant'}, - varname='p_aleph', defaults={if_true=224} }, { @@ -1071,16 +1069,16 @@ return { }, { full_name='hkmap', abbreviation='hk', - short_desc=N_("Hebrew keyboard mapping"), + short_desc=N_("No description"), type='bool', scope={'global'}, - varname='p_hkmap', + varname='p_force_off', defaults={if_true=false} }, { full_name='hkmapp', abbreviation='hkp', - short_desc=N_("phonetic Hebrew keyboard mapping"), + short_desc=N_("No description"), type='bool', scope={'global'}, - varname='p_hkmapp', + varname='p_force_off', defaults={if_true=false} }, { diff --git a/src/nvim/screen.c b/src/nvim/screen.c index da9178bdff..61594860d2 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -534,9 +534,6 @@ int showmode(void) } else if (restart_edit == 'V') { msg_puts_attr(_(" (vreplace)"), attr); } - if (p_hkmap) { - msg_puts_attr(_(" Hebrew"), attr); - } if (State & MODE_LANGMAP) { if (curwin->w_p_arab) { msg_puts_attr(_(" Arabic"), attr); diff --git a/src/nvim/testdir/test_charsearch.vim b/src/nvim/testdir/test_charsearch.vim index 54e0a62ce5..f8f3e958ca 100644 --- a/src/nvim/testdir/test_charsearch.vim +++ b/src/nvim/testdir/test_charsearch.vim @@ -86,6 +86,7 @@ endfunc " Test for character search with 'hkmap' func Test_charsearch_hkmap() + throw "Skipped: Nvim does not support 'hkmap'" new set hkmap call setline(1, "ùðáâ÷ëòéïçìêöî") diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index d568b5d425..1dceb43e5d 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -2111,7 +2111,8 @@ func Test_cmdline_revins() call assert_equal("\"abc\", @:) set allowrevins call feedkeys(":\"abc\xyz\\", 'xt') - call assert_equal('"abcñèæ', @:) + " call assert_equal('"abcñèæ', @:) + call assert_equal('"abcxyz', @:) set allowrevins& endfunc diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim index b6078a1e22..075f78ec76 100644 --- a/src/nvim/testdir/test_edit.vim +++ b/src/nvim/testdir/test_edit.vim @@ -516,7 +516,8 @@ func Test_edit_CTRL_() call setline(1, ['abc']) call cursor(1, 1) call feedkeys("i\xyz\", 'tnix') - call assert_equal(["æèñabc"], getline(1, '$')) + " call assert_equal(["æèñabc"], getline(1, '$')) + call assert_equal(["zyxabc"], getline(1, '$')) call assert_true(&revins) call setline(1, ['abc']) call cursor(1, 1) @@ -1913,6 +1914,7 @@ endfunc " Test for 'hkmap' and 'hkmapp' func Test_edit_hkmap() + throw "Skipped: Nvim does not support 'hkmap'" CheckFeature rightleft if has('win32') && !has('gui') " Test fails on the MS-Windows terminal version diff --git a/src/nvim/testdir/test_paste.vim b/src/nvim/testdir/test_paste.vim index dad3c2c6a0..923f4f42a6 100644 --- a/src/nvim/testdir/test_paste.vim +++ b/src/nvim/testdir/test_paste.vim @@ -20,7 +20,8 @@ endfunc func Test_paste_opt_restore() set autoindent expandtab ruler showmatch if has('rightleft') - set revins hkmap + " set hkmap + set revins endif set smarttab softtabstop=3 textwidth=27 wrapmargin=12 if has('vartabs') @@ -33,7 +34,7 @@ func Test_paste_opt_restore() call assert_false(&expandtab) if has('rightleft') call assert_false(&revins) - call assert_false(&hkmap) + " call assert_false(&hkmap) endif call assert_false(&ruler) call assert_false(&showmatch) @@ -51,7 +52,7 @@ func Test_paste_opt_restore() call assert_true(&expandtab) if has('rightleft') call assert_true(&revins) - call assert_true(&hkmap) + " call assert_true(&hkmap) endif call assert_true(&ruler) call assert_true(&showmatch) diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim index 1ee1d0dfe3..8216b1a894 100644 --- a/src/nvim/testdir/test_startup.vim +++ b/src/nvim/testdir/test_startup.vim @@ -389,7 +389,7 @@ endfunc " Test the -A, -F and -H arguments (Arabic, Farsi and Hebrew modes). func Test_A_F_H_arg() let after =<< trim [CODE] - call writefile([&rightleft, &arabic, 0, &hkmap], "Xtestout") + call writefile([&rightleft, &arabic, 0, &hkmap, &keymap], "Xtestout") qall [CODE] @@ -397,17 +397,17 @@ func Test_A_F_H_arg() " 'encoding' is not utf-8. if has('arabic') && &encoding == 'utf-8' && RunVim([], after, '-e -s -A') let lines = readfile('Xtestout') - call assert_equal(['1', '1', '0', '0'], lines) + call assert_equal(['1', '1', '0', '0', 'arabic'], lines) endif if has('farsi') && RunVim([], after, '-F') let lines = readfile('Xtestout') - call assert_equal(['1', '0', '1', '0'], lines) + call assert_equal(['1', '0', '1', '0', '???'], lines) endif if has('rightleft') && RunVim([], after, '-H') let lines = readfile('Xtestout') - call assert_equal(['1', '0', '0', '1'], lines) + call assert_equal(['1', '0', '0', '0', 'hebrew'], lines) endif call delete('Xtestout') -- cgit From 999fe9468862e22fa5317585f67f5cb32683fc15 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 1 Mar 2023 08:17:09 +0800 Subject: vim-patch:9.0.1365: dead test code (#22461) Problem: Dead test code. Solution: Remove code that depends on Farsi, which has been removed. (closes vim/vim#12084) https://github.com/vim/vim/commit/f0300fc7b81e63c2584dc3a763dedea4184d17e5 --- src/nvim/testdir/test_startup.vim | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim index 8216b1a894..da467ea23f 100644 --- a/src/nvim/testdir/test_startup.vim +++ b/src/nvim/testdir/test_startup.vim @@ -386,8 +386,8 @@ func Test_m_M_R() call delete('Xtestout') endfunc -" Test the -A, -F and -H arguments (Arabic, Farsi and Hebrew modes). -func Test_A_F_H_arg() +" Test the -A and -H arguments (Arabic and Hebrew modes). +func Test_A_H_arg() let after =<< trim [CODE] call writefile([&rightleft, &arabic, 0, &hkmap, &keymap], "Xtestout") qall @@ -400,11 +400,6 @@ func Test_A_F_H_arg() call assert_equal(['1', '1', '0', '0', 'arabic'], lines) endif - if has('farsi') && RunVim([], after, '-F') - let lines = readfile('Xtestout') - call assert_equal(['1', '0', '1', '0', '???'], lines) - endif - if has('rightleft') && RunVim([], after, '-H') let lines = readfile('Xtestout') call assert_equal(['1', '0', '0', '0', 'hebrew'], lines) -- cgit From f25d126b186e187f539a909824804d4bc88380e0 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 1 Mar 2023 23:23:39 +0800 Subject: vim-patch:8.2.{1949,2781} (#22451) vim-patch:8.2.2781: add() silently skips when adding to null list or blob Problem: Add() silently skips when adding to null list or blob. Solution: Give an error in Vim9 script. Allocate blob when it is NULL like with list and dict. https://github.com/vim/vim/commit/b7c21afef14bba0208f2c40d47c050a004eb2f34 Do not implicitly change a NULL blob/dict/list to an empty one. N/A patches for version.c: vim-patch:8.2.1949: Vim9: using extend() on null dict is silently ignored Problem: Vim9: using extend() on null dict is silently ignored. Solution: Give an error message. Initialize a dict variable with an empty dictionary. (closes vim/vim#7251) https://github.com/vim/vim/commit/348be7ed07d164970ec0004bc278e254eb0cf5bf N/A because Nvim's current behavior is an error message as a locked list/dict, which is more consistent. Ref #4615. Co-authored-by: Bram Moolenaar --- src/nvim/testdir/test_blob.vim | 56 +++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim index 2c145f2019..920ceb826d 100644 --- a/src/nvim/testdir/test_blob.vim +++ b/src/nvim/testdir/test_blob.vim @@ -317,27 +317,59 @@ func Test_blob_for_loop() endfunc func Test_blob_concatenate() - let b = 0z0011 - let b += 0z2233 - call assert_equal(0z00112233, b) + let lines =<< trim END + VAR b = 0z0011 + LET b += 0z2233 + call assert_equal(0z00112233, b) - call assert_fails('let b += "a"') - call assert_fails('let b += 88') + LET b = 0zDEAD + 0zBEEF + call assert_equal(0zDEADBEEF, b) + END + call CheckLegacyAndVim9Success(lines) - let b = 0zDEAD + 0zBEEF - call assert_equal(0zDEADBEEF, b) + let lines =<< trim END + VAR b = 0z0011 + LET b += "a" + END + call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:']) + + let lines =<< trim END + VAR b = 0z0011 + LET b += 88 + END + call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:']) endfunc func Test_blob_add() + let lines =<< trim END + VAR b = 0z0011 + call add(b, 0x22) + call assert_equal(0z001122, b) + END + call CheckLegacyAndVim9Success(lines) + + " Only works in legacy script let b = 0z0011 - call add(b, 0x22) - call assert_equal(0z001122, b) call add(b, '51') - call assert_equal(0z00112233, b) + call assert_equal(0z001133, b) call assert_equal(1, add(v:_null_blob, 0x22)) - call assert_fails('call add(b, [9])', 'E745:') - call assert_fails('call add("", 0x01)', 'E897:') + let lines =<< trim END + VAR b = 0z0011 + call add(b, [9]) + END + call CheckLegacyAndVim9Failure(lines, ['E745:', 'E1012:', 'E745:']) + + let lines =<< trim END + VAR b = 0z0011 + call add("", 0x01) + END + call CheckLegacyAndVim9Failure(lines, 'E897:') + + let lines =<< trim END + add(v:_null_blob, 0x22) + END + call CheckDefExecAndScriptFailure(lines, 'E1131:') endfunc func Test_blob_empty() -- cgit From a0292b4e5f106482edc5623eef85aa48e2e55bb7 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Thu, 2 Mar 2023 10:22:41 +0100 Subject: build: remove libfindmacros library (#22423) Large parts the library weren't being used, and the parts that were was overly abstracted for our use case. Additionally, part of its use case was to abstract pkgconfig boilerplate, which is no longer needed as pkgconfig has been removed in favor of relying on cmake alone in 09118052cee5aef978d6075db5287c1b6c27381a. --- src/nvim/CMakeLists.txt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 8884273649..9bd79a6ba7 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -25,29 +25,31 @@ set_target_properties(luv PROPERTIES IMPORTED_LOCATION ${LIBLUV_LIBRARIES}) target_link_libraries(main_lib INTERFACE luv) find_package(TreeSitter REQUIRED) -target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${TreeSitter_INCLUDE_DIRS}) -target_link_libraries(main_lib INTERFACE ${TreeSitter_LIBRARIES}) +target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${TreeSitter_INCLUDE_DIR}) +target_link_libraries(main_lib INTERFACE ${TreeSitter_LIBRARY}) find_package(unibilium 2.0 REQUIRED) target_link_libraries(main_lib INTERFACE unibilium) find_package(LibTermkey 0.22 REQUIRED) -target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBTERMKEY_INCLUDE_DIRS}) -target_link_libraries(main_lib INTERFACE ${LIBTERMKEY_LIBRARIES}) +target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBTERMKEY_INCLUDE_DIR}) +target_link_libraries(main_lib INTERFACE ${LIBTERMKEY_LIBRARY}) find_package(libvterm 0.3 REQUIRED) target_link_libraries(main_lib INTERFACE libvterm) find_package(Iconv REQUIRED) -target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${Iconv_INCLUDE_DIRS}) -target_link_libraries(main_lib INTERFACE ${Iconv_LIBRARIES}) +target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${ICONV_INCLUDE_DIR}) +if(ICONV_LIBRARY) + target_link_libraries(main_lib INTERFACE ${ICONV_LIBRARY}) +endif() option(ENABLE_LIBINTL "enable libintl" ON) if(ENABLE_LIBINTL) # LibIntl (not Intl) selects our FindLibIntl.cmake script. #8464 find_package(LibIntl REQUIRED) - target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LibIntl_INCLUDE_DIRS}) - if (LibIntl_FOUND) + target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LibIntl_INCLUDE_DIR}) + if (LibIntl_LIBRARY) target_link_libraries(main_lib INTERFACE ${LibIntl_LIBRARY}) endif() endif() -- cgit From 4cf4ae93df6af09ef3a0df678bb3d154b65bf731 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Thu, 2 Mar 2023 22:50:43 +0100 Subject: build: cmake cleanup (#22251) - Remove unused code - Use consistent casing. Variable names such as LibLuV_LIBRARIES is needlessly jarring, even if the name might be technically correct. - Use title casing for packages. find_package(unibilium) requires the find_module to be named "Findunibilium.cmake", which makes it harder to spot when scanning the files. Instead, use "Unibilium". --- src/nvim/CMakeLists.txt | 122 ++++++++++++--------------------------------- src/nvim/po/CMakeLists.txt | 3 -- 2 files changed, 33 insertions(+), 92 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 9bd79a6ba7..8c23b501f9 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -1,22 +1,19 @@ add_library(main_lib INTERFACE) add_executable(nvim main.c) -add_library(libuv_lib INTERFACE) +add_library(libuv INTERFACE) find_package(libuv CONFIG) if(TARGET libuv::uv_a) - target_link_libraries(libuv_lib INTERFACE libuv::uv_a) + target_link_libraries(libuv INTERFACE libuv::uv_a) + mark_as_advanced(libuv_DIR) else() # Fall back to find module for older libuv versions that don't provide config file - find_package(LibUV 1.28.0 REQUIRED MODULE) - target_include_directories(libuv_lib SYSTEM BEFORE INTERFACE ${LIBUV_INCLUDE_DIRS}) - target_link_libraries(libuv_lib INTERFACE ${LIBUV_LIBRARIES}) + find_package(Libuv 1.28.0 REQUIRED MODULE) + target_include_directories(libuv SYSTEM BEFORE INTERFACE ${LIBUV_INCLUDE_DIRS}) + target_link_libraries(libuv INTERFACE ${LIBUV_LIBRARIES}) endif() -find_package(Msgpack 1.0.0 REQUIRED) -target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${MSGPACK_INCLUDE_DIRS}) -target_link_libraries(main_lib INTERFACE ${MSGPACK_LIBRARIES}) - -find_package(LibLUV 1.43.0 REQUIRED) +find_package(Libluv 1.43.0 REQUIRED) target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBLUV_INCLUDE_DIRS}) # Use "luv" as imported library, to work around CMake using "-lluv" for # "luv.so". #10407 @@ -24,33 +21,28 @@ add_library(luv UNKNOWN IMPORTED) set_target_properties(luv PROPERTIES IMPORTED_LOCATION ${LIBLUV_LIBRARIES}) target_link_libraries(main_lib INTERFACE luv) -find_package(TreeSitter REQUIRED) -target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${TreeSitter_INCLUDE_DIR}) -target_link_libraries(main_lib INTERFACE ${TreeSitter_LIBRARY}) - -find_package(unibilium 2.0 REQUIRED) -target_link_libraries(main_lib INTERFACE unibilium) - -find_package(LibTermkey 0.22 REQUIRED) -target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBTERMKEY_INCLUDE_DIR}) -target_link_libraries(main_lib INTERFACE ${LIBTERMKEY_LIBRARY}) - -find_package(libvterm 0.3 REQUIRED) -target_link_libraries(main_lib INTERFACE libvterm) - find_package(Iconv REQUIRED) -target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${ICONV_INCLUDE_DIR}) -if(ICONV_LIBRARY) - target_link_libraries(main_lib INTERFACE ${ICONV_LIBRARY}) -endif() +find_package(Libtermkey 0.22 REQUIRED) +find_package(Libvterm 0.3 REQUIRED) +find_package(Msgpack 1.0.0 REQUIRED) +find_package(Treesitter REQUIRED) +find_package(Unibilium 2.0 REQUIRED) + +target_link_libraries(main_lib INTERFACE + iconv + libtermkey + libvterm + msgpack + treesitter + unibilium) option(ENABLE_LIBINTL "enable libintl" ON) if(ENABLE_LIBINTL) - # LibIntl (not Intl) selects our FindLibIntl.cmake script. #8464 - find_package(LibIntl REQUIRED) - target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LibIntl_INCLUDE_DIR}) - if (LibIntl_LIBRARY) - target_link_libraries(main_lib INTERFACE ${LibIntl_LIBRARY}) + # Libintl (not Intl) selects our FindLibintl.cmake script. #8464 + find_package(Libintl REQUIRED) + target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBINTL_INCLUDE_DIR}) + if (LIBINTL_LIBRARY) + target_link_libraries(main_lib INTERFACE ${LIBINTL_LIBRARY}) endif() endif() @@ -61,9 +53,9 @@ if(PREFER_LUA) target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LUA_INCLUDE_DIR}) target_link_libraries(main_lib INTERFACE ${LUA_LIBRARIES}) # Passive (not REQUIRED): if LUAJIT_FOUND is not set, fixtures for unittests is skipped. - find_package(LuaJit) + find_package(Luajit) else() - find_package(LuaJit REQUIRED) + find_package(Luajit REQUIRED) target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LUAJIT_INCLUDE_DIRS}) target_link_libraries(main_lib INTERFACE ${LUAJIT_LIBRARIES}) endif() @@ -191,52 +183,6 @@ if(UNSIGNED_CHAR) target_compile_options(main_lib INTERFACE -funsigned-char) endif() -list(APPEND CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}") -check_c_source_compiles(" -#include - -int -main(void) -{ - return MSGPACK_OBJECT_FLOAT32; -} -" MSGPACK_HAS_FLOAT32) -list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}") -if(MSGPACK_HAS_FLOAT32) - target_compile_definitions(main_lib INTERFACE NVIM_MSGPACK_HAS_FLOAT32) -endif() - -list(APPEND CMAKE_REQUIRED_INCLUDES "${TreeSitter_INCLUDE_DIRS}") -list(APPEND CMAKE_REQUIRED_LIBRARIES "${TreeSitter_LIBRARIES}") -check_c_source_compiles(" -#include -int -main(void) -{ - TSQueryCursor *cursor = ts_query_cursor_new(); - ts_query_cursor_set_match_limit(cursor, 32); - return 0; -} -" TS_HAS_SET_MATCH_LIMIT) -if(TS_HAS_SET_MATCH_LIMIT) - target_compile_definitions(main_lib INTERFACE NVIM_TS_HAS_SET_MATCH_LIMIT) -endif() -check_c_source_compiles(" -#include -#include -int -main(void) -{ - ts_set_allocator(malloc, calloc, realloc, free); - return 0; -} -" TS_HAS_SET_ALLOCATOR) -if(TS_HAS_SET_ALLOCATOR) - target_compile_definitions(main_lib INTERFACE NVIM_TS_HAS_SET_ALLOCATOR) -endif() -list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${TreeSitter_INCLUDE_DIRS}") -list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "${TreeSitter_LIBRARIES}") - target_compile_definitions(main_lib INTERFACE INCLUDE_GENERATED_DECLARATIONS) # Remove --sort-common from linker flags, as this seems to cause bugs (see #2641, #3374). @@ -260,7 +206,7 @@ endif() if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") target_link_libraries(nvim PRIVATE -Wl,--no-undefined -lsocket) - elseif(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") + elseif(NOT APPLE) target_link_libraries(nvim PRIVATE -Wl,--no-undefined) endif() @@ -287,7 +233,7 @@ if(WIN32) # Enable wmain target_link_libraries(nvim PRIVATE -municode) endif() -elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") +elseif(APPLE) target_link_libraries(nvim PRIVATE "-framework CoreServices") endif() @@ -437,7 +383,7 @@ else() endif() # Log level (MIN_LOG_LEVEL in log.h) -if($ENV{CI} MATCHES "true") +if($ENV{CI}) set(MIN_LOG_LEVEL 3) endif() if("${MIN_LOG_LEVEL}" MATCHES "^$") @@ -466,7 +412,7 @@ get_target_property(prop main_lib INTERFACE_INCLUDE_DIRECTORIES) foreach(gen_include ${prop}) list(APPEND gen_cflags "-I${gen_include}") endforeach() -if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_OSX_SYSROOT) +if(APPLE AND CMAKE_OSX_SYSROOT) list(APPEND gen_cflags "-isysroot") list(APPEND gen_cflags "${CMAKE_OSX_SYSROOT}") endif() @@ -718,7 +664,7 @@ if(${CMAKE_VERSION} VERSION_LESS 3.20) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) endif() -target_link_libraries(nvim PRIVATE main_lib PUBLIC libuv_lib) +target_link_libraries(nvim PRIVATE main_lib PUBLIC libuv) install_helper(TARGETS nvim) if(MSVC) install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) @@ -829,12 +775,10 @@ if(WIN32) file(WRITE ${PROJECT_BINARY_DIR}/external_blobs.cmake ${EXTERNAL_BLOBS_SCRIPT}) add_custom_target(external_blobs COMMAND ${CMAKE_COMMAND} -P ${PROJECT_BINARY_DIR}/external_blobs.cmake) - set_target_properties(external_blobs PROPERTIES FOLDER deps) add_dependencies(nvim_runtime_deps external_blobs) else() add_custom_target(nvim_runtime_deps) # Stub target to avoid CMP0046. endif() -set_target_properties(nvim_runtime_deps PROPERTIES FOLDER deps) file(MAKE_DIRECTORY ${BINARY_LIB_DIR}) @@ -862,7 +806,7 @@ set_target_properties( OUTPUT_NAME ${LIBNVIM_NAME} ) target_compile_definitions(libnvim PRIVATE MAKE_LIB) -target_link_libraries(libnvim PRIVATE main_lib PUBLIC libuv_lib) +target_link_libraries(libnvim PRIVATE main_lib PUBLIC libuv) if(CLANG_ASAN_UBSAN) message(STATUS "Enabling Clang address sanitizer and undefined behavior sanitizer for nvim.") diff --git a/src/nvim/po/CMakeLists.txt b/src/nvim/po/CMakeLists.txt index 74f043fe03..68e572911c 100644 --- a/src/nvim/po/CMakeLists.txt +++ b/src/nvim/po/CMakeLists.txt @@ -95,7 +95,6 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG) COMMENT "Checking ${name}.po" VERBATIM DEPENDS ${poFile}) - set_target_properties(check-po-${name} PROPERTIES FOLDER po/check) endmacro() macro(BuildPoIconvGenericWithCharset @@ -182,9 +181,7 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG) BuildMo(${LANGUAGE}) endforeach() - set_target_properties(${UPDATE_PO_TARGETS} PROPERTIES FOLDER po/update) add_custom_target(translations ALL DEPENDS ${LANGUAGE_MO_FILES}) add_custom_target(update-po DEPENDS ${UPDATE_PO_TARGETS}) - set_target_properties(translations update-po PROPERTIES FOLDER po) endif() -- cgit From fdb6b4d2e729211f0526ce75c6a3fcc636859bfd Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Thu, 2 Mar 2023 17:29:03 -0500 Subject: vim-patch:9.0.1368: Bass files are not recognized (#22485) Problem: Bass files are not recognized. Solution: Add patterns for Bass files. (Amaan Qureshi, closes vim/vim#12088) https://github.com/vim/vim/commit/4ed914b18a47192f79f342bea5e8f59e120d5260 --- src/nvim/testdir/test_filetype.vim | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 148f8b6d42..eb00cb98ca 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -80,6 +80,7 @@ let s:filename_checks = { \ 'awk': ['file.awk', 'file.gawk'], \ 'b': ['file.mch', 'file.ref', 'file.imp'], \ 'basic': ['file.bas', 'file.bi', 'file.bm'], + \ 'bass': ['file.bass'], \ 'bc': ['file.bc'], \ 'bdf': ['file.bdf'], \ 'beancount': ['file.beancount'], -- cgit From 361de6d54d41fc0fc8f8a89ec779696f3f7bb46e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 3 Mar 2023 07:44:16 +0800 Subject: vim-patch:9.0.1371: ballooneval interferes with Insert completion (#22487) Problem: Ballooneval interferes with Insert completion. Solution: Ignore mouse-move events when completing. (closes vim/vim#12094, closes vim/vim#12092) https://github.com/vim/vim/commit/440d4cb55b84fd4b188630abc4a1312598649af0 --- src/nvim/insexpand.c | 14 +++++----- src/nvim/testdir/test_ins_complete.vim | 48 ++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 6de3b0a9d0..8928979455 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -2096,10 +2096,10 @@ bool ins_compl_prep(int c) edit_submode_extra = NULL; } - // Ignore end of Select mode mapping and mouse scroll buttons. + // Ignore end of Select mode mapping and mouse scroll/movement. if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP - || c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_EVENT - || c == K_COMMAND || c == K_LUA) { + || c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_MOUSEMOVE + || c == K_EVENT || c == K_COMMAND || c == K_LUA) { return retval; } @@ -3043,8 +3043,8 @@ static void get_next_spell_completion(linenr_T lnum) /// @param cur_match_pos current match position /// @param match_len /// @param cont_s_ipos next ^X<> will set initial_pos -static char *ins_comp_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_pos, int *match_len, - bool *cont_s_ipos) +static char *ins_compl_get_next_word_or_line(buf_T *ins_buf, pos_T *cur_match_pos, int *match_len, + bool *cont_s_ipos) { *match_len = 0; char *ptr = ml_get_buf(ins_buf, cur_match_pos->lnum, false) + cur_match_pos->col; @@ -3206,8 +3206,8 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_ continue; } int len; - char *ptr = ins_comp_get_next_word_or_line(st->ins_buf, st->cur_match_pos, - &len, &cont_s_ipos); + char *ptr = ins_compl_get_next_word_or_line(st->ins_buf, st->cur_match_pos, + &len, &cont_s_ipos); if (ptr == NULL) { continue; } diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim index ec1379a378..af0856331d 100644 --- a/src/nvim/testdir/test_ins_complete.vim +++ b/src/nvim/testdir/test_ins_complete.vim @@ -375,6 +375,54 @@ func Test_completefunc_info() set completefunc& endfunc +" Test that mouse scrolling/movement should not interrupt completion. +func Test_mouse_scroll_move_during_completion() + new + com! -buffer TestCommand1 echo 'TestCommand1' + com! -buffer TestCommand2 echo 'TestCommand2' + call setline(1, ['', '', '', '', '']) + call cursor(5, 1) + + " Without completion menu scrolling can move text. + set completeopt-=menu wrap + call feedkeys("ccT\\\\", 'tx') + call assert_equal('TestCommand2', getline('.')) + call assert_notequal(1, winsaveview().topline) + call feedkeys("ccT\\\\", 'tx') + call assert_equal('TestCommand2', getline('.')) + call assert_equal(1, winsaveview().topline) + set nowrap + call feedkeys("ccT\\\\", 'tx') + call assert_equal('TestCommand2', getline('.')) + call assert_notequal(0, winsaveview().leftcol) + call feedkeys("ccT\\\\", 'tx') + call assert_equal('TestCommand2', getline('.')) + call assert_equal(0, winsaveview().leftcol) + call feedkeys("ccT\\\\", 'tx') + call assert_equal('TestCommand2', getline('.')) + + " With completion menu scrolling cannot move text. + set completeopt+=menu wrap + call feedkeys("ccT\\\\", 'tx') + call assert_equal('TestCommand2', getline('.')) + call assert_equal(1, winsaveview().topline) + call feedkeys("ccT\\\\", 'tx') + call assert_equal('TestCommand2', getline('.')) + call assert_equal(1, winsaveview().topline) + set nowrap + call feedkeys("ccT\\\\", 'tx') + call assert_equal('TestCommand2', getline('.')) + call assert_equal(0, winsaveview().leftcol) + call feedkeys("ccT\\\\", 'tx') + call assert_equal('TestCommand2', getline('.')) + call assert_equal(0, winsaveview().leftcol) + call feedkeys("ccT\\\\", 'tx') + call assert_equal('TestCommand2', getline('.')) + + bwipe! + set completeopt& wrap& +endfunc + " Check that when using feedkeys() typeahead does not interrupt searching for " completions. func Test_compl_feedkeys() -- cgit From a974d1511e20647b1e60015e6cdd456bd49f4718 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 3 Mar 2023 07:36:41 +0800 Subject: vim-patch:9.0.0690: buffer size for expanding tab not correctly computed Problem: Buffer size for expanding tab not correctly computed. Solution: Correctly use size of end character. https://github.com/vim/vim/commit/a0789478f6ebbb823670b7e14ce13ea3fd3b0217 Co-authored-by: Bram Moolenaar --- src/nvim/drawline.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index bf8649afe0..6b24fe6b46 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -2106,9 +2106,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // If n_extra > 0, it gives the number of chars // to use for a tab, else we need to calculate the width // for a tab. - int len = (tab_len * utf_char2len(wp->w_p_lcs_chars.tab2)); + int tab2_len = utf_char2len(wp->w_p_lcs_chars.tab2); + int len = tab_len * tab2_len; if (wp->w_p_lcs_chars.tab3) { - len += utf_char2len(wp->w_p_lcs_chars.tab3); + len += utf_char2len(wp->w_p_lcs_chars.tab3) - tab2_len; } if (n_extra > 0) { len += n_extra - tab_len; -- cgit From c2e602b9d0a09407179f5ccd8ff5c1a8b409280a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 3 Mar 2023 07:38:13 +0800 Subject: vim-patch:9.0.0691: lalloc(0) error in listchars test Problem: lalloc(0) error in listchars test. Solution: Skip generating text for tab if tab_len is zero. https://github.com/vim/vim/commit/2b7b4f7670f607704307f7715ce56752757c22e3 Co-authored-by: Bram Moolenaar --- src/nvim/drawline.c | 68 +++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 6b24fe6b46..e2a0895fff 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -2103,43 +2103,45 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, tab_len += n_extra - tab_len; } - // If n_extra > 0, it gives the number of chars - // to use for a tab, else we need to calculate the width - // for a tab. - int tab2_len = utf_char2len(wp->w_p_lcs_chars.tab2); - int len = tab_len * tab2_len; - if (wp->w_p_lcs_chars.tab3) { - len += utf_char2len(wp->w_p_lcs_chars.tab3) - tab2_len; - } - if (n_extra > 0) { - len += n_extra - tab_len; - } - c = wp->w_p_lcs_chars.tab1; - p = xmalloc((size_t)len + 1); - memset(p, ' ', (size_t)len); - p[len] = NUL; - xfree(p_extra_free); - p_extra_free = p; - for (int i = 0; i < tab_len; i++) { - if (*p == NUL) { - tab_len = i; - break; + if (tab_len > 0) { + // If n_extra > 0, it gives the number of chars + // to use for a tab, else we need to calculate the + // width for a tab. + int tab2_len = utf_char2len(wp->w_p_lcs_chars.tab2); + int len = tab_len * tab2_len; + if (wp->w_p_lcs_chars.tab3) { + len += utf_char2len(wp->w_p_lcs_chars.tab3) - tab2_len; } - int lcs = wp->w_p_lcs_chars.tab2; + if (n_extra > 0) { + len += n_extra - tab_len; + } + c = wp->w_p_lcs_chars.tab1; + p = xmalloc((size_t)len + 1); + memset(p, ' ', (size_t)len); + p[len] = NUL; + xfree(p_extra_free); + p_extra_free = p; + for (int i = 0; i < tab_len; i++) { + if (*p == NUL) { + tab_len = i; + break; + } + int lcs = wp->w_p_lcs_chars.tab2; - // if tab3 is given, use it for the last char - if (wp->w_p_lcs_chars.tab3 && i == tab_len - 1) { - lcs = wp->w_p_lcs_chars.tab3; + // if tab3 is given, use it for the last char + if (wp->w_p_lcs_chars.tab3 && i == tab_len - 1) { + lcs = wp->w_p_lcs_chars.tab3; + } + p += utf_char2bytes(lcs, p); + n_extra += utf_char2len(lcs) - (saved_nextra > 0 ? 1 : 0); } - p += utf_char2bytes(lcs, p); - n_extra += utf_char2len(lcs) - (saved_nextra > 0 ? 1 : 0); - } - p_extra = p_extra_free; + p_extra = p_extra_free; - // n_extra will be increased by FIX_FOX_BOGUSCOLS - // macro below, so need to adjust for that here - if (vcol_off > 0) { - n_extra -= vcol_off; + // n_extra will be increased by FIX_FOX_BOGUSCOLS + // macro below, so need to adjust for that here + if (vcol_off > 0) { + n_extra -= vcol_off; + } } } -- cgit From 4a3594f60e854db56589f30cec4fc16c8a46fe30 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 3 Mar 2023 07:41:57 +0800 Subject: vim-patch:9.0.0991: crash when reading help index with various options set Problem: Crash when reading help index with various options set. (Marius Gedminas) Solution: Do not set wlv.c_extra to NUL when wlv.p_extra is NULL. (closes vim/vim#11651) https://github.com/vim/vim/commit/c67c89c7589253215d57bad588edcf83a9403560 Co-authored-by: Bram Moolenaar --- src/nvim/drawline.c | 2 +- src/nvim/testdir/test_breakindent.vim | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index e2a0895fff..8f7928e1c9 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -2170,7 +2170,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, c = (n_extra == 0 && wp->w_p_lcs_chars.tab3) ? wp->w_p_lcs_chars.tab3 : wp->w_p_lcs_chars.tab1; - if (wp->w_p_lbr) { + if (wp->w_p_lbr && p_extra != NULL) { c_extra = NUL; // using p_extra from above } else { c_extra = wp->w_p_lcs_chars.tab2; diff --git a/src/nvim/testdir/test_breakindent.vim b/src/nvim/testdir/test_breakindent.vim index 2e377aa434..b61c9a570d 100644 --- a/src/nvim/testdir/test_breakindent.vim +++ b/src/nvim/testdir/test_breakindent.vim @@ -1075,4 +1075,22 @@ func Test_breakindent_column() bwipeout! endfunc +func Test_linebreak_list() + " This was setting wlv.c_extra to NUL while wlv.p_extra is NULL + filetype plugin on + syntax enable + edit! $VIMRUNTIME/doc/index.txt + /v_P + + setlocal list + setlocal listchars=tab:>- + setlocal linebreak + setlocal nowrap + setlocal filetype=help + redraw! + + bwipe! +endfunc + + " vim: shiftwidth=2 sts=2 expandtab -- cgit From bcf077414cf6f1a5701d68f848320008d6d89919 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 3 Mar 2023 07:44:11 +0800 Subject: vim-patch:9.0.1373: wrong text displayed when using both 'linebreak' and 'list' Problem: Wrong text displayed when using both 'linebreak' and 'list'. Solution: Only set "c_extra" to NUL when "p_extra" is not empty. (Hirohito Higashi, closes vim/vim#12065) https://github.com/vim/vim/commit/194555c001f2b8576483ef34511450b6e9b5e3fd Cherry-pick a change from patch 9.0.0153. Co-authored-by: h-east --- src/nvim/drawline.c | 5 +---- src/nvim/testdir/test_listlbr.vim | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 8f7928e1c9..e9ff299d68 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1691,12 +1691,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } else if (foldinfo.fi_lines > 0) { // skip writing the buffer line itself c = NUL; - XFREE_CLEAR(p_extra_free); } else { int c0; - XFREE_CLEAR(p_extra_free); - // Get a character from the line itself. c0 = c = (uint8_t)(*ptr); mb_c = c; @@ -2170,7 +2167,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, c = (n_extra == 0 && wp->w_p_lcs_chars.tab3) ? wp->w_p_lcs_chars.tab3 : wp->w_p_lcs_chars.tab1; - if (wp->w_p_lbr && p_extra != NULL) { + if (wp->w_p_lbr && p_extra != NULL && *p_extra != NUL) { c_extra = NUL; // using p_extra from above } else { c_extra = wp->w_p_lcs_chars.tab2; diff --git a/src/nvim/testdir/test_listlbr.vim b/src/nvim/testdir/test_listlbr.vim index 1cbdba5d76..a746779e73 100644 --- a/src/nvim/testdir/test_listlbr.vim +++ b/src/nvim/testdir/test_listlbr.vim @@ -73,6 +73,30 @@ func Test_linebreak_with_nolist() call s:close_windows() endfunc +func Test_linebreak_with_list_and_number() + call s:test_windows('setl list listchars+=tab:>-') + call setline(1, ["abcdefg\thijklmnopqrstu", "v"]) + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect_nonumber = [ +\ "abcdefg>------------", +\ "hijklmnopqrstu$ ", +\ "v$ ", +\ "~ ", +\ ] + call s:compare_lines(expect_nonumber, lines) + + setl number + let lines = s:screen_lines([1, 4], winwidth(0)) + let expect_number = [ +\ " 1 abcdefg>--------", +\ " hijklmnopqrstu$ ", +\ " 2 v$ ", +\ "~ ", +\ ] + call s:compare_lines(expect_number, lines) + call s:close_windows() +endfunc + func Test_should_break() call s:test_windows('setl sbr=+ nolist') call setline(1, "1\t" . repeat('a', winwidth(0)-2)) -- cgit From 5311c9048a638fecdc066810bb68b60c3048e326 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 3 Mar 2023 14:50:37 +0800 Subject: refactor(win_line): move some variables into a struct (#22490) This reduces the number of arguments to helpers functions. N/A patches for version.c: vim-patch:9.0.0152: warning for unused argument in small build Co-authored-by: Bram Moolenaar --- src/nvim/drawline.c | 1294 ++++++++++++++++++++++++++------------------------- 1 file changed, 651 insertions(+), 643 deletions(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index e9ff299d68..9a56477d83 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -68,6 +68,43 @@ typedef enum { WL_LINE, // text in the line } LineDrawState; +/// structure with variables passed between win_line() and other functions +typedef struct { + LineDrawState draw_state; ///< what to draw next + + linenr_T lnum; ///< line number to be drawn + + int startrow; ///< first row in the window to be drawn + int row; ///< row in the window, excl w_winrow + + colnr_T vcol; ///< virtual column, before wrapping + int col; ///< visual column on screen, after wrapping + int boguscols; ///< nonexistent columns added to "col" to force wrapping + int vcol_off; ///< offset for concealed characters + + int off; ///< offset relative start of line + + int cul_attr; ///< set when 'cursorline' active + int line_attr; ///< attribute for the whole line + int line_attr_lowprio; ///< low-priority attribute for the line + + int char_attr; ///< attributes for next character + + int n_extra; ///< number of extra bytes + char *p_extra; ///< string of extra chars, plus NUL, only used + ///< when c_extra and c_final are NUL + char *p_extra_free; ///< p_extra buffer that needs to be freed + int extra_attr; ///< attributes for p_extra + int c_extra; ///< extra chars, all the same + int c_final; ///< final char, mandatory if set + + char extra[57]; ///< sign, line number and 'fdc' must fit in here + + int filler_lines; ///< nr of filler lines to be drawn + int filler_todo; ///< nr of filler lines still to do + 1 + SignTextAttrs sattrs[SIGN_SHOW_MAX]; ///< sign attributes for the sign column +} winlinevars_T; + /// for line_putchar. Contains the state that needs to be remembered from /// putting one character to the next. typedef struct { @@ -307,93 +344,87 @@ static bool use_cursor_line_sign(win_T *wp, linenr_T lnum) && (wp->w_p_culopt_flags & CULOPT_NBR); } -// Get information needed to display the sign in line 'lnum' in window 'wp'. -// If 'nrcol' is true, the sign is going to be displayed in the number column. -// Otherwise the sign is going to be displayed in the sign column. -// -// @param count max number of signs -// @param[out] n_extrap number of characters from pp_extra to display -// @param sign_idxp Index of the displayed sign -static void get_sign_display_info(bool nrcol, win_T *wp, linenr_T lnum, SignTextAttrs sattrs[], - int row, int startrow, int filler_lines, int filler_todo, - int *c_extrap, int *c_finalp, char *extra, size_t extra_size, - char **pp_extra, int *n_extrap, int *char_attrp, int sign_idx, - int cul_attr) +/// Get information needed to display the sign in line "wlv->lnum" in window "wp". +/// If "nrcol" is true, the sign is going to be displayed in the number column. +/// Otherwise the sign is going to be displayed in the sign column. +static void get_sign_display_info(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx, + int sign_cul_attr) { // Draw cells with the sign value or blank. - *c_extrap = ' '; - *c_finalp = NUL; + wlv->c_extra = ' '; + wlv->c_final = NUL; if (nrcol) { - *n_extrap = number_width(wp) + 1; + wlv->n_extra = number_width(wp) + 1; } else { - if (use_cursor_line_sign(wp, lnum)) { - *char_attrp = win_hl_attr(wp, HLF_CLS); + if (use_cursor_line_sign(wp, wlv->lnum)) { + wlv->char_attr = win_hl_attr(wp, HLF_CLS); } else { - *char_attrp = win_hl_attr(wp, HLF_SC); + wlv->char_attr = win_hl_attr(wp, HLF_SC); } - *n_extrap = win_signcol_width(wp); + wlv->n_extra = win_signcol_width(wp); } - if (row == startrow + filler_lines && filler_todo <= 0) { - SignTextAttrs *sattr = sign_get_attr(sign_idx, sattrs, wp->w_scwidth); + if (wlv->row == wlv->startrow + wlv->filler_lines && wlv->filler_todo <= 0) { + SignTextAttrs *sattr = sign_get_attr(sign_idx, wlv->sattrs, wp->w_scwidth); if (sattr != NULL) { - *pp_extra = sattr->text; - if (*pp_extra != NULL) { - *c_extrap = NUL; - *c_finalp = NUL; + wlv->p_extra = sattr->text; + if (wlv->p_extra != NULL) { + wlv->c_extra = NUL; + wlv->c_final = NUL; if (nrcol) { int n, width = number_width(wp) - 2; for (n = 0; n < width; n++) { - extra[n] = ' '; + wlv->extra[n] = ' '; } - extra[n] = NUL; - STRCAT(extra, *pp_extra); - STRCAT(extra, " "); - *pp_extra = extra; - *n_extrap = (int)strlen(*pp_extra); + wlv->extra[n] = NUL; + STRCAT(wlv->extra, wlv->p_extra); + STRCAT(wlv->extra, " "); + wlv->p_extra = wlv->extra; + wlv->n_extra = (int)strlen(wlv->p_extra); } else { - size_t symbol_blen = strlen(*pp_extra); + size_t symbol_blen = strlen(wlv->p_extra); // TODO(oni-link): Is sign text already extended to // full cell width? - assert((size_t)win_signcol_width(wp) >= mb_string2cells((char *)(*pp_extra))); + assert((size_t)win_signcol_width(wp) >= mb_string2cells(wlv->p_extra)); // symbol(s) bytes + (filling spaces) (one byte each) - *n_extrap = (int)symbol_blen + win_signcol_width(wp) - - (int)mb_string2cells(*pp_extra); + wlv->n_extra = (int)symbol_blen + win_signcol_width(wp) - + (int)mb_string2cells(wlv->p_extra); - assert(extra_size > symbol_blen); - memset(extra, ' ', extra_size); - memcpy(extra, *pp_extra, symbol_blen); + assert(sizeof(wlv->extra) > symbol_blen); + memset(wlv->extra, ' ', sizeof(wlv->extra)); + memcpy(wlv->extra, wlv->p_extra, symbol_blen); - *pp_extra = extra; - (*pp_extra)[*n_extrap] = NUL; + wlv->p_extra = wlv->extra; + wlv->p_extra[wlv->n_extra] = NUL; } } - if (use_cursor_line_sign(wp, lnum) && cul_attr > 0) { - *char_attrp = cul_attr; + if (use_cursor_line_sign(wp, wlv->lnum) && sign_cul_attr > 0) { + wlv->char_attr = sign_cul_attr; } else { - *char_attrp = sattr->hl_attr_id; + wlv->char_attr = sattr->hl_attr_id; } } } } -static int get_sign_attrs(buf_T *buf, linenr_T lnum, SignTextAttrs *sattrs, int *line_attr, - int *num_attr, int *cul_attr) +static int get_sign_attrs(buf_T *buf, winlinevars_T *wlv, int *sign_num_attrp, int *sign_cul_attrp) { - HlPriAttr line_attrs = { *line_attr, 0 }; - HlPriAttr num_attrs = { *num_attr, 0 }; - HlPriAttr cul_attrs = { *cul_attr, 0 }; + HlPriAttr line_attrs = { wlv->line_attr, 0 }; + HlPriAttr num_attrs = { *sign_num_attrp, 0 }; + HlPriAttr cul_attrs = { *sign_cul_attrp, 0 }; // TODO(bfredl, vigoux): line_attr should not take priority over decoration! - int num_signs = buf_get_signattrs(buf, lnum, sattrs, &num_attrs, &line_attrs, &cul_attrs); - decor_redraw_signs(buf, lnum - 1, &num_signs, sattrs, &num_attrs, &line_attrs, &cul_attrs); + int num_signs = buf_get_signattrs(buf, wlv->lnum, wlv->sattrs, &num_attrs, &line_attrs, + &cul_attrs); + decor_redraw_signs(buf, wlv->lnum - 1, &num_signs, wlv->sattrs, &num_attrs, &line_attrs, + &cul_attrs); - *line_attr = line_attrs.attr_id; - *num_attr = num_attrs.attr_id; - *cul_attr = cul_attrs.attr_id; + wlv->line_attr = line_attrs.attr_id; + *sign_num_attrp = num_attrs.attr_id; + *sign_cul_attrp = cul_attrs.attr_id; return num_signs; } @@ -449,30 +480,30 @@ static void get_statuscol_str(win_T *wp, linenr_T lnum, int virtnum, statuscol_T } /// Get information needed to display the next segment in the 'statuscolumn'. -/// If not yet at the end, prepare for next segment and decrement "draw_state". +/// If not yet at the end, prepare for next segment and decrement "wlv->draw_state". /// /// @param stcp Status column attributes -/// @param[out] draw_state Current draw state in win_line() -static void get_statuscol_display_info(statuscol_T *stcp, LineDrawState *draw_state, int *char_attr, - int *n_extrap, int *c_extrap, int *c_finalp, char **pp_extra) +/// @param[in,out] wlv +static void get_statuscol_display_info(statuscol_T *stcp, winlinevars_T *wlv) { - *c_extrap = NUL; - *c_finalp = NUL; + wlv->c_extra = NUL; + wlv->c_final = NUL; do { - *draw_state = WL_STC; - *char_attr = stcp->cur_attr; - *pp_extra = stcp->textp; - *n_extrap = (int)((stcp->hlrecp->start ? stcp->hlrecp->start : stcp->text_end) - stcp->textp); + wlv->draw_state = WL_STC; + wlv->char_attr = stcp->cur_attr; + wlv->p_extra = stcp->textp; + wlv->n_extra = + (int)((stcp->hlrecp->start ? stcp->hlrecp->start : stcp->text_end) - stcp->textp); // Prepare for next highlight section if not yet at the end - if (stcp->textp + *n_extrap < stcp->text_end) { + if (stcp->textp + wlv->n_extra < stcp->text_end) { int hl = stcp->hlrecp->userhl; stcp->textp = stcp->hlrecp->start; stcp->cur_attr = hl < 0 ? syn_id2attr(-hl) : hl > 0 ? hl : stcp->num_attr; stcp->hlrecp++; - *draw_state = WL_STC - 1; + wlv->draw_state = WL_STC - 1; } // Skip over empty highlight sections - } while (*n_extrap == 0 && stcp->textp < stcp->text_end); + } while (wlv->n_extra == 0 && stcp->textp < stcp->text_end); } /// Return true if CursorLineNr highlight is to be used for the number column. @@ -484,13 +515,13 @@ static void get_statuscol_display_info(statuscol_T *stcp, LineDrawState *draw_st /// - When line is wrapped and 'cursorlineopt' does not have "line", only highlight the line number /// itself on the first screenline of the wrapped line, otherwise highlight the number column of /// all screenlines of the wrapped line. -static bool use_cursor_line_nr(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines) +static bool use_cursor_line_nr(win_T *wp, winlinevars_T *wlv) { return wp->w_p_cul - && lnum == wp->w_cursorline + && wlv->lnum == wp->w_cursorline && (wp->w_p_culopt_flags & CULOPT_NBR) - && (row == startrow + filler_lines - || (row > startrow + filler_lines + && (wlv->row == wlv->startrow + wlv->filler_lines + || (wlv->row > wlv->startrow + wlv->filler_lines && (wp->w_p_culopt_flags & CULOPT_LINE))); } @@ -515,20 +546,20 @@ static inline void get_line_number_str(win_T *wp, linenr_T lnum, char *buf, size snprintf(buf, buf_len, fmt, number_width(wp), num); } -static int get_line_number_attr(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines) +static int get_line_number_attr(win_T *wp, winlinevars_T *wlv) { - if (use_cursor_line_nr(wp, lnum, row, startrow, filler_lines)) { + if (use_cursor_line_nr(wp, wlv)) { // TODO(vim): Can we use CursorLine instead of CursorLineNr // when CursorLineNr isn't set? return win_hl_attr(wp, HLF_CLN); } if (wp->w_p_rnu) { - if (lnum < wp->w_cursor.lnum) { + if (wlv->lnum < wp->w_cursor.lnum) { // Use LineNrAbove return win_hl_attr(wp, HLF_LNA); } - if (lnum > wp->w_cursor.lnum) { + if (wlv->lnum > wp->w_cursor.lnum) { // Use LineNrBelow return win_hl_attr(wp, HLF_LNB); } @@ -537,22 +568,21 @@ static int get_line_number_attr(win_T *wp, linenr_T lnum, int row, int startrow, return win_hl_attr(wp, HLF_N); } -static void apply_cursorline_highlight(win_T *wp, linenr_T lnum, int *line_attr, int *cul_attr, - int *line_attr_lowprio) +static void apply_cursorline_highlight(win_T *wp, winlinevars_T *wlv) { - *cul_attr = win_hl_attr(wp, HLF_CUL); - HlAttrs ae = syn_attr2entry(*cul_attr); + wlv->cul_attr = win_hl_attr(wp, HLF_CUL); + HlAttrs ae = syn_attr2entry(wlv->cul_attr); // We make a compromise here (#7383): // * low-priority CursorLine if fg is not set // * high-priority ("same as Vim" priority) CursorLine if fg is set if (ae.rgb_fg_color == -1 && ae.cterm_fg_color == 0) { - *line_attr_lowprio = *cul_attr; + wlv->line_attr_lowprio = wlv->cul_attr; } else { if (!(State & MODE_INSERT) && bt_quickfix(wp->w_buffer) - && qf_current_entry(wp) == lnum) { - *line_attr = hl_combine_attr(*cul_attr, *line_attr); + && qf_current_entry(wp) == wlv->lnum) { + wlv->line_attr = hl_combine_attr(wlv->cul_attr, wlv->line_attr); } else { - *line_attr = *cul_attr; + wlv->line_attr = wlv->cul_attr; } } } @@ -604,6 +634,20 @@ static colnr_T get_leadcol(win_T *wp, const char *ptr, const char *line) return leadcol; } +/// Start a screen line at column zero. +static void win_line_start(win_T *wp, winlinevars_T *wlv) +{ + wlv->col = 0; + wlv->off = 0; + if (wp->w_p_rl) { + // Rightleft window: process the text in the normal direction, but put + // it in linebuf_char[wlv.off] from right to left. Start at the + // rightmost column of the window. + wlv->col = wp->w_grid.cols - 1; + wlv->off += wlv->col; + } +} + /// Display line "lnum" of window 'wp' on the screen. /// wp->w_virtcol needs to be valid. /// @@ -621,23 +665,15 @@ static colnr_T get_leadcol(win_T *wp, const char *ptr, const char *line) int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, bool number_only, foldinfo_T foldinfo, DecorProviders *providers, char **provider_err) { + winlinevars_T wlv; // variables passed between functions + int c = 0; // init for GCC - colnr_T vcol = 0; // virtual column (for tabs) long vcol_sbr = -1; // virtual column after showbreak - long vcol_prev = -1; // "vcol" of previous character + long vcol_prev = -1; // "wlv.vcol" of previous character char *line; // current line char *ptr; // current position in "line" - int row; // row in the window, excl w_winrow ScreenGrid *grid = &wp->w_grid; // grid specific to the window - char extra[57]; // sign, line number and 'fdc' must - // fit in here - int n_extra = 0; // number of extra chars - char *p_extra = NULL; // string of extra chars, plus NUL - char *p_extra_free = NULL; // p_extra needs to be freed - int c_extra = NUL; // extra chars, all the same - int c_final = NUL; // final char, mandatory if set - int extra_attr = 0; // attributes when n_extra != 0 static char *at_end_str = ""; // used for p_extra when displaying curwin->w_p_lcs_chars.eol // at end-of-line bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0; @@ -664,7 +700,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, pos_T pos; ptrdiff_t v; - int char_attr = 0; // attributes for next character bool attr_pri = false; // char_attr has priority bool area_highlighting = false; // Visual or incsearch highlighting in this line int vi_attr = 0; // attributes for Visual and incsearch highlighting @@ -697,17 +732,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int mb_c = 0; // decoded multi-byte character bool mb_utf8 = false; // screen char is UTF-8 char int u8cc[MAX_MCO]; // composing UTF-8 chars - int filler_lines; // nr of filler lines to be drawn - int filler_todo; // nr of filler lines still to do + 1 hlf_T diff_hlf = (hlf_T)0; // type of diff highlighting int change_start = MAXCOL; // first col of changed area int change_end = -1; // last col of changed area bool in_multispace = false; // in multiple consecutive spaces int multispace_pos = 0; // position in lcs-multispace string bool need_showbreak = false; // overlong line, skip first x chars - int line_attr = 0; // attribute for the whole line int line_attr_save; - int line_attr_lowprio = 0; // low-priority attribute for the line int line_attr_lowprio_save; int prev_c = 0; // previous Arabic character int prev_c1 = 0; // first composing char for prev_c @@ -720,7 +751,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, bool area_active = false; - int cul_attr = 0; // set when 'cursorline' active // 'cursorlineopt' has "screenline" and cursor is in this line bool cul_screenline = false; // margin columns for the screen line, needed for when 'cursorlineopt' @@ -728,8 +758,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int left_curline_col = 0; int right_curline_col = 0; - LineDrawState draw_state = WL_START; // what to draw next - int match_conc = 0; ///< cchar for match functions bool on_last_col = false; int syntax_flags = 0; @@ -737,27 +765,28 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int prev_syntax_id = 0; int conceal_attr = win_hl_attr(wp, HLF_CONCEAL); bool is_concealing = false; - int boguscols = 0; ///< nonexistent columns added to - ///< force wrapping - int vcol_off = 0; ///< offset for concealed characters int did_wcol = false; int old_boguscols = 0; -#define VCOL_HLC (vcol - vcol_off) +#define VCOL_HLC (wlv.vcol - wlv.vcol_off) #define FIX_FOR_BOGUSCOLS \ { \ - n_extra += vcol_off; \ - vcol -= vcol_off; \ - vcol_off = 0; \ - col -= boguscols; \ - old_boguscols = boguscols; \ - boguscols = 0; \ + wlv.n_extra += wlv.vcol_off; \ + wlv.vcol -= wlv.vcol_off; \ + wlv.vcol_off = 0; \ + wlv.col -= wlv.boguscols; \ + old_boguscols = wlv.boguscols; \ + wlv.boguscols = 0; \ } if (startrow > endrow) { // past the end already! return startrow; } - row = startrow; + CLEAR_FIELD(wlv); + + wlv.lnum = lnum; + wlv.startrow = startrow; + wlv.row = startrow; buf_T *buf = wp->w_buffer; bool end_fill = (lnum == buf->b_ml.ml_line_count + 1); @@ -935,9 +964,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int bg_attr = win_bg_attr(wp); int linestatus = 0; - filler_lines = diff_check_with_linestatus(wp, lnum, &linestatus); - if (filler_lines < 0 || linestatus < 0) { - if (filler_lines == -1 || linestatus == -1) { + wlv.filler_lines = diff_check_with_linestatus(wp, lnum, &linestatus); + if (wlv.filler_lines < 0 || linestatus < 0) { + if (wlv.filler_lines == -1 || linestatus == -1) { if (diff_find_change(wp, lnum, &change_start, &change_end)) { diff_hlf = HLF_ADD; // added line } else if (change_start == 0) { @@ -949,18 +978,18 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, diff_hlf = HLF_ADD; // added line } if (linestatus == 0) { - filler_lines = 0; + wlv.filler_lines = 0; } area_highlighting = true; } VirtLines virt_lines = KV_INITIAL_VALUE; int n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines, has_fold); - filler_lines += n_virt_lines; + wlv.filler_lines += n_virt_lines; if (lnum == wp->w_topline) { - filler_lines = wp->w_topfill; - n_virt_lines = MIN(n_virt_lines, filler_lines); + wlv.filler_lines = wp->w_topfill; + n_virt_lines = MIN(n_virt_lines, wlv.filler_lines); } - filler_todo = filler_lines; + wlv.filler_todo = wlv.filler_lines; // Cursor line highlighting for 'cursorline' in the current window. if (wp->w_p_cul && wp->w_p_culopt_flags != CULOPT_NBR && lnum == wp->w_cursorline @@ -969,31 +998,29 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, && !(wp == curwin && VIsual_active)) { cul_screenline = (wp->w_p_wrap && (wp->w_p_culopt_flags & CULOPT_SCRLINE)); if (!cul_screenline) { - apply_cursorline_highlight(wp, lnum, &line_attr, &cul_attr, &line_attr_lowprio); + apply_cursorline_highlight(wp, &wlv); } else { margin_columns_win(wp, &left_curline_col, &right_curline_col); } area_highlighting = true; } - SignTextAttrs sattrs[SIGN_SHOW_MAX]; // sign attributes for the sign column int sign_num_attr = 0; // sign attribute for the number column int sign_cul_attr = 0; // sign attribute for cursorline - CLEAR_FIELD(sattrs); - int num_signs = get_sign_attrs(buf, lnum, sattrs, &line_attr, &sign_num_attr, &sign_cul_attr); + int num_signs = get_sign_attrs(buf, &wlv, &sign_num_attr, &sign_cul_attr); // Highlight the current line in the quickfix window. if (bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) { - line_attr = win_hl_attr(wp, HLF_QFL); + wlv.line_attr = win_hl_attr(wp, HLF_QFL); } - if (line_attr_lowprio || line_attr) { + if (wlv.line_attr_lowprio || wlv.line_attr) { area_highlighting = true; } if (cul_screenline) { - line_attr_save = line_attr; - line_attr_lowprio_save = line_attr_lowprio; + line_attr_save = wlv.line_attr; + line_attr_lowprio_save = wlv.line_attr_lowprio; } line = end_fill ? "" : ml_get_buf(wp->w_buffer, lnum, false); @@ -1061,14 +1088,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, chartabsize_T cts; int charsize; - init_chartabsize_arg(&cts, wp, lnum, vcol, line, ptr); + init_chartabsize_arg(&cts, wp, lnum, wlv.vcol, line, ptr); while (cts.cts_vcol < v && *cts.cts_ptr != NUL) { charsize = win_lbr_chartabsize(&cts, NULL); cts.cts_vcol += charsize; prev_ptr = cts.cts_ptr; MB_PTR_ADV(cts.cts_ptr); } - vcol = cts.cts_vcol; + wlv.vcol = cts.cts_vcol; ptr = cts.cts_ptr; clear_chartabsize_arg(&cts); @@ -1078,31 +1105,31 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // - 'virtualedit' is set, or // - the visual mode is active, // the end of the line may be before the start of the displayed part. - if (vcol < v && (wp->w_p_cuc - || draw_color_col - || virtual_active() - || (VIsual_active && wp->w_buffer == curwin->w_buffer))) { - vcol = (colnr_T)v; + if (wlv.vcol < v && (wp->w_p_cuc + || draw_color_col + || virtual_active() + || (VIsual_active && wp->w_buffer == curwin->w_buffer))) { + wlv.vcol = (colnr_T)v; } // Handle a character that's not completely on the screen: Put ptr at // that character but skip the first few screen characters. - if (vcol > v) { - vcol -= charsize; + if (wlv.vcol > v) { + wlv.vcol -= charsize; ptr = prev_ptr; // If the character fits on the screen, don't need to skip it. // Except for a TAB. if (utf_ptr2cells(ptr) >= charsize || *ptr == TAB) { - n_skip = (int)(v - vcol); + n_skip = (int)(v - wlv.vcol); } } // Adjust for when the inverted text is before the screen, // and when the start of the inverted text is before the screen. - if (tocol <= vcol) { + if (tocol <= wlv.vcol) { fromcol = 0; - } else if (fromcol >= 0 && fromcol < vcol) { - fromcol = vcol; + } else if (fromcol >= 0 && fromcol < wlv.vcol) { + fromcol = wlv.vcol; } // When w_skipcol is non-zero, first line needs 'showbreak' @@ -1176,15 +1203,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, ptr = line + v; // "line" may have been updated } - int off = 0; // Offset relative start of line - int col = 0; // Visual column on screen. - if (wp->w_p_rl) { - // Rightleft window: process the text in the normal direction, but put - // it in linebuf_char[off] from right to left. Start at the - // rightmost column of the window. - col = grid->cols - 1; - off += col; - } + win_line_start(wp, &wlv); // won't highlight after TERM_ATTRS_MAX columns int term_attrs[TERM_ATTRS_MAX] = { 0 }; @@ -1197,13 +1216,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (*wp->w_p_stc != NUL) { // Draw the 'statuscolumn' if option is set. statuscol.draw = true; - statuscol.sattrs = sattrs; + statuscol.sattrs = wlv.sattrs; statuscol.foldinfo = foldinfo; statuscol.width = win_col_off(wp) - (cmdwin_type != 0 && wp == curwin); statuscol.use_cul = use_cursor_line_sign(wp, lnum); statuscol.sign_cul_attr = statuscol.use_cul ? sign_cul_attr : 0; - statuscol.num_attr = sign_num_attr ? sign_num_attr - : get_line_number_attr(wp, lnum, row, startrow, filler_lines); + statuscol.num_attr = sign_num_attr ? sign_num_attr : get_line_number_attr(wp, &wlv); } int sign_idx = 0; @@ -1217,27 +1235,27 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, bool did_decrement_ptr = false; // Skip this quickly when working on the text. - if (draw_state != WL_LINE) { + if (wlv.draw_state != WL_LINE) { if (cul_screenline) { - cul_attr = 0; - line_attr = line_attr_save; - line_attr_lowprio = line_attr_lowprio_save; + wlv.cul_attr = 0; + wlv.line_attr = line_attr_save; + wlv.line_attr_lowprio = line_attr_lowprio_save; } - if (draw_state == WL_CMDLINE - 1 && n_extra == 0) { - draw_state = WL_CMDLINE; + if (wlv.draw_state == WL_CMDLINE - 1 && wlv.n_extra == 0) { + wlv.draw_state = WL_CMDLINE; if (cmdwin_type != 0 && wp == curwin) { // Draw the cmdline character. - n_extra = 1; - c_extra = cmdwin_type; - c_final = NUL; - char_attr = win_hl_attr(wp, HLF_AT); + wlv.n_extra = 1; + wlv.c_extra = cmdwin_type; + wlv.c_final = NUL; + wlv.char_attr = win_hl_attr(wp, HLF_AT); } } - if (draw_state == WL_FOLD - 1 && n_extra == 0) { - if (filler_todo > 0) { - int index = filler_todo - (filler_lines - n_virt_lines); + if (wlv.draw_state == WL_FOLD - 1 && wlv.n_extra == 0) { + if (wlv.filler_todo > 0) { + int index = wlv.filler_todo - (wlv.filler_lines - n_virt_lines); if (index > 0) { virt_line_index = (int)kv_size(virt_lines) - index; assert(virt_line_index >= 0); @@ -1246,152 +1264,143 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } if (!virt_line_offset) { // Skip the column states if there is a "virt_left_col" line. - draw_state = WL_BRI - 1; + wlv.draw_state = WL_BRI - 1; } else if (statuscol.draw) { // Skip fold, sign and number states if 'statuscolumn' is set. - draw_state = WL_STC - 1; + wlv.draw_state = WL_STC - 1; } } - if (draw_state == WL_FOLD - 1 && n_extra == 0) { + if (wlv.draw_state == WL_FOLD - 1 && wlv.n_extra == 0) { int fdc = compute_foldcolumn(wp, 0); - draw_state = WL_FOLD; + wlv.draw_state = WL_FOLD; if (fdc > 0) { - // Draw the 'foldcolumn'. Allocate a buffer, "extra" may - // already be in use. - xfree(p_extra_free); - p_extra_free = xmalloc(MAX_MCO * (size_t)fdc + 1); - n_extra = (int)fill_foldcolumn(p_extra_free, wp, foldinfo, lnum); - p_extra_free[n_extra] = NUL; - p_extra = p_extra_free; - c_extra = NUL; - c_final = NUL; + // Draw the 'foldcolumn'. + // Allocate a buffer, "wlv->extra[]" may already be in use. + xfree(wlv.p_extra_free); + wlv.p_extra_free = xmalloc(MAX_MCO * (size_t)fdc + 1); + wlv.n_extra = (int)fill_foldcolumn(wlv.p_extra_free, wp, foldinfo, lnum); + wlv.p_extra_free[wlv.n_extra] = NUL; + wlv.p_extra = wlv.p_extra_free; + wlv.c_extra = NUL; + wlv.c_final = NUL; if (use_cursor_line_sign(wp, lnum)) { - char_attr = win_hl_attr(wp, HLF_CLF); + wlv.char_attr = win_hl_attr(wp, HLF_CLF); } else { - char_attr = win_hl_attr(wp, HLF_FC); + wlv.char_attr = win_hl_attr(wp, HLF_FC); } } } // sign column, this is hit until sign_idx reaches count - if (draw_state == WL_SIGN - 1 && n_extra == 0) { - draw_state = WL_SIGN; + if (wlv.draw_state == WL_SIGN - 1 && wlv.n_extra == 0) { + wlv.draw_state = WL_SIGN; // Show the sign column when there are any signs in this buffer if (wp->w_scwidth > 0) { - get_sign_display_info(false, wp, lnum, sattrs, row, - startrow, filler_lines, filler_todo, - &c_extra, &c_final, extra, sizeof(extra), - &p_extra, &n_extra, &char_attr, sign_idx, - sign_cul_attr); + get_sign_display_info(false, wp, &wlv, sign_idx, sign_cul_attr); sign_idx++; if (sign_idx < wp->w_scwidth) { - draw_state = WL_SIGN - 1; + wlv.draw_state = WL_SIGN - 1; } else { sign_idx = 0; } } } - if (draw_state == WL_NR - 1 && n_extra == 0) { - draw_state = WL_NR; + if (wlv.draw_state == WL_NR - 1 && wlv.n_extra == 0) { + wlv.draw_state = WL_NR; // Display the absolute or relative line number. After the // first fill with blanks when the 'n' flag isn't in 'cpo' if ((wp->w_p_nu || wp->w_p_rnu) - && (row == startrow + filler_lines + && (wlv.row == startrow + wlv.filler_lines || vim_strchr(p_cpo, CPO_NUMCOL) == NULL)) { // If 'signcolumn' is set to 'number' and a sign is present // in 'lnum', then display the sign instead of the line // number. if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' && num_signs > 0) { - get_sign_display_info(true, wp, lnum, sattrs, row, - startrow, filler_lines, filler_todo, - &c_extra, &c_final, extra, sizeof(extra), - &p_extra, &n_extra, &char_attr, sign_idx, - sign_cul_attr); + get_sign_display_info(true, wp, &wlv, sign_idx, sign_cul_attr); } else { // Draw the line number (empty space after wrapping). - if (row == startrow + filler_lines) { - get_line_number_str(wp, lnum, extra, sizeof(extra)); + if (wlv.row == startrow + wlv.filler_lines) { + get_line_number_str(wp, lnum, wlv.extra, sizeof(wlv.extra)); if (wp->w_skipcol > 0) { - for (p_extra = extra; *p_extra == ' '; p_extra++) { - *p_extra = '-'; + for (wlv.p_extra = wlv.extra; *wlv.p_extra == ' '; wlv.p_extra++) { + *wlv.p_extra = '-'; } } if (wp->w_p_rl) { // reverse line numbers // like rl_mirror(), but keep the space at the end - char *p2 = skipwhite(extra); + char *p2 = skipwhite(wlv.extra); p2 = skiptowhite(p2) - 1; - for (char *p1 = skipwhite(extra); p1 < p2; p1++, p2--) { + for (char *p1 = skipwhite(wlv.extra); p1 < p2; p1++, p2--) { const char t = *p1; *p1 = *p2; *p2 = t; } } - p_extra = extra; - c_extra = NUL; + wlv.p_extra = wlv.extra; + wlv.c_extra = NUL; } else { - c_extra = ' '; + wlv.c_extra = ' '; } - c_final = NUL; - n_extra = number_width(wp) + 1; + wlv.c_final = NUL; + wlv.n_extra = number_width(wp) + 1; if (sign_num_attr > 0) { - char_attr = sign_num_attr; + wlv.char_attr = sign_num_attr; } else { - char_attr = get_line_number_attr(wp, lnum, row, startrow, filler_lines); + wlv.char_attr = get_line_number_attr(wp, &wlv); } } } } - if (draw_state == WL_STC - 1 && n_extra == 0) { - draw_state = WL_STC; + if (wlv.draw_state == WL_STC - 1 && wlv.n_extra == 0) { + wlv.draw_state = WL_STC; // Draw the 'statuscolumn' if option is set. if (statuscol.draw) { if (statuscol.textp == NULL) { - get_statuscol_str(wp, lnum, row - startrow - filler_lines, &statuscol); + get_statuscol_str(wp, lnum, wlv.row - startrow - wlv.filler_lines, &statuscol); if (wp->w_redr_statuscol) { break; } } - get_statuscol_display_info(&statuscol, &draw_state, &char_attr, - &n_extra, &c_extra, &c_final, &p_extra); + get_statuscol_display_info(&statuscol, &wlv); } } - if (draw_state == WL_STC && n_extra == 0) { - win_col_offset = off; + if (wlv.draw_state == WL_STC && wlv.n_extra == 0) { + win_col_offset = wlv.off; } - if (wp->w_briopt_sbr && draw_state == WL_BRI - 1 - && n_extra == 0 && *get_showbreak_value(wp) != NUL) { + if (wp->w_briopt_sbr && wlv.draw_state == WL_BRI - 1 + && wlv.n_extra == 0 && *get_showbreak_value(wp) != NUL) { // draw indent after showbreak value - draw_state = WL_BRI; - } else if (wp->w_briopt_sbr && draw_state == WL_SBR && n_extra == 0) { + wlv.draw_state = WL_BRI; + } else if (wp->w_briopt_sbr && wlv.draw_state == WL_SBR && wlv.n_extra == 0) { // after the showbreak, draw the breakindent - draw_state = WL_BRI - 1; + wlv.draw_state = WL_BRI - 1; } // draw 'breakindent': indent wrapped text accordingly - if (draw_state == WL_BRI - 1 && n_extra == 0) { - draw_state = WL_BRI; + if (wlv.draw_state == WL_BRI - 1 && wlv.n_extra == 0) { + wlv.draw_state = WL_BRI; // if need_showbreak is set, breakindent also applies - if (wp->w_p_bri && (row != startrow || need_showbreak) - && filler_lines == 0) { - char_attr = 0; + if (wp->w_p_bri && (wlv.row != startrow || need_showbreak) + && wlv.filler_lines == 0) { + wlv.char_attr = 0; if (diff_hlf != (hlf_T)0) { - char_attr = win_hl_attr(wp, (int)diff_hlf); + wlv.char_attr = win_hl_attr(wp, (int)diff_hlf); } - p_extra = NULL; - c_extra = ' '; - c_final = NUL; - n_extra = + wlv.p_extra = NULL; + wlv.c_extra = ' '; + wlv.c_final = NUL; + wlv.n_extra = get_breakindent_win(wp, ml_get_buf(wp->w_buffer, lnum, false)); - if (row == startrow) { - n_extra -= win_col_off2(wp); - if (n_extra < 0) { - n_extra = 0; + if (wlv.row == startrow) { + wlv.n_extra -= win_col_off2(wp); + if (wlv.n_extra < 0) { + wlv.n_extra = 0; } } if (wp->w_skipcol > 0 && wp->w_p_wrap && wp->w_briopt_sbr) { @@ -1399,174 +1408,174 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } // Correct end of highlighted area for 'breakindent', // required wen 'linebreak' is also set. - if (tocol == vcol) { - tocol += n_extra; + if (tocol == wlv.vcol) { + tocol += wlv.n_extra; } } } - if (draw_state == WL_SBR - 1 && n_extra == 0) { - draw_state = WL_SBR; - if (filler_todo > filler_lines - n_virt_lines) { + if (wlv.draw_state == WL_SBR - 1 && wlv.n_extra == 0) { + wlv.draw_state = WL_SBR; + if (wlv.filler_todo > wlv.filler_lines - n_virt_lines) { // TODO(bfredl): check this doesn't inhibit TUI-style // clear-to-end-of-line. - c_extra = ' '; - c_final = NUL; + wlv.c_extra = ' '; + wlv.c_final = NUL; if (wp->w_p_rl) { - n_extra = col + 1; + wlv.n_extra = wlv.col + 1; } else { - n_extra = grid->cols - col; + wlv.n_extra = grid->cols - wlv.col; } - char_attr = 0; - } else if (filler_todo > 0) { + wlv.char_attr = 0; + } else if (wlv.filler_todo > 0) { // Draw "deleted" diff line(s) if (char2cells(wp->w_p_fcs_chars.diff) > 1) { - c_extra = '-'; - c_final = NUL; + wlv.c_extra = '-'; + wlv.c_final = NUL; } else { - c_extra = wp->w_p_fcs_chars.diff; - c_final = NUL; + wlv.c_extra = wp->w_p_fcs_chars.diff; + wlv.c_final = NUL; } if (wp->w_p_rl) { - n_extra = col + 1; + wlv.n_extra = wlv.col + 1; } else { - n_extra = grid->cols - col; + wlv.n_extra = grid->cols - wlv.col; } - char_attr = win_hl_attr(wp, HLF_DED); + wlv.char_attr = win_hl_attr(wp, HLF_DED); } char *const sbr = get_showbreak_value(wp); if (*sbr != NUL && need_showbreak) { // Draw 'showbreak' at the start of each broken line. - p_extra = sbr; - c_extra = NUL; - c_final = NUL; - n_extra = (int)strlen(sbr); - char_attr = win_hl_attr(wp, HLF_AT); + wlv.p_extra = sbr; + wlv.c_extra = NUL; + wlv.c_final = NUL; + wlv.n_extra = (int)strlen(sbr); + wlv.char_attr = win_hl_attr(wp, HLF_AT); if (wp->w_skipcol == 0 || !wp->w_p_wrap) { need_showbreak = false; } - vcol_sbr = vcol + mb_charlen(sbr); + vcol_sbr = wlv.vcol + mb_charlen(sbr); // Correct end of highlighted area for 'showbreak', // required when 'linebreak' is also set. - if (tocol == vcol) { - tocol += n_extra; + if (tocol == wlv.vcol) { + tocol += wlv.n_extra; } // Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'. - if (cul_attr) { - char_attr = hl_combine_attr(cul_attr, char_attr); + if (wlv.cul_attr) { + wlv.char_attr = hl_combine_attr(wlv.cul_attr, wlv.char_attr); } } } - if (draw_state == WL_LINE - 1 && n_extra == 0) { + if (wlv.draw_state == WL_LINE - 1 && wlv.n_extra == 0) { sign_idx = 0; - draw_state = WL_LINE; + wlv.draw_state = WL_LINE; - if (has_decor && row == startrow + filler_lines) { + if (has_decor && wlv.row == startrow + wlv.filler_lines) { // hide virt_text on text hidden by 'nowrap' - decor_redraw_col(wp->w_buffer, vcol, off, true, &decor_state); + decor_redraw_col(wp->w_buffer, wlv.vcol, wlv.off, true, &decor_state); } if (saved_n_extra) { // Continue item from end of wrapped line. - n_extra = saved_n_extra; - c_extra = saved_c_extra; - c_final = saved_c_final; - p_extra = saved_p_extra; - char_attr = saved_char_attr; + wlv.n_extra = saved_n_extra; + wlv.c_extra = saved_c_extra; + wlv.c_final = saved_c_final; + wlv.p_extra = saved_p_extra; + wlv.char_attr = saved_char_attr; } else { - char_attr = 0; + wlv.char_attr = 0; } } } - if (cul_screenline && draw_state == WL_LINE - && vcol >= left_curline_col - && vcol < right_curline_col) { - apply_cursorline_highlight(wp, lnum, &line_attr, &cul_attr, &line_attr_lowprio); + if (cul_screenline && wlv.draw_state == WL_LINE + && wlv.vcol >= left_curline_col + && wlv.vcol < right_curline_col) { + apply_cursorline_highlight(wp, &wlv); } // When still displaying '$' of change command, stop at cursor if (((dollar_vcol >= 0 && wp == curwin && lnum == wp->w_cursor.lnum - && vcol >= (long)wp->w_virtcol) - || (number_only && draw_state > WL_STC)) - && filler_todo <= 0) { - draw_virt_text(wp, buf, win_col_offset, &col, grid->cols, row); - grid_put_linebuf(grid, row, 0, col, -grid->cols, wp->w_p_rl, wp, bg_attr, false); + && wlv.vcol >= (long)wp->w_virtcol) + || (number_only && wlv.draw_state > WL_STC)) + && wlv.filler_todo <= 0) { + draw_virt_text(wp, buf, win_col_offset, &wlv.col, grid->cols, wlv.row); + grid_put_linebuf(grid, wlv.row, 0, wlv.col, -grid->cols, wp->w_p_rl, wp, bg_attr, false); // Pretend we have finished updating the window. Except when // 'cursorcolumn' is set. if (wp->w_p_cuc) { - row = wp->w_cline_row + wp->w_cline_height; + wlv.row = wp->w_cline_row + wp->w_cline_height; } else { - row = grid->rows; + wlv.row = grid->rows; } break; } - if (draw_state == WL_LINE + if (wlv.draw_state == WL_LINE && has_fold - && col == win_col_offset - && n_extra == 0 - && row == startrow + filler_lines) { - char_attr = win_hl_attr(wp, HLF_FL); + && wlv.col == win_col_offset + && wlv.n_extra == 0 + && wlv.row == startrow + wlv.filler_lines) { + wlv.char_attr = win_hl_attr(wp, HLF_FL); linenr_T lnume = lnum + foldinfo.fi_lines - 1; memset(buf_fold, ' ', FOLD_TEXT_LEN); - p_extra = get_foldtext(wp, lnum, lnume, foldinfo, buf_fold); - n_extra = (int)strlen(p_extra); + wlv.p_extra = get_foldtext(wp, lnum, lnume, foldinfo, buf_fold); + wlv.n_extra = (int)strlen(wlv.p_extra); - if (p_extra != buf_fold) { - xfree(p_extra_free); - p_extra_free = p_extra; + if (wlv.p_extra != buf_fold) { + xfree(wlv.p_extra_free); + wlv.p_extra_free = wlv.p_extra; } - c_extra = NUL; - c_final = NUL; - p_extra[n_extra] = NUL; + wlv.c_extra = NUL; + wlv.c_final = NUL; + wlv.p_extra[wlv.n_extra] = NUL; } - if (draw_state == WL_LINE + if (wlv.draw_state == WL_LINE && has_fold - && col < grid->cols - && n_extra == 0 - && row == startrow + filler_lines) { + && wlv.col < grid->cols + && wlv.n_extra == 0 + && wlv.row == startrow + wlv.filler_lines) { // fill rest of line with 'fold' - c_extra = wp->w_p_fcs_chars.fold; - c_final = NUL; + wlv.c_extra = wp->w_p_fcs_chars.fold; + wlv.c_final = NUL; - n_extra = wp->w_p_rl ? (col + 1) : (grid->cols - col); + wlv.n_extra = wp->w_p_rl ? (wlv.col + 1) : (grid->cols - wlv.col); } - if (draw_state == WL_LINE + if (wlv.draw_state == WL_LINE && has_fold - && col >= grid->cols - && n_extra != 0 - && row == startrow + filler_lines) { + && wlv.col >= grid->cols + && wlv.n_extra != 0 + && wlv.row == startrow + wlv.filler_lines) { // Truncate the folding. - n_extra = 0; + wlv.n_extra = 0; } - if (draw_state == WL_LINE && (area_highlighting || has_spell)) { + if (wlv.draw_state == WL_LINE && (area_highlighting || has_spell)) { // handle Visual or match highlighting in this line - if (vcol == fromcol - || (vcol + 1 == fromcol && n_extra == 0 + if (wlv.vcol == fromcol + || (wlv.vcol + 1 == fromcol && wlv.n_extra == 0 && utf_ptr2cells(ptr) > 1) || ((int)vcol_prev == fromcol_prev - && vcol_prev < vcol // not at margin - && vcol < tocol)) { + && vcol_prev < wlv.vcol // not at margin + && wlv.vcol < tocol)) { area_attr = vi_attr; // start highlighting if (area_highlighting) { area_active = true; } - } else if (area_attr != 0 && (vcol == tocol + } else if (area_attr != 0 && (wlv.vcol == tocol || (noinvcur - && vcol == wp->w_virtcol))) { + && wlv.vcol == wp->w_virtcol))) { area_attr = 0; // stop highlighting area_active = false; } - if (!n_extra) { + if (!wlv.n_extra) { // Check for start/end of 'hlsearch' and other matches. // After end, check for start/end of next match. // When another match, have to check for start again. @@ -1585,20 +1594,20 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (diff_hlf != (hlf_T)0) { if (diff_hlf == HLF_CHD && ptr - line >= change_start - && n_extra == 0) { + && wlv.n_extra == 0) { diff_hlf = HLF_TXD; // changed text } if (diff_hlf == HLF_TXD && ptr - line > change_end - && n_extra == 0) { + && wlv.n_extra == 0) { diff_hlf = HLF_CHD; // changed line } - line_attr = win_hl_attr(wp, (int)diff_hlf); + wlv.line_attr = win_hl_attr(wp, (int)diff_hlf); // Overlay CursorLine onto diff-mode highlight. - if (cul_attr) { - line_attr = 0 != line_attr_lowprio // Low-priority CursorLine - ? hl_combine_attr(hl_combine_attr(cul_attr, line_attr), + if (wlv.cul_attr) { + wlv.line_attr = 0 != wlv.line_attr_lowprio // Low-priority CursorLine + ? hl_combine_attr(hl_combine_attr(wlv.cul_attr, wlv.line_attr), hl_get_underline()) - : hl_combine_attr(line_attr, cul_attr); + : hl_combine_attr(wlv.line_attr, wlv.cul_attr); } } @@ -1606,25 +1615,25 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, attr_pri = true; if (area_attr != 0) { - char_attr = hl_combine_attr(line_attr, area_attr); + wlv.char_attr = hl_combine_attr(wlv.line_attr, area_attr); if (!highlight_match) { // let search highlight show in Visual area if possible - char_attr = hl_combine_attr(search_attr, char_attr); + wlv.char_attr = hl_combine_attr(search_attr, wlv.char_attr); } } else if (search_attr != 0) { - char_attr = hl_combine_attr(line_attr, search_attr); - } else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL) - || vcol < fromcol || vcol_prev < fromcol_prev - || vcol >= tocol)) { - // Use line_attr when not in the Visual or 'incsearch' area + wlv.char_attr = hl_combine_attr(wlv.line_attr, search_attr); + } else if (wlv.line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL) + || wlv.vcol < fromcol || vcol_prev < fromcol_prev + || wlv.vcol >= tocol)) { + // Use wlv.line_attr when not in the Visual or 'incsearch' area // (area_attr may be 0 when "noinvcur" is set). - char_attr = line_attr; + wlv.char_attr = wlv.line_attr; } else { attr_pri = false; if (has_syntax) { - char_attr = syntax_attr; + wlv.char_attr = syntax_attr; } else { - char_attr = 0; + wlv.char_attr = 0; } } } @@ -1638,23 +1647,23 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // "p_extra" must end in a NUL to avoid utfc_ptr2len() reads past // "p_extra[n_extra]". // For the '$' of the 'list' option, n_extra == 1, p_extra == "". - if (n_extra > 0) { - if (c_extra != NUL || (n_extra == 1 && c_final != NUL)) { - c = (n_extra == 1 && c_final != NUL) ? c_final : c_extra; + if (wlv.n_extra > 0) { + if (wlv.c_extra != NUL || (wlv.n_extra == 1 && wlv.c_final != NUL)) { + c = (wlv.n_extra == 1 && wlv.c_final != NUL) ? wlv.c_final : wlv.c_extra; mb_c = c; // doesn't handle non-utf-8 multi-byte! mb_utf8 = check_mb_utf8(&c, u8cc); } else { - assert(p_extra != NULL); - c = (uint8_t)(*p_extra); + assert(wlv.p_extra != NULL); + c = (uint8_t)(*wlv.p_extra); mb_c = c; // If the UTF-8 character is more than one byte: // Decode it into "mb_c". - mb_l = utfc_ptr2len(p_extra); + mb_l = utfc_ptr2len(wlv.p_extra); mb_utf8 = false; - if (mb_l > n_extra) { + if (mb_l > wlv.n_extra) { mb_l = 1; } else if (mb_l > 1) { - mb_c = utfc_ptr2char(p_extra, u8cc); + mb_c = utfc_ptr2char(wlv.p_extra, u8cc); mb_utf8 = true; c = 0xc0; } @@ -1663,7 +1672,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } // If a double-width char doesn't fit display a '>' in the last column. - if ((wp->w_p_rl ? (col <= 0) : (col >= grid->cols - 1)) + if ((wp->w_p_rl ? (wlv.col <= 0) : (wlv.col >= grid->cols - 1)) && utf_char2cells(mb_c) == 2) { c = '>'; mb_c = c; @@ -1671,23 +1680,23 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, (void)mb_l; multi_attr = win_hl_attr(wp, HLF_AT); - if (cul_attr) { - multi_attr = 0 != line_attr_lowprio - ? hl_combine_attr(cul_attr, multi_attr) - : hl_combine_attr(multi_attr, cul_attr); + if (wlv.cul_attr) { + multi_attr = 0 != wlv.line_attr_lowprio + ? hl_combine_attr(wlv.cul_attr, multi_attr) + : hl_combine_attr(multi_attr, wlv.cul_attr); } // put the pointer back to output the double-width // character at the start of the next line. - n_extra++; - p_extra--; + wlv.n_extra++; + wlv.p_extra--; } else { - n_extra -= mb_l - 1; - p_extra += mb_l - 1; + wlv.n_extra -= mb_l - 1; + wlv.p_extra += mb_l - 1; } - p_extra++; + wlv.p_extra++; } - n_extra--; + wlv.n_extra--; } else if (foldinfo.fi_lines > 0) { // skip writing the buffer line itself c = NUL; @@ -1726,22 +1735,22 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, || (mb_l > 1 && (!vim_isprintc(mb_c)))) { // Illegal UTF-8 byte: display as . // Non-BMP character : display as ? or fullwidth ?. - transchar_hex(extra, mb_c); + transchar_hex(wlv.extra, mb_c); if (wp->w_p_rl) { // reverse - rl_mirror(extra); + rl_mirror(wlv.extra); } - p_extra = extra; - c = (uint8_t)(*p_extra); - mb_c = mb_ptr2char_adv((const char **)&p_extra); + wlv.p_extra = wlv.extra; + c = (uint8_t)(*wlv.p_extra); + mb_c = mb_ptr2char_adv((const char **)&wlv.p_extra); mb_utf8 = (c >= 0x80); - n_extra = (int)strlen(p_extra); - c_extra = NUL; - c_final = NUL; + wlv.n_extra = (int)strlen(wlv.p_extra); + wlv.c_extra = NUL; + wlv.c_final = NUL; if (area_attr == 0 && search_attr == 0) { - n_attr = n_extra + 1; - extra_attr = win_hl_attr(wp, HLF_8); - saved_attr2 = char_attr; // save current attr + n_attr = wlv.n_extra + 1; + wlv.extra_attr = win_hl_attr(wp, HLF_8); + saved_attr2 = wlv.char_attr; // save current attr } } else if (mb_l == 0) { // at the NUL at end-of-line mb_l = 1; @@ -1771,8 +1780,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // If a double-width char doesn't fit display a '>' in the // last column; the character is displayed at the start of the // next line. - if ((wp->w_p_rl ? (col <= 0) : - (col >= grid->cols - 1)) + if ((wp->w_p_rl ? (wlv.col <= 0) : (wlv.col >= grid->cols - 1)) && utf_char2cells(mb_c) == 2) { c = '>'; mb_c = c; @@ -1789,15 +1797,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // If a double-width char doesn't fit at the left side display a '<' in // the first column. Don't do this for unprintable characters. - if (n_skip > 0 && mb_l > 1 && n_extra == 0) { - n_extra = 1; - c_extra = MB_FILLER_CHAR; - c_final = NUL; + if (n_skip > 0 && mb_l > 1 && wlv.n_extra == 0) { + wlv.n_extra = 1; + wlv.c_extra = MB_FILLER_CHAR; + wlv.c_final = NUL; c = ' '; if (area_attr == 0 && search_attr == 0) { - n_attr = n_extra + 1; - extra_attr = win_hl_attr(wp, HLF_AT); - saved_attr2 = char_attr; // save current attr + n_attr = wlv.n_extra + 1; + wlv.extra_attr = win_hl_attr(wp, HLF_AT); + saved_attr2 = wlv.char_attr; // save current attr } mb_c = c; mb_utf8 = false; @@ -1838,15 +1846,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, ptr = line + v; if (!attr_pri) { - if (cul_attr) { - char_attr = 0 != line_attr_lowprio - ? hl_combine_attr(cul_attr, syntax_attr) - : hl_combine_attr(syntax_attr, cul_attr); + if (wlv.cul_attr) { + wlv.char_attr = 0 != wlv.line_attr_lowprio + ? hl_combine_attr(wlv.cul_attr, syntax_attr) + : hl_combine_attr(syntax_attr, wlv.cul_attr); } else { - char_attr = syntax_attr; + wlv.char_attr = syntax_attr; } } else { - char_attr = hl_combine_attr(syntax_attr, char_attr); + wlv.char_attr = hl_combine_attr(syntax_attr, wlv.char_attr); } // no concealing past the end of the line, it interferes // with line highlighting. @@ -1856,19 +1864,19 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, syntax_flags = get_syntax_info(&syntax_seqnr); } } else if (!attr_pri) { - char_attr = 0; + wlv.char_attr = 0; } if (has_decor && v > 0) { bool selected = (area_active || (area_highlighting && noinvcur - && vcol == wp->w_virtcol)); - int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v - 1, off, + && wlv.vcol == wp->w_virtcol)); + int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v - 1, wlv.off, selected, &decor_state); if (extmark_attr != 0) { if (!attr_pri) { - char_attr = hl_combine_attr(char_attr, extmark_attr); + wlv.char_attr = hl_combine_attr(wlv.char_attr, extmark_attr); } else { - char_attr = hl_combine_attr(extmark_attr, char_attr); + wlv.char_attr = hl_combine_attr(extmark_attr, wlv.char_attr); } } @@ -1888,7 +1896,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (has_spell && v >= word_end && v > cur_checked_col) { spell_attr = 0; if (!attr_pri) { - char_attr = hl_combine_attr(char_attr, syntax_attr); + wlv.char_attr = hl_combine_attr(wlv.char_attr, syntax_attr); } if (c != 0 && ((!has_syntax && !no_plain_buffer) || can_spell)) { char *prev_ptr; @@ -1953,14 +1961,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } if (spell_attr != 0) { if (!attr_pri) { - char_attr = hl_combine_attr(char_attr, spell_attr); + wlv.char_attr = hl_combine_attr(wlv.char_attr, spell_attr); } else { - char_attr = hl_combine_attr(spell_attr, char_attr); + wlv.char_attr = hl_combine_attr(spell_attr, wlv.char_attr); } } if (wp->w_buffer->terminal) { - char_attr = hl_combine_attr(term_attrs[vcol], char_attr); + wlv.char_attr = hl_combine_attr(term_attrs[wlv.vcol], wlv.char_attr); } // Found last space before word: check for line break. @@ -1970,15 +1978,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, char *p = ptr - (mb_off + 1); chartabsize_T cts; - init_chartabsize_arg(&cts, wp, lnum, vcol, line, p); - n_extra = win_lbr_chartabsize(&cts, NULL) - 1; + init_chartabsize_arg(&cts, wp, lnum, wlv.vcol, line, p); + wlv.n_extra = win_lbr_chartabsize(&cts, NULL) - 1; // We have just drawn the showbreak value, no need to add // space for it again. - if (vcol == vcol_sbr) { - n_extra -= mb_charlen(get_showbreak_value(wp)); - if (n_extra < 0) { - n_extra = 0; + if (wlv.vcol == vcol_sbr) { + wlv.n_extra -= mb_charlen(get_showbreak_value(wp)); + if (wlv.n_extra < 0) { + wlv.n_extra = 0; } } if (on_last_col && c != TAB) { @@ -1988,12 +1996,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, search_attr = 0; } - if (c == TAB && n_extra + col > grid->cols) { - n_extra = tabstop_padding(vcol, wp->w_buffer->b_p_ts, - wp->w_buffer->b_p_vts_array) - 1; + if (c == TAB && wlv.n_extra + wlv.col > grid->cols) { + wlv.n_extra = tabstop_padding(wlv.vcol, wp->w_buffer->b_p_ts, + wp->w_buffer->b_p_vts_array) - 1; } - c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' '; - c_final = NUL; + wlv.c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' '; + wlv.c_final = NUL; if (ascii_iswhite(c)) { if (c == TAB) { // See "Tab alignment" below. @@ -2035,8 +2043,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, c = (c == ' ') ? wp->w_p_lcs_chars.space : wp->w_p_lcs_chars.nbsp; } n_attr = 1; - extra_attr = win_hl_attr(wp, HLF_0); - saved_attr2 = char_attr; // save current attr + wlv.extra_attr = win_hl_attr(wp, HLF_0); + saved_attr2 = wlv.char_attr; // save current attr mb_c = c; mb_utf8 = check_mb_utf8(&c, u8cc); } @@ -2058,8 +2066,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } n_attr = 1; - extra_attr = win_hl_attr(wp, HLF_0); - saved_attr2 = char_attr; // save current attr + wlv.extra_attr = win_hl_attr(wp, HLF_0); + saved_attr2 = wlv.char_attr; // save current attr mb_c = c; mb_utf8 = check_mb_utf8(&c, u8cc); } @@ -2071,13 +2079,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // turn it into something else on the way to putting it on the screen. if (c == TAB && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) { int tab_len = 0; - long vcol_adjusted = vcol; // removed showbreak length + long vcol_adjusted = wlv.vcol; // removed showbreak length char *const sbr = get_showbreak_value(wp); // Only adjust the tab_len, when at the first column after the // showbreak value was drawn. - if (*sbr != NUL && vcol == vcol_sbr && wp->w_p_wrap) { - vcol_adjusted = vcol - mb_charlen(sbr); + if (*sbr != NUL && wlv.vcol == vcol_sbr && wp->w_p_wrap) { + vcol_adjusted = wlv.vcol - mb_charlen(sbr); } // tab amount depends on current column tab_len = tabstop_padding((colnr_T)vcol_adjusted, @@ -2085,23 +2093,23 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, wp->w_buffer->b_p_vts_array) - 1; if (!wp->w_p_lbr || !wp->w_p_list) { - n_extra = tab_len; + wlv.n_extra = tab_len; } else { char *p; - int saved_nextra = n_extra; + int saved_nextra = wlv.n_extra; - if (vcol_off > 0) { + if (wlv.vcol_off > 0) { // there are characters to conceal - tab_len += vcol_off; + tab_len += wlv.vcol_off; } // boguscols before FIX_FOR_BOGUSCOLS macro from above. if (wp->w_p_lcs_chars.tab1 && old_boguscols > 0 - && n_extra > tab_len) { - tab_len += n_extra - tab_len; + && wlv.n_extra > tab_len) { + tab_len += wlv.n_extra - tab_len; } if (tab_len > 0) { - // If n_extra > 0, it gives the number of chars + // If wlv.n_extra > 0, it gives the number of chars // to use for a tab, else we need to calculate the // width for a tab. int tab2_len = utf_char2len(wp->w_p_lcs_chars.tab2); @@ -2109,15 +2117,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (wp->w_p_lcs_chars.tab3) { len += utf_char2len(wp->w_p_lcs_chars.tab3) - tab2_len; } - if (n_extra > 0) { - len += n_extra - tab_len; + if (wlv.n_extra > 0) { + len += wlv.n_extra - tab_len; } c = wp->w_p_lcs_chars.tab1; p = xmalloc((size_t)len + 1); memset(p, ' ', (size_t)len); p[len] = NUL; - xfree(p_extra_free); - p_extra_free = p; + xfree(wlv.p_extra_free); + wlv.p_extra_free = p; for (int i = 0; i < tab_len; i++) { if (*p == NUL) { tab_len = i; @@ -2130,20 +2138,20 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, lcs = wp->w_p_lcs_chars.tab3; } p += utf_char2bytes(lcs, p); - n_extra += utf_char2len(lcs) - (saved_nextra > 0 ? 1 : 0); + wlv.n_extra += utf_char2len(lcs) - (saved_nextra > 0 ? 1 : 0); } - p_extra = p_extra_free; + wlv.p_extra = wlv.p_extra_free; // n_extra will be increased by FIX_FOX_BOGUSCOLS // macro below, so need to adjust for that here - if (vcol_off > 0) { - n_extra -= vcol_off; + if (wlv.vcol_off > 0) { + wlv.n_extra -= wlv.vcol_off; } } } { - int vc_saved = vcol_off; + int vc_saved = wlv.vcol_off; // Tab alignment should be identical regardless of // 'conceallevel' value. So tab compensates of all @@ -2156,7 +2164,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // Make sure, the highlighting for the tab char will be // correctly set further below (effectively reverts the // FIX_FOR_BOGSUCOLS macro). - if (n_extra == tab_len + vc_saved && wp->w_p_list + if (wlv.n_extra == tab_len + vc_saved && wp->w_p_list && wp->w_p_lcs_chars.tab1) { tab_len += vc_saved; } @@ -2164,50 +2172,50 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, mb_utf8 = false; // don't draw as UTF-8 if (wp->w_p_list) { - c = (n_extra == 0 && wp->w_p_lcs_chars.tab3) + c = (wlv.n_extra == 0 && wp->w_p_lcs_chars.tab3) ? wp->w_p_lcs_chars.tab3 : wp->w_p_lcs_chars.tab1; - if (wp->w_p_lbr && p_extra != NULL && *p_extra != NUL) { - c_extra = NUL; // using p_extra from above + if (wp->w_p_lbr && wlv.p_extra != NULL && *wlv.p_extra != NUL) { + wlv.c_extra = NUL; // using p_extra from above } else { - c_extra = wp->w_p_lcs_chars.tab2; + wlv.c_extra = wp->w_p_lcs_chars.tab2; } - c_final = wp->w_p_lcs_chars.tab3; + wlv.c_final = wp->w_p_lcs_chars.tab3; n_attr = tab_len + 1; - extra_attr = win_hl_attr(wp, HLF_0); - saved_attr2 = char_attr; // save current attr + wlv.extra_attr = win_hl_attr(wp, HLF_0); + saved_attr2 = wlv.char_attr; // save current attr mb_c = c; mb_utf8 = check_mb_utf8(&c, u8cc); } else { - c_final = NUL; - c_extra = ' '; + wlv.c_final = NUL; + wlv.c_extra = ' '; c = ' '; } } else if (c == NUL && (wp->w_p_list || ((fromcol >= 0 || fromcol_prev >= 0) - && tocol > vcol + && tocol > wlv.vcol && VIsual_mode != Ctrl_V - && (wp->w_p_rl ? (col >= 0) : (col < grid->cols)) + && (wp->w_p_rl ? (wlv.col >= 0) : (wlv.col < grid->cols)) && !(noinvcur && lnum == wp->w_cursor.lnum - && vcol == wp->w_virtcol))) + && wlv.vcol == wp->w_virtcol))) && lcs_eol_one > 0) { // Display a '$' after the line or highlight an extra // character if the line break is included. // For a diff line the highlighting continues after the "$". if (diff_hlf == (hlf_T)0 - && line_attr == 0 - && line_attr_lowprio == 0) { + && wlv.line_attr == 0 + && wlv.line_attr_lowprio == 0) { // In virtualedit, visual selections may extend beyond end of line if (area_highlighting && virtual_active() - && tocol != MAXCOL && vcol < tocol) { - n_extra = 0; + && tocol != MAXCOL && wlv.vcol < tocol) { + wlv.n_extra = 0; } else { - p_extra = at_end_str; - n_extra = 1; - c_extra = NUL; - c_final = NUL; + wlv.p_extra = at_end_str; + wlv.n_extra = 1; + wlv.c_extra = NUL; + wlv.c_final = NUL; } } if (wp->w_p_list && wp->w_p_lcs_chars.eol > 0) { @@ -2217,46 +2225,46 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } lcs_eol_one = -1; ptr--; // put it back at the NUL - extra_attr = win_hl_attr(wp, HLF_AT); + wlv.extra_attr = win_hl_attr(wp, HLF_AT); n_attr = 1; mb_c = c; mb_utf8 = check_mb_utf8(&c, u8cc); } else if (c != NUL) { - p_extra = (char *)transchar_buf(wp->w_buffer, c); - if (n_extra == 0) { - n_extra = byte2cells(c) - 1; + wlv.p_extra = (char *)transchar_buf(wp->w_buffer, c); + if (wlv.n_extra == 0) { + wlv.n_extra = byte2cells(c) - 1; } if ((dy_flags & DY_UHEX) && wp->w_p_rl) { - rl_mirror(p_extra); // reverse "<12>" + rl_mirror(wlv.p_extra); // reverse "<12>" } - c_extra = NUL; - c_final = NUL; + wlv.c_extra = NUL; + wlv.c_final = NUL; if (wp->w_p_lbr) { char *p; - c = (uint8_t)(*p_extra); - p = xmalloc((size_t)n_extra + 1); - memset(p, ' ', (size_t)n_extra); + c = (uint8_t)(*wlv.p_extra); + p = xmalloc((size_t)wlv.n_extra + 1); + memset(p, ' ', (size_t)wlv.n_extra); strncpy(p, // NOLINT(runtime/printf) - p_extra + 1, - (size_t)strlen(p_extra) - 1); - p[n_extra] = NUL; - xfree(p_extra_free); - p_extra_free = p_extra = p; + wlv.p_extra + 1, + (size_t)strlen(wlv.p_extra) - 1); + p[wlv.n_extra] = NUL; + xfree(wlv.p_extra_free); + wlv.p_extra_free = wlv.p_extra = p; } else { - n_extra = byte2cells(c) - 1; - c = (uint8_t)(*p_extra++); + wlv.n_extra = byte2cells(c) - 1; + c = (uint8_t)(*wlv.p_extra++); } - n_attr = n_extra + 1; - extra_attr = win_hl_attr(wp, HLF_8); - saved_attr2 = char_attr; // save current attr + n_attr = wlv.n_extra + 1; + wlv.extra_attr = win_hl_attr(wp, HLF_8); + saved_attr2 = wlv.char_attr; // save current attr mb_utf8 = false; // don't draw as UTF-8 } else if (VIsual_active && (VIsual_mode == Ctrl_V || VIsual_mode == 'v') && virtual_active() && tocol != MAXCOL - && vcol < tocol - && (wp->w_p_rl ? (col >= 0) : (col < grid->cols))) { + && wlv.vcol < tocol + && (wp->w_p_rl ? (wlv.col >= 0) : (wlv.col < grid->cols))) { c = ' '; ptr--; // put it back at the NUL } @@ -2266,7 +2274,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, && (wp != curwin || lnum != wp->w_cursor.lnum || conceal_cursor_line(wp)) && ((syntax_flags & HL_CONCEAL) != 0 || has_match_conc > 0 || decor_conceal > 0) && !(lnum_in_visual_area && vim_strchr(wp->w_p_cocu, 'v') == NULL)) { - char_attr = conceal_attr; + wlv.char_attr = conceal_attr; if (((prev_syntax_id != syntax_seqnr && (syntax_flags & HL_CONCEAL) != 0) || has_match_conc > 1 || decor_conceal > 1) && (syn_get_sub_char() != NUL @@ -2281,7 +2289,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } else if (decor_conceal && decor_state.conceal_char) { c = decor_state.conceal_char; if (decor_state.conceal_attr) { - char_attr = decor_state.conceal_attr; + wlv.char_attr = decor_state.conceal_attr; } } else if (syn_get_sub_char() != NUL) { c = syn_get_sub_char(); @@ -2293,20 +2301,20 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, prev_syntax_id = syntax_seqnr; - if (n_extra > 0) { - vcol_off += n_extra; + if (wlv.n_extra > 0) { + wlv.vcol_off += wlv.n_extra; } - vcol += n_extra; - if (wp->w_p_wrap && n_extra > 0) { + wlv.vcol += wlv.n_extra; + if (wp->w_p_wrap && wlv.n_extra > 0) { if (wp->w_p_rl) { - col -= n_extra; - boguscols -= n_extra; + wlv.col -= wlv.n_extra; + wlv.boguscols -= wlv.n_extra; } else { - boguscols += n_extra; - col += n_extra; + wlv.boguscols += wlv.n_extra; + wlv.col += wlv.n_extra; } } - n_extra = 0; + wlv.n_extra = 0; n_attr = 0; } else if (n_skip == 0) { is_concealing = true; @@ -2327,23 +2335,23 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // In the cursor line and we may be concealing characters: correct // the cursor column when we reach its position. - if (!did_wcol && draw_state == WL_LINE + if (!did_wcol && wlv.draw_state == WL_LINE && wp == curwin && lnum == wp->w_cursor.lnum && conceal_cursor_line(wp) - && (int)wp->w_virtcol <= vcol + n_skip) { + && (int)wp->w_virtcol <= wlv.vcol + n_skip) { if (wp->w_p_rl) { - wp->w_wcol = grid->cols - col + boguscols - 1; + wp->w_wcol = grid->cols - wlv.col + wlv.boguscols - 1; } else { - wp->w_wcol = col - boguscols; + wp->w_wcol = wlv.col - wlv.boguscols; } - wp->w_wrow = row; + wp->w_wrow = wlv.row; did_wcol = true; wp->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL; } // Don't override visual selection highlighting. - if (n_attr > 0 && draw_state == WL_LINE && !search_attr_from_match) { - char_attr = hl_combine_attr(char_attr, extra_attr); + if (n_attr > 0 && wlv.draw_state == WL_LINE && !search_attr_from_match) { + wlv.char_attr = hl_combine_attr(wlv.char_attr, wlv.extra_attr); } // Handle the case where we are in column 0 but not on the first @@ -2351,25 +2359,25 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // special character (via 'listchars' option "precedes:". if (lcs_prec_todo != NUL && wp->w_p_list - && (wp->w_p_wrap ? (wp->w_skipcol > 0 && row == 0) : wp->w_leftcol > 0) - && filler_todo <= 0 - && draw_state > WL_STC + && (wp->w_p_wrap ? (wp->w_skipcol > 0 && wlv.row == 0) : wp->w_leftcol > 0) + && wlv.filler_todo <= 0 + && wlv.draw_state > WL_STC && c != NUL) { c = wp->w_p_lcs_chars.prec; lcs_prec_todo = NUL; if (utf_char2cells(mb_c) > 1) { // Double-width character being overwritten by the "precedes" // character, need to fill up half the character. - c_extra = MB_FILLER_CHAR; - c_final = NUL; - n_extra = 1; + wlv.c_extra = MB_FILLER_CHAR; + wlv.c_final = NUL; + wlv.n_extra = 1; n_attr = 2; - extra_attr = win_hl_attr(wp, HLF_AT); + wlv.extra_attr = win_hl_attr(wp, HLF_AT); } mb_c = c; mb_utf8 = check_mb_utf8(&c, u8cc); - saved_attr3 = char_attr; // save current attr - char_attr = win_hl_attr(wp, HLF_AT); // overwriting char_attr + saved_attr3 = wlv.char_attr; // save current attr + wlv.char_attr = win_hl_attr(wp, HLF_AT); // overwriting char_attr n_attr3 = 1; } @@ -2385,7 +2393,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // char on the screen, just overwrite that one (tricky!) Not // needed when a '$' was displayed for 'list'. if (wp->w_p_lcs_chars.eol == lcs_eol_one - && ((area_attr != 0 && vcol == fromcol + && ((area_attr != 0 && wlv.vcol == fromcol && (VIsual_mode != Ctrl_V || lnum == VIsual.lnum || lnum == curwin->w_cursor.lnum)) @@ -2394,22 +2402,22 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int n = 0; if (wp->w_p_rl) { - if (col < 0) { + if (wlv.col < 0) { n = 1; } } else { - if (col >= grid->cols) { + if (wlv.col >= grid->cols) { n = -1; } } if (n != 0) { // At the window boundary, highlight the last character // instead (better than nothing). - off += n; - col += n; + wlv.off += n; + wlv.col += n; } else { // Add a blank character to highlight. - schar_from_ascii(linebuf_char[off], ' '); + schar_from_ascii(linebuf_char[wlv.off], ' '); } if (area_attr == 0 && !has_fold) { // Use attributes from match with highest priority among @@ -2417,24 +2425,28 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, get_search_match_hl(wp, &screen_search_hl, (long)(ptr - line), // NOLINT(google-readability-casting) - &char_attr); + &wlv.char_attr); } - int eol_attr = char_attr; - if (cul_attr) { - eol_attr = hl_combine_attr(cul_attr, eol_attr); + int eol_attr = wlv.char_attr; + if (wlv.cul_attr) { + eol_attr = hl_combine_attr(wlv.cul_attr, eol_attr); } - linebuf_attr[off] = eol_attr; + linebuf_attr[wlv.off] = eol_attr; if (wp->w_p_rl) { - col--; - off--; + wlv.col--; + wlv.off--; } else { - col++; - off++; + wlv.col++; + wlv.off++; } - vcol++; + wlv.vcol++; eol_hl_off = 1; } + } + + // At end of the text line. + if (c == NUL) { // Highlight 'cursorcolumn' & 'colorcolumn' past end of the line. if (wp->w_p_wrap) { v = wp->w_skipcol; @@ -2443,13 +2455,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } // check if line ends before left margin - if (vcol < v + col - win_col_off(wp)) { - vcol = (colnr_T)v + col - win_col_off(wp); + if (wlv.vcol < v + wlv.col - win_col_off(wp)) { + wlv.vcol = (colnr_T)v + wlv.col - win_col_off(wp); } // Get rid of the boguscols now, we want to draw until the right // edge for 'cursorcolumn'. - col -= boguscols; - // boguscols = 0; // Disabled because value never read after this + wlv.col -= wlv.boguscols; + wlv.boguscols = 0; if (draw_color_col) { draw_color_col = advance_color_col(VCOL_HLC, &color_cols); @@ -2462,16 +2474,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, ? 1 : 0); if (has_decor) { - has_virttext = decor_redraw_eol(wp->w_buffer, &decor_state, &line_attr, - col + eol_skip); + has_virttext = decor_redraw_eol(wp->w_buffer, &decor_state, &wlv.line_attr, + wlv.col + eol_skip); } if (((wp->w_p_cuc && (int)wp->w_virtcol >= VCOL_HLC - eol_hl_off && (int)wp->w_virtcol < - (long)grid->cols * (row - startrow + 1) + v + (long)grid->cols * (wlv.row - startrow + 1) + v && lnum != wp->w_cursor.lnum) - || draw_color_col || line_attr_lowprio || line_attr + || draw_color_col || wlv.line_attr_lowprio || wlv.line_attr || diff_hlf != (hlf_T)0 || has_virttext)) { int rightmost_vcol = 0; @@ -2499,16 +2511,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, diff_attr = win_hl_attr(wp, (int)diff_hlf); } - int base_attr = hl_combine_attr(line_attr_lowprio, diff_attr); - if (base_attr || line_attr || has_virttext) { + int base_attr = hl_combine_attr(wlv.line_attr_lowprio, diff_attr); + if (base_attr || wlv.line_attr || has_virttext) { rightmost_vcol = INT_MAX; } int col_stride = wp->w_p_rl ? -1 : 1; - while (wp->w_p_rl ? col >= 0 : col < grid->cols) { - schar_from_ascii(linebuf_char[off], ' '); - col += col_stride; + while (wp->w_p_rl ? wlv.col >= 0 : wlv.col < grid->cols) { + schar_from_ascii(linebuf_char[wlv.off], ' '); + wlv.col += col_stride; if (draw_color_col) { draw_color_col = advance_color_col(VCOL_HLC, &color_cols); } @@ -2521,16 +2533,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, col_attr = mc_attr; } - col_attr = hl_combine_attr(col_attr, line_attr); + col_attr = hl_combine_attr(col_attr, wlv.line_attr); - linebuf_attr[off] = col_attr; - off += col_stride; + linebuf_attr[wlv.off] = col_attr; + wlv.off += col_stride; if (VCOL_HLC >= rightmost_vcol) { break; } - vcol += 1; + wlv.vcol += 1; } } @@ -2539,24 +2551,24 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // terminal buffers may need to highlight beyond the end of the // logical line int n = wp->w_p_rl ? -1 : 1; - while (col >= 0 && col < grid->cols) { - schar_from_ascii(linebuf_char[off], ' '); - linebuf_attr[off] = vcol >= TERM_ATTRS_MAX ? 0 : term_attrs[vcol]; - off += n; - vcol += n; - col += n; + while (wlv.col >= 0 && wlv.col < grid->cols) { + schar_from_ascii(linebuf_char[wlv.off], ' '); + linebuf_attr[wlv.off] = wlv.vcol >= TERM_ATTRS_MAX ? 0 : term_attrs[wlv.vcol]; + wlv.off += n; + wlv.vcol += n; + wlv.col += n; } } - draw_virt_text(wp, buf, win_col_offset, &col, grid->cols, row); - grid_put_linebuf(grid, row, 0, col, grid->cols, wp->w_p_rl, wp, bg_attr, false); - row++; + draw_virt_text(wp, buf, win_col_offset, &wlv.col, grid->cols, wlv.row); + grid_put_linebuf(grid, wlv.row, 0, wlv.col, grid->cols, wp->w_p_rl, wp, bg_attr, false); + wlv.row++; // Update w_cline_height and w_cline_folded if the cursor line was // updated (saves a call to plines_win() later). if (wp == curwin && lnum == curwin->w_cursor.lnum) { curwin->w_cline_row = startrow; - curwin->w_cline_height = row - startrow; + curwin->w_cline_height = wlv.row - startrow; curwin->w_cline_folded = foldinfo.fi_lines > 0; curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW); conceal_cursor_used = conceal_cursor_line(curwin); @@ -2567,17 +2579,17 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // Show "extends" character from 'listchars' if beyond the line end and // 'list' is set. if (wp->w_p_lcs_chars.ext != NUL - && draw_state == WL_LINE + && wlv.draw_state == WL_LINE && wp->w_p_list && !wp->w_p_wrap - && filler_todo <= 0 - && (wp->w_p_rl ? col == 0 : col == grid->cols - 1) + && wlv.filler_todo <= 0 + && (wp->w_p_rl ? wlv.col == 0 : wlv.col == grid->cols - 1) && !has_fold && (*ptr != NUL || lcs_eol_one > 0 - || (n_extra && (c_extra != NUL || *p_extra != NUL)))) { + || (wlv.n_extra && (wlv.c_extra != NUL || *wlv.p_extra != NUL)))) { c = wp->w_p_lcs_chars.ext; - char_attr = win_hl_attr(wp, HLF_AT); + wlv.char_attr = win_hl_attr(wp, HLF_AT); mb_c = c; mb_utf8 = check_mb_utf8(&c, u8cc); } @@ -2594,84 +2606,84 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // Also highlight the 'colorcolumn' if 'breakindent' and/or 'showbreak' // options are set vcol_save_attr = -1; - if ((draw_state == WL_LINE - || draw_state == WL_BRI - || draw_state == WL_SBR) + if ((wlv.draw_state == WL_LINE + || wlv.draw_state == WL_BRI + || wlv.draw_state == WL_SBR) && !lnum_in_visual_area && search_attr == 0 && area_attr == 0 - && filler_todo <= 0) { + && wlv.filler_todo <= 0) { if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol && lnum != wp->w_cursor.lnum) { - vcol_save_attr = char_attr; - char_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUC), char_attr); + vcol_save_attr = wlv.char_attr; + wlv.char_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUC), wlv.char_attr); } else if (draw_color_col && VCOL_HLC == *color_cols) { - vcol_save_attr = char_attr; - char_attr = hl_combine_attr(win_hl_attr(wp, HLF_MC), char_attr); + vcol_save_attr = wlv.char_attr; + wlv.char_attr = hl_combine_attr(win_hl_attr(wp, HLF_MC), wlv.char_attr); } } // Apply lowest-priority line attr now, so everything can override it. - if (draw_state == WL_LINE) { - char_attr = hl_combine_attr(line_attr_lowprio, char_attr); + if (wlv.draw_state == WL_LINE) { + wlv.char_attr = hl_combine_attr(wlv.line_attr_lowprio, wlv.char_attr); } // Store character to be displayed. // Skip characters that are left of the screen for 'nowrap'. - vcol_prev = vcol; - if (draw_state < WL_LINE || n_skip <= 0) { + vcol_prev = wlv.vcol; + if (wlv.draw_state < WL_LINE || n_skip <= 0) { // // Store the character. // if (wp->w_p_rl && utf_char2cells(mb_c) > 1) { // A double-wide character is: put first half in left cell. - off--; - col--; + wlv.off--; + wlv.col--; } if (mb_utf8) { - schar_from_cc(linebuf_char[off], mb_c, u8cc); + schar_from_cc(linebuf_char[wlv.off], mb_c, u8cc); } else { - schar_from_ascii(linebuf_char[off], (char)c); + schar_from_ascii(linebuf_char[wlv.off], (char)c); } if (multi_attr) { - linebuf_attr[off] = multi_attr; + linebuf_attr[wlv.off] = multi_attr; multi_attr = 0; } else { - linebuf_attr[off] = char_attr; + linebuf_attr[wlv.off] = wlv.char_attr; } if (utf_char2cells(mb_c) > 1) { // Need to fill two screen columns. - off++; - col++; + wlv.off++; + wlv.col++; // UTF-8: Put a 0 in the second screen char. - linebuf_char[off][0] = 0; - if (draw_state > WL_STC && filler_todo <= 0) { - vcol++; + linebuf_char[wlv.off][0] = 0; + if (wlv.draw_state > WL_STC && wlv.filler_todo <= 0) { + wlv.vcol++; } // When "tocol" is halfway through a character, set it to the end of // the character, otherwise highlighting won't stop. - if (tocol == vcol) { + if (tocol == wlv.vcol) { tocol++; } if (wp->w_p_rl) { // now it's time to backup one cell - off--; - col--; + wlv.off--; + wlv.col--; } } if (wp->w_p_rl) { - off--; - col--; + wlv.off--; + wlv.col--; } else { - off++; - col++; + wlv.off++; + wlv.col++; } } else if (wp->w_p_cole > 0 && is_concealing) { n_skip--; - vcol_off++; - if (n_extra > 0) { - vcol_off += n_extra; + wlv.vcol_off++; + if (wlv.n_extra > 0) { + wlv.vcol_off += wlv.n_extra; } if (wp->w_p_wrap) { // Special voodoo required if 'wrap' is on. @@ -2681,45 +2693,45 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // take up the same screen space when parts are concealed, // so that cursor line computations aren't messed up. // - // To avoid the fictitious advance of 'col' causing + // To avoid the fictitious advance of 'wlv.col' causing // trailing junk to be written out of the screen line // we are building, 'boguscols' keeps track of the number // of bad columns we have advanced. - if (n_extra > 0) { - vcol += n_extra; + if (wlv.n_extra > 0) { + wlv.vcol += wlv.n_extra; if (wp->w_p_rl) { - col -= n_extra; - boguscols -= n_extra; + wlv.col -= wlv.n_extra; + wlv.boguscols -= wlv.n_extra; } else { - col += n_extra; - boguscols += n_extra; + wlv.col += wlv.n_extra; + wlv.boguscols += wlv.n_extra; } - n_extra = 0; + wlv.n_extra = 0; n_attr = 0; } if (utf_char2cells(mb_c) > 1) { // Need to fill two screen columns. if (wp->w_p_rl) { - boguscols--; - col--; + wlv.boguscols--; + wlv.col--; } else { - boguscols++; - col++; + wlv.boguscols++; + wlv.col++; } } if (wp->w_p_rl) { - boguscols--; - col--; + wlv.boguscols--; + wlv.col--; } else { - boguscols++; - col++; + wlv.boguscols++; + wlv.col++; } } else { - if (n_extra > 0) { - vcol += n_extra; - n_extra = 0; + if (wlv.n_extra > 0) { + wlv.vcol += wlv.n_extra; + wlv.n_extra = 0; n_attr = 0; } } @@ -2727,58 +2739,58 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, n_skip--; } - // Only advance the "vcol" when after the 'number' or 'relativenumber' - // column. - if (draw_state > WL_STC - && filler_todo <= 0) { - vcol++; + // Only advance the "wlv.vcol" when after the 'number' or + // 'relativenumber' column. + if (wlv.draw_state > WL_STC + && wlv.filler_todo <= 0) { + wlv.vcol++; } if (vcol_save_attr >= 0) { - char_attr = vcol_save_attr; + wlv.char_attr = vcol_save_attr; } // restore attributes after "predeces" in 'listchars' - if (draw_state > WL_STC && n_attr3 > 0 && --n_attr3 == 0) { - char_attr = saved_attr3; + if (wlv.draw_state > WL_STC && n_attr3 > 0 && --n_attr3 == 0) { + wlv.char_attr = saved_attr3; } // restore attributes after last 'listchars' or 'number' char - if (n_attr > 0 && draw_state == WL_LINE && --n_attr == 0) { - char_attr = saved_attr2; + if (n_attr > 0 && wlv.draw_state == WL_LINE && --n_attr == 0) { + wlv.char_attr = saved_attr2; } // At end of screen line and there is more to come: Display the line // so far. If there is no more to display it is caught above. - if ((wp->w_p_rl ? (col < 0) : (col >= grid->cols)) + if ((wp->w_p_rl ? (wlv.col < 0) : (wlv.col >= grid->cols)) && (!has_fold || virt_line_offset >= 0) - && (draw_state != WL_LINE + && (wlv.draw_state != WL_LINE || *ptr != NUL - || filler_todo > 0 + || wlv.filler_todo > 0 || (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL - && p_extra != at_end_str) - || (n_extra != 0 - && (c_extra != NUL || *p_extra != NUL)))) { + && wlv.p_extra != at_end_str) + || (wlv.n_extra != 0 + && (wlv.c_extra != NUL || *wlv.p_extra != NUL)))) { bool wrap = wp->w_p_wrap // Wrapping enabled. - && filler_todo <= 0 // Not drawing diff filler lines. + && wlv.filler_todo <= 0 // Not drawing diff filler lines. && lcs_eol_one != -1 // Haven't printed the lcs_eol character. - && row != endrow - 1 // Not the last line being displayed. + && wlv.row != endrow - 1 // Not the last line being displayed. && (grid->cols == Columns // Window spans the width of the screen, || ui_has(kUIMultigrid)) // or has dedicated grid. && !wp->w_p_rl; // Not right-to-left. - int draw_col = col - boguscols; + int draw_col = wlv.col - wlv.boguscols; if (virt_line_offset >= 0) { draw_virt_text_item(buf, virt_line_offset, kv_A(virt_lines, virt_line_index).line, kHlModeReplace, grid->cols, 0); } else { - draw_virt_text(wp, buf, win_col_offset, &draw_col, grid->cols, row); + draw_virt_text(wp, buf, win_col_offset, &draw_col, grid->cols, wlv.row); } - grid_put_linebuf(grid, row, 0, draw_col, grid->cols, wp->w_p_rl, wp, bg_attr, wrap); + grid_put_linebuf(grid, wlv.row, 0, draw_col, grid->cols, wp->w_p_rl, wp, bg_attr, wrap); if (wrap) { ScreenGrid *current_grid = grid; - int current_row = row, dummy_col = 0; // dummy_col unused + int current_row = wlv.row, dummy_col = 0; // dummy_col unused grid_adjust(¤t_grid, ¤t_row, &dummy_col); // Force a redraw of the first column of the next line. @@ -2788,49 +2800,45 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, current_grid->line_wraps[current_row] = true; } - boguscols = 0; - row++; + wlv.boguscols = 0; + wlv.row++; // When not wrapping and finished diff lines, or when displayed // '$' and highlighting until last column, break here. - if ((!wp->w_p_wrap && filler_todo <= 0) || lcs_eol_one == -1) { + if ((!wp->w_p_wrap && wlv.filler_todo <= 0) || lcs_eol_one == -1) { break; } // When the window is too narrow draw all "@" lines. - if (draw_state != WL_LINE && filler_todo <= 0) { - win_draw_end(wp, '@', ' ', true, row, wp->w_grid.rows, HLF_AT); - set_empty_rows(wp, row); - row = endrow; + if (wlv.draw_state != WL_LINE && wlv.filler_todo <= 0) { + win_draw_end(wp, '@', ' ', true, wlv.row, wp->w_grid.rows, HLF_AT); + set_empty_rows(wp, wlv.row); + wlv.row = endrow; } // When line got too long for screen break here. - if (row == endrow) { - row++; + if (wlv.row == endrow) { + wlv.row++; break; } - col = 0; - off = 0; - if (wp->w_p_rl) { - col = grid->cols - 1; // col is not used if breaking! - off += col; - } + win_line_start(wp, &wlv); // reset the drawing state for the start of a wrapped line - draw_state = WL_START; - saved_n_extra = n_extra; - saved_p_extra = p_extra; - saved_c_extra = c_extra; - saved_c_final = c_final; - saved_char_attr = char_attr; - n_extra = 0; + wlv.draw_state = WL_START; + saved_n_extra = wlv.n_extra; + saved_p_extra = wlv.p_extra; + saved_c_extra = wlv.c_extra; + saved_c_final = wlv.c_final; + saved_char_attr = wlv.char_attr; + wlv.n_extra = 0; lcs_prec_todo = wp->w_p_lcs_chars.prec; - if (filler_todo <= 0) { + if (wlv.filler_todo <= 0) { need_showbreak = true; } if (statuscol.draw) { - if (row == startrow + filler_lines + 1 || row == startrow + filler_lines) { + if (wlv.row == startrow + wlv.filler_lines + 1 + || wlv.row == startrow + wlv.filler_lines) { // Re-evaluate 'statuscolumn' for the first wrapped row and non filler line statuscol.textp = NULL; } else if (statuscol.textp) { @@ -2840,11 +2848,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } // Fall back to default columns if the 'n' flag isn't in 'cpo' statuscol.draw = vim_strchr(p_cpo, CPO_NUMCOL) == NULL; } - filler_todo--; + wlv.filler_todo--; virt_line_offset = -1; // When the filler lines are actually below the last line of the // file, don't draw the line itself, break here. - if (filler_todo == 0 && (wp->w_botfill || end_fill)) { + if (wlv.filler_todo == 0 && (wp->w_botfill || end_fill)) { break; } } @@ -2857,6 +2865,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } kv_destroy(virt_lines); - xfree(p_extra_free); - return row; + xfree(wlv.p_extra_free); + return wlv.row; } -- cgit From 89cccea167ab8d3db6601a410dcbd33eb3824947 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 3 Mar 2023 17:24:14 +0800 Subject: vim-patch:9.0.0519: the win_line() function is much too long (#22491) Problem: The win_line() function is much too long. Solution: Move the code to draw the line number to a separate function. https://github.com/vim/vim/commit/d7657e95b21f660a202a5118af059aa17ad37120 N/A patches for version.c: vim-patch:9.0.0521: compiler warns for unused argument in small version Co-authored-by: Bram Moolenaar --- src/nvim/drawline.c | 95 ++++++++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 9a56477d83..7ed0c1b3c0 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -429,6 +429,54 @@ static int get_sign_attrs(buf_T *buf, winlinevars_T *wlv, int *sign_num_attrp, i return num_signs; } +/// Display the absolute or relative line number. After the first row fill with +/// blanks when the 'n' flag isn't in 'cpo'. +static void handle_lnum_col(win_T *wp, winlinevars_T *wlv, int num_signs, int sign_idx, + int sign_num_attr, int sign_cul_attr) +{ + if ((wp->w_p_nu || wp->w_p_rnu) + && (wlv->row == wlv->startrow + wlv->filler_lines + || vim_strchr(p_cpo, CPO_NUMCOL) == NULL)) { + // If 'signcolumn' is set to 'number' and a sign is present + // in "lnum", then display the sign instead of the line + // number. + if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' && num_signs > 0) { + get_sign_display_info(true, wp, wlv, sign_idx, sign_cul_attr); + } else { + // Draw the line number (empty space after wrapping). + if (wlv->row == wlv->startrow + wlv->filler_lines) { + get_line_number_str(wp, wlv->lnum, wlv->extra, sizeof(wlv->extra)); + if (wp->w_skipcol > 0) { + for (wlv->p_extra = wlv->extra; *wlv->p_extra == ' '; wlv->p_extra++) { + *wlv->p_extra = '-'; + } + } + if (wp->w_p_rl) { // reverse line numbers + // like rl_mirror(), but keep the space at the end + char *p2 = skipwhite(wlv->extra); + p2 = skiptowhite(p2) - 1; + for (char *p1 = skipwhite(wlv->extra); p1 < p2; p1++, p2--) { + const char t = *p1; + *p1 = *p2; + *p2 = t; + } + } + wlv->p_extra = wlv->extra; + wlv->c_extra = NUL; + } else { + wlv->c_extra = ' '; + } + wlv->c_final = NUL; + wlv->n_extra = number_width(wp) + 1; + if (sign_num_attr > 0) { + wlv->char_attr = sign_num_attr; + } else { + wlv->char_attr = get_line_number_attr(wp, wlv); + } + } + } +} + /// Prepare and build the 'statuscolumn' string for line "lnum" in window "wp". /// Fill "stcp" with the built status column string and attributes. /// This can be called three times per win_line(), once for virt_lines, once for @@ -1294,8 +1342,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // sign column, this is hit until sign_idx reaches count if (wlv.draw_state == WL_SIGN - 1 && wlv.n_extra == 0) { + // Show the sign column when desired. wlv.draw_state = WL_SIGN; - // Show the sign column when there are any signs in this buffer if (wp->w_scwidth > 0) { get_sign_display_info(false, wp, &wlv, sign_idx, sign_cul_attr); sign_idx++; @@ -1308,50 +1356,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } if (wlv.draw_state == WL_NR - 1 && wlv.n_extra == 0) { + // Show the line number, if desired. wlv.draw_state = WL_NR; - // Display the absolute or relative line number. After the - // first fill with blanks when the 'n' flag isn't in 'cpo' - if ((wp->w_p_nu || wp->w_p_rnu) - && (wlv.row == startrow + wlv.filler_lines - || vim_strchr(p_cpo, CPO_NUMCOL) == NULL)) { - // If 'signcolumn' is set to 'number' and a sign is present - // in 'lnum', then display the sign instead of the line - // number. - if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' && num_signs > 0) { - get_sign_display_info(true, wp, &wlv, sign_idx, sign_cul_attr); - } else { - // Draw the line number (empty space after wrapping). - if (wlv.row == startrow + wlv.filler_lines) { - get_line_number_str(wp, lnum, wlv.extra, sizeof(wlv.extra)); - if (wp->w_skipcol > 0) { - for (wlv.p_extra = wlv.extra; *wlv.p_extra == ' '; wlv.p_extra++) { - *wlv.p_extra = '-'; - } - } - if (wp->w_p_rl) { // reverse line numbers - // like rl_mirror(), but keep the space at the end - char *p2 = skipwhite(wlv.extra); - p2 = skiptowhite(p2) - 1; - for (char *p1 = skipwhite(wlv.extra); p1 < p2; p1++, p2--) { - const char t = *p1; - *p1 = *p2; - *p2 = t; - } - } - wlv.p_extra = wlv.extra; - wlv.c_extra = NUL; - } else { - wlv.c_extra = ' '; - } - wlv.c_final = NUL; - wlv.n_extra = number_width(wp) + 1; - if (sign_num_attr > 0) { - wlv.char_attr = sign_num_attr; - } else { - wlv.char_attr = get_line_number_attr(wp, &wlv); - } - } - } + handle_lnum_col(wp, &wlv, num_signs, sign_idx, sign_num_attr, sign_cul_attr); } if (wlv.draw_state == WL_STC - 1 && wlv.n_extra == 0) { -- cgit From bf445569062b410105bcb65e75c9a0ea88866b5b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 3 Mar 2023 17:37:59 +0800 Subject: refactor(drawline.c): move number column helpers function together --- src/nvim/drawline.c | 123 ++++++++++++++++++++++++++-------------------------- 1 file changed, 61 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 7ed0c1b3c0..4c1f2f90fa 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -429,6 +429,67 @@ static int get_sign_attrs(buf_T *buf, winlinevars_T *wlv, int *sign_num_attrp, i return num_signs; } +static inline void get_line_number_str(win_T *wp, linenr_T lnum, char *buf, size_t buf_len) +{ + long num; + char *fmt = "%*ld "; + + if (wp->w_p_nu && !wp->w_p_rnu) { + // 'number' + 'norelativenumber' + num = (long)lnum; + } else { + // 'relativenumber', don't use negative numbers + num = labs((long)get_cursor_rel_lnum(wp, lnum)); + if (num == 0 && wp->w_p_nu && wp->w_p_rnu) { + // 'number' + 'relativenumber' + num = lnum; + fmt = "%-*ld "; + } + } + + snprintf(buf, buf_len, fmt, number_width(wp), num); +} + +/// Return true if CursorLineNr highlight is to be used for the number column. +/// - 'cursorline' must be set +/// - "wlv->lnum" must be the cursor line +/// - 'cursorlineopt' has "number" +/// - don't highlight filler lines (when in diff mode) +/// - When line is wrapped and 'cursorlineopt' does not have "line", only highlight the line number +/// itself on the first screenline of the wrapped line, otherwise highlight the number column of +/// all screenlines of the wrapped line. +static bool use_cursor_line_nr(win_T *wp, winlinevars_T *wlv) +{ + return wp->w_p_cul + && wlv->lnum == wp->w_cursorline + && (wp->w_p_culopt_flags & CULOPT_NBR) + && (wlv->row == wlv->startrow + wlv->filler_lines + || (wlv->row > wlv->startrow + wlv->filler_lines + && (wp->w_p_culopt_flags & CULOPT_LINE))); +} + +static int get_line_number_attr(win_T *wp, winlinevars_T *wlv) +{ + if (use_cursor_line_nr(wp, wlv)) { + // TODO(vim): Can we use CursorLine instead of CursorLineNr + // when CursorLineNr isn't set? + return win_hl_attr(wp, HLF_CLN); + } + + if (wp->w_p_rnu) { + if (wlv->lnum < wp->w_cursor.lnum) { + // Use LineNrAbove + return win_hl_attr(wp, HLF_LNA); + } + if (wlv->lnum > wp->w_cursor.lnum) { + // Use LineNrBelow + return win_hl_attr(wp, HLF_LNB); + } + } + + return win_hl_attr(wp, HLF_N); +} + /// Display the absolute or relative line number. After the first row fill with /// blanks when the 'n' flag isn't in 'cpo'. static void handle_lnum_col(win_T *wp, winlinevars_T *wlv, int num_signs, int sign_idx, @@ -554,68 +615,6 @@ static void get_statuscol_display_info(statuscol_T *stcp, winlinevars_T *wlv) } while (wlv->n_extra == 0 && stcp->textp < stcp->text_end); } -/// Return true if CursorLineNr highlight is to be used for the number column. -/// -/// - 'cursorline' must be set -/// - lnum must be the cursor line -/// - 'cursorlineopt' has "number" -/// - don't highlight filler lines (when in diff mode) -/// - When line is wrapped and 'cursorlineopt' does not have "line", only highlight the line number -/// itself on the first screenline of the wrapped line, otherwise highlight the number column of -/// all screenlines of the wrapped line. -static bool use_cursor_line_nr(win_T *wp, winlinevars_T *wlv) -{ - return wp->w_p_cul - && wlv->lnum == wp->w_cursorline - && (wp->w_p_culopt_flags & CULOPT_NBR) - && (wlv->row == wlv->startrow + wlv->filler_lines - || (wlv->row > wlv->startrow + wlv->filler_lines - && (wp->w_p_culopt_flags & CULOPT_LINE))); -} - -static inline void get_line_number_str(win_T *wp, linenr_T lnum, char *buf, size_t buf_len) -{ - long num; - char *fmt = "%*ld "; - - if (wp->w_p_nu && !wp->w_p_rnu) { - // 'number' + 'norelativenumber' - num = (long)lnum; - } else { - // 'relativenumber', don't use negative numbers - num = labs((long)get_cursor_rel_lnum(wp, lnum)); - if (num == 0 && wp->w_p_nu && wp->w_p_rnu) { - // 'number' + 'relativenumber' - num = lnum; - fmt = "%-*ld "; - } - } - - snprintf(buf, buf_len, fmt, number_width(wp), num); -} - -static int get_line_number_attr(win_T *wp, winlinevars_T *wlv) -{ - if (use_cursor_line_nr(wp, wlv)) { - // TODO(vim): Can we use CursorLine instead of CursorLineNr - // when CursorLineNr isn't set? - return win_hl_attr(wp, HLF_CLN); - } - - if (wp->w_p_rnu) { - if (wlv->lnum < wp->w_cursor.lnum) { - // Use LineNrAbove - return win_hl_attr(wp, HLF_LNA); - } - if (wlv->lnum > wp->w_cursor.lnum) { - // Use LineNrBelow - return win_hl_attr(wp, HLF_LNB); - } - } - - return win_hl_attr(wp, HLF_N); -} - static void apply_cursorline_highlight(win_T *wp, winlinevars_T *wlv) { wlv->cul_attr = win_hl_attr(wp, HLF_CUL); -- cgit From a7dbfec9f3b7385b87588e09aeb20e2bf0b5fccd Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 3 Mar 2023 17:32:23 +0800 Subject: vim-patch:partial:9.0.0531: the win_line() function is much too long Problem: The win_line() function is much too long. Solution: Move code to separate functions. https://github.com/vim/vim/commit/c20a41972c61ab4bc211327d535c73c9b30cc166 Partial port as this depends on patch 9.0.0148. Co-authored-by: Bram Moolenaar --- src/nvim/drawline.c | 292 ++++++++++++++++++++++++++++------------------------ 1 file changed, 157 insertions(+), 135 deletions(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 4c1f2f90fa..1a4f718c11 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -73,6 +73,7 @@ typedef struct { LineDrawState draw_state; ///< what to draw next linenr_T lnum; ///< line number to be drawn + foldinfo_T foldinfo; ///< fold info for this line int startrow; ///< first row in the window to be drawn int row; ///< row in the window, excl w_winrow @@ -88,6 +89,11 @@ typedef struct { int line_attr; ///< attribute for the whole line int line_attr_lowprio; ///< low-priority attribute for the line + int fromcol; ///< start of inverting + int tocol; ///< end of inverting + + bool need_showbreak; ///< overlong line, skipping first x chars + int char_attr; ///< attributes for next character int n_extra; ///< number of extra bytes @@ -100,6 +106,8 @@ typedef struct { char extra[57]; ///< sign, line number and 'fdc' must fit in here + hlf_T diff_hlf; ///< type of diff highlighting + int filler_lines; ///< nr of filler lines to be drawn int filler_todo; ///< nr of filler lines still to do + 1 SignTextAttrs sattrs[SIGN_SHOW_MAX]; ///< sign attributes for the sign column @@ -337,13 +345,36 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode, } /// Return true if CursorLineSign highlight is to be used. -static bool use_cursor_line_sign(win_T *wp, linenr_T lnum) +static bool use_cursor_line_highlight(win_T *wp, linenr_T lnum) { return wp->w_p_cul && lnum == wp->w_cursorline && (wp->w_p_culopt_flags & CULOPT_NBR); } +/// Setup for drawing the 'foldcolumn', if there is one. +static void handle_foldcolumn(win_T *wp, winlinevars_T *wlv) +{ + int fdc = compute_foldcolumn(wp, 0); + if (fdc <= 0) { + return; + } + + // Allocate a buffer, "wlv->extra[]" may already be in use. + xfree(wlv->p_extra_free); + wlv->p_extra_free = xmalloc(MAX_MCO * (size_t)fdc + 1); + wlv->n_extra = (int)fill_foldcolumn(wlv->p_extra_free, wp, wlv->foldinfo, wlv->lnum); + wlv->p_extra_free[wlv->n_extra] = NUL; + wlv->p_extra = wlv->p_extra_free; + wlv->c_extra = NUL; + wlv->c_final = NUL; + if (use_cursor_line_highlight(wp, wlv->lnum)) { + wlv->char_attr = win_hl_attr(wp, HLF_CLF); + } else { + wlv->char_attr = win_hl_attr(wp, HLF_FC); + } +} + /// Get information needed to display the sign in line "wlv->lnum" in window "wp". /// If "nrcol" is true, the sign is going to be displayed in the number column. /// Otherwise the sign is going to be displayed in the sign column. @@ -356,7 +387,7 @@ static void get_sign_display_info(bool nrcol, win_T *wp, winlinevars_T *wlv, int if (nrcol) { wlv->n_extra = number_width(wp) + 1; } else { - if (use_cursor_line_sign(wp, wlv->lnum)) { + if (use_cursor_line_highlight(wp, wlv->lnum)) { wlv->char_attr = win_hl_attr(wp, HLF_CLS); } else { wlv->char_attr = win_hl_attr(wp, HLF_SC); @@ -401,7 +432,7 @@ static void get_sign_display_info(bool nrcol, win_T *wp, winlinevars_T *wlv, int } } - if (use_cursor_line_sign(wp, wlv->lnum) && sign_cul_attr > 0) { + if (use_cursor_line_highlight(wp, wlv->lnum) && sign_cul_attr > 0) { wlv->char_attr = sign_cul_attr; } else { wlv->char_attr = sattr->hl_attr_id; @@ -615,6 +646,49 @@ static void get_statuscol_display_info(statuscol_T *stcp, winlinevars_T *wlv) } while (wlv->n_extra == 0 && stcp->textp < stcp->text_end); } +static void handle_breakindent(win_T *wp, winlinevars_T *wlv) +{ + if (wp->w_briopt_sbr && wlv->draw_state == WL_BRI - 1 + && *get_showbreak_value(wp) != NUL) { + // draw indent after showbreak value + wlv->draw_state = WL_BRI; + } else if (wp->w_briopt_sbr && wlv->draw_state == WL_SBR) { + // after the showbreak, draw the breakindent + wlv->draw_state = WL_BRI - 1; + } + + // draw 'breakindent': indent wrapped text accordingly + if (wlv->draw_state == WL_BRI - 1 && wlv->n_extra == 0) { + wlv->draw_state = WL_BRI; + // if wlv->need_showbreak is set, breakindent also applies + if (wp->w_p_bri && (wlv->row != wlv->startrow || wlv->need_showbreak) + && wlv->filler_lines == 0) { + wlv->char_attr = 0; + if (wlv->diff_hlf != (hlf_T)0) { + wlv->char_attr = win_hl_attr(wp, (int)wlv->diff_hlf); + } + wlv->p_extra = NULL; + wlv->c_extra = ' '; + wlv->c_final = NUL; + wlv->n_extra = get_breakindent_win(wp, ml_get_buf(wp->w_buffer, wlv->lnum, false)); + if (wlv->row == wlv->startrow) { + wlv->n_extra -= win_col_off2(wp); + if (wlv->n_extra < 0) { + wlv->n_extra = 0; + } + } + if (wp->w_skipcol > 0 && wp->w_p_wrap && wp->w_briopt_sbr) { + wlv->need_showbreak = false; + } + // Correct end of highlighted area for 'breakindent', + // required wen 'linebreak' is also set. + if (wlv->tocol == wlv->vcol) { + wlv->tocol += wlv->n_extra; + } + } + } +} + static void apply_cursorline_highlight(win_T *wp, winlinevars_T *wlv) { wlv->cul_attr = win_hl_attr(wp, HLF_CUL); @@ -739,8 +813,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int n_skip = 0; // nr of chars to skip for 'nowrap' - int fromcol = -10; // start of inverting - int tocol = MAXCOL; // end of inverting int fromcol_prev = -2; // start of inverting after cursor bool noinvcur = false; // don't invert the cursor bool lnum_in_visual_area = false; @@ -779,12 +851,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int mb_c = 0; // decoded multi-byte character bool mb_utf8 = false; // screen char is UTF-8 char int u8cc[MAX_MCO]; // composing UTF-8 chars - hlf_T diff_hlf = (hlf_T)0; // type of diff highlighting int change_start = MAXCOL; // first col of changed area int change_end = -1; // last col of changed area bool in_multispace = false; // in multiple consecutive spaces int multispace_pos = 0; // position in lcs-multispace string - bool need_showbreak = false; // overlong line, skip first x chars int line_attr_save; int line_attr_lowprio_save; int prev_c = 0; // previous Arabic character @@ -832,8 +902,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, CLEAR_FIELD(wlv); wlv.lnum = lnum; + wlv.foldinfo = foldinfo; wlv.startrow = startrow; wlv.row = startrow; + wlv.fromcol = -10; + wlv.tocol = MAXCOL; buf_T *buf = wp->w_buffer; bool end_fill = (lnum == buf->b_ml.ml_line_count + 1); @@ -935,37 +1008,37 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (VIsual_mode == Ctrl_V) { // block mode if (lnum_in_visual_area) { - fromcol = wp->w_old_cursor_fcol; - tocol = wp->w_old_cursor_lcol; + wlv.fromcol = wp->w_old_cursor_fcol; + wlv.tocol = wp->w_old_cursor_lcol; } } else { // non-block mode if (lnum > top->lnum && lnum <= bot->lnum) { - fromcol = 0; + wlv.fromcol = 0; } else if (lnum == top->lnum) { if (VIsual_mode == 'V') { // linewise - fromcol = 0; + wlv.fromcol = 0; } else { - getvvcol(wp, top, (colnr_T *)&fromcol, NULL, NULL); + getvvcol(wp, top, (colnr_T *)&wlv.fromcol, NULL, NULL); if (gchar_pos(top) == NUL) { - tocol = fromcol + 1; + wlv.tocol = wlv.fromcol + 1; } } } if (VIsual_mode != 'V' && lnum == bot->lnum) { if (*p_sel == 'e' && bot->col == 0 && bot->coladd == 0) { - fromcol = -10; - tocol = MAXCOL; + wlv.fromcol = -10; + wlv.tocol = MAXCOL; } else if (bot->col == MAXCOL) { - tocol = MAXCOL; + wlv.tocol = MAXCOL; } else { pos = *bot; if (*p_sel == 'e') { - getvvcol(wp, &pos, (colnr_T *)&tocol, NULL, NULL); + getvvcol(wp, &pos, (colnr_T *)&wlv.tocol, NULL, NULL); } else { - getvvcol(wp, &pos, NULL, NULL, (colnr_T *)&tocol); - tocol++; + getvvcol(wp, &pos, NULL, NULL, (colnr_T *)&wlv.tocol); + wlv.tocol++; } } } @@ -978,7 +1051,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } // if inverting in this line set area_highlighting - if (fromcol >= 0) { + if (wlv.fromcol >= 0) { area_highlighting = true; vi_attr = win_hl_attr(wp, HLF_V); } @@ -990,18 +1063,18 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, && lnum <= curwin->w_cursor.lnum + search_match_lines) { if (lnum == curwin->w_cursor.lnum) { getvcol(curwin, &(curwin->w_cursor), - (colnr_T *)&fromcol, NULL, NULL); + (colnr_T *)&wlv.fromcol, NULL, NULL); } else { - fromcol = 0; + wlv.fromcol = 0; } if (lnum == curwin->w_cursor.lnum + search_match_lines) { pos.lnum = lnum; pos.col = search_match_endcol; - getvcol(curwin, &pos, (colnr_T *)&tocol, NULL, NULL); + getvcol(curwin, &pos, (colnr_T *)&wlv.tocol, NULL, NULL); } // do at least one character; happens when past end of line - if (fromcol == tocol && search_match_endcol) { - tocol = fromcol + 1; + if (wlv.fromcol == wlv.tocol && search_match_endcol) { + wlv.tocol = wlv.fromcol + 1; } area_highlighting = true; vi_attr = win_hl_attr(wp, HLF_I); @@ -1015,14 +1088,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (wlv.filler_lines < 0 || linestatus < 0) { if (wlv.filler_lines == -1 || linestatus == -1) { if (diff_find_change(wp, lnum, &change_start, &change_end)) { - diff_hlf = HLF_ADD; // added line + wlv.diff_hlf = HLF_ADD; // added line } else if (change_start == 0) { - diff_hlf = HLF_TXD; // changed text + wlv.diff_hlf = HLF_TXD; // changed text } else { - diff_hlf = HLF_CHD; // changed line + wlv.diff_hlf = HLF_CHD; // changed line } } else { - diff_hlf = HLF_ADD; // added line + wlv.diff_hlf = HLF_ADD; // added line } if (linestatus == 0) { wlv.filler_lines = 0; @@ -1173,15 +1246,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // Adjust for when the inverted text is before the screen, // and when the start of the inverted text is before the screen. - if (tocol <= wlv.vcol) { - fromcol = 0; - } else if (fromcol >= 0 && fromcol < wlv.vcol) { - fromcol = wlv.vcol; + if (wlv.tocol <= wlv.vcol) { + wlv.fromcol = 0; + } else if (wlv.fromcol >= 0 && wlv.fromcol < wlv.vcol) { + wlv.fromcol = wlv.vcol; } // When w_skipcol is non-zero, first line needs 'showbreak' if (wp->w_p_wrap) { - need_showbreak = true; + wlv.need_showbreak = true; } // When spell checking a word we need to figure out the start of the // word and if it's badly spelled or not. @@ -1225,20 +1298,20 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // Correct highlighting for cursor that can't be disabled. // Avoids having to check this for each character. - if (fromcol >= 0) { + if (wlv.fromcol >= 0) { if (noinvcur) { - if ((colnr_T)fromcol == wp->w_virtcol) { + if ((colnr_T)wlv.fromcol == wp->w_virtcol) { // highlighting starts at cursor, let it start just after the // cursor - fromcol_prev = fromcol; - fromcol = -1; - } else if ((colnr_T)fromcol < wp->w_virtcol) { + fromcol_prev = wlv.fromcol; + wlv.fromcol = -1; + } else if ((colnr_T)wlv.fromcol < wp->w_virtcol) { // restart highlighting after the cursor fromcol_prev = wp->w_virtcol; } } - if (fromcol >= tocol) { - fromcol = -1; + if (wlv.fromcol >= wlv.tocol) { + wlv.fromcol = -1; } } @@ -1266,7 +1339,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, statuscol.sattrs = wlv.sattrs; statuscol.foldinfo = foldinfo; statuscol.width = win_col_off(wp) - (cmdwin_type != 0 && wp == curwin); - statuscol.use_cul = use_cursor_line_sign(wp, lnum); + statuscol.use_cul = use_cursor_line_highlight(wp, lnum); statuscol.sign_cul_attr = statuscol.use_cul ? sign_cul_attr : 0; statuscol.num_attr = sign_num_attr ? sign_num_attr : get_line_number_attr(wp, &wlv); } @@ -1319,24 +1392,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } if (wlv.draw_state == WL_FOLD - 1 && wlv.n_extra == 0) { - int fdc = compute_foldcolumn(wp, 0); wlv.draw_state = WL_FOLD; - if (fdc > 0) { - // Draw the 'foldcolumn'. - // Allocate a buffer, "wlv->extra[]" may already be in use. - xfree(wlv.p_extra_free); - wlv.p_extra_free = xmalloc(MAX_MCO * (size_t)fdc + 1); - wlv.n_extra = (int)fill_foldcolumn(wlv.p_extra_free, wp, foldinfo, lnum); - wlv.p_extra_free[wlv.n_extra] = NUL; - wlv.p_extra = wlv.p_extra_free; - wlv.c_extra = NUL; - wlv.c_final = NUL; - if (use_cursor_line_sign(wp, lnum)) { - wlv.char_attr = win_hl_attr(wp, HLF_CLF); - } else { - wlv.char_attr = win_hl_attr(wp, HLF_FC); - } - } + handle_foldcolumn(wp, &wlv); } // sign column, this is hit until sign_idx reaches count @@ -1378,46 +1435,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, win_col_offset = wlv.off; } - if (wp->w_briopt_sbr && wlv.draw_state == WL_BRI - 1 - && wlv.n_extra == 0 && *get_showbreak_value(wp) != NUL) { - // draw indent after showbreak value - wlv.draw_state = WL_BRI; - } else if (wp->w_briopt_sbr && wlv.draw_state == WL_SBR && wlv.n_extra == 0) { - // after the showbreak, draw the breakindent - wlv.draw_state = WL_BRI - 1; - } - - // draw 'breakindent': indent wrapped text accordingly - if (wlv.draw_state == WL_BRI - 1 && wlv.n_extra == 0) { - wlv.draw_state = WL_BRI; - // if need_showbreak is set, breakindent also applies - if (wp->w_p_bri && (wlv.row != startrow || need_showbreak) - && wlv.filler_lines == 0) { - wlv.char_attr = 0; - - if (diff_hlf != (hlf_T)0) { - wlv.char_attr = win_hl_attr(wp, (int)diff_hlf); - } - wlv.p_extra = NULL; - wlv.c_extra = ' '; - wlv.c_final = NUL; - wlv.n_extra = - get_breakindent_win(wp, ml_get_buf(wp->w_buffer, lnum, false)); - if (wlv.row == startrow) { - wlv.n_extra -= win_col_off2(wp); - if (wlv.n_extra < 0) { - wlv.n_extra = 0; - } - } - if (wp->w_skipcol > 0 && wp->w_p_wrap && wp->w_briopt_sbr) { - need_showbreak = false; - } - // Correct end of highlighted area for 'breakindent', - // required wen 'linebreak' is also set. - if (tocol == wlv.vcol) { - tocol += wlv.n_extra; - } - } + // Check if 'breakindent' applies and show it. + // May change wlv.draw_state to WL_BRI or WL_BRI - 1. + if (wlv.n_extra == 0) { + handle_breakindent(wp, &wlv); } if (wlv.draw_state == WL_SBR - 1 && wlv.n_extra == 0) { @@ -1450,7 +1471,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, wlv.char_attr = win_hl_attr(wp, HLF_DED); } char *const sbr = get_showbreak_value(wp); - if (*sbr != NUL && need_showbreak) { + if (*sbr != NUL && wlv.need_showbreak) { // Draw 'showbreak' at the start of each broken line. wlv.p_extra = sbr; wlv.c_extra = NUL; @@ -1458,13 +1479,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, wlv.n_extra = (int)strlen(sbr); wlv.char_attr = win_hl_attr(wp, HLF_AT); if (wp->w_skipcol == 0 || !wp->w_p_wrap) { - need_showbreak = false; + wlv.need_showbreak = false; } vcol_sbr = wlv.vcol + mb_charlen(sbr); // Correct end of highlighted area for 'showbreak', // required when 'linebreak' is also set. - if (tocol == wlv.vcol) { - tocol += wlv.n_extra; + if (wlv.tocol == wlv.vcol) { + wlv.tocol += wlv.n_extra; } // Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'. if (wlv.cul_attr) { @@ -1564,19 +1585,18 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (wlv.draw_state == WL_LINE && (area_highlighting || has_spell)) { // handle Visual or match highlighting in this line - if (wlv.vcol == fromcol - || (wlv.vcol + 1 == fromcol && wlv.n_extra == 0 + if (wlv.vcol == wlv.fromcol + || (wlv.vcol + 1 == wlv.fromcol && wlv.n_extra == 0 && utf_ptr2cells(ptr) > 1) || ((int)vcol_prev == fromcol_prev && vcol_prev < wlv.vcol // not at margin - && wlv.vcol < tocol)) { + && wlv.vcol < wlv.tocol)) { area_attr = vi_attr; // start highlighting if (area_highlighting) { area_active = true; } - } else if (area_attr != 0 && (wlv.vcol == tocol - || (noinvcur - && wlv.vcol == wp->w_virtcol))) { + } else if (area_attr != 0 && (wlv.vcol == wlv.tocol + || (noinvcur && wlv.vcol == wp->w_virtcol))) { area_attr = 0; // stop highlighting area_active = false; } @@ -1598,16 +1618,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } } - if (diff_hlf != (hlf_T)0) { - if (diff_hlf == HLF_CHD && ptr - line >= change_start + if (wlv.diff_hlf != (hlf_T)0) { + if (wlv.diff_hlf == HLF_CHD && ptr - line >= change_start && wlv.n_extra == 0) { - diff_hlf = HLF_TXD; // changed text + wlv.diff_hlf = HLF_TXD; // changed text } - if (diff_hlf == HLF_TXD && ptr - line > change_end + if (wlv.diff_hlf == HLF_TXD && ptr - line > change_end && wlv.n_extra == 0) { - diff_hlf = HLF_CHD; // changed line + wlv.diff_hlf = HLF_CHD; // changed line } - wlv.line_attr = win_hl_attr(wp, (int)diff_hlf); + wlv.line_attr = win_hl_attr(wp, (int)wlv.diff_hlf); // Overlay CursorLine onto diff-mode highlight. if (wlv.cul_attr) { wlv.line_attr = 0 != wlv.line_attr_lowprio // Low-priority CursorLine @@ -1628,9 +1648,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } } else if (search_attr != 0) { wlv.char_attr = hl_combine_attr(wlv.line_attr, search_attr); - } else if (wlv.line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL) - || wlv.vcol < fromcol || vcol_prev < fromcol_prev - || wlv.vcol >= tocol)) { + } else if (wlv.line_attr != 0 + && ((wlv.fromcol == -10 && wlv.tocol == MAXCOL) + || wlv.vcol < wlv.fromcol + || vcol_prev < fromcol_prev + || wlv.vcol >= wlv.tocol)) { // Use wlv.line_attr when not in the Visual or 'incsearch' area // (area_attr may be 0 when "noinvcur" is set). wlv.char_attr = wlv.line_attr; @@ -2199,8 +2221,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } } else if (c == NUL && (wp->w_p_list - || ((fromcol >= 0 || fromcol_prev >= 0) - && tocol > wlv.vcol + || ((wlv.fromcol >= 0 || fromcol_prev >= 0) + && wlv.tocol > wlv.vcol && VIsual_mode != Ctrl_V && (wp->w_p_rl ? (wlv.col >= 0) : (wlv.col < grid->cols)) && !(noinvcur @@ -2210,12 +2232,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // Display a '$' after the line or highlight an extra // character if the line break is included. // For a diff line the highlighting continues after the "$". - if (diff_hlf == (hlf_T)0 + if (wlv.diff_hlf == (hlf_T)0 && wlv.line_attr == 0 && wlv.line_attr_lowprio == 0) { // In virtualedit, visual selections may extend beyond end of line if (area_highlighting && virtual_active() - && tocol != MAXCOL && wlv.vcol < tocol) { + && wlv.tocol != MAXCOL && wlv.vcol < wlv.tocol) { wlv.n_extra = 0; } else { wlv.p_extra = at_end_str; @@ -2268,8 +2290,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, } else if (VIsual_active && (VIsual_mode == Ctrl_V || VIsual_mode == 'v') && virtual_active() - && tocol != MAXCOL - && wlv.vcol < tocol + && wlv.tocol != MAXCOL + && wlv.vcol < wlv.tocol && (wp->w_p_rl ? (wlv.col >= 0) : (wlv.col < grid->cols))) { c = ' '; ptr--; // put it back at the NUL @@ -2399,7 +2421,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // char on the screen, just overwrite that one (tricky!) Not // needed when a '$' was displayed for 'list'. if (wp->w_p_lcs_chars.eol == lcs_eol_one - && ((area_attr != 0 && wlv.vcol == fromcol + && ((area_attr != 0 && wlv.vcol == wlv.fromcol && (VIsual_mode != Ctrl_V || lnum == VIsual.lnum || lnum == curwin->w_cursor.lnum)) @@ -2490,7 +2512,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, (long)grid->cols * (wlv.row - startrow + 1) + v && lnum != wp->w_cursor.lnum) || draw_color_col || wlv.line_attr_lowprio || wlv.line_attr - || diff_hlf != (hlf_T)0 || has_virttext)) { + || wlv.diff_hlf != (hlf_T)0 || has_virttext)) { int rightmost_vcol = 0; if (wp->w_p_cuc) { @@ -2510,11 +2532,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, int mc_attr = win_hl_attr(wp, HLF_MC); int diff_attr = 0; - if (diff_hlf == HLF_TXD) { - diff_hlf = HLF_CHD; + if (wlv.diff_hlf == HLF_TXD) { + wlv.diff_hlf = HLF_CHD; } - if (diff_hlf != 0) { - diff_attr = win_hl_attr(wp, (int)diff_hlf); + if (wlv.diff_hlf != 0) { + diff_attr = win_hl_attr(wp, (int)wlv.diff_hlf); } int base_attr = hl_combine_attr(wlv.line_attr_lowprio, diff_attr); @@ -2667,10 +2689,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (wlv.draw_state > WL_STC && wlv.filler_todo <= 0) { wlv.vcol++; } - // When "tocol" is halfway through a character, set it to the end of - // the character, otherwise highlighting won't stop. - if (tocol == wlv.vcol) { - tocol++; + // When "wlv.tocol" is halfway through a character, set it to the end + // of the character, otherwise highlighting won't stop. + if (wlv.tocol == wlv.vcol) { + wlv.tocol++; } if (wp->w_p_rl) { // now it's time to backup one cell @@ -2840,7 +2862,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, wlv.n_extra = 0; lcs_prec_todo = wp->w_p_lcs_chars.prec; if (wlv.filler_todo <= 0) { - need_showbreak = true; + wlv.need_showbreak = true; } if (statuscol.draw) { if (wlv.row == startrow + wlv.filler_lines + 1 -- cgit From bdde07f60ee452ea598b631be24609134654762a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 3 Mar 2023 18:13:53 +0800 Subject: vim-patch:9.0.0533: the win_line() function is much too long Problem: The win_line() function is much too long. Solution: Move code to separate functions. https://github.com/vim/vim/commit/e49f9acecc03755db850410b2590ad7312c5224b Co-authored-by: Bram Moolenaar --- src/nvim/drawline.c | 189 ++++++++++++++++++++++++++++------------------------ 1 file changed, 103 insertions(+), 86 deletions(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 1a4f718c11..dbbeabbba2 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -92,6 +92,7 @@ typedef struct { int fromcol; ///< start of inverting int tocol; ///< end of inverting + long vcol_sbr; ///< virtual column after showbreak bool need_showbreak; ///< overlong line, skipping first x chars int char_attr; ///< attributes for next character @@ -104,10 +105,18 @@ typedef struct { int c_extra; ///< extra chars, all the same int c_final; ///< final char, mandatory if set + // saved "extra" items for when draw_state becomes WL_LINE (again) + int saved_n_extra; + char *saved_p_extra; + int saved_c_extra; + int saved_c_final; + int saved_char_attr; + char extra[57]; ///< sign, line number and 'fdc' must fit in here hlf_T diff_hlf; ///< type of diff highlighting + int n_virt_lines; ///< nr of virtual lines int filler_lines; ///< nr of filler lines to be drawn int filler_todo; ///< nr of filler lines still to do + 1 SignTextAttrs sattrs[SIGN_SHOW_MAX]; ///< sign attributes for the sign column @@ -689,6 +698,60 @@ static void handle_breakindent(win_T *wp, winlinevars_T *wlv) } } +static void handle_showbreak_and_filler(win_T *wp, winlinevars_T *wlv) +{ + if (wlv->filler_todo > wlv->filler_lines - wlv->n_virt_lines) { + // TODO(bfredl): check this doesn't inhibit TUI-style + // clear-to-end-of-line. + wlv->c_extra = ' '; + wlv->c_final = NUL; + if (wp->w_p_rl) { + wlv->n_extra = wlv->col + 1; + } else { + wlv->n_extra = wp->w_grid.cols - wlv->col; + } + wlv->char_attr = 0; + } else if (wlv->filler_todo > 0) { + // Draw "deleted" diff line(s) + if (char2cells(wp->w_p_fcs_chars.diff) > 1) { + wlv->c_extra = '-'; + wlv->c_final = NUL; + } else { + wlv->c_extra = wp->w_p_fcs_chars.diff; + wlv->c_final = NUL; + } + if (wp->w_p_rl) { + wlv->n_extra = wlv->col + 1; + } else { + wlv->n_extra = wp->w_grid.cols - wlv->col; + } + wlv->char_attr = win_hl_attr(wp, HLF_DED); + } + + char *const sbr = get_showbreak_value(wp); + if (*sbr != NUL && wlv->need_showbreak) { + // Draw 'showbreak' at the start of each broken line. + wlv->p_extra = sbr; + wlv->c_extra = NUL; + wlv->c_final = NUL; + wlv->n_extra = (int)strlen(sbr); + wlv->char_attr = win_hl_attr(wp, HLF_AT); + if (wp->w_skipcol == 0 || !wp->w_p_wrap) { + wlv->need_showbreak = false; + } + wlv->vcol_sbr = wlv->vcol + mb_charlen(sbr); + // Correct end of highlighted area for 'showbreak', + // required when 'linebreak' is also set. + if (wlv->tocol == wlv->vcol) { + wlv->tocol += wlv->n_extra; + } + // Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'. + if (wlv->cul_attr) { + wlv->char_attr = hl_combine_attr(wlv->cul_attr, wlv->char_attr); + } + } +} + static void apply_cursorline_highlight(win_T *wp, winlinevars_T *wlv) { wlv->cul_attr = win_hl_attr(wp, HLF_CUL); @@ -756,10 +819,11 @@ static colnr_T get_leadcol(win_T *wp, const char *ptr, const char *line) } /// Start a screen line at column zero. -static void win_line_start(win_T *wp, winlinevars_T *wlv) +static void win_line_start(win_T *wp, winlinevars_T *wlv, bool save_extra) { wlv->col = 0; wlv->off = 0; + if (wp->w_p_rl) { // Rightleft window: process the text in the normal direction, but put // it in linebuf_char[wlv.off] from right to left. Start at the @@ -767,6 +831,33 @@ static void win_line_start(win_T *wp, winlinevars_T *wlv) wlv->col = wp->w_grid.cols - 1; wlv->off += wlv->col; } + + if (save_extra) { + // reset the drawing state for the start of a wrapped line + wlv->draw_state = WL_START; + wlv->saved_n_extra = wlv->n_extra; + wlv->saved_p_extra = wlv->p_extra; + wlv->saved_c_extra = wlv->c_extra; + wlv->saved_c_final = wlv->c_final; + wlv->saved_char_attr = wlv->char_attr; + + wlv->n_extra = 0; + } +} + +/// Called when wlv->draw_state is set to WL_LINE. +static void win_line_continue(winlinevars_T *wlv) +{ + if (wlv->saved_n_extra > 0) { + // Continue item from end of wrapped line. + wlv->n_extra = wlv->saved_n_extra; + wlv->c_extra = wlv->saved_c_extra; + wlv->c_final = wlv->saved_c_final; + wlv->p_extra = wlv->saved_p_extra; + wlv->char_attr = wlv->saved_char_attr; + } else { + wlv->char_attr = 0; + } } /// Display line "lnum" of window 'wp' on the screen. @@ -789,7 +880,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, winlinevars_T wlv; // variables passed between functions int c = 0; // init for GCC - long vcol_sbr = -1; // virtual column after showbreak long vcol_prev = -1; // "wlv.vcol" of previous character char *line; // current line char *ptr; // current position in "line" @@ -799,13 +889,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // at end-of-line bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0; - // saved "extra" items for when draw_state becomes WL_LINE (again) - int saved_n_extra = 0; - char *saved_p_extra = NULL; - int saved_c_extra = 0; - int saved_c_final = 0; - int saved_char_attr = 0; - int n_attr = 0; // chars with special attr int saved_attr2 = 0; // char_attr saved for n_attr int n_attr3 = 0; // chars with overruling special attr @@ -907,6 +990,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, wlv.row = startrow; wlv.fromcol = -10; wlv.tocol = MAXCOL; + wlv.vcol_sbr = -1; buf_T *buf = wp->w_buffer; bool end_fill = (lnum == buf->b_ml.ml_line_count + 1); @@ -1103,11 +1187,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, area_highlighting = true; } VirtLines virt_lines = KV_INITIAL_VALUE; - int n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines, has_fold); - wlv.filler_lines += n_virt_lines; + wlv.n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines, has_fold); + wlv.filler_lines += wlv.n_virt_lines; if (lnum == wp->w_topline) { wlv.filler_lines = wp->w_topfill; - n_virt_lines = MIN(n_virt_lines, wlv.filler_lines); + wlv.n_virt_lines = MIN(wlv.n_virt_lines, wlv.filler_lines); } wlv.filler_todo = wlv.filler_lines; @@ -1323,7 +1407,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, ptr = line + v; // "line" may have been updated } - win_line_start(wp, &wlv); + win_line_start(wp, &wlv, false); // won't highlight after TERM_ATTRS_MAX columns int term_attrs[TERM_ATTRS_MAX] = { 0 }; @@ -1375,7 +1459,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (wlv.draw_state == WL_FOLD - 1 && wlv.n_extra == 0) { if (wlv.filler_todo > 0) { - int index = wlv.filler_todo - (wlv.filler_lines - n_virt_lines); + int index = wlv.filler_todo - (wlv.filler_lines - wlv.n_virt_lines); if (index > 0) { virt_line_index = (int)kv_size(virt_lines) - index; assert(virt_line_index >= 0); @@ -1443,76 +1527,17 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (wlv.draw_state == WL_SBR - 1 && wlv.n_extra == 0) { wlv.draw_state = WL_SBR; - if (wlv.filler_todo > wlv.filler_lines - n_virt_lines) { - // TODO(bfredl): check this doesn't inhibit TUI-style - // clear-to-end-of-line. - wlv.c_extra = ' '; - wlv.c_final = NUL; - if (wp->w_p_rl) { - wlv.n_extra = wlv.col + 1; - } else { - wlv.n_extra = grid->cols - wlv.col; - } - wlv.char_attr = 0; - } else if (wlv.filler_todo > 0) { - // Draw "deleted" diff line(s) - if (char2cells(wp->w_p_fcs_chars.diff) > 1) { - wlv.c_extra = '-'; - wlv.c_final = NUL; - } else { - wlv.c_extra = wp->w_p_fcs_chars.diff; - wlv.c_final = NUL; - } - if (wp->w_p_rl) { - wlv.n_extra = wlv.col + 1; - } else { - wlv.n_extra = grid->cols - wlv.col; - } - wlv.char_attr = win_hl_attr(wp, HLF_DED); - } - char *const sbr = get_showbreak_value(wp); - if (*sbr != NUL && wlv.need_showbreak) { - // Draw 'showbreak' at the start of each broken line. - wlv.p_extra = sbr; - wlv.c_extra = NUL; - wlv.c_final = NUL; - wlv.n_extra = (int)strlen(sbr); - wlv.char_attr = win_hl_attr(wp, HLF_AT); - if (wp->w_skipcol == 0 || !wp->w_p_wrap) { - wlv.need_showbreak = false; - } - vcol_sbr = wlv.vcol + mb_charlen(sbr); - // Correct end of highlighted area for 'showbreak', - // required when 'linebreak' is also set. - if (wlv.tocol == wlv.vcol) { - wlv.tocol += wlv.n_extra; - } - // Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'. - if (wlv.cul_attr) { - wlv.char_attr = hl_combine_attr(wlv.cul_attr, wlv.char_attr); - } - } + handle_showbreak_and_filler(wp, &wlv); } if (wlv.draw_state == WL_LINE - 1 && wlv.n_extra == 0) { sign_idx = 0; wlv.draw_state = WL_LINE; - if (has_decor && wlv.row == startrow + wlv.filler_lines) { // hide virt_text on text hidden by 'nowrap' decor_redraw_col(wp->w_buffer, wlv.vcol, wlv.off, true, &decor_state); } - - if (saved_n_extra) { - // Continue item from end of wrapped line. - wlv.n_extra = saved_n_extra; - wlv.c_extra = saved_c_extra; - wlv.c_final = saved_c_final; - wlv.p_extra = saved_p_extra; - wlv.char_attr = saved_char_attr; - } else { - wlv.char_attr = 0; - } + win_line_continue(&wlv); // use wlv.saved_ values } } @@ -2011,7 +2036,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // We have just drawn the showbreak value, no need to add // space for it again. - if (wlv.vcol == vcol_sbr) { + if (wlv.vcol == wlv.vcol_sbr) { wlv.n_extra -= mb_charlen(get_showbreak_value(wp)); if (wlv.n_extra < 0) { wlv.n_extra = 0; @@ -2112,7 +2137,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, // Only adjust the tab_len, when at the first column after the // showbreak value was drawn. - if (*sbr != NUL && wlv.vcol == vcol_sbr && wp->w_p_wrap) { + if (*sbr != NUL && wlv.vcol == wlv.vcol_sbr && wp->w_p_wrap) { vcol_adjusted = wlv.vcol - mb_charlen(sbr); } // tab amount depends on current column @@ -2850,16 +2875,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, break; } - win_line_start(wp, &wlv); + win_line_start(wp, &wlv, true); - // reset the drawing state for the start of a wrapped line - wlv.draw_state = WL_START; - saved_n_extra = wlv.n_extra; - saved_p_extra = wlv.p_extra; - saved_c_extra = wlv.c_extra; - saved_c_final = wlv.c_final; - saved_char_attr = wlv.char_attr; - wlv.n_extra = 0; lcs_prec_todo = wp->w_p_lcs_chars.prec; if (wlv.filler_todo <= 0) { wlv.need_showbreak = true; -- cgit From 166b149d5b473f277c63e64ced03c40df44ac3c9 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 27 Feb 2023 16:30:32 +0100 Subject: refactor(build): remove unused stdlib function and include checks In addition: merge some checks for the same feature into one test_compile. This reduces the total number of test compiles which speeds up the cmake configure stage. --- src/nvim/CMakeLists.txt | 10 ++++++---- src/nvim/charset.c | 2 +- src/nvim/fileio.c | 10 +++++----- src/nvim/os/os_defs.h | 5 ++--- src/nvim/os/shell.c | 4 ++-- src/nvim/os/users.c | 10 +++++----- 6 files changed, 21 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 8c23b501f9..504dde5a9c 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -240,13 +240,15 @@ endif() if(UNIX) # -fstack-protector breaks non Unix builds even in Mingw-w64 check_c_compiler_flag(-fstack-protector-strong HAS_FSTACK_PROTECTOR_STRONG_FLAG) - check_c_compiler_flag(-fstack-protector HAS_FSTACK_PROTECTOR_FLAG) if(HAS_FSTACK_PROTECTOR_STRONG_FLAG) target_compile_options(main_lib INTERFACE -fstack-protector-strong) target_link_libraries(main_lib INTERFACE -fstack-protector-strong) - elseif(HAS_FSTACK_PROTECTOR_FLAG) - target_compile_options(main_lib INTERFACE -fstack-protector --param ssp-buffer-size=4) - target_link_libraries(main_lib INTERFACE -fstack-protector --param ssp-buffer-size=4) + else() + check_c_compiler_flag(-fstack-protector HAS_FSTACK_PROTECTOR_FLAG) + if(HAS_FSTACK_PROTECTOR_FLAG) + target_compile_options(main_lib INTERFACE -fstack-protector --param ssp-buffer-size=4) + target_link_libraries(main_lib INTERFACE -fstack-protector --param ssp-buffer-size=4) + endif() endif() endif() diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 1cfb5350f3..bf18d110c0 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1446,7 +1446,7 @@ long getdigits_long(char **pp, bool strict, long def) int32_t getdigits_int32(char **pp, bool strict, long def) { intmax_t number = getdigits(pp, strict, def); -#if SIZEOF_INTMAX_T > SIZEOF_INT32_T +#if SIZEOF_INTMAX_T > 4 if (strict) { assert(number >= INT32_MIN && number <= INT32_MAX); } else if (!(number >= INT32_MIN && number <= INT32_MAX)) { diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 755b8e0834..c93df43cff 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -68,7 +68,7 @@ # include "nvim/charset.h" #endif -#if defined(HAVE_FLOCK) && defined(HAVE_DIRFD) +#ifdef HAVE_DIRFD_AND_FLOCK # include # include #endif @@ -5146,7 +5146,7 @@ void forward_slash(char *fname) /// Path to Nvim's own temp dir. Ends in a slash. static char *vim_tempdir = NULL; -#if defined(HAVE_FLOCK) && defined(HAVE_DIRFD) +#ifdef HAVE_DIRFD_AND_FLOCK DIR *vim_tempdir_dp = NULL; ///< File descriptor of temp dir #endif @@ -5316,7 +5316,7 @@ int delete_recursive(const char *name) return result; } -#if defined(HAVE_FLOCK) && defined(HAVE_DIRFD) +#ifdef HAVE_DIRFD_AND_FLOCK /// Open temporary directory and take file lock to prevent /// to be auto-cleaned. static void vim_opentempdir(void) @@ -5353,7 +5353,7 @@ void vim_deltempdir(void) return; } -#if defined(HAVE_FLOCK) && defined(HAVE_DIRFD) +#ifdef HAVE_DIRFD_AND_FLOCK vim_closetempdir(); #endif // remove the trailing path separator @@ -5391,7 +5391,7 @@ static bool vim_settempdir(char *tempdir) vim_FullName(tempdir, buf, MAXPATHL, false); add_pathsep(buf); vim_tempdir = xstrdup(buf); -#if defined(HAVE_FLOCK) && defined(HAVE_DIRFD) +#ifdef HAVE_DIRFD_AND_FLOCK vim_opentempdir(); #endif xfree(buf); diff --git a/src/nvim/os/os_defs.h b/src/nvim/os/os_defs.h index f86c0d3483..9e201f1dfa 100644 --- a/src/nvim/os/os_defs.h +++ b/src/nvim/os/os_defs.h @@ -36,10 +36,9 @@ // Command-processing buffer. Use large buffers for all platforms. #define CMDBUFFSIZE 1024 -// Note: Some systems need both string.h and strings.h (Savage). However, -// some systems can't handle both, only use string.h in that case. +// Note: Some systems need both string.h and strings.h (Savage). #include -#if defined(HAVE_STRINGS_H) && !defined(NO_STRINGS_WITH_STRING_H) +#ifdef HAVE_STRINGS_H # include #endif diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index f1e2c5440f..f7d1154169 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -399,8 +399,8 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in fclose(fd); return FAIL; } -#if SIZEOF_LONG_LONG > SIZEOF_SIZE_T - assert(templen <= (long long)SIZE_MAX); // NOLINT(runtime/int) +#if 8 > SIZEOF_SIZE_T + assert(templen <= SIZE_MAX); // NOLINT(runtime/int) #endif len = (size_t)templen; fseek(fd, 0L, SEEK_SET); diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c index ef2986246b..411ba91fa7 100644 --- a/src/nvim/os/users.c +++ b/src/nvim/os/users.c @@ -15,7 +15,7 @@ #include "nvim/os/os.h" #include "nvim/types.h" #include "nvim/vim.h" -#ifdef HAVE_PWD_H +#ifdef HAVE_PWD_FUNCS # include #endif #ifdef MSWIN @@ -50,7 +50,7 @@ int os_get_usernames(garray_T *users) } ga_init(users, sizeof(char *), 20); -#if defined(HAVE_GETPWENT) && defined(HAVE_PWD_H) +#ifdef HAVE_PWD_FUNCS { struct passwd *pw; @@ -81,7 +81,7 @@ int os_get_usernames(garray_T *users) } } #endif -#if defined(HAVE_GETPWNAM) +#ifdef HAVE_PWD_FUNCS { const char *user_env = os_getenv("USER"); @@ -141,7 +141,7 @@ int os_get_username(char *s, size_t len) /// @return OK if a username was found, else FAIL. int os_get_uname(uv_uid_t uid, char *s, size_t len) { -#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID) +#ifdef HAVE_PWD_FUNCS struct passwd *pw; if ((pw = getpwuid(uid)) != NULL // NOLINT(runtime/threadsafe_fn) @@ -159,7 +159,7 @@ int os_get_uname(uv_uid_t uid, char *s, size_t len) /// Caller must free() the returned string. char *os_get_userdir(const char *name) { -#if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H) +#ifdef HAVE_PWD_FUNCS if (name == NULL || *name == NUL) { return NULL; } -- cgit From 1b3c1f6c06d73e881bfc2a46e5ee3e0b24ba96d8 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 27 Feb 2023 19:37:43 +0100 Subject: refactor(build): graduate HAVE_LOCALE_H feature Merge locale.h into os/lang.h Having a source file with the same name as a system header we use is considered an anti-pattern. --- src/nvim/cmdexpand.c | 2 +- src/nvim/eval.c | 2 +- src/nvim/generators/gen_ex_cmds.lua | 2 +- src/nvim/locale.c | 377 ------------------------------------ src/nvim/locale.h | 10 - src/nvim/main.c | 4 +- src/nvim/mbyte.c | 10 +- src/nvim/option.c | 1 - src/nvim/os/lang.c | 343 +++++++++++++++++++++++++++++++- src/nvim/os/lang.h | 3 + 10 files changed, 346 insertions(+), 408 deletions(-) delete mode 100644 src/nvim/locale.c delete mode 100644 src/nvim/locale.h (limited to 'src') diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index fcd6a73b2d..18d35e1e20 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -40,7 +40,6 @@ #include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" #include "nvim/keycodes.h" -#include "nvim/locale.h" #include "nvim/log.h" #include "nvim/lua/executor.h" #include "nvim/macros.h" @@ -50,6 +49,7 @@ #include "nvim/menu.h" #include "nvim/message.h" #include "nvim/option.h" +#include "nvim/os/lang.h" #include "nvim/os/os.h" #include "nvim/path.h" #include "nvim/popupmenu.h" diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 0fbf31a8cd..da2a88346a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -45,7 +45,6 @@ #include "nvim/insexpand.h" #include "nvim/keycodes.h" #include "nvim/lib/queue.h" -#include "nvim/locale.h" #include "nvim/lua/executor.h" #include "nvim/macros.h" #include "nvim/main.h" @@ -62,6 +61,7 @@ #include "nvim/optionstr.h" #include "nvim/os/fileio.h" #include "nvim/os/fs_defs.h" +#include "nvim/os/lang.h" #include "nvim/os/os.h" #include "nvim/os/shell.h" #include "nvim/os/stdpaths_defs.h" diff --git a/src/nvim/generators/gen_ex_cmds.lua b/src/nvim/generators/gen_ex_cmds.lua index 0c1051b04e..935d7b333e 100644 --- a/src/nvim/generators/gen_ex_cmds.lua +++ b/src/nvim/generators/gen_ex_cmds.lua @@ -66,7 +66,6 @@ defsfile:write(string.format([[ #include "nvim/ex_session.h" #include "nvim/help.h" #include "nvim/indent.h" -#include "nvim/locale.h" #include "nvim/lua/executor.h" #include "nvim/mapping.h" #include "nvim/mark.h" @@ -75,6 +74,7 @@ defsfile:write(string.format([[ #include "nvim/message.h" #include "nvim/ops.h" #include "nvim/option.h" +#include "nvim/os/lang.h" #include "nvim/profile.h" #include "nvim/quickfix.h" #include "nvim/runtime.h" diff --git a/src/nvim/locale.c b/src/nvim/locale.c deleted file mode 100644 index c3cfd3bedb..0000000000 --- a/src/nvim/locale.c +++ /dev/null @@ -1,377 +0,0 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - -// locale.c: functions for language/locale configuration - -#include -#include - -#include "auto/config.h" -#ifdef HAVE_LOCALE_H -# include -#endif - -#include "nvim/ascii.h" -#include "nvim/buffer.h" -#include "nvim/charset.h" -#include "nvim/eval.h" -#include "nvim/ex_cmds_defs.h" -#include "nvim/garray.h" -#include "nvim/gettext.h" -#include "nvim/locale.h" -#include "nvim/macros.h" -#include "nvim/memory.h" -#include "nvim/message.h" -#include "nvim/option.h" -#include "nvim/os/os.h" -#include "nvim/os/shell.h" -#include "nvim/path.h" -#include "nvim/profile.h" -#include "nvim/types.h" -#include "nvim/vim.h" - -#ifdef INCLUDE_GENERATED_DECLARATIONS -# include "locale.c.generated.h" -#endif - -#if defined(HAVE_LOCALE_H) -# define HAVE_GET_LOCALE_VAL - -static char *get_locale_val(int what) -{ - // Obtain the locale value from the libraries. - char *loc = setlocale(what, NULL); - - return loc; -} -#endif - -/// @return true when "lang" starts with a valid language name. -/// Rejects NULL, empty string, "C", "C.UTF-8" and others. -static bool is_valid_mess_lang(const char *lang) -{ - return lang != NULL && ASCII_ISALPHA(lang[0]) && ASCII_ISALPHA(lang[1]); -} - -/// Obtain the current messages language. Used to set the default for -/// 'helplang'. May return NULL or an empty string. -char *get_mess_lang(void) -{ - char *p; - -#ifdef HAVE_GET_LOCALE_VAL -# if defined(LC_MESSAGES) - p = get_locale_val(LC_MESSAGES); -# else - // This is necessary for Win32, where LC_MESSAGES is not defined and $LANG - // may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME - // and LC_MONETARY may be set differently for a Japanese working in the - // US. - p = get_locale_val(LC_COLLATE); -# endif -#else - p = os_getenv("LC_ALL"); - if (!is_valid_mess_lang(p)) { - p = os_getenv("LC_MESSAGES"); - if (!is_valid_mess_lang(p)) { - p = os_getenv("LANG"); - } - } -#endif - return is_valid_mess_lang(p) ? p : NULL; -} - -// Complicated #if; matches with where get_mess_env() is used below. -#ifdef HAVE_WORKING_LIBINTL -/// Get the language used for messages from the environment. -static char *get_mess_env(void) -{ - char *p; - - p = (char *)os_getenv("LC_ALL"); - if (p == NULL) { - p = (char *)os_getenv("LC_MESSAGES"); - if (p == NULL) { - p = (char *)os_getenv("LANG"); - if (p != NULL && ascii_isdigit(*p)) { - p = NULL; // ignore something like "1043" - } -# ifdef HAVE_GET_LOCALE_VAL - if (p == NULL) { - p = get_locale_val(LC_CTYPE); - } -# endif - } - } - return p; -} -#endif - -/// Set the "v:lang" variable according to the current locale setting. -/// Also do "v:lc_time"and "v:ctype". -void set_lang_var(void) -{ - const char *loc; - -#ifdef HAVE_GET_LOCALE_VAL - loc = get_locale_val(LC_CTYPE); -#else - // setlocale() not supported: use the default value - loc = "C"; -#endif - set_vim_var_string(VV_CTYPE, loc, -1); - - // When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall - // back to LC_CTYPE if it's empty. -#ifdef HAVE_WORKING_LIBINTL - loc = get_mess_env(); -#elif defined(LC_MESSAGES) - loc = get_locale_val(LC_MESSAGES); -#else - // In Windows LC_MESSAGES is not defined fallback to LC_CTYPE - loc = get_locale_val(LC_CTYPE); -#endif - set_vim_var_string(VV_LANG, loc, -1); - -#ifdef HAVE_GET_LOCALE_VAL - loc = get_locale_val(LC_TIME); -#endif - set_vim_var_string(VV_LC_TIME, loc, -1); - -#ifdef HAVE_GET_LOCALE_VAL - loc = get_locale_val(LC_COLLATE); -#else - // setlocale() not supported: use the default value - loc = "C"; -#endif - set_vim_var_string(VV_COLLATE, loc, -1); -} - -#if defined(HAVE_LOCALE_H) -/// Setup to use the current locale (for ctype() and many other things). -void init_locale(void) -{ - setlocale(LC_ALL, ""); - -# ifdef LC_NUMERIC - // Make sure strtod() uses a decimal point, not a comma. - setlocale(LC_NUMERIC, "C"); -# endif - - char localepath[MAXPATHL] = { 0 }; - snprintf(localepath, sizeof(localepath), "%s", get_vim_var_str(VV_PROGPATH)); - char *tail = path_tail_with_sep(localepath); - *tail = NUL; - tail = path_tail(localepath); - xstrlcpy(tail, "share/locale", - sizeof(localepath) - (size_t)(tail - localepath)); - bindtextdomain(PROJECT_NAME, localepath); - textdomain(PROJECT_NAME); - TIME_MSG("locale set"); -} -#endif - -#ifdef HAVE_WORKING_LIBINTL - -/// ":language": Set the language (locale). -/// -/// @param eap -void ex_language(exarg_T *eap) -{ - char *loc; - char *p; - char *name; - int what = LC_ALL; - char *whatstr = ""; -# ifdef LC_MESSAGES -# define VIM_LC_MESSAGES LC_MESSAGES -# else -# define VIM_LC_MESSAGES 6789 -# endif - - name = eap->arg; - - // Check for "messages {name}", "ctype {name}" or "time {name}" argument. - // Allow abbreviation, but require at least 3 characters to avoid - // confusion with a two letter language name "me" or "ct". - p = skiptowhite(eap->arg); - if ((*p == NUL || ascii_iswhite(*p)) && p - eap->arg >= 3) { - if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0) { - what = VIM_LC_MESSAGES; - name = skipwhite(p); - whatstr = "messages "; - } else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0) { - what = LC_CTYPE; - name = skipwhite(p); - whatstr = "ctype "; - } else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0) { - what = LC_TIME; - name = skipwhite(p); - whatstr = "time "; - } else if (STRNICMP(eap->arg, "collate", p - eap->arg) == 0) { - what = LC_COLLATE; - name = skipwhite(p); - whatstr = "collate "; - } - } - - if (*name == NUL) { - if (what == VIM_LC_MESSAGES) { - p = get_mess_env(); - } else { - p = setlocale(what, NULL); - } - if (p == NULL || *p == NUL) { - p = "Unknown"; - } - smsg(_("Current %slanguage: \"%s\""), whatstr, p); - } else { -# ifndef LC_MESSAGES - if (what == VIM_LC_MESSAGES) { - loc = ""; - } else { -# endif - loc = setlocale(what, name); -# ifdef LC_NUMERIC - // Make sure strtod() uses a decimal point, not a comma. - setlocale(LC_NUMERIC, "C"); -# endif -# ifndef LC_MESSAGES - } -# endif - if (loc == NULL) { - semsg(_("E197: Cannot set language to \"%s\""), name); - } else { -# ifdef HAVE_NL_MSG_CAT_CNTR - // Need to do this for GNU gettext, otherwise cached translations - // will be used again. - extern int _nl_msg_cat_cntr; - - _nl_msg_cat_cntr++; -# endif - // Reset $LC_ALL, otherwise it would overrule everything. - os_setenv("LC_ALL", "", 1); - - if (what != LC_TIME && what != LC_COLLATE) { - // Tell gettext() what to translate to. It apparently doesn't - // use the currently effective locale. - if (what == LC_ALL) { - os_setenv("LANG", name, 1); - - // Clear $LANGUAGE because GNU gettext uses it. - os_setenv("LANGUAGE", "", 1); - } - if (what != LC_CTYPE) { - os_setenv("LC_MESSAGES", name, 1); - set_helplang_default(name); - } - } - - // Set v:lang, v:lc_time, v:collate and v:ctype to the final result. - set_lang_var(); - maketitle(); - } - } -} - -static char **locales = NULL; // Array of all available locales - -# ifndef MSWIN -static bool did_init_locales = false; - -/// @return an array of strings for all available locales + NULL for the -/// last element or, -/// NULL in case of error. -static char **find_locales(void) -{ - garray_T locales_ga; - char *loc; - char *saveptr = NULL; - - // Find all available locales by running command "locale -a". If this - // doesn't work we won't have completion. - char *locale_a = get_cmd_output("locale -a", NULL, kShellOptSilent, NULL); - if (locale_a == NULL) { - return NULL; - } - ga_init(&locales_ga, sizeof(char *), 20); - - // Transform locale_a string where each locale is separated by "\n" - // into an array of locale strings. - loc = os_strtok(locale_a, "\n", &saveptr); - - while (loc != NULL) { - loc = xstrdup(loc); - GA_APPEND(char *, &locales_ga, loc); - loc = os_strtok(NULL, "\n", &saveptr); - } - xfree(locale_a); - // Guarantee that .ga_data is NULL terminated - ga_grow(&locales_ga, 1); - ((char **)locales_ga.ga_data)[locales_ga.ga_len] = NULL; - return locales_ga.ga_data; -} -# endif - -/// Lazy initialization of all available locales. -static void init_locales(void) -{ -# ifndef MSWIN - if (did_init_locales) { - return; - } - - did_init_locales = true; - locales = find_locales(); -# endif -} - -# if defined(EXITFREE) -void free_locales(void) -{ - if (locales == NULL) { - return; - } - - for (int i = 0; locales[i] != NULL; i++) { - xfree(locales[i]); - } - XFREE_CLEAR(locales); -} -# endif - -/// Function given to ExpandGeneric() to obtain the possible arguments of the -/// ":language" command. -char *get_lang_arg(expand_T *xp, int idx) -{ - if (idx == 0) { - return "messages"; - } - if (idx == 1) { - return "ctype"; - } - if (idx == 2) { - return "time"; - } - if (idx == 3) { - return "collate"; - } - - init_locales(); - if (locales == NULL) { - return NULL; - } - return locales[idx - 4]; -} - -/// Function given to ExpandGeneric() to obtain the available locales. -char *get_locales(expand_T *xp, int idx) -{ - init_locales(); - if (locales == NULL) { - return NULL; - } - return locales[idx]; -} - -#endif diff --git a/src/nvim/locale.h b/src/nvim/locale.h deleted file mode 100644 index 39735d371f..0000000000 --- a/src/nvim/locale.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef NVIM_LOCALE_H -#define NVIM_LOCALE_H - -#include "nvim/ex_cmds_defs.h" -#include "nvim/types.h" - -#ifdef INCLUDE_GENERATED_DECLARATIONS -# include "locale.h.generated.h" -#endif -#endif // NVIM_LOCALE_H diff --git a/src/nvim/main.c b/src/nvim/main.c index 975772169b..71c5c2af46 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -41,7 +41,6 @@ #include "nvim/highlight.h" #include "nvim/highlight_group.h" #include "nvim/keycodes.h" -#include "nvim/locale.h" #include "nvim/log.h" #include "nvim/lua/executor.h" #include "nvim/macros.h" @@ -60,6 +59,7 @@ #include "nvim/optionstr.h" #include "nvim/os/fileio.h" #include "nvim/os/input.h" +#include "nvim/os/lang.h" #include "nvim/os/os.h" #include "nvim/os/stdpaths_defs.h" #include "nvim/os/time.h" @@ -192,12 +192,10 @@ void early_init(mparm_T *paramp) TIME_MSG("early init"); -#if defined(HAVE_LOCALE_H) // Setup to use the current locale (for ctype() and many other things). // NOTE: Translated messages with encodings other than latin1 will not // work until set_init_1() has been called! init_locale(); -#endif // tabpage local options (p_ch) must be set before allocating first tabpage. set_init_tablocal(); diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index e27bb003e7..d8be4f4997 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -67,10 +68,6 @@ #include "nvim/types.h" #include "nvim/vim.h" -#ifdef HAVE_LOCALE_H -# include -#endif - typedef struct { int rangeStart; int rangeEnd; @@ -2193,10 +2190,7 @@ char *enc_locale(void) if (!(s = nl_langinfo(CODESET)) || *s == NUL) #endif { -#if defined(HAVE_LOCALE_H) - if (!(s = setlocale(LC_CTYPE, NULL)) || *s == NUL) -#endif - { + if (!(s = setlocale(LC_CTYPE, NULL)) || *s == NUL) { if ((s = os_getenv("LC_ALL"))) { if ((s = os_getenv("LC_CTYPE"))) { s = os_getenv("LANG"); diff --git a/src/nvim/option.c b/src/nvim/option.c index 0303f0bccd..6ddc3b5cfb 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -62,7 +62,6 @@ #include "nvim/indent_c.h" #include "nvim/insexpand.h" #include "nvim/keycodes.h" -#include "nvim/locale.h" #include "nvim/log.h" #include "nvim/lua/executor.h" #include "nvim/macros.h" diff --git a/src/nvim/os/lang.c b/src/nvim/os/lang.c index 57c82bba86..8ca2aa3a4b 100644 --- a/src/nvim/os/lang.c +++ b/src/nvim/os/lang.c @@ -7,16 +7,347 @@ # include # undef Boolean # undef FileInfo +#endif -# include "auto/config.h" -# ifdef HAVE_LOCALE_H -# include -# endif -# include "nvim/os/os.h" +#include +#include +#include + +#include "auto/config.h" +#include "nvim/ascii.h" +#include "nvim/buffer.h" +#include "nvim/charset.h" +#include "nvim/eval.h" +#include "nvim/ex_cmds_defs.h" +#include "nvim/garray.h" +#include "nvim/gettext.h" +#include "nvim/macros.h" +#include "nvim/memory.h" +#include "nvim/message.h" +#include "nvim/option.h" +#include "nvim/os/lang.h" +#include "nvim/os/os.h" +#include "nvim/os/shell.h" +#include "nvim/path.h" +#include "nvim/profile.h" +#include "nvim/types.h" +#include "nvim/vim.h" +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "os/lang.c.generated.h" #endif -#include "nvim/os/lang.h" +static char *get_locale_val(int what) +{ + // Obtain the locale value from the libraries. + char *loc = setlocale(what, NULL); + + return loc; +} + +/// @return true when "lang" starts with a valid language name. +/// Rejects NULL, empty string, "C", "C.UTF-8" and others. +static bool is_valid_mess_lang(const char *lang) +{ + return lang != NULL && ASCII_ISALPHA(lang[0]) && ASCII_ISALPHA(lang[1]); +} + +/// Obtain the current messages language. Used to set the default for +/// 'helplang'. May return NULL or an empty string. +char *get_mess_lang(void) +{ + char *p; + +#if defined(LC_MESSAGES) + p = get_locale_val(LC_MESSAGES); +#else + // This is necessary for Win32, where LC_MESSAGES is not defined and $LANG + // may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME + // and LC_MONETARY may be set differently for a Japanese working in the + // US. + p = get_locale_val(LC_COLLATE); +#endif + return is_valid_mess_lang(p) ? p : NULL; +} + +// Complicated #if; matches with where get_mess_env() is used below. +#ifdef HAVE_WORKING_LIBINTL +/// Get the language used for messages from the environment. +static char *get_mess_env(void) +{ + char *p; + + p = (char *)os_getenv("LC_ALL"); + if (p == NULL) { + p = (char *)os_getenv("LC_MESSAGES"); + if (p == NULL) { + p = (char *)os_getenv("LANG"); + if (p != NULL && ascii_isdigit(*p)) { + p = NULL; // ignore something like "1043" + } + if (p == NULL) { + p = get_locale_val(LC_CTYPE); + } + } + } + return p; +} +#endif + +/// Set the "v:lang" variable according to the current locale setting. +/// Also do "v:lc_time"and "v:ctype". +void set_lang_var(void) +{ + const char *loc; + + loc = get_locale_val(LC_CTYPE); + set_vim_var_string(VV_CTYPE, loc, -1); + + // When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall + // back to LC_CTYPE if it's empty. +#ifdef HAVE_WORKING_LIBINTL + loc = get_mess_env(); +#elif defined(LC_MESSAGES) + loc = get_locale_val(LC_MESSAGES); +#else + // In Windows LC_MESSAGES is not defined fallback to LC_CTYPE + loc = get_locale_val(LC_CTYPE); +#endif + set_vim_var_string(VV_LANG, loc, -1); + + loc = get_locale_val(LC_TIME); + set_vim_var_string(VV_LC_TIME, loc, -1); + + loc = get_locale_val(LC_COLLATE); + set_vim_var_string(VV_COLLATE, loc, -1); +} + +/// Setup to use the current locale (for ctype() and many other things). +void init_locale(void) +{ + setlocale(LC_ALL, ""); + +#ifdef LC_NUMERIC + // Make sure strtod() uses a decimal point, not a comma. + setlocale(LC_NUMERIC, "C"); +#endif + + char localepath[MAXPATHL] = { 0 }; + snprintf(localepath, sizeof(localepath), "%s", get_vim_var_str(VV_PROGPATH)); + char *tail = path_tail_with_sep(localepath); + *tail = NUL; + tail = path_tail(localepath); + xstrlcpy(tail, "share/locale", + sizeof(localepath) - (size_t)(tail - localepath)); + bindtextdomain(PROJECT_NAME, localepath); + textdomain(PROJECT_NAME); + TIME_MSG("locale set"); +} + +#ifdef HAVE_WORKING_LIBINTL + +/// ":language": Set the language (locale). +/// +/// @param eap +void ex_language(exarg_T *eap) +{ + char *loc; + char *p; + char *name; + int what = LC_ALL; + char *whatstr = ""; +# ifdef LC_MESSAGES +# define VIM_LC_MESSAGES LC_MESSAGES +# else +# define VIM_LC_MESSAGES 6789 +# endif + + name = eap->arg; + + // Check for "messages {name}", "ctype {name}" or "time {name}" argument. + // Allow abbreviation, but require at least 3 characters to avoid + // confusion with a two letter language name "me" or "ct". + p = skiptowhite(eap->arg); + if ((*p == NUL || ascii_iswhite(*p)) && p - eap->arg >= 3) { + if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0) { + what = VIM_LC_MESSAGES; + name = skipwhite(p); + whatstr = "messages "; + } else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0) { + what = LC_CTYPE; + name = skipwhite(p); + whatstr = "ctype "; + } else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0) { + what = LC_TIME; + name = skipwhite(p); + whatstr = "time "; + } else if (STRNICMP(eap->arg, "collate", p - eap->arg) == 0) { + what = LC_COLLATE; + name = skipwhite(p); + whatstr = "collate "; + } + } + + if (*name == NUL) { + if (what == VIM_LC_MESSAGES) { + p = get_mess_env(); + } else { + p = setlocale(what, NULL); + } + if (p == NULL || *p == NUL) { + p = "Unknown"; + } + smsg(_("Current %slanguage: \"%s\""), whatstr, p); + } else { +# ifndef LC_MESSAGES + if (what == VIM_LC_MESSAGES) { + loc = ""; + } else { +# endif + loc = setlocale(what, name); +# ifdef LC_NUMERIC + // Make sure strtod() uses a decimal point, not a comma. + setlocale(LC_NUMERIC, "C"); +# endif +# ifndef LC_MESSAGES + } +# endif + if (loc == NULL) { + semsg(_("E197: Cannot set language to \"%s\""), name); + } else { +# ifdef HAVE_NL_MSG_CAT_CNTR + // Need to do this for GNU gettext, otherwise cached translations + // will be used again. + extern int _nl_msg_cat_cntr; + + _nl_msg_cat_cntr++; +# endif + // Reset $LC_ALL, otherwise it would overrule everything. + os_setenv("LC_ALL", "", 1); + + if (what != LC_TIME && what != LC_COLLATE) { + // Tell gettext() what to translate to. It apparently doesn't + // use the currently effective locale. + if (what == LC_ALL) { + os_setenv("LANG", name, 1); + + // Clear $LANGUAGE because GNU gettext uses it. + os_setenv("LANGUAGE", "", 1); + } + if (what != LC_CTYPE) { + os_setenv("LC_MESSAGES", name, 1); + set_helplang_default(name); + } + } + + // Set v:lang, v:lc_time, v:collate and v:ctype to the final result. + set_lang_var(); + maketitle(); + } + } +} + +static char **locales = NULL; // Array of all available locales + +# ifndef MSWIN +static bool did_init_locales = false; + +/// @return an array of strings for all available locales + NULL for the +/// last element or, +/// NULL in case of error. +static char **find_locales(void) +{ + garray_T locales_ga; + char *loc; + char *saveptr = NULL; + + // Find all available locales by running command "locale -a". If this + // doesn't work we won't have completion. + char *locale_a = get_cmd_output("locale -a", NULL, kShellOptSilent, NULL); + if (locale_a == NULL) { + return NULL; + } + ga_init(&locales_ga, sizeof(char *), 20); + + // Transform locale_a string where each locale is separated by "\n" + // into an array of locale strings. + loc = os_strtok(locale_a, "\n", &saveptr); + + while (loc != NULL) { + loc = xstrdup(loc); + GA_APPEND(char *, &locales_ga, loc); + loc = os_strtok(NULL, "\n", &saveptr); + } + xfree(locale_a); + // Guarantee that .ga_data is NULL terminated + ga_grow(&locales_ga, 1); + ((char **)locales_ga.ga_data)[locales_ga.ga_len] = NULL; + return locales_ga.ga_data; +} +# endif + +/// Lazy initialization of all available locales. +static void init_locales(void) +{ +# ifndef MSWIN + if (did_init_locales) { + return; + } + + did_init_locales = true; + locales = find_locales(); +# endif +} + +# if defined(EXITFREE) +void free_locales(void) +{ + if (locales == NULL) { + return; + } + + for (int i = 0; locales[i] != NULL; i++) { + xfree(locales[i]); + } + XFREE_CLEAR(locales); +} +# endif + +/// Function given to ExpandGeneric() to obtain the possible arguments of the +/// ":language" command. +char *get_lang_arg(expand_T *xp, int idx) +{ + if (idx == 0) { + return "messages"; + } + if (idx == 1) { + return "ctype"; + } + if (idx == 2) { + return "time"; + } + if (idx == 3) { + return "collate"; + } + + init_locales(); + if (locales == NULL) { + return NULL; + } + return locales[idx - 4]; +} + +/// Function given to ExpandGeneric() to obtain the available locales. +char *get_locales(expand_T *xp, int idx) +{ + init_locales(); + if (locales == NULL) { + return NULL; + } + return locales[idx]; +} + +#endif void lang_init(void) { diff --git a/src/nvim/os/lang.h b/src/nvim/os/lang.h index f60e064f57..bb1ebfb721 100644 --- a/src/nvim/os/lang.h +++ b/src/nvim/os/lang.h @@ -1,6 +1,9 @@ #ifndef NVIM_OS_LANG_H #define NVIM_OS_LANG_H +#include "nvim/ex_cmds_defs.h" +#include "nvim/types.h" + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/lang.h.generated.h" #endif -- cgit From c002fd421e3d8deb4adf144cadcd3a6fe4635e12 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 27 Feb 2023 19:41:40 +0100 Subject: refactor(build): graduate libtreesitter features which are 1+ years old --- src/nvim/lua/treesitter.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src') diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index d72e7a1825..2db12b8ded 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -152,9 +152,7 @@ void tslua_init(lua_State *L) build_meta(L, TS_META_QUERYCURSOR, querycursor_meta); build_meta(L, TS_META_TREECURSOR, treecursor_meta); -#ifdef NVIM_TS_HAS_SET_ALLOCATOR ts_set_allocator(xmalloc, xcalloc, xrealloc, xfree); -#endif } int tslua_has_language(lua_State *L) @@ -1321,11 +1319,7 @@ static int node_rawquery(lua_State *L) } else { cursor = ts_query_cursor_new(); } - // TODO(clason): API introduced after tree-sitter release 0.19.5 - // remove guard when minimum ts version is bumped to 0.19.6+ -#ifdef NVIM_TS_HAS_SET_MATCH_LIMIT ts_query_cursor_set_match_limit(cursor, 64); -#endif ts_query_cursor_exec(cursor, query, node); bool captures = lua_toboolean(L, 3); -- cgit From c9b6db45417ecbd178f0c6106f4033c760cc75df Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 27 Feb 2023 19:46:39 +0100 Subject: refactor(build): graduate msgpack-c FLOAT32 "feature" since forever --- src/nvim/eval/decode.c | 4 ---- src/nvim/msgpack_rpc/helpers.c | 8 -------- 2 files changed, 12 deletions(-) (limited to 'src') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index cd1479f150..f57d06c83b 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -987,12 +987,8 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF)); } break; -#ifdef NVIM_MSGPACK_HAS_FLOAT32 case MSGPACK_OBJECT_FLOAT32: case MSGPACK_OBJECT_FLOAT64: -#else - case MSGPACK_OBJECT_FLOAT: -#endif *rettv = (typval_T) { .v_type = VAR_FLOAT, .v_lock = VAR_UNLOCKED, diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 5f0f03dd69..d1fd28f882 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -84,12 +84,8 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) *cur.aobj = INTEGER_OBJ((Integer)cur.mobj->via.u64); } break; -#ifdef NVIM_MSGPACK_HAS_FLOAT32 case MSGPACK_OBJECT_FLOAT32: case MSGPACK_OBJECT_FLOAT64: -#else - case MSGPACK_OBJECT_FLOAT: -#endif { STATIC_ASSERT(sizeof(Float) == sizeof(cur.mobj->via.f64), "Msgpack floating-point size does not match API integer"); @@ -156,12 +152,8 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg) case MSGPACK_OBJECT_BOOLEAN: case MSGPACK_OBJECT_POSITIVE_INTEGER: case MSGPACK_OBJECT_NEGATIVE_INTEGER: -#ifdef NVIM_MSGPACK_HAS_FLOAT32 case MSGPACK_OBJECT_FLOAT32: case MSGPACK_OBJECT_FLOAT64: -#else - case MSGPACK_OBJECT_FLOAT: -#endif case MSGPACK_OBJECT_EXT: case MSGPACK_OBJECT_MAP: case MSGPACK_OBJECT_ARRAY: -- cgit From 848dac0aaa68a6ecbb7fe346a90bb5e5f5d7f09f Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 27 Feb 2023 19:51:25 +0100 Subject: refactor(build): graduate unibilium VAR_FROM feature from 2017 --- src/nvim/tui/tui.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 48dc860ebd..df7c87ad60 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -60,27 +60,14 @@ #define LINUXSET0C "\x1b[?0c" #define LINUXSET1C "\x1b[?1c" -#ifdef NVIM_UNIBI_HAS_VAR_FROM -# define UNIBI_SET_NUM_VAR(var, num) \ +#define UNIBI_SET_NUM_VAR(var, num) \ do { \ (var) = unibi_var_from_num((num)); \ } while (0) -# define UNIBI_SET_STR_VAR(var, str) \ +#define UNIBI_SET_STR_VAR(var, str) \ do { \ (var) = unibi_var_from_str((str)); \ } while (0) -#else -# define UNIBI_SET_NUM_VAR(var, num) \ - do { \ - (var).p = NULL; \ - (var).i = (num); \ - } while (0) -# define UNIBI_SET_STR_VAR(var, str) \ - do { \ - (var).i = INT_MIN; \ - (var).p = str; \ - } while (0) -#endif typedef struct { int top, bot, left, right; -- cgit From 2cffd048334912f72e0f55b2a02bd1fd9107613a Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 27 Feb 2023 20:14:10 +0100 Subject: refactor(build): graduate -Wvla, -fno-common and -Og "features" These are in gcc 4.9+ which we require anyway. -Og is safe on clang as well (reserved for a future debug-optimize mode, and currently does the same as -O1 which is reasonable) --- src/nvim/CMakeLists.txt | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 504dde5a9c..10f44c428c 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -87,14 +87,14 @@ if(MSVC) target_sources(main_lib INTERFACE ${CMAKE_CURRENT_LIST_DIR}/os/nvim.manifest) else() target_compile_options(main_lib INTERFACE -Wall -Wextra -pedantic -Wno-unused-parameter - -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion + -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion -Wvla -Wdouble-promotion -Wmissing-noreturn -Wmissing-format-attribute -Wmissing-prototypes) if(CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_compile_options(main_lib INTERFACE + target_compile_options(main_lib INTERFACE -fno-common $<$:-Wno-unused-result> $<$:-Wno-unused-result> $<$:-Wno-unused-result>) @@ -144,17 +144,6 @@ if(WIN32) target_compile_definitions(main_lib INTERFACE _WIN32_WINNT=0x0602 MSWIN) endif() -# OpenBSD's GCC (4.2.1) doesn't have -Wvla -check_c_compiler_flag(-Wvla HAS_WVLA_FLAG) -if(HAS_WVLA_FLAG) - target_compile_options(main_lib INTERFACE -Wvla) -endif() - -check_c_compiler_flag(-fno-common HAVE_FNO_COMMON) -if (HAVE_FNO_COMMON) - target_compile_options(main_lib INTERFACE -fno-common) -endif() - check_c_compiler_flag(-fdiagnostics-color=auto HAS_DIAG_COLOR_FLAG) if(HAS_DIAG_COLOR_FLAG) if(CMAKE_GENERATOR MATCHES "Ninja") -- cgit From a88c18c24efe2b0d91882a48c4dedae9b8269806 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 3 Mar 2023 22:24:12 +0800 Subject: vim-patch:9.0.0527: long sign text may overflow buffer (#22496) Problem: Long sign text may overflow buffer. Solution: Use a larger buffer. Prevent for overflow. https://github.com/vim/vim/commit/2b1ddf19f8f14365d0b998b4ac12ca85c0923475 Don't change the size of extra[] as it's already large enough. N/A patches for version.c: vim-patch:9.0.0523: more compiler warnings for arguments in small version Co-authored-by: Bram Moolenaar --- src/nvim/drawline.c | 8 ++++---- src/nvim/testdir/test_signs.vim | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index dbbeabbba2..a2ae828f7e 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -413,13 +413,13 @@ static void get_sign_display_info(bool nrcol, win_T *wp, winlinevars_T *wlv, int wlv->c_final = NUL; if (nrcol) { - int n, width = number_width(wp) - 2; - for (n = 0; n < width; n++) { + int width = number_width(wp) - 2; + size_t n; + for (n = 0; (int)n < width; n++) { wlv->extra[n] = ' '; } wlv->extra[n] = NUL; - STRCAT(wlv->extra, wlv->p_extra); - STRCAT(wlv->extra, " "); + snprintf(wlv->extra + n, sizeof(wlv->extra) - n, "%s ", wlv->p_extra); wlv->p_extra = wlv->extra; wlv->n_extra = (int)strlen(wlv->p_extra); } else { diff --git a/src/nvim/testdir/test_signs.vim b/src/nvim/testdir/test_signs.vim index 8311955a15..129f1c1a0c 100644 --- a/src/nvim/testdir/test_signs.vim +++ b/src/nvim/testdir/test_signs.vim @@ -196,6 +196,20 @@ func Test_sign() \ bufnr('%'), 'E155:') endfunc +func Test_sign_many_bytes() + new + set signcolumn=number + set number + call setline(1, 'some text') + " composing characters can use many bytes, check for overflow + sign define manyBytes text=▶᷄᷅᷆◀᷄᷅᷆᷇ + sign place 17 line=1 name=manyBytes + redraw + + bwipe! + sign undefine manyBytes +endfunc + " Undefining placed sign is not recommended. " Quoting :help sign " -- cgit From 7e90f247e7b3add74a49895054a543c2140bbb08 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 3 Mar 2023 16:16:17 +0100 Subject: fix(treesitter): raise ts_match_limit to 256 (#22497) Problem: Some complex queries may not return all matches. Solution: Raise `ts_match_limit` from current 64 (twice the original default) to 256 (which Helix uses, and seems to be enough for the reported problematic cases). If this leads performance regressions in other queries, we should add a generic querying timeout instead of relying on a low value here. --- src/nvim/lua/treesitter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c index 2db12b8ded..4cbe7329a6 100644 --- a/src/nvim/lua/treesitter.c +++ b/src/nvim/lua/treesitter.c @@ -1319,7 +1319,7 @@ static int node_rawquery(lua_State *L) } else { cursor = ts_query_cursor_new(); } - ts_query_cursor_set_match_limit(cursor, 64); + ts_query_cursor_set_match_limit(cursor, 256); ts_query_cursor_exec(cursor, query, node); bool captures = lua_toboolean(L, 3); -- cgit From 446c353a507834a3cbe9007b06e7e0c2c46b5ac7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 4 Mar 2023 08:39:54 +0800 Subject: vim-patch:9.0.1376: accessing invalid memory with put in Visual block mode (#22505) Problem: Accessing invalid memory with put in Visual block mode. Solution: Adjust the cursor column if needed. https://github.com/vim/vim/commit/1c73b65229c25e3c1fd8824ba958f7cc4d604f9c Co-authored-by: Bram Moolenaar --- src/nvim/ops.c | 11 ++++++++++- src/nvim/testdir/test_put.vim | 11 +++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/ops.c b/src/nvim/ops.c index e89844098b..d2a96be5ad 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -3346,7 +3346,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) ptr += yanklen; // insert block's trailing spaces only if there's text behind - if ((j < count - 1 || !shortline) && spaces) { + if ((j < count - 1 || !shortline) && spaces > 0) { memset(ptr, ' ', (size_t)spaces); ptr += spaces; } else { @@ -3685,6 +3685,15 @@ error: msgmore(nr_lines); curwin->w_set_curswant = true; + // Make sure the cursor is not after the NUL. + int len = (int)strlen(get_cursor_line_ptr()); + if (curwin->w_cursor.col > len) { + if (cur_ve_flags == VE_ALL) { + curwin->w_cursor.coladd = curwin->w_cursor.col - len; + } + curwin->w_cursor.col = len; + } + end: if (cmdmod.cmod_flags & CMOD_LOCKMARKS) { curbuf->b_op_start = orig_start; diff --git a/src/nvim/testdir/test_put.vim b/src/nvim/testdir/test_put.vim index 97af3699a8..25fc5a2f04 100644 --- a/src/nvim/testdir/test_put.vim +++ b/src/nvim/testdir/test_put.vim @@ -235,5 +235,16 @@ func Test_put_visual_mode() set selection& endfunc +func Test_put_visual_block_mode() + enew + exe "norm 0R\\V" + sil exe "norm \c \" + set ve=all + sil norm vz=p + + bwipe! + set ve= +endfunc + " vim: shiftwidth=2 sts=2 expandtab -- cgit From 0a897f89c52b92cb518dae1c92de22ca1d170d2a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 4 Mar 2023 10:25:18 +0800 Subject: vim-patch:partial:9.0.0013: reproducing memory access errors can be difficult Problem: Reproducing memory access errors can be difficult. Solution: When testing, copy each line to allocated memory, so that valgrind can detect accessing memory before and/or after it. Fix uncovered problems. https://github.com/vim/vim/commit/fa4873ccfc10e0f278dc46f39d00136fab059b19 Since test_override() is N/A, enable ml_get_alloc_lines when ASAN is enabled instead, so it also applies to functional tests. Use xstrdup() to copy the line as ml_line_len looks hard to port. Squash the test changes from patch 9.0.0016. Co-authored-by: Bram Moolenaar --- src/nvim/change.c | 6 ++++- src/nvim/edit.c | 2 +- src/nvim/indent_c.c | 21 ++++++++------- src/nvim/memline.c | 48 ++++++++++++++++++++++++++--------- src/nvim/memline_defs.h | 9 ++++--- src/nvim/testdir/test_breakindent.vim | 10 ++++---- src/nvim/testdir/test_edit.vim | 3 +++ 7 files changed, 67 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/nvim/change.c b/src/nvim/change.c index 1bd7ea3a5a..7c8f62015d 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -1162,12 +1162,16 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment) if (p[0] == '/' && p[-1] == '*') { // End of C comment, indent should line up // with the line containing the start of - // the comment + // the comment. curwin->w_cursor.col = (colnr_T)(p - ptr); if ((pos = findmatch(NULL, NUL)) != NULL) { curwin->w_cursor.lnum = pos->lnum; newindent = get_indent(); + break; } + // this may make "ptr" invalid, get it again + ptr = ml_get(curwin->w_cursor.lnum); + p = ptr + curwin->w_cursor.col; } } } diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 7522cc202e..2849268da2 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -4653,9 +4653,9 @@ int ins_copychar(linenr_T lnum) } // try to advance to the cursor column + validate_virtcol(); line = ml_get(lnum); prev_ptr = line; - validate_virtcol(); chartabsize_T cts; init_chartabsize_arg(&cts, curwin, lnum, 0, line, line); diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c index 1c771073b2..3e7f640326 100644 --- a/src/nvim/indent_c.c +++ b/src/nvim/indent_c.c @@ -2529,8 +2529,6 @@ int get_c_indent(void) break; } - l = get_cursor_line_ptr(); - // If we're in a comment or raw string now, skip to // the start of it. trypos = ind_find_start_CORS(NULL); @@ -2540,9 +2538,9 @@ int get_c_indent(void) continue; } - // + l = get_cursor_line_ptr(); + // Skip preprocessor directives and blank lines. - // if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)) { continue; } @@ -2640,8 +2638,6 @@ int get_c_indent(void) break; } - l = get_cursor_line_ptr(); - // If we're in a comment or raw string now, skip // to the start of it. trypos = ind_find_start_CORS(NULL); @@ -2651,6 +2647,8 @@ int get_c_indent(void) continue; } + l = get_cursor_line_ptr(); + // Skip preprocessor directives and blank lines. if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)) { continue; @@ -2916,11 +2914,15 @@ int get_c_indent(void) trypos = NULL; } + l = get_cursor_line_ptr(); + // If we are looking for ',', we also look for matching // braces. - if (trypos == NULL && terminated == ',' - && find_last_paren(l, '{', '}')) { - trypos = find_start_brace(); + if (trypos == NULL && terminated == ',') { + if (find_last_paren(l, '{', '}')) { + trypos = find_start_brace(); + } + l = get_cursor_line_ptr(); } if (trypos != NULL) { @@ -2951,6 +2953,7 @@ int get_c_indent(void) curwin->w_cursor.lnum--; curwin->w_cursor.col = 0; } + l = get_cursor_line_ptr(); } // Get indent and pointer to text for current line, diff --git a/src/nvim/memline.c b/src/nvim/memline.c index ff0a6d7627..e9988eb844 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -244,6 +244,10 @@ typedef enum { # include "memline.c.generated.h" #endif +#if __has_feature(address_sanitizer) +# define ML_GET_ALLOC_LINES +#endif + /// Open a new memline for "buf". /// /// @return FAIL for failure, OK otherwise. @@ -535,7 +539,8 @@ void ml_close(buf_T *buf, int del_file) return; } mf_close(buf->b_ml.ml_mfp, del_file); // close the .swp file - if (buf->b_ml.ml_line_lnum != 0 && (buf->b_ml.ml_flags & ML_LINE_DIRTY)) { + if (buf->b_ml.ml_line_lnum != 0 + && (buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED))) { xfree(buf->b_ml.ml_line_ptr); } xfree(buf->b_ml.ml_stack); @@ -1780,7 +1785,6 @@ char *ml_get_buf(buf_T *buf, linenr_T lnum, bool will_change) recursive--; } ml_flush_line(buf); - buf->b_ml.ml_flags &= ~ML_LINE_DIRTY; errorret: STRCPY(questions, "???"); buf->b_ml.ml_line_lnum = lnum; @@ -1824,18 +1828,36 @@ errorret: char *ptr = (char *)dp + (dp->db_index[lnum - buf->b_ml.ml_locked_low] & DB_INDEX_MASK); buf->b_ml.ml_line_ptr = ptr; buf->b_ml.ml_line_lnum = lnum; - buf->b_ml.ml_flags &= ~ML_LINE_DIRTY; + buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED); } if (will_change) { buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS); +#ifdef ML_GET_ALLOC_LINES + if (buf->b_ml.ml_flags & ML_ALLOCATED) { + // can't make the change in the data block + buf->b_ml.ml_flags |= ML_LINE_DIRTY; + } +#endif ml_add_deleted_len_buf(buf, buf->b_ml.ml_line_ptr, -1); } +#ifdef ML_GET_ALLOC_LINES + if ((buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) == 0) { + // make sure the text is in allocated memory + buf->b_ml.ml_line_ptr = xstrdup(buf->b_ml.ml_line_ptr); + buf->b_ml.ml_flags |= ML_ALLOCATED; + if (will_change) { + // can't make the change in the data block + buf->b_ml.ml_flags |= ML_LINE_DIRTY; + } + } +#endif return buf->b_ml.ml_line_ptr; } /// Check if a line that was just obtained by a call to ml_get /// is in allocated memory. +/// This ignores ML_ALLOCATED to get the same behavior as without ML_GET_ALLOC_LINES. int ml_line_alloced(void) { return curbuf->b_ml.ml_flags & ML_LINE_DIRTY; @@ -2352,24 +2374,23 @@ int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy) return FAIL; } - bool readlen = true; - if (copy) { line = xstrdup(line); } - if (buf->b_ml.ml_line_lnum != lnum) { // other line buffered - ml_flush_line(buf); // flush it - } else if (buf->b_ml.ml_flags & ML_LINE_DIRTY) { // same line allocated - ml_add_deleted_len_buf(buf, buf->b_ml.ml_line_ptr, -1); - readlen = false; // already added the length - xfree(buf->b_ml.ml_line_ptr); // free it + if (buf->b_ml.ml_line_lnum != lnum) { + // another line is buffered, flush it + ml_flush_line(buf); } - if (readlen && kv_size(buf->update_callbacks)) { + if (kv_size(buf->update_callbacks)) { ml_add_deleted_len_buf(buf, ml_get_buf(buf, lnum, false), -1); } + if (buf->b_ml.ml_flags & (ML_LINE_DIRTY | ML_ALLOCATED)) { + xfree(buf->b_ml.ml_line_ptr); // free allocated line + } + buf->b_ml.ml_line_ptr = line; buf->b_ml.ml_line_lnum = lnum; buf->b_ml.ml_flags = (buf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY; @@ -2692,8 +2713,11 @@ static void ml_flush_line(buf_T *buf) xfree(new_line); entered = false; + } else if (buf->b_ml.ml_flags & ML_ALLOCATED) { + xfree(buf->b_ml.ml_line_ptr); } + buf->b_ml.ml_flags &= ~(ML_LINE_DIRTY | ML_ALLOCATED); buf->b_ml.ml_line_lnum = 0; buf->b_ml.ml_line_offset = 0; } diff --git a/src/nvim/memline_defs.h b/src/nvim/memline_defs.h index 6bb9255909..fd50a73f8c 100644 --- a/src/nvim/memline_defs.h +++ b/src/nvim/memline_defs.h @@ -49,10 +49,11 @@ typedef struct memline { int ml_stack_top; // current top of ml_stack int ml_stack_size; // total number of entries in ml_stack -#define ML_EMPTY 1 // empty buffer -#define ML_LINE_DIRTY 2 // cached line was changed and allocated -#define ML_LOCKED_DIRTY 4 // ml_locked was changed -#define ML_LOCKED_POS 8 // ml_locked needs positive block number +#define ML_EMPTY 0x01 // empty buffer +#define ML_LINE_DIRTY 0x02 // cached line was changed and allocated +#define ML_LOCKED_DIRTY 0x04 // ml_locked was changed +#define ML_LOCKED_POS 0x08 // ml_locked needs positive block number +#define ML_ALLOCATED 0x10 // ml_line_ptr is an allocated copy int ml_flags; linenr_T ml_line_lnum; // line number of cached line, 0 if not valid diff --git a/src/nvim/testdir/test_breakindent.vim b/src/nvim/testdir/test_breakindent.vim index b61c9a570d..0d1753182e 100644 --- a/src/nvim/testdir/test_breakindent.vim +++ b/src/nvim/testdir/test_breakindent.vim @@ -10,7 +10,9 @@ CheckOption breakindent source view_util.vim source screendump.vim -let s:input ="\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP" +func SetUp() + let s:input ="\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP" +endfunc func s:screen_lines(lnum, width) abort return ScreenLines([a:lnum, a:lnum + 2], a:width) @@ -837,12 +839,12 @@ func Test_breakindent20_list() call s:compare_lines(expect, lines) " check formatlistpat indent with different list levels let &l:flp = '^\s*\*\+\s\+' - redraw! %delete _ call setline(1, ['* Congress shall make no law', \ '*** Congress shall make no law', \ '**** Congress shall make no law']) norm! 1gg + redraw! let expect = [ \ "* Congress shall ", \ " make no law ", @@ -956,9 +958,9 @@ func Test_no_spurious_match() let @/ = '\%>3v[y]' redraw! call searchcount().total->assert_equal(1) + " cleanup set hls&vim - let s:input = "\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP" bwipeout! endfunc @@ -1023,8 +1025,6 @@ func Test_no_extra_indent() endfunc func Test_breakindent_column() - " restore original - let s:input ="\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP" call s:test_windows('setl breakindent breakindentopt=column:10') redraw! " 1) default: does not indent, too wide :( diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim index 075f78ec76..e4c21d9932 100644 --- a/src/nvim/testdir/test_edit.vim +++ b/src/nvim/testdir/test_edit.vim @@ -1890,6 +1890,9 @@ func Test_edit_insertmode_ex_edit() call writefile(lines, 'Xtest_edit_insertmode_ex_edit') let buf = RunVimInTerminal('-S Xtest_edit_insertmode_ex_edit', #{rows: 6}) + " Somehow this can be very slow with valgrind. A separate TermWait() works + " better than a longer time with WaitForAssert() (why?) + call TermWait(buf, 1000) call WaitForAssert({-> assert_match('^-- INSERT --\s*$', term_getline(buf, 6))}) call term_sendkeys(buf, "\\") call WaitForAssert({-> assert_notmatch('^-- INSERT --\s*$', term_getline(buf, 6))}) -- cgit From 98e8464319439a934946c67bbcb9c78e865a08c8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 4 Mar 2023 11:17:39 +0800 Subject: vim-patch:9.0.0016: comparing line pointer for 'breakindent' is not reliable Problem: Comparing line pointer for 'breakindent' is not reliable. Solution: Make a copy of the line. https://github.com/vim/vim/commit/c2a79b87fc31080ba24394c0b30bab45f1bea852 Test changes have been squashed into the previous commit. Co-authored-by: Bram Moolenaar --- src/nvim/indent.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/indent.c b/src/nvim/indent.c index ee9bc48460..c57d26dbe0 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -803,11 +803,12 @@ bool briopt_check(win_T *wp) int get_breakindent_win(win_T *wp, char *line) FUNC_ATTR_NONNULL_ALL { - static int prev_indent = 0; // Cached indent value. - static long prev_ts = 0L; // Cached tabstop value. - static const char *prev_line = NULL; // cached pointer to line. - static varnumber_T prev_tick = 0; // Changedtick of cached value. - static long *prev_vts = NULL; // Cached vartabs values. + static int prev_indent = 0; // cached indent value + static long prev_ts = 0L; // cached tabstop value + static int prev_fnum = 0; // cached buffer number + static char *prev_line = NULL; // cached copy of "line" + static varnumber_T prev_tick = 0; // changedtick of cached value + static long *prev_vts = NULL; // cached vartabs values static int prev_list = 0; // cached list value static int prev_listopt = 0; // cached w_p_briopt_list value static char *prev_flp = NULL; // cached formatlistpat value @@ -818,16 +819,24 @@ int get_breakindent_win(win_T *wp, char *line) && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL) ? number_width(wp) + 1 : 0); // used cached indent, unless - // - line pointer changed + // - buffer changed // - 'tabstop' changed + // - buffer was changed // - 'briopt_list changed' changed or // - 'formatlistpattern' changed - if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts + // - line changed + // - 'vartabs' changed + if (prev_fnum != wp->w_buffer->b_fnum + || prev_ts != wp->w_buffer->b_p_ts || prev_tick != buf_get_changedtick(wp->w_buffer) || prev_listopt != wp->w_briopt_list - || (prev_flp == NULL || (strcmp(prev_flp, get_flp_value(wp->w_buffer)) != 0)) + || prev_flp == NULL + || strcmp(prev_flp, get_flp_value(wp->w_buffer)) != 0 + || prev_line == NULL || strcmp(prev_line, line) != 0 || prev_vts != wp->w_buffer->b_p_vts_array) { - prev_line = line; + prev_fnum = wp->w_buffer->b_fnum; + xfree(prev_line); + prev_line = xstrdup(line); prev_ts = wp->w_buffer->b_p_ts; prev_tick = buf_get_changedtick(wp->w_buffer); prev_vts = wp->w_buffer->b_p_vts_array; -- cgit From 808691e3993ee54519229c175fb950cc02261287 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 4 Mar 2023 12:08:45 +0800 Subject: fix(luado): get old_line length before executing Lua code --- src/nvim/lua/executor.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index c8fc76e20d..bb461a7f13 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1706,7 +1706,9 @@ void ex_luado(exarg_T *const eap) break; } lua_pushvalue(lstate, -1); - const char *old_line = (const char *)ml_get_buf(curbuf, l, false); + const char *const old_line = (const char *)ml_get_buf(curbuf, l, false); + // Get length of old_line here as calling Lua code may free it. + const size_t old_line_len = strlen(old_line); lua_pushstring(lstate, old_line); lua_pushnumber(lstate, (lua_Number)l); if (nlua_pcall(lstate, 2, 1)) { @@ -1714,8 +1716,6 @@ void ex_luado(exarg_T *const eap) break; } if (lua_isstring(lstate, -1)) { - size_t old_line_len = strlen(old_line); - size_t new_line_len; const char *const new_line = lua_tolstring(lstate, -1, &new_line_len); char *const new_line_transformed = xmemdupz(new_line, new_line_len); -- cgit From b7d59649acf43c76cc72b25c04bcae926a40b4fe Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 4 Mar 2023 12:23:04 +0800 Subject: fix(redraw): get the line again after evaluating something --- src/nvim/drawline.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index a2ae828f7e..a46f383f64 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1507,6 +1507,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, if (statuscol.draw) { if (statuscol.textp == NULL) { get_statuscol_str(wp, lnum, wlv.row - startrow - wlv.filler_lines, &statuscol); + if (!end_fill) { + // Get the line again as evaluating 'statuscolumn' may free it. + line = ml_get_buf(wp->w_buffer, lnum, false); + ptr = line + v; + } if (wp->w_redr_statuscol) { break; } @@ -1585,6 +1590,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, wlv.c_extra = NUL; wlv.c_final = NUL; wlv.p_extra[wlv.n_extra] = NUL; + + // Get the line again as evaluating 'foldtext' may free it. + line = ml_get_buf(wp->w_buffer, lnum, false); + ptr = line + v; } if (wlv.draw_state == WL_LINE -- cgit From 6cab36e5b7b0d741abe6c5a7c0e20bad30361034 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 4 Mar 2023 13:10:00 +0100 Subject: refactor: replace char_u with char or uint8_t (#22400) Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/digraph.c | 16 +++--- src/nvim/edit.c | 18 +++---- src/nvim/eval.c | 20 ++++---- src/nvim/fileio.c | 46 +++++++++--------- src/nvim/grid_defs.h | 2 +- src/nvim/help.c | 2 +- src/nvim/keycodes.c | 10 ++-- src/nvim/mapping.c | 5 +- src/nvim/mbyte.c | 22 ++++----- src/nvim/memline.c | 26 +++++----- src/nvim/ops.c | 4 +- src/nvim/option.c | 29 ++++++----- src/nvim/regexp_defs.h | 18 +++---- src/nvim/spell.c | 14 +++--- src/nvim/spell_defs.h | 4 +- src/nvim/spellfile.c | 56 ++++++++++----------- src/nvim/spellsuggest.c | 126 ++++++++++++++++++++++++------------------------ 17 files changed, 212 insertions(+), 206 deletions(-) (limited to 'src') diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c index a057978a5e..ae13164191 100644 --- a/src/nvim/digraph.c +++ b/src/nvim/digraph.c @@ -41,8 +41,8 @@ typedef int result_T; typedef struct digraph { - char_u char1; - char_u char2; + uint8_t char1; + uint8_t char2; result_T result; } digr_T; @@ -1493,7 +1493,7 @@ char *get_digraph_for_char(int val_arg) { const int val = val_arg; const digr_T *dp; - static char_u r[3]; + static char r[3]; for (int use_defaults = 0; use_defaults <= 1; use_defaults++) { if (use_defaults == 0) { @@ -1503,10 +1503,10 @@ char *get_digraph_for_char(int val_arg) } for (int i = 0; use_defaults ? dp->char1 != NUL : i < user_digraphs.ga_len; i++) { if (dp->result == val) { - r[0] = dp->char1; - r[1] = dp->char2; + r[0] = (char)dp->char1; + r[1] = (char)dp->char2; r[2] = NUL; - return (char *)r; + return r; } dp++; } @@ -1645,8 +1645,8 @@ static void registerdigraph(int char1, int char2, int n) // Add a new digraph to the table. dp = GA_APPEND_VIA_PTR(digr_T, &user_digraphs); - dp->char1 = (char_u)char1; - dp->char2 = (char_u)char2; + dp->char1 = (uint8_t)char1; + dp->char2 = (uint8_t)char2; dp->result = n; } diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 2849268da2..9eb4802d97 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -2780,7 +2780,7 @@ static bool echeck_abbr(int c) // that the NL replaced. The extra one stores the characters after the cursor // that were deleted (always white space). -static char_u *replace_stack = NULL; +static uint8_t *replace_stack = NULL; static ssize_t replace_stack_nr = 0; // next entry in replace stack static ssize_t replace_stack_len = 0; // max. number of entries @@ -2801,11 +2801,11 @@ void replace_push(int c) replace_stack_len += 50; replace_stack = xrealloc(replace_stack, (size_t)replace_stack_len); } - char_u *p = replace_stack + replace_stack_nr - replace_offset; + uint8_t *p = replace_stack + replace_stack_nr - replace_offset; if (replace_offset) { memmove(p + 1, p, (size_t)replace_offset); } - *p = (char_u)c; + *p = (uint8_t)c; replace_stack_nr++; } @@ -2868,13 +2868,13 @@ static void replace_pop_ins(void) static void mb_replace_pop_ins(int cc) { int n; - char_u buf[MB_MAXBYTES + 1]; + uint8_t buf[MB_MAXBYTES + 1]; int i; if ((n = MB_BYTE2LEN(cc)) > 1) { - buf[0] = (char_u)cc; + buf[0] = (uint8_t)cc; for (i = 1; i < n; i++) { - buf[i] = (char_u)replace_pop(); + buf[i] = (uint8_t)replace_pop(); } ins_bytes_len((char *)buf, (size_t)n); } else { @@ -2893,10 +2893,10 @@ static void mb_replace_pop_ins(int cc) break; } - buf[0] = (char_u)c; + buf[0] = (uint8_t)c; assert(n > 1); for (i = 1; i < n; i++) { - buf[i] = (char_u)replace_pop(); + buf[i] = (uint8_t)replace_pop(); } if (utf_iscomposing(utf_ptr2char((char *)buf))) { ins_bytes_len((char *)buf, (size_t)n); @@ -3113,7 +3113,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) return true; } - if (keytyped == get_special_key_code((char_u *)look + 1)) { + if (keytyped == get_special_key_code(look + 1)) { return true; } } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index da2a88346a..67fede1aea 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -1185,7 +1185,7 @@ int eval_foldexpr(char *arg, int *cp) // the number. char *s = tv.vval.v_string; if (!ascii_isdigit(*s) && *s != '-') { - *cp = (char_u)(*s++); + *cp = (uint8_t)(*s++); } retval = atol(s); } @@ -1597,7 +1597,7 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool dictitem_T *di; if (lp->ll_tv == NULL) { - cc = (char_u)(*endp); + cc = (uint8_t)(*endp); *endp = NUL; if (lp->ll_blob != NULL) { if (op != NULL && *op != '=') { @@ -1993,7 +1993,7 @@ void set_context_for_expression(expand_T *xp, char *arg, cmdidx_T cmdidx) } arg = xp->xp_pattern; if (*arg != NUL) { - while ((c = (char_u)(*++arg)) != NUL && (c == ' ' || c == '\t')) {} + while ((c = (uint8_t)(*++arg)) != NUL && (c == ' ' || c == '\t')) {} } } @@ -2602,7 +2602,7 @@ static int eval5(char **arg, typval_T *rettv, int evaluate) // Repeat computing, until no '+', '-' or '.' is following. for (;;) { - int op = (char_u)(**arg); + int op = (uint8_t)(**arg); if (op != '+' && op != '-' && op != '.') { break; } @@ -2747,7 +2747,7 @@ static int eval6(char **arg, typval_T *rettv, int evaluate, int want_string) // Repeat computing, until no '*', '/' or '%' is following. for (;;) { - op = (char_u)(**arg); + op = (uint8_t)(**arg); if (op != '*' && op != '/' && op != '%') { break; } @@ -7441,9 +7441,9 @@ void ex_execute(exarg_T *eap) const size_t len = strlen(argstr); ga_grow(&ga, (int)len + 2); if (!GA_EMPTY(&ga)) { - ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; + ((char *)(ga.ga_data))[ga.ga_len++] = ' '; } - memcpy((char_u *)(ga.ga_data) + ga.ga_len, argstr, len + 1); + memcpy((char *)(ga.ga_data) + ga.ga_len, argstr, len + 1); if (eap->cmdidx != CMD_execute) { xfree((void *)argstr); } @@ -7838,7 +7838,7 @@ repeat: // ":~" - path relative to the home directory // ":8" - shortname path - postponed till after while (src[*usedlen] == ':' - && ((c = (char_u)src[*usedlen + 1]) == '.' || c == '~' || c == '8')) { + && ((c = (uint8_t)src[*usedlen + 1]) == '.' || c == '~' || c == '8')) { *usedlen += 2; if (c == '8') { continue; @@ -8084,7 +8084,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, const char if (zero_width == regmatch.startp[0]) { // avoid getting stuck on a match with an empty string int i = utfc_ptr2len(tail); - memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i); + memmove((char *)ga.ga_data + ga.ga_len, tail, (size_t)i); ga.ga_len += i; tail += i; continue; @@ -8103,7 +8103,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, const char // copy the text up to where the match is int i = (int)(regmatch.startp[0] - tail); - memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i); + memmove((char *)ga.ga_data + ga.ga_len, tail, (size_t)i); // add the substituted text (void)vim_regsub(®match, sub, expr, (char *)ga.ga_data + ga.ga_len + i, sublen, diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index c93df43cff..6a13548027 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -107,19 +107,19 @@ enum { // Structure to pass arguments from buf_write() to buf_write_bytes(). struct bw_info { - int bw_fd; // file descriptor - char *bw_buf; // buffer with data to be written - int bw_len; // length of data - int bw_flags; // FIO_ flags - char_u bw_rest[CONV_RESTLEN]; // not converted bytes - int bw_restlen; // nr of bytes in bw_rest[] - int bw_first; // first write call - char *bw_conv_buf; // buffer for writing converted chars - size_t bw_conv_buflen; // size of bw_conv_buf - int bw_conv_error; // set for conversion error - linenr_T bw_conv_error_lnum; // first line with error or zero - linenr_T bw_start_lnum; // line number at start of buffer - iconv_t bw_iconv_fd; // descriptor for iconv() or -1 + int bw_fd; // file descriptor + char *bw_buf; // buffer with data to be written + int bw_len; // length of data + int bw_flags; // FIO_ flags + uint8_t bw_rest[CONV_RESTLEN]; // not converted bytes + int bw_restlen; // nr of bytes in bw_rest[] + int bw_first; // first write call + char *bw_conv_buf; // buffer for writing converted chars + size_t bw_conv_buflen; // size of bw_conv_buf + int bw_conv_error; // set for conversion error + linenr_T bw_conv_error_lnum; // first line with error or zero + linenr_T bw_start_lnum; // line number at start of buffer + iconv_t bw_iconv_fd; // descriptor for iconv() or -1 }; typedef struct { @@ -989,7 +989,7 @@ retry: int ni; long tlen = 0; for (;;) { - p = (char_u *)ml_get(read_buf_lnum) + read_buf_col; + p = (uint8_t *)ml_get(read_buf_lnum) + read_buf_col; int n = (int)strlen((char *)p); if ((int)tlen + n + 1 > size) { // Filled up to "size", append partial line. @@ -1798,7 +1798,7 @@ failed: msg_scrolled_ign = true; if (!read_stdin && !read_buffer) { - p = (char_u *)msg_trunc_attr(IObuff, false, 0); + p = (uint8_t *)msg_trunc_attr(IObuff, false, 0); } if (read_stdin || read_buffer || restart_edit != 0 @@ -1859,7 +1859,7 @@ failed: // When opening a new file locate undo info and read it. if (read_undo_file) { - char_u hash[UNDO_HASH_SIZE]; + uint8_t hash[UNDO_HASH_SIZE]; sha256_finish(&sha_ctx, hash); u_read_undo(NULL, hash, fname); @@ -3208,7 +3208,7 @@ restore_backup: // Skip the BOM when appending and the file already existed, the BOM // only makes sense at the start of the file. if (buf->b_p_bomb && !write_bin && (!append || perm < 0)) { - write_info.bw_len = make_bom((char_u *)buffer, fenc); + write_info.bw_len = make_bom(buffer, fenc); if (write_info.bw_len > 0) { // don't convert write_info.bw_flags = FIO_NOCONVERT | wb_flags; @@ -3991,9 +3991,10 @@ static int buf_write_bytes(struct bw_info *ip) /// @param flags FIO_ flags that specify which encoding to use /// /// @return true for an error, false when it's OK. -static bool ucs2bytes(unsigned c, char **pp, int flags) FUNC_ATTR_NONNULL_ALL +static bool ucs2bytes(unsigned c, char **pp, int flags) + FUNC_ATTR_NONNULL_ALL { - char_u *p = (char_u *)(*pp); + uint8_t *p = (uint8_t *)(*pp); bool error = false; if (flags & FIO_UCS4) { @@ -4170,8 +4171,9 @@ static char *check_for_bom(const char *p_in, int size, int *lenp, int flags) /// Generate a BOM in "buf[4]" for encoding "name". /// /// @return the length of the BOM (zero when no BOM). -static int make_bom(char_u *buf, char *name) +static int make_bom(char *buf_in, char *name) { + uint8_t *buf = (uint8_t *)buf_in; int flags = get_fio_flags(name); // Can't put a BOM in a non-Unicode file. @@ -4187,7 +4189,7 @@ static int make_bom(char_u *buf, char *name) } char *p = (char *)buf; (void)ucs2bytes(0xfeff, &p, flags); - return (int)((char_u *)p - buf); + return (int)((uint8_t *)p - buf); } /// Shorten filename of a buffer. @@ -4953,7 +4955,7 @@ int buf_check_timestamp(buf_T *buf) // Reload the buffer. buf_reload(buf, orig_mode, reload == RELOAD_DETECT); if (buf->b_p_udf && buf->b_ffname != NULL) { - char_u hash[UNDO_HASH_SIZE]; + uint8_t hash[UNDO_HASH_SIZE]; // Any existing undo file is unusable, write it now. u_compute_hash(buf, hash); diff --git a/src/nvim/grid_defs.h b/src/nvim/grid_defs.h index db31f7b984..830c74e86d 100644 --- a/src/nvim/grid_defs.h +++ b/src/nvim/grid_defs.h @@ -50,7 +50,7 @@ struct ScreenGrid { schar_T *chars; sattr_T *attrs; size_t *line_offset; - char_u *line_wraps; + char *line_wraps; // last column that was drawn (not cleared with the default background). // only used when "throttled" is set. Not allocated by grid_alloc! diff --git a/src/nvim/help.c b/src/nvim/help.c index 5fa48e0cee..968f0bc2f4 100644 --- a/src/nvim/help.c +++ b/src/nvim/help.c @@ -1022,7 +1022,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool *p2 = NUL; vim_snprintf(NameBuff, MAXPATHL, _("E154: Duplicate tag \"%s\" in file %s/%s"), - ((char_u **)ga.ga_data)[i], dir, p2 + 1); + ((char **)ga.ga_data)[i], dir, p2 + 1); emsg(NameBuff); *p2 = '\t'; break; diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c index 8114efc10c..404087fec3 100644 --- a/src/nvim/keycodes.c +++ b/src/nvim/keycodes.c @@ -723,7 +723,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m if (modifiers != 0 && last_dash[l + 1] == '>') { key = utf_ptr2char(last_dash + off); } else { - key = get_special_key_code((char_u *)last_dash + off); + key = get_special_key_code(last_dash + off); if (!(flags & FSK_KEEP_X_KEY)) { key = handle_x_keys(key); } @@ -822,18 +822,18 @@ int find_special_key_in_table(int c) /// a termcap name. /// /// @return Key code or 0 if not found. -int get_special_key_code(const char_u *name) +int get_special_key_code(const char *name) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { for (int i = 0; key_names_table[i].name != NULL; i++) { const char *const table_name = key_names_table[i].name; int j; - for (j = 0; ascii_isident(name[j]) && table_name[j] != NUL; j++) { - if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j])) { + for (j = 0; ascii_isident((uint8_t)name[j]) && table_name[j] != NUL; j++) { + if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC((uint8_t)name[j])) { break; } } - if (!ascii_isident(name[j]) && table_name[j] == NUL) { + if (!ascii_isident((uint8_t)name[j]) && table_name[j] == NUL) { return key_names_table[i].key; } } diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 60524b9fb7..3c4ce0ee2b 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -1162,8 +1162,9 @@ static bool expand_buffer = false; /// @param cpo_flags Value of various flags present in &cpo /// /// @return NULL when there is a problem. -static char *translate_mapping(char_u *str, int cpo_flags) +static char *translate_mapping(char *str_in, int cpo_flags) { + uint8_t *str = (uint8_t *)str_in; garray_T ga; ga_init(&ga, 1, 40); @@ -1346,7 +1347,7 @@ int ExpandMappings(char *pat, regmatch_T *regmatch, int *numMatches, char ***mat continue; } - char *p = translate_mapping((char_u *)mp->m_keys, CPO_TO_CPO_FLAGS); + char *p = translate_mapping(mp->m_keys, CPO_TO_CPO_FLAGS); if (p == NULL) { continue; } diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index d8be4f4997..35af7479b0 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1930,16 +1930,16 @@ theend: /// @return true if string "s" is a valid utf-8 string. /// When "end" is NULL stop at the first NUL. Otherwise stop at "end". -bool utf_valid_string(const char_u *s, const char_u *end) +bool utf_valid_string(const char *s, const char *end) { - const char_u *p = s; + const uint8_t *p = (uint8_t *)s; - while (end == NULL ? *p != NUL : p < end) { + while (end == NULL ? *p != NUL : p < (uint8_t *)end) { int l = utf8len_tab_zero[*p]; if (l == 0) { return false; // invalid lead byte } - if (end != NULL && p + l > end) { + if (end != NULL && p + l > (uint8_t *)end) { return false; // incomplete byte sequence } p++; @@ -2454,8 +2454,8 @@ char *string_convert(const vimconv_T *const vcp, char *ptr, size_t *lenp) // set to the number of remaining bytes. char *string_convert_ext(const vimconv_T *const vcp, char *ptr, size_t *lenp, size_t *unconvlenp) { - char_u *retval = NULL; - char_u *d; + uint8_t *retval = NULL; + uint8_t *d; int c; size_t len; @@ -2475,10 +2475,10 @@ char *string_convert_ext(const vimconv_T *const vcp, char *ptr, size_t *lenp, si for (size_t i = 0; i < len; i++) { c = (uint8_t)ptr[i]; if (c < 0x80) { - *d++ = (char_u)c; + *d++ = (uint8_t)c; } else { - *d++ = (char_u)(0xc0 + (char_u)((unsigned)c >> 6)); - *d++ = (char_u)(0x80 + (c & 0x3f)); + *d++ = (uint8_t)(0xc0 + (uint8_t)((unsigned)c >> 6)); + *d++ = (uint8_t)(0x80 + (c & 0x3f)); } } *d = NUL; @@ -2573,7 +2573,7 @@ char *string_convert_ext(const vimconv_T *const vcp, char *ptr, size_t *lenp, si } if (!utf_iscomposing(c)) { // skip composing chars if (c < 0x100) { - *d++ = (char_u)c; + *d++ = (uint8_t)c; } else if (vcp->vc_fail) { xfree(retval); return NULL; @@ -2594,7 +2594,7 @@ char *string_convert_ext(const vimconv_T *const vcp, char *ptr, size_t *lenp, si break; case CONV_ICONV: // conversion with vcp->vc_fd - retval = (char_u *)iconv_string(vcp, ptr, len, unconvlenp, lenp); + retval = (uint8_t *)iconv_string(vcp, ptr, len, unconvlenp, lenp); break; } diff --git a/src/nvim/memline.c b/src/nvim/memline.c index e9988eb844..0d8da68a02 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -179,19 +179,19 @@ enum { // different machines. b0_magic_* is used to check the byte order and size of // variables, because the rest of the swap file is not portable. struct block0 { - char_u b0_id[2]; ///< ID for block 0: BLOCK0_ID0 and BLOCK0_ID1. + char b0_id[2]; ///< ID for block 0: BLOCK0_ID0 and BLOCK0_ID1. char b0_version[10]; // Vim version string - char_u b0_page_size[4]; // number of bytes per page - char_u b0_mtime[4]; // last modification time of file - char_u b0_ino[4]; // inode of b0_fname - char_u b0_pid[4]; // process id of creator (or 0) + char b0_page_size[4]; // number of bytes per page + char b0_mtime[4]; // last modification time of file + char b0_ino[4]; // inode of b0_fname + char b0_pid[4]; // process id of creator (or 0) char b0_uname[B0_UNAME_SIZE]; // name of user (uid if no name) char b0_hname[B0_HNAME_SIZE]; // host name (if it has a name) char b0_fname[B0_FNAME_SIZE_ORG]; // name of file being edited long b0_magic_long; // check for byte order of long int b0_magic_int; // check for byte order of int int16_t b0_magic_short; // check for byte order of short - char_u b0_magic_char; // check for last char + char b0_magic_char; // check for last char }; // Note: b0_dirty and b0_flags are put at the end of the file name. For very @@ -3556,19 +3556,21 @@ static bool fnamecmp_ino(char *fname_c, char *fname_s, long ino_block0) /// Move a long integer into a four byte character array. /// Used for machine independency in block zero. -static void long_to_char(long n, char_u *s) +static void long_to_char(long n, char *s_in) { - s[0] = (char_u)(n & 0xff); + uint8_t *s= (uint8_t *)s_in; + s[0] = (uint8_t)(n & 0xff); n = (unsigned)n >> 8; - s[1] = (char_u)(n & 0xff); + s[1] = (uint8_t)(n & 0xff); n = (unsigned)n >> 8; - s[2] = (char_u)(n & 0xff); + s[2] = (uint8_t)(n & 0xff); n = (unsigned)n >> 8; - s[3] = (char_u)(n & 0xff); + s[3] = (uint8_t)(n & 0xff); } -static long char_to_long(const char_u *s) +static long char_to_long(const char *s_in) { + const uint8_t *s = (uint8_t *)s_in; long retval; retval = s[3]; diff --git a/src/nvim/ops.c b/src/nvim/ops.c index d2a96be5ad..884eeef433 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1186,7 +1186,7 @@ int do_execreg(int regname, int colon, int addcr, int silent) /// used only after other typeahead has been processed. static void put_reedit_in_typebuf(int silent) { - char_u buf[3]; + uint8_t buf[3]; if (restart_edit == NUL) { return; @@ -1197,7 +1197,7 @@ static void put_reedit_in_typebuf(int silent) buf[1] = 'R'; buf[2] = NUL; } else { - buf[0] = (char_u)(restart_edit == 'I' ? 'i' : restart_edit); + buf[0] = (uint8_t)(restart_edit == 'I' ? 'i' : restart_edit); buf[1] = NUL; } if (ins_typebuf((char *)buf, REMAP_NONE, 0, true, silent) == OK) { diff --git a/src/nvim/option.c b/src/nvim/option.c index 6ddc3b5cfb..04cf7eede4 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -839,9 +839,8 @@ static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, co // Handle some special cases with string option values static void munge_string_opt_val(char **varp, char **oldval, char **const origval, - char_u **const origval_l, char_u **const origval_g, - char **const argp, char *const whichwrap, size_t whichwraplen, - char **const save_argp) + char **const origval_l, char **const origval_g, char **const argp, + char *const whichwrap, size_t whichwraplen, char **const save_argp) { // Set 'keywordprg' to ":help" if an empty // value was passed to :set by the user. @@ -870,11 +869,11 @@ static void munge_string_opt_val(char **varp, char **oldval, char **const origva if (*origval == *oldval) { *origval = *varp; } - if (*origval_l == (char_u *)(*oldval)) { - *origval_l = *(char_u **)varp; + if (*origval_l == *oldval) { + *origval_l = *varp; } - if (*origval_g == (char_u *)(*oldval)) { - *origval_g = *(char_u **)varp; + if (*origval_g == *oldval) { + *origval_g = *varp; } *oldval = *varp; } else if (varp == &p_ww && ascii_isdigit(**argp)) { @@ -919,8 +918,8 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, char *varp = varp_arg; char *save_arg = NULL; char *s = NULL; - char_u *origval_l = NULL; - char_u *origval_g = NULL; + char *origval_l = NULL; + char *origval_g = NULL; char whichwrap[80]; // When using ":set opt=val" for a global option @@ -935,12 +934,12 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, char *oldval = *(char **)varp; if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) { - origval_l = *(char_u **)get_varp_scope(&(options[opt_idx]), OPT_LOCAL); - origval_g = *(char_u **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); + origval_l = *(char **)get_varp_scope(&(options[opt_idx]), OPT_LOCAL); + origval_g = *(char **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL); // A global-local string option might have an empty option as value to // indicate that the global value should be used. - if (((int)options[opt_idx].indir & PV_BOTH) && origval_l == (char_u *)empty_option) { + if (((int)options[opt_idx].indir & PV_BOTH) && origval_l == empty_option) { origval_l = origval_g; } } @@ -1132,8 +1131,8 @@ static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, // origval may be freed by did_set_string_option(), make a copy. char *saved_origval = (origval != NULL) ? xstrdup(origval) : NULL; - char *saved_origval_l = (origval_l != NULL) ? xstrdup((char *)origval_l) : NULL; - char *saved_origval_g = (origval_g != NULL) ? xstrdup((char *)origval_g) : NULL; + char *saved_origval_l = (origval_l != NULL) ? xstrdup(origval_l) : NULL; + char *saved_origval_g = (origval_g != NULL) ? xstrdup(origval_g) : NULL; // newval (and varp) may become invalid if the buffer is closed by // autocommands. @@ -4672,7 +4671,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags) return; } } - int key = get_special_key_code((char_u *)arg + 1); + int key = get_special_key_code(arg + 1); if (key == 0) { // unknown name xp->xp_context = EXPAND_NOTHING; return; diff --git a/src/nvim/regexp_defs.h b/src/nvim/regexp_defs.h index b27a5b5942..ef155e8d46 100644 --- a/src/nvim/regexp_defs.h +++ b/src/nvim/regexp_defs.h @@ -98,11 +98,11 @@ typedef struct { bool re_in_use; int regstart; - char_u reganch; - char_u *regmust; + uint8_t reganch; + uint8_t *regmust; int regmlen; - char_u reghasz; - char_u program[]; + uint8_t reghasz; + uint8_t program[]; } bt_regprog_T; // Structure representing a NFA state. @@ -130,7 +130,7 @@ typedef struct { int reganch; // pattern starts with ^ int regstart; // char at start of pattern - char_u *match_text; // plain text to match with + uint8_t *match_text; // plain text to match with int has_zend; // pattern contains \ze int has_backref; // pattern contains \1 .. \9 @@ -158,19 +158,19 @@ typedef struct { // from 1 to zero the matches need to be freed. struct reg_extmatch { int16_t refcnt; - char_u *matches[NSUBEXP]; + uint8_t *matches[NSUBEXP]; }; struct regengine { /// bt_regcomp or nfa_regcomp - regprog_T *(*regcomp)(char_u *, int); + regprog_T *(*regcomp)(uint8_t *, int); /// bt_regfree or nfa_regfree void (*regfree)(regprog_T *); /// bt_regexec_nl or nfa_regexec_nl - int (*regexec_nl)(regmatch_T *, char_u *, colnr_T, bool); + int (*regexec_nl)(regmatch_T *, uint8_t *, colnr_T, bool); /// bt_regexec_mult or nfa_regexec_mult long (*regexec_multi)(regmmatch_T *, win_T *, buf_T *, linenr_T, colnr_T, proftime_T *, int *); - // char_u *expr; + // uint8_t *expr; }; // Flags used by vim_regsub() and vim_regsub_both() diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 117a770e50..dbe8ad5763 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -737,7 +737,7 @@ static void find_word(matchinf_T *mip, int mode) // If the word ends the sequence of compound flags of the // words must match with one of the COMPOUNDRULE items and // the number of syllables must not be too large. - mip->mi_compflags[mip->mi_complen] = (char_u)((unsigned)flags >> 24); + mip->mi_compflags[mip->mi_complen] = (uint8_t)((unsigned)flags >> 24); mip->mi_compflags[mip->mi_complen + 1] = NUL; if (word_ends) { char fword[MAXWLEN] = { 0 }; @@ -2354,8 +2354,8 @@ void clear_spell_chartab(spelltab_T *sp) CLEAR_FIELD(sp->st_isu); for (int i = 0; i < 256; i++) { - sp->st_fold[i] = (char_u)i; - sp->st_upper[i] = (char_u)i; + sp->st_fold[i] = (uint8_t)i; + sp->st_upper[i] = (uint8_t)i; } // We include digits. A word shouldn't start with a digit, but handling @@ -2366,11 +2366,11 @@ void clear_spell_chartab(spelltab_T *sp) for (int i = 'A'; i <= 'Z'; i++) { sp->st_isw[i] = true; sp->st_isu[i] = true; - sp->st_fold[i] = (char_u)(i + 0x20); + sp->st_fold[i] = (uint8_t)(i + 0x20); } for (int i = 'a'; i <= 'z'; i++) { sp->st_isw[i] = true; - sp->st_upper[i] = (char_u)(i - 0x20); + sp->st_upper[i] = (uint8_t)(i - 0x20); } } @@ -2391,8 +2391,8 @@ void init_spell_chartab(void) // The folded/upper-cased value is different between latin1 and // utf8 for 0xb5, causing E763 for no good reason. Use the latin1 // value for utf-8 to avoid this. - spelltab.st_fold[i] = (f < 256) ? (char_u)f : (char_u)i; - spelltab.st_upper[i] = (u < 256) ? (char_u)u : (char_u)i; + spelltab.st_fold[i] = (f < 256) ? (uint8_t)f : (uint8_t)i; + spelltab.st_upper[i] = (u < 256) ? (uint8_t)u : (uint8_t)i; } } diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h index 93cf335c3a..bda43a94d1 100644 --- a/src/nvim/spell_defs.h +++ b/src/nvim/spell_defs.h @@ -206,8 +206,8 @@ typedef struct langp_S { typedef struct { bool st_isw[256]; // flags: is word char bool st_isu[256]; // flags: is uppercase char - char_u st_fold[256]; // chars: folded case - char_u st_upper[256]; // chars: upper case + uint8_t st_fold[256]; // chars: folded case + uint8_t st_upper[256]; // chars: upper case } spelltab_T; // Use our own character-case definitions, because the current locale may diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index e9dd0a4d5e..bb2ef1a458 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -1079,7 +1079,7 @@ static int read_charflags_section(FILE *fd) // Set the word-char flags and fill SPELL_ISUPPER() table. if (flags != NULL && fol != NULL) { - set_spell_charflags((char_u *)flags, flagslen, (char *)fol); + set_spell_charflags(flags, flagslen, (char *)fol); } xfree(flags); @@ -1314,7 +1314,7 @@ static int read_words_section(FILE *fd, slang_T *lp, int len) int done = 0; int i; int c; - char_u word[MAXWLEN]; + uint8_t word[MAXWLEN]; while (done < len) { // Read one word at a time. @@ -1323,7 +1323,7 @@ static int read_words_section(FILE *fd, slang_T *lp, int len) if (c == EOF) { return SP_TRUNCERROR; } - word[i] = (char_u)c; + word[i] = (uint8_t)c; if (word[i] == NUL) { break; } @@ -1480,7 +1480,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len) // Add all flags to "sl_compallflags". if (vim_strchr("?*+[]/", c) == NULL && !byte_in_str(slang->sl_compallflags, c)) { - *ap++ = (char_u)c; + *ap++ = (uint8_t)c; *ap = NUL; } @@ -1493,7 +1493,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len) atstart = 0; } else { if (!byte_in_str(slang->sl_compstartflags, c)) { - *cp++ = (char_u)c; + *cp++ = (uint8_t)c; *cp = NUL; } if (atstart == 1) { @@ -1508,7 +1508,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len) XFREE_CLEAR(slang->sl_comprules); crp = NULL; } else { - *crp++ = (char_u)c; + *crp++ = (uint8_t)c; } } @@ -1709,7 +1709,7 @@ static int spell_read_tree(FILE *fd, char **bytsp, long *bytsp_len, idx_T **idxs *idxsp = ip; // Recursively read the tree and store it in the array. - idx = read_tree_node(fd, (char_u *)bp, ip, (int)len, 0, prefixtree, prefixcnt); + idx = read_tree_node(fd, bp, ip, (int)len, 0, prefixtree, prefixcnt); if (idx < 0) { return idx; } @@ -1729,9 +1729,10 @@ static int spell_read_tree(FILE *fd, char **bytsp, long *bytsp_len, idx_T **idxs /// @param startidx current index in "byts" and "idxs" /// @param prefixtree true for reading PREFIXTREE /// @param maxprefcondnr maximum for -static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx_T startidx, +static idx_T read_tree_node(FILE *fd, char *byts_in, idx_T *idxs, int maxidx, idx_T startidx, bool prefixtree, int maxprefcondnr) { + uint8_t *byts = (uint8_t *)byts_in; int len; int n; idx_T idx = startidx; @@ -1746,7 +1747,7 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx if (startidx + len >= maxidx) { return SP_FORMERROR; } - byts[idx++] = (char_u)len; + byts[idx++] = (uint8_t)len; // Read the byte values, flag/region bytes and shared indexes. for (int i = 1; i <= len; i++) { @@ -1806,7 +1807,7 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx c = getc(fd); // } } - byts[idx++] = (char_u)c; + byts[idx++] = (uint8_t)c; } // Recursively read the children for non-shared siblings. @@ -1818,7 +1819,7 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx idxs[startidx + i] &= ~SHARED_MASK; } else { idxs[startidx + i] = idx; - idx = read_tree_node(fd, byts, idxs, maxidx, idx, + idx = read_tree_node(fd, (char *)byts, idxs, maxidx, idx, prefixtree, maxprefcondnr); if (idx < 0) { break; @@ -2783,11 +2784,11 @@ static void aff_process_flags(afffile_T *affile, affentry_T *entry) if (entry->ae_flags != NULL && (affile->af_compforbid != 0 || affile->af_comppermit != 0)) { for (p = entry->ae_flags; *p != NUL;) { - char_u *prevp = (char_u *)p; + char *prevp = p; unsigned flag = get_affitem(affile->af_flagtype, &p); if (flag == affile->af_comppermit || flag == affile->af_compforbid) { STRMOVE(prevp, p); - p = (char *)prevp; + p = prevp; if (flag == affile->af_comppermit) { entry->ae_comppermit = true; } else { @@ -2894,12 +2895,12 @@ static void process_compflags(spellinfo_T *spin, afffile_T *aff, char *compflags STRCAT(p, "/"); } spin->si_compflags = p; - char_u *tp = (char_u *)p + strlen(p); + uint8_t *tp = (uint8_t *)p + strlen(p); for (p = compflags; *p != NUL;) { if (vim_strchr("/?*+[]", (uint8_t)(*p)) != NULL) { // Copy non-flag characters directly. - *tp++ = (char_u)(*p++); + *tp++ = (uint8_t)(*p++); } else { // First get the flag number, also checks validity. prevp = p; @@ -3640,7 +3641,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char *fname) char rline[MAXLINELEN]; char *line; char *pc = NULL; - char_u *p; + char *p; int l; int retval = OK; bool did_word = false; @@ -3748,7 +3749,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char *fname) regionmask = spin->si_region; // Check for flags and region after a slash. - p = (char_u *)vim_strchr(line, '/'); + p = vim_strchr(line, '/'); if (p != NULL) { *p++ = NUL; while (*p != NUL) { @@ -3758,13 +3759,13 @@ static int spell_read_wordfile(spellinfo_T *spin, char *fname) flags |= WF_BANNED; } else if (*p == '?') { // Rare word. flags |= WF_RARE; - } else if (ascii_isdigit(*p)) { // region number(s) + } else if (ascii_isdigit((uint8_t)(*p))) { // region number(s) if ((flags & WF_REGION) == 0) { // first one regionmask = 0; } flags |= WF_REGION; - l = *p - '0'; + l = (uint8_t)(*p) - '0'; if (l == 0 || l > spin->si_region_count) { smsg(_("Invalid region nr in %s line %ld: %s"), fname, lnum, p); @@ -3817,7 +3818,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char *fname) static void *getroom(spellinfo_T *spin, size_t len, bool align) FUNC_ATTR_NONNULL_RET { - char_u *p; + char *p; sblock_T *bl = spin->si_blocks; assert(len <= SBLOCKSIZE); @@ -3837,7 +3838,7 @@ static void *getroom(spellinfo_T *spin, size_t len, bool align) spin->si_blocks_cnt++; } - p = bl->sb_data + bl->sb_used; + p = (char *)bl->sb_data + bl->sb_used; bl->sb_used += (int)len; return p; @@ -3876,7 +3877,7 @@ static wordnode_T *wordtree_alloc(spellinfo_T *spin) /// Control characters and trailing '/' are invalid. Space is OK. static bool valid_spell_word(const char *word, const char *end) { - if (!utf_valid_string((char_u *)word, (char_u *)end)) { + if (!utf_valid_string(word, end)) { return false; } for (const char *p = word; *p != NUL && p < end; p += utfc_ptr2len(p)) { @@ -3913,7 +3914,7 @@ static int store_word(spellinfo_T *spin, char *word, int flags, int region, cons } (void)spell_casefold(curwin, word, len, foldword, MAXWLEN); - for (const char_u *p = (char_u *)pfxlist; res == OK; p++) { + for (const char *p = pfxlist; res == OK; p++) { if (!need_affix || (p != NULL && *p != NUL)) { res = tree_add_word(spin, (char_u *)foldword, spin->si_foldroot, ct | flags, region, p == NULL ? 0 : *p); @@ -3925,7 +3926,7 @@ static int store_word(spellinfo_T *spin, char *word, int flags, int region, cons spin->si_foldwcount++; if (res == OK && (ct == WF_KEEPCAP || (flags & WF_KEEPCAP))) { - for (const char_u *p = (char_u *)pfxlist; res == OK; p++) { + for (const char *p = pfxlist; res == OK; p++) { if (!need_affix || (p != NULL && *p != NUL)) { res = tree_add_word(spin, (char_u *)word, spin->si_keeproot, flags, region, p == NULL ? 0 : *p); @@ -5727,8 +5728,9 @@ static void init_spellfile(void) /// Set the spell character tables from strings in the .spl file. /// /// @param cnt length of "flags" -static void set_spell_charflags(const char_u *flags, int cnt, char *fol) +static void set_spell_charflags(const char *flags_in, int cnt, char *fol) { + const uint8_t *flags = (uint8_t *)flags_in; // We build the new tables here first, so that we can compare with the // previous one. spelltab_T new_st; @@ -5745,9 +5747,9 @@ static void set_spell_charflags(const char_u *flags, int cnt, char *fol) if (*p != NUL) { c = mb_ptr2char_adv((const char **)&p); - new_st.st_fold[i + 128] = (char_u)c; + new_st.st_fold[i + 128] = (uint8_t)c; if (i + 128 != c && new_st.st_isu[i + 128] && c < 256) { - new_st.st_upper[c] = (char_u)(i + 128); + new_st.st_upper[c] = (uint8_t)(i + 128); } } } diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c index ea2d5e6ff7..2823e74c2f 100644 --- a/src/nvim/spellsuggest.c +++ b/src/nvim/spellsuggest.c @@ -189,28 +189,28 @@ typedef enum { /// Struct to keep the state at each level in suggest_try_change(). typedef struct trystate_S { - state_T ts_state; ///< state at this level, STATE_ - int ts_score; ///< score - idx_T ts_arridx; ///< index in tree array, start of node - int16_t ts_curi; ///< index in list of child nodes - char_u ts_fidx; ///< index in fword[], case-folded bad word - char_u ts_fidxtry; ///< ts_fidx at which bytes may be changed - char_u ts_twordlen; ///< valid length of tword[] - char_u ts_prefixdepth; ///< stack depth for end of prefix or - ///< PFD_PREFIXTREE or PFD_NOPREFIX - char_u ts_flags; ///< TSF_ flags - char_u ts_tcharlen; ///< number of bytes in tword character - char_u ts_tcharidx; ///< current byte index in tword character - char_u ts_isdiff; ///< DIFF_ values - char_u ts_fcharstart; ///< index in fword where badword char started - char_u ts_prewordlen; ///< length of word in "preword[]" - char_u ts_splitoff; ///< index in "tword" after last split - char_u ts_splitfidx; ///< "ts_fidx" at word split - char_u ts_complen; ///< nr of compound words used - char_u ts_compsplit; ///< index for "compflags" where word was spit - char_u ts_save_badflags; ///< su_badflags saved here - char_u ts_delidx; ///< index in fword for char that was deleted, - ///< valid when "ts_flags" has TSF_DIDDEL + state_T ts_state; ///< state at this level, STATE_ + int ts_score; ///< score + idx_T ts_arridx; ///< index in tree array, start of node + int16_t ts_curi; ///< index in list of child nodes + uint8_t ts_fidx; ///< index in fword[], case-folded bad word + uint8_t ts_fidxtry; ///< ts_fidx at which bytes may be changed + uint8_t ts_twordlen; ///< valid length of tword[] + uint8_t ts_prefixdepth; ///< stack depth for end of prefix or + ///< PFD_PREFIXTREE or PFD_NOPREFIX + uint8_t ts_flags; ///< TSF_ flags + uint8_t ts_tcharlen; ///< number of bytes in tword character + uint8_t ts_tcharidx; ///< current byte index in tword character + uint8_t ts_isdiff; ///< DIFF_ values + uint8_t ts_fcharstart; ///< index in fword where badword char started + uint8_t ts_prewordlen; ///< length of word in "preword[]" + uint8_t ts_splitoff; ///< index in "tword" after last split + uint8_t ts_splitfidx; ///< "ts_fidx" at word split + uint8_t ts_complen; ///< nr of compound words used + uint8_t ts_compsplit; ///< index for "compflags" where word was spit + uint8_t ts_save_badflags; ///< su_badflags saved here + uint8_t ts_delidx; ///< index in fword for char that was deleted, + ///< valid when "ts_flags" has TSF_DIDDEL } trystate_T; // values for ts_isdiff @@ -243,7 +243,7 @@ static long spell_suggest_timeout = 5000; /// Returns true when the sequence of flags in "compflags" plus "flag" can /// possibly form a valid compounded word. This also checks the COMPOUNDRULE /// lines if they don't contain wildcards. -static bool can_be_compound(trystate_T *sp, slang_T *slang, char_u *compflags, int flag) +static bool can_be_compound(trystate_T *sp, slang_T *slang, uint8_t *compflags, int flag) { // If the flag doesn't appear in sl_compstartflags or sl_compallflags // then it can't possibly compound. @@ -256,7 +256,7 @@ static bool can_be_compound(trystate_T *sp, slang_T *slang, char_u *compflags, i // possibly can form a match with COMPOUNDRULE patterns. This only // makes sense when we have two or more words. if (slang->sl_comprules != NULL && sp->ts_complen > sp->ts_compsplit) { - compflags[sp->ts_complen] = (char_u)flag; + compflags[sp->ts_complen] = (uint8_t)flag; compflags[sp->ts_complen + 1] = NUL; bool v = match_compoundrule(slang, compflags + sp->ts_compsplit); compflags[sp->ts_complen] = NUL; @@ -349,7 +349,7 @@ static int badword_captype(char *word, char *end) /// @return the offset. static int bytes2offset(char **pp) { - char_u *p = (char_u *)(*pp); + uint8_t *p = (uint8_t *)(*pp); int nr; int c = *p++; @@ -1145,10 +1145,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // words and split word. NUL terminated // when going deeper but not when coming // back. - char_u compflags[MAXWLEN]; // compound flags, one for each word + uint8_t compflags[MAXWLEN]; // compound flags, one for each word int newscore; int score; - char_u *byts, *fbyts, *pbyts; + uint8_t *byts, *fbyts, *pbyts; idx_T *idxs, *fidxs, *pidxs; int c, c2, c3; int n = 0; @@ -1165,7 +1165,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun bool goodword_ends; #ifdef DEBUG_TRIEWALK // Stores the name of the change made at each level. - char_u changename[MAXWLEN][80]; + uint8_t changename[MAXWLEN][80]; #endif int breakcheckcount = 1000; bool compound_ok; @@ -1181,7 +1181,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun if (soundfold) { // Going through the soundfold tree. - byts = fbyts = (char_u *)slang->sl_sbyts; + byts = fbyts = (uint8_t *)slang->sl_sbyts; idxs = fidxs = slang->sl_sidxs; pbyts = NULL; pidxs = NULL; @@ -1190,9 +1190,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun } else { // When there are postponed prefixes we need to use these first. At // the end of the prefix we continue in the case-fold tree. - fbyts = (char_u *)slang->sl_fbyts; + fbyts = (uint8_t *)slang->sl_fbyts; fidxs = slang->sl_fidxs; - pbyts = (char_u *)slang->sl_pbyts; + pbyts = (uint8_t *)slang->sl_pbyts; pidxs = slang->sl_pidxs; if (pbyts != NULL) { byts = pbyts; @@ -1239,7 +1239,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun n = (int)sp->ts_state; PROF_STORE(sp->ts_state) sp->ts_state = STATE_ENDNUL; - sp->ts_save_badflags = (char_u)su->su_badflags; + sp->ts_save_badflags = (uint8_t)su->su_badflags; // At end of a prefix or at start of prefixtree: check for // following word. @@ -1256,7 +1256,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun go_deeper(stack, depth, 0); depth++; sp = &stack[depth]; - sp->ts_prefixdepth = (char_u)(depth - 1); + sp->ts_prefixdepth = (uint8_t)(depth - 1); byts = fbyts; idxs = fidxs; sp->ts_arridx = 0; @@ -1266,7 +1266,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun tword[sp->ts_twordlen] = NUL; make_case_word(tword + sp->ts_splitoff, preword + sp->ts_prewordlen, flags); - sp->ts_prewordlen = (char_u)strlen(preword); + sp->ts_prewordlen = (uint8_t)strlen(preword); sp->ts_splitoff = sp->ts_twordlen; } break; @@ -1276,7 +1276,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // Past bytes in node and/or past NUL bytes. PROF_STORE(sp->ts_state) sp->ts_state = STATE_ENDNUL; - sp->ts_save_badflags = (char_u)su->su_badflags; + sp->ts_save_badflags = (uint8_t)su->su_badflags; break; } @@ -1379,7 +1379,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun break; } - compflags[sp->ts_complen] = (char_u)((unsigned)flags >> 24); + compflags[sp->ts_complen] = (uint8_t)((unsigned)flags >> 24); compflags[sp->ts_complen + 1] = NUL; xstrlcpy(preword + sp->ts_prewordlen, tword + sp->ts_splitoff, @@ -1577,7 +1577,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun < slang->sl_compmax) && (can_be_compound(sp, slang, compflags, (int)((unsigned)flags >> 24)))) { try_compound = true; - compflags[sp->ts_complen] = (char_u)((unsigned)flags >> 24); + compflags[sp->ts_complen] = (uint8_t)((unsigned)flags >> 24); compflags[sp->ts_complen + 1] = NUL; } @@ -1596,7 +1596,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun sp->ts_curi--; // do the same NUL again compflags[sp->ts_complen] = NUL; } else { - sp->ts_flags &= (char_u) ~TSF_DIDSPLIT; + sp->ts_flags &= (uint8_t) ~TSF_DIDSPLIT; } if (try_split || try_compound) { @@ -1641,7 +1641,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun } #endif // Save things to be restored at STATE_SPLITUNDO. - sp->ts_save_badflags = (char_u)su->su_badflags; + sp->ts_save_badflags = (uint8_t)su->su_badflags; PROF_STORE(sp->ts_state) sp->ts_state = STATE_SPLITUNDO; @@ -1652,7 +1652,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun if (!try_compound && !fword_ends) { STRCAT(preword, " "); } - sp->ts_prewordlen = (char_u)strlen(preword); + sp->ts_prewordlen = (uint8_t)strlen(preword); sp->ts_splitoff = sp->ts_twordlen; sp->ts_splitfidx = sp->ts_fidx; @@ -1673,12 +1673,12 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun if (fword_ends) { // Copy the skipped character to preword. memmove(preword + sp->ts_prewordlen, fword + sp->ts_fidx, (size_t)l); - sp->ts_prewordlen = (char_u)(sp->ts_prewordlen + l); + sp->ts_prewordlen = (uint8_t)(sp->ts_prewordlen + l); preword[sp->ts_prewordlen] = NUL; } else { sp->ts_score -= SCORE_SPLIT - SCORE_SUBST; } - sp->ts_fidx = (char_u)(sp->ts_fidx + l); + sp->ts_fidx = (uint8_t)(sp->ts_fidx + l); } // When compounding include compound flag in @@ -1803,7 +1803,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // First byte. sp->ts_tcharidx = 0; sp->ts_tcharlen = MB_BYTE2LEN(c); - sp->ts_fcharstart = (char_u)(sp->ts_fidx - 1); + sp->ts_fcharstart = (uint8_t)(sp->ts_fidx - 1); sp->ts_isdiff = (newscore != 0) ? DIFF_YES : DIFF_NONE; } else if (sp->ts_isdiff == DIFF_INSERT && sp->ts_fidx > 0) { @@ -1816,8 +1816,8 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun if (sp->ts_isdiff == DIFF_YES) { // Correct ts_fidx for the byte length of the // character (we didn't check that before). - sp->ts_fidx = (char_u)(sp->ts_fcharstart - + utfc_ptr2len(fword + sp->ts_fcharstart)); + sp->ts_fidx = (uint8_t)(sp->ts_fcharstart + + utfc_ptr2len(fword + sp->ts_fcharstart)); // For changing a composing character adjust // the score from SCORE_SUBST to @@ -1905,7 +1905,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // results. c = utf_ptr2char(fword + sp->ts_fidx); stack[depth].ts_fidx = - (char_u)(stack[depth].ts_fidx + utfc_ptr2len(fword + sp->ts_fidx)); + (uint8_t)(stack[depth].ts_fidx + utfc_ptr2len(fword + sp->ts_fidx)); if (utf_iscomposing(c)) { stack[depth].ts_score -= SCORE_DEL - SCORE_DELCOMP; } else if (c == utf_ptr2char(fword + stack[depth].ts_fidx)) { @@ -1985,7 +1985,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun // There are following bytes for the same character. // We must find all bytes before trying // delete/insert/swap/etc. - sp->ts_tcharlen = (char_u)fl; + sp->ts_tcharlen = (uint8_t)fl; sp->ts_tcharidx = 1; sp->ts_isdiff = DIFF_INSERT; } @@ -2061,7 +2061,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun fl = utf_char2len(c2); memmove(p, p + n, (size_t)fl); utf_char2bytes(c, p + fl); - stack[depth].ts_fidxtry = (char_u)(sp->ts_fidx + n + fl); + stack[depth].ts_fidxtry = (uint8_t)(sp->ts_fidx + n + fl); } else { // If this swap doesn't work then SWAP3 won't either. PROF_STORE(sp->ts_state) @@ -2118,7 +2118,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun memmove(p, p + n + fl, (size_t)tl); utf_char2bytes(c2, p + tl); utf_char2bytes(c, p + fl + tl); - stack[depth].ts_fidxtry = (char_u)(sp->ts_fidx + n + fl + tl); + stack[depth].ts_fidxtry = (uint8_t)(sp->ts_fidx + n + fl + tl); } else { PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; @@ -2166,7 +2166,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun fl += utf_ptr2len(p + n + fl); memmove(p, p + n, (size_t)fl); utf_char2bytes(c, p + fl); - stack[depth].ts_fidxtry = (char_u)(sp->ts_fidx + n + fl); + stack[depth].ts_fidxtry = (uint8_t)(sp->ts_fidx + n + fl); } else { PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; @@ -2203,7 +2203,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun tl = utf_ptr2len(p + n); memmove(p + tl, p, (size_t)n); utf_char2bytes(c, p); - stack[depth].ts_fidxtry = (char_u)(sp->ts_fidx + n + tl); + stack[depth].ts_fidxtry = (uint8_t)(sp->ts_fidx + n + tl); } else { PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; @@ -2293,7 +2293,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun repextra += tl - fl; } memmove(p, ftp->ft_to, (size_t)tl); - stack[depth].ts_fidxtry = (char_u)(sp->ts_fidx + tl); + stack[depth].ts_fidxtry = (uint8_t)(sp->ts_fidx + tl); stack[depth].ts_tcharlen = 0; break; } @@ -2381,7 +2381,7 @@ static void find_keepcap_word(slang_T *slang, char *fword, char *kword) int c; idx_T lo, hi, m; char *p; - char_u *byts = (char_u *)slang->sl_kbyts; // array with bytes of the words + uint8_t *byts = (uint8_t *)slang->sl_kbyts; // array with bytes of the words idx_T *idxs = slang->sl_kidxs; // array with indexes if (byts == NULL) { @@ -2683,11 +2683,11 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char *ba /// handled already. typedef struct { int16_t sft_score; ///< lowest score used - char_u sft_word[]; ///< soundfolded word + uint8_t sft_word[]; ///< soundfolded word } sftword_T; static sftword_T dumsft; -#define HIKEY2SFT(p) ((sftword_T *)((p) - (dumsft.sft_word - (char_u *)&dumsft))) +#define HIKEY2SFT(p) ((sftword_T *)((p) - (dumsft.sft_word - (uint8_t *)&dumsft))) #define HI2SFT(hi) HIKEY2SFT((hi)->hi_key) /// Prepare for calling suggest_try_soundalike(). @@ -2779,7 +2779,7 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T char theword[MAXWLEN]; int i; int wlen; - char_u *byts; + uint8_t *byts; idx_T *idxs; int n; int wordcount; @@ -2824,7 +2824,7 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T // previous wordnr. orgnr += bytes2offset(&nrline); - byts = (char_u *)slang->sl_fbyts; + byts = (uint8_t *)slang->sl_fbyts; idxs = slang->sl_fidxs; // Lookup the word "orgnr" one of the two tries. @@ -2954,10 +2954,10 @@ static int soundfold_find(slang_T *slang, char *word) { idx_T arridx = 0; int wlen = 0; - char_u *ptr = (char_u *)word; + uint8_t *ptr = (uint8_t *)word; int wordnr = 0; - char_u *byts = (char_u *)slang->sl_sbyts; + uint8_t *byts = (uint8_t *)slang->sl_sbyts; idx_T *idxs = slang->sl_sidxs; for (;;) { @@ -3236,15 +3236,15 @@ static void rescore_one(suginfo_T *su, suggest_T *stp) // Only rescore suggestions that have no sal score yet and do have a // language. if (slang != NULL && !GA_EMPTY(&slang->sl_sal) && !stp->st_had_bonus) { - char_u *p; + char *p; if (slang == su->su_sallang) { - p = (char_u *)su->su_sal_badword; + p = su->su_sal_badword; } else { spell_soundfold(slang, su->su_fbadword, true, sal_badword); - p = (char_u *)sal_badword; + p = sal_badword; } - stp->st_altscore = stp_sal_score(stp, su, slang, (char *)p); + stp->st_altscore = stp_sal_score(stp, su, slang, p); if (stp->st_altscore == SCORE_MAXMAX) { stp->st_altscore = SCORE_BIG; } -- cgit From dde5ce46b2e3e77efc27394b946ef49ce565cd95 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 4 Mar 2023 21:09:50 +0800 Subject: refactor(spell): use uint8_t for "byts" variables (#22519) Avoid casting back and forth. --- src/nvim/spell.c | 16 ++++++++-------- src/nvim/spell_defs.h | 8 ++++---- src/nvim/spellfile.c | 19 ++++++++----------- src/nvim/spellsuggest.c | 12 ++++++------ 4 files changed, 26 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/nvim/spell.c b/src/nvim/spell.c index dbe8ad5763..b514ed694d 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -444,7 +444,7 @@ static void find_word(matchinf_T *mip, int mode) // Check for word with matching case in keep-case tree. ptr = mip->mi_word; flen = 9999; // no case folding, always enough bytes - byts = (uint8_t *)slang->sl_kbyts; + byts = slang->sl_kbyts; idxs = slang->sl_kidxs; if (mode == FIND_KEEPCOMPOUND) { @@ -455,7 +455,7 @@ static void find_word(matchinf_T *mip, int mode) // Check for case-folded in case-folded tree. ptr = mip->mi_fword; flen = mip->mi_fwordlen; // available case-folded bytes - byts = (uint8_t *)slang->sl_fbyts; + byts = slang->sl_fbyts; idxs = slang->sl_fidxs; if (mode == FIND_PREFIX) { @@ -1062,7 +1062,7 @@ static void find_prefix(matchinf_T *mip, int mode) int wlen = 0; slang_T *slang = mip->mi_lp->lp_slang; - uint8_t *byts = (uint8_t *)slang->sl_pbyts; + uint8_t *byts = slang->sl_pbyts; if (byts == NULL) { return; // array is empty } @@ -3194,7 +3194,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg) int curi[MAXWLEN]; char word[MAXWLEN]; int c; - char *byts; + uint8_t *byts; idx_T *idxs; linenr_T lnum = 0; int depth; @@ -3296,7 +3296,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg) // Do one more byte at this node. n = arridx[depth] + curi[depth]; curi[depth]++; - c = (uint8_t)byts[n]; + c = byts[n]; if (c == 0 || depth >= MAXWLEN - 1) { // End of word or reached maximum length, deal with the // word. @@ -3462,7 +3462,7 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char *pat, Direction * has_word_up = true; } - char *byts = slang->sl_pbyts; + uint8_t *byts = slang->sl_pbyts; idx_T *idxs = slang->sl_pidxs; if (byts != NULL) { // array not is empty // Loop over all prefixes, building them byte-by-byte in prefix[]. @@ -3472,7 +3472,7 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char *pat, Direction * curi[0] = 1; while (depth >= 0 && !got_int) { int n = arridx[depth]; - int len = (uint8_t)byts[n]; + int len = byts[n]; if (curi[depth] > len) { // Done all bytes at this node, go up one level. depth--; @@ -3481,7 +3481,7 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char *pat, Direction * // Do one more byte at this node. n += curi[depth]; curi[depth]++; - c = (uint8_t)byts[n]; + c = byts[n]; if (c == 0) { // End of prefix, find out how many IDs there are. int i; diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h index bda43a94d1..1c163071c5 100644 --- a/src/nvim/spell_defs.h +++ b/src/nvim/spell_defs.h @@ -119,12 +119,12 @@ struct slang_S { char *sl_fname; // name of .spl file bool sl_add; // true if it's a .add file. - char *sl_fbyts; // case-folded word bytes + uint8_t *sl_fbyts; // case-folded word bytes long sl_fbyts_len; // length of sl_fbyts idx_T *sl_fidxs; // case-folded word indexes - char *sl_kbyts; // keep-case word bytes + uint8_t *sl_kbyts; // keep-case word bytes idx_T *sl_kidxs; // keep-case word indexes - char *sl_pbyts; // prefix tree word bytes + uint8_t *sl_pbyts; // prefix tree word bytes idx_T *sl_pidxs; // prefix tree word indexes char *sl_info; // infotext string or NULL @@ -172,7 +172,7 @@ struct slang_S { // Info from the .sug file. Loaded on demand. time_t sl_sugtime; // timestamp for .sug file - char *sl_sbyts; // soundfolded word bytes + uint8_t *sl_sbyts; // soundfolded word bytes idx_T *sl_sidxs; // soundfolded word indexes buf_T *sl_sugbuf; // buffer with word number table bool sl_sugloaded; // true when .sug file was loaded or failed to diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index bb2ef1a458..8927b599d0 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -838,9 +838,8 @@ endOK: // Fill in the wordcount fields for a trie. // Returns the total number of words. -static void tree_count_words(const char *byts_in, idx_T *idxs) +static void tree_count_words(const uint8_t *byts, idx_T *idxs) { - const uint8_t *byts= (const uint8_t *)byts_in; int depth; idx_T arridx[MAXWLEN]; int curi[MAXWLEN]; @@ -1675,12 +1674,12 @@ static int *mb_str2wide(char *s) /// @param prefixcnt when "prefixtree" is true: prefix count /// /// @return zero when OK, SP_ value for an error. -static int spell_read_tree(FILE *fd, char **bytsp, long *bytsp_len, idx_T **idxsp, bool prefixtree, - int prefixcnt) +static int spell_read_tree(FILE *fd, uint8_t **bytsp, long *bytsp_len, idx_T **idxsp, + bool prefixtree, int prefixcnt) FUNC_ATTR_NONNULL_ARG(1, 2, 4) { int idx; - char *bp; + uint8_t *bp; idx_T *ip; // The tree size was computed when writing the file, so that we can @@ -1729,10 +1728,9 @@ static int spell_read_tree(FILE *fd, char **bytsp, long *bytsp_len, idx_T **idxs /// @param startidx current index in "byts" and "idxs" /// @param prefixtree true for reading PREFIXTREE /// @param maxprefcondnr maximum for -static idx_T read_tree_node(FILE *fd, char *byts_in, idx_T *idxs, int maxidx, idx_T startidx, +static idx_T read_tree_node(FILE *fd, uint8_t *byts, idx_T *idxs, int maxidx, idx_T startidx, bool prefixtree, int maxprefcondnr) { - uint8_t *byts = (uint8_t *)byts_in; int len; int n; idx_T idx = startidx; @@ -1819,8 +1817,7 @@ static idx_T read_tree_node(FILE *fd, char *byts_in, idx_T *idxs, int maxidx, id idxs[startidx + i] &= ~SHARED_MASK; } else { idxs[startidx + i] = idx; - idx = read_tree_node(fd, (char *)byts, idxs, maxidx, idx, - prefixtree, maxprefcondnr); + idx = read_tree_node(fd, byts, idxs, maxidx, idx, prefixtree, maxprefcondnr); if (idx < 0) { break; } @@ -4955,7 +4952,7 @@ theend: // Build the soundfold trie for language "slang". static int sug_filltree(spellinfo_T *spin, slang_T *slang) { - char_u *byts; + uint8_t *byts; idx_T *idxs; int depth; idx_T arridx[MAXWLEN]; @@ -4975,7 +4972,7 @@ static int sug_filltree(spellinfo_T *spin, slang_T *slang) // Go through the whole case-folded tree, soundfold each word and put it // in the trie. - byts = (char_u *)slang->sl_fbyts; + byts = slang->sl_fbyts; idxs = slang->sl_fidxs; arridx[0] = 0; diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c index 2823e74c2f..2a9b5e1f4e 100644 --- a/src/nvim/spellsuggest.c +++ b/src/nvim/spellsuggest.c @@ -1181,7 +1181,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun if (soundfold) { // Going through the soundfold tree. - byts = fbyts = (uint8_t *)slang->sl_sbyts; + byts = fbyts = slang->sl_sbyts; idxs = fidxs = slang->sl_sidxs; pbyts = NULL; pidxs = NULL; @@ -1190,9 +1190,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun } else { // When there are postponed prefixes we need to use these first. At // the end of the prefix we continue in the case-fold tree. - fbyts = (uint8_t *)slang->sl_fbyts; + fbyts = slang->sl_fbyts; fidxs = slang->sl_fidxs; - pbyts = (uint8_t *)slang->sl_pbyts; + pbyts = slang->sl_pbyts; pidxs = slang->sl_pidxs; if (pbyts != NULL) { byts = pbyts; @@ -2381,7 +2381,7 @@ static void find_keepcap_word(slang_T *slang, char *fword, char *kword) int c; idx_T lo, hi, m; char *p; - uint8_t *byts = (uint8_t *)slang->sl_kbyts; // array with bytes of the words + uint8_t *byts = slang->sl_kbyts; // array with bytes of the words idx_T *idxs = slang->sl_kidxs; // array with indexes if (byts == NULL) { @@ -2824,7 +2824,7 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T // previous wordnr. orgnr += bytes2offset(&nrline); - byts = (uint8_t *)slang->sl_fbyts; + byts = slang->sl_fbyts; idxs = slang->sl_fidxs; // Lookup the word "orgnr" one of the two tries. @@ -2957,7 +2957,7 @@ static int soundfold_find(slang_T *slang, char *word) uint8_t *ptr = (uint8_t *)word; int wordnr = 0; - uint8_t *byts = (uint8_t *)slang->sl_sbyts; + uint8_t *byts = slang->sl_sbyts; idx_T *idxs = slang->sl_sidxs; for (;;) { -- cgit From 2ba224e1526681c1a0b1b2b095b1ef2b0874db48 Mon Sep 17 00:00:00 2001 From: bfredl Date: Sun, 26 Feb 2023 12:51:03 +0100 Subject: refactor(log): reduce compile time LOG_LEVEL granularity --- src/nvim/CMakeLists.txt | 19 ++--- src/nvim/README.md | 6 +- src/nvim/channel.c | 2 +- src/nvim/generators/gen_api_dispatch.lua | 5 +- src/nvim/keycodes.c | 12 --- src/nvim/log.c | 6 +- src/nvim/log.h | 45 +++------- src/nvim/msgpack_rpc/channel.c | 137 +++++++++++++++---------------- src/nvim/state.c | 5 +- src/nvim/ui.c | 6 +- 10 files changed, 103 insertions(+), 140 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 10f44c428c..61530f5a7b 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -373,19 +373,16 @@ else() ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion -Wno-strict-prototypes -Wno-misleading-indentation") endif() -# Log level (MIN_LOG_LEVEL in log.h) +# Log level (NVIM_LOG_DEBUG in log.h) if($ENV{CI}) - set(MIN_LOG_LEVEL 3) -endif() -if("${MIN_LOG_LEVEL}" MATCHES "^$") - # Minimize logging for release-type builds. - target_compile_definitions(main_lib INTERFACE MIN_LOG_LEVEL=$,1,3>) + # Don't debug log on CI, it gets too verbose in the main build log. + # TODO(bfredl): debug log level also exposes some errors with EXITFREE in ASAN build. + set(LOG_DEBUG FALSE) +elseif(LOG_DEBUG) + target_compile_definitions(nvim PRIVATE NVIM_LOG_DEBUG) else() - if(NOT MIN_LOG_LEVEL MATCHES "^[0-3]$") - message(FATAL_ERROR "invalid MIN_LOG_LEVEL: " ${MIN_LOG_LEVEL}) - endif() - message(STATUS "MIN_LOG_LEVEL=${MIN_LOG_LEVEL}") - target_compile_definitions(main_lib INTERFACE MIN_LOG_LEVEL=${MIN_LOG_LEVEL}) + # Minimize logging for release-type builds. + target_compile_definitions(nvim PRIVATE $<$:NVIM_LOG_DEBUG>) endif() if(CLANG_ASAN_UBSAN OR CLANG_MSAN OR CLANG_TSAN) diff --git a/src/nvim/README.md b/src/nvim/README.md index 0951142555..5a6d63c662 100644 --- a/src/nvim/README.md +++ b/src/nvim/README.md @@ -29,17 +29,17 @@ Logs Low-level log messages sink to `$NVIM_LOG_FILE`. -UI events are logged at DEBUG level (`LOGLVL_DBG`). +UI events are logged at DEBUG level. rm -rf build/ - make CMAKE_EXTRA_FLAGS="-DMIN_LOG_LEVEL=0" + make CMAKE_EXTRA_FLAGS="-DLOG_DEBUG" Use `LOG_CALLSTACK()` (Linux only) to log the current stacktrace. To log to an alternate file (e.g. stderr) use `LOG_CALLSTACK_TO_FILE(FILE*)`. Requires `-no-pie` ([ref](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=860394#15)): rm -rf build/ - make CMAKE_EXTRA_FLAGS="-DMIN_LOG_LEVEL=0 -DCMAKE_C_FLAGS=-no-pie" + make CMAKE_EXTRA_FLAGS="-DLOG_DEBUG -DCMAKE_C_FLAGS=-no-pie" Many log messages have a shared prefix, such as "UI" or "RPC". Use the shell to filter the log, e.g. at DEBUG level you might want to exclude UI messages: diff --git a/src/nvim/channel.c b/src/nvim/channel.c index 5f1ad6cb67..f68ee2b39e 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -209,7 +209,7 @@ Channel *channel_alloc(ChannelStreamType type) void channel_create_event(Channel *chan, const char *ext_source) { -#if MIN_LOG_LEVEL <= LOGLVL_INF +#ifdef NVIM_LOG_DEBUG const char *source; if (ext_source) { diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua index 35f6bf8455..a0a67af78d 100644 --- a/src/nvim/generators/gen_api_dispatch.lua +++ b/src/nvim/generators/gen_api_dispatch.lua @@ -257,9 +257,8 @@ for i = 1, #functions do output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Arena* arena, Error *error)') output:write('\n{') - output:write('\n#if MIN_LOG_LEVEL <= LOGLVL_DBG') - output:write('\n logmsg(LOGLVL_DBG, "RPC: ", NULL, -1, true, "ch %" PRIu64 ": invoke ' - ..fn.name..'", channel_id);') + output:write('\n#ifdef NVIM_LOG_DEBUG') + output:write('\n DLOG("RPC: ch %" PRIu64 ": invoke '..fn.name..'", channel_id);') output:write('\n#endif') output:write('\n Object ret = NIL;') -- Declare/initialize variables that will hold converted arguments diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c index 404087fec3..a3edd1465a 100644 --- a/src/nvim/keycodes.c +++ b/src/nvim/keycodes.c @@ -1095,15 +1095,3 @@ void vim_unescape_ks(char *p) } *d = NUL; } - -/// Logs a single key as a human-readable keycode. -void log_key(int log_level, int key) -{ - if (log_level < MIN_LOG_LEVEL) { - return; - } - char *keyname = key == K_EVENT - ? "K_EVENT" - : (char *)get_special_key_name(key, mod_mask); - LOG(log_level, "input: %s", keyname); -} diff --git a/src/nvim/log.c b/src/nvim/log.c index 2c214aa32d..77eeb09fec 100644 --- a/src/nvim/log.c +++ b/src/nvim/log.c @@ -141,9 +141,13 @@ bool logmsg(int log_level, const char *context, const char *func_name, int line_ return false; } - if (log_level < MIN_LOG_LEVEL) { +#ifndef NVIM_LOG_DEBUG + // This should rarely happen (callsites are compiled out), but to be sure. + // TODO(bfredl): allow log levels to be configured at runtime + if (log_level < LOGLVL_WRN) { return false; } +#endif #ifdef EXITFREE // Logging after we've already started freeing all our memory will only cause diff --git a/src/nvim/log.h b/src/nvim/log.h index 14d46c2ea7..6866680de2 100644 --- a/src/nvim/log.h +++ b/src/nvim/log.h @@ -17,54 +17,29 @@ # define NVIM_PROBE(name, n, ...) #endif -#define LOGLVL_TRC 0 #define LOGLVL_DBG 1 #define LOGLVL_INF 2 #define LOGLVL_WRN 3 #define LOGLVL_ERR 4 -#define DLOG(...) -#define DLOGN(...) -#define ILOG(...) -#define ILOGN(...) -#define WLOG(...) -#define WLOGN(...) -#define ELOG(...) -#define ELOGN(...) - -#ifndef MIN_LOG_LEVEL -# define MIN_LOG_LEVEL LOGLVL_INF -#endif - #define LOG(level, ...) logmsg((level), NULL, __func__, __LINE__, true, __VA_ARGS__) -#if MIN_LOG_LEVEL <= LOGLVL_DBG -# undef DLOG -# undef DLOGN +#ifdef NVIM_LOG_DEBUG # define DLOG(...) logmsg(LOGLVL_DBG, NULL, __func__, __LINE__, true, __VA_ARGS__) # define DLOGN(...) logmsg(LOGLVL_DBG, NULL, __func__, __LINE__, false, __VA_ARGS__) -#endif - -#if MIN_LOG_LEVEL <= LOGLVL_INF -# undef ILOG -# undef ILOGN # define ILOG(...) logmsg(LOGLVL_INF, NULL, __func__, __LINE__, true, __VA_ARGS__) # define ILOGN(...) logmsg(LOGLVL_INF, NULL, __func__, __LINE__, false, __VA_ARGS__) +#else +# define DLOG(...) +# define DLOGN(...) +# define ILOG(...) +# define ILOGN(...) #endif -#if MIN_LOG_LEVEL <= LOGLVL_WRN -# undef WLOG -# undef WLOGN -# define WLOG(...) logmsg(LOGLVL_WRN, NULL, __func__, __LINE__, true, __VA_ARGS__) -# define WLOGN(...) logmsg(LOGLVL_WRN, NULL, __func__, __LINE__, false, __VA_ARGS__) -#endif - -#if MIN_LOG_LEVEL <= LOGLVL_ERR -# undef ELOG -# undef ELOGN -# define ELOG(...) logmsg(LOGLVL_ERR, NULL, __func__, __LINE__, true, __VA_ARGS__) -# define ELOGN(...) logmsg(LOGLVL_ERR, NULL, __func__, __LINE__, false, __VA_ARGS__) -#endif +#define WLOG(...) logmsg(LOGLVL_WRN, NULL, __func__, __LINE__, true, __VA_ARGS__) +#define WLOGN(...) logmsg(LOGLVL_WRN, NULL, __func__, __LINE__, false, __VA_ARGS__) +#define ELOG(...) logmsg(LOGLVL_ERR, NULL, __func__, __LINE__, true, __VA_ARGS__) +#define ELOGN(...) logmsg(LOGLVL_ERR, NULL, __func__, __LINE__, false, __VA_ARGS__) #ifdef HAVE_EXECINFO_BACKTRACE # define LOG_CALLSTACK() log_callstack(__func__, __LINE__) diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index f8be0d4c8d..96b4bf5c3a 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -39,7 +39,73 @@ #include "nvim/ui.h" #include "nvim/ui_client.h" -#if MIN_LOG_LEVEL > LOGLVL_DBG +#ifdef NVIM_LOG_DEBUG +# define REQ "[request] " +# define RES "[response] " +# define NOT "[notify] " +# define ERR "[error] " + +// Cannot define array with negative offsets, so this one is needed to be added +// to MSGPACK_UNPACK_\* values. +# define MUR_OFF 2 + +static const char *const msgpack_error_messages[] = { + [MSGPACK_UNPACK_EXTRA_BYTES + MUR_OFF] = "extra bytes found", + [MSGPACK_UNPACK_CONTINUE + MUR_OFF] = "incomplete string", + [MSGPACK_UNPACK_PARSE_ERROR + MUR_OFF] = "parse error", + [MSGPACK_UNPACK_NOMEM_ERROR + MUR_OFF] = "not enough memory", +}; + +static void log_close(FILE *f) +{ + fputc('\n', f); + fflush(f); + fclose(f); + log_unlock(); +} + +static void log_server_msg(uint64_t channel_id, msgpack_sbuffer *packed) +{ + msgpack_unpacked unpacked; + msgpack_unpacked_init(&unpacked); + DLOGN("RPC ->ch %" PRIu64 ": ", channel_id); + const msgpack_unpack_return result = + msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL); + switch (result) { + case MSGPACK_UNPACK_SUCCESS: { + uint64_t type = unpacked.data.via.array.ptr[0].via.u64; + log_lock(); + FILE *f = open_log_file(); + fprintf(f, type ? (type == 1 ? RES : NOT) : REQ); + msgpack_object_print(f, unpacked.data); + log_close(f); + msgpack_unpacked_destroy(&unpacked); + break; + } + case MSGPACK_UNPACK_EXTRA_BYTES: + case MSGPACK_UNPACK_CONTINUE: + case MSGPACK_UNPACK_PARSE_ERROR: + case MSGPACK_UNPACK_NOMEM_ERROR: { + log_lock(); + FILE *f = open_log_file(); + fprintf(f, ERR); + fprintf(f, "%s", msgpack_error_messages[result + MUR_OFF]); + log_close(f); + break; + } + } +} + +static void log_client_msg(uint64_t channel_id, bool is_request, const char *name) +{ + DLOGN("RPC <-ch %" PRIu64 ": ", channel_id); + log_lock(); + FILE *f = open_log_file(); + fprintf(f, "%s: %s", is_request ? REQ : RES, name); + log_close(f); +} + +#else # define log_client_msg(...) # define log_server_msg(...) #endif @@ -71,7 +137,7 @@ void rpc_start(Channel *channel) if (channel->streamtype != kChannelStreamInternal) { Stream *out = channel_outstream(channel); -#if MIN_LOG_LEVEL <= LOGLVL_DBG +#ifdef NVIM_LOG_DEBUG Stream *in = channel_instream(channel); DLOG("rpc ch %" PRIu64 " in-stream=%p out-stream=%p", channel->id, (void *)in, (void *)out); @@ -668,70 +734,3 @@ const char *rpc_client_name(Channel *chan) return NULL; } - -#if MIN_LOG_LEVEL <= LOGLVL_DBG -# define REQ "[request] " -# define RES "[response] " -# define NOT "[notify] " -# define ERR "[error] " - -// Cannot define array with negative offsets, so this one is needed to be added -// to MSGPACK_UNPACK_\* values. -# define MUR_OFF 2 - -static const char *const msgpack_error_messages[] = { - [MSGPACK_UNPACK_EXTRA_BYTES + MUR_OFF] = "extra bytes found", - [MSGPACK_UNPACK_CONTINUE + MUR_OFF] = "incomplete string", - [MSGPACK_UNPACK_PARSE_ERROR + MUR_OFF] = "parse error", - [MSGPACK_UNPACK_NOMEM_ERROR + MUR_OFF] = "not enough memory", -}; - -static void log_server_msg(uint64_t channel_id, msgpack_sbuffer *packed) -{ - msgpack_unpacked unpacked; - msgpack_unpacked_init(&unpacked); - DLOGN("RPC ->ch %" PRIu64 ": ", channel_id); - const msgpack_unpack_return result = - msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL); - switch (result) { - case MSGPACK_UNPACK_SUCCESS: { - uint64_t type = unpacked.data.via.array.ptr[0].via.u64; - log_lock(); - FILE *f = open_log_file(); - fprintf(f, type ? (type == 1 ? RES : NOT) : REQ); - msgpack_object_print(f, unpacked.data); - log_close(f); - msgpack_unpacked_destroy(&unpacked); - break; - } - case MSGPACK_UNPACK_EXTRA_BYTES: - case MSGPACK_UNPACK_CONTINUE: - case MSGPACK_UNPACK_PARSE_ERROR: - case MSGPACK_UNPACK_NOMEM_ERROR: { - log_lock(); - FILE *f = open_log_file(); - fprintf(f, ERR); - fprintf(f, "%s", msgpack_error_messages[result + MUR_OFF]); - log_close(f); - break; - } - } -} - -static void log_client_msg(uint64_t channel_id, bool is_request, const char *name) -{ - DLOGN("RPC <-ch %" PRIu64 ": ", channel_id); - log_lock(); - FILE *f = open_log_file(); - fprintf(f, "%s: %s", is_request ? REQ : RES, name); - log_close(f); -} - -static void log_close(FILE *f) -{ - fputc('\n', f); - fflush(f); - fclose(f); - log_unlock(); -} -#endif diff --git a/src/nvim/state.c b/src/nvim/state.c index 9ba5f81776..40ee9af5ac 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -92,8 +92,9 @@ getkey: may_sync_undo(); } -#if MIN_LOG_LEVEL <= LOGLVL_DBG - log_key(LOGLVL_DBG, key); +#ifdef NVIM_LOG_DEBUG + char *keyname = key == K_EVENT ? "K_EVENT" : (char *)get_special_key_name(key, mod_mask); + DLOG("input: %s", keyname); #endif int execute_result = s->execute(s, key); diff --git a/src/nvim/ui.c b/src/nvim/ui.c index ce1a57350a..45959b7b67 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -63,9 +63,7 @@ static int pending_has_mouse = -1; static Array call_buf = ARRAY_DICT_INIT; -#if MIN_LOG_LEVEL > LOGLVL_DBG -# define ui_log(funname) -#else +#ifdef NVIM_LOG_DEBUG static size_t uilog_seen = 0; static const char *uilog_last_event = NULL; @@ -89,6 +87,8 @@ static void ui_log(const char *funname) uilog_last_event = funname; } } +#else +# define ui_log(funname) #endif // UI_CALL invokes a function on all registered UI instances. -- cgit From 39842be8cd8808c7da2638a6cc84d7c3fe40b996 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 5 Mar 2023 07:09:28 +0800 Subject: fix(extmarks): don't leak memory on error (#22507) --- src/nvim/api/extmark.c | 3 +-- src/nvim/decoration.c | 17 +++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 845a4c7dbe..9e03cc8676 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -809,8 +809,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer return (Integer)id; error: - clear_virttext(&decor.virt_text); - xfree(decor.sign_text); + decor_clear(&decor); return 0; } diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index c98ffbeefb..7e47565247 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -112,15 +112,20 @@ void decor_remove(buf_T *buf, int row, int row2, Decoration *decor) decor_free(decor); } +void decor_clear(Decoration *decor) +{ + clear_virttext(&decor->virt_text); + for (size_t i = 0; i < kv_size(decor->virt_lines); i++) { + clear_virttext(&kv_A(decor->virt_lines, i).line); + } + kv_destroy(decor->virt_lines); + xfree(decor->sign_text); +} + void decor_free(Decoration *decor) { if (decor) { - clear_virttext(&decor->virt_text); - for (size_t i = 0; i < kv_size(decor->virt_lines); i++) { - clear_virttext(&kv_A(decor->virt_lines, i).line); - } - kv_destroy(decor->virt_lines); - xfree(decor->sign_text); + decor_clear(decor); xfree(decor); } } -- cgit From 089f962d6a18bd91d89998e16834b822ab2adf9f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 5 Mar 2023 08:08:04 +0800 Subject: vim-patch:9.0.1378: illegal memory access when using virtual editing (#22527) Problem: Illegal memory access when using virtual editing. Solution: Make sure "startspaces" is not negative. https://github.com/vim/vim/commit/c99cbf8f289bdda5d4a77d7ec415850a520330ba Co-authored-by: Bram Moolenaar --- src/nvim/ops.c | 6 ++++-- src/nvim/testdir/test_virtualedit.vim | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 884eeef433..6929189750 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -2684,8 +2684,10 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) getvcol(curwin, &oap->start, &cs, NULL, &ce); if (ce != cs && oap->start.coladd > 0) { // Part of a tab selected -- but don't double-count it. - bd.startspaces = (ce - cs + 1) - - oap->start.coladd; + bd.startspaces = (ce - cs + 1) - oap->start.coladd; + if (bd.startspaces < 0) { + bd.startspaces = 0; + } startcol++; } } diff --git a/src/nvim/testdir/test_virtualedit.vim b/src/nvim/testdir/test_virtualedit.vim index 20a5f87517..a2baf276ac 100644 --- a/src/nvim/testdir/test_virtualedit.vim +++ b/src/nvim/testdir/test_virtualedit.vim @@ -88,6 +88,16 @@ func Test_edit_change() set virtualedit= endfunc +func Test_edit_special_char() + new + se ve=all + norm a0 + sil! exe "norm o00000\k Date: Sun, 5 Mar 2023 08:34:58 +0800 Subject: test(old): make getting an unused PID work (#22529) --- src/nvim/testdir/test_swap.vim | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/nvim/testdir/test_swap.vim b/src/nvim/testdir/test_swap.vim index ceadc1d85a..4241f4fd69 100644 --- a/src/nvim/testdir/test_swap.vim +++ b/src/nvim/testdir/test_swap.vim @@ -435,6 +435,12 @@ func s:get_unused_pid(base) if job_status(j) ==# 'dead' return job_info(j).process endif + elseif has('nvim') + let j = jobstart('echo') + let pid = jobpid(j) + if jobwait([j])[0] >= 0 + return pid + endif endif " Must add four for MS-Windows to see it as a different one. return a:base + 4 -- cgit From 419819b6245e120aba8897e3ddea711b2cd0246c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 5 Mar 2023 09:18:42 +0800 Subject: vim-patch:9.0.1380: CTRL-X on 2**64 subtracts two (#22530) Problem: CTRL-X on 2**64 subtracts two. (James McCoy) Solution: Correct computation for large number. (closes vim/vim#12103) https://github.com/vim/vim/commit/5fb78c3fa5c996c08a65431d698bd2c251eef5c7 Co-authored-by: Bram Moolenaar --- src/nvim/charset.c | 12 +++++++++++- src/nvim/eval.c | 2 +- src/nvim/eval/decode.c | 4 ++-- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/typval.c | 2 +- src/nvim/ex_cmds.c | 4 ++-- src/nvim/ex_getln.c | 4 ++-- src/nvim/keycodes.c | 4 ++-- src/nvim/ops.c | 9 ++++++--- src/nvim/option.c | 2 +- src/nvim/testdir/test_increment.vim | 16 ++++++++++++++++ src/nvim/viml/parser/expressions.c | 4 ++-- 12 files changed, 47 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/nvim/charset.c b/src/nvim/charset.c index bf18d110c0..b792ae5ece 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1500,9 +1500,10 @@ bool vim_isblankline(char *lbuf) /// @param strict If true, fail if the number has unexpected trailing /// alphanumeric chars: *len is set to 0 and nothing else is /// returned. +/// @param overflow When not NULL, set to true for overflow. void vim_str2nr(const char *const start, int *const prep, int *const len, const int what, varnumber_T *const nptr, uvarnumber_T *const unptr, const int maxlen, - const bool strict) + const bool strict, bool *const overflow) FUNC_ATTR_NONNULL_ARG(1) { const char *ptr = start; @@ -1626,6 +1627,9 @@ void vim_str2nr(const char *const start, int *const prep, int *const len, const un = (base) * un + digit; \ } else { \ un = UVARNUMBER_MAX; \ + if (overflow != NULL) { \ + *overflow = true; \ + } \ } \ ptr++; \ } \ @@ -1664,12 +1668,18 @@ vim_str2nr_proceed: // avoid ubsan error for overflow if (un > VARNUMBER_MAX) { *nptr = VARNUMBER_MIN; + if (overflow != NULL) { + *overflow = true; + } } else { *nptr = -(varnumber_T)un; } } else { if (un > VARNUMBER_MAX) { un = VARNUMBER_MAX; + if (overflow != NULL) { + *overflow = true; + } } *nptr = (varnumber_T)un; } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 67fede1aea..e10607772a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -3678,7 +3678,7 @@ static int get_number_tv(char **arg, typval_T *rettv, bool evaluate, bool want_s // decimal, hex or octal number int len; varnumber_T n; - vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, true); + vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, true, NULL); if (len == 0) { if (evaluate) { semsg(_(e_invexpr2), *arg); diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index f57d06c83b..6ce9309677 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -439,7 +439,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, t += 4; uvarnumber_T ch; vim_str2nr(ubuf, NULL, NULL, - STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true); + STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true, NULL); if (ch == 0) { hasnul = true; } @@ -608,7 +608,7 @@ parse_json_number_check: // Convert integer varnumber_T nr; int num_len; - vim_str2nr(s, NULL, &num_len, 0, &nr, NULL, (int)(p - s), true); + vim_str2nr(s, NULL, &num_len, 0, &nr, NULL, (int)(p - s), true, NULL); if ((int)exp_num_len != num_len) { semsg(_("E685: internal error: while converting number \"%.*s\" " "to integer vim_str2nr consumed %i bytes in place of %zu"), diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 4208c5ca46..3a7da21606 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8033,7 +8033,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) break; } varnumber_T n; - vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, false); + vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, false, NULL); // Text after the number is silently ignored. if (isneg) { rettv->vval.v_number = -n; diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 7d49049b0c..d077998dae 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -3890,7 +3890,7 @@ varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error) case VAR_STRING: { varnumber_T n = 0; if (tv->vval.v_string != NULL) { - vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0, false); + vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0, false, NULL); } return n; } diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 67d1a1e2f7..a12c2a15b4 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -580,7 +580,7 @@ void ex_sort(exarg_T *eap) } if (sort_nr || sort_flt) { - // Make sure vim_str2nr doesn't read any digits past the end + // Make sure vim_str2nr() doesn't read any digits past the end // of the match, by temporarily terminating the string there s2 = s + end_col; c = *s2; @@ -605,7 +605,7 @@ void ex_sort(exarg_T *eap) } else { nrs[lnum - eap->line1].st_u.num.is_number = true; vim_str2nr(s, NULL, NULL, sort_what, - &nrs[lnum - eap->line1].st_u.num.value, NULL, 0, false); + &nrs[lnum - eap->line1].st_u.num.value, NULL, 0, false, NULL); } } else { s = skipwhite(p); diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 4b56dfdd3f..e4cb7a5a76 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -4241,7 +4241,7 @@ int get_list_range(char **str, int *num1, int *num2) *str = skipwhite((*str)); if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range - vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false); + vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false, NULL); *str += len; *num1 = (int)num; first = true; @@ -4249,7 +4249,7 @@ int get_list_range(char **str, int *num1, int *num2) *str = skipwhite((*str)); if (**str == ',') { // parse "to" part of range *str = skipwhite((*str) + 1); - vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false); + vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false, NULL); if (len > 0) { *num2 = (int)num; *str = skipwhite((*str) + len); diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c index a3edd1465a..f3d379c2e9 100644 --- a/src/nvim/keycodes.c +++ b/src/nvim/keycodes.c @@ -673,7 +673,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m if (end - bp > 3 && bp[0] == 't' && bp[1] == '_') { bp += 3; // skip t_xx, xx may be '-' or '>' } else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) { - vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true); + vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true, NULL); if (l == 0) { emsg(_(e_invarg)); return 0; @@ -704,7 +704,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m if (STRNICMP(last_dash + 1, "char-", 5) == 0 && ascii_isdigit(last_dash[6])) { // or or - vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, true); + vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, true, NULL); if (l == 0) { emsg(_(e_invarg)); return 0; diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 6929189750..1a33ae8bbf 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -4658,11 +4658,12 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) : length); } + bool overflow = false; vim_str2nr(ptr + col, &pre, &length, 0 + (do_bin ? STR2NR_BIN : 0) + (do_oct ? STR2NR_OCT : 0) + (do_hex ? STR2NR_HEX : 0), - NULL, &n, maxlen, false); + NULL, &n, maxlen, false, &overflow); // ignore leading '-' for hex, octal and bin numbers if (pre && negative) { @@ -4682,8 +4683,10 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) oldn = n; - n = subtract ? n - (uvarnumber_T)Prenum1 - : n + (uvarnumber_T)Prenum1; + if (!overflow) { // if number is too big don't add/subtract + n = subtract ? n - (uvarnumber_T)Prenum1 + : n + (uvarnumber_T)Prenum1; + } // handle wraparound for decimal numbers if (!pre) { diff --git a/src/nvim/option.c b/src/nvim/option.c index 04cf7eede4..be82cf22c7 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -814,7 +814,7 @@ static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, co } else if (*arg == '-' || ascii_isdigit(*arg)) { int i; // Allow negative, octal and hex numbers. - vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true); + vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true, NULL); if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) { *errmsg = e_number_required_after_equal; return; diff --git a/src/nvim/testdir/test_increment.vim b/src/nvim/testdir/test_increment.vim index 3c2b88ef9f..433b2b4471 100644 --- a/src/nvim/testdir/test_increment.vim +++ b/src/nvim/testdir/test_increment.vim @@ -841,6 +841,22 @@ func Test_increment_unsigned() set nrformats-=unsigned endfunc +func Test_in_decrement_large_number() + " NOTE: 18446744073709551616 == 2^64 + call setline(1, '18446744073709551616') + exec "norm! gg0\" + call assert_equal('18446744073709551615', getline(1)) + + exec "norm! gg0\" + call assert_equal('18446744073709551614', getline(1)) + + exec "norm! gg0\" + call assert_equal('18446744073709551615', getline(1)) + + exec "norm! gg0\" + call assert_equal('-18446744073709551615', getline(1)) +endfunc + func Test_normal_increment_with_virtualedit() set virtualedit=all diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c index 53224f2ee9..35d9de069b 100644 --- a/src/nvim/viml/parser/expressions.c +++ b/src/nvim/viml/parser/expressions.c @@ -376,7 +376,7 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags) } if (exp_start) { vim_str2nr(pline.data + exp_start, NULL, NULL, 0, NULL, &exp_part, - (int)(ret.len - exp_start), false); + (int)(ret.len - exp_start), false, NULL); } if (exp_negative) { exp_part += frac_size; @@ -394,7 +394,7 @@ LexExprToken viml_pexpr_next_token(ParserState *const pstate, const int flags) int len; int prep; vim_str2nr(pline.data, &prep, &len, STR2NR_ALL, NULL, - &ret.data.num.val.integer, (int)pline.size, false); + &ret.data.num.val.integer, (int)pline.size, false, NULL); ret.len = (size_t)len; const uint8_t bases[] = { [0] = 10, -- cgit From 1cfe83c2a2d5d1d5dcc37bdcdb9dba4107e41de7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 5 Mar 2023 14:47:51 +0800 Subject: vim-patch:9.0.0736: quickfix listing does not handle very long messages Problem: Quickfix listing does not handle very long messages. Solution: Use a growarray instead of a fixed size buffer. (Yegappan Lakshmanan, closes vim/vim#11357) https://github.com/vim/vim/commit/f8412c9d7cc487dacf47a217ae947da68a525c53 Override Test_very_long_error_line() with a rewrite that doesn't use deferred delete and string interpolation. Co-authored-by: Yegappan Lakshmanan --- src/nvim/quickfix.c | 147 ++++++++++++++++++------------------- src/nvim/testdir/test_quickfix.vim | 60 +++++++++++++++ 2 files changed, 130 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 5518fdfa51..af2d10798a 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -2807,13 +2807,15 @@ static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf update_screen(); } } - snprintf(IObuff, IOSIZE, _("(%d of %d)%s%s: "), qf_index, - qf_get_curlist(qi)->qf_count, - qf_ptr->qf_cleared ? _(" (line deleted)") : "", - qf_types(qf_ptr->qf_type, qf_ptr->qf_nr)); + vim_snprintf(IObuff, IOSIZE, _("(%d of %d)%s%s: "), qf_index, + qf_get_curlist(qi)->qf_count, + qf_ptr->qf_cleared ? _(" (line deleted)") : "", + qf_types(qf_ptr->qf_type, qf_ptr->qf_nr)); // Add the message, skipping leading whitespace and newlines. - int len = (int)strlen(IObuff); - qf_fmt_text(skipwhite(qf_ptr->qf_text), IObuff + len, IOSIZE - len); + garray_T ga; + ga_init(&ga, 1, 256); + ga_concat(&ga, IObuff); + qf_fmt_text(&ga, skipwhite(qf_ptr->qf_text)); // Output the message. Overwrite to avoid scrolling when the 'O' // flag is present in 'shortmess'; But when not jumping, print the @@ -2825,8 +2827,9 @@ static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf msg_scroll = false; } msg_ext_set_kind("quickfix"); - msg_attr_keep(IObuff, 0, true, false); + msg_attr_keep(ga.ga_data, 0, true, false); msg_scroll = (int)i; + ga_clear(&ga); } /// Find a usable window for opening a file from the quickfix/location list. If @@ -3086,41 +3089,32 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel) if (qfp->qf_lnum != 0) { msg_puts_attr(":", qfSepAttr); } + garray_T ga; + ga_init(&ga, 1, 256); if (qfp->qf_lnum == 0) { - IObuff[0] = NUL; + ga_append(&ga, NUL); } else { - qf_range_text(qfp, IObuff, IOSIZE); + qf_range_text(&ga, qfp); } - vim_snprintf(IObuff + strlen(IObuff), IOSIZE, "%s", qf_types(qfp->qf_type, qfp->qf_nr)); - msg_puts_attr((const char *)IObuff, qfLineAttr); + ga_concat(&ga, qf_types(qfp->qf_type, qfp->qf_nr)); + ga_append(&ga, NUL); + msg_puts_attr(ga.ga_data, qfLineAttr); + ga_clear(&ga); msg_puts_attr(":", qfSepAttr); if (qfp->qf_pattern != NULL) { - qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE); - msg_puts((const char *)IObuff); + qf_fmt_text(&ga, qfp->qf_pattern); + msg_puts(ga.ga_data); + ga_clear(&ga); msg_puts_attr(":", qfSepAttr); } msg_puts(" "); - char *tbuf = IObuff; - size_t tbuflen = IOSIZE; - size_t len = strlen(qfp->qf_text) + 3; - - if (len > IOSIZE) { - tbuf = xmalloc(len); - tbuflen = len; - } - // Remove newlines and leading whitespace from the text. For an // unrecognized line keep the indent, the compiler may mark a word // with ^^^^. - qf_fmt_text((fname != NULL || qfp->qf_lnum != 0) - ? skipwhite(qfp->qf_text) : qfp->qf_text, - tbuf, (int)tbuflen); - msg_prt_line(tbuf, false); - - if (tbuf != IObuff) { - xfree(tbuf); - } + qf_fmt_text(&ga, (fname != NULL || qfp->qf_lnum != 0) ? skipwhite(qfp->qf_text) : qfp->qf_text); + msg_prt_line(ga.ga_data, false); + ga_clear(&ga); } // ":clist": list all errors @@ -3197,49 +3191,54 @@ void qf_list(exarg_T *eap) } } -// Remove newlines and leading whitespace from an error message. -// Put the result in "buf[bufsize]". -static void qf_fmt_text(const char *restrict text, char *restrict buf, int bufsize) +/// Remove newlines and leading whitespace from an error message. +/// Add the result to the grow array "gap". +static void qf_fmt_text(garray_T *gap, const char *restrict text) FUNC_ATTR_NONNULL_ALL { - int i; const char *p = (char *)text; - for (i = 0; *p != NUL && i < bufsize - 1; i++) { + while (*p != NUL) { if (*p == '\n') { - buf[i] = ' '; + ga_append(gap, ' '); while (*++p != NUL) { if (!ascii_iswhite(*p) && *p != '\n') { break; } } } else { - buf[i] = *p++; + ga_append(gap, (uint8_t)(*p++)); } } - buf[i] = NUL; + + ga_append(gap, NUL); } -// Range information from lnum, col, end_lnum, and end_col. -// Put the result in "buf[bufsize]". -static void qf_range_text(const qfline_T *qfp, char *buf, int bufsize) +/// Add the range information from the lnum, col, end_lnum, and end_col values +/// of a quickfix entry to the grow array "gap". +static void qf_range_text(garray_T *gap, const qfline_T *qfp) { - vim_snprintf(buf, (size_t)bufsize, "%" PRIdLINENR, qfp->qf_lnum); - int len = (int)strlen(buf); + char *const buf = IObuff; + const size_t bufsize = IOSIZE; + + vim_snprintf(buf, bufsize, "%" PRIdLINENR, qfp->qf_lnum); + size_t len = strlen(buf); if (qfp->qf_end_lnum > 0 && qfp->qf_lnum != qfp->qf_end_lnum) { - vim_snprintf(buf + len, (size_t)(bufsize - len), "-%" PRIdLINENR, qfp->qf_end_lnum); - len += (int)strlen(buf + len); + vim_snprintf(buf + len, bufsize - len, "-%" PRIdLINENR, qfp->qf_end_lnum); + len += strlen(buf + len); } if (qfp->qf_col > 0) { - vim_snprintf(buf + len, (size_t)(bufsize - len), " col %d", qfp->qf_col); - len += (int)strlen(buf + len); + vim_snprintf(buf + len, bufsize - len, " col %d", qfp->qf_col); + len += strlen(buf + len); if (qfp->qf_end_col > 0 && qfp->qf_col != qfp->qf_end_col) { - vim_snprintf(buf + len, (size_t)(bufsize - len), "-%d", qfp->qf_end_col); - len += (int)strlen(buf + len); + vim_snprintf(buf + len, bufsize - len, "-%d", qfp->qf_end_col); + len += strlen(buf + len); } } buf[len] = NUL; + + ga_concat_len(gap, buf, len); } /// Display information (list number, list size and the title) about a @@ -3945,21 +3944,22 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli char *dirname, char *qftf_str, bool first_bufline) FUNC_ATTR_NONNULL_ARG(1, 2, 4, 5) { + garray_T ga; + ga_init(&ga, 1, 256); + // If the 'quickfixtextfunc' function returned a non-empty custom string // for this entry, then use it. if (qftf_str != NULL && *qftf_str != NUL) { - xstrlcpy(IObuff, qftf_str, IOSIZE); + ga_concat(&ga, qftf_str); } else { buf_T *errbuf; - int len; if (qfp->qf_module != NULL) { - xstrlcpy(IObuff, qfp->qf_module, IOSIZE); - len = (int)strlen(IObuff); + ga_concat(&ga, qfp->qf_module); } else if (qfp->qf_fnum != 0 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL && errbuf->b_fname != NULL) { if (qfp->qf_type == 1) { // :helpgrep - xstrlcpy(IObuff, path_tail(errbuf->b_fname), IOSIZE); + ga_concat(&ga, path_tail(errbuf->b_fname)); } else { // Shorten the file name if not done already. // For optimization, do this only for the first entry in a @@ -3972,42 +3972,35 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli } shorten_buf_fname(errbuf, dirname, false); } - xstrlcpy(IObuff, errbuf->b_fname, IOSIZE); + ga_concat(&ga, errbuf->b_fname); } - len = (int)strlen(IObuff); - } else { - len = 0; - } - if (len < IOSIZE - 1) { - IObuff[len++] = '|'; } - if (qfp->qf_lnum > 0) { - qf_range_text(qfp, IObuff + len, IOSIZE - len); - len += (int)strlen(IObuff + len); - snprintf(IObuff + len, (size_t)(IOSIZE - len), "%s", qf_types(qfp->qf_type, - qfp->qf_nr)); - len += (int)strlen(IObuff + len); + ga_append(&ga, '|'); + + if (qfp->qf_lnum > 0) { + qf_range_text(&ga, qfp); + ga_concat(&ga, qf_types(qfp->qf_type, qfp->qf_nr)); } else if (qfp->qf_pattern != NULL) { - qf_fmt_text(qfp->qf_pattern, IObuff + len, IOSIZE - len); - len += (int)strlen(IObuff + len); - } - if (len < IOSIZE - 2) { - IObuff[len++] = '|'; - IObuff[len++] = ' '; + qf_fmt_text(&ga, qfp->qf_pattern); } + ga_append(&ga, '|'); + ga_append(&ga, ' '); // Remove newlines and leading whitespace from the text. // For an unrecognized line keep the indent, the compiler may // mark a word with ^^^^. - qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text, - IObuff + len, IOSIZE - len); + qf_fmt_text(&ga, ga.ga_len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text); } - if (ml_append_buf(buf, lnum, IObuff, - (colnr_T)strlen(IObuff) + 1, false) == FAIL) { + ga_append(&ga, NUL); + + if (ml_append_buf(buf, lnum, ga.ga_data, ga.ga_len + 1, false) == FAIL) { return FAIL; } + + ga_clear(&ga); + return OK; } diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 8dc4173d60..fedc486e62 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -6220,6 +6220,66 @@ func Test_loclist_replace_autocmd() call setloclist(0, [], 'f') endfunc +" Test for a very long error line and a very long information line +func Test_very_long_error_line() + let msg = repeat('abcdefghijklmn', 146) + let emsg = 'Xlonglines.c:1:' . msg + call writefile([msg, emsg], 'Xerror', 'D') + cfile Xerror + cwindow + call assert_equal($'|| {msg}', getline(1)) + call assert_equal($'Xlonglines.c|1| {msg}', getline(2)) + cclose + + let l = execute('clist!')->split("\n") + call assert_equal([$' 1: {msg}', $' 2 Xlonglines.c:1: {msg}'], l) + + let l = execute('cc')->split("\n") + call assert_equal([$'(2 of 2): {msg}'], l) + + call setqflist([], 'f') +endfunc + +" The test depends on deferred delete and string interpolation, which haven't +" been ported, so override it with a rewrite that doesn't use these features. +func! Test_very_long_error_line() + let msg = repeat('abcdefghijklmn', 146) + let emsg = 'Xlonglines.c:1:' . msg + call writefile([msg, emsg], 'Xerror') + cfile Xerror + call delete('Xerror') + cwindow + call assert_equal('|| ' .. msg, getline(1)) + call assert_equal('Xlonglines.c|1| ' .. msg, getline(2)) + cclose + + let l = execute('clist!')->split("\n") + call assert_equal([' 1: ' .. msg, ' 2 Xlonglines.c:1: ' .. msg], l) + + let l = execute('cc')->split("\n") + call assert_equal(['(2 of 2): ' .. msg], l) + + call setqflist([], 'f') +endfunc + +" In the quickfix window, spaces at the beginning of an informational line +" should not be removed but should be removed from an error line. +func Test_info_line_with_space() + cexpr ["a.c:20:12: error: expected ';' before ':' token", + \ ' 20 | Afunc():', '', ' | ^'] + copen + call assert_equal(["a.c|20 col 12| error: expected ';' before ':' token", + \ '|| 20 | Afunc():', '|| ', + \ '|| | ^'], getline(1, '$')) + cclose + + let l = execute('clist!')->split("\n") + call assert_equal([" 1 a.c:20 col 12: error: expected ';' before ':' token", + \ ' 2: 20 | Afunc():', ' 3: ', ' 4: | ^'], l) + + call setqflist([], 'f') +endfunc + func s:QfTf(_) endfunc -- cgit From 1adad44b7ce6574f505f4cf5df3c8e21c0747f93 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 5 Mar 2023 16:52:47 +0800 Subject: vim-patch:9.0.0749: alloc/free of buffer for each quickfix entry is inefficient Problem: Alloc/free of buffer for each quickfix entry is inefficient. Solution: Use a shared grow array. (Yegappan Lakshmanan, closes vim/vim#11365) https://github.com/vim/vim/commit/975a665d4811649a51e2c6a97a6ce096290d87ae Co-authored-by: Yegappan Lakshmanan --- src/nvim/memory.c | 6 +-- src/nvim/quickfix.c | 107 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 67 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 4e799dfd08..ffeafbdf2c 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -755,11 +755,7 @@ void free_all_mem(void) p_hi = 0; init_history(); - qf_free_all(NULL); - // Free all location lists - FOR_ALL_TAB_WINDOWS(tab, win) { - qf_free_all(win); - } + free_quickfix(); // Close all script inputs. close_all_scripts(); diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index af2d10798a..51cc7fa30b 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -245,6 +245,10 @@ typedef struct vgr_args_S { #endif static char *e_no_more_items = N_("E553: No more items"); +static char *e_current_quickfix_list_was_changed = + N_("E925: Current quickfix list was changed"); +static char *e_current_location_list_was_changed = + N_("E926: Current location list was changed"); // Quickfix window check helper macro #define IS_QF_WINDOW(wp) (bt_quickfix((wp)->w_buffer) && (wp)->w_llist_ref == NULL) @@ -275,10 +279,24 @@ static char *e_no_more_items = N_("E553: No more items"); static char *qf_last_bufname = NULL; static bufref_T qf_last_bufref = { NULL, 0, 0 }; -static char *e_current_quickfix_list_was_changed = - N_("E925: Current quickfix list was changed"); -static char *e_current_location_list_was_changed = - N_("E926: Current location list was changed"); +static garray_T qfga; + +/// Get a growarray to buffer text in. Shared between various commands to avoid +/// many alloc/free calls. +static garray_T *qfga_get(void) +{ + static bool initialized = false; + + if (!initialized) { + initialized = true; + ga_init(&qfga, 1, 256); + } + + // Retain ga_data from previous use. Reset the length to zero. + qfga.ga_len = 0; + + return &qfga; +} // Counter to prevent autocmds from freeing up location lists when they are // still being used. @@ -2799,6 +2817,8 @@ static void qf_jump_goto_line(linenr_T qf_lnum, int qf_col, char qf_viscol, char static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf_T *old_curbuf, linenr_T old_lnum) { + garray_T *const gap = qfga_get(); + // Update the screen before showing the message, unless the screen // scrolled up. if (!msg_scrolled) { @@ -2812,10 +2832,8 @@ static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf qf_ptr->qf_cleared ? _(" (line deleted)") : "", qf_types(qf_ptr->qf_type, qf_ptr->qf_nr)); // Add the message, skipping leading whitespace and newlines. - garray_T ga; - ga_init(&ga, 1, 256); - ga_concat(&ga, IObuff); - qf_fmt_text(&ga, skipwhite(qf_ptr->qf_text)); + ga_concat(gap, IObuff); + qf_fmt_text(gap, skipwhite(qf_ptr->qf_text)); // Output the message. Overwrite to avoid scrolling when the 'O' // flag is present in 'shortmess'; But when not jumping, print the @@ -2827,9 +2845,8 @@ static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf msg_scroll = false; } msg_ext_set_kind("quickfix"); - msg_attr_keep(ga.ga_data, 0, true, false); + msg_attr_keep(gap->ga_data, 0, true, false); msg_scroll = (int)i; - ga_clear(&ga); } /// Find a usable window for opening a file from the quickfix/location list. If @@ -3089,22 +3106,20 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel) if (qfp->qf_lnum != 0) { msg_puts_attr(":", qfSepAttr); } - garray_T ga; - ga_init(&ga, 1, 256); + garray_T *gap = qfga_get(); if (qfp->qf_lnum == 0) { - ga_append(&ga, NUL); + ga_append(gap, NUL); } else { - qf_range_text(&ga, qfp); + qf_range_text(gap, qfp); } - ga_concat(&ga, qf_types(qfp->qf_type, qfp->qf_nr)); - ga_append(&ga, NUL); - msg_puts_attr(ga.ga_data, qfLineAttr); - ga_clear(&ga); + ga_concat(gap, qf_types(qfp->qf_type, qfp->qf_nr)); + ga_append(gap, NUL); + msg_puts_attr(gap->ga_data, qfLineAttr); msg_puts_attr(":", qfSepAttr); if (qfp->qf_pattern != NULL) { - qf_fmt_text(&ga, qfp->qf_pattern); - msg_puts(ga.ga_data); - ga_clear(&ga); + gap = qfga_get(); + qf_fmt_text(gap, qfp->qf_pattern); + msg_puts(gap->ga_data); msg_puts_attr(":", qfSepAttr); } msg_puts(" "); @@ -3112,9 +3127,9 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel) // Remove newlines and leading whitespace from the text. For an // unrecognized line keep the indent, the compiler may mark a word // with ^^^^. - qf_fmt_text(&ga, (fname != NULL || qfp->qf_lnum != 0) ? skipwhite(qfp->qf_text) : qfp->qf_text); - msg_prt_line(ga.ga_data, false); - ga_clear(&ga); + gap = qfga_get(); + qf_fmt_text(gap, (fname != NULL || qfp->qf_lnum != 0) ? skipwhite(qfp->qf_text) : qfp->qf_text); + msg_prt_line(gap->ga_data, false); } // ":clist": list all errors @@ -3944,22 +3959,21 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli char *dirname, char *qftf_str, bool first_bufline) FUNC_ATTR_NONNULL_ARG(1, 2, 4, 5) { - garray_T ga; - ga_init(&ga, 1, 256); + garray_T *gap = qfga_get(); // If the 'quickfixtextfunc' function returned a non-empty custom string // for this entry, then use it. if (qftf_str != NULL && *qftf_str != NUL) { - ga_concat(&ga, qftf_str); + ga_concat(gap, qftf_str); } else { buf_T *errbuf; if (qfp->qf_module != NULL) { - ga_concat(&ga, qfp->qf_module); + ga_concat(gap, qfp->qf_module); } else if (qfp->qf_fnum != 0 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL && errbuf->b_fname != NULL) { if (qfp->qf_type == 1) { // :helpgrep - ga_concat(&ga, path_tail(errbuf->b_fname)); + ga_concat(gap, path_tail(errbuf->b_fname)); } else { // Shorten the file name if not done already. // For optimization, do this only for the first entry in a @@ -3972,35 +3986,33 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli } shorten_buf_fname(errbuf, dirname, false); } - ga_concat(&ga, errbuf->b_fname); + ga_concat(gap, errbuf->b_fname); } } - ga_append(&ga, '|'); + ga_append(gap, '|'); if (qfp->qf_lnum > 0) { - qf_range_text(&ga, qfp); - ga_concat(&ga, qf_types(qfp->qf_type, qfp->qf_nr)); + qf_range_text(gap, qfp); + ga_concat(gap, qf_types(qfp->qf_type, qfp->qf_nr)); } else if (qfp->qf_pattern != NULL) { - qf_fmt_text(&ga, qfp->qf_pattern); + qf_fmt_text(gap, qfp->qf_pattern); } - ga_append(&ga, '|'); - ga_append(&ga, ' '); + ga_append(gap, '|'); + ga_append(gap, ' '); // Remove newlines and leading whitespace from the text. // For an unrecognized line keep the indent, the compiler may // mark a word with ^^^^. - qf_fmt_text(&ga, ga.ga_len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text); + qf_fmt_text(gap, gap->ga_len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text); } - ga_append(&ga, NUL); + ga_append(gap, NUL); - if (ml_append_buf(buf, lnum, ga.ga_data, ga.ga_len + 1, false) == FAIL) { + if (ml_append_buf(buf, lnum, gap->ga_data, gap->ga_len + 1, false) == FAIL) { return FAIL; } - ga_clear(&ga); - return OK; } @@ -7207,6 +7219,19 @@ void ex_helpgrep(exarg_T *eap) } } +#if defined(EXITFREE) +void free_quickfix(void) +{ + qf_free_all(NULL); + // Free all location lists + FOR_ALL_TAB_WINDOWS(tab, win) { + qf_free_all(win); + } + + ga_clear(&qfga); +} +#endif + static void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv) { if (what_arg->v_type == VAR_UNKNOWN) { -- cgit From 749fe2c383f662bb13f97336329a0e08200c0a3b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 5 Mar 2023 17:03:00 +0800 Subject: vim-patch:9.0.0770: quickfix commands may keep memory allocated Problem: Quickfix commands may keep memory allocated. Solution: Free memory when it's a bit much. (Yegappan Lakshmanan, closes vim/vim#11379) https://github.com/vim/vim/commit/d8cd6f7427bc89aa38f42cc44f58bf5fb5f0f972 Co-authored-by: Yegappan Lakshmanan --- src/nvim/quickfix.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 51cc7fa30b..3c20c5239c 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -292,12 +292,26 @@ static garray_T *qfga_get(void) ga_init(&qfga, 1, 256); } - // Retain ga_data from previous use. Reset the length to zero. + // Reset the length to zero. Retain ga_data from previous use to avoid + // many alloc/free calls. qfga.ga_len = 0; return &qfga; } +/// The "qfga" grow array buffer is reused across multiple quickfix commands as +/// a temporary buffer to reduce the number of alloc/free calls. But if the +/// buffer size is large, then to avoid holding on to that memory, clear the +/// grow array. Otherwise just reset the grow array length. +static void qfga_clear(void) +{ + if (qfga.ga_maxlen > 1000) { + ga_clear(&qfga); + } else { + qfga.ga_len = 0; + } +} + // Counter to prevent autocmds from freeing up location lists when they are // still being used. static int quickfix_busy = 0; @@ -2847,6 +2861,8 @@ static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf msg_ext_set_kind("quickfix"); msg_attr_keep(gap->ga_data, 0, true, false); msg_scroll = (int)i; + + qfga_clear(); } /// Find a usable window for opening a file from the quickfix/location list. If @@ -3204,6 +3220,7 @@ void qf_list(exarg_T *eap) } os_breakcheck(); } + qfga_clear(); } /// Remove newlines and leading whitespace from an error message. @@ -4147,6 +4164,8 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q // Delete the empty line which is now at the end (void)ml_delete(lnum + 1, false); } + + qfga_clear(); } // Correct cursor position. -- cgit From e0bbe8ccf88d4ad0667ef38ae48d8bfdabb0cc26 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 5 Mar 2023 17:04:53 +0800 Subject: vim-patch:9.0.0870: get E967 when using text property in quickfix window Problem: Get E967 when using text property in quickfix window. (Sergey Vlasov) Solution: Do not add an extra NUL and compute the text length correctly. (closes vim/vim#11513) https://github.com/vim/vim/commit/2f7bfe66a1373051792f2ecaeefb66049825221d Co-authored-by: Bram Moolenaar --- src/nvim/quickfix.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 3c20c5239c..9f6181f986 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -3982,6 +3982,7 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli // for this entry, then use it. if (qftf_str != NULL && *qftf_str != NUL) { ga_concat(gap, qftf_str); + ga_append(gap, NUL); } else { buf_T *errbuf; if (qfp->qf_module != NULL) { @@ -4024,9 +4025,7 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli qf_fmt_text(gap, gap->ga_len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text); } - ga_append(gap, NUL); - - if (ml_append_buf(buf, lnum, gap->ga_data, gap->ga_len + 1, false) == FAIL) { + if (ml_append_buf(buf, lnum, gap->ga_data, gap->ga_len, false) == FAIL) { return FAIL; } -- cgit From 07758587037de1c8a4c45f1b39722ae73522c6bd Mon Sep 17 00:00:00 2001 From: Biswapriyo Nath Date: Sun, 5 Mar 2023 19:22:32 +0530 Subject: build: fix unknown pragma warning with mingw (#22533) This checks MSVC toolchain with _MSC_VER macro before adding pragma warning directive. It is specific to MSVC and shows compiler warning with mingw gcc as following: main.c:187: warning: ignoring '#pragma warning ' [-Wunknown-pragmas] 187 | # pragma warning(suppress : 4996) --- src/nvim/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/main.c b/src/nvim/main.c index 71c5c2af46..be1714b207 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -184,8 +184,12 @@ void early_init(mparm_T *paramp) ovi.dwOSVersionInfoSize = sizeof(ovi); // Disable warning about GetVersionExA being deprecated. There doesn't seem to be a convenient // replacement that doesn't add a ton of extra code as of writing this. -# pragma warning(suppress : 4996) +# ifdef _MSC_VER +# pragma warning(suppress : 4996) GetVersionEx(&ovi); +# else + GetVersionEx(&ovi); +# endif snprintf(windowsVersion, sizeof(windowsVersion), "%d.%d", (int)ovi.dwMajorVersion, (int)ovi.dwMinorVersion); #endif -- cgit From da0c66bcddbe4e6ebc72357c9f6c5de75e176744 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 5 Mar 2023 17:06:13 +0100 Subject: build: remove workaround for incorrectly packaged libluv This removes a workaround for incorrectly packaged libluv in 90e44ecf1144cb32195da00e24d23afb111ea680 as it should not be needed anymore. --- src/nvim/CMakeLists.txt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 61530f5a7b..51e0727cd5 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -14,12 +14,8 @@ else() endif() find_package(Libluv 1.43.0 REQUIRED) -target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBLUV_INCLUDE_DIRS}) -# Use "luv" as imported library, to work around CMake using "-lluv" for -# "luv.so". #10407 -add_library(luv UNKNOWN IMPORTED) -set_target_properties(luv PROPERTIES IMPORTED_LOCATION ${LIBLUV_LIBRARIES}) -target_link_libraries(main_lib INTERFACE luv) +target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBLUV_INCLUDE_DIR}) +target_link_libraries(main_lib INTERFACE ${LIBLUV_LIBRARY}) find_package(Iconv REQUIRED) find_package(Libtermkey 0.22 REQUIRED) -- cgit From e389b189021cb6b72cfd7583ce6fb5d8d3346d45 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 6 Mar 2023 07:52:11 +0800 Subject: vim-patch:9.0.1385: g'Esc is considered an error (#22544) Problem: g'Esc is considered an error. Solution: Make g'Esc silently abandon the command. (closes vim/vim#12110) https://github.com/vim/vim/commit/f86dea8119f3141e3d2c680219036d1511101f9b --- src/nvim/normal.c | 7 ++++--- src/nvim/testdir/test_normal.vim | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/normal.c b/src/nvim/normal.c index f7c99d5991..890215e754 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -963,7 +963,8 @@ normal_end: may_trigger_modechanged(); // Redraw the cursor with another shape, if we were in Operator-pending // mode or did a replace command. - if (s->c || s->ca.cmdchar == 'r') { + if (s->c || s->ca.cmdchar == 'r' + || (s->ca.cmdchar == 'g' && s->ca.nchar == 'r')) { ui_cursor_shape(); // may show different cursor shape } @@ -1162,7 +1163,7 @@ static int normal_execute(VimState *state, int key) State = MODE_NORMAL; - if (s->ca.nchar == ESC) { + if (s->ca.nchar == ESC || s->ca.extra_char == ESC) { clearop(&s->oa); s->command_finished = true; goto finish; @@ -4706,7 +4707,7 @@ static void nv_vreplace(cmdarg_T *cap) return; } - if (checkclearopq(cap->oap) || cap->extra_char == ESC) { + if (checkclearopq(cap->oap)) { return; } diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index 5d8e1913a2..582596748f 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -2540,6 +2540,8 @@ func Test_normal33_g_cmd2() norm! g'a call assert_equal('>', a[-1:]) call assert_equal(1, line('.')) + call assert_nobeep("normal! g`\") + call assert_nobeep("normal! g'\") " Test for g; and g, norm! g; @@ -3315,7 +3317,8 @@ func Test_gr_command() set modifiable& call assert_nobeep("normal! gr\") - call assert_beeps("normal! cgr\") + call assert_nobeep("normal! cgr\") + call assert_beeps("normal! cgrx") call assert_equal('zxxxx line l', getline(1)) exe "normal! 2|gr\\" @@ -3895,4 +3898,36 @@ func Test_mouse_shape_after_failed_change() call delete('Xmouseshapes') endfunc +" Test that mouse shape is restored to Normal mode after cancelling "gr". +func Test_mouse_shape_after_cancelling_gr() + CheckFeature mouseshape + CheckCanRunGui + + let lines =<< trim END + vim9script + var mouse_shapes = [] + + feedkeys('gr') + timer_start(50, (_) => { + mouse_shapes += [getmouseshape()] + timer_start(50, (_) => { + feedkeys("\") + timer_start(50, (_) => { + mouse_shapes += [getmouseshape()] + timer_start(50, (_) => { + writefile(mouse_shapes, 'Xmouseshapes') + quit + }) + }) + }) + }) + END + call writefile(lines, 'Xmouseshape.vim', 'D') + call RunVim([], [], "-g -S Xmouseshape.vim") + sleep 300m + call assert_equal(['beam', 'arrow'], readfile('Xmouseshapes')) + + call delete('Xmouseshapes') +endfunc + " vim: shiftwidth=2 sts=2 expandtab -- cgit From b0620ffe5a2e16d6d52e803978c90d0ffb030908 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 6 Mar 2023 16:45:57 +0800 Subject: vim-patch:9.0.1386: options test fails with some window width (#22548) Problem: Options test fails with some window width. Solution: Adjust what text the test checks with. (closes vim/vim#12111) https://github.com/vim/vim/commit/30585e03a7ce6cf985f93ca30275bf4dae0d87cc --- src/nvim/testdir/test_normal.vim | 3 +++ src/nvim/testdir/test_options.vim | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim index 582596748f..48e6bc5298 100644 --- a/src/nvim/testdir/test_normal.vim +++ b/src/nvim/testdir/test_normal.vim @@ -2540,8 +2540,11 @@ func Test_normal33_g_cmd2() norm! g'a call assert_equal('>', a[-1:]) call assert_equal(1, line('.')) + let v:errmsg = '' call assert_nobeep("normal! g`\") + call assert_equal('', v:errmsg) call assert_nobeep("normal! g'\") + call assert_equal('', v:errmsg) " Test for g; and g, norm! g; diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index 43cc3632e6..b6b982e92e 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -890,8 +890,9 @@ func Test_debug_option() exe "normal \" call assert_equal('Beep!', Screenline(&lines)) call assert_equal('line 4:', Screenline(&lines - 1)) - " only match the final colon in the line that shows the source - call assert_match(':$', Screenline(&lines - 2)) + " also check a line above, with a certain window width the colon is there + call assert_match('Test_debug_option:$', + \ Screenline(&lines - 3) .. Screenline(&lines - 2)) set debug& endfunc -- cgit From 0e7196438d8f856eecd7c90e160b79cbc8fb08dc Mon Sep 17 00:00:00 2001 From: Kelly Lin Date: Sun, 19 Feb 2023 22:33:57 +1100 Subject: feat(lua): add semver api --- src/nvim/lua/executor.c | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'src') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index bb461a7f13..5ec91aebb0 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -165,17 +165,6 @@ static int nlua_pcall(lua_State *lstate, int nargs, int nresults) return status; } -/// Gets the version of the current Nvim build. -/// -/// @param lstate Lua interpreter state. -static int nlua_nvim_version(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL -{ - Dictionary version = version_dict(); - nlua_push_Dictionary(lstate, version, true); - api_free_dictionary(version); - return 1; -} - static void nlua_luv_error_event(void **argv) { char *error = (char *)argv[0]; @@ -739,10 +728,6 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL // vim.types, vim.type_idx, vim.val_idx nlua_init_types(lstate); - // neovim version - lua_pushcfunction(lstate, &nlua_nvim_version); - lua_setfield(lstate, -2, "version"); - // schedule lua_pushcfunction(lstate, &nlua_schedule); lua_setfield(lstate, -2, "schedule"); -- cgit From 98f2df931ad8657f21124d8a6024967c5997fc99 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 6 Mar 2023 16:10:04 +0000 Subject: fix(diff): add NULL check --- src/nvim/linematch.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/nvim/linematch.c b/src/nvim/linematch.c index a9dac40731..a15f41d9a8 100644 --- a/src/nvim/linematch.c +++ b/src/nvim/linematch.c @@ -161,6 +161,9 @@ void fastforward_buf_to_lnum(const char **s, long lnum) { for (long i = 0; i < lnum - 1; i++) { *s = strchr(*s, '\n'); + if (!*s) { + return; + } (*s)++; } } -- cgit From 1cc23e1109ed88275df5c986c352f73b99a0301c Mon Sep 17 00:00:00 2001 From: swarn Date: Mon, 6 Mar 2023 12:03:13 -0600 Subject: feat(lsp)!: add rule-based sem token highlighting (#22022) feat(lsp)!: change semantic token highlighting Change the default highlights used, and add more highlights per token. Add an LspTokenUpdate event and a highlight_token function. :Inspect now shows any highlights applied by token highlighting rules, default or user-defined. BREAKING CHANGE: change the default highlight groups used by semantic token highlighting. --- src/nvim/auevents.lua | 2 ++ src/nvim/highlight_group.c | 26 ++++++++++++++++---------- 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index a75ee3bbd5..aef08be820 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -72,6 +72,7 @@ return { 'InsertLeavePre', -- just before leaving Insert mode 'LspAttach', -- after an LSP client attaches to a buffer 'LspDetach', -- after an LSP client detaches from a buffer + 'LspTokenUpdate', -- after a visible LSP token is updated 'MenuPopup', -- just before popup menu is displayed 'ModeChanged', -- after changing the mode 'OptionSet', -- after setting any option @@ -151,6 +152,7 @@ return { DiagnosticChanged=true, LspAttach=true, LspDetach=true, + LspTokenUpdate=true, RecordingEnter=true, RecordingLeave=true, Signal=true, diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index d2f5b60dc6..70ee6c757c 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -270,16 +270,22 @@ static const char *highlight_init_both[] = { "default link @tag Tag", // LSP semantic tokens - "default link @class Structure", - "default link @struct Structure", - "default link @enum Type", - "default link @enumMember Constant", - "default link @event Identifier", - "default link @interface Identifier", - "default link @modifier Identifier", - "default link @regexp SpecialChar", - "default link @typeParameter Type", - "default link @decorator Identifier", + "default link @lsp.type.class Structure", + "default link @lsp.type.decorator Function", + "default link @lsp.type.enum Structure", + "default link @lsp.type.enumMember Constant", + "default link @lsp.type.function Function", + "default link @lsp.type.interface Structure", + "default link @lsp.type.macro Macro", + "default link @lsp.type.method Function", + "default link @lsp.type.namespace Structure", + "default link @lsp.type.parameter Identifier", + "default link @lsp.type.property Identifier", + "default link @lsp.type.struct Structure", + "default link @lsp.type.type Type", + "default link @lsp.type.typeParameter TypeDef", + "default link @lsp.type.variable Identifier", + NULL }; -- cgit From 6aa5346b04d6ffbac1ba8fc5626182c16b5ad947 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 6 Mar 2023 22:36:04 +0100 Subject: build: enable unit testing on release builds (#22554) Unittests not working on release builds can lead to confusing situations, such as contributors wondering why their tests aren't working if they forgot they've built with a release build. This only increased the Release executable size by 8 kB on my personal machine, which is an acceptable tradeoff. --- src/nvim/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 51e0727cd5..f3344c10de 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -626,8 +626,8 @@ if(PREFER_LUA) message(STATUS "luajit not used, skipping unit tests") else() glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c) - target_sources(nvim PRIVATE $<$:${UNIT_TEST_FIXTURES}>) - target_compile_definitions(nvim PRIVATE $<$:UNIT_TESTING>) + target_sources(nvim PRIVATE ${UNIT_TEST_FIXTURES}) + target_compile_definitions(nvim PRIVATE UNIT_TESTING) endif() target_sources(main_lib INTERFACE -- cgit From 79571b92ced968ad27bee2a7515a4a04e84dbad2 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 27 Jan 2021 09:00:28 +0100 Subject: feat(lua): omnifunc for builting lua interpreter also make implicit submodules "uri" and "_inspector" work with completion this is needed for `:lua=vim.uri_` wildmenu completion to work even before uri or _inspector functions are used. --- src/nvim/lua/executor.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index bb461a7f13..8a50c8fe4f 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1872,6 +1872,12 @@ int nlua_expand_pat(expand_T *xp, char *pat, int *num_results, char ***results) lua_getfield(lstate, -1, "_expand_pat"); luaL_checktype(lstate, -1, LUA_TFUNCTION); + // ex expansion prepends a ^, but don't worry, it is not a regex + if (pat[0] != '^') { + return FAIL; + } + pat++; + // [ vim, vim._expand_pat, buf ] lua_pushlstring(lstate, (const char *)pat, strlen(pat)); -- cgit From bf4eada2c83f5402fc56370fd22af11029a4a3aa Mon Sep 17 00:00:00 2001 From: luukvbaal <31730729+luukvbaal@users.noreply.github.com> Date: Tue, 7 Mar 2023 01:45:08 +0100 Subject: fix(column): issues with 'statuscolumn' width (#22542) Problem: 'statuscolumn' width can be incorrect when toggling 'number' or setting 'statuscolumn'. Solution: Make sure the width is reset and re-estimated when 'statuscolumn' and 'number' are set. (When 'relativenumber' is set this already happens because it always changes "nrwidth_line_count".) --- src/nvim/option.c | 4 ++++ src/nvim/optionstr.c | 1 + 2 files changed, 5 insertions(+) (limited to 'src') diff --git a/src/nvim/option.c b/src/nvim/option.c index be82cf22c7..5ad2929a91 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2176,6 +2176,10 @@ static char *set_bool_option(const int opt_idx, char *const varp, const int valu if (curwin->w_p_spell) { errmsg = did_set_spelllang(curwin); } + } else if ((int *)varp == &curwin->w_p_nu && *curwin->w_p_stc != NUL) { + // When 'statuscolumn' is set and 'number' is changed: + curwin->w_nrwidth_line_count = 0; // make sure width is reset + curwin->w_statuscol_line_count = 0; // make sure width is re-estimated } if ((int *)varp == &curwin->w_p_arab) { diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index f903ad3d09..b335e255a4 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1199,6 +1199,7 @@ static void did_set_statusline(win_T *win, char **varp, char **gvarp, char **err ru_wid = 0; } else if (varp == &win->w_p_stc) { win->w_nrwidth_line_count = 0; + win->w_statuscol_line_count = 0; } char *s = *varp; if (varp == &p_ruf && *s == '%') { -- cgit From af23d173883f47fd02a9a380c719e4428370b484 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 7 Mar 2023 04:13:04 +0100 Subject: test: move oldtests to test directory (#22536) The new oldtest directory is in test/old/testdir. The reason for this is that many tests have hardcoded the parent directory name to be 'testdir'. --- src/nvim/testdir/Make_all.mak | 1 - src/nvim/testdir/Makefile | 154 - src/nvim/testdir/README.txt | 121 - src/nvim/testdir/check.vim | 217 - src/nvim/testdir/dotest.in | 3 - src/nvim/testdir/load.vim | 32 - src/nvim/testdir/pyxfile/py2_magic.py | 4 - src/nvim/testdir/pyxfile/py2_shebang.py | 4 - src/nvim/testdir/pyxfile/py3_magic.py | 4 - src/nvim/testdir/pyxfile/py3_shebang.py | 4 - src/nvim/testdir/pyxfile/pyx.py | 2 - src/nvim/testdir/runnvim.sh | 88 - src/nvim/testdir/runnvim.vim | 58 - src/nvim/testdir/runtest.vim | 485 -- src/nvim/testdir/samples/memfile_test.c | 148 - src/nvim/testdir/samples/quickfix.txt | 4 - src/nvim/testdir/samples/re.freeze.txt | 6 - src/nvim/testdir/sautest/autoload/foo.vim | 15 - src/nvim/testdir/sautest/autoload/footest.vim | 5 - src/nvim/testdir/sautest/autoload/globone.vim | 1 - src/nvim/testdir/sautest/autoload/globtwo.vim | 1 - src/nvim/testdir/sautest/autoload/sourced.vim | 3 - src/nvim/testdir/screendump.vim | 2 - src/nvim/testdir/script_util.vim | 69 - src/nvim/testdir/setup.vim | 85 - src/nvim/testdir/shared.vim | 389 -- src/nvim/testdir/suite.sh | 10 - src/nvim/testdir/summarize.vim | 62 - src/nvim/testdir/term_util.vim | 13 - src/nvim/testdir/test.sh | 91 - src/nvim/testdir/test1.in | 13 - src/nvim/testdir/test1.ok | 1 - src/nvim/testdir/test_alot.vim | 31 - src/nvim/testdir/test_alot_latin.vim | 7 - src/nvim/testdir/test_alot_utf8.vim | 14 - src/nvim/testdir/test_arabic.vim | 587 -- src/nvim/testdir/test_arglist.vim | 748 --- src/nvim/testdir/test_assert.vim | 363 -- src/nvim/testdir/test_autochdir.vim | 130 - src/nvim/testdir/test_autocmd.vim | 3630 ----------- src/nvim/testdir/test_autoload.vim | 25 - src/nvim/testdir/test_backspace_opt.vim | 141 - src/nvim/testdir/test_backup.vim | 89 - src/nvim/testdir/test_behave.vim | 29 - src/nvim/testdir/test_blob.vim | 830 --- src/nvim/testdir/test_blockedit.vim | 132 - src/nvim/testdir/test_breakindent.vim | 1096 ---- src/nvim/testdir/test_buffer.vim | 525 -- src/nvim/testdir/test_bufline.vim | 296 - src/nvim/testdir/test_bufwintabinfo.vim | 187 - src/nvim/testdir/test_cd.vim | 256 - src/nvim/testdir/test_cdo.vim | 216 - src/nvim/testdir/test_changedtick.vim | 95 - src/nvim/testdir/test_changelist.vim | 107 - src/nvim/testdir/test_charsearch.vim | 99 - src/nvim/testdir/test_charsearch_utf8.vim | 19 - src/nvim/testdir/test_checkpath.vim | 121 - src/nvim/testdir/test_cindent.vim | 5428 ----------------- src/nvim/testdir/test_cjk_linebreak.vim | 97 - src/nvim/testdir/test_clientserver.vim | 195 - src/nvim/testdir/test_close_count.vim | 174 - src/nvim/testdir/test_cmdline.vim | 3586 ----------- src/nvim/testdir/test_command_count.vim | 196 - src/nvim/testdir/test_comments.vim | 277 - src/nvim/testdir/test_comparators.vim | 9 - src/nvim/testdir/test_compiler.vim | 78 - src/nvim/testdir/test_conceal.vim | 284 - src/nvim/testdir/test_const.vim | 294 - src/nvim/testdir/test_cpoptions.vim | 934 --- src/nvim/testdir/test_cursor_func.vim | 481 -- src/nvim/testdir/test_cursorline.vim | 354 -- src/nvim/testdir/test_curswant.vim | 23 - src/nvim/testdir/test_debugger.vim | 1237 ---- src/nvim/testdir/test_delete.vim | 110 - src/nvim/testdir/test_diffmode.vim | 1647 ----- src/nvim/testdir/test_digraph.vim | 604 -- src/nvim/testdir/test_display.vim | 482 -- src/nvim/testdir/test_edit.vim | 2105 ------- src/nvim/testdir/test_environ.vim | 89 - src/nvim/testdir/test_erasebackword.vim | 19 - src/nvim/testdir/test_escaped_glob.vim | 34 - src/nvim/testdir/test_eval_stuff.vim | 392 -- src/nvim/testdir/test_ex_equal.vim | 32 - src/nvim/testdir/test_ex_mode.vim | 243 - src/nvim/testdir/test_ex_undo.vim | 19 - src/nvim/testdir/test_ex_z.vim | 108 - src/nvim/testdir/test_excmd.vim | 750 --- src/nvim/testdir/test_exec_while_if.vim | 43 - src/nvim/testdir/test_execute_func.vim | 176 - src/nvim/testdir/test_exists.vim | 331 - src/nvim/testdir/test_exists_autocmd.vim | 26 - src/nvim/testdir/test_exit.vim | 135 - src/nvim/testdir/test_expand.vim | 229 - src/nvim/testdir/test_expand_func.vim | 146 - src/nvim/testdir/test_expr.vim | 676 --- src/nvim/testdir/test_expr_utf8.vim | 34 - src/nvim/testdir/test_file_perm.vim | 30 - src/nvim/testdir/test_file_size.vim | 58 - src/nvim/testdir/test_filechanged.vim | 274 - src/nvim/testdir/test_fileformat.vim | 309 - src/nvim/testdir/test_filetype.vim | 2055 ------- src/nvim/testdir/test_filter_cmd.vim | 190 - src/nvim/testdir/test_filter_map.vim | 108 - src/nvim/testdir/test_find_complete.vim | 163 - src/nvim/testdir/test_findfile.vim | 255 - src/nvim/testdir/test_fixeol.vim | 118 - src/nvim/testdir/test_flatten.vim | 108 - src/nvim/testdir/test_float_func.vim | 369 -- src/nvim/testdir/test_fnameescape.vim | 27 - src/nvim/testdir/test_fnamemodify.vim | 104 - src/nvim/testdir/test_fold.vim | 1558 ----- src/nvim/testdir/test_functions.vim | 2568 -------- src/nvim/testdir/test_ga.vim | 43 - src/nvim/testdir/test_getcwd.vim | 112 - src/nvim/testdir/test_getvar.vim | 155 - src/nvim/testdir/test_gf.vim | 303 - src/nvim/testdir/test_glob2regpat.vim | 32 - src/nvim/testdir/test_global.vim | 131 - src/nvim/testdir/test_gn.vim | 221 - src/nvim/testdir/test_goto.vim | 442 -- src/nvim/testdir/test_gui.vim | 43 - src/nvim/testdir/test_help.vim | 229 - src/nvim/testdir/test_help_tagjump.vim | 322 - src/nvim/testdir/test_hide.vim | 97 - src/nvim/testdir/test_highlight.vim | 868 --- src/nvim/testdir/test_history.vim | 252 - src/nvim/testdir/test_hlsearch.vim | 88 - src/nvim/testdir/test_increment.vim | 913 --- src/nvim/testdir/test_increment_dbcs.vim | 31 - src/nvim/testdir/test_indent.vim | 279 - src/nvim/testdir/test_input.vim | 61 - src/nvim/testdir/test_ins_complete.vim | 2240 ------- src/nvim/testdir/test_ins_complete_no_halt.vim | 51 - src/nvim/testdir/test_interrupt.vim | 32 - src/nvim/testdir/test_join.vim | 447 -- src/nvim/testdir/test_jumplist.vim | 107 - src/nvim/testdir/test_lambda.vim | 334 -- src/nvim/testdir/test_langmap.vim | 89 - src/nvim/testdir/test_largefile.vim | 29 - src/nvim/testdir/test_let.vim | 478 -- src/nvim/testdir/test_lineending.vim | 19 - src/nvim/testdir/test_lispindent.vim | 129 - src/nvim/testdir/test_listchars.vim | 695 --- src/nvim/testdir/test_listdict.vim | 1138 ---- src/nvim/testdir/test_listlbr.vim | 333 -- src/nvim/testdir/test_listlbr_utf8.vim | 282 - src/nvim/testdir/test_makeencoding.py | 69 - src/nvim/testdir/test_makeencoding.vim | 125 - src/nvim/testdir/test_maparg.vim | 325 - src/nvim/testdir/test_mapping.vim | 1227 ---- src/nvim/testdir/test_marks.vim | 320 - src/nvim/testdir/test_match.vim | 442 -- src/nvim/testdir/test_matchadd_conceal.vim | 422 -- src/nvim/testdir/test_matchadd_conceal_utf8.vim | 39 - src/nvim/testdir/test_matchfuzzy.vim | 263 - src/nvim/testdir/test_menu.vim | 574 -- src/nvim/testdir/test_messages.vim | 530 -- src/nvim/testdir/test_method.vim | 174 - src/nvim/testdir/test_mksession.vim | 1027 ---- src/nvim/testdir/test_mksession_utf8.vim | 105 - src/nvim/testdir/test_modeline.vim | 376 -- src/nvim/testdir/test_move.vim | 70 - src/nvim/testdir/test_nested_function.vim | 63 - src/nvim/testdir/test_normal.vim | 3936 ------------ src/nvim/testdir/test_number.vim | 359 -- src/nvim/testdir/test_options.vim | 1346 ----- src/nvim/testdir/test_packadd.vim | 437 -- src/nvim/testdir/test_partial.vim | 361 -- src/nvim/testdir/test_paste.vim | 77 - src/nvim/testdir/test_perl.vim | 311 - src/nvim/testdir/test_plus_arg_edit.vim | 47 - src/nvim/testdir/test_popup.vim | 1263 ---- src/nvim/testdir/test_preview.vim | 64 - src/nvim/testdir/test_profile.vim | 596 -- src/nvim/testdir/test_prompt_buffer.vim | 257 - src/nvim/testdir/test_put.vim | 250 - src/nvim/testdir/test_python2.vim | 173 - src/nvim/testdir/test_python3.vim | 192 - src/nvim/testdir/test_pyx2.vim | 81 - src/nvim/testdir/test_pyx3.vim | 81 - src/nvim/testdir/test_quickfix.vim | 6296 -------------------- src/nvim/testdir/test_quotestar.vim | 155 - src/nvim/testdir/test_random.vim | 59 - src/nvim/testdir/test_recover.vim | 467 -- src/nvim/testdir/test_regex_char_classes.vim | 297 - src/nvim/testdir/test_regexp_latin.vim | 1094 ---- src/nvim/testdir/test_regexp_utf8.vim | 603 -- src/nvim/testdir/test_registers.vim | 800 --- src/nvim/testdir/test_reltime.vim | 31 - src/nvim/testdir/test_rename.vim | 120 - src/nvim/testdir/test_retab.vim | 117 - src/nvim/testdir/test_ruby.vim | 417 -- src/nvim/testdir/test_scriptnames.vim | 32 - src/nvim/testdir/test_scroll_opt.vim | 54 - src/nvim/testdir/test_scrollbind.vim | 272 - src/nvim/testdir/test_search.vim | 2109 ------- src/nvim/testdir/test_search_stat.vim | 448 -- src/nvim/testdir/test_searchpos.vim | 30 - src/nvim/testdir/test_selectmode.vim | 210 - src/nvim/testdir/test_set.vim | 48 - src/nvim/testdir/test_sha256.vim | 22 - src/nvim/testdir/test_shell.vim | 209 - src/nvim/testdir/test_shift.vim | 117 - src/nvim/testdir/test_signals.vim | 165 - src/nvim/testdir/test_signs.vim | 2047 ------- src/nvim/testdir/test_sleep.vim | 27 - src/nvim/testdir/test_smartindent.vim | 136 - src/nvim/testdir/test_sort.vim | 1524 ----- src/nvim/testdir/test_source.vim | 113 - src/nvim/testdir/test_source_utf8.vim | 61 - src/nvim/testdir/test_spell.vim | 1467 ----- src/nvim/testdir/test_spell_utf8.vim | 832 --- src/nvim/testdir/test_spellfile.vim | 1066 ---- src/nvim/testdir/test_startup.vim | 1278 ---- src/nvim/testdir/test_startup_utf8.vim | 82 - src/nvim/testdir/test_stat.vim | 228 - src/nvim/testdir/test_statusline.vim | 613 -- src/nvim/testdir/test_substitute.vim | 1386 ----- src/nvim/testdir/test_suspend.vim | 63 - src/nvim/testdir/test_swap.vim | 588 -- src/nvim/testdir/test_syn_attr.vim | 51 - src/nvim/testdir/test_syntax.vim | 981 --- src/nvim/testdir/test_system.vim | 145 - src/nvim/testdir/test_tab.vim | 90 - src/nvim/testdir/test_tabline.vim | 207 - src/nvim/testdir/test_tabpage.vim | 888 --- src/nvim/testdir/test_tagcase.vim | 74 - src/nvim/testdir/test_tagfunc.vim | 417 -- src/nvim/testdir/test_tagjump.vim | 1615 ----- src/nvim/testdir/test_taglist.vim | 281 - src/nvim/testdir/test_termcodes.vim | 63 - src/nvim/testdir/test_textformat.vim | 1307 ---- src/nvim/testdir/test_textobjects.vim | 646 -- src/nvim/testdir/test_timers.vim | 458 -- src/nvim/testdir/test_true_false.vim | 155 - src/nvim/testdir/test_trycatch.vim | 2333 -------- src/nvim/testdir/test_undo.vim | 805 --- src/nvim/testdir/test_unlet.vim | 67 - src/nvim/testdir/test_user_func.vim | 504 -- src/nvim/testdir/test_usercommands.vim | 759 --- src/nvim/testdir/test_utf8.vim | 331 - src/nvim/testdir/test_utf8_comparisons.vim | 94 - src/nvim/testdir/test_vartabs.vim | 448 -- src/nvim/testdir/test_version.vim | 26 - src/nvim/testdir/test_viminfo.vim | 26 - src/nvim/testdir/test_vimscript.vim | 7284 ----------------------- src/nvim/testdir/test_virtualedit.vim | 612 -- src/nvim/testdir/test_visual.vim | 1560 ----- src/nvim/testdir/test_winbuf_close.vim | 231 - src/nvim/testdir/test_window_cmd.vim | 1879 ------ src/nvim/testdir/test_window_id.vim | 142 - src/nvim/testdir/test_windows_home.vim | 120 - src/nvim/testdir/test_wnext.vim | 101 - src/nvim/testdir/test_wordcount.vim | 104 - src/nvim/testdir/test_writefile.vim | 963 --- src/nvim/testdir/unix.vim | 15 - src/nvim/testdir/view_util.vim | 64 - src/nvim/testdir/vim9.vim | 116 - 258 files changed, 120891 deletions(-) delete mode 100644 src/nvim/testdir/Make_all.mak delete mode 100644 src/nvim/testdir/Makefile delete mode 100644 src/nvim/testdir/README.txt delete mode 100644 src/nvim/testdir/check.vim delete mode 100644 src/nvim/testdir/dotest.in delete mode 100644 src/nvim/testdir/load.vim delete mode 100644 src/nvim/testdir/pyxfile/py2_magic.py delete mode 100644 src/nvim/testdir/pyxfile/py2_shebang.py delete mode 100644 src/nvim/testdir/pyxfile/py3_magic.py delete mode 100644 src/nvim/testdir/pyxfile/py3_shebang.py delete mode 100644 src/nvim/testdir/pyxfile/pyx.py delete mode 100755 src/nvim/testdir/runnvim.sh delete mode 100644 src/nvim/testdir/runnvim.vim delete mode 100644 src/nvim/testdir/runtest.vim delete mode 100644 src/nvim/testdir/samples/memfile_test.c delete mode 100644 src/nvim/testdir/samples/quickfix.txt delete mode 100644 src/nvim/testdir/samples/re.freeze.txt delete mode 100644 src/nvim/testdir/sautest/autoload/foo.vim delete mode 100644 src/nvim/testdir/sautest/autoload/footest.vim delete mode 100644 src/nvim/testdir/sautest/autoload/globone.vim delete mode 100644 src/nvim/testdir/sautest/autoload/globtwo.vim delete mode 100644 src/nvim/testdir/sautest/autoload/sourced.vim delete mode 100644 src/nvim/testdir/screendump.vim delete mode 100644 src/nvim/testdir/script_util.vim delete mode 100644 src/nvim/testdir/setup.vim delete mode 100644 src/nvim/testdir/shared.vim delete mode 100644 src/nvim/testdir/suite.sh delete mode 100644 src/nvim/testdir/summarize.vim delete mode 100644 src/nvim/testdir/term_util.vim delete mode 100644 src/nvim/testdir/test.sh delete mode 100644 src/nvim/testdir/test1.in delete mode 100644 src/nvim/testdir/test1.ok delete mode 100644 src/nvim/testdir/test_alot.vim delete mode 100644 src/nvim/testdir/test_alot_latin.vim delete mode 100644 src/nvim/testdir/test_alot_utf8.vim delete mode 100644 src/nvim/testdir/test_arabic.vim delete mode 100644 src/nvim/testdir/test_arglist.vim delete mode 100644 src/nvim/testdir/test_assert.vim delete mode 100644 src/nvim/testdir/test_autochdir.vim delete mode 100644 src/nvim/testdir/test_autocmd.vim delete mode 100644 src/nvim/testdir/test_autoload.vim delete mode 100644 src/nvim/testdir/test_backspace_opt.vim delete mode 100644 src/nvim/testdir/test_backup.vim delete mode 100644 src/nvim/testdir/test_behave.vim delete mode 100644 src/nvim/testdir/test_blob.vim delete mode 100644 src/nvim/testdir/test_blockedit.vim delete mode 100644 src/nvim/testdir/test_breakindent.vim delete mode 100644 src/nvim/testdir/test_buffer.vim delete mode 100644 src/nvim/testdir/test_bufline.vim delete mode 100644 src/nvim/testdir/test_bufwintabinfo.vim delete mode 100644 src/nvim/testdir/test_cd.vim delete mode 100644 src/nvim/testdir/test_cdo.vim delete mode 100644 src/nvim/testdir/test_changedtick.vim delete mode 100644 src/nvim/testdir/test_changelist.vim delete mode 100644 src/nvim/testdir/test_charsearch.vim delete mode 100644 src/nvim/testdir/test_charsearch_utf8.vim delete mode 100644 src/nvim/testdir/test_checkpath.vim delete mode 100644 src/nvim/testdir/test_cindent.vim delete mode 100644 src/nvim/testdir/test_cjk_linebreak.vim delete mode 100644 src/nvim/testdir/test_clientserver.vim delete mode 100644 src/nvim/testdir/test_close_count.vim delete mode 100644 src/nvim/testdir/test_cmdline.vim delete mode 100644 src/nvim/testdir/test_command_count.vim delete mode 100644 src/nvim/testdir/test_comments.vim delete mode 100644 src/nvim/testdir/test_comparators.vim delete mode 100644 src/nvim/testdir/test_compiler.vim delete mode 100644 src/nvim/testdir/test_conceal.vim delete mode 100644 src/nvim/testdir/test_const.vim delete mode 100644 src/nvim/testdir/test_cpoptions.vim delete mode 100644 src/nvim/testdir/test_cursor_func.vim delete mode 100644 src/nvim/testdir/test_cursorline.vim delete mode 100644 src/nvim/testdir/test_curswant.vim delete mode 100644 src/nvim/testdir/test_debugger.vim delete mode 100644 src/nvim/testdir/test_delete.vim delete mode 100644 src/nvim/testdir/test_diffmode.vim delete mode 100644 src/nvim/testdir/test_digraph.vim delete mode 100644 src/nvim/testdir/test_display.vim delete mode 100644 src/nvim/testdir/test_edit.vim delete mode 100644 src/nvim/testdir/test_environ.vim delete mode 100644 src/nvim/testdir/test_erasebackword.vim delete mode 100644 src/nvim/testdir/test_escaped_glob.vim delete mode 100644 src/nvim/testdir/test_eval_stuff.vim delete mode 100644 src/nvim/testdir/test_ex_equal.vim delete mode 100644 src/nvim/testdir/test_ex_mode.vim delete mode 100644 src/nvim/testdir/test_ex_undo.vim delete mode 100644 src/nvim/testdir/test_ex_z.vim delete mode 100644 src/nvim/testdir/test_excmd.vim delete mode 100644 src/nvim/testdir/test_exec_while_if.vim delete mode 100644 src/nvim/testdir/test_execute_func.vim delete mode 100644 src/nvim/testdir/test_exists.vim delete mode 100644 src/nvim/testdir/test_exists_autocmd.vim delete mode 100644 src/nvim/testdir/test_exit.vim delete mode 100644 src/nvim/testdir/test_expand.vim delete mode 100644 src/nvim/testdir/test_expand_func.vim delete mode 100644 src/nvim/testdir/test_expr.vim delete mode 100644 src/nvim/testdir/test_expr_utf8.vim delete mode 100644 src/nvim/testdir/test_file_perm.vim delete mode 100644 src/nvim/testdir/test_file_size.vim delete mode 100644 src/nvim/testdir/test_filechanged.vim delete mode 100644 src/nvim/testdir/test_fileformat.vim delete mode 100644 src/nvim/testdir/test_filetype.vim delete mode 100644 src/nvim/testdir/test_filter_cmd.vim delete mode 100644 src/nvim/testdir/test_filter_map.vim delete mode 100644 src/nvim/testdir/test_find_complete.vim delete mode 100644 src/nvim/testdir/test_findfile.vim delete mode 100644 src/nvim/testdir/test_fixeol.vim delete mode 100644 src/nvim/testdir/test_flatten.vim delete mode 100644 src/nvim/testdir/test_float_func.vim delete mode 100644 src/nvim/testdir/test_fnameescape.vim delete mode 100644 src/nvim/testdir/test_fnamemodify.vim delete mode 100644 src/nvim/testdir/test_fold.vim delete mode 100644 src/nvim/testdir/test_functions.vim delete mode 100644 src/nvim/testdir/test_ga.vim delete mode 100644 src/nvim/testdir/test_getcwd.vim delete mode 100644 src/nvim/testdir/test_getvar.vim delete mode 100644 src/nvim/testdir/test_gf.vim delete mode 100644 src/nvim/testdir/test_glob2regpat.vim delete mode 100644 src/nvim/testdir/test_global.vim delete mode 100644 src/nvim/testdir/test_gn.vim delete mode 100644 src/nvim/testdir/test_goto.vim delete mode 100644 src/nvim/testdir/test_gui.vim delete mode 100644 src/nvim/testdir/test_help.vim delete mode 100644 src/nvim/testdir/test_help_tagjump.vim delete mode 100644 src/nvim/testdir/test_hide.vim delete mode 100644 src/nvim/testdir/test_highlight.vim delete mode 100644 src/nvim/testdir/test_history.vim delete mode 100644 src/nvim/testdir/test_hlsearch.vim delete mode 100644 src/nvim/testdir/test_increment.vim delete mode 100644 src/nvim/testdir/test_increment_dbcs.vim delete mode 100644 src/nvim/testdir/test_indent.vim delete mode 100644 src/nvim/testdir/test_input.vim delete mode 100644 src/nvim/testdir/test_ins_complete.vim delete mode 100644 src/nvim/testdir/test_ins_complete_no_halt.vim delete mode 100644 src/nvim/testdir/test_interrupt.vim delete mode 100644 src/nvim/testdir/test_join.vim delete mode 100644 src/nvim/testdir/test_jumplist.vim delete mode 100644 src/nvim/testdir/test_lambda.vim delete mode 100644 src/nvim/testdir/test_langmap.vim delete mode 100644 src/nvim/testdir/test_largefile.vim delete mode 100644 src/nvim/testdir/test_let.vim delete mode 100644 src/nvim/testdir/test_lineending.vim delete mode 100644 src/nvim/testdir/test_lispindent.vim delete mode 100644 src/nvim/testdir/test_listchars.vim delete mode 100644 src/nvim/testdir/test_listdict.vim delete mode 100644 src/nvim/testdir/test_listlbr.vim delete mode 100644 src/nvim/testdir/test_listlbr_utf8.vim delete mode 100644 src/nvim/testdir/test_makeencoding.py delete mode 100644 src/nvim/testdir/test_makeencoding.vim delete mode 100644 src/nvim/testdir/test_maparg.vim delete mode 100644 src/nvim/testdir/test_mapping.vim delete mode 100644 src/nvim/testdir/test_marks.vim delete mode 100644 src/nvim/testdir/test_match.vim delete mode 100644 src/nvim/testdir/test_matchadd_conceal.vim delete mode 100644 src/nvim/testdir/test_matchadd_conceal_utf8.vim delete mode 100644 src/nvim/testdir/test_matchfuzzy.vim delete mode 100644 src/nvim/testdir/test_menu.vim delete mode 100644 src/nvim/testdir/test_messages.vim delete mode 100644 src/nvim/testdir/test_method.vim delete mode 100644 src/nvim/testdir/test_mksession.vim delete mode 100644 src/nvim/testdir/test_mksession_utf8.vim delete mode 100644 src/nvim/testdir/test_modeline.vim delete mode 100644 src/nvim/testdir/test_move.vim delete mode 100644 src/nvim/testdir/test_nested_function.vim delete mode 100644 src/nvim/testdir/test_normal.vim delete mode 100644 src/nvim/testdir/test_number.vim delete mode 100644 src/nvim/testdir/test_options.vim delete mode 100644 src/nvim/testdir/test_packadd.vim delete mode 100644 src/nvim/testdir/test_partial.vim delete mode 100644 src/nvim/testdir/test_paste.vim delete mode 100644 src/nvim/testdir/test_perl.vim delete mode 100644 src/nvim/testdir/test_plus_arg_edit.vim delete mode 100644 src/nvim/testdir/test_popup.vim delete mode 100644 src/nvim/testdir/test_preview.vim delete mode 100644 src/nvim/testdir/test_profile.vim delete mode 100644 src/nvim/testdir/test_prompt_buffer.vim delete mode 100644 src/nvim/testdir/test_put.vim delete mode 100644 src/nvim/testdir/test_python2.vim delete mode 100644 src/nvim/testdir/test_python3.vim delete mode 100644 src/nvim/testdir/test_pyx2.vim delete mode 100644 src/nvim/testdir/test_pyx3.vim delete mode 100644 src/nvim/testdir/test_quickfix.vim delete mode 100644 src/nvim/testdir/test_quotestar.vim delete mode 100644 src/nvim/testdir/test_random.vim delete mode 100644 src/nvim/testdir/test_recover.vim delete mode 100644 src/nvim/testdir/test_regex_char_classes.vim delete mode 100644 src/nvim/testdir/test_regexp_latin.vim delete mode 100644 src/nvim/testdir/test_regexp_utf8.vim delete mode 100644 src/nvim/testdir/test_registers.vim delete mode 100644 src/nvim/testdir/test_reltime.vim delete mode 100644 src/nvim/testdir/test_rename.vim delete mode 100644 src/nvim/testdir/test_retab.vim delete mode 100644 src/nvim/testdir/test_ruby.vim delete mode 100644 src/nvim/testdir/test_scriptnames.vim delete mode 100644 src/nvim/testdir/test_scroll_opt.vim delete mode 100644 src/nvim/testdir/test_scrollbind.vim delete mode 100644 src/nvim/testdir/test_search.vim delete mode 100644 src/nvim/testdir/test_search_stat.vim delete mode 100644 src/nvim/testdir/test_searchpos.vim delete mode 100644 src/nvim/testdir/test_selectmode.vim delete mode 100644 src/nvim/testdir/test_set.vim delete mode 100644 src/nvim/testdir/test_sha256.vim delete mode 100644 src/nvim/testdir/test_shell.vim delete mode 100644 src/nvim/testdir/test_shift.vim delete mode 100644 src/nvim/testdir/test_signals.vim delete mode 100644 src/nvim/testdir/test_signs.vim delete mode 100644 src/nvim/testdir/test_sleep.vim delete mode 100644 src/nvim/testdir/test_smartindent.vim delete mode 100644 src/nvim/testdir/test_sort.vim delete mode 100644 src/nvim/testdir/test_source.vim delete mode 100644 src/nvim/testdir/test_source_utf8.vim delete mode 100644 src/nvim/testdir/test_spell.vim delete mode 100644 src/nvim/testdir/test_spell_utf8.vim delete mode 100644 src/nvim/testdir/test_spellfile.vim delete mode 100644 src/nvim/testdir/test_startup.vim delete mode 100644 src/nvim/testdir/test_startup_utf8.vim delete mode 100644 src/nvim/testdir/test_stat.vim delete mode 100644 src/nvim/testdir/test_statusline.vim delete mode 100644 src/nvim/testdir/test_substitute.vim delete mode 100644 src/nvim/testdir/test_suspend.vim delete mode 100644 src/nvim/testdir/test_swap.vim delete mode 100644 src/nvim/testdir/test_syn_attr.vim delete mode 100644 src/nvim/testdir/test_syntax.vim delete mode 100644 src/nvim/testdir/test_system.vim delete mode 100644 src/nvim/testdir/test_tab.vim delete mode 100644 src/nvim/testdir/test_tabline.vim delete mode 100644 src/nvim/testdir/test_tabpage.vim delete mode 100644 src/nvim/testdir/test_tagcase.vim delete mode 100644 src/nvim/testdir/test_tagfunc.vim delete mode 100644 src/nvim/testdir/test_tagjump.vim delete mode 100644 src/nvim/testdir/test_taglist.vim delete mode 100644 src/nvim/testdir/test_termcodes.vim delete mode 100644 src/nvim/testdir/test_textformat.vim delete mode 100644 src/nvim/testdir/test_textobjects.vim delete mode 100644 src/nvim/testdir/test_timers.vim delete mode 100644 src/nvim/testdir/test_true_false.vim delete mode 100644 src/nvim/testdir/test_trycatch.vim delete mode 100644 src/nvim/testdir/test_undo.vim delete mode 100644 src/nvim/testdir/test_unlet.vim delete mode 100644 src/nvim/testdir/test_user_func.vim delete mode 100644 src/nvim/testdir/test_usercommands.vim delete mode 100644 src/nvim/testdir/test_utf8.vim delete mode 100644 src/nvim/testdir/test_utf8_comparisons.vim delete mode 100644 src/nvim/testdir/test_vartabs.vim delete mode 100644 src/nvim/testdir/test_version.vim delete mode 100644 src/nvim/testdir/test_viminfo.vim delete mode 100644 src/nvim/testdir/test_vimscript.vim delete mode 100644 src/nvim/testdir/test_virtualedit.vim delete mode 100644 src/nvim/testdir/test_visual.vim delete mode 100644 src/nvim/testdir/test_winbuf_close.vim delete mode 100644 src/nvim/testdir/test_window_cmd.vim delete mode 100644 src/nvim/testdir/test_window_id.vim delete mode 100644 src/nvim/testdir/test_windows_home.vim delete mode 100644 src/nvim/testdir/test_wnext.vim delete mode 100644 src/nvim/testdir/test_wordcount.vim delete mode 100644 src/nvim/testdir/test_writefile.vim delete mode 100644 src/nvim/testdir/unix.vim delete mode 100644 src/nvim/testdir/view_util.vim delete mode 100644 src/nvim/testdir/vim9.vim (limited to 'src') diff --git a/src/nvim/testdir/Make_all.mak b/src/nvim/testdir/Make_all.mak deleted file mode 100644 index b917877422..0000000000 --- a/src/nvim/testdir/Make_all.mak +++ /dev/null @@ -1 +0,0 @@ -# Tests may depend on the existence of this file. diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile deleted file mode 100644 index 9511b311e6..0000000000 --- a/src/nvim/testdir/Makefile +++ /dev/null @@ -1,154 +0,0 @@ -# vim: noet ts=8 -# Makefile to run all tests for Vim -# - -ifeq ($(OS),Windows_NT) - NVIM_PRG ?= ../../../build/bin/nvim.exe -else - NVIM_PRG ?= ../../../build/bin/nvim -endif -ROOT := ../../.. - -export SHELL := sh -export NVIM_PRG := $(NVIM_PRG) -export TMPDIR := $(abspath X-test-tmpdir) - -ifeq ($(OS),Windows_NT) - FIXFF = fixff -else - FIXFF = -endif - -# Tests using runtest.vim. -NEW_TESTS_ALOT := test_alot_utf8 test_alot test_alot_latin -NEW_TESTS_IN_ALOT := $(shell sed -n '/^source/ s/^source //; s/\.vim$$//p' $(addsuffix .vim,$(NEW_TESTS_ALOT))) -# Ignored tests. -# test_largefile: uses too much resources to run on CI. -NEW_TESTS_IGNORE := \ - test_largefile \ - -NEW_TESTS := $(sort $(basename $(notdir $(wildcard test_*.vim)))) -NEW_TESTS_RES := $(addsuffix .res,$(filter-out $(NEW_TESTS_ALOT) $(NEW_TESTS_IN_ALOT) $(NEW_TESTS_IGNORE),$(NEW_TESTS)) $(NEW_TESTS_ALOT)) - - -ifdef VALGRIND_GDB - VGDB := --vgdb=yes \ - --vgdb-error=0 -endif - -ifdef USE_VALGRIND - VALGRIND_TOOL := --tool=memcheck \ - --leak-check=yes \ - --track-origins=yes -# VALGRIND_TOOL := exp-sgcheck - TOOL := valgrind -q \ - -q \ - $(VALGRIND_TOOL) \ - --suppressions=../../.valgrind.supp \ - --error-exitcode=123 \ - --log-file=valgrind-\%p.$* \ - $(VGDB) \ - --trace-children=yes -else - ifdef USE_GDB - TOOL = gdb --args - endif -endif - -nongui: nolog $(FIXFF) newtests report - -.gdbinit: - @echo "[OLDTEST-PREP] Setting up .gdbinit" - @echo 'set $$_exitcode = -1\nrun\nif $$_exitcode != -1\n quit\nend' > .gdbinit - -report: - $(NVIM_PRG) -u NONE $(NO_INITS) -S summarize.vim messages - @echo - @echo 'Test results:' - @cat test_result.log - @/bin/sh -c "if test -f test.log; \ - then echo TEST FAILURE; exit 1; \ - else echo ALL DONE; \ - fi" - -test1.out: $(NVIM_PRG) - -NO_PLUGINS = --noplugin --headless -# In vim, if the -u command line option is specified, compatible is turned on -# and viminfo is not read. Unlike vim, neovim reads viminfo and requires the -# -i command line option. -NO_INITS = -U NONE -i NONE $(NO_PLUGINS) - -# TODO: find a way to avoid changing the distributed files. -fixff: - -$(NVIM_PRG) $(NO_INITS) -u unix.vim "+argdo set ff=dos|upd" +q \ - *.in *.ok - -$(NVIM_PRG) $(NO_INITS) -u unix.vim "+argdo set ff=dos|upd" +q \ - dotest.in - -# Execute an individual new style test, e.g.: -# make test_largefile -$(NEW_TESTS): - rm -f $@.res test.log messages - @MAKEFLAGS=--no-print-directory $(MAKE) -f Makefile $@.res - @cat messages - @if test -f test.log; then \ - exit 1; \ - fi - -RM_ON_RUN := test.out X* viminfo -RM_ON_START := test.ok -RUN_VIM := $(TOOL) $(NVIM_PRG) -u unix.vim -U NONE -i viminfo --headless --noplugin -s dotest.in - -# Delete files that may interfere with running tests. This includes some files -# that may result from working on the tests, not only from running them. -CLEAN_FILES := *.out \ - *.failed \ - *.res \ - *.rej \ - *.orig \ - *.tlog \ - test.log \ - test_result.log \ - messages \ - $(RM_ON_RUN) \ - $(RM_ON_START) \ - valgrind.* \ - .*.swp \ - .*.swo \ - .gdbinit \ - $(TMPDIR) \ - del -clean: - $(RM) -rf $(CLEAN_FILES) - -test1.out: .gdbinit test1.in - @echo "[OLDTEST-PREP] Running test1" - @rm -rf $*.failed $(RM_ON_RUN) $(RM_ON_START) wrongtermsize - @mkdir -p $(TMPDIR) - @/bin/sh runnvim.sh $(ROOT) $(NVIM_PRG) $* $(RUN_VIM) $*.in - @rm -f wrongtermsize - @rm -rf X* viminfo - -nolog: - @echo "[OLDTEST-PREP] Removing test.log and messages" - @rm -f test.log messages - - -# New style of tests uses Vim script with assert calls. These are easier -# to write and a lot easier to read and debug. -# Limitation: Only works with the +eval feature. -RUN_VIMTEST = $(TOOL) $(NVIM_PRG) -u unix.vim - -newtests: newtestssilent - @/bin/sh -c "if test -f messages && grep -q 'FAILED' messages; then \ - cat messages && cat test.log; \ - fi" - -newtestssilent: $(NEW_TESTS_RES) - -%.res: %.vim .gdbinit - @echo "[OLDTEST] Running" $* - @rm -rf $*.failed test.ok $(RM_ON_RUN) - @mkdir -p $(TMPDIR) - @/bin/sh runnvim.sh $(ROOT) $(NVIM_PRG) $* $(RUN_VIMTEST) $(NO_INITS) -u NONE --cmd "set shortmess-=F" -S runtest.vim $*.vim diff --git a/src/nvim/testdir/README.txt b/src/nvim/testdir/README.txt deleted file mode 100644 index b8bc52f1e6..0000000000 --- a/src/nvim/testdir/README.txt +++ /dev/null @@ -1,121 +0,0 @@ -This directory contains tests for various Vim features. -For testing an indent script see runtime/indent/testdir/README.txt. - -If it makes sense, add a new test method to an already existing file. You may -want to separate it from other tests with comment lines. - -TO ADD A NEW STYLE TEST: - -1) Create a test_.vim file. -2) Add test_.res to NEW_TESTS_RES in Make_all.mak in alphabetical - order. -3) Also add an entry "test_" to NEW_TESTS in Make_all.mak. -4) Use make test_ to run a single test. - -At 2), instead of running the test separately, it can be included in -"test_alot". Do this for quick tests without side effects. The test runs a -bit faster, because Vim doesn't have to be started, one Vim instance runs many -tests. - -At 4), to run a test in GUI, add "GUI_FLAG=-g" to the make command. - - -What you can use (see test_assert.vim for an example): - -- Call assert_equal(), assert_true(), assert_false(), etc. - -- Use assert_fails() to check for expected errors. - -- Use try/catch to avoid an exception aborts the test. - -- Use test_alloc_fail() to have memory allocation fail. This makes it possible - to check memory allocation failures are handled gracefully. You need to - change the source code to add an ID to the allocation. Add a new one to - alloc_id_T, before aid_last. - -- Use test_override() to make Vim behave differently, e.g. if char_avail() - must return FALSE for a while. E.g. to trigger the CursorMovedI autocommand - event. See test_cursor_func.vim for an example. - -- If the bug that is being tested isn't fixed yet, you can throw an exception - with "Skipped" so that it's clear this still needs work. E.g.: throw - "Skipped: Bug with and popupmenu not fixed yet" - -- The following environment variables are recognized and can be set to - influence the behavior of the test suite (see runtest.vim for details) - - - $TEST_MAY_FAIL=Test_channel_one - ignore those failing tests - - $TEST_FILTER=Test_channel - only run test that match this pattern - - $TEST_SKIP_PAT=Test_channel - skip tests that match this pattern - - $TEST_NO_RETRY=yes - do not try to re-run failing tests - You can also set them in Vim: - :let $TEST_MAY_FAIL = 'Test_channel_one' - :let $TEST_FILTER = '_set_mode' - :let $TEST_SKIP_PAT = 'Test_loop_forever' - :let $TEST_NO_RETRY = 'yes' - Use an empty string to revert, e.g.: - :let $TEST_FILTER = '' - -- See the start of runtest.vim for more help. - - -TO ADD A SCREEN DUMP TEST: - -Mostly the same as writing a new style test. Additionally, see help on -"terminal-dumptest". Put the reference dump in "dumps/Test_func_name.dump". - - -OLD STYLE TESTS: - -There are a few tests that are used when Vim was built without the +eval -feature. These cannot use the "assert" functions, therefore they consist of a -.in file that contains Normal mode commands between STARTTEST and ENDTEST. -They modify the file and the result gets written in the test.out file. This -is then compared with the .ok file. If they are equal the test passed. If -they differ the test failed. - - -RUNNING THE TESTS: - -To run a single test from the src directory: - - $ make test_ - -The below commands should be run from the src/testdir directory. - -To run a single test: - - $ make test_.res - -The file 'messages' contains the messages generated by the test script. If a -test fails, then the test.log file contains the error messages. If all the -tests are successful, then this file will be an empty file. - -- To run a single test function from a test script: - - $ ../vim -u NONE -S runtest.vim .vim - -- To execute only specific test functions, add a second argument: - - $ ../vim -u NONE -S runtest.vim test_channel.vim open_delay - - -- To run all the tests: - - $ make - -- To run the test on MS-Windows using the MSVC nmake: - - > nmake -f Make_dos.mak - -- To run the tests with GUI Vim: - - $ make GUI_FLAG=-g - - or - - $ make VIMPROG=../gvim - -- To cleanup the temporary files after running the tests: - - $ make clean diff --git a/src/nvim/testdir/check.vim b/src/nvim/testdir/check.vim deleted file mode 100644 index 680a59006b..0000000000 --- a/src/nvim/testdir/check.vim +++ /dev/null @@ -1,217 +0,0 @@ -source shared.vim -source term_util.vim - -command -nargs=1 MissingFeature throw 'Skipped: ' .. .. ' feature missing' - -" Command to check for the presence of a feature. -command -nargs=1 CheckFeature call CheckFeature() -func CheckFeature(name) - " if !has(a:name, 1) - " throw 'Checking for non-existent feature ' .. a:name - " endif - if !has(a:name) - MissingFeature a:name - endif -endfunc - -" Command to check for the absence of a feature. -command -nargs=1 CheckNotFeature call CheckNotFeature() -func CheckNotFeature(name) - " if !has(a:name, 1) - " throw 'Checking for non-existent feature ' .. a:name - " endif - if has(a:name) - throw 'Skipped: ' .. a:name .. ' feature present' - endif -endfunc - -" Command to check for the presence of a working option. -command -nargs=1 CheckOption call CheckOption() -func CheckOption(name) - if !exists('&' .. a:name) - throw 'Checking for non-existent option ' .. a:name - endif - if !exists('+' .. a:name) - throw 'Skipped: ' .. a:name .. ' option not supported' - endif -endfunc - -" Command to check for the presence of a function. -command -nargs=1 CheckFunction call CheckFunction() -func CheckFunction(name) - if !exists('*' .. a:name) - throw 'Skipped: ' .. a:name .. ' function missing' - endif -endfunc - -" Command to check for the presence of an Ex command -command -nargs=1 CheckCommand call CheckCommand() -func CheckCommand(name) - if !exists(':' .. a:name) - throw 'Skipped: ' .. a:name .. ' command not supported' - endif -endfunc - -" Command to check for the presence of a shell command -command -nargs=1 CheckExecutable call CheckExecutable() -func CheckExecutable(name) - if !executable(a:name) - throw 'Skipped: ' .. a:name .. ' program not executable' - endif -endfunc - -" Command to check for the presence of python. Argument should have been -" obtained with PythonProg() -func CheckPython(name) - if a:name == '' - throw 'Skipped: python command not available' - endif -endfunc - -" Command to check for running on MS-Windows -command CheckMSWindows call CheckMSWindows() -func CheckMSWindows() - if !has('win32') - throw 'Skipped: only works on MS-Windows' - endif -endfunc - -" Command to check for NOT running on MS-Windows -command CheckNotMSWindows call CheckNotMSWindows() -func CheckNotMSWindows() - if has('win32') - throw 'Skipped: does not work on MS-Windows' - endif -endfunc - -" Command to check for running on Unix -command CheckUnix call CheckUnix() -func CheckUnix() - if !has('unix') - throw 'Skipped: only works on Unix' - endif -endfunc - -" Command to check for running on Linux -command CheckLinux call CheckLinux() -func CheckLinux() - if !has('linux') - throw 'Skipped: only works on Linux' - endif -endfunc - -" Command to check that making screendumps is supported. -" Caller must source screendump.vim -command CheckScreendump call CheckScreendump() -func CheckScreendump() - if !CanRunVimInTerminal() - throw 'Skipped: cannot make screendumps' - endif -endfunc - -" Command to check that we can Run Vim in a terminal window -command CheckRunVimInTerminal call CheckRunVimInTerminal() -func CheckRunVimInTerminal() - if !CanRunVimInTerminal() - throw 'Skipped: cannot run Vim in a terminal window' - endif -endfunc - -" Command to check that we can run the GUI -command CheckCanRunGui call CheckCanRunGui() -func CheckCanRunGui() - if !has('gui') || ($DISPLAY == "" && !has('gui_running')) - throw 'Skipped: cannot start the GUI' - endif -endfunc - -" Command to Check for an environment variable -command -nargs=1 CheckEnv call CheckEnv() -func CheckEnv(name) - if empty(eval('$' .. a:name)) - throw 'Skipped: Environment variable ' .. a:name .. ' is not set' - endif -endfunc - -" Command to check that we are using the GUI -command CheckGui call CheckGui() -func CheckGui() - if !has('gui_running') - throw 'Skipped: only works in the GUI' - endif -endfunc - -" Command to check that not currently using the GUI -command CheckNotGui call CheckNotGui() -func CheckNotGui() - if has('gui_running') - throw 'Skipped: only works in the terminal' - endif -endfunc - -" Command to check that test is not running as root -command CheckNotRoot call CheckNotRoot() -func CheckNotRoot() - if IsRoot() - throw 'Skipped: cannot run test as root' - endif -endfunc - -" Command to check that the current language is English -command CheckEnglish call CheckEnglish() -func CheckEnglish() - if v:lang != "C" && v:lang !~ '^[Ee]n' - throw 'Skipped: only works in English language environment' - endif -endfunc - -" Command to check for not running under ASAN -command CheckNotAsan call CheckNotAsan() -func CheckNotAsan() - if execute('version') =~# '-fsanitize=[a-z,]*\' - throw 'Skipped: does not work with ASAN' - endif -endfunc - -" Command to check for not running under valgrind -command CheckNotValgrind call CheckNotValgrind() -func CheckNotValgrind() - if RunningWithValgrind() - throw 'Skipped: does not work well with valgrind' - endif -endfunc - -" Command to check for X11 based GUI -command CheckX11BasedGui call CheckX11BasedGui() -func CheckX11BasedGui() - if !g:x11_based_gui - throw 'Skipped: requires X11 based GUI' - endif -endfunc - -" Command to check for satisfying any of the conditions. -" e.g. CheckAnyOf Feature:bsd Feature:sun Linux -command -nargs=+ CheckAnyOf call CheckAnyOf() -func CheckAnyOf(...) - let excp = [] - for arg in a:000 - try - exe 'Check' .. substitute(arg, ':', ' ', '') - return - catch /^Skipped:/ - let excp += [substitute(v:exception, '^Skipped:\s*', '', '')] - endtry - endfor - throw 'Skipped: ' .. join(excp, '; ') -endfunc - -" Command to check for satisfying all of the conditions. -" e.g. CheckAllOf Unix Gui Option:ballooneval -command -nargs=+ CheckAllOf call CheckAllOf() -func CheckAllOf(...) - for arg in a:000 - exe 'Check' .. substitute(arg, ':', ' ', '') - endfor -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/dotest.in b/src/nvim/testdir/dotest.in deleted file mode 100644 index 2ef4576f4e..0000000000 --- a/src/nvim/testdir/dotest.in +++ /dev/null @@ -1,3 +0,0 @@ -:set nomore -:map dotest /^STARTTEST j:set ff=unix cpo-=A :.,/ENDTEST/-1w! Xdotest :set ff& cpo+=A nj0:so! Xdotest dotest -dotest diff --git a/src/nvim/testdir/load.vim b/src/nvim/testdir/load.vim deleted file mode 100644 index 5697ee7304..0000000000 --- a/src/nvim/testdir/load.vim +++ /dev/null @@ -1,32 +0,0 @@ -" Also used by: test/functional/helpers.lua - -function! s:load_factor() abort - let timeout = 200 - let times = [] - - for _ in range(5) - let g:val = 0 - let start = reltime() - call timer_start(timeout, {-> nvim_set_var('val', 1)}) - while 1 - sleep 10m - if g:val == 1 - let g:waited_in_ms = float2nr(reltimefloat(reltime(start)) * 1000) - break - endif - endwhile - call insert(times, g:waited_in_ms, 0) - endfor - - let longest = max(times) - let factor = (longest + 50.0) / timeout - - return factor -endfunction - -" Compute load factor only once. -let g:test_load_factor = s:load_factor() - -function! LoadAdjust(num) abort - return float2nr(ceil(a:num * g:test_load_factor)) -endfunction diff --git a/src/nvim/testdir/pyxfile/py2_magic.py b/src/nvim/testdir/pyxfile/py2_magic.py deleted file mode 100644 index 819892fd16..0000000000 --- a/src/nvim/testdir/pyxfile/py2_magic.py +++ /dev/null @@ -1,4 +0,0 @@ -# requires python 2.x - -import sys -print(sys.version) diff --git a/src/nvim/testdir/pyxfile/py2_shebang.py b/src/nvim/testdir/pyxfile/py2_shebang.py deleted file mode 100644 index 13bfc491ec..0000000000 --- a/src/nvim/testdir/pyxfile/py2_shebang.py +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/python2 - -import sys -print(sys.version) diff --git a/src/nvim/testdir/pyxfile/py3_magic.py b/src/nvim/testdir/pyxfile/py3_magic.py deleted file mode 100644 index d4b7ee0071..0000000000 --- a/src/nvim/testdir/pyxfile/py3_magic.py +++ /dev/null @@ -1,4 +0,0 @@ -# requires python 3.x - -import sys -print(sys.version) diff --git a/src/nvim/testdir/pyxfile/py3_shebang.py b/src/nvim/testdir/pyxfile/py3_shebang.py deleted file mode 100644 index ec05808ca4..0000000000 --- a/src/nvim/testdir/pyxfile/py3_shebang.py +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/python3 - -import sys -print(sys.version) diff --git a/src/nvim/testdir/pyxfile/pyx.py b/src/nvim/testdir/pyxfile/pyx.py deleted file mode 100644 index 261a6512c0..0000000000 --- a/src/nvim/testdir/pyxfile/pyx.py +++ /dev/null @@ -1,2 +0,0 @@ -import sys -print(sys.version) diff --git a/src/nvim/testdir/runnvim.sh b/src/nvim/testdir/runnvim.sh deleted file mode 100755 index 4d8ea0527d..0000000000 --- a/src/nvim/testdir/runnvim.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env bash - -main() {( - local separator="================================================================================" - local oldesttest= - if test "$1" = "--oldesttest" ; then - shift - oldesttest=1 - fi - local root="$1" ; shift - local nvim_prg="$1" ; shift - local test_name="$1" ; shift - - local tlog="$test_name.tlog" - - export NVIM_TEST_ARGC=$# - local arg - local i=0 - # shellcheck disable=SC2034 # (unused "arg", used in "eval"). - for arg ; do - eval "export NVIM_TEST_ARG$i=\"\$arg\"" - i=$(( i+1 )) - done - - BUILD_DIR="$(dirname "$nvim_prg")/.." - export BUILD_DIR - export FAILED=0 - - . $(dirname $0)/test.sh - - # Redirect XDG_CONFIG_HOME so users local config doesn't interfere - export XDG_CONFIG_HOME="$root" - - export VIMRUNTIME="$root/runtime" - if ! "$nvim_prg" \ - -u NONE -i NONE \ - --headless \ - --cmd 'set shortmess+=I noswapfile noundofile nomore' \ - -S runnvim.vim \ - "$tlog" > "out-$tlog" 2> "err-$tlog" - then - fail "$test_name" "Nvim exited with non-zero code" - fi - { - echo "Stdout of :terminal runner" - echo "$separator" - cat "out-$tlog" - echo "$separator" - echo "Stderr of :terminal runner" - echo "$separator" - cat "err-$tlog" - echo "$separator" - } >> "$tlog" - if test "$oldesttest" = 1 ; then - if ! diff -q test.out "$test_name.ok" > /dev/null 2>&1 ; then - if test -f test.out ; then - fail "$test_name" "Oldest test .out file differs from .ok file" - { - echo "Diff between test.out and $test_name.ok" - echo "$separator" - diff -a test.out "$test_name.ok" - echo "$separator" - } >> "$tlog" - else - echo "No output in test.out" >> "$tlog" - fi - fi - fi - valgrind_check . - if test -n "$LOG_DIR" ; then - check_sanitizer "$LOG_DIR" - fi - check_core_dumps - if test "$FAILED" = 1 ; then - cat "$tlog" - fi - rm -f "$tlog" - if test "$FAILED" = 1 ; then - echo "Test $test_name failed, see output above and summary for more details" >> test.log - # When Neovim crashed/aborted it might not have created messages. - # test.log itself is used as an indicator to exit non-zero in the Makefile. - if ! test -f message; then - cp -a test.log messages - fi - fi -)} - -main "$@" diff --git a/src/nvim/testdir/runnvim.vim b/src/nvim/testdir/runnvim.vim deleted file mode 100644 index a46e2d3fc0..0000000000 --- a/src/nvim/testdir/runnvim.vim +++ /dev/null @@ -1,58 +0,0 @@ -let s:logger = {'d_events': []} -function s:logger.on_stdout(id, data, event) - call add(self.d_events, [a:event, a:data]) -endfunction -let s:logger.on_stderr = s:logger.on_stdout -function s:logger.on_exit(id, data, event) - call add(self.d_events, [a:event, ['']]) -endfunction - -" Replace non-printable chars by special sequence, or "<%x>". -let s:escaped_char = {"\n": '\n', "\r": '\r', "\t": '\t'} -function! s:escape_non_printable(char) abort - let r = get(s:escaped_char, a:char) - return r is 0 ? printf('<%x>', char2nr(a:char)) : r -endfunction - -function Main() - let argc = +$NVIM_TEST_ARGC - let args = [] - for i in range(argc) - call add(args, eval("$NVIM_TEST_ARG" . i)) - endfor - set lines=25 - set columns=80 - enew - let job = termopen(args, s:logger) - let results = jobwait([job], 5 * 60 * 1000) - " TODO(ZyX-I): Get colors - let screen = getline(1, '$') - bwipeout! " kills the job always. - let stringified_events = map(s:logger.d_events, - \'v:val[0] . ": " . ' . - \'join(map(v:val[1], '. - \ '''substitute(v:val, '. - \ '"\\v\\C(\\p@!.|\\<)", '. - \ '"\\=s:escape_non_printable(submatch(0))", '. - \ '"g")''), '. - \ '''\n'')') - call setline(1, [ - \ 'Job exited with code ' . results[0], - \ printf('Screen (%u lines)', len(screen)), - \ repeat('=', 80), - \] + screen + [ - \ repeat('=', 80), - \ printf('Events (%u lines):', len(stringified_events)), - \ repeat('=', 80), - \] + stringified_events + [ - \ repeat('=', 80), - \]) - write - if results[0] != 0 - cquit - else - qall - endif -endfunction - -call Main() diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim deleted file mode 100644 index 3c5699af73..0000000000 --- a/src/nvim/testdir/runtest.vim +++ /dev/null @@ -1,485 +0,0 @@ -" This script is sourced while editing the .vim file with the tests. -" When the script is successful the .res file will be created. -" Errors are appended to the test.log file. -" -" To execute only specific test functions, add a second argument. It will be -" matched against the names of the Test_ function. E.g.: -" ../vim -u NONE -S runtest.vim test_channel.vim open_delay -" The output can be found in the "messages" file. -" -" If the environment variable $TEST_FILTER is set then only test functions -" matching this pattern are executed. E.g. for sh/bash: -" export TEST_FILTER=Test_channel -" For csh: -" setenv TEST_FILTER Test_channel -" -" While working on a test you can make $TEST_NO_RETRY non-empty to not retry: -" export TEST_NO_RETRY=yes -" -" To ignore failure for tests that are known to fail in a certain environment, -" set $TEST_MAY_FAIL to a comma separated list of function names. E.g. for -" sh/bash: -" export TEST_MAY_FAIL=Test_channel_one,Test_channel_other -" The failure report will then not be included in the test.log file and -" "make test" will not fail. -" -" The test script may contain anything, only functions that start with -" "Test_" are special. These will be invoked and should contain assert -" functions. See test_assert.vim for an example. -" -" It is possible to source other files that contain "Test_" functions. This -" can speed up testing, since Vim does not need to restart. But be careful -" that the tests do not interfere with each other. -" -" If an error cannot be detected properly with an assert function add the -" error to the v:errors list: -" call add(v:errors, 'test foo failed: Cannot find xyz') -" -" If preparation for each Test_ function is needed, define a SetUp function. -" It will be called before each Test_ function. -" -" If cleanup after each Test_ function is needed, define a TearDown function. -" It will be called after each Test_ function. -" -" When debugging a test it can be useful to add messages to v:errors: -" call add(v:errors, "this happened") - - -" Check that the screen size is at least 24 x 80 characters. -if &lines < 24 || &columns < 80 - let error = 'Screen size too small! Tests require at least 24 lines with 80 characters, got ' .. &lines .. ' lines with ' .. &columns .. ' characters' - echoerr error - split test.log - $put =error - write - split messages - call append(line('$'), '') - call append(line('$'), 'From ' . expand('%') . ':') - call append(line('$'), error) - write - qa! -endif - -if has('reltime') - let s:start_time = reltime() -endif - -" Always use forward slashes. -set shellslash - -" Common with all tests on all systems. -source setup.vim - -" For consistency run all tests with 'nocompatible' set. -" This also enables use of line continuation. -set nocp viminfo+=nviminfo - -" Use utf-8 by default, instead of whatever the system default happens to be. -" Individual tests can overrule this at the top of the file. -set encoding=utf-8 - -" REDIR_TEST_TO_NULL has a very permissive SwapExists autocommand which is for -" the test_name.vim file itself. Replace it here with a more restrictive one, -" so we still catch mistakes. -let s:test_script_fname = expand('%') -au! SwapExists * call HandleSwapExists() -func HandleSwapExists() - if exists('g:ignoreSwapExists') - return - endif - " Ignore finding a swap file for the test script (the user might be - " editing it and do ":make test_name") and the output file. - " Report finding another swap file and chose 'q' to avoid getting stuck. - if expand('') == 'messages' || expand('') =~ s:test_script_fname - let v:swapchoice = 'e' - else - call assert_report('Unexpected swap file: ' .. v:swapname) - let v:swapchoice = 'q' - endif -endfunc - -" Avoid stopping at the "hit enter" prompt -set nomore - -" Output all messages in English. -lang mess C - -" Nvim: append runtime from build dir, which contains the generated doc/tags. -let &runtimepath ..= ',' .. expand($BUILD_DIR) .. '/runtime/' - -let s:t_bold = &t_md -let s:t_normal = &t_me -if has('win32') - " avoid prompt that is long or contains a line break - let $PROMPT = '$P$G' -endif - -if has('mac') - " In MacOS, when starting a shell in a terminal, a bash deprecation warning - " message is displayed. This breaks the terminal test. Disable the warning - " message. - let $BASH_SILENCE_DEPRECATION_WARNING = 1 -endif - -" Prepare for calling test_garbagecollect_now(). -let v:testing = 1 - -" Support function: get the alloc ID by name. -func GetAllocId(name) - exe 'split ' . s:srcdir . '/alloc.h' - let top = search('typedef enum') - if top == 0 - call add(v:errors, 'typedef not found in alloc.h') - endif - let lnum = search('aid_' . a:name . ',') - if lnum == 0 - call add(v:errors, 'Alloc ID ' . a:name . ' not defined') - endif - close - return lnum - top - 1 -endfunc - -func RunTheTest(test) - echo 'Executing ' . a:test - if has('reltime') - let func_start = reltime() - endif - - " Avoid stopping at the "hit enter" prompt - set nomore - - " Avoid a three second wait when a message is about to be overwritten by the - " mode message. - set noshowmode - - " Some tests wipe out buffers. To be consistent, always wipe out all - " buffers. - %bwipe! - - " The test may change the current directory. Save and restore the - " directory after executing the test. - let save_cwd = getcwd() - - " Align Nvim defaults to Vim. - source setup.vim - - if exists("*SetUp") - try - call SetUp() - catch - call add(v:errors, 'Caught exception in SetUp() before ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) - endtry - endif - - au VimLeavePre * call EarlyExit(g:testfunc) - if a:test =~ 'Test_nocatch_' - " Function handles errors itself. This avoids skipping commands after the - " error. - let g:skipped_reason = '' - exe 'call ' . a:test - if g:skipped_reason != '' - call add(s:messages, ' Skipped') - call add(s:skipped, 'SKIPPED ' . a:test . ': ' . g:skipped_reason) - endif - else - try - exe 'call ' . a:test - catch /^\cskipped/ - call add(s:messages, ' Skipped') - call add(s:skipped, 'SKIPPED ' . a:test . ': ' . substitute(v:exception, '^\S*\s\+', '', '')) - catch - call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) - endtry - endif - au! VimLeavePre - - " In case 'insertmode' was set and something went wrong, make sure it is - " reset to avoid trouble with anything else. - set noinsertmode - - if exists("*TearDown") - try - call TearDown() - catch - call add(v:errors, 'Caught exception in TearDown() after ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) - endtry - endif - - " Clear any autocommands and put back the catch-all for SwapExists. - au! - au SwapExists * call HandleSwapExists() - - " Close any extra tab pages and windows and make the current one not modified. - while tabpagenr('$') > 1 - let winid = win_getid() - quit! - if winid == win_getid() - echoerr 'Could not quit window' - break - endif - endwhile - - while 1 - let wincount = winnr('$') - if wincount == 1 - break - endif - bwipe! - if wincount == winnr('$') - " Did not manage to close a window. - only! - break - endif - endwhile - - exe 'cd ' . save_cwd - - let message = 'Executed ' . a:test - if has('reltime') - let message ..= repeat(' ', 50 - len(message)) - let time = reltime(func_start) - if has('float') && reltimefloat(time) > 0.1 - let message = s:t_bold .. message - endif - let message ..= ' in ' .. reltimestr(time) .. ' seconds' - if has('float') && reltimefloat(time) > 0.1 - let message ..= s:t_normal - endif - endif - call add(s:messages, message) - let s:done += 1 -endfunc - -func AfterTheTest(func_name) - if len(v:errors) > 0 - if match(s:may_fail_list, '^' .. a:func_name) >= 0 - let s:fail_expected += 1 - call add(s:errors_expected, 'Found errors in ' . g:testfunc . ':') - call extend(s:errors_expected, v:errors) - else - let s:fail += 1 - call add(s:errors, 'Found errors in ' . g:testfunc . ':') - call extend(s:errors, v:errors) - endif - let v:errors = [] - endif -endfunc - -func EarlyExit(test) - " It's OK for the test we use to test the quit detection. - if a:test != 'Test_zz_quit_detected()' - call add(v:errors, v:errmsg) - call add(v:errors, 'Test caused Vim to exit: ' . a:test) - endif - - call FinishTesting() -endfunc - -" This function can be called by a test if it wants to abort testing. -func FinishTesting() - call AfterTheTest('') - - " Don't write viminfo on exit. - set viminfo= - - " Clean up files created by setup.vim - call delete('XfakeHOME', 'rf') - - if s:fail == 0 && s:fail_expected == 0 - " Success, create the .res file so that make knows it's done. - exe 'split ' . fnamemodify(g:testname, ':r') . '.res' - write - endif - - if len(s:errors) > 0 - " Append errors to test.log - split test.log - call append(line('$'), '') - call append(line('$'), 'From ' . g:testname . ':') - call append(line('$'), s:errors) - write - endif - - if s:done == 0 - if s:filtered > 0 - let message = "NO tests match $TEST_FILTER: '" .. $TEST_FILTER .. "'" - else - let message = 'NO tests executed' - endif - else - if s:filtered > 0 - call add(s:messages, "Filtered " .. s:filtered .. " tests with $TEST_FILTER") - endif - let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test') - endif - if s:done > 0 && has('reltime') - let message = s:t_bold .. message .. repeat(' ', 40 - len(message)) - let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds' - let message ..= s:t_normal - endif - echo message - call add(s:messages, message) - if s:fail > 0 - let message = s:fail . ' FAILED:' - echo message - call add(s:messages, message) - call extend(s:messages, s:errors) - endif - if s:fail_expected > 0 - let message = s:fail_expected . ' FAILED (matching $TEST_MAY_FAIL):' - echo message - call add(s:messages, message) - call extend(s:messages, s:errors_expected) - endif - - " Add SKIPPED messages - call extend(s:messages, s:skipped) - - " Append messages to the file "messages" - split messages - call append(line('$'), '') - call append(line('$'), 'From ' . g:testname . ':') - call append(line('$'), s:messages) - write - - qall! -endfunc - -" Source the test script. First grab the file name, in case the script -" navigates away. g:testname can be used by the tests. -let g:testname = expand('%') -let s:done = 0 -let s:fail = 0 -let s:fail_expected = 0 -let s:errors = [] -let s:errors_expected = [] -let s:messages = [] -let s:skipped = [] -if expand('%') =~ 'test_vimscript.vim' - " this test has intentional errors, don't use try/catch. - source % -else - try - source % - catch /^\cskipped/ - call add(s:messages, ' Skipped') - call add(s:skipped, 'SKIPPED ' . expand('%') . ': ' . substitute(v:exception, '^\S*\s\+', '', '')) - catch - let s:fail += 1 - call add(s:errors, 'Caught exception: ' . v:exception . ' @ ' . v:throwpoint) - endtry -endif - -" Names of flaky tests. -let s:flaky_tests = [ - \ 'Test_autocmd_SafeState()', - \ 'Test_cursorhold_insert()', - \ 'Test_exit_callback_interval()', - \ 'Test_map_timeout_with_timer_interrupt()', - \ 'Test_out_cb()', - \ 'Test_popup_and_window_resize()', - \ 'Test_quoteplus()', - \ 'Test_quotestar()', - \ 'Test_reltime()', - \ 'Test_state()', - \ 'Test_term_mouse_double_click_to_create_tab()', - \ 'Test_term_mouse_multiple_clicks_to_visually_select()', - \ 'Test_terminal_composing_unicode()', - \ 'Test_terminal_redir_file()', - \ 'Test_terminal_tmap()', - \ 'Test_timer_oneshot()', - \ 'Test_timer_paused()', - \ 'Test_timer_repeat_many()', - \ 'Test_timer_repeat_three()', - \ 'Test_timer_stop_all_in_callback()', - \ 'Test_timer_stop_in_callback()', - \ 'Test_timer_with_partial_callback()', - \ 'Test_termwinscroll()', - \ ] - -" Locate Test_ functions and execute them. -redir @q -silent function /^Test_ -redir END -let s:tests = split(substitute(@q, 'function \(\k*()\)', '\1', 'g')) - -" If there is an extra argument filter the function names against it. -if argc() > 1 - let s:tests = filter(s:tests, 'v:val =~ argv(1)') -endif - -" If the environment variable $TEST_FILTER is set then filter the function -" names against it. -let s:filtered = 0 -if $TEST_FILTER != '' - let s:filtered = len(s:tests) - let s:tests = filter(s:tests, 'v:val =~ $TEST_FILTER') - let s:filtered -= len(s:tests) -endif - -let s:may_fail_list = [] -if $TEST_MAY_FAIL != '' - " Split the list at commas and add () to make it match g:testfunc. - let s:may_fail_list = split($TEST_MAY_FAIL, ',')->map({i, v -> v .. '()'}) -endif - -" Execute the tests in alphabetical order. -for g:testfunc in sort(s:tests) - " Silence, please! - set belloff=all - let prev_error = '' - let total_errors = [] - let g:run_nr = 1 - - " A test can set g:test_is_flaky to retry running the test. - let g:test_is_flaky = 0 - - call RunTheTest(g:testfunc) - - " Repeat a flaky test. Give up when: - " - $TEST_NO_RETRY is not empty - " - it fails again with the same message - " - it fails five times (with a different message) - if len(v:errors) > 0 - \ && $TEST_NO_RETRY == '' - \ && (index(s:flaky_tests, g:testfunc) >= 0 - \ || g:test_is_flaky) - while 1 - call add(s:messages, 'Found errors in ' . g:testfunc . ':') - call extend(s:messages, v:errors) - - call add(total_errors, 'Run ' . g:run_nr . ':') - call extend(total_errors, v:errors) - - if g:run_nr >= 5 || prev_error == v:errors[0] - call add(total_errors, 'Flaky test failed too often, giving up') - let v:errors = total_errors - break - endif - - call add(s:messages, 'Flaky test failed, running it again') - - " Flakiness is often caused by the system being very busy. Sleep a - " couple of seconds to have a higher chance of succeeding the second - " time. - sleep 2 - - let prev_error = v:errors[0] - let v:errors = [] - let g:run_nr += 1 - - call RunTheTest(g:testfunc) - - if len(v:errors) == 0 - " Test passed on rerun. - break - endif - endwhile - endif - - call AfterTheTest(g:testfunc) -endfor - -call FinishTesting() - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/samples/memfile_test.c b/src/nvim/testdir/samples/memfile_test.c deleted file mode 100644 index 73f67fb250..0000000000 --- a/src/nvim/testdir/samples/memfile_test.c +++ /dev/null @@ -1,148 +0,0 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - -// uncrustify:off - -/* vi:set ts=8 sts=4 sw=4 noet: - * - * VIM - Vi IMproved by Bram Moolenaar - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - * See README.txt for an overview of the Vim source code. - */ - -/* - * memfile_test.c: Unittests for memfile.c - * Mostly by Ivan Krasilnikov. - */ - -#undef NDEBUG -#include - -/* Must include main.c because it contains much more than just main() */ -#define NO_VIM_MAIN -#include "main.c" - -/* This file has to be included because the tested functions are static */ -#include "memfile.c" - -#define index_to_key(i) ((i) ^ 15167) -#define TEST_COUNT 50000 - -/* - * Test mf_hash_*() functions. - */ - static void -test_mf_hash(void) -{ - mf_hashtab_T ht; - mf_hashitem_T *item; - blocknr_T key; - size_t i; - size_t num_buckets; - - mf_hash_init(&ht); - - /* insert some items and check invariants */ - for (i = 0; i < TEST_COUNT; i++) - { - assert(ht.mht_count == i); - - /* check that number of buckets is a power of 2 */ - num_buckets = ht.mht_mask + 1; - assert(num_buckets > 0 && (num_buckets & (num_buckets - 1)) == 0); - - /* check load factor */ - assert(ht.mht_count <= (num_buckets << MHT_LOG_LOAD_FACTOR)); - - if (i < (MHT_INIT_SIZE << MHT_LOG_LOAD_FACTOR)) - { - /* first expansion shouldn't have occurred yet */ - assert(num_buckets == MHT_INIT_SIZE); - assert(ht.mht_buckets == ht.mht_small_buckets); - } - else - { - assert(num_buckets > MHT_INIT_SIZE); - assert(ht.mht_buckets != ht.mht_small_buckets); - } - - key = index_to_key(i); - assert(mf_hash_find(&ht, key) == NULL); - - /* allocate and add new item */ - item = (mf_hashitem_T *)lalloc_clear(sizeof(*item), FALSE); - assert(item != NULL); - item->mhi_key = key; - mf_hash_add_item(&ht, item); - - assert(mf_hash_find(&ht, key) == item); - - if (ht.mht_mask + 1 != num_buckets) - { - /* hash table was expanded */ - assert(ht.mht_mask + 1 == num_buckets * MHT_GROWTH_FACTOR); - assert(i + 1 == (num_buckets << MHT_LOG_LOAD_FACTOR)); - } - } - - /* check presence of inserted items */ - for (i = 0; i < TEST_COUNT; i++) - { - key = index_to_key(i); - item = mf_hash_find(&ht, key); - assert(item != NULL); - assert(item->mhi_key == key); - } - - /* delete some items */ - for (i = 0; i < TEST_COUNT; i++) - { - if (i % 100 < 70) - { - key = index_to_key(i); - item = mf_hash_find(&ht, key); - assert(item != NULL); - assert(item->mhi_key == key); - - mf_hash_rem_item(&ht, item); - assert(mf_hash_find(&ht, key) == NULL); - - mf_hash_add_item(&ht, item); - assert(mf_hash_find(&ht, key) == item); - - mf_hash_rem_item(&ht, item); - assert(mf_hash_find(&ht, key) == NULL); - - vim_free(item); - } - } - - /* check again */ - for (i = 0; i < TEST_COUNT; i++) - { - key = index_to_key(i); - item = mf_hash_find(&ht, key); - - if (i % 100 < 70) - { - assert(item == NULL); - } - else - { - assert(item != NULL); - assert(item->mhi_key == key); - } - } - - /* free hash table and all remaining items */ - mf_hash_free_all(&ht); -} - - int -main(void) -{ - test_mf_hash(); - return 0; -} diff --git a/src/nvim/testdir/samples/quickfix.txt b/src/nvim/testdir/samples/quickfix.txt deleted file mode 100644 index 2de3835473..0000000000 --- a/src/nvim/testdir/samples/quickfix.txt +++ /dev/null @@ -1,4 +0,0 @@ -samples/quickfix.txt:1:1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -samples/quickfix.txt:2:1:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb -samples/quickfix.txt:3:1:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -samples/quickfix.txt:4:1:dddddddddd diff --git a/src/nvim/testdir/samples/re.freeze.txt b/src/nvim/testdir/samples/re.freeze.txt deleted file mode 100644 index d768c23c5e..0000000000 --- a/src/nvim/testdir/samples/re.freeze.txt +++ /dev/null @@ -1,6 +0,0 @@ -:set re=0 or 2 -Search for the pattern: /\s\+\%#\@55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555 - diff --git a/src/nvim/testdir/sautest/autoload/foo.vim b/src/nvim/testdir/sautest/autoload/foo.vim deleted file mode 100644 index 21d33a0f4d..0000000000 --- a/src/nvim/testdir/sautest/autoload/foo.vim +++ /dev/null @@ -1,15 +0,0 @@ -let g:loaded_foo_vim += 1 - -let foo#bar = {} - -func foo#bar.echo() - let g:called_foo_bar_echo += 1 -endfunc - -func foo#addFoo(head) - return a:head .. 'foo' -endfunc - -func foo#() - return 'empty' -endfunc diff --git a/src/nvim/testdir/sautest/autoload/footest.vim b/src/nvim/testdir/sautest/autoload/footest.vim deleted file mode 100644 index 1e78963a10..0000000000 --- a/src/nvim/testdir/sautest/autoload/footest.vim +++ /dev/null @@ -1,5 +0,0 @@ -" Autoload script used by test_listdict.vim, test_exists.vim and test_let.vim -let footest#x = 1 -func footest#F() - return 0 -endfunc diff --git a/src/nvim/testdir/sautest/autoload/globone.vim b/src/nvim/testdir/sautest/autoload/globone.vim deleted file mode 100644 index 98c9a10582..0000000000 --- a/src/nvim/testdir/sautest/autoload/globone.vim +++ /dev/null @@ -1 +0,0 @@ -" used by Test_globpath() diff --git a/src/nvim/testdir/sautest/autoload/globtwo.vim b/src/nvim/testdir/sautest/autoload/globtwo.vim deleted file mode 100644 index 98c9a10582..0000000000 --- a/src/nvim/testdir/sautest/autoload/globtwo.vim +++ /dev/null @@ -1 +0,0 @@ -" used by Test_globpath() diff --git a/src/nvim/testdir/sautest/autoload/sourced.vim b/src/nvim/testdir/sautest/autoload/sourced.vim deleted file mode 100644 index f69f00cb53..0000000000 --- a/src/nvim/testdir/sautest/autoload/sourced.vim +++ /dev/null @@ -1,3 +0,0 @@ -let g:loaded_sourced_vim += 1 -func! sourced#something() -endfunc diff --git a/src/nvim/testdir/screendump.vim b/src/nvim/testdir/screendump.vim deleted file mode 100644 index 8afff1da91..0000000000 --- a/src/nvim/testdir/screendump.vim +++ /dev/null @@ -1,2 +0,0 @@ -source shared.vim -source term_util.vim diff --git a/src/nvim/testdir/script_util.vim b/src/nvim/testdir/script_util.vim deleted file mode 100644 index 28d6a621d6..0000000000 --- a/src/nvim/testdir/script_util.vim +++ /dev/null @@ -1,69 +0,0 @@ -" Functions shared by the tests for Vim Script - -" Commands to track the execution path of a script -com! XpathINIT let g:Xpath = '' -com! -nargs=1 -bar Xpath let g:Xpath ..= -com! XloopINIT let g:Xloop = 1 -com! -nargs=1 -bar Xloop let g:Xpath ..= .. g:Xloop -com! XloopNEXT let g:Xloop += 1 - -" MakeScript() - Make a script file from a function. {{{2 -" -" Create a script that consists of the body of the function a:funcname. -" Replace any ":return" by a ":finish", any argument variable by a global -" variable, and every ":call" by a ":source" for the next following argument -" in the variable argument list. This function is useful if similar tests are -" to be made for a ":return" from a function call or a ":finish" in a script -" file. -func MakeScript(funcname, ...) - let script = tempname() - execute "redir! >" . script - execute "function" a:funcname - redir END - execute "edit" script - " Delete the "function" and the "endfunction" lines. Do not include the - " word "function" in the pattern since it might be translated if LANG is - " set. When MakeScript() is being debugged, this deletes also the debugging - " output of its line 3 and 4. - exec '1,/.*' . a:funcname . '(.*)/d' - /^\d*\s*endfunction\>/,$d - %s/^\d*//e - %s/return/finish/e - %s/\ 0 - let cnt = cnt + 1 - s/\) - diff --git a/src/nvim/testdir/setup.vim b/src/nvim/testdir/setup.vim deleted file mode 100644 index 25ac2d1239..0000000000 --- a/src/nvim/testdir/setup.vim +++ /dev/null @@ -1,85 +0,0 @@ -if exists('s:did_load') - " Align Nvim defaults to Vim. - set backspace= - set complete=.,w,b,u,t,i - set directory& - set directory^=. - set display= - set fillchars=vert:\|,foldsep:\|,fold:- - set formatoptions=tcq - set fsync - set laststatus=1 - set listchars=eol:$ - set joinspaces - set nohidden nosmarttab noautoindent noautoread noruler noshowcmd - set nohlsearch noincsearch - set nrformats=bin,octal,hex - set shortmess=filnxtToOS - set sidescroll=0 - set tags=./tags,tags - set undodir& - set undodir^=. - set wildoptions= - set startofline - set sessionoptions& - set sessionoptions+=options - set viewoptions& - set viewoptions+=options - set switchbuf= - if g:testname !~ 'test_mapping.vim$' - " Make "Q" switch to Ex mode. - " This does not work for all tests. - nnoremap Q gQ - endif -endif - -" Common preparations for running tests. - -" Only load this once. -if exists('s:did_load') - finish -endif -let s:did_load = 1 - -" Clear Nvim default mappings and menus. -mapclear -mapclear! -aunmenu * -tlunmenu * - -" roughly equivalent to test_setmouse() in Vim -func Ntest_setmouse(row, col) - call nvim_input_mouse('move', '', '', 0, a:row - 1, a:col - 1) -endfunc - -" Prevent Nvim log from writing to stderr. -let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log' - - -" Make sure 'runtimepath' and 'packpath' does not include $HOME. -set rtp=$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after -let &packpath = &rtp - -" Avoid storing shell history. -let $HISTFILE = "" - -" Use default shell on Windows to avoid segfault, caused by TUI -if has('win32') - let $SHELL = '' - let $TERM = '' - let &shell = empty($COMSPEC) ? exepath('cmd.exe') : $COMSPEC - set shellcmdflag=/s/c shellxquote=\" shellredir=>%s\ 2>&1 - let &shellpipe = &shellredir -endif - -" Detect user modules for language providers -let $PYTHONUSERBASE = $HOME . '/.local' -if executable('gem') - let $GEM_PATH = system('gem env gempath') -endif - -" Make sure $HOME does not get read or written. -let $HOME = expand(getcwd() . '/XfakeHOME') -if !isdirectory($HOME) - call mkdir($HOME) -endif diff --git a/src/nvim/testdir/shared.vim b/src/nvim/testdir/shared.vim deleted file mode 100644 index 33f6d9a2d0..0000000000 --- a/src/nvim/testdir/shared.vim +++ /dev/null @@ -1,389 +0,0 @@ -" Functions shared by several tests. - -" Only load this script once. -if exists('*PythonProg') - finish -endif - -source view_util.vim - -" {Nvim} -" Filepath captured from output may be truncated, like this: -" /home/va...estdir/X-test-tmpdir/nvimxbXN4i/10 -" Get last 2 segments, then combine with $TMPDIR. -func! Fix_truncated_tmpfile(fname) - " sanity check - if $TMPDIR ==# '' - throw '$TMPDIR is empty' - endif - let tmpdir_tail = fnamemodify(substitute($TMPDIR, '[\/]\+$', '', 'g'), ':t') - if tmpdir_tail ==# '' - throw 'empty tmpdir_tail' - endif - if a:fname !~# tmpdir_tail - throw printf('$TMPDIR (%s) not in fname: %s', tmpdir_tail, a:fname) - endif - let last2segments = matchstr(a:fname, '[\/][^\/]\+[\/][^\/]\+$') - return $TMPDIR.last2segments -endfunc - -" Get the name of the Python executable. -" Also keeps it in s:python. -func PythonProg() - " This test requires the Python command to run the test server. - " This most likely only works on Unix and Windows. - if has('unix') - " We also need the job feature or the pkill command to make sure the server - " can be stopped. - if !(executable('python') && (has('job') || executable('pkill'))) - return '' - endif - let s:python = 'python' - elseif has('win32') - " Use Python Launcher for Windows (py.exe) if available. - if executable('py.exe') - let s:python = 'py.exe' - elseif executable('python.exe') - let s:python = 'python.exe' - else - return '' - endif - else - return '' - endif - return s:python -endfunc - -" Run "cmd". Returns the job if using a job. -func RunCommand(cmd) - " Running an external command can occasionally be slow or fail. - let g:test_is_flaky = 1 - - let job = 0 - if has('job') - let job = job_start(a:cmd, {"stoponexit": "hup"}) - call job_setoptions(job, {"stoponexit": "kill"}) - elseif has('win32') - exe 'silent !start cmd /c start "test_channel" ' . a:cmd - else - exe 'silent !' . a:cmd . '&' - endif - return job -endfunc - -" Read the port number from the Xportnr file. -func GetPort() - let l = [] - " with 200 it sometimes failed - for i in range(400) - try - let l = readfile("Xportnr") - catch - endtry - if len(l) >= 1 - break - endif - sleep 10m - endfor - call delete("Xportnr") - - if len(l) == 0 - " Can't make the connection, give up. - return 0 - endif - return l[0] -endfunc - -" Run a Python server for "cmd" and call "testfunc". -" Always kills the server before returning. -func RunServer(cmd, testfunc, args) - " The Python program writes the port number in Xportnr. - call delete("Xportnr") - - if len(a:args) == 1 - let arg = ' ' . a:args[0] - else - let arg = '' - endif - let pycmd = s:python . " " . a:cmd . arg - - try - let g:currentJob = RunCommand(pycmd) - - " Wait for up to 2 seconds for the port number to be there. - let port = GetPort() - if port == 0 - call assert_false(1, "Can't start " . a:cmd) - return - endif - - call call(function(a:testfunc), [port]) - catch - call assert_false(1, 'Caught exception: "' . v:exception . '" in ' . v:throwpoint) - finally - call s:kill_server(a:cmd) - endtry -endfunc - -func s:kill_server(cmd) - if has('job') - if exists('g:currentJob') - call job_stop(g:currentJob) - unlet g:currentJob - endif - elseif has('win32') - let cmd = substitute(a:cmd, ".py", '', '') - call system('taskkill /IM ' . s:python . ' /T /F /FI "WINDOWTITLE eq ' . cmd . '"') - else - call system("pkill -f " . a:cmd) - endif -endfunc - -" Wait for up to five seconds for "expr" to become true. "expr" can be a -" stringified expression to evaluate, or a funcref without arguments. -" Using a lambda works best. Example: -" call WaitFor({-> status == "ok"}) -" -" A second argument can be used to specify a different timeout in msec. -" -" When successful the time slept is returned. -" When running into the timeout an exception is thrown, thus the function does -" not return. -func WaitFor(expr, ...) - let timeout = get(a:000, 0, 5000) - let slept = s:WaitForCommon(a:expr, v:null, timeout) - if slept < 0 - throw 'WaitFor() timed out after ' . timeout . ' msec' - endif - return slept -endfunc - -" Wait for up to five seconds for "assert" to return zero. "assert" must be a -" (lambda) function containing one assert function. Example: -" call WaitForAssert({-> assert_equal("dead", job_status(job)}) -" -" A second argument can be used to specify a different timeout in msec. -" -" Return zero for success, one for failure (like the assert function). -func WaitForAssert(assert, ...) - let timeout = get(a:000, 0, 5000) - if s:WaitForCommon(v:null, a:assert, timeout) < 0 - return 1 - endif - return 0 -endfunc - -" Common implementation of WaitFor() and WaitForAssert(). -" Either "expr" or "assert" is not v:null -" Return the waiting time for success, -1 for failure. -func s:WaitForCommon(expr, assert, timeout) - " using reltime() is more accurate, but not always available - let slept = 0 - if exists('*reltimefloat') - let start = reltime() - endif - - while 1 - if type(a:expr) == v:t_func - let success = a:expr() - elseif type(a:assert) == v:t_func - let success = a:assert() == 0 - else - let success = eval(a:expr) - endif - if success - return slept - endif - - if slept >= a:timeout - break - endif - if type(a:assert) == v:t_func - " Remove the error added by the assert function. - call remove(v:errors, -1) - endif - - sleep 10m - if exists('*reltimefloat') - let slept = float2nr(reltimefloat(reltime(start)) * 1000) - else - let slept += 10 - endif - endwhile - - return -1 " timed out -endfunc - - -" Wait for up to a given milliseconds. -" With the +timers feature this waits for key-input by getchar(), Resume() -" feeds key-input and resumes process. Return time waited in milliseconds. -" Without +timers it uses simply :sleep. -func Standby(msec) - if has('timers') && exists('*reltimefloat') - let start = reltime() - let g:_standby_timer = timer_start(a:msec, function('s:feedkeys')) - call getchar() - return float2nr(reltimefloat(reltime(start)) * 1000) - else - execute 'sleep ' a:msec . 'm' - return a:msec - endif -endfunc - -func Resume() - if exists('g:_standby_timer') - call timer_stop(g:_standby_timer) - call s:feedkeys(0) - unlet g:_standby_timer - endif -endfunc - -func s:feedkeys(timer) - call feedkeys('x', 'nt') -endfunc - -" Get $VIMPROG to run the Vim executable. -" The Makefile writes it as the first line in the "vimcmd" file. -" Nvim: uses $NVIM_TEST_ARG0. -func GetVimProg() - if empty($NVIM_TEST_ARG0) - " Assume the script was sourced instead of running "make". - return v:progpath - endif - if has('win32') - return substitute($NVIM_TEST_ARG0, '/', '\\', 'g') - else - return $NVIM_TEST_ARG0 - endif -endfunc - -let g:valgrind_cnt = 1 - -" Get the command to run Vim, with -u NONE and --headless arguments. -" If there is an argument use it instead of "NONE". -func GetVimCommand(...) - if a:0 == 0 - let name = 'NONE' - else - let name = a:1 - endif - let cmd = GetVimProg() - let cmd = substitute(cmd, '-u \f\+', '-u ' . name, '') - if cmd !~ '-u '. name - let cmd = cmd . ' -u ' . name - endif - let cmd .= ' --headless -i NONE' - let cmd = substitute(cmd, 'VIMRUNTIME=\S\+', '', '') - - " If using valgrind, make sure every run uses a different log file. - if cmd =~ 'valgrind.*--log-file=' - let cmd = substitute(cmd, '--log-file=\(\S*\)', '--log-file=\1.' . g:valgrind_cnt, '') - let g:valgrind_cnt += 1 - endif - - return cmd -endfunc - -" Return one when it looks like the tests are run with valgrind, which means -" that everything is much slower. -func RunningWithValgrind() - return GetVimCommand() =~ '\' -endfunc - -" Get the command to run Vim, with --clean instead of "-u NONE". -func GetVimCommandClean() - let cmd = GetVimCommand() - let cmd = substitute(cmd, '-u NONE', '--clean', '') - let cmd = substitute(cmd, '--headless', '', '') - - " Force using utf-8, Vim may pick up something else from the environment. - " let cmd ..= ' --cmd "set enc=utf8" ' - - " Optionally run Vim under valgrind - " let cmd = 'valgrind --tool=memcheck --leak-check=yes --num-callers=25 --log-file=valgrind ' . cmd - - return cmd -endfunc - -" Get the command to run Vim, with --clean, and force to run in terminal so it -" won't start a new GUI. -func GetVimCommandCleanTerm() - " Add -v to have gvim run in the terminal (if possible) - return GetVimCommandClean() .. ' -v ' -endfunc - -" Run Vim, using the "vimcmd" file and "-u NORC". -" "before" is a list of Vim commands to be executed before loading plugins. -" "after" is a list of Vim commands to be executed after loading plugins. -" Plugins are not loaded, unless 'loadplugins' is set in "before". -" Return 1 if Vim could be executed. -func RunVim(before, after, arguments) - return RunVimPiped(a:before, a:after, a:arguments, '') -endfunc - -func RunVimPiped(before, after, arguments, pipecmd) - let cmd = GetVimCommand() - let args = '' - if len(a:before) > 0 - call writefile(a:before, 'Xbefore.vim') - let args .= ' --cmd "so Xbefore.vim"' - endif - if len(a:after) > 0 - call writefile(a:after, 'Xafter.vim') - let args .= ' -S Xafter.vim' - endif - - " Optionally run Vim under valgrind - " let cmd = 'valgrind --tool=memcheck --leak-check=yes --num-callers=25 --log-file=valgrind ' . cmd - - let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log' - " Nvim does not support -Z flag, remove it. - exe "silent !" . a:pipecmd . cmd . args . ' ' . substitute(a:arguments, '-Z', '', 'g') - - if len(a:before) > 0 - call delete('Xbefore.vim') - endif - if len(a:after) > 0 - call delete('Xafter.vim') - endif - return 1 -endfunc - -func IsRoot() - if !has('unix') - return v:false - elseif $USER == 'root' || system('id -un') =~ '\' - return v:true - endif - return v:false -endfunc - -" Get all messages but drop the maintainer entry. -func GetMessages() - redir => result - redraw | messages - redir END - let msg_list = split(result, "\n") - " if msg_list->len() > 0 && msg_list[0] =~ 'Messages maintainer:' - " return msg_list[1:] - " endif - return msg_list -endfunc - -" Run the list of commands in 'cmds' and look for 'errstr' in exception. -" Note that assert_fails() cannot be used in some places and this function -" can be used. -func AssertException(cmds, errstr) - let save_exception = '' - try - for cmd in a:cmds - exe cmd - endfor - catch - let save_exception = v:exception - endtry - call assert_match(a:errstr, save_exception) -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/suite.sh b/src/nvim/testdir/suite.sh deleted file mode 100644 index bf5a16fd89..0000000000 --- a/src/nvim/testdir/suite.sh +++ /dev/null @@ -1,10 +0,0 @@ -fail() { - local test_name="$1" - local message="$2" - - : "${message:=Test $test_name failed}" - - local full_msg="$test_name :: $message" - echo "Failed: $full_msg" - export FAILED=1 -} diff --git a/src/nvim/testdir/summarize.vim b/src/nvim/testdir/summarize.vim deleted file mode 100644 index da5856a2e7..0000000000 --- a/src/nvim/testdir/summarize.vim +++ /dev/null @@ -1,62 +0,0 @@ -set cpo&vim -if 1 - " This is executed only with the eval feature - set nocompatible - set viminfo= - func Count(match, type) - if a:type ==# 'executed' - let g:executed += (a:match+0) - elseif a:type ==# 'failed' - let g:failed += a:match+0 - elseif a:type ==# 'skipped' - let g:skipped += 1 - call extend(g:skipped_output, ["\t" .. a:match]) - endif - endfunc - - let g:executed = 0 - let g:skipped = 0 - let g:failed = 0 - let g:skipped_output = [] - let g:failed_output = [] - let output = [""] - - if $TEST_FILTER != '' - call extend(g:skipped_output, ["\tAll tests not matching $TEST_FILTER: '" .. $TEST_FILTER .. "'"]) - endif - - try - " This uses the :s command to just fetch and process the output of the - " tests, it doesn't actually replace anything. - " And it uses "silent" to avoid reporting the number of matches. - silent %s/Executed\s\+\zs\d\+\ze\s\+tests\?/\=Count(submatch(0),'executed')/egn - silent %s/^SKIPPED \zs.*/\=Count(submatch(0), 'skipped')/egn - silent %s/^\(\d\+\)\s\+FAILED:/\=Count(submatch(1), 'failed')/egn - - call extend(output, ["Skipped:"]) - call extend(output, skipped_output) - - call extend(output, [ - \ "", - \ "-------------------------------", - \ printf("Executed: %5d Tests", g:executed), - \ printf(" Skipped: %5d Tests", g:skipped), - \ printf(" %s: %5d Tests", g:failed == 0 ? 'Failed' : 'FAILED', g:failed), - \ "", - \ ]) - if filereadable('test.log') - " outputs and indents the failed test result - call extend(output, ["", "Failures: "]) - let failed_output = filter(readfile('test.log'), { v,k -> !empty(k)}) - call extend(output, map(failed_output, { v,k -> "\t".k})) - " Add a final newline - call extend(output, [""]) - endif - - catch " Catch-all - finally - call writefile(output, 'test_result.log') " overwrites an existing file - endtry -endif - -q! diff --git a/src/nvim/testdir/term_util.vim b/src/nvim/testdir/term_util.vim deleted file mode 100644 index 5ff09e25b4..0000000000 --- a/src/nvim/testdir/term_util.vim +++ /dev/null @@ -1,13 +0,0 @@ -" Functions about terminal shared by several tests - -" Only load this script once. -if exists('*CanRunVimInTerminal') - finish -endif - -func CanRunVimInTerminal() - " Nvim: always false, we use Lua screen-tests instead. - return 0 -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test.sh b/src/nvim/testdir/test.sh deleted file mode 100644 index affdc308d1..0000000000 --- a/src/nvim/testdir/test.sh +++ /dev/null @@ -1,91 +0,0 @@ -fail() { - local test_name="$1" - local message="$2" - - : "${message:=Test $test_name failed}" - - local full_msg="$test_name :: $message" - echo "Failed: $full_msg" - export FAILED=1 -} - -print_core() { - local app="$1" - local core="$2" - if test "$app" = quiet ; then - echo "Found core $core" - return 0 - fi - echo "======= Core file $core =======" - if test "${CI_OS_NAME}" = osx ; then - lldb -Q -o "bt all" -f "${app}" -c "${core}" - else - gdb -n -batch -ex 'thread apply all bt full' "${app}" -c "${core}" - fi -} - -check_core_dumps() { - local del= - if test "$1" = "--delete" ; then - del=1 - shift - fi - local app="${1:-${BUILD_DIR}/bin/nvim}" - local cores - if test "${CI_OS_NAME}" = osx ; then - cores="$(find /cores/ -type f -print)" - local _sudo='sudo' - else - cores="$(find ./ -type f \( -name 'core.*' -o -name core -o -name nvim.core \) -print)" - local _sudo= - fi - - if test -z "${cores}" ; then - return - fi - local core - for core in $cores; do - if test "$del" = "1" ; then - print_core "$app" "$core" >&2 - "$_sudo" rm "$core" - else - print_core "$app" "$core" - fi - done - if test "$app" != quiet ; then - fail 'cores' 'Core dumps found' - fi -} - -check_logs() { - # Iterate through each log to remove an useless warning. - # shellcheck disable=SC2044 - for log in $(find "${1}" -type f -name "${2}"); do - sed -i "${log}" \ - -e '/Warning: noted but unhandled ioctl/d' \ - -e '/could cause spurious value errors to appear/d' \ - -e '/See README_MISSING_SYSCALL_OR_IOCTL for guidance/d' - done - - # Now do it again, but only consider files with size > 0. - local err="" - # shellcheck disable=SC2044 - for log in $(find "${1}" -type f -name "${2}" -size +0); do - cat "${log}" - err=1 - rm "${log}" - done - if test -n "${err}" ; then - fail 'logs' 'Runtime errors detected.' - fi -} - -valgrind_check() { - check_logs "${1}" "valgrind-*" -} - -check_sanitizer() { - if test -n "${CLANG_SANITIZER}"; then - check_logs "${1}" "*san.*" | cat - fi -} diff --git a/src/nvim/testdir/test1.in b/src/nvim/testdir/test1.in deleted file mode 100644 index 272500cd25..0000000000 --- a/src/nvim/testdir/test1.in +++ /dev/null @@ -1,13 +0,0 @@ -First a simple test to check if the test script works. - -STARTTEST -:" If columns or lines are too small, create wrongtermsize. -:" (Some tests will fail. When columns and/or lines are small) -:if &lines < 24 || &columns < 80 | sp another | w! wrongtermsize | qa! | endif -:" -:" Write a single line to test.out to check if testing works at all. -:%d -athis is a test:w! test.out -:qa! -ENDTEST - diff --git a/src/nvim/testdir/test1.ok b/src/nvim/testdir/test1.ok deleted file mode 100644 index 90bfcb5106..0000000000 --- a/src/nvim/testdir/test1.ok +++ /dev/null @@ -1 +0,0 @@ -this is a test diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim deleted file mode 100644 index a3d240f27e..0000000000 --- a/src/nvim/testdir/test_alot.vim +++ /dev/null @@ -1,31 +0,0 @@ -" A series of tests that can run in one Vim invocation. -" This makes testing go faster, since Vim doesn't need to restart. - -source test_backup.vim -source test_behave.vim -source test_compiler.vim -source test_ex_equal.vim -source test_ex_undo.vim -source test_ex_z.vim -source test_ex_mode.vim -source test_expand.vim -source test_expand_func.vim -source test_file_perm.vim -source test_fnamemodify.vim -source test_ga.vim -source test_glob2regpat.vim -source test_global.vim -source test_move.vim -source test_put.vim -source test_reltime.vim -source test_scroll_opt.vim -source test_searchpos.vim -source test_set.vim -source test_shift.vim -source test_sha256.vim -source test_tabline.vim -source test_tagcase.vim -source test_tagfunc.vim -source test_unlet.vim -source test_version.vim -source test_wnext.vim diff --git a/src/nvim/testdir/test_alot_latin.vim b/src/nvim/testdir/test_alot_latin.vim deleted file mode 100644 index 23a404cac1..0000000000 --- a/src/nvim/testdir/test_alot_latin.vim +++ /dev/null @@ -1,7 +0,0 @@ -" A series of tests that can run in one Vim invocation. -" This makes testing go faster, since Vim doesn't need to restart. - -" These tests use latin1 'encoding'. Setting 'encoding' is in the individual -" files, so that they can be run by themselves. - -source test_regexp_latin.vim diff --git a/src/nvim/testdir/test_alot_utf8.vim b/src/nvim/testdir/test_alot_utf8.vim deleted file mode 100644 index 77f5ede4c8..0000000000 --- a/src/nvim/testdir/test_alot_utf8.vim +++ /dev/null @@ -1,14 +0,0 @@ -" A series of tests that can run in one Vim invocation. -" This makes testing go faster, since Vim doesn't need to restart. - -" These tests use utf8 'encoding'. Setting 'encoding' is already done in -" runtest.vim. - -source test_charsearch_utf8.vim -source test_expr_utf8.vim -source test_mksession_utf8.vim -source test_regexp_utf8.vim -source test_source_utf8.vim -source test_startup_utf8.vim -source test_utf8.vim -source test_utf8_comparisons.vim diff --git a/src/nvim/testdir/test_arabic.vim b/src/nvim/testdir/test_arabic.vim deleted file mode 100644 index 272937387d..0000000000 --- a/src/nvim/testdir/test_arabic.vim +++ /dev/null @@ -1,587 +0,0 @@ -" Simplistic testing of Arabic mode. -" NOTE: This just checks if the code works. If you know Arabic please add -" functional tests that check the shaping works with real text. - -source check.vim -CheckFeature arabic - -source view_util.vim - -" Return list of Unicode characters at line lnum. -" Combining characters are treated as a single item. -func s:get_chars(lnum) - call cursor(a:lnum, 1) - let chars = [] - let numchars = strchars(getline('.'), 1) - for i in range(1, numchars) - exe 'norm ' i . '|' - let c = execute('ascii') - let c = substitute(c, '\n\?<.\{-}Hex\s*', 'U+', 'g') - let c = substitute(c, ',\s*Oct\(al\)\=\s\d*\(, Digr ..\)\=', '', 'g') - call add(chars, c) - endfor - return chars -endfunc - -func Test_arabic_toggle() - set arabic - call assert_equal(1, &rightleft) - call assert_equal(1, &arabicshape) - call assert_equal('arabic', &keymap) - call assert_equal(1, &delcombine) - - set iminsert=1 imsearch=1 - set arabic& - call assert_equal(0, &rightleft) - call assert_equal(1, &arabicshape) - call assert_equal('arabic', &keymap) - call assert_equal(1, &delcombine) - call assert_equal(0, &iminsert) - call assert_equal(-1, &imsearch) - - set arabicshape& keymap= delcombine& -endfunc - -func Test_arabic_input() - new - set arabic - " Typing sghl in Arabic insert mode should show the - " Arabic word 'Salaam' i.e. 'peace', spelled: - " SEEN, LAM, ALEF, MEEM. - " See: https://www.mediawiki.org/wiki/VisualEditor/Typing/Right-to-left - call feedkeys('isghl!', 'tx') - call assert_match("^ *!\uFEE1\uFEFC\uFEB3$", ScreenLines(1, &columns)[0]) - call assert_equal([ - \ 'U+0633', - \ 'U+0644 U+0627', - \ 'U+0645', - \ 'U+21'], s:get_chars(1)) - - " Without shaping, it should give individual Arabic letters. - set noarabicshape - call assert_match("^ *!\u0645\u0627\u0644\u0633$", ScreenLines(1, &columns)[0]) - call assert_equal([ - \ 'U+0633', - \ 'U+0644', - \ 'U+0627', - \ 'U+0645', - \ 'U+21'], s:get_chars(1)) - - set arabic& arabicshape& - bwipe! -endfunc - -func Test_arabic_toggle_keymap() - new - set arabic - call feedkeys("i12\12\12", 'tx') - call assert_match("^ *٢١21٢١$", ScreenLines(1, &columns)[0]) - call assert_equal('١٢12١٢', getline('.')) - set arabic& - bwipe! -endfunc - -func Test_delcombine() - new - set arabic - call feedkeys("isghl\\", 'tx') - call assert_match("^ *\uFEDE\uFEB3$", ScreenLines(1, &columns)[0]) - call assert_equal(['U+0633', 'U+0644'], s:get_chars(1)) - - " Now the same with 'nodelcombine' - set nodelcombine - %d - call feedkeys("isghl\\", 'tx') - call assert_match("^ *\uFEB1$", ScreenLines(1, &columns)[0]) - call assert_equal(['U+0633'], s:get_chars(1)) - set arabic& - bwipe! -endfunc - -" Values from src/arabic.h (not all used yet) -let s:a_COMMA = "\u060C" -let s:a_SEMICOLON = "\u061B" -let s:a_QUESTION = "\u061F" -let s:a_HAMZA = "\u0621" -let s:a_ALEF_MADDA = "\u0622" -let s:a_ALEF_HAMZA_ABOVE = "\u0623" -let s:a_WAW_HAMZA = "\u0624" -let s:a_ALEF_HAMZA_BELOW = "\u0625" -let s:a_YEH_HAMZA = "\u0626" -let s:a_ALEF = "\u0627" -let s:a_BEH = "\u0628" -let s:a_TEH_MARBUTA = "\u0629" -let s:a_TEH = "\u062a" -let s:a_THEH = "\u062b" -let s:a_JEEM = "\u062c" -let s:a_HAH = "\u062d" -let s:a_KHAH = "\u062e" -let s:a_DAL = "\u062f" -let s:a_THAL = "\u0630" -let s:a_REH = "\u0631" -let s:a_ZAIN = "\u0632" -let s:a_SEEN = "\u0633" -let s:a_SHEEN = "\u0634" -let s:a_SAD = "\u0635" -let s:a_DAD = "\u0636" -let s:a_TAH = "\u0637" -let s:a_ZAH = "\u0638" -let s:a_AIN = "\u0639" -let s:a_GHAIN = "\u063a" -let s:a_TATWEEL = "\u0640" -let s:a_FEH = "\u0641" -let s:a_QAF = "\u0642" -let s:a_KAF = "\u0643" -let s:a_LAM = "\u0644" -let s:a_MEEM = "\u0645" -let s:a_NOON = "\u0646" -let s:a_HEH = "\u0647" -let s:a_WAW = "\u0648" -let s:a_ALEF_MAKSURA = "\u0649" -let s:a_YEH = "\u064a" - -let s:a_FATHATAN = "\u064b" -let s:a_DAMMATAN = "\u064c" -let s:a_KASRATAN = "\u064d" -let s:a_FATHA = "\u064e" -let s:a_DAMMA = "\u064f" -let s:a_KASRA = "\u0650" -let s:a_SHADDA = "\u0651" -let s:a_SUKUN = "\u0652" - -let s:a_MADDA_ABOVE = "\u0653" -let s:a_HAMZA_ABOVE = "\u0654" -let s:a_HAMZA_BELOW = "\u0655" - -let s:a_ZERO = "\u0660" -let s:a_ONE = "\u0661" -let s:a_TWO = "\u0662" -let s:a_THREE = "\u0663" -let s:a_FOUR = "\u0664" -let s:a_FIVE = "\u0665" -let s:a_SIX = "\u0666" -let s:a_SEVEN = "\u0667" -let s:a_EIGHT = "\u0668" -let s:a_NINE = "\u0669" -let s:a_PERCENT = "\u066a" -let s:a_DECIMAL = "\u066b" -let s:a_THOUSANDS = "\u066c" -let s:a_STAR = "\u066d" -let s:a_MINI_ALEF = "\u0670" - -let s:a_s_FATHATAN = "\ufe70" -let s:a_m_TATWEEL_FATHATAN = "\ufe71" -let s:a_s_DAMMATAN = "\ufe72" - -let s:a_s_KASRATAN = "\ufe74" - -let s:a_s_FATHA = "\ufe76" -let s:a_m_FATHA = "\ufe77" -let s:a_s_DAMMA = "\ufe78" -let s:a_m_DAMMA = "\ufe79" -let s:a_s_KASRA = "\ufe7a" -let s:a_m_KASRA = "\ufe7b" -let s:a_s_SHADDA = "\ufe7c" -let s:a_m_SHADDA = "\ufe7d" -let s:a_s_SUKUN = "\ufe7e" -let s:a_m_SUKUN = "\ufe7f" - -let s:a_s_HAMZA = "\ufe80" -let s:a_s_ALEF_MADDA = "\ufe81" -let s:a_f_ALEF_MADDA = "\ufe82" -let s:a_s_ALEF_HAMZA_ABOVE = "\ufe83" -let s:a_f_ALEF_HAMZA_ABOVE = "\ufe84" -let s:a_s_WAW_HAMZA = "\ufe85" -let s:a_f_WAW_HAMZA = "\ufe86" -let s:a_s_ALEF_HAMZA_BELOW = "\ufe87" -let s:a_f_ALEF_HAMZA_BELOW = "\ufe88" -let s:a_s_YEH_HAMZA = "\ufe89" -let s:a_f_YEH_HAMZA = "\ufe8a" -let s:a_i_YEH_HAMZA = "\ufe8b" -let s:a_m_YEH_HAMZA = "\ufe8c" -let s:a_s_ALEF = "\ufe8d" -let s:a_f_ALEF = "\ufe8e" -let s:a_s_BEH = "\ufe8f" -let s:a_f_BEH = "\ufe90" -let s:a_i_BEH = "\ufe91" -let s:a_m_BEH = "\ufe92" -let s:a_s_TEH_MARBUTA = "\ufe93" -let s:a_f_TEH_MARBUTA = "\ufe94" -let s:a_s_TEH = "\ufe95" -let s:a_f_TEH = "\ufe96" -let s:a_i_TEH = "\ufe97" -let s:a_m_TEH = "\ufe98" -let s:a_s_THEH = "\ufe99" -let s:a_f_THEH = "\ufe9a" -let s:a_i_THEH = "\ufe9b" -let s:a_m_THEH = "\ufe9c" -let s:a_s_JEEM = "\ufe9d" -let s:a_f_JEEM = "\ufe9e" -let s:a_i_JEEM = "\ufe9f" -let s:a_m_JEEM = "\ufea0" -let s:a_s_HAH = "\ufea1" -let s:a_f_HAH = "\ufea2" -let s:a_i_HAH = "\ufea3" -let s:a_m_HAH = "\ufea4" -let s:a_s_KHAH = "\ufea5" -let s:a_f_KHAH = "\ufea6" -let s:a_i_KHAH = "\ufea7" -let s:a_m_KHAH = "\ufea8" -let s:a_s_DAL = "\ufea9" -let s:a_f_DAL = "\ufeaa" -let s:a_s_THAL = "\ufeab" -let s:a_f_THAL = "\ufeac" -let s:a_s_REH = "\ufead" -let s:a_f_REH = "\ufeae" -let s:a_s_ZAIN = "\ufeaf" -let s:a_f_ZAIN = "\ufeb0" -let s:a_s_SEEN = "\ufeb1" -let s:a_f_SEEN = "\ufeb2" -let s:a_i_SEEN = "\ufeb3" -let s:a_m_SEEN = "\ufeb4" -let s:a_s_SHEEN = "\ufeb5" -let s:a_f_SHEEN = "\ufeb6" -let s:a_i_SHEEN = "\ufeb7" -let s:a_m_SHEEN = "\ufeb8" -let s:a_s_SAD = "\ufeb9" -let s:a_f_SAD = "\ufeba" -let s:a_i_SAD = "\ufebb" -let s:a_m_SAD = "\ufebc" -let s:a_s_DAD = "\ufebd" -let s:a_f_DAD = "\ufebe" -let s:a_i_DAD = "\ufebf" -let s:a_m_DAD = "\ufec0" -let s:a_s_TAH = "\ufec1" -let s:a_f_TAH = "\ufec2" -let s:a_i_TAH = "\ufec3" -let s:a_m_TAH = "\ufec4" -let s:a_s_ZAH = "\ufec5" -let s:a_f_ZAH = "\ufec6" -let s:a_i_ZAH = "\ufec7" -let s:a_m_ZAH = "\ufec8" -let s:a_s_AIN = "\ufec9" -let s:a_f_AIN = "\ufeca" -let s:a_i_AIN = "\ufecb" -let s:a_m_AIN = "\ufecc" -let s:a_s_GHAIN = "\ufecd" -let s:a_f_GHAIN = "\ufece" -let s:a_i_GHAIN = "\ufecf" -let s:a_m_GHAIN = "\ufed0" -let s:a_s_FEH = "\ufed1" -let s:a_f_FEH = "\ufed2" -let s:a_i_FEH = "\ufed3" -let s:a_m_FEH = "\ufed4" -let s:a_s_QAF = "\ufed5" -let s:a_f_QAF = "\ufed6" -let s:a_i_QAF = "\ufed7" -let s:a_m_QAF = "\ufed8" -let s:a_s_KAF = "\ufed9" -let s:a_f_KAF = "\ufeda" -let s:a_i_KAF = "\ufedb" -let s:a_m_KAF = "\ufedc" -let s:a_s_LAM = "\ufedd" -let s:a_f_LAM = "\ufede" -let s:a_i_LAM = "\ufedf" -let s:a_m_LAM = "\ufee0" -let s:a_s_MEEM = "\ufee1" -let s:a_f_MEEM = "\ufee2" -let s:a_i_MEEM = "\ufee3" -let s:a_m_MEEM = "\ufee4" -let s:a_s_NOON = "\ufee5" -let s:a_f_NOON = "\ufee6" -let s:a_i_NOON = "\ufee7" -let s:a_m_NOON = "\ufee8" -let s:a_s_HEH = "\ufee9" -let s:a_f_HEH = "\ufeea" -let s:a_i_HEH = "\ufeeb" -let s:a_m_HEH = "\ufeec" -let s:a_s_WAW = "\ufeed" -let s:a_f_WAW = "\ufeee" -let s:a_s_ALEF_MAKSURA = "\ufeef" -let s:a_f_ALEF_MAKSURA = "\ufef0" -let s:a_s_YEH = "\ufef1" -let s:a_f_YEH = "\ufef2" -let s:a_i_YEH = "\ufef3" -let s:a_m_YEH = "\ufef4" -let s:a_s_LAM_ALEF_MADDA_ABOVE = "\ufef5" -let s:a_f_LAM_ALEF_MADDA_ABOVE = "\ufef6" -let s:a_s_LAM_ALEF_HAMZA_ABOVE = "\ufef7" -let s:a_f_LAM_ALEF_HAMZA_ABOVE = "\ufef8" -let s:a_s_LAM_ALEF_HAMZA_BELOW = "\ufef9" -let s:a_f_LAM_ALEF_HAMZA_BELOW = "\ufefa" -let s:a_s_LAM_ALEF = "\ufefb" -let s:a_f_LAM_ALEF = "\ufefc" - -let s:a_BYTE_ORDER_MARK = "\ufeff" - -func Test_shape_initial() - new - set arabicshape - - " Shaping arabic {testchar} non-arabic Tests chg_c_a2i(). - " pair[0] = testchar, pair[1] = next-result, pair[2] = current-result - for pair in [[s:a_YEH_HAMZA, s:a_f_GHAIN, s:a_i_YEH_HAMZA], - \ [s:a_HAMZA, s:a_s_GHAIN, s:a_s_HAMZA], - \ [s:a_ALEF_MADDA, s:a_s_GHAIN, s:a_s_ALEF_MADDA], - \ [s:a_ALEF_HAMZA_ABOVE, s:a_s_GHAIN, s:a_s_ALEF_HAMZA_ABOVE], - \ [s:a_WAW_HAMZA, s:a_s_GHAIN, s:a_s_WAW_HAMZA], - \ [s:a_ALEF_HAMZA_BELOW, s:a_s_GHAIN, s:a_s_ALEF_HAMZA_BELOW], - \ [s:a_ALEF, s:a_s_GHAIN, s:a_s_ALEF], - \ [s:a_TEH_MARBUTA, s:a_s_GHAIN, s:a_s_TEH_MARBUTA], - \ [s:a_DAL, s:a_s_GHAIN, s:a_s_DAL], - \ [s:a_THAL, s:a_s_GHAIN, s:a_s_THAL], - \ [s:a_REH, s:a_s_GHAIN, s:a_s_REH], - \ [s:a_ZAIN, s:a_s_GHAIN, s:a_s_ZAIN], - \ [s:a_TATWEEL, s:a_f_GHAIN, s:a_TATWEEL], - \ [s:a_WAW, s:a_s_GHAIN, s:a_s_WAW], - \ [s:a_ALEF_MAKSURA, s:a_s_GHAIN, s:a_s_ALEF_MAKSURA], - \ [s:a_BEH, s:a_f_GHAIN, s:a_i_BEH], - \ [s:a_TEH, s:a_f_GHAIN, s:a_i_TEH], - \ [s:a_THEH, s:a_f_GHAIN, s:a_i_THEH], - \ [s:a_JEEM, s:a_f_GHAIN, s:a_i_JEEM], - \ [s:a_HAH, s:a_f_GHAIN, s:a_i_HAH], - \ [s:a_KHAH, s:a_f_GHAIN, s:a_i_KHAH], - \ [s:a_SEEN, s:a_f_GHAIN, s:a_i_SEEN], - \ [s:a_SHEEN, s:a_f_GHAIN, s:a_i_SHEEN], - \ [s:a_SAD, s:a_f_GHAIN, s:a_i_SAD], - \ [s:a_DAD, s:a_f_GHAIN, s:a_i_DAD], - \ [s:a_TAH, s:a_f_GHAIN, s:a_i_TAH], - \ [s:a_ZAH, s:a_f_GHAIN, s:a_i_ZAH], - \ [s:a_AIN, s:a_f_GHAIN, s:a_i_AIN], - \ [s:a_GHAIN, s:a_f_GHAIN, s:a_i_GHAIN], - \ [s:a_FEH, s:a_f_GHAIN, s:a_i_FEH], - \ [s:a_QAF, s:a_f_GHAIN, s:a_i_QAF], - \ [s:a_KAF, s:a_f_GHAIN, s:a_i_KAF], - \ [s:a_LAM, s:a_f_GHAIN, s:a_i_LAM], - \ [s:a_MEEM, s:a_f_GHAIN, s:a_i_MEEM], - \ [s:a_NOON, s:a_f_GHAIN, s:a_i_NOON], - \ [s:a_HEH, s:a_f_GHAIN, s:a_i_HEH], - \ [s:a_YEH, s:a_f_GHAIN, s:a_i_YEH], - \ ] - call setline(1, s:a_GHAIN . pair[0] . ' ') - call assert_equal([pair[1] . pair[2] . ' '], ScreenLines(1, 3)) - endfor - - set arabicshape& - bwipe! -endfunc - -func Test_shape_isolated() - new - set arabicshape - - " Shaping non-arabic {testchar} non-arabic Tests chg_c_a2s(). - " pair[0] = testchar, pair[1] = current-result - for pair in [[s:a_HAMZA, s:a_s_HAMZA], - \ [s:a_ALEF_MADDA, s:a_s_ALEF_MADDA], - \ [s:a_ALEF_HAMZA_ABOVE, s:a_s_ALEF_HAMZA_ABOVE], - \ [s:a_WAW_HAMZA, s:a_s_WAW_HAMZA], - \ [s:a_ALEF_HAMZA_BELOW, s:a_s_ALEF_HAMZA_BELOW], - \ [s:a_YEH_HAMZA, s:a_s_YEH_HAMZA], - \ [s:a_ALEF, s:a_s_ALEF], - \ [s:a_TEH_MARBUTA, s:a_s_TEH_MARBUTA], - \ [s:a_DAL, s:a_s_DAL], - \ [s:a_THAL, s:a_s_THAL], - \ [s:a_REH, s:a_s_REH], - \ [s:a_ZAIN, s:a_s_ZAIN], - \ [s:a_TATWEEL, s:a_TATWEEL], - \ [s:a_WAW, s:a_s_WAW], - \ [s:a_ALEF_MAKSURA, s:a_s_ALEF_MAKSURA], - \ [s:a_BEH, s:a_s_BEH], - \ [s:a_TEH, s:a_s_TEH], - \ [s:a_THEH, s:a_s_THEH], - \ [s:a_JEEM, s:a_s_JEEM], - \ [s:a_HAH, s:a_s_HAH], - \ [s:a_KHAH, s:a_s_KHAH], - \ [s:a_SEEN, s:a_s_SEEN], - \ [s:a_SHEEN, s:a_s_SHEEN], - \ [s:a_SAD, s:a_s_SAD], - \ [s:a_DAD, s:a_s_DAD], - \ [s:a_TAH, s:a_s_TAH], - \ [s:a_ZAH, s:a_s_ZAH], - \ [s:a_AIN, s:a_s_AIN], - \ [s:a_GHAIN, s:a_s_GHAIN], - \ [s:a_FEH, s:a_s_FEH], - \ [s:a_QAF, s:a_s_QAF], - \ [s:a_KAF, s:a_s_KAF], - \ [s:a_LAM, s:a_s_LAM], - \ [s:a_MEEM, s:a_s_MEEM], - \ [s:a_NOON, s:a_s_NOON], - \ [s:a_HEH, s:a_s_HEH], - \ [s:a_YEH, s:a_s_YEH], - \ ] - call setline(1, ' ' . pair[0] . ' ') - call assert_equal([' ' . pair[1] . ' '], ScreenLines(1, 3)) - endfor - - set arabicshape& - bwipe! -endfunc - -func Test_shape_iso_to_medial() - new - set arabicshape - - " Shaping arabic {testchar} arabic Tests chg_c_a2m(). - " pair[0] = testchar, pair[1] = next-result, pair[2] = current-result, - " pair[3] = previous-result - for pair in [[s:a_HAMZA, s:a_s_GHAIN, s:a_s_HAMZA, s:a_s_BEH], - \[s:a_ALEF_MADDA, s:a_s_GHAIN, s:a_f_ALEF_MADDA, s:a_i_BEH], - \[s:a_ALEF_HAMZA_ABOVE, s:a_s_GHAIN, s:a_f_ALEF_HAMZA_ABOVE, s:a_i_BEH], - \[s:a_WAW_HAMZA, s:a_s_GHAIN, s:a_f_WAW_HAMZA, s:a_i_BEH], - \[s:a_ALEF_HAMZA_BELOW, s:a_s_GHAIN, s:a_f_ALEF_HAMZA_BELOW, s:a_i_BEH], - \[s:a_YEH_HAMZA, s:a_f_GHAIN, s:a_m_YEH_HAMZA, s:a_i_BEH], - \[s:a_ALEF, s:a_s_GHAIN, s:a_f_ALEF, s:a_i_BEH], - \[s:a_BEH, s:a_f_GHAIN, s:a_m_BEH, s:a_i_BEH], - \[s:a_TEH_MARBUTA, s:a_s_GHAIN, s:a_f_TEH_MARBUTA, s:a_i_BEH], - \[s:a_TEH, s:a_f_GHAIN, s:a_m_TEH, s:a_i_BEH], - \[s:a_THEH, s:a_f_GHAIN, s:a_m_THEH, s:a_i_BEH], - \[s:a_JEEM, s:a_f_GHAIN, s:a_m_JEEM, s:a_i_BEH], - \[s:a_HAH, s:a_f_GHAIN, s:a_m_HAH, s:a_i_BEH], - \[s:a_KHAH, s:a_f_GHAIN, s:a_m_KHAH, s:a_i_BEH], - \[s:a_DAL, s:a_s_GHAIN, s:a_f_DAL, s:a_i_BEH], - \[s:a_THAL, s:a_s_GHAIN, s:a_f_THAL, s:a_i_BEH], - \[s:a_REH, s:a_s_GHAIN, s:a_f_REH, s:a_i_BEH], - \[s:a_ZAIN, s:a_s_GHAIN, s:a_f_ZAIN, s:a_i_BEH], - \[s:a_SEEN, s:a_f_GHAIN, s:a_m_SEEN, s:a_i_BEH], - \[s:a_SHEEN, s:a_f_GHAIN, s:a_m_SHEEN, s:a_i_BEH], - \[s:a_SAD, s:a_f_GHAIN, s:a_m_SAD, s:a_i_BEH], - \[s:a_DAD, s:a_f_GHAIN, s:a_m_DAD, s:a_i_BEH], - \[s:a_TAH, s:a_f_GHAIN, s:a_m_TAH, s:a_i_BEH], - \[s:a_ZAH, s:a_f_GHAIN, s:a_m_ZAH, s:a_i_BEH], - \[s:a_AIN, s:a_f_GHAIN, s:a_m_AIN, s:a_i_BEH], - \[s:a_GHAIN, s:a_f_GHAIN, s:a_m_GHAIN, s:a_i_BEH], - \[s:a_TATWEEL, s:a_f_GHAIN, s:a_TATWEEL, s:a_i_BEH], - \[s:a_FEH, s:a_f_GHAIN, s:a_m_FEH, s:a_i_BEH], - \[s:a_QAF, s:a_f_GHAIN, s:a_m_QAF, s:a_i_BEH], - \[s:a_KAF, s:a_f_GHAIN, s:a_m_KAF, s:a_i_BEH], - \[s:a_LAM, s:a_f_GHAIN, s:a_m_LAM, s:a_i_BEH], - \[s:a_MEEM, s:a_f_GHAIN, s:a_m_MEEM, s:a_i_BEH], - \[s:a_NOON, s:a_f_GHAIN, s:a_m_NOON, s:a_i_BEH], - \[s:a_HEH, s:a_f_GHAIN, s:a_m_HEH, s:a_i_BEH], - \[s:a_WAW, s:a_s_GHAIN, s:a_f_WAW, s:a_i_BEH], - \[s:a_ALEF_MAKSURA, s:a_s_GHAIN, s:a_f_ALEF_MAKSURA, s:a_i_BEH], - \[s:a_YEH, s:a_f_GHAIN, s:a_m_YEH, s:a_i_BEH], - \ ] - call setline(1, s:a_GHAIN . pair[0] . s:a_BEH) - call assert_equal([pair[1] . pair[2] . pair[3]], ScreenLines(1, 3)) - endfor - - set arabicshape& - bwipe! -endfunc - -func Test_shape_final() - new - set arabicshape - - " Shaping arabic {testchar} arabic Tests chg_c_a2f(). - " pair[0] = testchar, pair[1] = current-result, pair[2] = previous-result - for pair in [[s:a_HAMZA, s:a_s_HAMZA, s:a_s_BEH], - \[s:a_ALEF_MADDA, s:a_f_ALEF_MADDA, s:a_i_BEH], - \[s:a_ALEF_HAMZA_ABOVE, s:a_f_ALEF_HAMZA_ABOVE, s:a_i_BEH], - \[s:a_WAW_HAMZA, s:a_f_WAW_HAMZA, s:a_i_BEH], - \[s:a_ALEF_HAMZA_BELOW, s:a_f_ALEF_HAMZA_BELOW, s:a_i_BEH], - \[s:a_YEH_HAMZA, s:a_f_YEH_HAMZA, s:a_i_BEH], - \[s:a_ALEF, s:a_f_ALEF, s:a_i_BEH], - \[s:a_BEH, s:a_f_BEH, s:a_i_BEH], - \[s:a_TEH_MARBUTA, s:a_f_TEH_MARBUTA, s:a_i_BEH], - \[s:a_TEH, s:a_f_TEH, s:a_i_BEH], - \[s:a_THEH, s:a_f_THEH, s:a_i_BEH], - \[s:a_JEEM, s:a_f_JEEM, s:a_i_BEH], - \[s:a_HAH, s:a_f_HAH, s:a_i_BEH], - \[s:a_KHAH, s:a_f_KHAH, s:a_i_BEH], - \[s:a_DAL, s:a_f_DAL, s:a_i_BEH], - \[s:a_THAL, s:a_f_THAL, s:a_i_BEH], - \[s:a_REH, s:a_f_REH, s:a_i_BEH], - \[s:a_ZAIN, s:a_f_ZAIN, s:a_i_BEH], - \[s:a_SEEN, s:a_f_SEEN, s:a_i_BEH], - \[s:a_SHEEN, s:a_f_SHEEN, s:a_i_BEH], - \[s:a_SAD, s:a_f_SAD, s:a_i_BEH], - \[s:a_DAD, s:a_f_DAD, s:a_i_BEH], - \[s:a_TAH, s:a_f_TAH, s:a_i_BEH], - \[s:a_ZAH, s:a_f_ZAH, s:a_i_BEH], - \[s:a_AIN, s:a_f_AIN, s:a_i_BEH], - \[s:a_GHAIN, s:a_f_GHAIN, s:a_i_BEH], - \[s:a_TATWEEL, s:a_TATWEEL, s:a_i_BEH], - \[s:a_FEH, s:a_f_FEH, s:a_i_BEH], - \[s:a_QAF, s:a_f_QAF, s:a_i_BEH], - \[s:a_KAF, s:a_f_KAF, s:a_i_BEH], - \[s:a_LAM, s:a_f_LAM, s:a_i_BEH], - \[s:a_MEEM, s:a_f_MEEM, s:a_i_BEH], - \[s:a_NOON, s:a_f_NOON, s:a_i_BEH], - \[s:a_HEH, s:a_f_HEH, s:a_i_BEH], - \[s:a_WAW, s:a_f_WAW, s:a_i_BEH], - \[s:a_ALEF_MAKSURA, s:a_f_ALEF_MAKSURA, s:a_i_BEH], - \[s:a_YEH, s:a_f_YEH, s:a_i_BEH], - \ ] - call setline(1, ' ' . pair[0] . s:a_BEH) - call assert_equal([' ' . pair[1] . pair[2]], ScreenLines(1, 3)) - endfor - - set arabicshape& - bwipe! -endfunc - -func Test_shape_combination_final() - new - set arabicshape - - " Shaping arabic {testchar} arabic Tests chg_c_laa2f(). - " pair[0] = testchar, pair[1] = current-result - for pair in [[s:a_ALEF_MADDA, s:a_f_LAM_ALEF_MADDA_ABOVE], - \ [s:a_ALEF_HAMZA_ABOVE, s:a_f_LAM_ALEF_HAMZA_ABOVE], - \ [s:a_ALEF_HAMZA_BELOW, s:a_f_LAM_ALEF_HAMZA_BELOW], - \ [s:a_ALEF, s:a_f_LAM_ALEF], - \ ] - " The test char is a composing char, put on s:a_LAM. - call setline(1, ' ' . s:a_LAM . pair[0] . s:a_BEH) - call assert_equal([' ' . pair[1] . s:a_i_BEH], ScreenLines(1, 3)) - endfor - - set arabicshape& - bwipe! -endfunc - -func Test_shape_combination_isolated() - new - set arabicshape - - " Shaping arabic {testchar} arabic Tests chg_c_laa2i(). - " pair[0] = testchar, pair[1] = current-result - for pair in [[s:a_ALEF_MADDA, s:a_s_LAM_ALEF_MADDA_ABOVE], - \ [s:a_ALEF_HAMZA_ABOVE, s:a_s_LAM_ALEF_HAMZA_ABOVE], - \ [s:a_ALEF_HAMZA_BELOW, s:a_s_LAM_ALEF_HAMZA_BELOW], - \ [s:a_ALEF, s:a_s_LAM_ALEF], - \ ] - " The test char is a composing char, put on s:a_LAM. - call setline(1, ' ' . s:a_LAM . pair[0] . ' ') - call assert_equal([' ' . pair[1] . ' '], ScreenLines(1, 3)) - endfor - - set arabicshape& - bwipe! -endfunc - -" Test for entering arabic character in a search command -func Test_arabic_chars_in_search_cmd() - new - set arabic - call feedkeys("i\nsghl!\vim\", 'tx') - call cursor(1, 1) - call feedkeys("/^sghl!\vim$\\", 'tx') - call assert_equal([2, 1], [line('.'), col('.')]) - - " Try searching in left-to-right mode - set rightleftcmd= - call cursor(1, 1) - call feedkeys("/^sghl!\vim$\", 'tx') - call assert_equal([2, 1], [line('.'), col('.')]) - - set rightleftcmd& - set rightleft& - set arabic& - bwipe! -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_arglist.vim b/src/nvim/testdir/test_arglist.vim deleted file mode 100644 index fb8b17cd16..0000000000 --- a/src/nvim/testdir/test_arglist.vim +++ /dev/null @@ -1,748 +0,0 @@ -" Test argument list commands - -source check.vim -source shared.vim -source term_util.vim - -func Reset_arglist() - args a | %argd -endfunc - -func Test_argidx() - args a b c - last - call assert_equal(2, argidx()) - %argdelete - call assert_equal(0, argidx()) - " doing it again doesn't result in an error - %argdelete - call assert_equal(0, argidx()) - call assert_fails('2argdelete', 'E16:') - - args a b c - call assert_equal(0, argidx()) - next - call assert_equal(1, argidx()) - next - call assert_equal(2, argidx()) - 1argdelete - call assert_equal(1, argidx()) - 1argdelete - call assert_equal(0, argidx()) - 1argdelete - call assert_equal(0, argidx()) -endfunc - -func Test_argadd() - call Reset_arglist() - - %argdelete - argadd a b c - call assert_equal(0, argidx()) - - %argdelete - argadd a - call assert_equal(0, argidx()) - argadd b c d - call assert_equal(0, argidx()) - - call Init_abc() - argadd x - call Assert_argc(['a', 'b', 'x', 'c']) - call assert_equal(1, argidx()) - - call Init_abc() - 0argadd x - call Assert_argc(['x', 'a', 'b', 'c']) - call assert_equal(2, argidx()) - - call Init_abc() - 1argadd x - call Assert_argc(['a', 'x', 'b', 'c']) - call assert_equal(2, argidx()) - - call Init_abc() - $argadd x - call Assert_argc(['a', 'b', 'c', 'x']) - call assert_equal(1, argidx()) - - call Init_abc() - $argadd x - +2argadd y - call Assert_argc(['a', 'b', 'c', 'x', 'y']) - call assert_equal(1, argidx()) - - %argd - edit d - arga - call assert_equal(1, len(argv())) - call assert_equal('d', get(argv(), 0, '')) - - %argd - edit some\ file - arga - call assert_equal(1, len(argv())) - call assert_equal('some file', get(argv(), 0, '')) - - %argd - new - arga - call assert_equal(0, len(argv())) - - if has('unix') - call assert_fails('argadd `Xdoes_not_exist`', 'E479:') - endif -endfunc - -func Test_argadd_empty_curbuf() - new - let curbuf = bufnr('%') - call writefile(['test', 'Xargadd'], 'Xargadd') - " must not re-use the current buffer. - argadd Xargadd - call assert_equal(curbuf, bufnr('%')) - call assert_equal('', bufname('%')) - call assert_equal(1, '$'->line()) - rew - call assert_notequal(curbuf, '%'->bufnr()) - call assert_equal('Xargadd', '%'->bufname()) - call assert_equal(2, line('$')) - - %argd - bwipe! -endfunc - -func Init_abc() - args a b c - next -endfunc - -func Assert_argc(l) - call assert_equal(len(a:l), argc()) - let i = 0 - while i < len(a:l) && i < argc() - call assert_equal(a:l[i], argv(i)) - let i += 1 - endwhile -endfunc - -" Test for [count]argument and [count]argdelete commands -" Ported from the test_argument_count.in test script -func Test_argument() - call Reset_arglist() - - let save_hidden = &hidden - set hidden - - let g:buffers = [] - augroup TEST - au BufEnter * call add(buffers, expand('%:t')) - augroup END - - argadd a b c d - $argu - $-argu - -argu - 1argu - +2argu - - augroup TEST - au! - augroup END - - call assert_equal(['d', 'c', 'b', 'a', 'c'], g:buffers) - - call assert_equal("\na b [c] d ", execute(':args')) - - .argd - call assert_equal(['a', 'b', 'd'], argv()) - - -argd - call assert_equal(['a', 'd'], argv()) - - $argd - call assert_equal(['a'], argv()) - - 1arga c - 1arga b - $argu - $arga x - call assert_equal(['a', 'b', 'c', 'x'], argv()) - - 0arga y - call assert_equal(['y', 'a', 'b', 'c', 'x'], argv()) - - %argd - call assert_equal([], argv()) - - arga a b c d e f - 2,$-argd - call assert_equal(['a', 'f'], argv()) - - let &hidden = save_hidden - - let save_columns = &columns - let &columns = 79 - exe 'args ' .. join(range(1, 81)) - call assert_equal(join([ - \ '', - \ '[1] 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76 81 ', - \ '2 7 12 17 22 27 32 37 42 47 52 57 62 67 72 77 ', - \ '3 8 13 18 23 28 33 38 43 48 53 58 63 68 73 78 ', - \ '4 9 14 19 24 29 34 39 44 49 54 59 64 69 74 79 ', - \ '5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 ', - \ ], "\n"), - \ execute('args')) - - " No trailing newline with one item per row. - let long_arg = repeat('X', 81) - exe 'args ' .. long_arg - call assert_equal("\n[".long_arg.']', execute('args')) - let &columns = save_columns - - " Setting argument list should fail when the current buffer has unsaved - " changes - %argd - enew! - set modified - call assert_fails('args x y z', 'E37:') - args! x y z - call assert_equal(['x', 'y', 'z'], argv()) - call assert_equal('x', expand('%:t')) - - last | enew | argu - call assert_equal('z', expand('%:t')) - - %argdelete - call assert_fails('argument', 'E163:') -endfunc - -func Test_list_arguments() - " Clean the argument list - arga a | %argd - - " four args half the screen width makes two lines with two columns - let aarg = repeat('a', &columns / 2 - 4) - let barg = repeat('b', &columns / 2 - 4) - let carg = repeat('c', &columns / 2 - 4) - let darg = repeat('d', &columns / 2 - 4) - exe 'argadd ' aarg barg carg darg - - redir => result - args - redir END - call assert_match('\[' . aarg . '] \+' . carg . '\n' . barg . ' \+' . darg, trim(result)) - - " if one arg is longer than half the screen make one column - exe 'argdel' aarg - let aarg = repeat('a', &columns / 2 + 2) - exe '0argadd' aarg - redir => result - args - redir END - call assert_match(aarg . '\n\[' . barg . ']\n' . carg . '\n' . darg, trim(result)) - - %argdelete -endfunc - -func Test_args_with_quote() - " Only on Unix can a file name include a double quote. - if has('unix') - args \"foobar - call assert_equal('"foobar', argv(0)) - %argdelete - endif -endfunc - -" Test for 0argadd and 0argedit -" Ported from the test_argument_0count.in test script -func Test_zero_argadd() - call Reset_arglist() - - arga a b c d - 2argu - 0arga added - call assert_equal(['added', 'a', 'b', 'c', 'd'], argv()) - - 2argu - arga third - call assert_equal(['added', 'a', 'third', 'b', 'c', 'd'], argv()) - - %argd - arga a b c d - 2argu - 0arge edited - call assert_equal(['edited', 'a', 'b', 'c', 'd'], argv()) - - 2argu - arga third - call assert_equal(['edited', 'a', 'third', 'b', 'c', 'd'], argv()) - - 2argu - argedit file\ with\ spaces another file - call assert_equal(['edited', 'a', 'file with spaces', 'another', 'file', 'third', 'b', 'c', 'd'], argv()) - call assert_equal('file with spaces', expand('%')) -endfunc - -" Test for argc() -func Test_argc() - call Reset_arglist() - call assert_equal(0, argc()) - argadd a b - call assert_equal(2, argc()) -endfunc - -" Test for arglistid() -func Test_arglistid() - call Reset_arglist() - arga a b - call assert_equal(0, arglistid()) - split - arglocal - call assert_equal(1, arglistid()) - tabnew | tabfirst - call assert_equal(0, arglistid(2)) - call assert_equal(1, arglistid(1, 1)) - call assert_equal(0, arglistid(2, 1)) - call assert_equal(1, arglistid(1, 2)) - tabonly | only | enew! - argglobal - call assert_equal(0, arglistid()) -endfunc - -" Tests for argv() and argc() -func Test_argv() - call Reset_arglist() - call assert_equal([], argv()) - call assert_equal("", argv(2)) - call assert_equal(0, argc()) - argadd a b c d - call assert_equal(4, argc()) - call assert_equal('c', argv(2)) - - let w1_id = win_getid() - split - let w2_id = win_getid() - arglocal - args e f g - tabnew - let w3_id = win_getid() - split - let w4_id = win_getid() - argglobal - tabfirst - call assert_equal(4, argc(w1_id)) - call assert_equal('b', argv(1, w1_id)) - call assert_equal(['a', 'b', 'c', 'd'], argv(-1, w1_id)) - - call assert_equal(3, argc(w2_id)) - call assert_equal('f', argv(1, w2_id)) - call assert_equal(['e', 'f', 'g'], argv(-1, w2_id)) - - call assert_equal(3, argc(w3_id)) - call assert_equal('e', argv(0, w3_id)) - call assert_equal(['e', 'f', 'g'], argv(-1, w3_id)) - - call assert_equal(4, argc(w4_id)) - call assert_equal('c', argv(2, w4_id)) - call assert_equal(['a', 'b', 'c', 'd'], argv(-1, w4_id)) - - call assert_equal(4, argc(-1)) - call assert_equal(3, argc()) - call assert_equal('d', argv(3, -1)) - call assert_equal(['a', 'b', 'c', 'd'], argv(-1, -1)) - tabonly | only | enew! - " Negative test cases - call assert_equal(-1, argc(100)) - call assert_equal('', argv(1, 100)) - call assert_equal([], argv(-1, 100)) - call assert_equal('', argv(10, -1)) -endfunc - -" Test for the :argedit command -func Test_argedit() - call Reset_arglist() - argedit a - call assert_equal(['a'], argv()) - call assert_equal('a', expand('%:t')) - argedit b - call assert_equal(['a', 'b'], argv()) - call assert_equal('b', expand('%:t')) - argedit a - call assert_equal(['a', 'b', 'a'], argv()) - call assert_equal('a', expand('%:t')) - " When file name case is ignored, an existing buffer with only case - " difference is re-used. - argedit C D - call assert_equal('C', expand('%:t')) - call assert_equal(['a', 'b', 'a', 'C', 'D'], argv()) - argedit c - if has('fname_case') - call assert_equal(['a', 'b', 'a', 'C', 'c', 'D'], argv()) - else - call assert_equal(['a', 'b', 'a', 'C', 'C', 'D'], argv()) - endif - 0argedit x - if has('fname_case') - call assert_equal(['x', 'a', 'b', 'a', 'C', 'c', 'D'], argv()) - else - call assert_equal(['x', 'a', 'b', 'a', 'C', 'C', 'D'], argv()) - endif - enew! | set modified - call assert_fails('argedit y', 'E37:') - argedit! y - if has('fname_case') - call assert_equal(['x', 'y', 'y', 'a', 'b', 'a', 'C', 'c', 'D'], argv()) - else - call assert_equal(['x', 'y', 'y', 'a', 'b', 'a', 'C', 'C', 'D'], argv()) - endif - %argd - bwipe! C - bwipe! D - - " :argedit reuses the current buffer if it is empty - %argd - " make sure to use a new buffer number for x when it is loaded - bw! x - new - let a = bufnr() - argedit x - call assert_equal(a, bufnr()) - call assert_equal('x', bufname()) - %argd - bw! x -endfunc - -" Test for the :argdedupe command -func Test_argdedupe() - call Reset_arglist() - argdedupe - call assert_equal([], argv()) - - args a a a aa b b a b aa - argdedupe - call assert_equal(['a', 'aa', 'b'], argv()) - - args a b c - argdedupe - call assert_equal(['a', 'b', 'c'], argv()) - - args a - argdedupe - call assert_equal(['a'], argv()) - - args a A b B - argdedupe - if has('fname_case') - call assert_equal(['a', 'A', 'b', 'B'], argv()) - else - call assert_equal(['a', 'b'], argv()) - endif - - args a b a c a b - last - argdedupe - next - call assert_equal('c', expand('%:t')) - - args a ./a - argdedupe - call assert_equal(['a'], argv()) - - %argd -endfunc - -" Test for the :argdelete command -func Test_argdelete() - call Reset_arglist() - args aa a aaa b bb - argdelete a* - call assert_equal(['b', 'bb'], argv()) - call assert_equal('aa', expand('%:t')) - last - argdelete % - call assert_equal(['b'], argv()) - call assert_fails('argdelete', 'E610:') - call assert_fails('1,100argdelete', 'E16:') - call assert_fails('argdel /\)/', 'E55:') - call assert_fails('1argdel 1', 'E474:') - - call Reset_arglist() - args a b c d - next - argdel - call Assert_argc(['a', 'c', 'd']) - %argdel - - call assert_fails('argdel does_not_exist', 'E480:') -endfunc - -func Test_argdelete_completion() - args foo bar - - call feedkeys(":argdelete \\\"\", 'tx') - call assert_equal('"argdelete bar foo', @:) - - call feedkeys(":argdelete x \\\"\", 'tx') - call assert_equal('"argdelete x bar foo', @:) - - %argd -endfunc - -" Tests for the :next, :prev, :first, :last, :rewind commands -func Test_argpos() - call Reset_arglist() - args a b c d - last - call assert_equal(3, argidx()) - call assert_fails('next', 'E165:') - prev - call assert_equal(2, argidx()) - Next - call assert_equal(1, argidx()) - first - call assert_equal(0, argidx()) - call assert_fails('prev', 'E164:') - 3next - call assert_equal(3, argidx()) - rewind - call assert_equal(0, argidx()) - %argd -endfunc - -" Test for autocommand that redefines the argument list, when doing ":all". -func Test_arglist_autocmd() - autocmd BufReadPost Xxx2 next Xxx2 Xxx1 - call writefile(['test file Xxx1'], 'Xxx1') - call writefile(['test file Xxx2'], 'Xxx2') - call writefile(['test file Xxx3'], 'Xxx3') - - new - " redefine arglist; go to Xxx1 - next! Xxx1 Xxx2 Xxx3 - " open window for all args; Reading Xxx2 will try to change the arglist and - " that will fail - call assert_fails("all", "E1156:") - call assert_equal('test file Xxx1', getline(1)) - wincmd w - call assert_equal('test file Xxx2', getline(1)) - wincmd w - call assert_equal('test file Xxx3', getline(1)) - - autocmd! BufReadPost Xxx2 - enew! | only - call delete('Xxx1') - call delete('Xxx2') - call delete('Xxx3') - argdelete Xxx* - bwipe! Xxx1 Xxx2 Xxx3 -endfunc - -func Test_arg_all_expand() - call writefile(['test file Xxx1'], 'Xx x') - next notexist Xx\ x runtest.vim - call assert_equal('notexist Xx\ x runtest.vim', expand('##')) - call delete('Xx x') -endfunc - -func Test_large_arg() - " Argument longer or equal to the number of columns used to cause - " access to invalid memory. - exe 'argadd ' .repeat('x', &columns) - args -endfunc - -func Test_argdo() - next! Xa.c Xb.c Xc.c - new - let l = [] - argdo call add(l, expand('%')) - call assert_equal(['Xa.c', 'Xb.c', 'Xc.c'], l) - bwipe Xa.c Xb.c Xc.c -endfunc - -" Test for quitting Vim with unedited files in the argument list -func Test_quit_with_arglist() - CheckRunVimInTerminal - let buf = RunVimInTerminal('', {'rows': 6}) - call term_sendkeys(buf, ":set nomore\n") - call term_sendkeys(buf, ":args a b c\n") - call term_sendkeys(buf, ":quit\n") - call term_wait(buf) - call WaitForAssert({-> assert_match('^E173:', term_getline(buf, 6))}) - call StopVimInTerminal(buf) - - " Try :confirm quit with unedited files in arglist - let buf = RunVimInTerminal('', {'rows': 6}) - call term_sendkeys(buf, ":set nomore\n") - call term_sendkeys(buf, ":args a b c\n") - call term_sendkeys(buf, ":confirm quit\n") - call term_wait(buf) - call WaitForAssert({-> assert_match('^\[Y\]es, (N)o: *$', - \ term_getline(buf, 6))}) - call term_sendkeys(buf, "N") - call term_wait(buf) - call term_sendkeys(buf, ":confirm quit\n") - call WaitForAssert({-> assert_match('^\[Y\]es, (N)o: *$', - \ term_getline(buf, 6))}) - call term_sendkeys(buf, "Y") - call term_wait(buf) - call WaitForAssert({-> assert_equal("finished", term_getstatus(buf))}) - only! - " When this test fails, swap files are left behind which breaks subsequent - " tests - call delete('.a.swp') - call delete('.b.swp') - call delete('.c.swp') -endfunc - -" Test for ":all" not working when in the cmdline window -func Test_all_not_allowed_from_cmdwin() - au BufEnter * all - next x - " Use try/catch here, somehow assert_fails() doesn't work on MS-Windows - " console. - let caught = 'no' - try - exe ":norm! 7q?apat\" - catch /E11:/ - let caught = 'yes' - endtry - call assert_equal('yes', caught) - au! BufEnter -endfunc - -func Test_clear_arglist_in_all() - n 0 00 000 0000 00000 000000 - au WinNew 0 n 0 - call assert_fails("all", "E1156") - au! * -endfunc - -" Test for the :all command -func Test_all_command() - %argdelete - - " :all command should not close windows with files in the argument list, - " but can rearrange the windows. - args Xargnew1 Xargnew2 - %bw! - edit Xargold1 - split Xargnew1 - let Xargnew1_winid = win_getid() - split Xargold2 - split Xargnew2 - let Xargnew2_winid = win_getid() - split Xargold3 - all - call assert_equal(2, winnr('$')) - call assert_equal([Xargnew1_winid, Xargnew2_winid], - \ [win_getid(1), win_getid(2)]) - call assert_equal([bufnr('Xargnew1'), bufnr('Xargnew2')], - \ [winbufnr(1), winbufnr(2)]) - - " :all command should close windows for files which are not in the - " argument list in the current tab page. - %bw! - edit Xargold1 - split Xargold2 - tabedit Xargold3 - split Xargold4 - tabedit Xargold5 - tabfirst - all - call assert_equal(3, tabpagenr('$')) - call assert_equal([bufnr('Xargnew1'), bufnr('Xargnew2')], tabpagebuflist(1)) - call assert_equal([bufnr('Xargold4'), bufnr('Xargold3')], tabpagebuflist(2)) - call assert_equal([bufnr('Xargold5')], tabpagebuflist(3)) - - " :tab all command should close windows for files which are not in the - " argument list across all the tab pages. - %bw! - edit Xargold1 - split Xargold2 - tabedit Xargold3 - split Xargold4 - tabedit Xargold5 - tabfirst - args Xargnew1 Xargnew2 - tab all - call assert_equal(2, tabpagenr('$')) - call assert_equal([bufnr('Xargnew1')], tabpagebuflist(1)) - call assert_equal([bufnr('Xargnew2')], tabpagebuflist(2)) - - " If a count is specified, then :all should open only that many windows. - %bw! - args Xargnew1 Xargnew2 Xargnew3 Xargnew4 Xargnew5 - all 3 - call assert_equal(3, winnr('$')) - call assert_equal([bufnr('Xargnew1'), bufnr('Xargnew2'), bufnr('Xargnew3')], - \ [winbufnr(1), winbufnr(2), winbufnr(3)]) - - " The :all command should not open more than 'tabpagemax' tab pages. - " If there are more files, then they should be opened in the last tab page. - %bw! - set tabpagemax=3 - tab all - call assert_equal(3, tabpagenr('$')) - call assert_equal([bufnr('Xargnew1')], tabpagebuflist(1)) - call assert_equal([bufnr('Xargnew2')], tabpagebuflist(2)) - call assert_equal([bufnr('Xargnew3'), bufnr('Xargnew4'), bufnr('Xargnew5')], - \ tabpagebuflist(3)) - set tabpagemax& - - " Without the 'hidden' option, modified buffers should not be closed. - args Xargnew1 Xargnew2 - %bw! - edit Xargtemp1 - call setline(1, 'temp buffer 1') - split Xargtemp2 - call setline(1, 'temp buffer 2') - all - call assert_equal(4, winnr('$')) - call assert_equal([bufnr('Xargtemp2'), bufnr('Xargtemp1'), bufnr('Xargnew1'), - \ bufnr('Xargnew2')], - \ [winbufnr(1), winbufnr(2), winbufnr(3), winbufnr(4)]) - - " With the 'hidden' option set, both modified and unmodified buffers in - " closed windows should be hidden. - set hidden - all - call assert_equal(2, winnr('$')) - call assert_equal([bufnr('Xargnew1'), bufnr('Xargnew2')], - \ [winbufnr(1), winbufnr(2)]) - call assert_equal([1, 1, 0, 0], [getbufinfo('Xargtemp1')[0].hidden, - \ getbufinfo('Xargtemp2')[0].hidden, - \ getbufinfo('Xargnew1')[0].hidden, - \ getbufinfo('Xargnew2')[0].hidden]) - set nohidden - - " When 'winheight' is set to a large value, :all should open only one - " window. - args Xargnew1 Xargnew2 Xargnew3 Xargnew4 Xargnew5 - %bw! - set winheight=9999 - call assert_fails('all', 'E36:') - call assert_equal([1, bufnr('Xargnew1')], [winnr('$'), winbufnr(1)]) - set winheight& - - " When 'winwidth' is set to a large value, :vert all should open only one - " window. - %bw! - set winwidth=9999 - call assert_fails('vert all', 'E36:') - call assert_equal([1, bufnr('Xargnew1')], [winnr('$'), winbufnr(1)]) - set winwidth& - - " empty argument list tests - %bw! - %argdelete - call assert_equal('', execute('args')) - all - call assert_equal(1, winnr('$')) - - %argdelete - %bw! -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_assert.vim b/src/nvim/testdir/test_assert.vim deleted file mode 100644 index 431908e95c..0000000000 --- a/src/nvim/testdir/test_assert.vim +++ /dev/null @@ -1,363 +0,0 @@ -" Test that the methods used for testing work. - -func Test_assert_false() - call assert_equal(0, assert_false(0)) - call assert_equal(0, assert_false(v:false)) - call assert_equal(0, v:false->assert_false()) - - call assert_equal(1, assert_false(123)) - call assert_match("Expected False but got 123", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, 123->assert_false()) - call assert_match("Expected False but got 123", v:errors[0]) - call remove(v:errors, 0) -endfunc - -func Test_assert_true() - call assert_equal(0, assert_true(1)) - call assert_equal(0, assert_true(123)) - call assert_equal(0, assert_true(v:true)) - call assert_equal(0, v:true->assert_true()) - - call assert_equal(1, assert_true(0)) - call assert_match("Expected True but got 0", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, 0->assert_true()) - call assert_match("Expected True but got 0", v:errors[0]) - call remove(v:errors, 0) -endfunc - -func Test_assert_equal() - let s = 'foo' - call assert_equal(0, assert_equal('foo', s)) - let n = 4 - call assert_equal(0, assert_equal(4, n)) - let l = [1, 2, 3] - call assert_equal(0, assert_equal([1, 2, 3], l)) - call assert_equal(v:_null_list, v:_null_list) - call assert_equal(v:_null_list, []) - call assert_equal([], v:_null_list) - - let s = 'foo' - call assert_equal(1, assert_equal('bar', s)) - call assert_match("Expected 'bar' but got 'foo'", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal('XxxxxxxxxxxxxxxxxxxxxxX', 'XyyyyyyyyyyyyyyyyyyyyyyyyyX') - call assert_match("Expected 'X\\\\\\[x occurs 21 times]X' but got 'X\\\\\\[y occurs 25 times]X'", v:errors[0]) - call remove(v:errors, 0) - - " special characters are escaped - call assert_equal("\b\e\f\n\t\r\\\x01\x7f", 'x') - call assert_match('Expected ''\\b\\e\\f\\n\\t\\r\\\\\\x01\\x7f'' but got ''x''', v:errors[0]) - call remove(v:errors, 0) -endfunc - -func Test_assert_equal_dict() - call assert_equal(0, assert_equal(#{one: 1, two: 2}, #{two: 2, one: 1})) - - call assert_equal(1, assert_equal(#{one: 1, two: 2}, #{two: 2, one: 3})) - call assert_match("Expected {'one': 1} but got {'one': 3} - 1 equal item omitted", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, assert_equal(#{one: 1, two: 2}, #{two: 22, one: 11})) - call assert_match("Expected {'one': 1, 'two': 2} but got {'one': 11, 'two': 22}", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, assert_equal(#{}, #{two: 2, one: 1})) - call assert_match("Expected {} but got {'one': 1, 'two': 2}", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, assert_equal(#{two: 2, one: 1}, #{})) - call assert_match("Expected {'one': 1, 'two': 2} but got {}", v:errors[0]) - call remove(v:errors, 0) -endfunc - -func Test_assert_equalfile() - call assert_equal(1, assert_equalfile('abcabc', 'xyzxyz')) - call assert_match("E485: Can't read file abcabc", v:errors[0]) - call remove(v:errors, 0) - - let goodtext = ["one", "two", "three"] - call writefile(goodtext, 'Xone') - call assert_equal(1, 'Xone'->assert_equalfile('xyzxyz')) - call assert_match("E485: Can't read file xyzxyz", v:errors[0]) - call remove(v:errors, 0) - - call writefile(goodtext, 'Xtwo') - call assert_equal(0, assert_equalfile('Xone', 'Xtwo')) - - call writefile([goodtext[0]], 'Xone') - call assert_equal(1, assert_equalfile('Xone', 'Xtwo')) - call assert_match("first file is shorter", v:errors[0]) - call remove(v:errors, 0) - - call writefile(goodtext, 'Xone') - call writefile([goodtext[0]], 'Xtwo') - call assert_equal(1, assert_equalfile('Xone', 'Xtwo')) - call assert_match("second file is shorter", v:errors[0]) - call remove(v:errors, 0) - - call writefile(['1234X89'], 'Xone') - call writefile(['1234Y89'], 'Xtwo') - call assert_equal(1, assert_equalfile('Xone', 'Xtwo')) - call assert_match('difference at byte 4, line 1 after "1234X" vs "1234Y"', v:errors[0]) - call remove(v:errors, 0) - - call writefile([repeat('x', 234) .. 'X'], 'Xone') - call writefile([repeat('x', 234) .. 'Y'], 'Xtwo') - call assert_equal(1, assert_equalfile('Xone', 'Xtwo')) - let xes = repeat('x', 134) - call assert_match('difference at byte 234, line 1 after "' .. xes .. 'X" vs "' .. xes .. 'Y"', v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, assert_equalfile('Xone', 'Xtwo', 'a message')) - call assert_match("a message: difference at byte 234, line 1 after", v:errors[0]) - call remove(v:errors, 0) - - call delete('Xone') - call delete('Xtwo') -endfunc - -func Test_assert_notequal() - let n = 4 - call assert_equal(0, assert_notequal('foo', n)) - let s = 'foo' - call assert_equal(0, assert_notequal([1, 2, 3], s)) - - call assert_equal(1, assert_notequal('foo', s)) - call assert_match("Expected not equal to 'foo'", v:errors[0]) - call remove(v:errors, 0) -endfunc - -func Test_assert_report() - call assert_equal(1, assert_report('something is wrong')) - call assert_match('something is wrong', v:errors[0]) - call remove(v:errors, 0) - call assert_equal(1, 'also wrong'->assert_report()) - call assert_match('also wrong', v:errors[0]) - call remove(v:errors, 0) -endfunc - -func Test_assert_exception() - try - nocommand - catch - call assert_equal(0, assert_exception('E492:')) - endtry - - try - nocommand - catch - call assert_equal(1, assert_exception('E12345:')) - endtry - call assert_match("Expected 'E12345:' but got 'Vim:E492: ", v:errors[0]) - call remove(v:errors, 0) - - try - nocommand - catch - try - " illegal argument, get NULL for error - call assert_equal(1, assert_exception([])) - catch - call assert_equal(0, assert_exception('E730:')) - endtry - endtry - - call assert_equal(1, assert_exception('E492:')) - call assert_match('v:exception is not set', v:errors[0]) - call remove(v:errors, 0) -endfunc - -func Test_wrong_error_type() - let save_verrors = v:errors - let v:['errors'] = {'foo': 3} - call assert_equal('yes', 'no') - let verrors = v:errors - let v:errors = save_verrors - call assert_equal(type([]), type(verrors)) -endfunc - -func Test_match() - call assert_equal(0, assert_match('^f.*b.*r$', 'foobar')) - - call assert_equal(1, assert_match('bar.*foo', 'foobar')) - call assert_match("Pattern 'bar.*foo' does not match 'foobar'", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, assert_match('bar.*foo', 'foobar', 'wrong')) - call assert_match('wrong', v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, 'foobar'->assert_match('bar.*foo', 'wrong')) - call assert_match('wrong', v:errors[0]) - call remove(v:errors, 0) -endfunc - -func Test_notmatch() - call assert_equal(0, assert_notmatch('foo', 'bar')) - call assert_equal(0, assert_notmatch('^foobar$', 'foobars')) - - call assert_equal(1, assert_notmatch('foo', 'foobar')) - call assert_match("Pattern 'foo' does match 'foobar'", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, 'foobar'->assert_notmatch('foo')) - call assert_match("Pattern 'foo' does match 'foobar'", v:errors[0]) - call remove(v:errors, 0) -endfunc - -func Test_assert_fail_fails() - call assert_equal(1, assert_fails('xxx', 'E12345')) - call assert_match("Expected 'E12345' but got 'E492:", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, assert_fails('xxx', 'E9876', 'stupid')) - call assert_match("stupid: Expected 'E9876' but got 'E492:", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, assert_fails('xxx', ['E9876'])) - call assert_match("Expected \\['E9876'\\] but got 'E492:", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, assert_fails('xxx', ['E492:', 'E9876'])) - call assert_match("Expected \\['E492:', 'E9876'\\] but got 'E492:", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, assert_fails('echo', '', 'echo command')) - call assert_match("command did not fail: echo command", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(1, 'echo'->assert_fails('', 'echo command')) - call assert_match("command did not fail: echo command", v:errors[0]) - call remove(v:errors, 0) - - try - call assert_equal(1, assert_fails('xxx', [])) - catch - let exp = v:exception - endtry - call assert_match("E856: assert_fails() second argument", exp) - - try - call assert_equal(1, assert_fails('xxx', ['1', '2', '3'])) - catch - let exp = v:exception - endtry - call assert_match("E856: assert_fails() second argument", exp) - - try - call assert_equal(1, assert_fails('xxx', #{one: 1})) - catch - let exp = v:exception - endtry - call assert_match("E856: assert_fails() second argument", exp) - - try - call assert_equal(1, assert_fails('xxx', 'E492', '', 'burp')) - catch - let exp = v:exception - endtry - call assert_match("E1115: assert_fails() fourth argument must be a number", exp) - - try - call assert_equal(1, assert_fails('xxx', 'E492', '', 54, 123)) - catch - let exp = v:exception - endtry - call assert_match("E1116: assert_fails() fifth argument must be a string", exp) -endfunc - -func Test_assert_fails_in_try_block() - try - call assert_equal(0, assert_fails('throw "error"')) - endtry -endfunc - -func Test_assert_beeps() - new - call assert_equal(0, assert_beeps('normal h')) - - call assert_equal(1, assert_beeps('normal 0')) - call assert_match("command did not beep: normal 0", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(0, 'normal h'->assert_beeps()) - call assert_equal(1, 'normal 0'->assert_beeps()) - call assert_match("command did not beep: normal 0", v:errors[0]) - call remove(v:errors, 0) - - bwipe -endfunc - -func Test_assert_inrange() - call assert_equal(0, assert_inrange(7, 7, 7)) - call assert_equal(0, assert_inrange(5, 7, 5)) - call assert_equal(0, assert_inrange(5, 7, 6)) - call assert_equal(0, assert_inrange(5, 7, 7)) - - call assert_equal(1, assert_inrange(5, 7, 4)) - call assert_match("Expected range 5 - 7, but got 4", v:errors[0]) - call remove(v:errors, 0) - call assert_equal(1, assert_inrange(5, 7, 8)) - call assert_match("Expected range 5 - 7, but got 8", v:errors[0]) - call remove(v:errors, 0) - - call assert_equal(0, 5->assert_inrange(5, 7)) - call assert_equal(0, 7->assert_inrange(5, 7)) - call assert_equal(1, 8->assert_inrange(5, 7)) - call assert_match("Expected range 5 - 7, but got 8", v:errors[0]) - call remove(v:errors, 0) - - call assert_fails('call assert_inrange(1, 1)', 'E119:') - - if has('float') - call assert_equal(0, assert_inrange(7.0, 7, 7)) - call assert_equal(0, assert_inrange(7, 7.0, 7)) - call assert_equal(0, assert_inrange(7, 7, 7.0)) - call assert_equal(0, assert_inrange(5, 7, 5.0)) - call assert_equal(0, assert_inrange(5, 7, 6.0)) - call assert_equal(0, assert_inrange(5, 7, 7.0)) - - call assert_equal(1, assert_inrange(5, 7, 4.0)) - call assert_match("Expected range 5.0 - 7.0, but got 4.0", v:errors[0]) - call remove(v:errors, 0) - call assert_equal(1, assert_inrange(5, 7, 8.0)) - call assert_match("Expected range 5.0 - 7.0, but got 8.0", v:errors[0]) - call remove(v:errors, 0) - endif -endfunc - -func Test_assert_with_msg() - call assert_equal('foo', 'bar', 'testing') - call assert_match("testing: Expected 'foo' but got 'bar'", v:errors[0]) - call remove(v:errors, 0) -endfunc - -func Test_mouse_position() - let save_mouse = &mouse - set mouse=a - new - call setline(1, ['line one', 'line two']) - call assert_equal([0, 1, 1, 0], getpos('.')) - call Ntest_setmouse(1, 5) - call feedkeys("\", "xt") - call assert_equal([0, 1, 5, 0], getpos('.')) - call Ntest_setmouse(2, 20) - call feedkeys("\", "xt") - call assert_equal([0, 2, 8, 0], getpos('.')) - call Ntest_setmouse(5, 1) - call feedkeys("\", "xt") - call assert_equal([0, 2, 1, 0], getpos('.')) - bwipe! - let &mouse = save_mouse -endfunc - -" Must be last. -func Test_zz_quit_detected() - " Verify that if a test function ends Vim the test script detects this. - quit -endfunc diff --git a/src/nvim/testdir/test_autochdir.vim b/src/nvim/testdir/test_autochdir.vim deleted file mode 100644 index a8810047a0..0000000000 --- a/src/nvim/testdir/test_autochdir.vim +++ /dev/null @@ -1,130 +0,0 @@ -" Test 'autochdir' behavior - -source check.vim -CheckOption autochdir - -func Test_set_filename() - CheckFunction test_autochdir - let cwd = getcwd() - call test_autochdir() - set acd - - let s:li = [] - autocmd DirChanged auto call add(s:li, "autocd") - autocmd DirChanged auto call add(s:li, expand("")) - - new - w samples/Xtest - call assert_equal("Xtest", expand('%')) - call assert_equal("samples", substitute(getcwd(), '.*/\(\k*\)', '\1', '')) - call assert_equal(["autocd", getcwd()], s:li) - - bwipe! - au! DirChanged - set noacd - call chdir(cwd) - call delete('samples/Xtest') -endfunc - -func Test_set_filename_other_window() - CheckFunction test_autochdir - let cwd = getcwd() - call test_autochdir() - call mkdir('Xa') - call mkdir('Xb') - call mkdir('Xc') - try - args Xa/aaa.txt Xb/bbb.txt - set acd - let winid = win_getid() - snext - call assert_equal('Xb', substitute(getcwd(), '.*/\([^/]*\)$', '\1', '')) - call win_execute(winid, 'file ' .. cwd .. '/Xc/ccc.txt') - call assert_equal('Xb', substitute(getcwd(), '.*/\([^/]*\)$', '\1', '')) - finally - set noacd - call chdir(cwd) - call delete('Xa', 'rf') - call delete('Xb', 'rf') - call delete('Xc', 'rf') - bwipe! aaa.txt - bwipe! bbb.txt - bwipe! ccc.txt - endtry -endfunc - -func Test_acd_win_execute() - CheckFunction test_autochdir - let cwd = getcwd() - set acd - call test_autochdir() - - call mkdir('Xfile') - let winid = win_getid() - new Xfile/file - call assert_match('testdir.Xfile$', getcwd()) - cd .. - call assert_match('testdir$', getcwd()) - call win_execute(winid, 'echo') - call assert_match('testdir$', getcwd()) - - bwipe! - set noacd - call chdir(cwd) - call delete('Xfile', 'rf') -endfunc - -func Test_verbose_pwd() - CheckFunction test_autochdir - let cwd = getcwd() - call test_autochdir() - - edit global.txt - call assert_match('\[global\].*testdir$', execute('verbose pwd')) - - call mkdir('Xautodir') - split Xautodir/local.txt - lcd Xautodir - call assert_match('\[window\].*testdir[/\\]Xautodir', execute('verbose pwd')) - - set acd - wincmd w - call assert_match('\[autochdir\].*testdir$', execute('verbose pwd')) - execute 'tcd' cwd - call assert_match('\[tabpage\].*testdir$', execute('verbose pwd')) - execute 'cd' cwd - call assert_match('\[global\].*testdir$', execute('verbose pwd')) - execute 'lcd' cwd - call assert_match('\[window\].*testdir$', execute('verbose pwd')) - edit - call assert_match('\[autochdir\].*testdir$', execute('verbose pwd')) - enew - wincmd w - call assert_match('\[autochdir\].*testdir[/\\]Xautodir', execute('verbose pwd')) - wincmd w - call assert_match('\[window\].*testdir$', execute('verbose pwd')) - wincmd w - call assert_match('\[autochdir\].*testdir[/\\]Xautodir', execute('verbose pwd')) - set noacd - call assert_match('\[autochdir\].*testdir[/\\]Xautodir', execute('verbose pwd')) - wincmd w - call assert_match('\[window\].*testdir$', execute('verbose pwd')) - execute 'cd' cwd - call assert_match('\[global\].*testdir$', execute('verbose pwd')) - wincmd w - call assert_match('\[window\].*testdir[/\\]Xautodir', execute('verbose pwd')) - - bwipe! - call chdir(cwd) - call delete('Xautodir', 'rf') -endfunc - -func Test_multibyte() - " using an invalid character should not cause a crash - set wic - call assert_fails('tc û¦*', has('win32') ? 'E480:' : 'E344:') - set nowic -endfunc - - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim deleted file mode 100644 index 6d7f1649b3..0000000000 --- a/src/nvim/testdir/test_autocmd.vim +++ /dev/null @@ -1,3630 +0,0 @@ -" Tests for autocommands - -source shared.vim -source check.vim -source term_util.vim -source screendump.vim -source load.vim - -func s:cleanup_buffers() abort - for bnr in range(1, bufnr('$')) - if bufloaded(bnr) && bufnr('%') != bnr - execute 'bd! ' . bnr - endif - endfor -endfunc - -func Test_vim_did_enter() - call assert_false(v:vim_did_enter) - - " This script will never reach the main loop, can't check if v:vim_did_enter - " becomes one. -endfunc - -" Test for the CursorHold autocmd -func Test_CursorHold_autocmd() - CheckRunVimInTerminal - call writefile(['one', 'two', 'three'], 'Xfile') - let before =<< trim END - set updatetime=10 - au CursorHold * call writefile([line('.')], 'Xoutput', 'a') - END - call writefile(before, 'Xinit') - let buf = RunVimInTerminal('-S Xinit Xfile', {}) - call term_sendkeys(buf, "G") - call term_wait(buf, 20) - call term_sendkeys(buf, "gg") - call term_wait(buf) - call WaitForAssert({-> assert_equal(['1'], readfile('Xoutput')[-1:-1])}) - call term_sendkeys(buf, "j") - call term_wait(buf) - call WaitForAssert({-> assert_equal(['1', '2'], readfile('Xoutput')[-2:-1])}) - call term_sendkeys(buf, "j") - call term_wait(buf) - call WaitForAssert({-> assert_equal(['1', '2', '3'], readfile('Xoutput')[-3:-1])}) - call StopVimInTerminal(buf) - - call delete('Xinit') - call delete('Xoutput') - call delete('Xfile') -endfunc - -if has('timers') - - func ExitInsertMode(id) - call feedkeys("\") - endfunc - - func Test_cursorhold_insert() - " Need to move the cursor. - call feedkeys("ggG", "xt") - - let g:triggered = 0 - au CursorHoldI * let g:triggered += 1 - set updatetime=20 - call timer_start(LoadAdjust(200), 'ExitInsertMode') - call feedkeys('a', 'x!') - call assert_equal(1, g:triggered) - unlet g:triggered - au! CursorHoldI - set updatetime& - endfunc - - func Test_cursorhold_insert_with_timer_interrupt() - CheckFeature job - " Need to move the cursor. - call feedkeys("ggG", "xt") - - " Confirm the timer invoked in exit_cb of the job doesn't disturb - " CursorHoldI event. - let g:triggered = 0 - au CursorHoldI * let g:triggered += 1 - set updatetime=500 - call job_start(has('win32') ? 'cmd /c echo:' : 'echo', - \ {'exit_cb': {-> timer_start(1000, 'ExitInsertMode')}}) - call feedkeys('a', 'x!') - call assert_equal(1, g:triggered) - unlet g:triggered - au! CursorHoldI - set updatetime& - endfunc - - func Test_cursorhold_insert_ctrl_x() - let g:triggered = 0 - au CursorHoldI * let g:triggered += 1 - set updatetime=20 - call timer_start(LoadAdjust(100), 'ExitInsertMode') - " CursorHoldI does not trigger after CTRL-X - call feedkeys("a\", 'x!') - call assert_equal(0, g:triggered) - unlet g:triggered - au! CursorHoldI - set updatetime& - endfunc - - func Test_OptionSet_modeline() - CheckFunction test_override - call test_override('starting', 1) - au! OptionSet - augroup set_tabstop - au OptionSet tabstop call timer_start(1, {-> execute("echo 'Handler called'", "")}) - augroup END - call writefile(['vim: set ts=7 sw=5 :', 'something'], 'XoptionsetModeline') - set modeline - let v:errmsg = '' - call assert_fails('split XoptionsetModeline', 'E12:') - call assert_equal(7, &ts) - call assert_equal('', v:errmsg) - - augroup set_tabstop - au! - augroup END - bwipe! - set ts& - call delete('XoptionsetModeline') - call test_override('starting', 0) - endfunc - -endif "has('timers') - -func Test_bufunload() - augroup test_bufunload_group - autocmd! - autocmd BufUnload * call add(s:li, "bufunload") - autocmd BufDelete * call add(s:li, "bufdelete") - autocmd BufWipeout * call add(s:li, "bufwipeout") - augroup END - - let s:li = [] - new - setlocal bufhidden= - bunload - call assert_equal(["bufunload", "bufdelete"], s:li) - - let s:li = [] - new - setlocal bufhidden=delete - bunload - call assert_equal(["bufunload", "bufdelete"], s:li) - - let s:li = [] - new - setlocal bufhidden=unload - bwipeout - call assert_equal(["bufunload", "bufdelete", "bufwipeout"], s:li) - - au! test_bufunload_group - augroup! test_bufunload_group -endfunc - -" SEGV occurs in older versions. (At least 7.4.2005 or older) -func Test_autocmd_bufunload_with_tabnext() - tabedit - tabfirst - - augroup test_autocmd_bufunload_with_tabnext_group - autocmd! - autocmd BufUnload tabnext - augroup END - - quit - call assert_equal(2, tabpagenr('$')) - - autocmd! test_autocmd_bufunload_with_tabnext_group - augroup! test_autocmd_bufunload_with_tabnext_group - tablast - quit -endfunc - -func Test_argdelete_in_next() - au BufNew,BufEnter,BufLeave,BufWinEnter * argdel - call assert_fails('next a b', 'E1156:') - au! BufNew,BufEnter,BufLeave,BufWinEnter * -endfunc - -func Test_autocmd_bufwinleave_with_tabfirst() - tabedit - augroup sample - autocmd! - autocmd BufWinLeave tabfirst - augroup END - call setline(1, ['a', 'b', 'c']) - edit! a.txt - tabclose -endfunc - -" SEGV occurs in older versions. (At least 7.4.2321 or older) -func Test_autocmd_bufunload_avoiding_SEGV_01() - split aa.txt - let lastbuf = bufnr('$') - - augroup test_autocmd_bufunload - autocmd! - exe 'autocmd BufUnload ' . (lastbuf + 1) . 'bwipeout!' - augroup END - - call assert_fails('edit bb.txt', 'E937:') - - autocmd! test_autocmd_bufunload - augroup! test_autocmd_bufunload - bwipe! aa.txt - bwipe! bb.txt -endfunc - -" SEGV occurs in older versions. (At least 7.4.2321 or older) -func Test_autocmd_bufunload_avoiding_SEGV_02() - setlocal buftype=nowrite - let lastbuf = bufnr('$') - - augroup test_autocmd_bufunload - autocmd! - exe 'autocmd BufUnload ' . (lastbuf + 1) . 'bwipeout!' - augroup END - - normal! i1 - call assert_fails('edit a.txt', 'E517:') - - autocmd! test_autocmd_bufunload - augroup! test_autocmd_bufunload - bwipe! a.txt -endfunc - -func Test_autocmd_dummy_wipeout() - " prepare files - call writefile([''], 'Xdummywipetest1.txt') - call writefile([''], 'Xdummywipetest2.txt') - augroup test_bufunload_group - autocmd! - autocmd BufUnload * call add(s:li, "bufunload") - autocmd BufDelete * call add(s:li, "bufdelete") - autocmd BufWipeout * call add(s:li, "bufwipeout") - augroup END - - let s:li = [] - split Xdummywipetest1.txt - silent! vimgrep /notmatched/ Xdummywipetest* - call assert_equal(["bufunload", "bufwipeout"], s:li) - - bwipeout - call delete('Xdummywipetest1.txt') - call delete('Xdummywipetest2.txt') - au! test_bufunload_group - augroup! test_bufunload_group -endfunc - -func Test_win_tab_autocmd() - let g:record = [] - - augroup testing - au WinNew * call add(g:record, 'WinNew') - au WinClosed * call add(g:record, 'WinClosed') - au WinEnter * call add(g:record, 'WinEnter') - au WinLeave * call add(g:record, 'WinLeave') - au TabNew * call add(g:record, 'TabNew') - au TabClosed * call add(g:record, 'TabClosed') - au TabEnter * call add(g:record, 'TabEnter') - au TabLeave * call add(g:record, 'TabLeave') - augroup END - - split - tabnew - close - close - - call assert_equal([ - \ 'WinLeave', 'WinNew', 'WinEnter', - \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', - \ 'WinLeave', 'TabLeave', 'WinClosed', 'TabClosed', 'WinEnter', 'TabEnter', - \ 'WinLeave', 'WinClosed', 'WinEnter' - \ ], g:record) - - let g:record = [] - tabnew somefile - tabnext - bwipe somefile - - call assert_equal([ - \ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter', - \ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', - \ 'WinClosed', 'TabClosed' - \ ], g:record) - - augroup testing - au! - augroup END - unlet g:record -endfunc - -func Test_WinResized() - CheckRunVimInTerminal - - let lines =<< trim END - set scrolloff=0 - call setline(1, ['111', '222']) - vnew - call setline(1, ['aaa', 'bbb']) - new - call setline(1, ['foo', 'bar']) - - let g:resized = 0 - au WinResized * let g:resized += 1 - - func WriteResizedEvent() - call writefile([json_encode(v:event)], 'XresizeEvent') - endfunc - au WinResized * call WriteResizedEvent() - END - call writefile(lines, 'Xtest_winresized', 'D') - let buf = RunVimInTerminal('-S Xtest_winresized', {'rows': 10}) - - " redraw now to avoid a redraw after the :echo command - call term_sendkeys(buf, ":redraw!\") - call TermWait(buf) - - call term_sendkeys(buf, ":echo g:resized\") - call WaitForAssert({-> assert_match('^0$', term_getline(buf, 10))}, 1000) - - " increase window height, two windows will be reported - call term_sendkeys(buf, "\+") - call TermWait(buf) - call term_sendkeys(buf, ":echo g:resized\") - call WaitForAssert({-> assert_match('^1$', term_getline(buf, 10))}, 1000) - - let event = readfile('XresizeEvent')[0]->json_decode() - call assert_equal({ - \ 'windows': [1002, 1001], - \ }, event) - - " increase window width, three windows will be reported - call term_sendkeys(buf, "\>") - call TermWait(buf) - call term_sendkeys(buf, ":echo g:resized\") - call WaitForAssert({-> assert_match('^2$', term_getline(buf, 10))}, 1000) - - let event = readfile('XresizeEvent')[0]->json_decode() - call assert_equal({ - \ 'windows': [1002, 1001, 1000], - \ }, event) - - call delete('XresizeEvent') - call StopVimInTerminal(buf) -endfunc - -func Test_WinScrolled() - CheckRunVimInTerminal - - let lines =<< trim END - set nowrap scrolloff=0 - for ii in range(1, 18) - call setline(ii, repeat(nr2char(96 + ii), ii * 2)) - endfor - let win_id = win_getid() - let g:matched = v:false - func WriteScrollEvent() - call writefile([json_encode(v:event)], 'XscrollEvent') - endfunc - execute 'au WinScrolled' win_id 'let g:matched = v:true' - let g:scrolled = 0 - au WinScrolled * let g:scrolled += 1 - au WinScrolled * let g:amatch = str2nr(expand('')) - au WinScrolled * let g:afile = str2nr(expand('')) - au WinScrolled * call WriteScrollEvent() - END - call writefile(lines, 'Xtest_winscrolled', 'D') - let buf = RunVimInTerminal('-S Xtest_winscrolled', {'rows': 6}) - - call term_sendkeys(buf, ":echo g:scrolled\") - call WaitForAssert({-> assert_match('^0 ', term_getline(buf, 6))}, 1000) - - " Scroll left/right in Normal mode. - call term_sendkeys(buf, "zlzh:echo g:scrolled\") - call WaitForAssert({-> assert_match('^2 ', term_getline(buf, 6))}, 1000) - - let event = readfile('XscrollEvent')[0]->json_decode() - call assert_equal({ - \ 'all': {'leftcol': 1, 'topline': 0, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, - \ '1000': {'leftcol': -1, 'topline': 0, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0} - \ }, event) - - " Scroll up/down in Normal mode. - call term_sendkeys(buf, "\\:echo g:scrolled\") - call WaitForAssert({-> assert_match('^4 ', term_getline(buf, 6))}, 1000) - - let event = readfile('XscrollEvent')[0]->json_decode() - call assert_equal({ - \ 'all': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, - \ '1000': {'leftcol': 0, 'topline': -1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0} - \ }, event) - - " Scroll up/down in Insert mode. - call term_sendkeys(buf, "Mi\\\i\\\") - call term_sendkeys(buf, ":echo g:scrolled\") - call WaitForAssert({-> assert_match('^6 ', term_getline(buf, 6))}, 1000) - - let event = readfile('XscrollEvent')[0]->json_decode() - call assert_equal({ - \ 'all': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, - \ '1000': {'leftcol': 0, 'topline': -1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0} - \ }, event) - - " Scroll the window horizontally to focus the last letter of the third line - " containing only six characters. Moving to the previous and shorter lines - " should trigger another autocommand as Vim has to make them visible. - call term_sendkeys(buf, "5zl2k") - call term_sendkeys(buf, ":echo g:scrolled\") - call WaitForAssert({-> assert_match('^8 ', term_getline(buf, 6))}, 1000) - - let event = readfile('XscrollEvent')[0]->json_decode() - call assert_equal({ - \ 'all': {'leftcol': 5, 'topline': 0, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, - \ '1000': {'leftcol': -5, 'topline': 0, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0} - \ }, event) - - " Ensure the command was triggered for the specified window ID. - call term_sendkeys(buf, ":echo g:matched\") - call WaitForAssert({-> assert_match('^v:true ', term_getline(buf, 6))}, 1000) - - " Ensure the expansion of and matches the window ID. - call term_sendkeys(buf, ":echo g:amatch == win_id && g:afile == win_id\") - call WaitForAssert({-> assert_match('^v:true ', term_getline(buf, 6))}, 1000) - - call delete('XscrollEvent') - call StopVimInTerminal(buf) -endfunc - -func Test_WinScrolled_mouse() - CheckRunVimInTerminal - - let lines =<< trim END - set nowrap scrolloff=0 - set mouse=a term=xterm ttymouse=sgr mousetime=200 clipboard= - call setline(1, ['foo']->repeat(32)) - split - let g:scrolled = 0 - au WinScrolled * let g:scrolled += 1 - END - call writefile(lines, 'Xtest_winscrolled_mouse', 'D') - let buf = RunVimInTerminal('-S Xtest_winscrolled_mouse', {'rows': 10}) - - " With the upper split focused, send a scroll-down event to the unfocused one. - call test_setmouse(7, 1) - call term_sendkeys(buf, "\") - call TermWait(buf) - call term_sendkeys(buf, ":echo g:scrolled\") - call WaitForAssert({-> assert_match('^1', term_getline(buf, 10))}, 1000) - - " Again, but this time while we're in insert mode. - call term_sendkeys(buf, "i\\") - call TermWait(buf) - call term_sendkeys(buf, ":echo g:scrolled\") - call WaitForAssert({-> assert_match('^2', term_getline(buf, 10))}, 1000) - - call StopVimInTerminal(buf) -endfunc - -func Test_WinScrolled_close_curwin() - CheckRunVimInTerminal - - let lines =<< trim END - set nowrap scrolloff=0 - call setline(1, ['aaa', 'bbb']) - vsplit - au WinScrolled * close - au VimLeave * call writefile(['123456'], 'Xtestout') - END - call writefile(lines, 'Xtest_winscrolled_close_curwin', 'D') - let buf = RunVimInTerminal('-S Xtest_winscrolled_close_curwin', {'rows': 6}) - - " This was using freed memory - call term_sendkeys(buf, "\") - call TermWait(buf) - call StopVimInTerminal(buf) - - " check the startup script finished to the end - call assert_equal(['123456'], readfile('Xtestout')) - call delete('Xtestout') -endfunc - -func Test_WinScrolled_once_only() - CheckRunVimInTerminal - - let lines =<< trim END - set cmdheight=2 - call setline(1, ['aaa', 'bbb']) - let trigger_count = 0 - func ShowInfo(id) - echo g:trigger_count g:winid winlayout() - endfunc - - vsplit - split - " use a timer to show the info after a redraw - au WinScrolled * let trigger_count += 1 | let winid = expand('') | call timer_start(100, 'ShowInfo') - wincmd j - wincmd l - END - call writefile(lines, 'Xtest_winscrolled_once', 'D') - let buf = RunVimInTerminal('-S Xtest_winscrolled_once', #{rows: 10, cols: 60, statusoff: 2}) - - call term_sendkeys(buf, "\") - call VerifyScreenDump(buf, 'Test_winscrolled_once_only_1', {}) - - call StopVimInTerminal(buf) -endfunc - -" Check that WinScrolled is not triggered immediately when defined and there -" are split windows. -func Test_WinScrolled_not_when_defined() - CheckRunVimInTerminal - - let lines =<< trim END - call setline(1, ['aaa', 'bbb']) - echo 'nothing happened' - func ShowTriggered(id) - echo 'triggered' - endfunc - END - call writefile(lines, 'Xtest_winscrolled_not', 'D') - let buf = RunVimInTerminal('-S Xtest_winscrolled_not', #{rows: 10, cols: 60, statusoff: 2}) - call term_sendkeys(buf, ":split\") - call TermWait(buf) - " use a timer to show the message after redrawing - call term_sendkeys(buf, ":au WinScrolled * call timer_start(100, 'ShowTriggered')\") - call VerifyScreenDump(buf, 'Test_winscrolled_not_when_defined_1', {}) - - call term_sendkeys(buf, "\") - call VerifyScreenDump(buf, 'Test_winscrolled_not_when_defined_2', {}) - - call StopVimInTerminal(buf) -endfunc - -func Test_WinScrolled_long_wrapped() - CheckRunVimInTerminal - - let lines =<< trim END - set scrolloff=0 - let height = winheight(0) - let width = winwidth(0) - let g:scrolled = 0 - au WinScrolled * let g:scrolled += 1 - call setline(1, repeat('foo', height * width)) - call cursor(1, height * width) - END - call writefile(lines, 'Xtest_winscrolled_long_wrapped', 'D') - let buf = RunVimInTerminal('-S Xtest_winscrolled_long_wrapped', {'rows': 6}) - - call term_sendkeys(buf, ":echo g:scrolled\") - call WaitForAssert({-> assert_match('^0 ', term_getline(buf, 6))}, 1000) - - call term_sendkeys(buf, 'gj') - call term_sendkeys(buf, ":echo g:scrolled\") - call WaitForAssert({-> assert_match('^1 ', term_getline(buf, 6))}, 1000) - - call term_sendkeys(buf, '0') - call term_sendkeys(buf, ":echo g:scrolled\") - call WaitForAssert({-> assert_match('^2 ', term_getline(buf, 6))}, 1000) - - call term_sendkeys(buf, '$') - call term_sendkeys(buf, ":echo g:scrolled\") - call WaitForAssert({-> assert_match('^3 ', term_getline(buf, 6))}, 1000) - - call StopVimInTerminal(buf) -endfunc - -func Test_WinScrolled_diff() - CheckRunVimInTerminal - - let lines =<< trim END - set diffopt+=foldcolumn:0 - call setline(1, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']) - vnew - call setline(1, ['d', 'e', 'f', 'g', 'h', 'i']) - windo diffthis - func WriteScrollEvent() - call writefile([json_encode(v:event)], 'XscrollEvent') - endfunc - au WinScrolled * call WriteScrollEvent() - END - call writefile(lines, 'Xtest_winscrolled_diff', 'D') - let buf = RunVimInTerminal('-S Xtest_winscrolled_diff', {'rows': 8}) - - call term_sendkeys(buf, "\") - call WaitForAssert({-> assert_match('^d', term_getline(buf, 3))}, 1000) - - let event = readfile('XscrollEvent')[0]->json_decode() - call assert_equal({ - \ 'all': {'leftcol': 0, 'topline': 1, 'topfill': 1, 'width': 0, 'height': 0, 'skipcol': 0}, - \ '1000': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, - \ '1001': {'leftcol': 0, 'topline': 0, 'topfill': -1, 'width': 0, 'height': 0, 'skipcol': 0} - \ }, event) - - call term_sendkeys(buf, "2\") - call WaitForAssert({-> assert_match('^f', term_getline(buf, 3))}, 1000) - - let event = readfile('XscrollEvent')[0]->json_decode() - call assert_equal({ - \ 'all': {'leftcol': 0, 'topline': 2, 'topfill': 2, 'width': 0, 'height': 0, 'skipcol': 0}, - \ '1000': {'leftcol': 0, 'topline': 2, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, - \ '1001': {'leftcol': 0, 'topline': 0, 'topfill': -2, 'width': 0, 'height': 0, 'skipcol': 0} - \ }, event) - - call term_sendkeys(buf, "\") - call WaitForAssert({-> assert_match('^g', term_getline(buf, 3))}, 1000) - - let event = readfile('XscrollEvent')[0]->json_decode() - call assert_equal({ - \ 'all': {'leftcol': 0, 'topline': 2, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, - \ '1000': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, - \ '1001': {'leftcol': 0, 'topline': 1, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0} - \ }, event) - - call term_sendkeys(buf, "2\") - call WaitForAssert({-> assert_match('^e', term_getline(buf, 3))}, 1000) - - let event = readfile('XscrollEvent')[0]->json_decode() - call assert_equal({ - \ 'all': {'leftcol': 0, 'topline': 3, 'topfill': 1, 'width': 0, 'height': 0, 'skipcol': 0}, - \ '1000': {'leftcol': 0, 'topline': -2, 'topfill': 0, 'width': 0, 'height': 0, 'skipcol': 0}, - \ '1001': {'leftcol': 0, 'topline': -1, 'topfill': 1, 'width': 0, 'height': 0, 'skipcol': 0} - \ }, event) - - call StopVimInTerminal(buf) - call delete('XscrollEvent') -endfunc - -func Test_WinClosed() - " Test that the pattern is matched against the closed window's ID, and both - " and are set to it. - new - let winid = win_getid() - let g:matched = v:false - augroup test-WinClosed - autocmd! - execute 'autocmd WinClosed' winid 'let g:matched = v:true' - autocmd WinClosed * let g:amatch = str2nr(expand('')) - autocmd WinClosed * let g:afile = str2nr(expand('')) - augroup END - close - call assert_true(g:matched) - call assert_equal(winid, g:amatch) - call assert_equal(winid, g:afile) - - " Test that WinClosed is non-recursive. - new - new - call assert_equal(3, winnr('$')) - let g:triggered = 0 - augroup test-WinClosed - autocmd! - autocmd WinClosed * let g:triggered += 1 - autocmd WinClosed * 2 wincmd c - augroup END - close - call assert_equal(1, winnr('$')) - call assert_equal(1, g:triggered) - - autocmd! test-WinClosed - augroup! test-WinClosed - unlet g:matched - unlet g:amatch - unlet g:afile - unlet g:triggered -endfunc - -func Test_WinClosed_throws() - vnew - let bnr = bufnr() - call assert_equal(1, bufloaded(bnr)) - augroup test-WinClosed - autocmd WinClosed * throw 'foo' - augroup END - try - close - catch /.*/ - endtry - call assert_equal(0, bufloaded(bnr)) - - autocmd! test-WinClosed - augroup! test-WinClosed -endfunc - -func Test_WinClosed_throws_with_tabs() - tabnew - let bnr = bufnr() - call assert_equal(1, bufloaded(bnr)) - augroup test-WinClosed - autocmd WinClosed * throw 'foo' - augroup END - try - close - catch /.*/ - endtry - call assert_equal(0, bufloaded(bnr)) - - autocmd! test-WinClosed - augroup! test-WinClosed -endfunc - -" This used to trigger WinClosed twice for the same window, and the window's -" buffer was NULL in the second autocommand. -func Test_WinClosed_switch_tab() - edit Xa - split Xb - split Xc - tab split - new - augroup test-WinClosed - autocmd WinClosed * tabprev | bwipe! - augroup END - close - " Check that the tabline has been fully removed - call assert_equal([1, 1], win_screenpos(0)) - - autocmd! test-WinClosed - augroup! test-WinClosed - %bwipe! -endfunc - -func s:AddAnAutocmd() - augroup vimBarTest - au BufReadCmd * echo 'hello' - augroup END - call assert_equal(3, len(split(execute('au vimBarTest'), "\n"))) -endfunc - -func Test_early_bar() - " test that a bar is recognized before the {event} - call s:AddAnAutocmd() - augroup vimBarTest | au! | let done = 77 | augroup END - call assert_equal(1, len(split(execute('au vimBarTest'), "\n"))) - call assert_equal(77, done) - - call s:AddAnAutocmd() - augroup vimBarTest| au!| let done = 88 | augroup END - call assert_equal(1, len(split(execute('au vimBarTest'), "\n"))) - call assert_equal(88, done) - - " test that a bar is recognized after the {event} - call s:AddAnAutocmd() - augroup vimBarTest| au!BufReadCmd| let done = 99 | augroup END - call assert_equal(1, len(split(execute('au vimBarTest'), "\n"))) - call assert_equal(99, done) - - " test that a bar is recognized after the {group} - call s:AddAnAutocmd() - au! vimBarTest|echo 'hello' - call assert_equal(1, len(split(execute('au vimBarTest'), "\n"))) -endfunc - -func RemoveGroup() - autocmd! StartOK - augroup! StartOK -endfunc - -func Test_augroup_warning() - augroup TheWarning - au VimEnter * echo 'entering' - augroup END - call assert_match("TheWarning.*VimEnter", execute('au VimEnter')) - redir => res - augroup! TheWarning - redir END - call assert_match("W19:", res) - call assert_match("-Deleted-.*VimEnter", execute('au VimEnter')) - - " check "Another" does not take the pace of the deleted entry - augroup Another - augroup END - call assert_match("-Deleted-.*VimEnter", execute('au VimEnter')) - augroup! Another - - " no warning for postpone aucmd delete - augroup StartOK - au VimEnter * call RemoveGroup() - augroup END - call assert_match("StartOK.*VimEnter", execute('au VimEnter')) - redir => res - doautocmd VimEnter - redir END - call assert_notmatch("W19:", res) - au! VimEnter - - call assert_fails('augroup!', 'E471:') -endfunc - -func Test_BufReadCmdHelp() - " This used to cause access to free memory - au BufReadCmd * e +h - help - - au! BufReadCmd -endfunc - -func Test_BufReadCmdHelpJump() - " This used to cause access to free memory - au BufReadCmd * e +h{ - " } to fix highlighting - call assert_fails('help', 'E434:') - - au! BufReadCmd -endfunc - -" BufReadCmd is triggered for a "nofile" buffer. Check all values. -func Test_BufReadCmdNofile() - for val in ['nofile', - \ 'nowrite', - \ 'acwrite', - \ 'quickfix', - \ 'help', - "\ 'terminal', - \ 'prompt', - "\ 'popup', - \ ] - new somefile - exe 'set buftype=' .. val - au BufReadCmd somefile call setline(1, 'triggered') - edit - call assert_equal('triggered', getline(1)) - - au! BufReadCmd - bwipe! - endfor -endfunc - -func Test_augroup_deleted() - " This caused a crash before E936 was introduced - augroup x - call assert_fails('augroup! x', 'E936:') - au VimEnter * echo - augroup end - augroup! x - call assert_match("-Deleted-.*VimEnter", execute('au VimEnter')) - au! VimEnter -endfunc - -" Tests for autocommands on :close command. -" This used to be in test13. -func Test_three_windows() - " Clean up buffers, because in some cases this function fails. - call s:cleanup_buffers() - - " Write three files and open them, each in a window. - " Then go to next window, with autocommand that deletes the previous one. - " Do this twice, writing the file. - e! Xtestje1 - call setline(1, 'testje1') - w - sp Xtestje2 - call setline(1, 'testje2') - w - sp Xtestje3 - call setline(1, 'testje3') - w - wincmd w - au WinLeave Xtestje2 bwipe - wincmd w - call assert_equal('Xtestje1', expand('%')) - - au WinLeave Xtestje1 bwipe Xtestje3 - close - call assert_equal('Xtestje1', expand('%')) - - " Test deleting the buffer on a Unload event. If this goes wrong there - " will be the ATTENTION prompt. - e Xtestje1 - au! - au! BufUnload Xtestje1 bwipe - call assert_fails('e Xtestje3', 'E937:') - call assert_equal('Xtestje3', expand('%')) - - e Xtestje2 - sp Xtestje1 - call assert_fails('e', 'E937:') - 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. - au! - only - e Xanother - e Xtestje1 - bwipe Xtestje2 - bwipe Xtestje3 - au BufWipeout Xtestje1 buf Xtestje1 - bwipe - call assert_equal('Xanother', expand('%')) - - only - - help - wincmd w - 1quit - call assert_equal('Xanother', expand('%')) - - au! - enew - call delete('Xtestje1') - call delete('Xtestje2') - call delete('Xtestje3') -endfunc - -func Test_BufEnter() - au! BufEnter - au Bufenter * let val = val . '+' - let g:val = '' - split NewFile - call assert_equal('+', g:val) - bwipe! - call assert_equal('++', g:val) - - " Also get BufEnter when editing a directory - call mkdir('Xdir') - split Xdir - call assert_equal('+++', g:val) - - " On MS-Windows we can't edit the directory, make sure we wipe the right - " buffer. - bwipe! Xdir - call delete('Xdir', 'd') - au! BufEnter - - " Editing a "nofile" buffer doesn't read the file but does trigger BufEnter - " for historic reasons. Also test other 'buftype' values. - for val in ['nofile', - \ 'nowrite', - \ 'acwrite', - \ 'quickfix', - \ 'help', - "\ 'terminal', - \ 'prompt', - "\ 'popup', - \ ] - new somefile - exe 'set buftype=' .. val - au BufEnter somefile call setline(1, 'some text') - edit - call assert_equal('some text', getline(1)) - bwipe! - au! BufEnter - endfor -endfunc - -" Closing a window might cause an endless loop -" E814 for older Vims -func Test_autocmd_bufwipe_in_SessLoadPost() - edit Xtest - tabnew - file Xsomething - set noswapfile - mksession! - - let content =<< trim [CODE] - set nocp noswapfile - let v:swapchoice = "e" - augroup test_autocmd_sessionload - autocmd! - autocmd SessionLoadPost * exe bufnr("Xsomething") . "bw!" - augroup END - - func WriteErrors() - call writefile([execute("messages")], "Xerrors") - endfunc - au VimLeave * call WriteErrors() - [CODE] - - call writefile(content, 'Xvimrc') - call system(GetVimCommand('Xvimrc') .. ' --headless --noplugins -S Session.vim -c cq') - let errors = join(readfile('Xerrors')) - call assert_match('E814', errors) - - set swapfile - for file in ['Session.vim', 'Xvimrc', 'Xerrors'] - call delete(file) - endfor -endfunc - -" Using :blast and :ball for many events caused a crash, because b_nwindows was -" not incremented correctly. -func Test_autocmd_blast_badd() - let content =<< trim [CODE] - au BufNew,BufAdd,BufWinEnter,BufEnter,BufLeave,BufWinLeave,BufUnload,VimEnter foo* blast - edit foo1 - au BufNew,BufAdd,BufWinEnter,BufEnter,BufLeave,BufWinLeave,BufUnload,VimEnter foo* ball - edit foo2 - call writefile(['OK'], 'Xerrors') - qall - [CODE] - - call writefile(content, 'XblastBall') - call system(GetVimCommand() .. ' --clean -S XblastBall') - call assert_match('OK', readfile('Xerrors')->join()) - - call delete('XblastBall') - call delete('Xerrors') -endfunc - -" SEGV occurs in older versions. -func Test_autocmd_bufwipe_in_SessLoadPost2() - tabnew - set noswapfile - mksession! - - let content =<< trim [CODE] - set nocp noswapfile - function! DeleteInactiveBufs() - tabfirst - let tabblist = [] - for i in range(1, tabpagenr(''$'')) - call extend(tabblist, tabpagebuflist(i)) - endfor - for b in range(1, bufnr(''$'')) - if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'') - exec ''bwipeout '' . b - endif - endfor - echomsg "SessionLoadPost DONE" - endfunction - au SessionLoadPost * call DeleteInactiveBufs() - - func WriteErrors() - call writefile([execute("messages")], "Xerrors") - endfunc - au VimLeave * call WriteErrors() - [CODE] - - call writefile(content, 'Xvimrc') - call system(GetVimCommand('Xvimrc') .. ' --headless --noplugins -S Session.vim -c cq') - let errors = join(readfile('Xerrors')) - " This probably only ever matches on unix. - call assert_notmatch('Caught deadly signal SEGV', errors) - call assert_match('SessionLoadPost DONE', errors) - - set swapfile - for file in ['Session.vim', 'Xvimrc', 'Xerrors'] - call delete(file) - endfor -endfunc - -func Test_empty_doau() - doau \| -endfunc - -func s:AutoCommandOptionSet(match) - let template = "Option: <%s>, OldVal: <%s>, OldValLocal: <%s>, OldValGlobal: <%s>, NewVal: <%s>, Scope: <%s>, Command: <%s>\n" - let item = remove(g:options, 0) - let expected = printf(template, item[0], item[1], item[2], item[3], item[4], item[5], item[6]) - let actual = printf(template, a:match, v:option_old, v:option_oldlocal, v:option_oldglobal, v:option_new, v:option_type, v:option_command) - let g:opt = [expected, actual] - "call assert_equal(expected, actual) -endfunc - -func Test_OptionSet() - CheckFunction test_override - CheckOption autochdir - - call test_override('starting', 1) - set nocp - au OptionSet * :call s:AutoCommandOptionSet(expand("")) - - " 1: Setting number option" - let g:options = [['number', 0, 0, 0, 1, 'global', 'set']] - set nu - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 2: Setting local number option" - let g:options = [['number', 1, 1, '', 0, 'local', 'setlocal']] - setlocal nonu - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 3: Setting global number option" - let g:options = [['number', 1, '', 1, 0, 'global', 'setglobal']] - setglobal nonu - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 4: Setting local autoindent option" - let g:options = [['autoindent', 0, 0, '', 1, 'local', 'setlocal']] - setlocal ai - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 5: Setting global autoindent option" - let g:options = [['autoindent', 0, '', 0, 1, 'global', 'setglobal']] - setglobal ai - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 6: Setting global autoindent option" - let g:options = [['autoindent', 1, 1, 1, 0, 'global', 'set']] - set ai! - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 6a: Setting global autoindent option" - let g:options = [['autoindent', 1, 1, 0, 0, 'global', 'set']] - noa setlocal ai - noa setglobal noai - set ai! - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " Should not print anything, use :noa - " 7: don't trigger OptionSet" - let g:options = [['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']] - noa set nonu - call assert_equal([['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 8: Setting several global list and number option" - let g:options = [['list', 0, 0, 0, 1, 'global', 'set'], ['number', 0, 0, 0, 1, 'global', 'set']] - set list nu - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 9: don't trigger OptionSet" - let g:options = [['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid'], ['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']] - noa set nolist nonu - call assert_equal([['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid'], ['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 10: Setting global acd" - let g:options = [['autochdir', 0, 0, '', 1, 'local', 'setlocal']] - setlocal acd - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 11: Setting global autoread (also sets local value)" - let g:options = [['autoread', 0, 0, 0, 1, 'global', 'set']] - set ar - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 12: Setting local autoread" - let g:options = [['autoread', 1, 1, '', 1, 'local', 'setlocal']] - setlocal ar - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 13: Setting global autoread" - let g:options = [['autoread', 1, '', 1, 0, 'global', 'setglobal']] - setglobal invar - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 14: Setting option backspace through :let" - let g:options = [['backspace', '', '', '', 'eol,indent,start', 'global', 'set']] - let &bs = "eol,indent,start" - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 15: Setting option backspace through setbufvar()" - let g:options = [['backup', 0, 0, '', 1, 'local', 'setlocal']] - " try twice, first time, shouldn't trigger because option name is invalid, - " second time, it should trigger - let bnum = bufnr('%') - call assert_fails("call setbufvar(bnum, '&l:bk', 1)", 'E355:') - " should trigger, use correct option name - call setbufvar(bnum, '&backup', 1) - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 16: Setting number option using setwinvar" - let g:options = [['number', 0, 0, '', 1, 'local', 'setlocal']] - call setwinvar(0, '&number', 1) - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 17: Setting key option, shouldn't trigger" - let g:options = [['key', 'invalid', 'invalid1', 'invalid2', 'invalid3', 'invalid4', 'invalid5']] - setlocal key=blah - setlocal key= - call assert_equal([['key', 'invalid', 'invalid1', 'invalid2', 'invalid3', 'invalid4', 'invalid5']], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 18a: Setting string global option" - let oldval = &backupext - let g:options = [['backupext', oldval, oldval, oldval, 'foo', 'global', 'set']] - set backupext=foo - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 18b: Resetting string global option" - let g:options = [['backupext', 'foo', 'foo', 'foo', oldval, 'global', 'set']] - set backupext& - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 18c: Setting global string global option" - let g:options = [['backupext', oldval, '', oldval, 'bar', 'global', 'setglobal']] - setglobal backupext=bar - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 18d: Setting local string global option" - " As this is a global option this sets the global value even though - " :setlocal is used! - noa set backupext& " Reset global and local value (without triggering autocmd) - let g:options = [['backupext', oldval, oldval, '', 'baz', 'local', 'setlocal']] - setlocal backupext=baz - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 18e: Setting again string global option" - noa setglobal backupext=ext_global " Reset global and local value (without triggering autocmd) - noa setlocal backupext=ext_local " Sets the global(!) value! - let g:options = [['backupext', 'ext_local', 'ext_local', 'ext_local', 'fuu', 'global', 'set']] - set backupext=fuu - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 19a: Setting string global-local (to buffer) option" - let oldval = &tags - let g:options = [['tags', oldval, oldval, oldval, 'tagpath', 'global', 'set']] - set tags=tagpath - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 19b: Resetting string global-local (to buffer) option" - let g:options = [['tags', 'tagpath', 'tagpath', 'tagpath', oldval, 'global', 'set']] - set tags& - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 19c: Setting global string global-local (to buffer) option " - let g:options = [['tags', oldval, '', oldval, 'tagpath1', 'global', 'setglobal']] - setglobal tags=tagpath1 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 19d: Setting local string global-local (to buffer) option" - let g:options = [['tags', 'tagpath1', 'tagpath1', '', 'tagpath2', 'local', 'setlocal']] - setlocal tags=tagpath2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 19e: Setting again string global-local (to buffer) option" - " Note: v:option_old is the old global value for global-local string options - " but the old local value for all other kinds of options. - noa setglobal tags=tag_global " Reset global and local value (without triggering autocmd) - noa setlocal tags=tag_local - let g:options = [['tags', 'tag_global', 'tag_local', 'tag_global', 'tagpath', 'global', 'set']] - set tags=tagpath - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 19f: Setting string global-local (to buffer) option to an empty string" - " Note: v:option_old is the old global value for global-local string options - " but the old local value for all other kinds of options. - noa set tags=tag_global " Reset global and local value (without triggering autocmd) - noa setlocal tags= " empty string - let g:options = [['tags', 'tag_global', '', 'tag_global', 'tagpath', 'global', 'set']] - set tags=tagpath - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 20a: Setting string local (to buffer) option" - let oldval = &spelllang - let g:options = [['spelllang', oldval, oldval, oldval, 'elvish,klingon', 'global', 'set']] - set spelllang=elvish,klingon - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 20b: Resetting string local (to buffer) option" - let g:options = [['spelllang', 'elvish,klingon', 'elvish,klingon', 'elvish,klingon', oldval, 'global', 'set']] - set spelllang& - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 20c: Setting global string local (to buffer) option" - let g:options = [['spelllang', oldval, '', oldval, 'elvish', 'global', 'setglobal']] - setglobal spelllang=elvish - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 20d: Setting local string local (to buffer) option" - noa set spelllang& " Reset global and local value (without triggering autocmd) - let g:options = [['spelllang', oldval, oldval, '', 'klingon', 'local', 'setlocal']] - setlocal spelllang=klingon - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 20e: Setting again string local (to buffer) option" - " Note: v:option_old is the old global value for global-local string options - " but the old local value for all other kinds of options. - noa setglobal spelllang=spellglobal " Reset global and local value (without triggering autocmd) - noa setlocal spelllang=spelllocal - let g:options = [['spelllang', 'spelllocal', 'spelllocal', 'spellglobal', 'foo', 'global', 'set']] - set spelllang=foo - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 21a: Setting string global-local (to window) option" - let oldval = &statusline - let g:options = [['statusline', oldval, oldval, oldval, 'foo', 'global', 'set']] - set statusline=foo - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 21b: Resetting string global-local (to window) option" - " Note: v:option_old is the old global value for global-local string options - " but the old local value for all other kinds of options. - let g:options = [['statusline', 'foo', 'foo', 'foo', oldval, 'global', 'set']] - set statusline& - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 21c: Setting global string global-local (to window) option" - let g:options = [['statusline', oldval, '', oldval, 'bar', 'global', 'setglobal']] - setglobal statusline=bar - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 21d: Setting local string global-local (to window) option" - noa set statusline& " Reset global and local value (without triggering autocmd) - let g:options = [['statusline', oldval, oldval, '', 'baz', 'local', 'setlocal']] - setlocal statusline=baz - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 21e: Setting again string global-local (to window) option" - " Note: v:option_old is the old global value for global-local string options - " but the old local value for all other kinds of options. - noa setglobal statusline=bar " Reset global and local value (without triggering autocmd) - noa setlocal statusline=baz - let g:options = [['statusline', 'bar', 'baz', 'bar', 'foo', 'global', 'set']] - set statusline=foo - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 22a: Setting string local (to window) option" - let oldval = &foldignore - let g:options = [['foldignore', oldval, oldval, oldval, 'fo', 'global', 'set']] - set foldignore=fo - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 22b: Resetting string local (to window) option" - let g:options = [['foldignore', 'fo', 'fo', 'fo', oldval, 'global', 'set']] - set foldignore& - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 22c: Setting global string local (to window) option" - let g:options = [['foldignore', oldval, '', oldval, 'bar', 'global', 'setglobal']] - setglobal foldignore=bar - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 22d: Setting local string local (to window) option" - noa set foldignore& " Reset global and local value (without triggering autocmd) - let g:options = [['foldignore', oldval, oldval, '', 'baz', 'local', 'setlocal']] - setlocal foldignore=baz - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 22e: Setting again string local (to window) option" - noa setglobal foldignore=glob " Reset global and local value (without triggering autocmd) - noa setlocal foldignore=loc - let g:options = [['foldignore', 'loc', 'loc', 'glob', 'fo', 'global', 'set']] - set foldignore=fo - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 23a: Setting global number global option" - noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd) - noa setlocal cmdheight=1 " Sets the global(!) value! - let g:options = [['cmdheight', '1', '', '1', '2', 'global', 'setglobal']] - setglobal cmdheight=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 23b: Setting local number global option" - noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd) - noa setlocal cmdheight=1 " Sets the global(!) value! - let g:options = [['cmdheight', '1', '1', '', '2', 'local', 'setlocal']] - setlocal cmdheight=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 23c: Setting again number global option" - noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd) - noa setlocal cmdheight=1 " Sets the global(!) value! - let g:options = [['cmdheight', '1', '1', '1', '2', 'global', 'set']] - set cmdheight=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 23d: Setting again number global option" - noa set cmdheight=8 " Reset global and local value (without triggering autocmd) - let g:options = [['cmdheight', '8', '8', '8', '2', 'global', 'set']] - set cmdheight=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 24a: Setting global number global-local (to buffer) option" - noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd) - noa setlocal undolevels=1 - let g:options = [['undolevels', '8', '', '8', '2', 'global', 'setglobal']] - setglobal undolevels=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 24b: Setting local number global-local (to buffer) option" - noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd) - noa setlocal undolevels=1 - let g:options = [['undolevels', '1', '1', '', '2', 'local', 'setlocal']] - setlocal undolevels=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 24c: Setting again number global-local (to buffer) option" - noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd) - noa setlocal undolevels=1 - let g:options = [['undolevels', '1', '1', '8', '2', 'global', 'set']] - set undolevels=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 24d: Setting again global number global-local (to buffer) option" - noa set undolevels=8 " Reset global and local value (without triggering autocmd) - let g:options = [['undolevels', '8', '8', '8', '2', 'global', 'set']] - set undolevels=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 25a: Setting global number local (to buffer) option" - noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd) - noa setlocal wrapmargin=1 - let g:options = [['wrapmargin', '8', '', '8', '2', 'global', 'setglobal']] - setglobal wrapmargin=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 25b: Setting local number local (to buffer) option" - noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd) - noa setlocal wrapmargin=1 - let g:options = [['wrapmargin', '1', '1', '', '2', 'local', 'setlocal']] - setlocal wrapmargin=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 25c: Setting again number local (to buffer) option" - noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd) - noa setlocal wrapmargin=1 - let g:options = [['wrapmargin', '1', '1', '8', '2', 'global', 'set']] - set wrapmargin=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 25d: Setting again global number local (to buffer) option" - noa set wrapmargin=8 " Reset global and local value (without triggering autocmd) - let g:options = [['wrapmargin', '8', '8', '8', '2', 'global', 'set']] - set wrapmargin=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 26: Setting number global-local (to window) option. - " Such option does currently not exist. - - - " 27a: Setting global number local (to window) option" - noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd) - noa setlocal foldcolumn=1 - let g:options = [['foldcolumn', '8', '', '8', '2', 'global', 'setglobal']] - setglobal foldcolumn=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 27b: Setting local number local (to window) option" - noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd) - noa setlocal foldcolumn=1 - let g:options = [['foldcolumn', '1', '1', '', '2', 'local', 'setlocal']] - setlocal foldcolumn=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 27c: Setting again number local (to window) option" - noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd) - noa setlocal foldcolumn=1 - let g:options = [['foldcolumn', '1', '1', '8', '2', 'global', 'set']] - set foldcolumn=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 27d: Setting again global number local (to window) option" - noa set foldcolumn=8 " Reset global and local value (without triggering autocmd) - let g:options = [['foldcolumn', '8', '8', '8', '2', 'global', 'set']] - set foldcolumn=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 28a: Setting global boolean global option" - noa setglobal nowrapscan " Reset global and local value (without triggering autocmd) - noa setlocal wrapscan " Sets the global(!) value! - let g:options = [['wrapscan', '1', '', '1', '0', 'global', 'setglobal']] - setglobal nowrapscan - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 28b: Setting local boolean global option" - noa setglobal nowrapscan " Reset global and local value (without triggering autocmd) - noa setlocal wrapscan " Sets the global(!) value! - let g:options = [['wrapscan', '1', '1', '', '0', 'local', 'setlocal']] - setlocal nowrapscan - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 28c: Setting again boolean global option" - noa setglobal nowrapscan " Reset global and local value (without triggering autocmd) - noa setlocal wrapscan " Sets the global(!) value! - let g:options = [['wrapscan', '1', '1', '1', '0', 'global', 'set']] - set nowrapscan - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 28d: Setting again global boolean global option" - noa set nowrapscan " Reset global and local value (without triggering autocmd) - let g:options = [['wrapscan', '0', '0', '0', '1', 'global', 'set']] - set wrapscan - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 29a: Setting global boolean global-local (to buffer) option" - noa setglobal noautoread " Reset global and local value (without triggering autocmd) - noa setlocal autoread - let g:options = [['autoread', '0', '', '0', '1', 'global', 'setglobal']] - setglobal autoread - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 29b: Setting local boolean global-local (to buffer) option" - noa setglobal noautoread " Reset global and local value (without triggering autocmd) - noa setlocal autoread - let g:options = [['autoread', '1', '1', '', '0', 'local', 'setlocal']] - setlocal noautoread - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 29c: Setting again boolean global-local (to buffer) option" - noa setglobal noautoread " Reset global and local value (without triggering autocmd) - noa setlocal autoread - let g:options = [['autoread', '1', '1', '0', '1', 'global', 'set']] - set autoread - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 29d: Setting again global boolean global-local (to buffer) option" - noa set noautoread " Reset global and local value (without triggering autocmd) - let g:options = [['autoread', '0', '0', '0', '1', 'global', 'set']] - set autoread - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 30a: Setting global boolean local (to buffer) option" - noa setglobal nocindent " Reset global and local value (without triggering autocmd) - noa setlocal cindent - let g:options = [['cindent', '0', '', '0', '1', 'global', 'setglobal']] - setglobal cindent - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 30b: Setting local boolean local (to buffer) option" - noa setglobal nocindent " Reset global and local value (without triggering autocmd) - noa setlocal cindent - let g:options = [['cindent', '1', '1', '', '0', 'local', 'setlocal']] - setlocal nocindent - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 30c: Setting again boolean local (to buffer) option" - noa setglobal nocindent " Reset global and local value (without triggering autocmd) - noa setlocal cindent - let g:options = [['cindent', '1', '1', '0', '1', 'global', 'set']] - set cindent - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 30d: Setting again global boolean local (to buffer) option" - noa set nocindent " Reset global and local value (without triggering autocmd) - let g:options = [['cindent', '0', '0', '0', '1', 'global', 'set']] - set cindent - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 31: Setting boolean global-local (to window) option - " Currently no such option exists. - - - " 32a: Setting global boolean local (to window) option" - noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd) - noa setlocal cursorcolumn - let g:options = [['cursorcolumn', '0', '', '0', '1', 'global', 'setglobal']] - setglobal cursorcolumn - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 32b: Setting local boolean local (to window) option" - noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd) - noa setlocal cursorcolumn - let g:options = [['cursorcolumn', '1', '1', '', '0', 'local', 'setlocal']] - setlocal nocursorcolumn - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 32c: Setting again boolean local (to window) option" - noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd) - noa setlocal cursorcolumn - let g:options = [['cursorcolumn', '1', '1', '0', '1', 'global', 'set']] - set cursorcolumn - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - " 32d: Setting again global boolean local (to window) option" - noa set nocursorcolumn " Reset global and local value (without triggering autocmd) - let g:options = [['cursorcolumn', '0', '0', '0', '1', 'global', 'set']] - set cursorcolumn - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " 33: Test autocommands when an option value is converted internally. - noa set backspace=1 " Reset global and local value (without triggering autocmd) - let g:options = [['backspace', 'indent,eol', 'indent,eol', 'indent,eol', '2', 'global', 'set']] - set backspace=2 - call assert_equal([], g:options) - call assert_equal(g:opt[0], g:opt[1]) - - - " Cleanup - au! OptionSet - " set tags& - for opt in ['nu', 'ai', 'acd', 'ar', 'bs', 'backup', 'cul', 'cp', 'backupext', 'tags', 'spelllang', 'statusline', 'foldignore', 'cmdheight', 'undolevels', 'wrapmargin', 'foldcolumn', 'wrapscan', 'autoread', 'cindent', 'cursorcolumn'] - exe printf(":set %s&vim", opt) - endfor - call test_override('starting', 0) - delfunc! AutoCommandOptionSet -endfunc - -func Test_OptionSet_diffmode() - CheckFunction test_override - call test_override('starting', 1) - " 18: Changing an option when entering diff mode - new - au OptionSet diff :let &l:cul = v:option_new - - call setline(1, ['buffer 1', 'line2', 'line3', 'line4']) - call assert_equal(0, &l:cul) - diffthis - call assert_equal(1, &l:cul) - - vnew - call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4']) - call assert_equal(0, &l:cul) - diffthis - call assert_equal(1, &l:cul) - - diffoff - call assert_equal(0, &l:cul) - call assert_equal(1, getwinvar(2, '&l:cul')) - bw! - - call assert_equal(1, &l:cul) - diffoff! - call assert_equal(0, &l:cul) - call assert_equal(0, getwinvar(1, '&l:cul')) - bw! - - " Cleanup - au! OptionSet - call test_override('starting', 0) -endfunc - -func Test_OptionSet_diffmode_close() - CheckFunction test_override - call test_override('starting', 1) - " 19: Try to close the current window when entering diff mode - " should not segfault - new - au OptionSet diff close - - call setline(1, ['buffer 1', 'line2', 'line3', 'line4']) - call assert_fails(':diffthis', 'E788') - call assert_equal(1, &diff) - vnew - call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4']) - call assert_fails(':diffthis', 'E788') - call assert_equal(1, &diff) - set diffopt-=closeoff - bw! - call assert_fails(':diffoff!', 'E788') - bw! - - " Cleanup - au! OptionSet - call test_override('starting', 0) - "delfunc! AutoCommandOptionSet -endfunc - -" Test for Bufleave autocommand that deletes the buffer we are about to edit. -func Test_BufleaveWithDelete() - new | edit Xfile1 - - augroup test_bufleavewithdelete - autocmd! - autocmd BufLeave Xfile1 bwipe Xfile2 - augroup END - - call assert_fails('edit Xfile2', 'E143:') - call assert_equal('Xfile1', bufname('%')) - - autocmd! test_bufleavewithdelete BufLeave Xfile1 - augroup! test_bufleavewithdelete - - new - bwipe! Xfile1 -endfunc - -" Test for autocommand that changes the buffer list, when doing ":ball". -func Test_Acmd_BufAll() - enew! - %bwipe! - call writefile(['Test file Xxx1'], 'Xxx1') - call writefile(['Test file Xxx2'], 'Xxx2') - call writefile(['Test file Xxx3'], 'Xxx3') - - " Add three files to the buffer list - split Xxx1 - close - split Xxx2 - close - split Xxx3 - close - - " Wipe the buffer when the buffer is opened - au BufReadPost Xxx2 bwipe - - call append(0, 'Test file Xxx4') - ball - - call assert_equal(2, winnr('$')) - call assert_equal('Xxx1', bufname(winbufnr(winnr('$')))) - wincmd t - - au! BufReadPost - %bwipe! - call delete('Xxx1') - call delete('Xxx2') - call delete('Xxx3') - enew! | only -endfunc - -" Test for autocommand that changes current buffer on BufEnter event. -" Check if modelines are interpreted for the correct buffer. -func Test_Acmd_BufEnter() - %bwipe! - call writefile(['start of test file Xxx1', - \ "\this is a test", - \ 'end of test file Xxx1'], 'Xxx1') - call writefile(['start of test file Xxx2', - \ 'vim: set noai :', - \ "\this is a test", - \ 'end of test file Xxx2'], 'Xxx2') - - au BufEnter Xxx2 brew - set ai modeline modelines=3 - edit Xxx1 - " edit Xxx2, autocmd will do :brew - edit Xxx2 - exe "normal G?this is a\" - " Append text with autoindent to this file - normal othis should be auto-indented - call assert_equal("\this should be auto-indented", getline('.')) - call assert_equal(3, line('.')) - " Remove autocmd and edit Xxx2 again - au! BufEnter Xxx2 - buf! Xxx2 - exe "normal G?this is a\" - " append text without autoindent to Xxx - normal othis should be in column 1 - call assert_equal("this should be in column 1", getline('.')) - call assert_equal(4, line('.')) - - %bwipe! - call delete('Xxx1') - call delete('Xxx2') - set ai&vim modeline&vim modelines&vim -endfunc - -" Test for issue #57 -" do not move cursor on when autoindent is set -func Test_ai_CTRL_O() - enew! - set ai - let save_fo = &fo - set fo+=r - exe "normal o# abcdef\2hi\\d0\" - exe "normal o# abcdef\2hi\d0\" - call assert_equal(['# abc', 'def', 'def'], getline(2, 4)) - - set ai&vim - let &fo = save_fo - enew! -endfunc - -" Test for autocommand that deletes the current buffer on BufLeave event. -" Also test deleting the last buffer, should give a new, empty buffer. -func Test_BufLeave_Wipe() - %bwipe! - let content = ['start of test file Xxx', - \ 'this is a test', - \ 'end of test file Xxx'] - call writefile(content, 'Xxx1') - call writefile(content, 'Xxx2') - - au BufLeave Xxx2 bwipe - edit Xxx1 - split Xxx2 - " delete buffer Xxx2, we should be back to Xxx1 - bwipe - call assert_equal('Xxx1', bufname('%')) - call assert_equal(1, winnr('$')) - - " Create an alternate buffer - %write! test.out - call assert_equal('test.out', bufname('#')) - " delete alternate buffer - bwipe test.out - call assert_equal('Xxx1', bufname('%')) - call assert_equal('', bufname('#')) - - au BufLeave Xxx1 bwipe - " delete current buffer, get an empty one - bwipe! - call assert_equal(1, line('$')) - call assert_equal('', bufname('%')) - let g:bufinfo = getbufinfo() - call assert_equal(1, len(g:bufinfo)) - - call delete('Xxx1') - call delete('Xxx2') - call delete('test.out') - %bwipe - au! BufLeave - - " check that bufinfo doesn't contain a pointer to freed memory - call test_garbagecollect_now() -endfunc - -func Test_QuitPre() - edit Xfoo - let winid = win_getid(winnr()) - split Xbar - au! QuitPre * let g:afile = expand('') - " Close the other window, should be correct. - exe win_id2win(winid) . 'q' - call assert_equal('Xfoo', g:afile) - - unlet g:afile - bwipe Xfoo - bwipe Xbar -endfunc - -func Test_Cmdline() - au! CmdlineChanged : let g:text = getcmdline() - let g:text = 0 - call feedkeys(":echom 'hello'\", 'xt') - call assert_equal("echom 'hello'", g:text) - au! CmdlineChanged - - au! CmdlineChanged : let g:entered = expand('') - let g:entered = 0 - call feedkeys(":echom 'hello'\", 'xt') - call assert_equal(':', g:entered) - au! CmdlineChanged - - autocmd CmdlineChanged : let g:log += [getcmdline()] - - let g:log = [] - cnoremap call setcmdline('ls') - call feedkeys(":\", 'xt') - call assert_equal(['ls'], g:log) - cunmap - - let g:log = [] - call feedkeys(":sign \\\\\\\", 'xt') - call assert_equal([ - \ 's', - \ 'si', - \ 'sig', - \ 'sign', - \ 'sign ', - \ 'sign define', - \ 'sign jump', - \ 'sign list', - \ 'sign jump', - \ 'sign define', - \ 'sign ', - \ ], g:log) - let g:log = [] - set wildmenu wildoptions+=pum - call feedkeys(":sign \\\\\\", 'xt') - call assert_equal([ - \ 's', - \ 'si', - \ 'sig', - \ 'sign', - \ 'sign ', - \ 'sign unplace', - \ 'sign jump', - \ 'sign define', - \ 'sign undefine', - \ 'sign unplace', - \ ], g:log) - set wildmenu& wildoptions& - - let g:log = [] - let @r = 'abc' - call feedkeys(":0\r1\\r2\\r3\", 'xt') - call assert_equal([ - \ '0', - \ '0a', - \ '0ab', - \ '0abc', - \ '0abc1', - \ '0abc1abc', - \ '0abc1abc2', - \ '0abc1abc2abc', - \ '0abc1abc2abc3', - \ ], g:log) - - unlet g:log - au! CmdlineChanged - - au! CmdlineEnter : let g:entered = expand('') - au! CmdlineLeave : let g:left = expand('') - let g:entered = 0 - let g:left = 0 - call feedkeys(":echo 'hello'\", 'xt') - call assert_equal(':', g:entered) - call assert_equal(':', g:left) - au! CmdlineEnter - au! CmdlineLeave - - let save_shellslash = &shellslash - set noshellslash - au! CmdlineEnter / let g:entered = expand('') - au! CmdlineLeave / let g:left = expand('') - let g:entered = 0 - let g:left = 0 - new - call setline(1, 'hello') - call feedkeys("/hello\", 'xt') - call assert_equal('/', g:entered) - call assert_equal('/', g:left) - bwipe! - au! CmdlineEnter - au! CmdlineLeave - let &shellslash = save_shellslash -endfunc - -" Test for BufWritePre autocommand that deletes or unloads the buffer. -func Test_BufWritePre() - %bwipe - au BufWritePre Xxx1 bunload - au BufWritePre Xxx2 bwipe - - call writefile(['start of Xxx1', 'test', 'end of Xxx1'], 'Xxx1') - call writefile(['start of Xxx2', 'test', 'end of Xxx2'], 'Xxx2') - - edit Xtest - e! Xxx2 - bdel Xtest - e Xxx1 - " write it, will unload it and give an error msg - call assert_fails('w', 'E203') - call assert_equal('Xxx2', bufname('%')) - edit Xtest - e! Xxx2 - bwipe Xtest - " write it, will delete the buffer and give an error msg - call assert_fails('w', 'E203') - call assert_equal('Xxx1', bufname('%')) - au! BufWritePre - call delete('Xxx1') - call delete('Xxx2') -endfunc - -" Test for BufUnload autocommand that unloads all the other buffers -func Test_bufunload_all() - call writefile(['Test file Xxx1'], 'Xxx1')" - call writefile(['Test file Xxx2'], 'Xxx2')" - - let content =<< trim [CODE] - func UnloadAllBufs() - let i = 1 - while i <= bufnr('$') - if i != bufnr('%') && bufloaded(i) - exe i . 'bunload' - endif - let i += 1 - endwhile - endfunc - au BufUnload * call UnloadAllBufs() - au VimLeave * call writefile(['Test Finished'], 'Xout') - set nohidden - edit Xxx1 - split Xxx2 - q - [CODE] - - call writefile(content, 'Xtest') - - call delete('Xout') - call system(GetVimCommandClean() .. ' -N --headless -S Xtest') - call assert_true(filereadable('Xout')) - - call delete('Xxx1') - call delete('Xxx2') - call delete('Xtest') - call delete('Xout') -endfunc - -" Some tests for buffer-local autocommands -func Test_buflocal_autocmd() - let g:bname = '' - edit xx - au BufLeave let g:bname = expand("%") - " here, autocommand for xx should trigger. - " but autocommand shall not apply to buffer named . - edit somefile - call assert_equal('xx', g:bname) - let g:bname = '' - " here, autocommand shall be auto-deleted - bwipe xx - " autocmd should not trigger - edit xx - call assert_equal('', g:bname) - " autocmd should not trigger - edit somefile - call assert_equal('', g:bname) - enew - unlet g:bname -endfunc - -" Test for "*Cmd" autocommands -func Test_Cmd_Autocmds() - call writefile(['start of Xxx', "\tabc2", 'end of Xxx'], 'Xxx') - - enew! - au BufReadCmd XtestA 0r Xxx|$del - edit XtestA " will read text of Xxd instead - call assert_equal('start of Xxx', getline(1)) - - au BufWriteCmd XtestA call append(line("$"), "write") - write " will append a line to the file - call assert_equal('write', getline('$')) - call assert_fails('read XtestA', 'E484') " should not read anything - call assert_equal('write', getline(4)) - - " now we have: - " 1 start of Xxx - " 2 abc2 - " 3 end of Xxx - " 4 write - - au FileReadCmd XtestB '[r Xxx - 2r XtestB " will read Xxx below line 2 instead - call assert_equal('start of Xxx', getline(3)) - - " now we have: - " 1 start of Xxx - " 2 abc2 - " 3 start of Xxx - " 4 abc2 - " 5 end of Xxx - " 6 end of Xxx - " 7 write - - au FileWriteCmd XtestC '[,']copy $ - normal 4GA1 - 4,5w XtestC " will copy lines 4 and 5 to the end - call assert_equal("\tabc21", getline(8)) - call assert_fails('r XtestC', 'E484') " should not read anything - call assert_equal("end of Xxx", getline(9)) - - " now we have: - " 1 start of Xxx - " 2 abc2 - " 3 start of Xxx - " 4 abc21 - " 5 end of Xxx - " 6 end of Xxx - " 7 write - " 8 abc21 - " 9 end of Xxx - - let g:lines = [] - au FileAppendCmd XtestD call extend(g:lines, getline(line("'["), line("']"))) - w >>XtestD " will add lines to 'lines' - call assert_equal(9, len(g:lines)) - call assert_fails('$r XtestD', 'E484') " should not read anything - call assert_equal(9, line('$')) - call assert_equal('end of Xxx', getline('$')) - - au BufReadCmd XtestE 0r Xxx|$del - sp XtestE " split window with test.out - call assert_equal('end of Xxx', getline(3)) - - let g:lines = [] - exe "normal 2Goasdf\\\" - au BufWriteCmd XtestE call extend(g:lines, getline(0, '$')) - wall " will write other window to 'lines' - call assert_equal(4, len(g:lines), g:lines) - call assert_equal("asdf", g:lines[2]) - - au! BufReadCmd - au! BufWriteCmd - au! FileReadCmd - au! FileWriteCmd - au! FileAppendCmd - %bwipe! - call delete('Xxx') - enew! -endfunc - -func s:ReadFile() - setl noswapfile nomodified - let filename = resolve(expand(":p")) - execute 'read' fnameescape(filename) - 1d_ - exe 'file' fnameescape(filename) - setl buftype=acwrite -endfunc - -func s:WriteFile() - let filename = resolve(expand(":p")) - setl buftype= - noautocmd execute 'write' fnameescape(filename) - setl buftype=acwrite - setl nomodified -endfunc - -func Test_BufReadCmd() - autocmd BufReadCmd *.test call s:ReadFile() - autocmd BufWriteCmd *.test call s:WriteFile() - - call writefile(['one', 'two', 'three'], 'Xcmd.test') - edit Xcmd.test - call assert_match('Xcmd.test" line 1 of 3', execute('file')) - normal! Gofour - write - call assert_equal(['one', 'two', 'three', 'four'], readfile('Xcmd.test')) - - bwipe! - call delete('Xcmd.test') - au! BufReadCmd - au! BufWriteCmd -endfunc - -func Test_BufWriteCmd() - autocmd BufWriteCmd Xbufwritecmd let g:written = 1 - new - file Xbufwritecmd - set buftype=acwrite - call mkdir('Xbufwritecmd') - write - " BufWriteCmd should be triggered even if a directory has the same name - call assert_equal(1, g:written) - call delete('Xbufwritecmd', 'd') - unlet g:written - au! BufWriteCmd - bwipe! -endfunc - -func SetChangeMarks(start, end) - exe a:start .. 'mark [' - exe a:end .. 'mark ]' -endfunc - -" Verify the effects of autocmds on '[ and '] -func Test_change_mark_in_autocmds() - edit! Xtest - call feedkeys("ia\b\c\d\u\", 'xtn') - - call SetChangeMarks(2, 3) - write - call assert_equal([1, 4], [line("'["), line("']")]) - - call SetChangeMarks(2, 3) - au BufWritePre * call assert_equal([1, 4], [line("'["), line("']")]) - write - au! BufWritePre - - if has('unix') - write XtestFilter - write >> XtestFilter - - call SetChangeMarks(2, 3) - " Marks are set to the entire range of the write - au FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")]) - " '[ is adjusted to just before the line that will receive the filtered - " data - au FilterReadPre * call assert_equal([4, 4], [line("'["), line("']")]) - " The filtered data is read into the buffer, and the source lines are - " still present, so the range is after the source lines - au FilterReadPost * call assert_equal([5, 12], [line("'["), line("']")]) - %!cat XtestFilter - " After the filtered data is read, the original lines are deleted - call assert_equal([1, 8], [line("'["), line("']")]) - au! FilterWritePre,FilterReadPre,FilterReadPost - undo - - call SetChangeMarks(1, 4) - au FilterWritePre * call assert_equal([2, 3], [line("'["), line("']")]) - au FilterReadPre * call assert_equal([3, 3], [line("'["), line("']")]) - au FilterReadPost * call assert_equal([4, 11], [line("'["), line("']")]) - 2,3!cat XtestFilter - call assert_equal([2, 9], [line("'["), line("']")]) - au! FilterWritePre,FilterReadPre,FilterReadPost - undo - - call delete('XtestFilter') - endif - - call SetChangeMarks(1, 4) - au FileWritePre * call assert_equal([2, 3], [line("'["), line("']")]) - 2,3write Xtest2 - au! FileWritePre - - call SetChangeMarks(2, 3) - au FileAppendPre * call assert_equal([1, 4], [line("'["), line("']")]) - write >> Xtest2 - au! FileAppendPre - - call SetChangeMarks(1, 4) - au FileAppendPre * call assert_equal([2, 3], [line("'["), line("']")]) - 2,3write >> Xtest2 - au! FileAppendPre - - call SetChangeMarks(1, 1) - au FileReadPre * call assert_equal([3, 1], [line("'["), line("']")]) - au FileReadPost * call assert_equal([4, 11], [line("'["), line("']")]) - 3read Xtest2 - au! FileReadPre,FileReadPost - undo - - call SetChangeMarks(4, 4) - " When the line is 0, it's adjusted to 1 - au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")]) - au FileReadPost * call assert_equal([1, 8], [line("'["), line("']")]) - 0read Xtest2 - au! FileReadPre,FileReadPost - undo - - call SetChangeMarks(4, 4) - " When the line is 0, it's adjusted to 1 - au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")]) - au FileReadPost * call assert_equal([2, 9], [line("'["), line("']")]) - 1read Xtest2 - au! FileReadPre,FileReadPost - undo - - bwipe! - call delete('Xtest') - call delete('Xtest2') -endfunc - -func Test_Filter_noshelltemp() - CheckExecutable cat - - enew! - call setline(1, ['a', 'b', 'c', 'd']) - - let shelltemp = &shelltemp - set shelltemp - - let g:filter_au = 0 - au FilterWritePre * let g:filter_au += 1 - au FilterReadPre * let g:filter_au += 1 - au FilterReadPost * let g:filter_au += 1 - %!cat - call assert_equal(3, g:filter_au) - - if has('filterpipe') - set noshelltemp - - let g:filter_au = 0 - au FilterWritePre * let g:filter_au += 1 - au FilterReadPre * let g:filter_au += 1 - au FilterReadPost * let g:filter_au += 1 - %!cat - call assert_equal(0, g:filter_au) - endif - - au! FilterWritePre,FilterReadPre,FilterReadPost - let &shelltemp = shelltemp - bwipe! -endfunc - -func Test_TextYankPost() - enew! - call setline(1, ['foo']) - - let g:event = [] - au TextYankPost * let g:event = copy(v:event) - - call assert_equal({}, v:event) - call assert_fails('let v:event = {}', 'E46:') - call assert_fails('let v:event.mykey = 0', 'E742:') - - norm "ayiw - call assert_equal( - \{'regcontents': ['foo'], 'inclusive': v:true, 'regname': 'a', 'operator': 'y', 'visual': v:false, 'regtype': 'v'}, - \g:event) - norm y_ - call assert_equal( - \{'regcontents': ['foo'], 'inclusive': v:false, 'regname': '', 'operator': 'y', 'visual': v:false, 'regtype': 'V'}, - \g:event) - norm Vy - call assert_equal( - \{'regcontents': ['foo'], 'inclusive': v:true, 'regname': '', 'operator': 'y', 'visual': v:true, 'regtype': 'V'}, - \g:event) - call feedkeys("\y", 'x') - call assert_equal( - \{'regcontents': ['f'], 'inclusive': v:true, 'regname': '', 'operator': 'y', 'visual': v:true, 'regtype': "\x161"}, - \g:event) - norm "xciwbar - call assert_equal( - \{'regcontents': ['foo'], 'inclusive': v:true, 'regname': 'x', 'operator': 'c', 'visual': v:false, 'regtype': 'v'}, - \g:event) - norm "bdiw - call assert_equal( - \{'regcontents': ['bar'], 'inclusive': v:true, 'regname': 'b', 'operator': 'd', 'visual': v:false, 'regtype': 'v'}, - \g:event) - - call assert_equal({}, v:event) - - au! TextYankPost - unlet g:event - bwipe! -endfunc - -func Test_autocommand_all_events() - call assert_fails('au * * bwipe', 'E1155:') - call assert_fails('au * x bwipe', 'E1155:') - call assert_fails('au! * x bwipe', 'E1155:') -endfunc - -func Test_autocmd_user() - au User MyEvent let s:res = [expand(""), expand("")] - doautocmd User MyEvent - call assert_equal(['MyEvent', 'MyEvent'], s:res) - au! User - unlet s:res -endfunc - -function s:Before_test_dirchanged() - augroup test_dirchanged - autocmd! - augroup END - let s:li = [] - let s:dir_this = getcwd() - let s:dir_foo = s:dir_this . '/Xfoo' - call mkdir(s:dir_foo) - let s:dir_bar = s:dir_this . '/Xbar' - call mkdir(s:dir_bar) -endfunc - -function s:After_test_dirchanged() - call chdir(s:dir_this) - call delete(s:dir_foo, 'd') - call delete(s:dir_bar, 'd') - augroup test_dirchanged - autocmd! - augroup END -endfunc - -function Test_dirchanged_global() - call s:Before_test_dirchanged() - autocmd test_dirchanged DirChangedPre global call add(s:li, expand("") .. " pre cd " .. v:event.directory) - autocmd test_dirchanged DirChanged global call add(s:li, "cd:") - autocmd test_dirchanged DirChanged global call add(s:li, expand("")) - call chdir(s:dir_foo) - let expected = ["global pre cd " .. s:dir_foo, "cd:", s:dir_foo] - call assert_equal(expected, s:li) - call chdir(s:dir_foo) - call assert_equal(expected, s:li) - exe 'lcd ' .. fnameescape(s:dir_bar) - call assert_equal(expected, s:li) - - exe 'cd ' .. s:dir_foo - exe 'cd ' .. s:dir_bar - autocmd! test_dirchanged DirChanged global let g:result = expand("") - cd - - call assert_equal(s:dir_foo, substitute(g:result, '\\', '/', 'g')) - - call s:After_test_dirchanged() -endfunc - -function Test_dirchanged_local() - call s:Before_test_dirchanged() - autocmd test_dirchanged DirChanged window call add(s:li, "lcd:") - autocmd test_dirchanged DirChanged window call add(s:li, expand("")) - call chdir(s:dir_foo) - call assert_equal([], s:li) - exe 'lcd ' .. fnameescape(s:dir_bar) - call assert_equal(["lcd:", s:dir_bar], s:li) - exe 'lcd ' .. fnameescape(s:dir_bar) - call assert_equal(["lcd:", s:dir_bar], s:li) - call s:After_test_dirchanged() -endfunc - -function Test_dirchanged_auto() - CheckFunction test_autochdir - CheckOption autochdir - call s:Before_test_dirchanged() - call test_autochdir() - autocmd test_dirchanged DirChangedPre auto call add(s:li, "pre cd " .. v:event.directory) - autocmd test_dirchanged DirChanged auto call add(s:li, "auto:") - autocmd test_dirchanged DirChanged auto call add(s:li, expand("")) - set acd - cd .. - call assert_equal([], s:li) - exe 'edit ' . s:dir_foo . '/Xfile' - call assert_equal(s:dir_foo, getcwd()) - let expected = ["pre cd " .. s:dir_foo, "auto:", s:dir_foo] - call assert_equal(expected, s:li) - set noacd - bwipe! - call s:After_test_dirchanged() -endfunc - -" Test TextChangedI and TextChangedP -func Test_ChangedP() - throw 'Skipped: use test/functional/editor/completion_spec.lua' - new - call setline(1, ['foo', 'bar', 'foobar']) - call test_override("char_avail", 1) - set complete=. completeopt=menuone - - func! TextChangedAutocmd(char) - let g:autocmd .= a:char - endfunc - - au! TextChanged :call TextChangedAutocmd('N') - au! TextChangedI :call TextChangedAutocmd('I') - au! TextChangedP :call TextChangedAutocmd('P') - - call cursor(3, 1) - let g:autocmd = '' - call feedkeys("o\", 'tnix') - call assert_equal('I', g:autocmd) - - let g:autocmd = '' - call feedkeys("Sf", 'tnix') - call assert_equal('II', g:autocmd) - - let g:autocmd = '' - call feedkeys("Sf\", 'tnix') - call assert_equal('IIP', g:autocmd) - - let g:autocmd = '' - call feedkeys("Sf\\", 'tnix') - call assert_equal('IIPP', g:autocmd) - - let g:autocmd = '' - call feedkeys("Sf\\\", 'tnix') - call assert_equal('IIPPP', g:autocmd) - - let g:autocmd = '' - call feedkeys("Sf\\\\", 'tnix') - call assert_equal('IIPPPP', g:autocmd) - - call assert_equal(['foo', 'bar', 'foobar', 'foo'], getline(1, '$')) - " TODO: how should it handle completeopt=noinsert,noselect? - - " CleanUp - call test_override("char_avail", 0) - au! TextChanged - au! TextChangedI - au! TextChangedP - delfu TextChangedAutocmd - unlet! g:autocmd - set complete&vim completeopt&vim - - bw! -endfunc - -let g:setline_handled = v:false -func SetLineOne() - if !g:setline_handled - call setline(1, "(x)") - let g:setline_handled = v:true - endif -endfunc - -func Test_TextChangedI_with_setline() - CheckFunction test_override - new - call test_override('char_avail', 1) - autocmd TextChangedI call SetLineOne() - call feedkeys("i(\\", 'tx') - call assert_equal('(', getline(1)) - call assert_equal('x)', getline(2)) - undo - call assert_equal('', getline(1)) - call assert_equal('', getline(2)) - - call test_override('starting', 0) - bwipe! -endfunc - -func Test_Changed_FirstTime() - CheckFeature terminal - CheckNotGui - " Starting a terminal to run Vim is always considered flaky. - let g:test_is_flaky = 1 - - " Prepare file for TextChanged event. - call writefile([''], 'Xchanged.txt') - let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3}) - call assert_equal('running', term_getstatus(buf)) - " Wait for the ruler (in the status line) to be shown. - call WaitForAssert({-> assert_match('\ call writefile(['No'], 'Xchanged.txt')\") - call term_sendkeys(buf, "\\:qa!\") - call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))}) - call assert_equal([''], readfile('Xchanged.txt')) - - " clean up - call delete('Xchanged.txt') - bwipe! -endfunc - -func Test_autocmd_nested() - let g:did_nested = 0 - augroup Testing - au WinNew * edit somefile - au BufNew * let g:did_nested = 1 - augroup END - split - call assert_equal(0, g:did_nested) - close - bwipe! somefile - - " old nested argument still works - augroup Testing - au! - au WinNew * nested edit somefile - au BufNew * let g:did_nested = 1 - augroup END - split - call assert_equal(1, g:did_nested) - close - bwipe! somefile - - " New ++nested argument works - augroup Testing - au! - au WinNew * ++nested edit somefile - au BufNew * let g:did_nested = 1 - augroup END - split - call assert_equal(1, g:did_nested) - close - bwipe! somefile - - augroup Testing - au! - augroup END - - call assert_fails('au WinNew * ++nested ++nested echo bad', 'E983:') - call assert_fails('au WinNew * nested nested echo bad', 'E983:') -endfunc - -func Test_autocmd_nested_cursor_invalid() - set laststatus=0 - copen - cclose - call setline(1, ['foo', 'bar', 'baz']) - 3 - augroup nested_inv - autocmd User foo ++nested copen - autocmd BufAdd * let &laststatus = 2 - &laststatus - augroup END - doautocmd User foo - - augroup nested_inv - au! - augroup END - set laststatus& - cclose - bwipe! -endfunc - -func Test_autocmd_nested_keeps_cursor_pos() - enew - call setline(1, 'foo') - autocmd User foo ++nested normal! $a - autocmd InsertLeave * : - doautocmd User foo - call assert_equal([0, 1, 3, 0], getpos('.')) - - bwipe! -endfunc - -func Test_autocmd_nested_switch_window() - " run this in a separate Vim so that SafeState works - CheckRunVimInTerminal - - let lines =<< trim END - vim9script - ['()']->writefile('Xautofile') - autocmd VimEnter * ++nested edit Xautofile | split - autocmd BufReadPost * autocmd SafeState * ++once foldclosed('.') - autocmd WinEnter * matchadd('ErrorMsg', 'pat') - END - call writefile(lines, 'Xautoscript') - let buf = RunVimInTerminal('-S Xautoscript', {'rows': 10}) - call VerifyScreenDump(buf, 'Test_autocmd_nested_switch', {}) - - call StopVimInTerminal(buf) - call delete('Xautofile') - call delete('Xautoscript') -endfunc - -func Test_autocmd_once() - " Without ++once WinNew triggers twice - let g:did_split = 0 - augroup Testing - au WinNew * let g:did_split += 1 - augroup END - split - split - call assert_equal(2, g:did_split) - call assert_true(exists('#WinNew')) - close - close - - " With ++once WinNew triggers once - let g:did_split = 0 - augroup Testing - au! - au WinNew * ++once let g:did_split += 1 - augroup END - split - split - call assert_equal(1, g:did_split) - call assert_false(exists('#WinNew')) - close - close - - call assert_fails('au WinNew * ++once ++once echo bad', 'E983:') -endfunc - -func Test_autocmd_bufreadpre() - new - let b:bufreadpre = 1 - call append(0, range(100)) - w! XAutocmdBufReadPre.txt - autocmd BufReadPre :let b:bufreadpre += 1 - norm! 50gg - sp - norm! 100gg - wincmd p - let g:wsv1 = winsaveview() - wincmd p - let g:wsv2 = winsaveview() - " triggers BufReadPre, should not move the cursor in either window - " The topline may change one line in a large window. - edit - call assert_inrange(g:wsv2.topline - 1, g:wsv2.topline + 1, winsaveview().topline) - call assert_equal(g:wsv2.lnum, winsaveview().lnum) - call assert_equal(2, b:bufreadpre) - wincmd p - call assert_equal(g:wsv1.topline, winsaveview().topline) - call assert_equal(g:wsv1.lnum, winsaveview().lnum) - call assert_equal(2, b:bufreadpre) - " Now set the cursor position in an BufReadPre autocommand - " (even though the position will be invalid, this should make Vim reset the - " cursor position in the other window. - wincmd p - 1 " set cpo+=g - " won't do anything, but try to set the cursor on an invalid lnum - autocmd BufReadPre :norm! 70gg - " triggers BufReadPre, should not move the cursor in either window - e - call assert_equal(1, winsaveview().topline) - call assert_equal(1, winsaveview().lnum) - call assert_equal(3, b:bufreadpre) - wincmd p - call assert_equal(g:wsv1.topline, winsaveview().topline) - call assert_equal(g:wsv1.lnum, winsaveview().lnum) - call assert_equal(3, b:bufreadpre) - close - close - call delete('XAutocmdBufReadPre.txt') - set cpo-=g -endfunc - -" FileChangedShell tested in test_filechanged.vim - -" Tests for the following autocommands: -" - FileWritePre writing a compressed file -" - FileReadPost reading a compressed file -" - BufNewFile reading a file template -" - BufReadPre decompressing the file to be read -" - FilterReadPre substituting characters in the temp file -" - FilterReadPost substituting characters after filtering -" - FileReadPre set options for decompression -" - FileReadPost decompress the file -func Test_ReadWrite_Autocmds() - " Run this test only on Unix-like systems and if gzip is available - if !has('unix') || !executable("gzip") - return - endif - - " Make $GZIP empty, "-v" would cause trouble. - let $GZIP = "" - - " Use a FileChangedShell autocommand to avoid a prompt for 'Xtestfile.gz' - " being modified outside of Vim (noticed on Solaris). - au FileChangedShell * echo 'caught FileChangedShell' - - " Test for the FileReadPost, FileWritePre and FileWritePost autocmds - augroup Test1 - au! - au FileWritePre *.gz '[,']!gzip - au FileWritePost *.gz undo - au FileReadPost *.gz '[,']!gzip -d - augroup END - - new - set bin - call append(0, [ - \ 'line 2 Abcdefghijklmnopqrstuvwxyz', - \ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 4 Abcdefghijklmnopqrstuvwxyz', - \ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 6 Abcdefghijklmnopqrstuvwxyz', - \ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 8 Abcdefghijklmnopqrstuvwxyz', - \ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 10 Abcdefghijklmnopqrstuvwxyz' - \ ]) - 1,9write! Xtestfile.gz - enew! | close - - new - " Read and decompress the testfile - 0read Xtestfile.gz - call assert_equal([ - \ 'line 2 Abcdefghijklmnopqrstuvwxyz', - \ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 4 Abcdefghijklmnopqrstuvwxyz', - \ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 6 Abcdefghijklmnopqrstuvwxyz', - \ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 8 Abcdefghijklmnopqrstuvwxyz', - \ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 10 Abcdefghijklmnopqrstuvwxyz' - \ ], getline(1, 9)) - enew! | close - - augroup Test1 - au! - augroup END - - " Test for the FileAppendPre and FileAppendPost autocmds - augroup Test2 - au! - au BufNewFile *.c read Xtest.c - au FileAppendPre *.out '[,']s/new/NEW/ - au FileAppendPost *.out !cat Xtest.c >> test.out - augroup END - - call writefile(['/*', ' * Here is a new .c file', ' */'], 'Xtest.c') - new foo.c " should load Xtest.c - call assert_equal(['/*', ' * Here is a new .c file', ' */'], getline(2, 4)) - w! >> test.out " append it to the output file - - let contents = readfile('test.out') - call assert_equal(' * Here is a NEW .c file', contents[2]) - call assert_equal(' * Here is a new .c file', contents[5]) - - call delete('test.out') - enew! | close - augroup Test2 - au! - augroup END - - " Test for the BufReadPre and BufReadPost autocmds - augroup Test3 - au! - " setup autocommands to decompress before reading and re-compress - " afterwards - au BufReadPre *.gz exe '!gzip -d ' . shellescape(expand("")) - au BufReadPre *.gz call rename(expand(":r"), expand("")) - au BufReadPost *.gz call rename(expand(""), expand(":r")) - au BufReadPost *.gz exe '!gzip ' . shellescape(expand(":r")) - augroup END - - e! Xtestfile.gz " Edit compressed file - call assert_equal([ - \ 'line 2 Abcdefghijklmnopqrstuvwxyz', - \ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 4 Abcdefghijklmnopqrstuvwxyz', - \ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 6 Abcdefghijklmnopqrstuvwxyz', - \ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 8 Abcdefghijklmnopqrstuvwxyz', - \ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 10 Abcdefghijklmnopqrstuvwxyz' - \ ], getline(1, 9)) - - w! >> test.out " Append it to the output file - - augroup Test3 - au! - augroup END - - " Test for the FilterReadPre and FilterReadPost autocmds. - set shelltemp " need temp files here - augroup Test4 - au! - au FilterReadPre *.out call rename(expand(""), expand("") . ".t") - au FilterReadPre *.out exe 'silent !sed s/e/E/ ' . shellescape(expand("")) . ".t >" . shellescape(expand("")) - au FilterReadPre *.out exe 'silent !rm ' . shellescape(expand("")) . '.t' - au FilterReadPost *.out '[,']s/x/X/g - augroup END - - e! test.out " Edit the output file - 1,$!cat - call assert_equal([ - \ 'linE 2 AbcdefghijklmnopqrstuvwXyz', - \ 'linE 3 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - \ 'linE 4 AbcdefghijklmnopqrstuvwXyz', - \ 'linE 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - \ 'linE 6 AbcdefghijklmnopqrstuvwXyz', - \ 'linE 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - \ 'linE 8 AbcdefghijklmnopqrstuvwXyz', - \ 'linE 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - \ 'linE 10 AbcdefghijklmnopqrstuvwXyz' - \ ], getline(1, 9)) - call assert_equal([ - \ 'line 2 Abcdefghijklmnopqrstuvwxyz', - \ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 4 Abcdefghijklmnopqrstuvwxyz', - \ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 6 Abcdefghijklmnopqrstuvwxyz', - \ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 8 Abcdefghijklmnopqrstuvwxyz', - \ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 10 Abcdefghijklmnopqrstuvwxyz' - \ ], readfile('test.out')) - - augroup Test4 - au! - augroup END - set shelltemp&vim - - " Test for the FileReadPre and FileReadPost autocmds. - augroup Test5 - au! - au FileReadPre *.gz exe 'silent !gzip -d ' . shellescape(expand("")) - au FileReadPre *.gz call rename(expand(":r"), expand("")) - au FileReadPost *.gz '[,']s/l/L/ - augroup END - - new - 0r Xtestfile.gz " Read compressed file - call assert_equal([ - \ 'Line 2 Abcdefghijklmnopqrstuvwxyz', - \ 'Line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'Line 4 Abcdefghijklmnopqrstuvwxyz', - \ 'Line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'Line 6 Abcdefghijklmnopqrstuvwxyz', - \ 'Line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'Line 8 Abcdefghijklmnopqrstuvwxyz', - \ 'Line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'Line 10 Abcdefghijklmnopqrstuvwxyz' - \ ], getline(1, 9)) - call assert_equal([ - \ 'line 2 Abcdefghijklmnopqrstuvwxyz', - \ 'line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 4 Abcdefghijklmnopqrstuvwxyz', - \ 'line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 6 Abcdefghijklmnopqrstuvwxyz', - \ 'line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 8 Abcdefghijklmnopqrstuvwxyz', - \ 'line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', - \ 'line 10 Abcdefghijklmnopqrstuvwxyz' - \ ], readfile('Xtestfile.gz')) - - augroup Test5 - au! - augroup END - - au! FileChangedShell - call delete('Xtestfile.gz') - call delete('Xtest.c') - call delete('test.out') -endfunc - -func Test_throw_in_BufWritePre() - new - call setline(1, ['one', 'two', 'three']) - call assert_false(filereadable('Xthefile')) - augroup throwing - au BufWritePre X* throw 'do not write' - augroup END - try - w Xthefile - catch - let caught = 1 - endtry - call assert_equal(1, caught) - call assert_false(filereadable('Xthefile')) - - bwipe! - au! throwing -endfunc - -func Test_autocmd_in_try_block() - call mkdir('Xdir') - au BufEnter * let g:fname = expand('%') - try - edit Xdir/ - endtry - call assert_match('Xdir', g:fname) - - unlet g:fname - au! BufEnter - call delete('Xdir', 'rf') -endfunc - -func Test_autocmd_CmdWinEnter() - CheckRunVimInTerminal - " There is not cmdwin switch, so - " test for cmdline_hist - " (both are available with small builds) - CheckFeature cmdline_hist - let lines =<< trim END - let b:dummy_var = 'This is a dummy' - autocmd CmdWinEnter * quit - let winnr = winnr('$') - END - let filename = 'XCmdWinEnter' - call writefile(lines, filename) - let buf = RunVimInTerminal('-S '.filename, #{rows: 6}) - - call term_sendkeys(buf, "q:") - call term_wait(buf) - call term_sendkeys(buf, ":echo b:dummy_var\") - call WaitForAssert({-> assert_match('^This is a dummy', term_getline(buf, 6))}, 2000) - call term_sendkeys(buf, ":echo &buftype\") - call WaitForAssert({-> assert_notmatch('^nofile', term_getline(buf, 6))}, 1000) - call term_sendkeys(buf, ":echo winnr\") - call WaitForAssert({-> assert_match('^1', term_getline(buf, 6))}, 1000) - - " clean up - call StopVimInTerminal(buf) - call delete(filename) -endfunc - -func Test_autocmd_was_using_freed_memory() - pedit xx - n x - augroup winenter - au WinEnter * if winnr('$') > 2 | quit | endif - augroup END - " Nvim needs large 'winwidth' and 'nowinfixwidth' to crash - set winwidth=99999 nowinfixwidth - split - - augroup winenter - au! WinEnter - augroup END - - set winwidth& winfixwidth& - bwipe xx - bwipe x - pclose -endfunc - -func Test_BufWrite_lockmarks() - edit! Xtest - call setline(1, ['a', 'b', 'c', 'd']) - - " :lockmarks preserves the marks - call SetChangeMarks(2, 3) - lockmarks write - call assert_equal([2, 3], [line("'["), line("']")]) - - " *WritePre autocmds get the correct line range, but lockmarks preserves the - " original values for the user - augroup lockmarks - au! - au BufWritePre,FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")]) - au FileWritePre * call assert_equal([3, 4], [line("'["), line("']")]) - augroup END - - lockmarks write - call assert_equal([2, 3], [line("'["), line("']")]) - - if executable('cat') - lockmarks %!cat - call assert_equal([2, 3], [line("'["), line("']")]) - endif - - lockmarks 3,4write Xtest2 - call assert_equal([2, 3], [line("'["), line("']")]) - - au! lockmarks - augroup! lockmarks - call delete('Xtest') - call delete('Xtest2') -endfunc - -func Test_FileType_spell() - if !isdirectory('/tmp') - throw "Skipped: requires /tmp directory" - endif - - " this was crashing with an invalid free() - setglobal spellfile=/tmp/en.utf-8.add - augroup crash - autocmd! - autocmd BufNewFile,BufReadPost crashfile setf somefiletype - autocmd BufNewFile,BufReadPost crashfile set ft=anotherfiletype - autocmd FileType anotherfiletype setlocal spell - augroup END - func! NoCrash() abort - edit /tmp/crashfile - endfunc - call NoCrash() - - au! crash - setglobal spellfile= -endfunc - -" this was wiping out the current buffer and using freed memory -func Test_SpellFileMissing_bwipe() - next 0 - au SpellFileMissing 0 bwipe - call assert_fails('set spell spelllang=0', 'E937:') - - au! SpellFileMissing - set nospell spelllang=en - bwipe -endfunc - -" Test closing a window or editing another buffer from a FileChangedRO handler -" in a readonly buffer -func Test_FileChangedRO_winclose() - augroup FileChangedROTest - au! - autocmd FileChangedRO * quit - augroup END - new - set readonly - call assert_fails('normal i', 'E788:') - close - augroup! FileChangedROTest - - augroup FileChangedROTest - au! - autocmd FileChangedRO * edit Xfile - augroup END - new - set readonly - call assert_fails('normal i', 'E788:') - close - augroup! FileChangedROTest -endfunc - -func LogACmd() - call add(g:logged, line('$')) -endfunc - -func Test_TermChanged() - throw 'skipped: Nvim does not support TermChanged event' - CheckNotGui - - enew! - tabnew - call setline(1, ['a', 'b', 'c', 'd']) - $ - au TermChanged * call LogACmd() - let g:logged = [] - let term_save = &term - set term=xterm - call assert_equal([1, 4], g:logged) - - au! TermChanged - let &term = term_save - bwipe! -endfunc - -" Test for FileReadCmd autocmd -func Test_autocmd_FileReadCmd() - func ReadFileCmd() - call append(line('$'), "v:cmdarg = " .. v:cmdarg) - endfunc - augroup FileReadCmdTest - au! - au FileReadCmd Xtest call ReadFileCmd() - augroup END - - new - read ++bin Xtest - read ++nobin Xtest - read ++edit Xtest - read ++bad=keep Xtest - read ++bad=drop Xtest - read ++bad=- Xtest - read ++ff=unix Xtest - read ++ff=dos Xtest - read ++ff=mac Xtest - read ++enc=utf-8 Xtest - - call assert_equal(['', - \ 'v:cmdarg = ++bin', - \ 'v:cmdarg = ++nobin', - \ 'v:cmdarg = ++edit', - \ 'v:cmdarg = ++bad=keep', - \ 'v:cmdarg = ++bad=drop', - \ 'v:cmdarg = ++bad=-', - \ 'v:cmdarg = ++ff=unix', - \ 'v:cmdarg = ++ff=dos', - \ 'v:cmdarg = ++ff=mac', - \ 'v:cmdarg = ++enc=utf-8'], getline(1, '$')) - - close! - augroup FileReadCmdTest - au! - augroup END - delfunc ReadFileCmd -endfunc - -" Test for passing invalid arguments to autocmd -func Test_autocmd_invalid_args() - " Additional character after * for event - call assert_fails('autocmd *a Xfile set ff=unix', 'E215:') - augroup Test - augroup END - " Invalid autocmd event - call assert_fails('autocmd Bufabc Xfile set ft=vim', 'E216:') - " Invalid autocmd event in a autocmd group - call assert_fails('autocmd Test Bufabc Xfile set ft=vim', 'E216:') - augroup! Test - " Execute all autocmds - call assert_fails('doautocmd * BufEnter', 'E217:') - call assert_fails('augroup! x1a2b3', 'E367:') - call assert_fails('autocmd BufNew pwd', 'E680:') - call assert_fails('autocmd BufNew \) set ff=unix', 'E55:') -endfunc - -" Test for deep nesting of autocmds -func Test_autocmd_deep_nesting() - autocmd BufEnter Xfile doautocmd BufEnter Xfile - call assert_fails('doautocmd BufEnter Xfile', 'E218:') - autocmd! BufEnter Xfile -endfunc - -" Tests for SigUSR1 autocmd event, which is only available on posix systems. -func Test_autocmd_sigusr1() - CheckUnix - - let g:sigusr1_passed = 0 - au Signal SIGUSR1 let g:sigusr1_passed = 1 - call system('kill -s usr1 ' . getpid()) - call WaitForAssert({-> assert_true(g:sigusr1_passed)}) - - au! Signal - unlet g:sigusr1_passed -endfunc - -" Test for BufReadPre autocmd deleting the file -func Test_BufReadPre_delfile() - augroup TestAuCmd - au! - autocmd BufReadPre Xfile call delete('Xfile') - augroup END - call writefile([], 'Xfile') - call assert_fails('new Xfile', 'E200:') - call assert_equal('Xfile', @%) - call assert_equal(1, &readonly) - call delete('Xfile') - augroup TestAuCmd - au! - augroup END - close! -endfunc - -" Test for BufReadPre autocmd changing the current buffer -func Test_BufReadPre_changebuf() - augroup TestAuCmd - au! - autocmd BufReadPre Xfile edit Xsomeotherfile - augroup END - call writefile([], 'Xfile') - call assert_fails('new Xfile', 'E201:') - call assert_equal('Xsomeotherfile', @%) - call assert_equal(1, &readonly) - call delete('Xfile') - augroup TestAuCmd - au! - augroup END - close! -endfunc - -" Test for BufWipeouti autocmd changing the current buffer when reading a file -" in an empty buffer with 'f' flag in 'cpo' -func Test_BufDelete_changebuf() - new - augroup TestAuCmd - au! - autocmd BufWipeout * let bufnr = bufadd('somefile') | exe "b " .. bufnr - augroup END - let save_cpo = &cpo - set cpo+=f - call assert_fails('r Xfile', ['E812:', 'E484:']) - call assert_equal('somefile', @%) - let &cpo = save_cpo - augroup TestAuCmd - au! - augroup END - close! -endfunc - -" Test for the temporary internal window used to execute autocmds -func Test_autocmd_window() - %bw! - edit one.txt - tabnew two.txt - vnew three.txt - tabnew four.txt - tabprevious - let g:blist = [] - augroup aucmd_win_test1 - au! - au BufEnter * call add(g:blist, [expand(''), - \ win_gettype(bufwinnr(expand('')))]) - augroup END - - doautoall BufEnter - call assert_equal([ - \ ['one.txt', 'autocmd'], - \ ['two.txt', ''], - \ ['four.txt', 'autocmd'], - \ ['three.txt', ''], - \ ], g:blist) - - augroup aucmd_win_test1 - au! - augroup END - augroup! aucmd_win_test1 - %bw! -endfunc - -" Test for trying to close the temporary window used for executing an autocmd -func Test_close_autocmd_window() - %bw! - edit one.txt - tabnew two.txt - augroup aucmd_win_test2 - au! - " Nvim makes aucmd_win the last window - " au BufEnter * if expand('') == 'one.txt' | 1close | endif - au BufEnter * if expand('') == 'one.txt' | close | endif - augroup END - - call assert_fails('doautoall BufEnter', 'E813:') - - augroup aucmd_win_test2 - au! - augroup END - augroup! aucmd_win_test2 - %bw! -endfunc - -" Test for trying to close the tab that has the temporary window for exeucing -" an autocmd. -func Test_close_autocmd_tab() - edit one.txt - tabnew two.txt - augroup aucmd_win_test - au! - au BufEnter * if expand('') == 'one.txt' | tabfirst | tabonly | endif - augroup END - - call assert_fails('doautoall BufEnter', 'E813:') - - tabonly - augroup aucmd_win_test - au! - augroup END - augroup! aucmd_win_test - %bwipe! -endfunc - -func Test_Visual_doautoall_redraw() - call setline(1, ['a', 'b']) - new - wincmd p - call feedkeys("G\", 'txn') - autocmd User Explode ++once redraw - doautoall User Explode - %bwipe! -endfunc - -" This was using freed memory. -func Test_BufNew_arglocal() - arglocal - au BufNew * arglocal - call assert_fails('drop xx', 'E1156:') - - au! BufNew -endfunc - -func Test_autocmd_closes_window() - au BufNew,BufWinLeave * e %e - file yyy - au BufNew,BufWinLeave * ball - n xxx - - %bwipe - au! BufNew - au! BufWinLeave -endfunc - -func Test_autocmd_quit_psearch() - sn aa bb - augroup aucmd_win_test - au! - au BufEnter,BufLeave,BufNew,WinEnter,WinLeave,WinNew * if winnr('$') > 1 | q | endif - augroup END - ps / - - augroup aucmd_win_test - au! - augroup END - new - pclose -endfunc - -" Fuzzer found some strange combination that caused a crash. -func Test_autocmd_normal_mess() - " For unknown reason this hangs on MS-Windows - CheckNotMSWindows - - augroup aucmd_normal_test - au BufLeave,BufWinLeave,BufHidden,BufUnload,BufDelete,BufWipeout * norm 7q/qc - augroup END - " Nvim has removed :open - " call assert_fails('o4', 'E1159') - call assert_fails('e4', 'E1159') - silent! H - call assert_fails('e xx', 'E1159') - normal G - - augroup aucmd_normal_test - au! - augroup END -endfunc - -func Test_autocmd_closing_cmdwin() - " For unknown reason this hangs on MS-Windows - CheckNotMSWindows - - au BufWinLeave * nested q - call assert_fails("norm 7q?\n", 'E855:') - - au! BufWinLeave - new - only -endfunc - -func Test_autocmd_vimgrep() - augroup aucmd_vimgrep - au QuickfixCmdPre,BufNew,BufReadCmd * sb - " Nvim makes aucmd_win the last window - " au QuickfixCmdPre,BufNew,BufReadCmd * q9 - au QuickfixCmdPre,BufNew,BufReadCmd * exe 'q' .. (winnr('$') - (win_gettype(winnr('$')) == 'autocmd')) - augroup END - call assert_fails('lv ?a? foo', 'E926:') - - augroup aucmd_vimgrep - au! - augroup END -endfunc - -func Test_bufwipeout_changes_window() - " This should not crash, but we don't have any expectations about what - " happens, changing window in BufWipeout has unpredictable results. - tabedit - let g:window_id = win_getid() - topleft new - setlocal bufhidden=wipe - autocmd BufWipeout call win_gotoid(g:window_id) - tabprevious - +tabclose - - unlet g:window_id - au! BufWipeout - %bwipe! -endfunc - -func Test_v_event_readonly() - autocmd CompleteChanged * let v:event.width = 0 - call assert_fails("normal! i\\", 'E46:') - au! CompleteChanged - - autocmd DirChangedPre * let v:event.directory = '' - call assert_fails('cd .', 'E46:') - au! DirChangedPre - - autocmd ModeChanged * let v:event.new_mode = '' - call assert_fails('normal! cc', 'E46:') - au! ModeChanged - - autocmd TextYankPost * let v:event.operator = '' - call assert_fails('normal! yy', 'E46:') - au! TextYankPost -endfunc - -" Test for ModeChanged pattern -func Test_mode_changes() - let g:index = 0 - let g:mode_seq = ['n', 'i', 'n', 'v', 'V', 'i', 'ix', 'i', 'ic', 'i', 'n', 'no', 'n', 'V', 'v', 's', 'n'] - func! TestMode() - call assert_equal(g:mode_seq[g:index], get(v:event, "old_mode")) - call assert_equal(g:mode_seq[g:index + 1], get(v:event, "new_mode")) - call assert_equal(mode(1), get(v:event, "new_mode")) - let g:index += 1 - endfunc - - au ModeChanged * :call TestMode() - let g:n_to_any = 0 - au ModeChanged n:* let g:n_to_any += 1 - call feedkeys("i\vVca\\\\ggdG", 'tnix') - - let g:V_to_v = 0 - au ModeChanged V:v let g:V_to_v += 1 - call feedkeys("Vv\\", 'tnix') - call assert_equal(len(filter(g:mode_seq[1:], {idx, val -> val == 'n'})), g:n_to_any) - call assert_equal(1, g:V_to_v) - call assert_equal(len(g:mode_seq) - 1, g:index) - - let g:n_to_i = 0 - au ModeChanged n:i let g:n_to_i += 1 - let g:n_to_niI = 0 - au ModeChanged i:niI let g:n_to_niI += 1 - let g:niI_to_i = 0 - au ModeChanged niI:i let g:niI_to_i += 1 - let g:nany_to_i = 0 - au ModeChanged n*:i let g:nany_to_i += 1 - let g:i_to_n = 0 - au ModeChanged i:n let g:i_to_n += 1 - let g:nori_to_any = 0 - au ModeChanged [ni]:* let g:nori_to_any += 1 - let g:i_to_any = 0 - au ModeChanged i:* let g:i_to_any += 1 - let g:index = 0 - let g:mode_seq = ['n', 'i', 'niI', 'i', 'n'] - call feedkeys("a\l\", 'tnix') - call assert_equal(len(g:mode_seq) - 1, g:index) - call assert_equal(1, g:n_to_i) - call assert_equal(1, g:n_to_niI) - call assert_equal(1, g:niI_to_i) - call assert_equal(2, g:nany_to_i) - call assert_equal(1, g:i_to_n) - call assert_equal(2, g:i_to_any) - call assert_equal(3, g:nori_to_any) - - if has('terminal') - let g:mode_seq += ['c', 'n', 't', 'nt', 'c', 'nt', 'n'] - call feedkeys(":term\\N:bd!\", 'tnix') - call assert_equal(len(g:mode_seq) - 1, g:index) - call assert_equal(1, g:n_to_i) - call assert_equal(1, g:n_to_niI) - call assert_equal(1, g:niI_to_i) - call assert_equal(2, g:nany_to_i) - call assert_equal(1, g:i_to_n) - call assert_equal(2, g:i_to_any) - call assert_equal(5, g:nori_to_any) - endif - - let g:n_to_c = 0 - au ModeChanged n:c let g:n_to_c += 1 - let g:c_to_n = 0 - au ModeChanged c:n let g:c_to_n += 1 - let g:mode_seq += ['c', 'n', 'c', 'n'] - call feedkeys("q:\\", 'tnix') - call assert_equal(len(g:mode_seq) - 1, g:index) - call assert_equal(2, g:n_to_c) - call assert_equal(2, g:c_to_n) - unlet g:n_to_c - unlet g:c_to_n - - let g:n_to_v = 0 - au ModeChanged n:v let g:n_to_v += 1 - let g:v_to_n = 0 - au ModeChanged v:n let g:v_to_n += 1 - let g:mode_seq += ['v', 'n'] - call feedkeys("v\", 'tnix') - call assert_equal(len(g:mode_seq) - 1, g:index) - call assert_equal(1, g:n_to_v) - call assert_equal(1, g:v_to_n) - unlet g:n_to_v - unlet g:v_to_n - - au! ModeChanged - delfunc TestMode - unlet! g:mode_seq - unlet! g:index - unlet! g:n_to_any - unlet! g:V_to_v - unlet! g:n_to_i - unlet! g:n_to_niI - unlet! g:niI_to_i - unlet! g:nany_to_i - unlet! g:i_to_n - unlet! g:nori_to_any - unlet! g:i_to_any -endfunc - -func Test_recursive_ModeChanged() - au! ModeChanged * norm 0u - sil! norm  - au! ModeChanged -endfunc - -func Test_ModeChanged_starts_visual() - " This was triggering ModeChanged before setting VIsual, causing a crash. - au! ModeChanged * norm 0u - sil! norm  - - au! ModeChanged -endfunc - -func Test_noname_autocmd() - augroup test_noname_autocmd_group - autocmd! - autocmd BufEnter * call add(s:li, ["BufEnter", expand("")]) - autocmd BufDelete * call add(s:li, ["BufDelete", expand("")]) - autocmd BufLeave * call add(s:li, ["BufLeave", expand("")]) - autocmd BufUnload * call add(s:li, ["BufUnload", expand("")]) - autocmd BufWipeout * call add(s:li, ["BufWipeout", expand("")]) - augroup END - - let s:li = [] - edit foo - call assert_equal([['BufUnload', ''], ['BufDelete', ''], ['BufWipeout', ''], ['BufEnter', 'foo']], s:li) - - au! test_noname_autocmd_group - augroup! test_noname_autocmd_group -endfunc - -func Test_autocmd_split_dummy() - " Autocommand trying to split a window containing a dummy buffer. - auto BufReadPre * exe "sbuf " .. expand("") - " Avoid the "W11" prompt - au FileChangedShell * let v:fcs_choice = 'reload' - func Xautocmd_changelist() - cal writefile(['Xtestfile2:4:4'], 'Xerr') - edit Xerr - lex 'Xtestfile2:4:4' - endfunc - call Xautocmd_changelist() - " Should get E86, but it doesn't always happen (timing?) - silent! call Xautocmd_changelist() - - au! BufReadPre - au! FileChangedShell - delfunc Xautocmd_changelist - bwipe! Xerr - call delete('Xerr') -endfunc - -" This was crashing because there was only one window to execute autocommands -" in. -func Test_autocmd_nested_setbufvar() - CheckFeature python3 - - set hidden - edit Xaaa - edit Xbbb - call setline(1, 'bar') - enew - au BufWriteCmd Xbbb ++nested call setbufvar('Xaaa', '&ft', 'foo') | bw! Xaaa - au FileType foo call py3eval('vim.current.buffer.options["cindent"]') - wall - - au! BufWriteCmd - au! FileType foo - set nohidden - call delete('Xaaa') - call delete('Xbbb') - %bwipe! -endfunc - - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_autoload.vim b/src/nvim/testdir/test_autoload.vim deleted file mode 100644 index e89fe3943b..0000000000 --- a/src/nvim/testdir/test_autoload.vim +++ /dev/null @@ -1,25 +0,0 @@ -" Tests for autoload - -set runtimepath=./sautest - -func Test_autoload_dict_func() - let g:loaded_foo_vim = 0 - let g:called_foo_bar_echo = 0 - call g:foo#bar.echo() - call assert_equal(1, g:loaded_foo_vim) - call assert_equal(1, g:called_foo_bar_echo) - - eval 'bar'->g:foo#addFoo()->assert_equal('barfoo') - - " empty name works in legacy script - call assert_equal('empty', foo#()) -endfunc - -func Test_source_autoload() - let g:loaded_sourced_vim = 0 - source sautest/autoload/sourced.vim - call assert_equal(1, g:loaded_sourced_vim) -endfunc - - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_backspace_opt.vim b/src/nvim/testdir/test_backspace_opt.vim deleted file mode 100644 index 59e94d2898..0000000000 --- a/src/nvim/testdir/test_backspace_opt.vim +++ /dev/null @@ -1,141 +0,0 @@ -" Tests for 'backspace' settings - -func Test_backspace_option() - set backspace= - call assert_equal('', &backspace) - set backspace=indent - call assert_equal('indent', &backspace) - set backspace=eol - call assert_equal('eol', &backspace) - set backspace=start - call assert_equal('start', &backspace) - set backspace=nostop - call assert_equal('nostop', &backspace) - " Add the value - set backspace= - set backspace=indent - call assert_equal('indent', &backspace) - set backspace+=eol - call assert_equal('indent,eol', &backspace) - set backspace+=start - call assert_equal('indent,eol,start', &backspace) - set backspace+=nostop - call assert_equal('indent,eol,start,nostop', &backspace) - " Delete the value - set backspace-=nostop - call assert_equal('indent,eol,start', &backspace) - set backspace-=indent - call assert_equal('eol,start', &backspace) - set backspace-=start - call assert_equal('eol', &backspace) - set backspace-=eol - call assert_equal('', &backspace) - " Check the error - call assert_fails('set backspace=ABC', 'E474:') - call assert_fails('set backspace+=def', 'E474:') - " NOTE: Vim doesn't check following error... - "call assert_fails('set backspace-=ghi', 'E474:') - - " Check backwards compatibility with version 5.4 and earlier - set backspace=0 - call assert_equal('0', &backspace) - set backspace=1 - call assert_equal('1', &backspace) - set backspace=2 - call assert_equal('2', &backspace) - set backspace=3 - call assert_equal('3', &backspace) - call assert_fails('set backspace=4', 'E474:') - call assert_fails('set backspace=10', 'E474:') - - " Cleared when 'compatible' is set - " set compatible - " call assert_equal('', &backspace) - set nocompatible viminfo+=nviminfo -endfunc - -" Test with backspace set to the non-compatible setting -func Test_backspace_ctrl_u() - new - call append(0, [ - \ "1 this shouldn't be deleted", - \ "2 this shouldn't be deleted", - \ "3 this shouldn't be deleted", - \ "4 this should be deleted", - \ "5 this shouldn't be deleted", - \ "6 this shouldn't be deleted", - \ "7 this shouldn't be deleted", - \ "8 this shouldn't be deleted (not touched yet)"]) - call cursor(2, 1) - - " set compatible - set backspace=2 - - exe "normal Avim1\\\" - exe "normal Avim2\u\\\" - - set cpo-=< - inoremap - exe "normal Avim3\<*C-U>\\" - iunmap - exe "normal Avim4\\\\" - - " Test with backspace set to the compatible setting - set backspace= visualbell - exe "normal A vim5\A\\\\" - exe "normal A vim6\Azwei\u\\\" - - inoremap - exe "normal A vim7\<*C-U>\<*C-U>\\" - - call assert_equal([ - \ "1 this shouldn't be deleted", - \ "2 this shouldn't be deleted", - \ "3 this shouldn't be deleted", - \ "4 this should be deleted3", - \ "", - \ "6 this shouldn't be deleted vim5", - \ "7 this shouldn't be deleted vim6", - \ "8 this shouldn't be deleted (not touched yet) vim7", - \ ""], getline(1, '$')) - - " Reset values - set compatible&vim - set visualbell&vim - set backspace&vim - - " Test new nostop option - %d_ - let expected = "foo bar foobar" - call setline(1, expected) - call cursor(1, 8) - exe ":norm! ianotherone\" - call assert_equal(expected, getline(1)) - call cursor(1, 8) - exe ":norm! ianothertwo\" - call assert_equal(expected, getline(1)) - - let content = getline(1) - for value in ['indent,nostop', 'eol,nostop', 'indent,eol,nostop', 'indent,eol,start,nostop'] - exe ":set bs=".. value - %d _ - call setline(1, content) - let expected = " foobar" - call cursor(1, 8) - exe ":norm! ianotherone\" - call assert_equal(expected, getline(1), 'CTRL-U backspace value: '.. &bs) - let expected = "foo foobar" - call setline(1, content) - call cursor(1, 8) - exe ":norm! ianothertwo\" - call assert_equal(expected, getline(1), 'CTRL-W backspace value: '.. &bs) - endfor - - " Reset options - set compatible&vim - set visualbell&vim - set backspace&vim - close! -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_backup.vim b/src/nvim/testdir/test_backup.vim deleted file mode 100644 index d304773da4..0000000000 --- a/src/nvim/testdir/test_backup.vim +++ /dev/null @@ -1,89 +0,0 @@ -" Tests for the backup function - -source check.vim - -func Test_backup() - set backup backupdir=. backupskip= - new - call setline(1, ['line1', 'line2']) - :f Xbackup.txt - :w! Xbackup.txt - " backup file is only created after - " writing a second time (before overwriting) - :w! Xbackup.txt - let l = readfile('Xbackup.txt~') - call assert_equal(['line1', 'line2'], l) - bw! - set backup&vim backupdir&vim backupskip&vim - call delete('Xbackup.txt') - call delete('Xbackup.txt~') -endfunc - -func Test_backup_backupskip() - set backup backupdir=. backupskip=*.txt - new - call setline(1, ['line1', 'line2']) - :f Xbackup.txt - :w! Xbackup.txt - " backup file is only created after - " writing a second time (before overwriting) - :w! Xbackup.txt - call assert_false(filereadable('Xbackup.txt~')) - bw! - set backup&vim backupdir&vim backupskip&vim - call delete('Xbackup.txt') - call delete('Xbackup.txt~') -endfunc - -func Test_backup2() - set backup backupdir=.// backupskip= - new - call setline(1, ['line1', 'line2', 'line3']) - :f Xbackup.txt - :w! Xbackup.txt - " backup file is only created after - " writing a second time (before overwriting) - :w! Xbackup.txt - sp *Xbackup.txt~ - call assert_equal(['line1', 'line2', 'line3'], getline(1,'$')) - let f = expand('%') - call assert_match('%testdir%Xbackup.txt\~', f) - bw! - bw! - call delete('Xbackup.txt') - call delete(f) - set backup&vim backupdir&vim backupskip&vim -endfunc - -func Test_backup2_backupcopy() - set backup backupdir=.// backupcopy=yes backupskip= - new - call setline(1, ['line1', 'line2', 'line3']) - :f Xbackup.txt - :w! Xbackup.txt - " backup file is only created after - " writing a second time (before overwriting) - :w! Xbackup.txt - sp *Xbackup.txt~ - call assert_equal(['line1', 'line2', 'line3'], getline(1,'$')) - let f = expand('%') - call assert_match('%testdir%Xbackup.txt\~', f) - bw! - bw! - call delete('Xbackup.txt') - call delete(f) - set backup&vim backupdir&vim backupcopy&vim backupskip&vim -endfunc - -" Test for using a non-existing directory as a backup directory -func Test_non_existing_backupdir() - throw 'Skipped: Nvim auto-creates backup directory' - set backupdir=./non_existing_dir backupskip= - call writefile(['line1'], 'Xfile') - new Xfile - call assert_fails('write', 'E510:') - set backupdir&vim backupskip&vim - call delete('Xfile') -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_behave.vim b/src/nvim/testdir/test_behave.vim deleted file mode 100644 index c26bfe7ce3..0000000000 --- a/src/nvim/testdir/test_behave.vim +++ /dev/null @@ -1,29 +0,0 @@ -" Test the :behave command - -func Test_behave() - behave mswin - call assert_equal('mouse,key', &selectmode) - call assert_equal('popup', &mousemodel) - call assert_equal('startsel,stopsel', &keymodel) - call assert_equal('exclusive', &selection) - - behave xterm - call assert_equal('', &selectmode) - call assert_equal('extend', &mousemodel) - call assert_equal('', &keymodel) - call assert_equal('inclusive', &selection) - - set selection& - set mousemodel& - set keymodel& - set selection& -endfunc - -func Test_behave_completion() - call feedkeys(":behave \\\"\", 'tx') - call assert_equal('"behave mswin xterm', @:) -endfunc - -func Test_behave_error() - call assert_fails('behave x', 'E475:') -endfunc diff --git a/src/nvim/testdir/test_blob.vim b/src/nvim/testdir/test_blob.vim deleted file mode 100644 index 920ceb826d..0000000000 --- a/src/nvim/testdir/test_blob.vim +++ /dev/null @@ -1,830 +0,0 @@ -" Tests for the Blob types - -source check.vim -source vim9.vim - -func TearDown() - " Run garbage collection after every test - call test_garbagecollect_now() -endfunc - -" Tests for Blob type - -" Blob creation from constant -func Test_blob_create() - let lines =<< trim END - VAR b = 0zDEADBEEF - call assert_equal(v:t_blob, type(b)) - call assert_equal(4, len(b)) - call assert_equal(0xDE, b[0]) - call assert_equal(0xAD, b[1]) - call assert_equal(0xBE, b[2]) - call assert_equal(0xEF, b[3]) - call assert_fails('VAR x = b[4]') - - call assert_equal(0xDE, get(b, 0)) - call assert_equal(0xEF, get(b, 3)) - - call assert_fails('VAR b = 0z1', 'E973:') - call assert_fails('VAR b = 0z1x', 'E973:') - call assert_fails('VAR b = 0z12345', 'E973:') - - call assert_equal(0z, v:_null_blob) - - LET b = 0z001122.33445566.778899.aabbcc.dd - call assert_equal(0z00112233445566778899aabbccdd, b) - call assert_fails('VAR b = 0z1.1') - call assert_fails('VAR b = 0z.') - call assert_fails('VAR b = 0z001122.') - call assert_fails('call get("", 1)', 'E896:') - call assert_equal(0, len(v:_null_blob)) - END - call CheckLegacyAndVim9Success(lines) -endfunc - -" assignment to a blob -func Test_blob_assign() - let lines =<< trim END - VAR b = 0zDEADBEEF - VAR b2 = b[1 : 2] - call assert_equal(0zADBE, b2) - - VAR bcopy = b[:] - call assert_equal(b, bcopy) - call assert_false(b is bcopy) - - LET b = 0zDEADBEEF - LET b2 = b - call assert_true(b is b2) - LET b[:] = 0z11223344 - call assert_equal(0z11223344, b) - call assert_equal(0z11223344, b2) - call assert_true(b is b2) - - LET b = 0zDEADBEEF - LET b[3 :] = 0z66 - call assert_equal(0zDEADBE66, b) - LET b[: 1] = 0z8899 - call assert_equal(0z8899BE66, b) - - LET b = 0zDEADBEEF - LET b += 0z99 - call assert_equal(0zDEADBEEF99, b) - - VAR l = [0z12] - VAR m = deepcopy(l) - LET m[0] = 0z34 #" E742 or E741 should not occur. - END - call CheckLegacyAndVim9Success(lines) - - let lines =<< trim END - VAR b = 0zDEADBEEF - LET b[2 : 3] = 0z112233 - END - call CheckLegacyAndVim9Failure(lines, 'E972:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - LET b[2 : 3] = 0z11 - END - call CheckLegacyAndVim9Failure(lines, 'E972:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - LET b[3 : 2] = 0z - END - call CheckLegacyAndVim9Failure(lines, 'E979:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - LET b ..= 0z33 - END - call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1019:', 'E734:']) - - let lines =<< trim END - VAR b = 0zDEADBEEF - LET b ..= "xx" - END - call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1019:', 'E734:']) - - let lines =<< trim END - VAR b = 0zDEADBEEF - LET b += "xx" - END - call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:']) - - let lines =<< trim END - VAR b = 0zDEADBEEF - LET b[1 : 1] ..= 0z55 - END - call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1183:', 'E734:']) -endfunc - -func Test_blob_get_range() - let lines =<< trim END - VAR b = 0z0011223344 - call assert_equal(0z2233, b[2 : 3]) - call assert_equal(0z223344, b[2 : -1]) - call assert_equal(0z00, b[0 : -5]) - call assert_equal(0z, b[0 : -11]) - call assert_equal(0z44, b[-1 :]) - call assert_equal(0z0011223344, b[:]) - call assert_equal(0z0011223344, b[: -1]) - call assert_equal(0z, b[5 : 6]) - call assert_equal(0z0011, b[-10 : 1]) - END - call CheckLegacyAndVim9Success(lines) - - " legacy script white space - let b = 0z0011223344 - call assert_equal(0z2233, b[2:3]) -endfunc - -func Test_blob_get() - let lines =<< trim END - VAR b = 0z0011223344 - call assert_equal(0x00, get(b, 0)) - call assert_equal(0x22, get(b, 2, 999)) - call assert_equal(0x44, get(b, 4)) - call assert_equal(0x44, get(b, -1)) - call assert_equal(-1, get(b, 5)) - call assert_equal(999, get(b, 5, 999)) - call assert_equal(-1, get(b, -8)) - call assert_equal(999, get(b, -8, 999)) - call assert_equal(10, get(v:_null_blob, 2, 10)) - - call assert_equal(0x00, b[0]) - call assert_equal(0x22, b[2]) - call assert_equal(0x44, b[4]) - call assert_equal(0x44, b[-1]) - END - call CheckLegacyAndVim9Success(lines) - - let lines =<< trim END - VAR b = 0z0011223344 - echo b[5] - END - call CheckLegacyAndVim9Failure(lines, 'E979:') - - let lines =<< trim END - VAR b = 0z0011223344 - echo b[-8] - END - call CheckLegacyAndVim9Failure(lines, 'E979:') -endfunc - -func Test_blob_to_string() - let lines =<< trim END - VAR b = 0z00112233445566778899aabbccdd - call assert_equal('0z00112233.44556677.8899AABB.CCDD', string(b)) - call assert_equal(b, eval(string(b))) - call remove(b, 4, -1) - call assert_equal('0z00112233', string(b)) - call remove(b, 0, 3) - call assert_equal('0z', string(b)) - call assert_equal('0z', string(v:_null_blob)) - END - call CheckLegacyAndVim9Success(lines) -endfunc - -func Test_blob_compare() - let lines =<< trim END - VAR b1 = 0z0011 - VAR b2 = 0z1100 - VAR b3 = 0z001122 - call assert_true(b1 == b1) - call assert_false(b1 == b2) - call assert_false(b1 == b3) - call assert_true(b1 != b2) - call assert_true(b1 != b3) - call assert_true(b1 == 0z0011) - - call assert_false(b1 is b2) - LET b2 = b1 - call assert_true(b1 == b2) - call assert_true(b1 is b2) - LET b2 = copy(b1) - call assert_true(b1 == b2) - call assert_false(b1 is b2) - LET b2 = b1[:] - call assert_true(b1 == b2) - call assert_false(b1 is b2) - call assert_true(b1 isnot b2) - END - call CheckLegacyAndVim9Success(lines) - - let lines =<< trim END - VAR b1 = 0z0011 - echo b1 == 9 - END - call CheckLegacyAndVim9Failure(lines, ['E977:', 'E1072', 'E1072']) - - let lines =<< trim END - VAR b1 = 0z0011 - echo b1 != 9 - END - call CheckLegacyAndVim9Failure(lines, ['E977:', 'E1072', 'E1072']) - - let lines =<< trim END - VAR b1 = 0z0011 - VAR b2 = 0z1100 - VAR x = b1 > b2 - END - call CheckLegacyAndVim9Failure(lines, ['E978:', 'E1072:', 'E1072:']) - - let lines =<< trim END - VAR b1 = 0z0011 - VAR b2 = 0z1100 - VAR x = b1 < b2 - END - call CheckLegacyAndVim9Failure(lines, ['E978:', 'E1072:', 'E1072:']) - - let lines =<< trim END - VAR b1 = 0z0011 - VAR b2 = 0z1100 - VAR x = b1 - b2 - END - call CheckLegacyAndVim9Failure(lines, ['E974:', 'E1036:', 'E974:']) - - let lines =<< trim END - VAR b1 = 0z0011 - VAR b2 = 0z1100 - VAR x = b1 / b2 - END - call CheckLegacyAndVim9Failure(lines, ['E974:', 'E1036:', 'E974:']) - - let lines =<< trim END - VAR b1 = 0z0011 - VAR b2 = 0z1100 - VAR x = b1 * b2 - END - call CheckLegacyAndVim9Failure(lines, ['E974:', 'E1036:', 'E974:']) -endfunc - -func Test_blob_index_assign() - let lines =<< trim END - VAR b = 0z00 - LET b[1] = 0x11 - LET b[2] = 0x22 - call assert_equal(0z001122, b) - END - call CheckLegacyAndVim9Success(lines) - - let lines =<< trim END - VAR b = 0z00 - LET b[2] = 0x33 - END - call CheckLegacyAndVim9Failure(lines, 'E979:') - - let lines =<< trim END - VAR b = 0z00 - LET b[-2] = 0x33 - END - call CheckLegacyAndVim9Failure(lines, 'E979:') -endfunc - -func Test_blob_for_loop() - let lines =<< trim END - VAR blob = 0z00010203 - VAR i = 0 - for byte in blob - call assert_equal(i, byte) - LET i += 1 - endfor - call assert_equal(4, i) - - LET blob = 0z00 - call remove(blob, 0) - call assert_equal(0, len(blob)) - for byte in blob - call assert_report('loop over empty blob') - endfor - - LET blob = 0z0001020304 - LET i = 0 - for byte in blob - call assert_equal(i, byte) - if i == 1 - call remove(blob, 0) - elseif i == 3 - call remove(blob, 3) - endif - LET i += 1 - endfor - call assert_equal(5, i) - END - call CheckLegacyAndVim9Success(lines) -endfunc - -func Test_blob_concatenate() - let lines =<< trim END - VAR b = 0z0011 - LET b += 0z2233 - call assert_equal(0z00112233, b) - - LET b = 0zDEAD + 0zBEEF - call assert_equal(0zDEADBEEF, b) - END - call CheckLegacyAndVim9Success(lines) - - let lines =<< trim END - VAR b = 0z0011 - LET b += "a" - END - call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:']) - - let lines =<< trim END - VAR b = 0z0011 - LET b += 88 - END - call CheckLegacyAndVim9Failure(lines, ['E734:', 'E1012:', 'E734:']) -endfunc - -func Test_blob_add() - let lines =<< trim END - VAR b = 0z0011 - call add(b, 0x22) - call assert_equal(0z001122, b) - END - call CheckLegacyAndVim9Success(lines) - - " Only works in legacy script - let b = 0z0011 - call add(b, '51') - call assert_equal(0z001133, b) - call assert_equal(1, add(v:_null_blob, 0x22)) - - let lines =<< trim END - VAR b = 0z0011 - call add(b, [9]) - END - call CheckLegacyAndVim9Failure(lines, ['E745:', 'E1012:', 'E745:']) - - let lines =<< trim END - VAR b = 0z0011 - call add("", 0x01) - END - call CheckLegacyAndVim9Failure(lines, 'E897:') - - let lines =<< trim END - add(v:_null_blob, 0x22) - END - call CheckDefExecAndScriptFailure(lines, 'E1131:') -endfunc - -func Test_blob_empty() - call assert_false(empty(0z001122)) - call assert_true(empty(0z)) - call assert_true(empty(v:_null_blob)) -endfunc - -" Test removing items in blob -func Test_blob_func_remove() - let lines =<< trim END - #" Test removing 1 element - VAR b = 0zDEADBEEF - call assert_equal(0xDE, remove(b, 0)) - call assert_equal(0zADBEEF, b) - - LET b = 0zDEADBEEF - call assert_equal(0xEF, remove(b, -1)) - call assert_equal(0zDEADBE, b) - - LET b = 0zDEADBEEF - call assert_equal(0xAD, remove(b, 1)) - call assert_equal(0zDEBEEF, b) - - #" Test removing range of element(s) - LET b = 0zDEADBEEF - call assert_equal(0zBE, remove(b, 2, 2)) - call assert_equal(0zDEADEF, b) - - LET b = 0zDEADBEEF - call assert_equal(0zADBE, remove(b, 1, 2)) - call assert_equal(0zDEEF, b) - END - call CheckLegacyAndVim9Success(lines) - - " Test invalid cases - let lines =<< trim END - VAR b = 0zDEADBEEF - call remove(b, 5) - END - call CheckLegacyAndVim9Failure(lines, 'E979:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - call remove(b, 1, 5) - END - call CheckLegacyAndVim9Failure(lines, 'E979:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - call remove(b, 3, 2) - END - call CheckLegacyAndVim9Failure(lines, 'E979:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - call remove(1, 0) - END - call CheckLegacyAndVim9Failure(lines, 'E896:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - call remove(b, b) - END - call CheckLegacyAndVim9Failure(lines, 'E974:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - call remove(b, 1, []) - END - call CheckLegacyAndVim9Failure(lines, 'E745:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - call remove(v:_null_blob, 1, 2) - END - call CheckLegacyAndVim9Failure(lines, 'E979:') - - let lines =<< trim END - let b = 0zDEADBEEF - lockvar b - call remove(b, 0) - unlockvar b - END - call CheckScriptFailure(lines, 'E741:') - - " can only check at script level, not in a :def function - let lines =<< trim END - vim9script - var b = 0zDEADBEEF - lockvar b - remove(b, 0) - END - call CheckScriptFailure(lines, 'E741:') -endfunc - -func Test_blob_read_write() - let lines =<< trim END - VAR b = 0zDEADBEEF - call writefile(b, 'Xblob') - VAR br = readfile('Xblob', 'B') - call assert_equal(b, br) - VAR br2 = readblob('Xblob') - call assert_equal(b, br2) - VAR br3 = readblob('Xblob', 1) - call assert_equal(b[1 :], br3) - VAR br4 = readblob('Xblob', 1, 2) - call assert_equal(b[1 : 2], br4) - VAR br5 = readblob('Xblob', -3) - call assert_equal(b[-3 :], br5) - VAR br6 = readblob('Xblob', -3, 2) - call assert_equal(b[-3 : -2], br6) - - #" reading past end of file, empty result - VAR br1e = readblob('Xblob', 10000) - call assert_equal(0z, br1e) - - #" reading too much, result is truncated - VAR blong = readblob('Xblob', -1000) - call assert_equal(b, blong) - LET blong = readblob('Xblob', -10, 8) - call assert_equal(b, blong) - LET blong = readblob('Xblob', 0, 10) - call assert_equal(b, blong) - - call delete('Xblob') - END - call CheckLegacyAndVim9Success(lines) - - if filereadable('/dev/random') - let b = readblob('/dev/random', 0, 10) - call assert_equal(10, len(b)) - endif - - call assert_fails("call readblob('notexist')", 'E484:') - " TODO: How do we test for the E485 error? - - " This was crashing when calling readfile() with a directory. - call assert_fails("call readfile('.', 'B')", 'E17: "." is a directory') -endfunc - -" filter() item in blob -func Test_blob_filter() - let lines =<< trim END - call assert_equal(v:_null_blob, filter(v:_null_blob, '0')) - call assert_equal(0z, filter(0zDEADBEEF, '0')) - call assert_equal(0zADBEEF, filter(0zDEADBEEF, 'v:val != 0xDE')) - call assert_equal(0zDEADEF, filter(0zDEADBEEF, 'v:val != 0xBE')) - call assert_equal(0zDEADBE, filter(0zDEADBEEF, 'v:val != 0xEF')) - call assert_equal(0zDEADBEEF, filter(0zDEADBEEF, '1')) - call assert_equal(0z01030103, filter(0z010203010203, 'v:val != 0x02')) - call assert_equal(0zADEF, filter(0zDEADBEEF, 'v:key % 2')) - END - call CheckLegacyAndVim9Success(lines) -endfunc - -" map() item in blob -func Test_blob_map() - let lines =<< trim END - call assert_equal(0zDFAEBFF0, map(0zDEADBEEF, 'v:val + 1')) - call assert_equal(0z00010203, map(0zDEADBEEF, 'v:key')) - call assert_equal(0zDEAEC0F2, map(0zDEADBEEF, 'v:key + v:val')) - END - call CheckLegacyAndVim9Success(lines) - - let lines =<< trim END - call map(0z00, '[9]') - END - call CheckLegacyAndVim9Failure(lines, 'E978:') -endfunc - -func Test_blob_index() - let lines =<< trim END - call assert_equal(2, index(0zDEADBEEF, 0xBE)) - call assert_equal(-1, index(0zDEADBEEF, 0)) - call assert_equal(2, index(0z11111111, 0x11, 2)) - call assert_equal(3, 0z11110111->index(0x11, 2)) - call assert_equal(2, index(0z11111111, 0x11, -2)) - call assert_equal(3, index(0z11110111, 0x11, -2)) - call assert_equal(0, index(0z11110111, 0x11, -10)) - call assert_equal(-1, index(v:_null_blob, 1)) - END - call CheckLegacyAndVim9Success(lines) - - let lines =<< trim END - echo index(0z11110111, 0x11, []) - END - call CheckLegacyAndVim9Failure(lines, 'E745:') - - let lines =<< trim END - call index("asdf", 0) - END - call CheckLegacyAndVim9Failure(lines, 'E897:') -endfunc - -func Test_blob_insert() - let lines =<< trim END - VAR b = 0zDEADBEEF - call insert(b, 0x33) - call assert_equal(0z33DEADBEEF, b) - - LET b = 0zDEADBEEF - call insert(b, 0x33, 2) - call assert_equal(0zDEAD33BEEF, b) - END - call CheckLegacyAndVim9Success(lines) - - " only works in legacy script - call assert_equal(0, insert(v:_null_blob, 0x33)) - - let lines =<< trim END - VAR b = 0zDEADBEEF - call insert(b, -1) - END - call CheckLegacyAndVim9Failure(lines, 'E475:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - call insert(b, 257) - END - call CheckLegacyAndVim9Failure(lines, 'E475:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - call insert(b, 0, [9]) - END - call CheckLegacyAndVim9Failure(lines, ['E745:', 'E1013:', 'E745:']) - - let lines =<< trim END - VAR b = 0zDEADBEEF - call insert(b, 0, -20) - END - call CheckLegacyAndVim9Failure(lines, 'E475:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - call insert(b, 0, 20) - END - call CheckLegacyAndVim9Failure(lines, 'E475:') - - let lines =<< trim END - VAR b = 0zDEADBEEF - call insert(b, []) - END - call CheckLegacyAndVim9Failure(lines, ['E745:', 'E1013:', 'E745:']) - - let lines =<< trim END - insert(v:_null_blob, 0x33) - END - call CheckDefExecAndScriptFailure(lines, 'E1131:') - - let lines =<< trim END - let b = 0zDEADBEEF - lockvar b - call insert(b, 3) - unlockvar b - END - call CheckScriptFailure(lines, 'E741:') - - let lines =<< trim END - vim9script - var b = 0zDEADBEEF - lockvar b - insert(b, 3) - END - call CheckScriptFailure(lines, 'E741:') -endfunc - -func Test_blob_reverse() - let lines =<< trim END - call assert_equal(0zEFBEADDE, reverse(0zDEADBEEF)) - call assert_equal(0zBEADDE, reverse(0zDEADBE)) - call assert_equal(0zADDE, reverse(0zDEAD)) - call assert_equal(0zDE, reverse(0zDE)) - call assert_equal(0z, reverse(v:_null_blob)) - END - call CheckLegacyAndVim9Success(lines) -endfunc - -func Test_blob_json_encode() - let lines =<< trim END - #" call assert_equal('[222,173,190,239]', json_encode(0zDEADBEEF)) - call assert_equal('[222, 173, 190, 239]', json_encode(0zDEADBEEF)) - call assert_equal('[]', json_encode(0z)) - END - call CheckLegacyAndVim9Success(lines) -endfunc - -func Test_blob_lock() - let lines =<< trim END - let b = 0z112233 - lockvar b - unlockvar b - let b = 0z44 - END - call CheckScriptSuccess(lines) - - let lines =<< trim END - vim9script - var b = 0z112233 - lockvar b - unlockvar b - b = 0z44 - END - call CheckScriptSuccess(lines) - - let lines =<< trim END - let b = 0z112233 - lockvar b - let b = 0z44 - END - call CheckScriptFailure(lines, 'E741:') - - let lines =<< trim END - vim9script - var b = 0z112233 - lockvar b - b = 0z44 - END - call CheckScriptFailure(lines, 'E741:') -endfunc - -func Test_blob_sort() - if has('float') - call CheckLegacyAndVim9Failure(['call sort([1.0, 0z11], "f")'], 'E975:') - endif - call CheckLegacyAndVim9Failure(['call sort([11, 0z11], "N")'], 'E974:') -endfunc - -" Tests for the blob2list() function -func Test_blob2list() - call assert_fails('let v = blob2list(10)', 'E1238: Blob required for argument 1') - eval 0zFFFF->blob2list()->assert_equal([255, 255]) - let tests = [[0z0102, [1, 2]], - \ [0z00, [0]], - \ [0z, []], - \ [0z00000000, [0, 0, 0, 0]], - \ [0zAABB.CCDD, [170, 187, 204, 221]]] - for t in tests - call assert_equal(t[0]->blob2list(), t[1]) - endfor - exe 'let v = 0z' .. repeat('000102030405060708090A0B0C0D0E0F', 64) - call assert_equal(1024, blob2list(v)->len()) - call assert_equal([4, 8, 15], [v[100], v[1000], v[1023]]) - call assert_equal([], blob2list(v:_null_blob)) -endfunc - -" Tests for the list2blob() function -func Test_list2blob() - call assert_fails('let b = list2blob(0z10)', 'E1211: List required for argument 1') - let tests = [[[1, 2], 0z0102], - \ [[0], 0z00], - \ [[], 0z], - \ [[0, 0, 0, 0], 0z00000000], - \ [[255, 255], 0zFFFF], - \ [[170, 187, 204, 221], 0zAABB.CCDD], - \ ] - for t in tests - call assert_equal(t[1], t[0]->list2blob()) - endfor - call assert_fails('let b = list2blob([1, []])', 'E745:') - call assert_fails('let b = list2blob([-1])', 'E1239:') - call assert_fails('let b = list2blob([256])', 'E1239:') - let b = range(16)->repeat(64)->list2blob() - call assert_equal(1024, b->len()) - call assert_equal([4, 8, 15], [b[100], b[1000], b[1023]]) - call assert_equal(0z, list2blob(v:_null_list)) -endfunc - -" The following used to cause an out-of-bounds memory access -func Test_blob2string() - let v = '0z' .. repeat('01010101.', 444) - let v ..= '01' - exe 'let b = ' .. v - call assert_equal(v, string(b)) -endfunc - -func Test_blob_repeat() - call assert_equal(0z, repeat(0z00, 0)) - call assert_equal(0z00, repeat(0z00, 1)) - call assert_equal(0z0000, repeat(0z00, 2)) - call assert_equal(0z00000000, repeat(0z0000, 2)) - - call assert_equal(0z, repeat(0z12, 0)) - call assert_equal(0z, repeat(0z1234, 0)) - call assert_equal(0z1234, repeat(0z1234, 1)) - call assert_equal(0z12341234, repeat(0z1234, 2)) -endfunc - -" Test for blob allocation failure -func Test_blob_alloc_failure() - CheckFunction test_alloc_fail - " blob variable - call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) - call assert_fails('let v = 0z10', 'E342:') - - " blob slice - let v = 0z1020 - call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) - call assert_fails('let x = v[0:0]', 'E342:') - call assert_equal(0z1020, x) - - " blob remove() - let v = 0z10203040 - call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) - call assert_fails('let x = remove(v, 1, 2)', 'E342:') - call assert_equal(0, x) - - " list2blob() - call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) - call assert_fails('let a = list2blob([1, 2, 4])', 'E342:') - call assert_equal(0, a) - - " mapnew() - call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) - call assert_fails('let x = mapnew(0z1234, {_, v -> 1})', 'E342:') - call assert_equal(0, x) - - " copy() - call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) - call assert_fails('let x = copy(v)', 'E342:') - call assert_equal(0z, x) - - " readblob() - call test_alloc_fail(GetAllocId('blob_alloc'), 0, 0) - call assert_fails('let x = readblob("test_blob.vim")', 'E342:') - call assert_equal(0, x) -endfunc - -" Test for the indexof() function -func Test_indexof() - let b = 0zdeadbeef - call assert_equal(0, indexof(b, {i, v -> v == 0xde})) - call assert_equal(3, indexof(b, {i, v -> v == 0xef})) - call assert_equal(-1, indexof(b, {i, v -> v == 0x1})) - call assert_equal(1, indexof(b, "v:val == 0xad")) - call assert_equal(-1, indexof(b, "v:val == 0xff")) - call assert_equal(-1, indexof(b, {_, v -> "v == 0xad"})) - - call assert_equal(-1, indexof(0z, "v:val == 0x0")) - call assert_equal(-1, indexof(v:_null_blob, "v:val == 0xde")) - call assert_equal(-1, indexof(b, v:_null_string)) - " Nvim doesn't have null functions - " call assert_equal(-1, indexof(b, test_null_function())) - - let b = 0z01020102 - call assert_equal(1, indexof(b, "v:val == 0x02", #{startidx: 0})) - call assert_equal(2, indexof(b, "v:val == 0x01", #{startidx: -2})) - call assert_equal(-1, indexof(b, "v:val == 0x01", #{startidx: 5})) - call assert_equal(0, indexof(b, "v:val == 0x01", #{startidx: -5})) - call assert_equal(0, indexof(b, "v:val == 0x01", v:_null_dict)) - - " failure cases - call assert_fails('let i = indexof(b, "val == 0xde")', 'E121:') - call assert_fails('let i = indexof(b, {})', 'E1256:') -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_blockedit.vim b/src/nvim/testdir/test_blockedit.vim deleted file mode 100644 index 7b56b1554f..0000000000 --- a/src/nvim/testdir/test_blockedit.vim +++ /dev/null @@ -1,132 +0,0 @@ -" Test for block inserting -" - -func Test_blockinsert_indent() - new - filetype plugin indent on - setlocal sw=2 et ft=vim - call setline(1, ['let a=[', ' ''eins'',', ' ''zwei'',', ' ''drei'']']) - call cursor(2, 3) - exe "norm! \2jI\\ \" - call assert_equal(['let a=[', ' \ ''eins'',', ' \ ''zwei'',', ' \ ''drei'']'], - \ getline(1,'$')) - " reset to sane state - filetype off - bwipe! -endfunc - -func Test_blockinsert_autoindent() - new - let lines =<< trim END - var d = { - a: () => 0, - b: () => 0, - c: () => 0, - } - END - call setline(1, lines) - filetype plugin indent on - setlocal sw=2 et ft=vim - setlocal indentkeys+=: - exe "norm! 2Gf)\2jA: asdf\" - let expected =<< trim END - var d = { - a: (): asdf => 0, - b: (): asdf => 0, - c: (): asdf => 0, - } - END - call assert_equal(expected, getline(1, 5)) - - " insert on the next column should do exactly the same - :%dele - call setline(1, lines) - exe "norm! 2Gf)l\2jI: asdf\" - call assert_equal(expected, getline(1, 5)) - - :%dele - call setline(1, lines) - setlocal sw=8 noet - exe "norm! 2Gf)\2jA: asdf\" - let expected =<< trim END - var d = { - a: (): asdf => 0, - b: (): asdf => 0, - c: (): asdf => 0, - } - END - call assert_equal(expected, getline(1, 5)) - - " insert on the next column should do exactly the same - :%dele - call setline(1, lines) - exe "norm! 2Gf)l\2jI: asdf\" - call assert_equal(expected, getline(1, 5)) - - filetype off - bwipe! -endfunc - -func Test_blockinsert_delete() - new - let _bs = &bs - set bs=2 - call setline(1, ['case Arg is ', ' when Name_Async,', ' when Name_Num_Gangs,', 'end if;']) - exe "norm! ggjVj\$o$A\\" - "call feedkeys("Vj\$o$A\\", 'ti') - call assert_equal(["case Arg is ", " when Name_Async", " when Name_Num_Gangs,", "end if;"], - \ getline(1,'$')) - " reset to sane state - let &bs = _bs - bwipe! -endfunc - -func Test_blockappend_eol_cursor() - new - " Test 1 Move 1 char left - call setline(1, ['aaa', 'bbb', 'ccc']) - exe "norm! gg$\2jA\x\" - call assert_equal(['aaxa', 'bbxb', 'ccxc'], getline(1, '$')) - " Test 2 Move 2 chars left - sil %d - call setline(1, ['aaa', 'bbb', 'ccc']) - exe "norm! gg$\2jA\\x\" - call assert_equal(['axaa', 'bxbb', 'cxcc'], getline(1, '$')) - " Test 3 Move 3 chars left (outside of the visual selection) - sil %d - call setline(1, ['aaa', 'bbb', 'ccc']) - exe "norm! ggl$\2jA\\\x\" - call assert_equal(['xaaa', 'bbb', 'ccc'], getline(1, '$')) - bw! -endfunc - -func Test_blockappend_eol_cursor2() - new - " Test 1 Move 1 char left - call setline(1, ['aaaaa', 'bbb', 'ccccc']) - exe "norm! gg\$2jA\x\" - call assert_equal(['aaaaxa', 'bbbx', 'ccccxc'], getline(1, '$')) - " Test 2 Move 2 chars left - sil %d - call setline(1, ['aaaaa', 'bbb', 'ccccc']) - exe "norm! gg\$2jA\\x\" - call assert_equal(['aaaxaa', 'bbbx', 'cccxcc'], getline(1, '$')) - " Test 3 Move 3 chars left (to the beginning of the visual selection) - sil %d - call setline(1, ['aaaaa', 'bbb', 'ccccc']) - exe "norm! gg\$2jA\\\x\" - call assert_equal(['aaxaaa', 'bbxb', 'ccxccc'], getline(1, '$')) - " Test 4 Move 3 chars left (outside of the visual selection) - sil %d - call setline(1, ['aaaaa', 'bbb', 'ccccc']) - exe "norm! ggl\$2jA\\\x\" - call assert_equal(['aaxaaa', 'bbxb', 'ccxccc'], getline(1, '$')) - " Test 5 Move 4 chars left (outside of the visual selection) - sil %d - call setline(1, ['aaaaa', 'bbb', 'ccccc']) - exe "norm! ggl\$2jA\\\\x\" - call assert_equal(['axaaaa', 'bxbb', 'cxcccc'], getline(1, '$')) - bw! -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_breakindent.vim b/src/nvim/testdir/test_breakindent.vim deleted file mode 100644 index 0d1753182e..0000000000 --- a/src/nvim/testdir/test_breakindent.vim +++ /dev/null @@ -1,1096 +0,0 @@ -" Test for breakindent -" -" Note: if you get strange failures when adding new tests, it might be that -" while the test is run, the breakindent caching gets in its way. -" It helps to change the tabstop setting and force a redraw (e.g. see -" Test_breakindent08()) -source check.vim -CheckOption breakindent - -source view_util.vim -source screendump.vim - -func SetUp() - let s:input ="\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP" -endfunc - -func s:screen_lines(lnum, width) abort - return ScreenLines([a:lnum, a:lnum + 2], a:width) -endfunc - -func s:screen_lines2(lnums, lnume, width) abort - return ScreenLines([a:lnums, a:lnume], a:width) -endfunc - -func s:compare_lines(expect, actual) - call assert_equal(join(a:expect, "\n"), join(a:actual, "\n")) -endfunc - -func s:test_windows(...) - call NewWindow(10, 20) - setl ts=4 sw=4 sts=4 breakindent - put =s:input - exe get(a:000, 0, '') -endfunc - -func s:close_windows(...) - call CloseWindow() - exe get(a:000, 0, '') -endfunc - -func Test_breakindent01() - " simple breakindent test - call s:test_windows('setl briopt=min:0') - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ " abcd", - \ " qrst", - \ " GHIJ", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows() -endfunc - -func Test_breakindent01_vartabs() - " like 01 but with vartabs feature - if !has("vartabs") - return - endif - call s:test_windows('setl briopt=min:0 vts=4') - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ " abcd", - \ " qrst", - \ " GHIJ", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set vts&') -endfunc - -func Test_breakindent02() - " simple breakindent test with showbreak set - set sbr=>> - call s:test_windows('setl briopt=min:0 sbr=') - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ " abcd", - \ " >>qr", - \ " >>EF", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set sbr=') -endfunc - -func Test_breakindent02_vartabs() - if !has("vartabs") - return - endif - " simple breakindent test with showbreak set - call s:test_windows('setl briopt=min:0 sbr=>> vts=4') - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ " abcd", - \ " >>qr", - \ " >>EF", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set sbr= vts&') -endfunc - -func Test_breakindent03() - " simple breakindent test with showbreak set and briopt including sbr - call s:test_windows('setl briopt=sbr,min:0 sbr=++') - let lines = s:screen_lines(line('.'),8) - let expect=[ -\ " abcd", -\ "++ qrst", -\ "++ GHIJ", -\ ] - call s:compare_lines(expect, lines) - " clean up - call s:close_windows('set sbr=') -endfunc - -func Test_breakindent03_vartabs() - " simple breakindent test with showbreak set and briopt including sbr - if !has("vartabs") - return - endif - call s:test_windows('setl briopt=sbr,min:0 sbr=++ vts=4') - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ " abcd", - \ "++ qrst", - \ "++ GHIJ", - \ ] - call s:compare_lines(expect, lines) - " clean up - call s:close_windows('set sbr= vts&') -endfunc - -func Test_breakindent04() - " breakindent set with min width 18 - set sbr=<<< - call s:test_windows('setl sbr=NONE briopt=min:18') - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ " abcd", - \ " qrstuv", - \ " IJKLMN", - \ ] - call s:compare_lines(expect, lines) - " clean up - call s:close_windows('set sbr=') - set sbr= -endfunc - -func Test_breakindent04_vartabs() - " breakindent set with min width 18 - if !has("vartabs") - return - endif - call s:test_windows('setl sbr= briopt=min:18 vts=4') - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ " abcd", - \ " qrstuv", - \ " IJKLMN", - \ ] - call s:compare_lines(expect, lines) - " clean up - call s:close_windows('set sbr= vts&') -endfunc - -func Test_breakindent05() - " breakindent set and shift by 2 - call s:test_windows('setl briopt=shift:2,min:0') - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ " abcd", - \ " qr", - \ " EF", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows() -endfunc - -func Test_breakindent05_vartabs() - " breakindent set and shift by 2 - if !has("vartabs") - return - endif - call s:test_windows('setl briopt=shift:2,min:0 vts=4') - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ " abcd", - \ " qr", - \ " EF", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set vts&') -endfunc - -func Test_breakindent06() - " breakindent set and shift by -1 - call s:test_windows('setl briopt=shift:-1,min:0') - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ " abcd", - \ " qrstu", - \ " HIJKL", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows() -endfunc - -func Test_breakindent06_vartabs() - " breakindent set and shift by -1 - if !has("vartabs") - return - endif - call s:test_windows('setl briopt=shift:-1,min:0 vts=4') - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ " abcd", - \ " qrstu", - \ " HIJKL", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set vts&') -endfunc - -func Test_breakindent07() - " breakindent set and shift by 1, Number set sbr=? and briopt:sbr - call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 cpo+=n') - let lines = s:screen_lines(line('.'),10) - let expect = [ - \ " 2 ab", - \ "? m", - \ "? x", - \ ] - call s:compare_lines(expect, lines) - " clean up - call s:close_windows('set sbr= cpo-=n') -endfunc - -func Test_breakindent07_vartabs() - if !has("vartabs") - return - endif - " breakindent set and shift by 1, Number set sbr=? and briopt:sbr - call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 cpo+=n vts=4') - let lines = s:screen_lines(line('.'),10) - let expect = [ - \ " 2 ab", - \ "? m", - \ "? x", - \ ] - call s:compare_lines(expect, lines) - " clean up - call s:close_windows('set sbr= cpo-=n vts&') -endfunc - -func Test_breakindent07a() - " breakindent set and shift by 1, Number set sbr=? and briopt:sbr - call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4') - let lines = s:screen_lines(line('.'),10) - let expect = [ - \ " 2 ab", - \ " ? m", - \ " ? x", - \ ] - call s:compare_lines(expect, lines) - " clean up - call s:close_windows('set sbr=') -endfunc - -func Test_breakindent07a_vartabs() - if !has("vartabs") - return - endif - " breakindent set and shift by 1, Number set sbr=? and briopt:sbr - call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 vts=4') - let lines = s:screen_lines(line('.'),10) - let expect = [ - \ " 2 ab", - \ " ? m", - \ " ? x", - \ ] - call s:compare_lines(expect, lines) - " clean up - call s:close_windows('set sbr= vts&') -endfunc - -func Test_breakindent08() - " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr - call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list cpo+=n ts=4') - " make sure, cache is invalidated! - set ts=8 - redraw! - set ts=4 - redraw! - let lines = s:screen_lines(line('.'),10) - let expect = [ - \ " 2 ^Iabcd", - \ "# opq", - \ "# BCD", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set sbr= cpo-=n') -endfunc - -func Test_breakindent08_vartabs() - if !has("vartabs") - return - endif - " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr - call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list cpo+=n ts=4 vts=4') - " make sure, cache is invalidated! - set ts=8 - redraw! - set ts=4 - redraw! - let lines = s:screen_lines(line('.'),10) - let expect = [ - \ " 2 ^Iabcd", - \ "# opq", - \ "# BCD", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set sbr= cpo-=n vts&') -endfunc - -func Test_breakindent08a() - " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr - call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list') - let lines = s:screen_lines(line('.'),10) - let expect = [ - \ " 2 ^Iabcd", - \ " # opq", - \ " # BCD", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set sbr=') -endfunc - -func Test_breakindent08a_vartabs() - if !has("vartabs") - return - endif - " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr - call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list vts=4') - let lines = s:screen_lines(line('.'),10) - let expect = [ - \ " 2 ^Iabcd", - \ " # opq", - \ " # BCD", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set sbr= vts&') -endfunc - -func Test_breakindent09() - " breakindent set and shift by 1, Number and list set sbr=# - call s:test_windows('setl briopt=shift:1,min:0 nu nuw=4 sbr=# list') - let lines = s:screen_lines(line('.'),10) - let expect = [ - \ " 2 ^Iabcd", - \ " #op", - \ " #AB", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set sbr=') -endfunc - -func Test_breakindent09_vartabs() - if !has("vartabs") - return - endif - " breakindent set and shift by 1, Number and list set sbr=# - call s:test_windows('setl briopt=shift:1,min:0 nu nuw=4 sbr=# list vts=4') - let lines = s:screen_lines(line('.'),10) - let expect = [ - \ " 2 ^Iabcd", - \ " #op", - \ " #AB", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set sbr= vts&') -endfunc - -func Test_breakindent10() - " breakindent set, Number set sbr=~ - call s:test_windows('setl cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0') - " make sure, cache is invalidated! - set ts=8 - redraw! - set ts=4 - redraw! - let lines = s:screen_lines(line('.'),10) - let expect = [ - \ " 2 ab", - \ "~ mn", - \ "~ yz", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set sbr= cpo-=n') -endfunc - -func Test_breakindent10_vartabs() - if !has("vartabs") - return - endif - " breakindent set, Number set sbr=~ - call s:test_windows('setl cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0 vts=4') - " make sure, cache is invalidated! - set ts=8 - redraw! - set ts=4 - redraw! - let lines = s:screen_lines(line('.'),10) - let expect = [ - \ " 2 ab", - \ "~ mn", - \ "~ yz", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set sbr= cpo-=n vts&') -endfunc - -func Test_breakindent11() - " test strdisplaywidth() - call s:test_windows('setl cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4') - let text = getline(2) - let width = strlen(text[1:]) + indent(2) + strlen(&sbr) * 3 " text wraps 3 times - call assert_equal(width, strdisplaywidth(text)) - call s:close_windows('set sbr=') - call assert_equal(4, strdisplaywidth("\t", 4)) -endfunc - -func Test_breakindent11_vartabs() - if !has("vartabs") - return - endif - " test strdisplaywidth() - call s:test_windows('setl cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4 vts=4') - let text = getline(2) - let width = strlen(text[1:]) + 2->indent() + strlen(&sbr) * 3 " text wraps 3 times - call assert_equal(width, text->strdisplaywidth()) - call s:close_windows('set sbr= vts&') -endfunc - -func Test_breakindent12() - " test breakindent with long indent - let s:input="\t\t\t\t\t{" - call s:test_windows('setl breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4 list listchars=tab:>-') - let lines = s:screen_lines(2,16) - let expect = [ - \ " 2 >--->--->--->", - \ " ---{ ", - \ "~ ", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set nuw=4 listchars=') -endfunc - -func Test_breakindent12_vartabs() - if !has("vartabs") - return - endif - " test breakindent with long indent - let s:input = "\t\t\t\t\t{" - call s:test_windows('setl breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4 list listchars=tab:>- vts=4') - let lines = s:screen_lines(2,16) - let expect = [ - \ " 2 >--->--->--->", - \ " ---{ ", - \ "~ ", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set nuw=4 listchars= vts&') -endfunc - -func Test_breakindent13() - let s:input = "" - call s:test_windows('setl breakindent briopt=min:10 ts=8') - vert resize 20 - call setline(1, [" a\tb\tc\td\te", " z y x w v"]) - 1 - norm! fbgj"ayl - 2 - norm! fygj"byl - call assert_equal('d', @a) - call assert_equal('w', @b) - call s:close_windows() -endfunc - -func Test_breakindent13_vartabs() - if !has("vartabs") - return - endif - let s:input = "" - call s:test_windows('setl breakindent briopt=min:10 ts=8 vts=8') - vert resize 20 - call setline(1, [" a\tb\tc\td\te", " z y x w v"]) - 1 - norm! fbgj"ayl - 2 - norm! fygj"byl - call assert_equal('d', @a) - call assert_equal('w', @b) - call s:close_windows('set vts&') -endfunc - -func Test_breakindent14() - let s:input = "" - call s:test_windows('setl breakindent briopt= ts=8') - vert resize 30 - norm! 3a1234567890 - norm! a abcde - exec "norm! 0\tex" - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ "e ", - \ "~ ", - \ "~ ", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows() -endfunc - -func Test_breakindent14_vartabs() - if !has("vartabs") - return - endif - let s:input = "" - call s:test_windows('setl breakindent briopt= ts=8 vts=8') - vert resize 30 - norm! 3a1234567890 - norm! a abcde - exec "norm! 0\tex" - let lines = s:screen_lines(line('.'),8) - let expect = [ - \ "e ", - \ "~ ", - \ "~ ", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set vts&') -endfunc - -func Test_breakindent15() - let s:input = "" - call s:test_windows('setl breakindent briopt= ts=8 sw=8') - vert resize 30 - norm! 4a1234567890 - exe "normal! >>\3f0x" - let lines = s:screen_lines(line('.'),20) - let expect = [ - \ " 1234567890 ", - \ "~ ", - \ "~ ", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows() -endfunc - -func Test_breakindent15_vartabs() - if !has("vartabs") - return - endif - let s:input = "" - call s:test_windows('setl breakindent briopt= ts=8 sw=8 vts=8') - vert resize 30 - norm! 4a1234567890 - exe "normal! >>\3f0x" - let lines = s:screen_lines(line('.'),20) - let expect = [ - \ " 1234567890 ", - \ "~ ", - \ "~ ", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set vts&') -endfunc - -func Test_breakindent16() - " Check that overlong lines are indented correctly. - let s:input = "" - call s:test_windows('setl breakindent briopt=min:0 ts=4') - call setline(1, "\t".repeat("1234567890", 10)) - resize 6 - norm! 1gg$ - redraw! - let lines = s:screen_lines(1,10) - let expect = [ - \ " 789012", - \ " 345678", - \ " 901234", - \ ] - call s:compare_lines(expect, lines) - let lines = s:screen_lines(4,10) - let expect = [ - \ " 567890", - \ " 123456", - \ " 7890 ", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows() -endfunc - -func Test_breakindent16_vartabs() - if !has("vartabs") - return - endif - " Check that overlong lines are indented correctly. - let s:input = "" - call s:test_windows('setl breakindent briopt=min:0 ts=4 vts=4') - call setline(1, "\t".repeat("1234567890", 10)) - resize 6 - norm! 1gg$ - redraw! - let lines = s:screen_lines(1,10) - let expect = [ - \ " 789012", - \ " 345678", - \ " 901234", - \ ] - call s:compare_lines(expect, lines) - let lines = s:screen_lines(4,10) - let expect = [ - \ " 567890", - \ " 123456", - \ " 7890 ", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set vts&') -endfunc - -func Test_breakindent17_vartabs() - if !has("vartabs") - return - endif - let s:input = "" - call s:test_windows('setl breakindent list listchars=tab:<-> showbreak=+++') - call setline(1, "\t" . repeat('a', 63)) - vert resize 30 - norm! 1gg$ - redraw! - let lines = s:screen_lines(1, 30) - let expect = [ - \ "<-->aaaaaaaaaaaaaaaaaaaaaaaaaa", - \ " +++aaaaaaaaaaaaaaaaaaaaaaa", - \ " +++aaaaaaaaaaaaaa ", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set breakindent& list& listchars& showbreak&') -endfunc - -func Test_breakindent18_vartabs() - if !has("vartabs") - return - endif - let s:input = "" - call s:test_windows('setl breakindent list listchars=tab:<->') - call setline(1, "\t" . repeat('a', 63)) - vert resize 30 - norm! 1gg$ - redraw! - let lines = s:screen_lines(1, 30) - let expect = [ - \ "<-->aaaaaaaaaaaaaaaaaaaaaaaaaa", - \ " aaaaaaaaaaaaaaaaaaaaaaaaaa", - \ " aaaaaaaaaaa ", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set breakindent& list& listchars&') -endfunc - -func Test_breakindent19_sbr_nextpage() - let s:input = "" - call s:test_windows('setl breakindent briopt=shift:2,sbr,min:18 sbr=>') - call setline(1, repeat('a', 200)) - norm! 1gg - redraw! - let lines = s:screen_lines(1, 20) - let expect = [ - \ "aaaaaaaaaaaaaaaaaaaa", - \ "> aaaaaaaaaaaaaaaaaa", - \ "> aaaaaaaaaaaaaaaaaa", - \ ] - call s:compare_lines(expect, lines) - " Scroll down one screen line - setl scrolloff=5 - norm! 5gj - let lines = s:screen_lines(1, 20) - let expect = [ - \ "aaaaaaaaaaaaaaaaaaaa", - \ "> aaaaaaaaaaaaaaaaaa", - \ "> aaaaaaaaaaaaaaaaaa", - \ ] - call s:compare_lines(expect, lines) - redraw! - " moving the cursor doesn't change the text offset - norm! l - redraw! - let lines = s:screen_lines(1, 20) - call s:compare_lines(expect, lines) - - setl breakindent briopt=min:18 sbr=> - norm! 5gj - let lines = s:screen_lines(1, 20) - let expect = [ - \ ">aaaaaaaaaaaaaaaaaaa", - \ ">aaaaaaaaaaaaaaaaaaa", - \ ">aaaaaaaaaaaaaaaaaaa", - \ ] - call s:compare_lines(expect, lines) - call s:close_windows('set breakindent& briopt& sbr&') -endfunc - -func Test_breakindent20_cpo_n_nextpage() - let s:input = "" - call s:test_windows('setl breakindent briopt=min:14 cpo+=n number') - call setline(1, repeat('a', 200)) - norm! 1gg - redraw! - let lines = s:screen_lines(1, 20) - let expect = [ - \ " 1 aaaaaaaaaaaaaaaa", - \ " aaaaaaaaaaaaaaaa", - \ " aaaaaaaaaaaaaaaa", - \ ] - call s:compare_lines(expect, lines) - " Scroll down one screen line - setl scrolloff=5 - norm! 5gj - redraw! - let lines = s:screen_lines(1, 20) - let expect = [ - \ "--1 aaaaaaaaaaaaaaaa", - \ " aaaaaaaaaaaaaaaa", - \ " aaaaaaaaaaaaaaaa", - \ ] - call s:compare_lines(expect, lines) - - setl briopt+=shift:2 - norm! 1gg - let lines = s:screen_lines(1, 20) - let expect = [ - \ " 1 aaaaaaaaaaaaaaaa", - \ " aaaaaaaaaaaaaa", - \ " aaaaaaaaaaaaaa", - \ ] - call s:compare_lines(expect, lines) - " Scroll down one screen line - norm! 5gj - let lines = s:screen_lines(1, 20) - let expect = [ - \ "--1 aaaaaaaaaaaaaa", - \ " aaaaaaaaaaaaaa", - \ " aaaaaaaaaaaaaa", - \ ] - call s:compare_lines(expect, lines) - - call s:close_windows('set breakindent& briopt& cpo& number&') -endfunc - -func Test_breakindent20_list() - call s:test_windows('setl breakindent breakindentopt= linebreak') - " default: - call setline(1, [' 1. Congress shall make no law', - \ ' 2.) Congress shall make no law', - \ ' 3.] Congress shall make no law']) - norm! 1gg - redraw! - let lines = s:screen_lines2(1, 6, 20) - let expect = [ - \ " 1. Congress ", - \ "shall make no law ", - \ " 2.) Congress ", - \ "shall make no law ", - \ " 3.] Congress ", - \ "shall make no law ", - \ ] - call s:compare_lines(expect, lines) - " set minimum indent - setl briopt=min:5 - redraw! - let lines = s:screen_lines2(1, 6, 20) - let expect = [ - \ " 1. Congress ", - \ " shall make no law ", - \ " 2.) Congress ", - \ " shall make no law ", - \ " 3.] Congress ", - \ " shall make no law ", - \ ] - call s:compare_lines(expect, lines) - " set additional handing indent - setl briopt+=list:4 - redraw! - let expect = [ - \ " 1. Congress ", - \ " shall make no ", - \ " law ", - \ " 2.) Congress ", - \ " shall make no ", - \ " law ", - \ " 3.] Congress ", - \ " shall make no ", - \ " law ", - \ ] - let lines = s:screen_lines2(1, 9, 20) - call s:compare_lines(expect, lines) - - " reset linebreak option - " Note: it indents by one additional - " space, because of the leading space. - setl linebreak&vim list listchars=eol:$,space:_ - redraw! - let expect = [ - \ "__1.__Congress_shall", - \ " _make_no_law$ ", - \ "__2.)_Congress_shall", - \ " _make_no_law$ ", - \ "__3.]_Congress_shall", - \ " _make_no_law$ ", - \ ] - let lines = s:screen_lines2(1, 6, 20) - call s:compare_lines(expect, lines) - - " check formatlistpat indent - setl briopt=min:5,list:-1 - setl linebreak list&vim listchars&vim - let &l:flp = '^\s*\d\+\.\?[\]:)}\t ]\s*' - redraw! - let expect = [ - \ " 1. Congress ", - \ " shall make no ", - \ " law ", - \ " 2.) Congress ", - \ " shall make no ", - \ " law ", - \ " 3.] Congress ", - \ " shall make no ", - \ " law ", - \ ] - let lines = s:screen_lines2(1, 9, 20) - call s:compare_lines(expect, lines) - " check formatlistpat indent with different list levels - let &l:flp = '^\s*\*\+\s\+' - %delete _ - call setline(1, ['* Congress shall make no law', - \ '*** Congress shall make no law', - \ '**** Congress shall make no law']) - norm! 1gg - redraw! - let expect = [ - \ "* Congress shall ", - \ " make no law ", - \ "*** Congress shall ", - \ " make no law ", - \ "**** Congress shall ", - \ " make no law ", - \ ] - let lines = s:screen_lines2(1, 6, 20) - call s:compare_lines(expect, lines) - - " check formatlistpat indent with different list level - " showbreak and sbr - setl briopt=min:5,sbr,list:-1 - setl showbreak=> - redraw! - let expect = [ - \ "* Congress shall ", - \ "> make no law ", - \ "*** Congress shall ", - \ "> make no law ", - \ "**** Congress shall ", - \ "> make no law ", - \ ] - let lines = s:screen_lines2(1, 6, 20) - call s:compare_lines(expect, lines) - - " check formatlistpat indent with different list level - " showbreak sbr and shift - setl briopt=min:5,sbr,list:-1,shift:2 - setl showbreak=> - redraw! - let expect = [ - \ "* Congress shall ", - \ "> make no law ", - \ "*** Congress shall ", - \ "> make no law ", - \ "**** Congress shall ", - \ "> make no law ", - \ ] - let lines = s:screen_lines2(1, 6, 20) - call s:compare_lines(expect, lines) - - " check breakindent works if breakindentopt=list:-1 - " for a non list content - %delete _ - call setline(1, [' Congress shall make no law', - \ ' Congress shall make no law', - \ ' Congress shall make no law']) - norm! 1gg - setl briopt=min:5,list:-1 - setl showbreak= - redraw! - let expect = [ - \ " Congress shall ", - \ " make no law ", - \ " Congress shall ", - \ " make no law ", - \ " Congress shall ", - \ " make no law ", - \ ] - let lines = s:screen_lines2(1, 6, 20) - call s:compare_lines(expect, lines) - - call s:close_windows('set breakindent& briopt& linebreak& list& listchars& showbreak&') -endfunc - -" The following used to crash Vim. This is fixed by 8.2.3391. -" This is a regression introduced by 8.2.2903. -func Test_window_resize_with_linebreak() - new - 53vnew - setl linebreak - setl showbreak=>> - setl breakindent - setl breakindentopt=shift:4 - call setline(1, "\naaaaaaaaa\n\na\naaaaa\n¯aaaaaaaaaa\naaaaaaaaaaaa\naaa\n\"a:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - aaaaaaaa\"\naaaaaaaa\n\"a") - redraw! - call assert_equal([" >>aa^@\"a: "], ScreenLines(2, 14)) - vertical resize 52 - redraw! - call assert_equal([" >>aaa^@\"a:"], ScreenLines(2, 14)) - set linebreak& showbreak& breakindent& breakindentopt& - %bw! -endfunc - -func Test_cursor_position_with_showbreak() - CheckScreendump - - let lines =<< trim END - vim9script - &signcolumn = 'yes' - &showbreak = '+ ' - var leftcol: number = win_getid()->getwininfo()->get(0, {})->get('textoff') - repeat('x', &columns - leftcol - 1)->setline(1) - 'second line'->setline(2) - END - call writefile(lines, 'XscriptShowbreak') - let buf = RunVimInTerminal('-S XscriptShowbreak', #{rows: 6}) - - call term_sendkeys(buf, "AX") - call VerifyScreenDump(buf, 'Test_cursor_position_with_showbreak', {}) - - call StopVimInTerminal(buf) - call delete('XscriptShowbreak') -endfunc - -func Test_no_spurious_match() - let s:input = printf('- y %s y %s', repeat('x', 50), repeat('x', 50)) - call s:test_windows('setl breakindent breakindentopt=list:-1 formatlistpat=^- hls') - let @/ = '\%>3v[y]' - redraw! - call searchcount().total->assert_equal(1) - - " cleanup - set hls&vim - bwipeout! -endfunc - -func Test_no_extra_indent() - call s:test_windows('setl breakindent breakindentopt=list:-1,min:10') - %d - let &l:formatlistpat='^\s*\d\+\.\s\+' - let text = 'word ' - let len = text->strcharlen() - let line1 = text->repeat((winwidth(0) / len) * 2) - let line2 = repeat(' ', 2) .. '1. ' .. line1 - call setline(1, [line2]) - redraw! - " 1) matches formatlist pattern, so indent - let expect = [ - \ " 1. word word word ", - \ " word word word ", - \ " word word ", - \ "~ ", - \ ] - let lines = s:screen_lines2(1, 4, 20) - call s:compare_lines(expect, lines) - " 2) change formatlist pattern - " -> indent adjusted - let &l:formatlistpat='^\s*\d\+\.' - let expect = [ - \ " 1. word word word ", - \ " word word word ", - \ " word word ", - \ "~ ", - \ ] - let lines = s:screen_lines2(1, 4, 20) - " 3) no local formatlist pattern, - " so use global one -> indent - let g_flp = &g:flp - let &g:formatlistpat='^\s*\d\+\.\s\+' - let &l:formatlistpat='' - let expect = [ - \ " 1. word word word ", - \ " word word word ", - \ " word word ", - \ "~ ", - \ ] - let lines = s:screen_lines2(1, 4, 20) - call s:compare_lines(expect, lines) - let &g:flp = g_flp - let &l:formatlistpat='^\s*\d\+\.' - " 4) add something in front, no additional indent - norm! gg0 - exe ":norm! 5iword \" - redraw! - let expect = [ - \ "word word word word ", - \ "word 1. word word ", - \ "word word word word ", - \ "word word ", - \ "~ ", - \ ] - let lines = s:screen_lines2(1, 5, 20) - call s:compare_lines(expect, lines) - bwipeout! -endfunc - -func Test_breakindent_column() - call s:test_windows('setl breakindent breakindentopt=column:10') - redraw! - " 1) default: does not indent, too wide :( - let expect = [ - \ " ", - \ " abcdefghijklmnop", - \ "qrstuvwxyzABCDEFGHIJ", - \ "KLMNOP " - \ ] - let lines = s:screen_lines2(1, 4, 20) - call s:compare_lines(expect, lines) - " 2) lower min value, so that breakindent works - setl breakindentopt+=min:5 - redraw! - let expect = [ - \ " ", - \ " abcdefghijklmnop", - \ " qrstuvwxyz", - \ " ABCDEFGHIJ", - \ " KLMNOP " - \ ] - let lines = s:screen_lines2(1, 5, 20) - " 3) set shift option -> no influence - setl breakindentopt+=shift:5 - redraw! - let expect = [ - \ " ", - \ " abcdefghijklmnop", - \ " qrstuvwxyz", - \ " ABCDEFGHIJ", - \ " KLMNOP " - \ ] - let lines = s:screen_lines2(1, 5, 20) - call s:compare_lines(expect, lines) - " 4) add showbreak value - setl showbreak=++ - redraw! - let expect = [ - \ " ", - \ " abcdefghijklmnop", - \ " ++qrstuvwx", - \ " ++yzABCDEF", - \ " ++GHIJKLMN", - \ " ++OP " - \ ] - let lines = s:screen_lines2(1, 6, 20) - call s:compare_lines(expect, lines) - bwipeout! -endfunc - -func Test_linebreak_list() - " This was setting wlv.c_extra to NUL while wlv.p_extra is NULL - filetype plugin on - syntax enable - edit! $VIMRUNTIME/doc/index.txt - /v_P - - setlocal list - setlocal listchars=tab:>- - setlocal linebreak - setlocal nowrap - setlocal filetype=help - redraw! - - bwipe! -endfunc - - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_buffer.vim b/src/nvim/testdir/test_buffer.vim deleted file mode 100644 index 98eba83f73..0000000000 --- a/src/nvim/testdir/test_buffer.vim +++ /dev/null @@ -1,525 +0,0 @@ -" Tests for Vim buffer - -source check.vim - -" Test for the :bunload command with an offset -func Test_bunload_with_offset() - %bwipe! - call writefile(['B1'], 'b1') - call writefile(['B2'], 'b2') - call writefile(['B3'], 'b3') - call writefile(['B4'], 'b4') - - " Load four buffers. Unload the second and third buffers and then - " execute .+3bunload to unload the last buffer. - edit b1 - new b2 - new b3 - new b4 - - bunload b2 - bunload b3 - exe bufwinnr('b1') . 'wincmd w' - .+3bunload - call assert_equal(0, getbufinfo('b4')[0].loaded) - call assert_equal('b1', - \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t')) - - " Load four buffers. Unload the third and fourth buffers. Execute .+3bunload - " and check whether the second buffer is unloaded. - ball - bunload b3 - bunload b4 - exe bufwinnr('b1') . 'wincmd w' - .+3bunload - call assert_equal(0, getbufinfo('b2')[0].loaded) - call assert_equal('b1', - \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t')) - - " Load four buffers. Unload the second and third buffers and from the last - " buffer execute .-3bunload to unload the first buffer. - ball - bunload b2 - bunload b3 - exe bufwinnr('b4') . 'wincmd w' - .-3bunload - call assert_equal(0, getbufinfo('b1')[0].loaded) - call assert_equal('b4', - \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t')) - - " Load four buffers. Unload the first and second buffers. Execute .-3bunload - " from the last buffer and check whether the third buffer is unloaded. - ball - bunload b1 - bunload b2 - exe bufwinnr('b4') . 'wincmd w' - .-3bunload - call assert_equal(0, getbufinfo('b3')[0].loaded) - call assert_equal('b4', - \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t')) - - %bwipe! - call delete('b1') - call delete('b2') - call delete('b3') - call delete('b4') - - call assert_fails('1,4bunload', 'E16:') - call assert_fails(',100bunload', 'E16:') - - call assert_fails('$bunload', 'E90:') -endfunc - -" Test for :buffer, :bnext, :bprevious, :brewind, :blast and :bmodified -" commands -func Test_buflist_browse() - %bwipe! - call assert_fails('buffer 1000', 'E86:') - - call writefile(['foo1', 'foo2', 'foo3', 'foo4'], 'Xfile1') - call writefile(['bar1', 'bar2', 'bar3', 'bar4'], 'Xfile2') - call writefile(['baz1', 'baz2', 'baz3', 'baz4'], 'Xfile3') - edit Xfile1 - let b1 = bufnr() - edit Xfile2 - let b2 = bufnr() - edit +/baz4 Xfile3 - let b3 = bufnr() - - call assert_fails('buffer ' .. b1 .. ' abc', 'E488:') - call assert_equal(b3, bufnr()) - call assert_equal(4, line('.')) - exe 'buffer +/bar2 ' .. b2 - call assert_equal(b2, bufnr()) - call assert_equal(2, line('.')) - exe 'buffer +/bar1' - call assert_equal(b2, bufnr()) - call assert_equal(1, line('.')) - - brewind + - call assert_equal(b1, bufnr()) - call assert_equal(4, line('.')) - - blast +/baz2 - call assert_equal(b3, bufnr()) - call assert_equal(2, line('.')) - - bprevious +/bar4 - call assert_equal(b2, bufnr()) - call assert_equal(4, line('.')) - - bnext +/baz3 - call assert_equal(b3, bufnr()) - call assert_equal(3, line('.')) - - call assert_fails('bmodified', 'E84:') - call setbufvar(b2, '&modified', 1) - exe 'bmodified +/bar3' - call assert_equal(b2, bufnr()) - call assert_equal(3, line('.')) - - " With no listed buffers in the list, :bnext and :bprev should fail - %bwipe! - set nobuflisted - call assert_fails('bnext', 'E85:') - call assert_fails('bprev', 'E85:') - set buflisted - - call assert_fails('sandbox bnext', 'E48:') - - call delete('Xfile1') - call delete('Xfile2') - call delete('Xfile3') - %bwipe! -endfunc - -" Test for :bdelete -func Test_bdelete_cmd() - %bwipe! - call assert_fails('bdelete 5', 'E516:') - call assert_fails('1,1bdelete 1 2', 'E488:') - call assert_fails('bdelete \)', 'E55:') - - " Deleting a unlisted and unloaded buffer - edit Xfile1 - let bnr = bufnr() - set nobuflisted - enew - call assert_fails('bdelete ' .. bnr, 'E516:') - - " Deleting more than one buffer - new Xbuf1 - new Xbuf2 - exe 'bdel ' .. bufnr('Xbuf2') .. ' ' .. bufnr('Xbuf1') - call assert_equal(1, winnr('$')) - call assert_equal(0, getbufinfo('Xbuf1')[0].loaded) - call assert_equal(0, getbufinfo('Xbuf2')[0].loaded) - - " Deleting more than one buffer and an invalid buffer - new Xbuf1 - new Xbuf2 - let cmd = "exe 'bdel ' .. bufnr('Xbuf2') .. ' xxx ' .. bufnr('Xbuf1')" - call assert_fails(cmd, 'E94:') - call assert_equal(2, winnr('$')) - call assert_equal(1, getbufinfo('Xbuf1')[0].loaded) - call assert_equal(0, getbufinfo('Xbuf2')[0].loaded) - - %bwipe! -endfunc - -func Test_buffer_error() - new foo1 - new foo2 - - call assert_fails('buffer foo', 'E93:') - call assert_fails('buffer bar', 'E94:') - call assert_fails('buffer 0', 'E939:') - - %bwipe -endfunc - -" Test for the status messages displayed when unloading, deleting or wiping -" out buffers -func Test_buffer_statusmsg() - CheckEnglish - set report=1 - new Xbuf1 - new Xbuf2 - let bnr = bufnr() - exe "normal 2\" - call assert_match('buf ' .. bnr .. ':', v:statusmsg) - bunload Xbuf1 Xbuf2 - call assert_equal('2 buffers unloaded', v:statusmsg) - bdel Xbuf1 Xbuf2 - call assert_equal('2 buffers deleted', v:statusmsg) - bwipe Xbuf1 Xbuf2 - call assert_equal('2 buffers wiped out', v:statusmsg) - set report& -endfunc - -" Test for quitting the 'swapfile exists' dialog with the split buffer -" command. -func Test_buffer_sbuf_cleanup() - call writefile([], 'Xfile') - " first open the file in a buffer - new Xfile - let bnr = bufnr() - close - " create the swap file - call writefile([], '.Xfile.swp') - " Remove the catch-all that runtest.vim adds - au! SwapExists - augroup BufTest - au! - autocmd SwapExists Xfile let v:swapchoice='q' - augroup END - exe 'sbuf ' . bnr - call assert_equal(1, winnr('$')) - call assert_equal(0, getbufinfo('Xfile')[0].loaded) - - " test for :sball - sball - call assert_equal(1, winnr('$')) - call assert_equal(0, getbufinfo('Xfile')[0].loaded) - - %bw! - set shortmess+=F - let v:statusmsg = '' - edit Xfile - call assert_equal('', v:statusmsg) - call assert_equal(1, winnr('$')) - call assert_equal(0, getbufinfo('Xfile')[0].loaded) - set shortmess& - - call delete('Xfile') - call delete('.Xfile.swp') - augroup BufTest - au! - augroup END - augroup! BufTest -endfunc - -" Test for deleting a modified buffer with :confirm -func Test_bdel_with_confirm() - " requires a UI to be active - throw 'Skipped: use test/functional/legacy/buffer_spec.lua' - CheckUnix - CheckNotGui - CheckFeature dialog_con - new - call setline(1, 'test') - call assert_fails('bdel', 'E89:') - call feedkeys('c', 'L') - confirm bdel - call assert_equal(2, winnr('$')) - call assert_equal(1, &modified) - call feedkeys('n', 'L') - confirm bdel - call assert_equal(1, winnr('$')) -endfunc - -" Test for editing another buffer from a modified buffer with :confirm -func Test_goto_buf_with_confirm() - " requires a UI to be active - throw 'Skipped: use test/functional/legacy/buffer_spec.lua' - CheckUnix - CheckNotGui - CheckFeature dialog_con - new Xfile - enew - call setline(1, 'test') - call assert_fails('b Xfile', 'E37:') - call feedkeys('c', 'L') - call assert_fails('confirm b Xfile', 'E37:') - call assert_equal(1, &modified) - call assert_equal('', @%) - call feedkeys('y', 'L') - call assert_fails('confirm b Xfile', ['', 'E37:']) - call assert_equal(1, &modified) - call assert_equal('', @%) - call feedkeys('n', 'L') - confirm b Xfile - call assert_equal('Xfile', @%) - close! -endfunc - -" Test for splitting buffer with 'switchbuf' -func Test_buffer_switchbuf() - new Xfile - wincmd w - set switchbuf=useopen - sbuf Xfile - call assert_equal(1, winnr()) - call assert_equal(2, winnr('$')) - set switchbuf=usetab - tabnew - sbuf Xfile - call assert_equal(1, tabpagenr()) - call assert_equal(2, tabpagenr('$')) - set switchbuf& - %bw -endfunc - -" Test for BufAdd autocommand wiping out the buffer -func Test_bufadd_autocmd_bwipe() - %bw! - augroup BufAdd_Wipe - au! - autocmd BufAdd Xfile %bw! - augroup END - edit Xfile - call assert_equal('', @%) - call assert_equal(0, bufexists('Xfile')) - augroup BufAdd_Wipe - au! - augroup END - augroup! BufAdd_Wipe -endfunc - -" Test for trying to load a buffer with text locked -" e in the command line is used to lock the text -func Test_load_buf_with_text_locked() - new Xfile1 - edit Xfile2 - let cmd = ":\eexecute(\"normal \\")\\" - call assert_fails("call feedkeys(cmd, 'xt')", 'E565:') - %bw! -endfunc - -" Test for using CTRL-^ to edit the alternative file keeping the cursor -" position with 'nostartofline'. Also test using the 'buf' command. -func Test_buffer_edit_altfile() - call writefile(repeat(['one two'], 50), 'Xfile1') - call writefile(repeat(['five six'], 50), 'Xfile2') - set nosol - edit Xfile1 - call cursor(25, 5) - edit Xfile2 - call cursor(30, 4) - exe "normal \" - call assert_equal([0, 25, 5, 0], getpos('.')) - exe "normal \" - call assert_equal([0, 30, 4, 0], getpos('.')) - buf Xfile1 - call assert_equal([0, 25, 5, 0], getpos('.')) - buf Xfile2 - call assert_equal([0, 30, 4, 0], getpos('.')) - set sol& - call delete('Xfile1') - call delete('Xfile2') -endfunc - -" Test for running the :sball command with a maximum window count and a -" modified buffer -func Test_sball_with_count() - %bw! - edit Xfile1 - call setline(1, ['abc']) - new Xfile2 - new Xfile3 - new Xfile4 - 2sball - call assert_equal(bufnr('Xfile4'), winbufnr(1)) - call assert_equal(bufnr('Xfile1'), winbufnr(2)) - call assert_equal(0, getbufinfo('Xfile2')[0].loaded) - call assert_equal(0, getbufinfo('Xfile3')[0].loaded) - %bw! -endfunc - -func Test_badd_options() - new SomeNewBuffer - setlocal numberwidth=3 - wincmd p - badd +1 SomeNewBuffer - new SomeNewBuffer - call assert_equal(3, &numberwidth) - close - close - bwipe! SomeNewBuffer -endfunc - -func Test_balt() - new SomeNewBuffer - balt +3 OtherBuffer - e # - call assert_equal('OtherBuffer', bufname()) -endfunc - -" Test for buffer match URL(scheme) check -" scheme is alpha and inner hyphen only. -func Test_buffer_scheme() - CheckMSWindows - - set noshellslash - %bwipe! - let bufnames = [ - \ #{id: 'ssb0', name: 'test://xyz/foo/ssb0' , match: 1}, - \ #{id: 'ssb1', name: 'test+abc://xyz/foo/ssb1', match: 0}, - \ #{id: 'ssb2', name: 'test_abc://xyz/foo/ssb2', match: 0}, - \ #{id: 'ssb3', name: 'test-abc://xyz/foo/ssb3', match: 1}, - \ #{id: 'ssb4', name: '-test://xyz/foo/ssb4' , match: 0}, - \ #{id: 'ssb5', name: 'test-://xyz/foo/ssb5' , match: 0}, - \] - for buf in bufnames - new `=buf.name` - if buf.match - call assert_equal(buf.name, getbufinfo(buf.id)[0].name) - else - " slashes will have become backslashes - call assert_notequal(buf.name, getbufinfo(buf.id)[0].name) - endif - bwipe - endfor - - set shellslash& -endfunc - -" this was using a NULL pointer after failing to use the pattern -func Test_buf_pattern_invalid() - vsplit 0000000 - silent! buf [0--]\&\zs*\zs*e - bwipe! - - vsplit 00000000000000000000000000 - silent! buf [0--]\&\zs*\zs*e - bwipe! - - " similar case with different code path - split 0 - edit ÿ - silent! buf [0--]\&\zs*\zs*0 - bwipe! -endfunc - -" Test for the 'maxmem' and 'maxmemtot' options -func Test_buffer_maxmem() - " use 1KB per buffer and 2KB for all the buffers - " set maxmem=1 maxmemtot=2 - new - let v:errmsg = '' - " try opening some files - edit test_arglist.vim - call assert_equal('test_arglist.vim', bufname()) - edit test_eval_stuff.vim - call assert_equal('test_eval_stuff.vim', bufname()) - b test_arglist.vim - call assert_equal('test_arglist.vim', bufname()) - b test_eval_stuff.vim - call assert_equal('test_eval_stuff.vim', bufname()) - close - call assert_equal('', v:errmsg) - " set maxmem& maxmemtot& -endfunc - -" Test for buffer allocation failure -func Test_buflist_alloc_failure() - CheckFunction test_alloc_fail - %bw! - - edit Xfile1 - call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) - call assert_fails('edit Xfile2', 'E342:') - - " test for bufadd() - call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) - call assert_fails('call bufadd("Xbuffer")', 'E342:') - - " test for setting the arglist - edit Xfile2 - call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) - call assert_fails('next Xfile3', 'E342:') - - " test for setting the alternate buffer name when writing a file - call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) - call assert_fails('write Xother', 'E342:') - call delete('Xother') - - " test for creating a buffer using bufnr() - call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) - call assert_fails("call bufnr('Xnewbuf', v:true)", 'E342:') - - " test for renaming buffer using :file - call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) - call assert_fails('file Xnewfile', 'E342:') - - " test for creating a buffer for a popup window - call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) - call assert_fails('call popup_create("mypop", {})', 'E342:') - - if has('terminal') - " test for creating a buffer for a terminal window - call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) - call assert_fails('call term_start(&shell)', 'E342:') - %bw! - endif - - " test for loading a new buffer after wiping out all the buffers - edit Xfile4 - call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) - call assert_fails('%bw!', 'E342:') - - " test for :checktime loading the buffer - call writefile(['one'], 'Xfile5') - if has('unix') - edit Xfile5 - " sleep for some time to make sure the timestamp is different - sleep 200m - call writefile(['two'], 'Xfile5') - set autoread - call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) - call assert_fails('checktime', 'E342:') - set autoread& - bw! - endif - - " test for :vimgrep loading a dummy buffer - call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) - call assert_fails('vimgrep two Xfile5', 'E342:') - call delete('Xfile5') - - " test for quickfix command loading a buffer - call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) - call assert_fails('cexpr "Xfile6:10:Line10"', 'E342:') -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_bufline.vim b/src/nvim/testdir/test_bufline.vim deleted file mode 100644 index 0468025f55..0000000000 --- a/src/nvim/testdir/test_bufline.vim +++ /dev/null @@ -1,296 +0,0 @@ -" Tests for setbufline(), getbufline(), appendbufline(), deletebufline() - -source shared.vim -source screendump.vim -source check.vim - -func Test_setbufline_getbufline() - " similar to Test_set_get_bufline() - new - let b = bufnr('%') - hide - call assert_equal(0, setbufline(b, 1, ['foo', 'bar'])) - call assert_equal(['foo'], getbufline(b, 1)) - call assert_equal('foo', getbufoneline(b, 1)) - call assert_equal(['bar'], getbufline(b, '$')) - call assert_equal('bar', getbufoneline(b, '$')) - call assert_equal(['foo', 'bar'], getbufline(b, 1, 2)) - exe "bd!" b - call assert_equal([], getbufline(b, 1, 2)) - - split Xtest - call setline(1, ['a', 'b', 'c']) - let b = bufnr('%') - wincmd w - - call assert_equal(1, setbufline(b, 5, 'x')) - call assert_equal(1, setbufline(b, 5, ['x'])) - call assert_equal(1, setbufline(b, 5, [])) - call assert_equal(1, setbufline(b, 5, v:_null_list)) - - call assert_equal(1, 'x'->setbufline(bufnr('$') + 1, 1)) - call assert_equal(1, ['x']->setbufline(bufnr('$') + 1, 1)) - call assert_equal(1, []->setbufline(bufnr('$') + 1, 1)) - call assert_equal(1, v:_null_list->setbufline(bufnr('$') + 1, 1)) - - call assert_equal(['a', 'b', 'c'], getbufline(b, 1, '$')) - - call assert_equal(0, setbufline(b, 4, ['d', 'e'])) - call assert_equal(['c'], b->getbufline(3)) - call assert_equal('c', b->getbufoneline(3)) - call assert_equal(['d'], getbufline(b, 4)) - call assert_equal('d', getbufoneline(b, 4)) - call assert_equal(['e'], getbufline(b, 5)) - call assert_equal('e', getbufoneline(b, 5)) - call assert_equal([], getbufline(b, 6)) - call assert_equal([], getbufline(b, 2, 1)) - - if has('job') - call setbufline(b, 2, [function('eval'), #{key: 123}, test_null_job()]) - call assert_equal(["function('eval')", - \ "{'key': 123}", - \ "no process"], - \ getbufline(b, 2, 4)) - endif - exe "bwipe! " . b -endfunc - -func Test_setbufline_getbufline_fold() - split Xtest - setlocal foldmethod=expr foldexpr=0 - let b = bufnr('%') - new - call assert_equal(0, setbufline(b, 1, ['foo', 'bar'])) - call assert_equal(['foo'], getbufline(b, 1)) - call assert_equal(['bar'], getbufline(b, 2)) - call assert_equal(['foo', 'bar'], getbufline(b, 1, 2)) - exe "bwipe!" b - bwipe! -endfunc - -func Test_setbufline_getbufline_fold_tab() - split Xtest - setlocal foldmethod=expr foldexpr=0 - let b = bufnr('%') - tab new - call assert_equal(0, setbufline(b, 1, ['foo', 'bar'])) - call assert_equal(['foo'], getbufline(b, 1)) - call assert_equal(['bar'], getbufline(b, 2)) - call assert_equal(['foo', 'bar'], getbufline(b, 1, 2)) - exe "bwipe!" b - bwipe! -endfunc - -func Test_setline_startup() - let cmd = GetVimCommand('Xscript') - if cmd == '' - return - endif - call writefile(['call setline(1, "Hello")', 'silent w Xtest', 'q!'], 'Xscript') - call system(cmd) - call assert_equal(['Hello'], readfile('Xtest')) - - call delete('Xscript') - call delete('Xtest') -endfunc - -func Test_appendbufline() - new - let b = bufnr('%') - hide - - new - call setline(1, ['line1', 'line2', 'line3']) - normal! 2gggg - call assert_equal(2, line("''")) - - call assert_equal(0, appendbufline(b, 0, ['foo', 'bar'])) - call assert_equal(['foo'], getbufline(b, 1)) - call assert_equal(['bar'], getbufline(b, 2)) - call assert_equal(['foo', 'bar'], getbufline(b, 1, 2)) - call assert_equal(0, appendbufline(b, 0, 'baz')) - call assert_equal(['baz', 'foo', 'bar'], getbufline(b, 1, 3)) - - " appendbufline() in a hidden buffer shouldn't move marks in current window. - call assert_equal(2, line("''")) - bwipe! - - exe "bd!" b - call assert_equal([], getbufline(b, 1, 3)) - - split Xtest - call setline(1, ['a', 'b', 'c']) - let b = bufnr('%') - wincmd w - - call assert_equal(1, appendbufline(b, -1, 'x')) - call assert_equal(1, appendbufline(b, -1, ['x'])) - call assert_equal(1, appendbufline(b, -1, [])) - call assert_equal(1, appendbufline(b, -1, v:_null_list)) - - call assert_equal(1, appendbufline(b, 4, 'x')) - call assert_equal(1, appendbufline(b, 4, ['x'])) - call assert_equal(1, appendbufline(b, 4, [])) - call assert_equal(1, appendbufline(b, 4, v:_null_list)) - - call assert_equal(1, appendbufline(1234, 1, 'x')) - call assert_equal(1, appendbufline(1234, 1, ['x'])) - call assert_equal(1, appendbufline(1234, 1, [])) - call assert_equal(1, appendbufline(1234, 1, v:_null_list)) - - call assert_equal(0, appendbufline(b, 1, [])) - call assert_equal(0, appendbufline(b, 1, v:_null_list)) - call assert_equal(1, appendbufline(b, 3, [])) - call assert_equal(1, appendbufline(b, 3, v:_null_list)) - - call assert_equal(['a', 'b', 'c'], getbufline(b, 1, '$')) - - call assert_equal(0, appendbufline(b, 3, ['d', 'e'])) - call assert_equal(['c'], getbufline(b, 3)) - call assert_equal(['d'], getbufline(b, 4)) - call assert_equal(['e'], getbufline(b, 5)) - call assert_equal([], getbufline(b, 6)) - exe "bwipe! " . b -endfunc - -func Test_deletebufline() - new - let b = bufnr('%') - call setline(1, ['aaa', 'bbb', 'ccc']) - hide - - new - call setline(1, ['line1', 'line2', 'line3']) - normal! 2gggg - call assert_equal(2, line("''")) - - call assert_equal(0, deletebufline(b, 2)) - call assert_equal(['aaa', 'ccc'], getbufline(b, 1, 2)) - call assert_equal(0, deletebufline(b, 2, 8)) - call assert_equal(['aaa'], getbufline(b, 1, 2)) - - " deletebufline() in a hidden buffer shouldn't move marks in current window. - call assert_equal(2, line("''")) - bwipe! - - exe "bd!" b - call assert_equal(1, b->deletebufline(1)) - - call assert_equal(1, deletebufline(-1, 1)) - - split Xtest - call setline(1, ['a', 'b', 'c']) - call cursor(line('$'), 1) - let b = bufnr('%') - wincmd w - call assert_equal(1, deletebufline(b, 4)) - call assert_equal(0, deletebufline(b, 1)) - call assert_equal(['b', 'c'], getbufline(b, 1, 2)) - exe "bwipe! " . b - - edit XbufOne - let one = bufnr() - call setline(1, ['a', 'b', 'c']) - setlocal nomodifiable - split XbufTwo - let two = bufnr() - call assert_fails('call deletebufline(one, 1)', 'E21:') - call assert_equal(two, bufnr()) - bwipe! XbufTwo - bwipe! XbufOne -endfunc - -func Test_appendbufline_redraw() - CheckScreendump - - let lines =<< trim END - new foo - let winnr = 'foo'->bufwinnr() - let buf = bufnr('foo') - wincmd p - call appendbufline(buf, '$', range(1,200)) - exe winnr .. 'wincmd w' - norm! G - wincmd p - call deletebufline(buf, 1, '$') - call appendbufline(buf, '$', 'Hello Vim world...') - END - call writefile(lines, 'XscriptMatchCommon') - let buf = RunVimInTerminal('-S XscriptMatchCommon', #{rows: 10}) - call term_wait(buf) - call VerifyScreenDump(buf, 'Test_appendbufline_1', {}) - - call StopVimInTerminal(buf) - call delete('XscriptMatchCommon') -endfunc - -func Test_setbufline_select_mode() - new - call setline(1, ['foo', 'bar']) - call feedkeys("j^v2l\", 'nx') - - let bufnr = bufadd('Xdummy') - call bufload(bufnr) - call setbufline(bufnr, 1, ['abc']) - - call feedkeys("x", 'nx') - call assert_equal(['foo', 'x'], getline(1, 2)) - - exe "bwipe! " .. bufnr - bwipe! -endfunc - -func Test_deletebufline_select_mode() - new - call setline(1, ['foo', 'bar']) - call feedkeys("j^v2l\", 'nx') - - let bufnr = bufadd('Xdummy') - call bufload(bufnr) - call setbufline(bufnr, 1, ['abc', 'def']) - call deletebufline(bufnr, 1) - - call feedkeys("x", 'nx') - call assert_equal(['foo', 'x'], getline(1, 2)) - - exe "bwipe! " .. bufnr - bwipe! -endfunc - -func Test_setbufline_startup_nofile() - let before =<< trim [CODE] - set shortmess+=F - file Xresult - set buftype=nofile - call setbufline('', 1, 'success') - [CODE] - let after =<< trim [CODE] - set buftype= - write - quit - [CODE] - - if !RunVim(before, after, '--clean') - return - endif - call assert_equal(['success'], readfile('Xresult')) - call delete('Xresult') -endfunc - -" Test that setbufline(), appendbufline() and deletebufline() should fail and -" return 1 when "textlock" is active. -func Test_change_bufline_with_textlock() - new - inoremap setbufline('', 1, '') - call assert_fails("normal a\", 'E565:') - call assert_equal('1', getline(1)) - inoremap appendbufline('', 1, '') - call assert_fails("normal a\", 'E565:') - call assert_equal('11', getline(1)) - inoremap deletebufline('', 1) - call assert_fails("normal a\", 'E565:') - call assert_equal('111', getline(1)) - bwipe! -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_bufwintabinfo.vim b/src/nvim/testdir/test_bufwintabinfo.vim deleted file mode 100644 index 326aefb731..0000000000 --- a/src/nvim/testdir/test_bufwintabinfo.vim +++ /dev/null @@ -1,187 +0,0 @@ -" Tests for the getbufinfo(), getwininfo() and gettabinfo() functions - -function Test_getbufwintabinfo() - edit Xtestfile1 - edit Xtestfile2 - let buflist = getbufinfo() - call assert_equal(2, len(buflist)) - call assert_match('Xtestfile1', buflist[0].name) - call assert_match('Xtestfile2', getbufinfo('Xtestfile2')[0].name) - call assert_equal([], getbufinfo(2016)) - edit Xtestfile1 - hide edit Xtestfile2 - hide enew - call assert_equal(3, len(getbufinfo({'bufloaded':1}))) - - set tabstop&vim - let b:editor = 'vim' - let l = getbufinfo('%') - call assert_equal(bufnr('%'), l[0].bufnr) - call assert_equal('vim', l[0].variables.editor) - call assert_notequal(-1, index(l[0].windows, '%'->bufwinid())) - - let l = '%'->getbufinfo() - call assert_equal(bufnr('%'), l[0].bufnr) - - " Test for getbufinfo() with 'bufmodified' - call assert_equal(0, len(getbufinfo({'bufmodified' : 1}))) - call setbufline('Xtestfile1', 1, ["Line1"]) - let l = getbufinfo({'bufmodified' : 1}) - call assert_equal(1, len(l)) - call assert_equal(bufnr('Xtestfile1'), l[0].bufnr) - - if has('signs') - call append(0, ['Linux', 'Windows', 'Mac']) - sign define Mark text=>> texthl=Search - exe "sign place 2 line=3 name=Mark buffer=" . bufnr('%') - let l = getbufinfo('%') - call assert_equal(2, l[0].signs[0].id) - call assert_equal(3, l[0].signs[0].lnum) - call assert_equal('Mark', l[0].signs[0].name) - sign unplace * - sign undefine Mark - enew! - endif - - only - let w1_id = win_getid() - setl foldcolumn=3 - new - let w2_id = win_getid() - tabnew | let w3_id = win_getid() - new | let w4_id = win_getid() - vert new | let w5_id = win_getid() - eval 'green'->setwinvar(0, 'signal') - tabfirst - let winlist = getwininfo() - call assert_equal(5, len(winlist)) - call assert_equal(winwidth(1), winlist[0].width) - call assert_equal(1, winlist[0].wincol) - " tabline adds one row in terminal, not in GUI - let tablineheight = winlist[0].winrow == 2 ? 1 : 0 - call assert_equal(tablineheight + 1, winlist[0].winrow) - - call assert_equal(winbufnr(2), winlist[1].bufnr) - call assert_equal(winheight(2), winlist[1].height) - call assert_equal(1, winlist[1].wincol) - call assert_equal(3, winlist[1].textoff) " foldcolumn - call assert_equal(tablineheight + winheight(1) + 2, winlist[1].winrow) - - call assert_equal(1, winlist[2].winnr) - call assert_equal(tablineheight + 1, winlist[2].winrow) - call assert_equal(1, winlist[2].wincol) - - call assert_equal(winlist[2].width + 2, winlist[3].wincol) - call assert_equal(1, winlist[4].wincol) - - call assert_equal(1, winlist[0].tabnr) - call assert_equal(1, winlist[1].tabnr) - call assert_equal(2, winlist[2].tabnr) - call assert_equal(2, winlist[3].tabnr) - call assert_equal(2, winlist[4].tabnr) - - call assert_equal('green', winlist[2].variables.signal) - call assert_equal(w4_id, winlist[3].winid) - let winfo = w5_id->getwininfo()[0] - call assert_equal(2, winfo.tabnr) - call assert_equal([], getwininfo(3)) - - call settabvar(1, 'space', 'build') - let tablist = gettabinfo() - call assert_equal(2, len(tablist)) - call assert_equal(3, len(tablist[1].windows)) - call assert_equal(2, tablist[1].tabnr) - call assert_equal('build', tablist[0].variables.space) - call assert_equal(w2_id, tablist[0].windows[0]) - call assert_equal([], 3->gettabinfo()) - - tabonly | only - - lexpr '' - lopen - copen - let winlist = getwininfo() - call assert_false(winlist[0].quickfix) - call assert_false(winlist[0].loclist) - call assert_true(winlist[1].quickfix) - call assert_true(winlist[1].loclist) - call assert_true(winlist[2].quickfix) - call assert_false(winlist[2].loclist) - wincmd t | only -endfunction - -function Test_get_buf_options() - let opts = bufnr()->getbufvar('&') - call assert_equal(v:t_dict, type(opts)) - call assert_equal(8, opts.tabstop) -endfunc - -function Test_get_win_options() - if has('folding') - set foldlevel=999 - endif - set list - let opts = getwinvar(1, '&') - call assert_equal(v:t_dict, type(opts)) - call assert_equal(0, opts.linebreak) - call assert_equal(1, opts.list) - if has('folding') - call assert_equal(999, opts.foldlevel) - endif - if has('signs') - call assert_equal('auto', opts.signcolumn) - endif - - let opts = gettabwinvar(1, 1, '&') - call assert_equal(v:t_dict, type(opts)) - call assert_equal(0, opts.linebreak) - call assert_equal(1, opts.list) - if has('signs') - call assert_equal('auto', opts.signcolumn) - endif - set list& - if has('folding') - set foldlevel=0 - endif -endfunc - -function Test_getbufinfo_lastused() - new Xfoo - let info = getbufinfo('Xfoo')[0] - call assert_equal(has_key(info, 'lastused'), 1) - call assert_equal(type(info.lastused), type(0)) -endfunc - -func Test_getbufinfo_lines() - new Xfoo - call setline(1, ['a', 'bc', 'd']) - let bn = bufnr('%') - hide - call assert_equal(3, getbufinfo(bn)[0]["linecount"]) - edit Xfoo - bw! -endfunc - -func Test_getwininfo_au() - enew - call setline(1, range(1, 16)) - - let g:info = #{} - augroup T1 - au! - au WinEnter * let g:info = getwininfo(win_getid())[0] - augroup END - - 4split - " Check that calling getwininfo() from WinEnter returns fresh values for - " topline and botline. - call assert_equal(1, g:info.topline) - call assert_equal(4, g:info.botline) - close - - unlet g:info - augroup! T1 - bwipe! -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_cd.vim b/src/nvim/testdir/test_cd.vim deleted file mode 100644 index 2b37f2c7c0..0000000000 --- a/src/nvim/testdir/test_cd.vim +++ /dev/null @@ -1,256 +0,0 @@ -" Test for :cd and chdir() - -source shared.vim -source check.vim - -func Test_cd_large_path() - " This used to crash with a heap write overflow. - call assert_fails('cd ' . repeat('x', 5000), 'E344:') -endfunc - -func Test_cd_up_and_down() - let path = getcwd() - cd .. - call assert_notequal(path, getcwd()) - exe 'cd ' .. fnameescape(path) - call assert_equal(path, getcwd()) -endfunc - -func Test_cd_no_arg() - if has('unix') - " Test that cd without argument goes to $HOME directory on Unix systems. - let path = getcwd() - cd - call assert_equal($HOME, getcwd()) - call assert_notequal(path, getcwd()) - exe 'cd ' .. fnameescape(path) - call assert_equal(path, getcwd()) - else - " Test that cd without argument echoes cwd on non-Unix systems. - call assert_match(getcwd(), execute('cd')) - endif -endfunc - -func Test_cd_minus() - " Test the :cd - goes back to the previous directory. - let path = getcwd() - cd .. - let path_dotdot = getcwd() - call assert_notequal(path, path_dotdot) - cd - - call assert_equal(path, getcwd()) - cd - - call assert_equal(path_dotdot, getcwd()) - cd - - call assert_equal(path, getcwd()) - - " Test for :cd - after a failed :cd - call assert_fails('cd /nonexistent', 'E344:') - call assert_equal(path, getcwd()) - cd - - call assert_equal(path_dotdot, getcwd()) - cd - - - " Test for :cd - without a previous directory - let lines =<< trim [SCRIPT] - call assert_fails('cd -', 'E186:') - call assert_fails('call chdir("-")', 'E186:') - call writefile(v:errors, 'Xresult') - qall! - [SCRIPT] - call writefile(lines, 'Xscript') - if RunVim([], [], '--clean -S Xscript') - call assert_equal([], readfile('Xresult')) - endif - call delete('Xscript') - call delete('Xresult') -endfunc - -" Test for chdir() -func Test_chdir_func() - let topdir = getcwd() - call mkdir('Xdir/y/z', 'p') - - " Create a few tabpages and windows with different directories - new - cd Xdir - tabnew - tcd y - below new - below new - lcd z - - tabfirst - call assert_match('^\[global\] .*/Xdir$', trim(execute('verbose pwd'))) - call chdir('..') - call assert_equal('y', fnamemodify(getcwd(1, 2), ':t')) - call assert_equal('z', fnamemodify(3->getcwd(2), ':t')) - tabnext | wincmd t - call assert_match('^\[tabpage\] .*/y$', trim(execute('verbose pwd'))) - eval '..'->chdir() - call assert_equal('Xdir', fnamemodify(getcwd(1, 2), ':t')) - call assert_equal('Xdir', fnamemodify(getcwd(2, 2), ':t')) - call assert_equal('z', fnamemodify(getcwd(3, 2), ':t')) - call assert_equal('testdir', fnamemodify(getcwd(1, 1), ':t')) - 3wincmd w - call assert_match('^\[window\] .*/z$', trim(execute('verbose pwd'))) - call chdir('..') - call assert_equal('Xdir', fnamemodify(getcwd(1, 2), ':t')) - call assert_equal('Xdir', fnamemodify(getcwd(2, 2), ':t')) - call assert_equal('y', fnamemodify(getcwd(3, 2), ':t')) - call assert_equal('testdir', fnamemodify(getcwd(1, 1), ':t')) - - " Error case - call assert_fails("call chdir('dir-abcd')", 'E344:') - silent! let d = chdir("dir_abcd") - call assert_equal("", d) - " Should not crash - call chdir(d) - - only | tabonly - call chdir(topdir) - call delete('Xdir', 'rf') -endfunc - -" Test for changing to the previous directory '-' -func Test_prev_dir() - let topdir = getcwd() - call mkdir('Xdir/a/b/c', 'p') - - " Create a few tabpages and windows with different directories - new | only - tabnew | new - tabnew - tabfirst - cd Xdir - tabnext | wincmd t - tcd a - wincmd w - lcd b - tabnext - tcd a/b/c - - " Change to the previous directory twice in all the windows. - tabfirst - cd - | cd - - tabnext | wincmd t - tcd - | tcd - - wincmd w - lcd - | lcd - - tabnext - tcd - | tcd - - - " Check the directory of all the windows - tabfirst - call assert_equal('Xdir', fnamemodify(getcwd(), ':t')) - tabnext | wincmd t - call assert_equal('a', fnamemodify(getcwd(), ':t')) - wincmd w - call assert_equal('b', fnamemodify(getcwd(), ':t')) - tabnext - call assert_equal('c', fnamemodify(getcwd(), ':t')) - - " Change to the previous directory using chdir() - tabfirst - call chdir("-") | call chdir("-") - tabnext | wincmd t - call chdir("-") | call chdir("-") - wincmd w - call chdir("-") | call chdir("-") - tabnext - call chdir("-") | call chdir("-") - - " Check the directory of all the windows - tabfirst - call assert_equal('Xdir', fnamemodify(getcwd(), ':t')) - tabnext | wincmd t - call assert_equal('a', fnamemodify(getcwd(), ':t')) - wincmd w - call assert_equal('b', fnamemodify(getcwd(), ':t')) - tabnext - call assert_equal('c', fnamemodify(getcwd(), ':t')) - - only | tabonly - call chdir(topdir) - call delete('Xdir', 'rf') -endfunc - -func Test_lcd_split() - let curdir = getcwd() - lcd .. - split - lcd - - call assert_equal(curdir, getcwd()) - quit! -endfunc - -func Test_cd_from_non_existing_dir() - CheckNotMSWindows - - let saveddir = getcwd() - call mkdir('Xdeleted_dir') - cd Xdeleted_dir - call delete(saveddir .. '/Xdeleted_dir', 'd') - - " Expect E187 as the current directory was deleted. - call assert_fails('pwd', 'E187:') - call assert_equal('', getcwd()) - cd - - call assert_equal(saveddir, getcwd()) -endfunc - -func Test_cd_completion() - call mkdir('XComplDir1', 'p') - call mkdir('XComplDir2', 'p') - call writefile([], 'XComplFile') - - for cmd in ['cd', 'chdir', 'lcd', 'lchdir', 'tcd', 'tchdir'] - call feedkeys(':' .. cmd .. " XCompl\\\"\", 'tx') - call assert_equal('"' .. cmd .. ' XComplDir1/ XComplDir2/', @:) - endfor - - call delete('XComplDir1', 'd') - call delete('XComplDir2', 'd') - call delete('XComplFile') -endfunc - -func Test_cd_unknown_dir() - call mkdir('Xa') - cd Xa - call writefile(['text'], 'Xb.txt') - edit Xa/Xb.txt - let first_buf = bufnr() - cd .. - edit - call assert_equal(first_buf, bufnr()) - edit Xa/Xb.txt - call assert_notequal(first_buf, bufnr()) - - bwipe! - exe "bwipe! " .. first_buf - call delete('Xa', 'rf') -endfunc - -func Test_getcwd_actual_dir() - CheckFunction test_autochdir - CheckOption autochdir - - let startdir = getcwd() - call mkdir('Xactual') - call test_autochdir() - set autochdir - edit Xactual/file.txt - call assert_match('testdir.Xactual$', getcwd()) - lcd .. - call assert_match('testdir$', getcwd()) - edit - call assert_match('testdir.Xactual$', getcwd()) - call assert_match('testdir$', getcwd(win_getid())) - - set noautochdir - bwipe! - call chdir(startdir) - call delete('Xactual', 'rf') -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_cdo.vim b/src/nvim/testdir/test_cdo.vim deleted file mode 100644 index dbed7df4ac..0000000000 --- a/src/nvim/testdir/test_cdo.vim +++ /dev/null @@ -1,216 +0,0 @@ -" Tests for the :cdo, :cfdo, :ldo and :lfdo commands - -source check.vim -CheckFeature quickfix - -" Create the files used by the tests -func SetUp() - call writefile(["Line1", "Line2", "Line3"], 'Xtestfile1') - call writefile(["Line1", "Line2", "Line3"], 'Xtestfile2') - call writefile(["Line1", "Line2", "Line3"], 'Xtestfile3') -endfunc - -" Remove the files used by the tests -func TearDown() - call delete('Xtestfile1') - call delete('Xtestfile2') - call delete('Xtestfile3') -endfunc - -" Returns the current line in ' L C' format -func GetRuler() - return expand('%') . ' ' . line('.') . 'L' . ' ' . col('.') . 'C' -endfunc - -" Tests for the :cdo and :ldo commands -func XdoTests(cchar) - enew - - " Shortcuts for calling the cdo and ldo commands - let Xdo = a:cchar . 'do' - let Xgetexpr = a:cchar . 'getexpr' - let Xprev = a:cchar. 'prev' - let XdoCmd = Xdo . ' call add(l, GetRuler())' - - " Try with an empty list - let l = [] - exe XdoCmd - call assert_equal([], l) - - " Populate the list and then try - exe Xgetexpr . " ['non-error 1', 'Xtestfile1:1:3:Line1', 'non-error 2', 'Xtestfile2:2:2:Line2', 'non-error 3', 'Xtestfile3:3:1:Line3']" - - let l = [] - exe XdoCmd - call assert_equal(['Xtestfile1 1L 3C', 'Xtestfile2 2L 2C', 'Xtestfile3 3L 1C'], l) - - " Run command only on selected error lines - let l = [] - enew - exe "2,3" . XdoCmd - call assert_equal(['Xtestfile2 2L 2C', 'Xtestfile3 3L 1C'], l) - - " Boundary condition tests - let l = [] - enew - exe "1,1" . XdoCmd - call assert_equal(['Xtestfile1 1L 3C'], l) - - let l = [] - enew - exe "3" . XdoCmd - call assert_equal(['Xtestfile3 3L 1C'], l) - - " Range test commands - let l = [] - enew - exe "%" . XdoCmd - call assert_equal(['Xtestfile1 1L 3C', 'Xtestfile2 2L 2C', 'Xtestfile3 3L 1C'], l) - - let l = [] - enew - exe "1,$" . XdoCmd - call assert_equal(['Xtestfile1 1L 3C', 'Xtestfile2 2L 2C', 'Xtestfile3 3L 1C'], l) - - let l = [] - enew - exe Xprev - exe "." . XdoCmd - call assert_equal(['Xtestfile2 2L 2C'], l) - - let l = [] - enew - exe "+" . XdoCmd - call assert_equal(['Xtestfile3 3L 1C'], l) - - " Invalid error lines test - let l = [] - enew - exe "silent! 27" . XdoCmd - exe "silent! 4,5" . XdoCmd - call assert_equal([], l) - - " Run commands from an unsaved buffer - let v:errmsg='' - let l = [] - enew - setlocal modified - exe "silent! 2,2" . XdoCmd - if v:errmsg !~# 'No write since last change' - call add(v:errors, 'Unsaved file change test failed') - endif - - " If the executed command fails, then the operation should be aborted - enew! - let subst_count = 0 - exe "silent!" . Xdo . " s/Line/xLine/ | let subst_count += 1" - if subst_count != 1 || getline('.') != 'xLine1' - call add(v:errors, 'Abort command on error test failed') - endif - - let l = [] - exe "2,2" . Xdo . "! call add(l, GetRuler())" - call assert_equal(['Xtestfile2 2L 2C'], l) - - " List with no valid error entries - let l = [] - edit! +2 Xtestfile1 - exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']" - exe XdoCmd - call assert_equal([], l) - exe "silent! 2" . XdoCmd - call assert_equal([], l) - let v:errmsg='' - exe "%" . XdoCmd - exe "1,$" . XdoCmd - exe "." . XdoCmd - call assert_equal('', v:errmsg) - - " List with only one valid entry - let l = [] - exe Xgetexpr . " ['Xtestfile3:3:1:Line3']" - exe XdoCmd - call assert_equal(['Xtestfile3 3L 1C'], l) - -endfunc - -" Tests for the :cfdo and :lfdo commands -func XfdoTests(cchar) - enew - - " Shortcuts for calling the cfdo and lfdo commands - let Xfdo = a:cchar . 'fdo' - let Xgetexpr = a:cchar . 'getexpr' - let XfdoCmd = Xfdo . ' call add(l, GetRuler())' - let Xpfile = a:cchar. 'pfile' - - " Clear the quickfix/location list - exe Xgetexpr . " []" - - " Try with an empty list - let l = [] - exe XfdoCmd - call assert_equal([], l) - - " Populate the list and then try - exe Xgetexpr . " ['non-error 1', 'Xtestfile1:1:3:Line1', 'Xtestfile1:2:1:Line2', 'non-error 2', 'Xtestfile2:2:2:Line2', 'non-error 3', 'Xtestfile3:2:3:Line2', 'Xtestfile3:3:1:Line3']" - - let l = [] - exe XfdoCmd - call assert_equal(['Xtestfile1 1L 3C', 'Xtestfile2 2L 2C', 'Xtestfile3 2L 3C'], l) - - " Run command only on selected error lines - let l = [] - exe "2,3" . XfdoCmd - call assert_equal(['Xtestfile2 2L 2C', 'Xtestfile3 2L 3C'], l) - - " Boundary condition tests - let l = [] - exe "3" . XfdoCmd - call assert_equal(['Xtestfile3 2L 3C'], l) - - " Range test commands - let l = [] - exe "%" . XfdoCmd - call assert_equal(['Xtestfile1 1L 3C', 'Xtestfile2 2L 2C', 'Xtestfile3 2L 3C'], l) - - let l = [] - exe "1,$" . XfdoCmd - call assert_equal(['Xtestfile1 1L 3C', 'Xtestfile2 2L 2C', 'Xtestfile3 2L 3C'], l) - - let l = [] - exe Xpfile - exe "." . XfdoCmd - call assert_equal(['Xtestfile2 2L 2C'], l) - - " List with only one valid entry - let l = [] - exe Xgetexpr . " ['Xtestfile2:2:5:Line2']" - exe XfdoCmd - call assert_equal(['Xtestfile2 2L 5C'], l) - -endfunc - -" Tests for cdo and cfdo -func Test_cdo() - call XdoTests('c') - call XfdoTests('c') -endfunc - -" Tests for ldo and lfdo -func Test_ldo() - call XdoTests('l') - call XfdoTests('l') -endfunc - -" Test for making 'shm' doesn't interfere with the output. -func Test_cdo_print() - enew | only! - cgetexpr ["Xtestfile1:1:Line1", "Xtestfile2:1:Line1", "Xtestfile3:1:Line1"] - cdo print - call assert_equal('Line1', Screenline(&lines)) - call assert_equal('Line1', Screenline(&lines - 3)) - call assert_equal('Line1', Screenline(&lines - 6)) -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_changedtick.vim b/src/nvim/testdir/test_changedtick.vim deleted file mode 100644 index c789cdc1bc..0000000000 --- a/src/nvim/testdir/test_changedtick.vim +++ /dev/null @@ -1,95 +0,0 @@ -" Tests for b:changedtick - -func Test_changedtick_increments() - new - " New buffer has an empty line, tick starts at 2. - let expected = 2 - call assert_equal(expected, b:changedtick) - call assert_equal(expected, b:['changedtick']) - call setline(1, 'hello') - let expected += 1 - call assert_equal(expected, b:changedtick) - call assert_equal(expected, b:['changedtick']) - undo - " Somehow undo counts as two changes. - let expected += 2 - call assert_equal(expected, b:changedtick) - call assert_equal(expected, b:['changedtick']) - bwipe! -endfunc - -func Test_changedtick_dict_entry() - let d = b: - call assert_equal(b:changedtick, d['changedtick']) -endfunc - -func Test_changedtick_bdel() - new - let bnr = bufnr('%') - let v = b:changedtick - bdel - " Delete counts as a change too. - call assert_equal(v + 1, getbufvar(bnr, 'changedtick')) -endfunc - -func Test_changedtick_islocked() - call assert_equal(0, islocked('b:changedtick')) - let d = b: - call assert_equal(0, islocked('d.changedtick')) -endfunc - -func Test_changedtick_fixed() - call assert_fails('let b:changedtick = 4', 'E46:') - call assert_fails('let b:["changedtick"] = 4', 'E46:') - - call assert_fails('lockvar b:changedtick', 'E940:') - call assert_fails('lockvar b:["changedtick"]', 'E46:') - call assert_fails('unlockvar b:changedtick', 'E940:') - call assert_fails('unlockvar b:["changedtick"]', 'E46:') - call assert_fails('unlet b:changedtick', 'E795:') - call assert_fails('unlet b:["changedtick"]', 'E46:') - - let d = b: - call assert_fails('lockvar d["changedtick"]', 'E46:') - call assert_fails('unlockvar d["changedtick"]', 'E46:') - call assert_fails('unlet d["changedtick"]', 'E46:') - -endfunc - -func Test_changedtick_not_incremented_with_write() - new - let fname = "XChangeTick" - exe 'w ' .. fname - - " :write when the buffer is not changed does not increment changedtick - let expected = b:changedtick - w - call assert_equal(expected, b:changedtick) - - " :write when the buffer IS changed DOES increment changedtick - let expected = b:changedtick + 1 - setlocal modified - w - call assert_equal(expected, b:changedtick) - - " Two ticks: change + write - let expected = b:changedtick + 2 - call setline(1, 'hello') - w - call assert_equal(expected, b:changedtick) - - " Two ticks: start insert + write - let expected = b:changedtick + 2 - normal! o - w - call assert_equal(expected, b:changedtick) - - " Three ticks: start insert + change + write - let expected = b:changedtick + 3 - normal! ochanged - w - call assert_equal(expected, b:changedtick) - - bwipe - call delete(fname) -endfunc diff --git a/src/nvim/testdir/test_changelist.vim b/src/nvim/testdir/test_changelist.vim deleted file mode 100644 index 3bb22a89b8..0000000000 --- a/src/nvim/testdir/test_changelist.vim +++ /dev/null @@ -1,107 +0,0 @@ -" Tests for the changelist functionality - -" When splitting a window the changelist position is wrong. -" Test the changelist position after splitting a window. -" Test for the bug fixed by 7.4.386 -func Test_changelist() - let save_ul = &ul - enew! - call append('$', ['1', '2']) - exe "normal i\u" - exe "normal Gkylpa\u" - set ul=100 - exe "normal Gylpa\u" - set ul=100 - normal gg - vsplit - normal g; - call assert_equal([3, 2], [line('.'), col('.')]) - normal g; - call assert_equal([2, 2], [line('.'), col('.')]) - call assert_fails('normal g;', 'E662:') - new - call assert_fails('normal g;', 'E664:') - %bwipe! - let &ul = save_ul -endfunc - -" Moving a split should not change its changelist index. -func Test_changelist_index_move_split() - exe "norm! iabc\u\ndef\u\nghi" - vsplit - normal 99g; - call assert_equal(0, getchangelist('%')[1]) - wincmd L - call assert_equal(0, getchangelist('%')[1]) -endfunc - -" Tests for the getchangelist() function -func Test_changelist_index() - edit Xfile1.txt - exe "normal iabc\u\ndef\u\nghi" - call assert_equal(3, getchangelist('%')[1]) - " Move one step back in the changelist. - normal 2g; - - hide edit Xfile2.txt - exe "normal iabcd\u\ndefg\u\nghij" - call assert_equal(3, getchangelist('%')[1]) - " Move to the beginning of the changelist. - normal 99g; - - " Check the changelist indices. - call assert_equal(0, getchangelist('%')[1]) - call assert_equal(1, getchangelist('#')[1]) - - bwipe! - call delete('Xfile1.txt') - call delete('Xfile2.txt') -endfunc - -func Test_getchangelist() - bwipe! - enew - call assert_equal([], 10->getchangelist()) - call assert_equal([[], 0], getchangelist()) - - call writefile(['line1', 'line2', 'line3'], 'Xfile1.txt') - call writefile(['line1', 'line2', 'line3'], 'Xfile2.txt') - - edit Xfile1.txt - let buf_1 = bufnr() - exe "normal 1Goline\u1.1" - exe "normal 3Goline\u2.1" - exe "normal 5Goline\u3.1" - normal g; - call assert_equal([[ - \ {'lnum' : 2, 'col' : 4, 'coladd' : 0}, - \ {'lnum' : 4, 'col' : 4, 'coladd' : 0}, - \ {'lnum' : 6, 'col' : 4, 'coladd' : 0}], 2], - \ getchangelist('%')) - - hide edit Xfile2.txt - let buf_2 = bufnr() - exe "normal 1GOline\u1.0" - exe "normal 2Goline\u2.0" - call assert_equal([[ - \ {'lnum' : 1, 'col' : 6, 'coladd' : 0}, - \ {'lnum' : 3, 'col' : 6, 'coladd' : 0}], 2], - \ getchangelist('%')) - hide enew - - call assert_equal([[ - \ {'lnum' : 2, 'col' : 4, 'coladd' : 0}, - \ {'lnum' : 4, 'col' : 4, 'coladd' : 0}, - \ {'lnum' : 6, 'col' : 4, 'coladd' : 0}], 2], - \ getchangelist(buf_1)) - call assert_equal([[ - \ {'lnum' : 1, 'col' : 6, 'coladd' : 0}, - \ {'lnum' : 3, 'col' : 6, 'coladd' : 0}], 2], - \ getchangelist(buf_2)) - - bwipe! - call delete('Xfile1.txt') - call delete('Xfile2.txt') -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_charsearch.vim b/src/nvim/testdir/test_charsearch.vim deleted file mode 100644 index f8f3e958ca..0000000000 --- a/src/nvim/testdir/test_charsearch.vim +++ /dev/null @@ -1,99 +0,0 @@ -" Test for character search commands - t, T, f, F, ; and , - -func Test_charsearch() - enew! - call append(0, ['Xabcdefghijkemnopqretuvwxyz', - \ 'Yabcdefghijkemnopqretuvwxyz', - \ 'Zabcdefghijkemnokqretkvwxyz']) - " check that "fe" and ";" work - 1 - normal! ylfep;;p,,p - call assert_equal('XabcdeXfghijkeXmnopqreXtuvwxyz', getline(1)) - " check that save/restore works - 2 - normal! ylfep - let csave = getcharsearch() - normal! fip - call setcharsearch(csave) - normal! ;p;p - call assert_equal('YabcdeYfghiYjkeYmnopqreYtuvwxyz', getline(2)) - - " check that setcharsearch() changes the settings. - 3 - normal! ylfep - eval {'char': 'k'}->setcharsearch() - normal! ;p - call setcharsearch({'forward': 0}) - normal! $;p - call setcharsearch({'until': 1}) - set cpo-=; - normal! ;;p - call assert_equal('ZabcdeZfghijkZZemnokqretkZvwxyz', getline(3)) - - " check that repeating a search before and after a line fails - normal 3Gfv - call assert_beeps('normal ;') - call assert_beeps('normal ,') - - " clear the character search - call setcharsearch({'char' : ''}) - call assert_equal('', getcharsearch().char) - - call assert_fails("call setcharsearch([])", 'E715:') - enew! -endfunc - -" Test for character search in virtual edit mode with -func Test_csearch_virtualedit() - new - set virtualedit=all - call setline(1, "a\tb") - normal! tb - call assert_equal([0, 1, 2, 6], getpos('.')) - set virtualedit& - bw! -endfunc - -" Test for character search failure in latin1 encoding -func Test_charsearch_latin1() - new - let save_enc = &encoding - " set encoding=latin1 - call setline(1, 'abcdefghijk') - call assert_beeps('normal fz') - call assert_beeps('normal tx') - call assert_beeps('normal $Fz') - call assert_beeps('normal $Tx') - let &encoding = save_enc - bw! -endfunc - -" Test for using character search to find a multibyte character with composing -" characters. -func Test_charsearch_composing_char() - new - call setline(1, "one two thq\u0328\u0301r\u0328\u0301ree") - call feedkeys("fr\u0328\u0301", 'xt') - call assert_equal([0, 1, 16, 0, 12], getcurpos()) - - " use character search with a multi-byte character followed by a - " non-composing character - call setline(1, "abc deȉf ghi") - call feedkeys("ggcf\u0209\u0210", 'xt') - call assert_equal("\u0210f ghi", getline(1)) - bw! -endfunc - -" Test for character search with 'hkmap' -func Test_charsearch_hkmap() - throw "Skipped: Nvim does not support 'hkmap'" - new - set hkmap - call setline(1, "ùðáâ÷ëòéïçìêöî") - call feedkeys("fë", 'xt') - call assert_equal([0, 1, 11, 0, 6], getcurpos()) - set hkmap& - bw! -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_charsearch_utf8.vim b/src/nvim/testdir/test_charsearch_utf8.vim deleted file mode 100644 index 82a807ac5b..0000000000 --- a/src/nvim/testdir/test_charsearch_utf8.vim +++ /dev/null @@ -1,19 +0,0 @@ -" Tests for related f{char} and t{char} using utf-8. - -" Test for t,f,F,T movement commands -func Test_search_cmds() - new! - call setline(1, "・最åˆã‹ã‚‰æœ€å¾Œã¾ã§æœ€å¼·ã®Vimã¯æœ€é«˜") - 1 - normal! f最 - call assert_equal([0, 1, 4, 0], getpos('.')) - normal! ; - call assert_equal([0, 1, 16, 0], getpos('.')) - normal! 2; - call assert_equal([0, 1, 43, 0], getpos('.')) - normal! , - call assert_equal([0, 1, 28, 0], getpos('.')) - bw! -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_checkpath.vim b/src/nvim/testdir/test_checkpath.vim deleted file mode 100644 index f6a3bbce08..0000000000 --- a/src/nvim/testdir/test_checkpath.vim +++ /dev/null @@ -1,121 +0,0 @@ -" Tests for the :checkpath command - -" Test for 'include' without \zs or \ze -func Test_checkpath1() - call mkdir("Xdir1/dir2", "p") - call writefile(['#include "bar.a"'], 'Xdir1/dir2/foo.a') - call writefile(['#include "baz.a"'], 'Xdir1/dir2/bar.a') - call writefile(['#include "foo.a"'], 'Xdir1/dir2/baz.a') - call writefile(['#include '], 'Xbase.a') - - edit Xbase.a - set path=Xdir1/dir2 - let res = split(execute("checkpath!"), "\n") - call assert_equal([ - \ '--- Included files in path ---', - \ 'Xdir1/dir2/foo.a', - \ 'Xdir1/dir2/foo.a -->', - \ ' Xdir1/dir2/bar.a', - \ ' Xdir1/dir2/bar.a -->', - \ ' Xdir1/dir2/baz.a', - \ ' Xdir1/dir2/baz.a -->', - \ ' "foo.a" (Already listed)'], res) - - enew - call delete("./Xbase.a") - call delete("Xdir1", "rf") - set path& -endfunc - -func DotsToSlashes() - return substitute(v:fname, '\.', '/', 'g') . '.b' -endfunc - -" Test for 'include' with \zs and \ze -func Test_checkpath2() - call mkdir("Xdir1/dir2", "p") - call writefile(['%inc /bar/'], 'Xdir1/dir2/foo.b') - call writefile(['%inc /baz/'], 'Xdir1/dir2/bar.b') - call writefile(['%inc /foo/'], 'Xdir1/dir2/baz.b') - call writefile(['%inc /foo/'], 'Xbase.b') - - let &include='^\s*%inc\s*/\zs[^/]\+\ze' - let &includeexpr='DotsToSlashes()' - - edit Xbase.b - set path=Xdir1/dir2 - let res = split(execute("checkpath!"), "\n") - call assert_equal([ - \ '--- Included files in path ---', - \ 'Xdir1/dir2/foo.b', - \ 'Xdir1/dir2/foo.b -->', - \ ' Xdir1/dir2/bar.b', - \ ' Xdir1/dir2/bar.b -->', - \ ' Xdir1/dir2/baz.b', - \ ' Xdir1/dir2/baz.b -->', - \ ' foo (Already listed)'], res) - - enew - call delete("./Xbase.b") - call delete("Xdir1", "rf") - set path& - set include& - set includeexpr& -endfunc - -func StripNewlineChar() - if v:fname =~ '\n$' - return v:fname[:-2] - endif - return v:fname -endfunc - -" Test for 'include' with \zs and no \ze -func Test_checkpath3() - call mkdir("Xdir1/dir2", "p") - call writefile(['%inc bar.c'], 'Xdir1/dir2/foo.c') - call writefile(['%inc baz.c'], 'Xdir1/dir2/bar.c') - call writefile(['%inc foo.c'], 'Xdir1/dir2/baz.c') - call writefile(['%inc foo.c'], 'Xdir1/dir2/FALSE.c') - call writefile(['%inc FALSE.c foo.c'], 'Xbase.c') - - let &include='^\s*%inc\s*\%([[:upper:]][^[:space:]]*\s\+\)\?\zs\S\+\ze' - let &includeexpr='StripNewlineChar()' - - edit Xbase.c - set path=Xdir1/dir2 - let res = split(execute("checkpath!"), "\n") - call assert_equal([ - \ '--- Included files in path ---', - \ 'Xdir1/dir2/foo.c', - \ 'Xdir1/dir2/foo.c -->', - \ ' Xdir1/dir2/bar.c', - \ ' Xdir1/dir2/bar.c -->', - \ ' Xdir1/dir2/baz.c', - \ ' Xdir1/dir2/baz.c -->', - \ ' foo.c (Already listed)'], res) - - enew - call delete("./Xbase.c") - call delete("Xdir1", "rf") - set path& - set include& - set includeexpr& -endfunc - -" Test for invalid regex in 'include' and 'define' options -func Test_checkpath_errors() - let save_include = &include - set include=\\%( - call assert_fails('checkpath', 'E53:') - let &include = save_include - - let save_define = &define - set define=\\%( - call assert_fails('dsearch abc', 'E53:') - let &define = save_define - - call assert_fails('psearch \%(', 'E53:') -endfunc - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_cindent.vim b/src/nvim/testdir/test_cindent.vim deleted file mode 100644 index ccc8168c09..0000000000 --- a/src/nvim/testdir/test_cindent.vim +++ /dev/null @@ -1,5428 +0,0 @@ -" Test for cinoptions and cindent -" - -func Test_cino_hash() - " Test that curbuf->b_ind_hash_comment is correctly reset - new - setlocal cindent cinoptions=#1 - setlocal cinoptions= - call setline(1, ["#include "]) - call cursor(1, 1) - norm! o#include - "call feedkeys("o#include\", 't') - call assert_equal(["#include ", "#include"], getline(1,2)) - bwipe! -endfunc - -func Test_cino_extern_c() - " Test for cino-E - - let without_ind =<< trim [CODE] - #ifdef __cplusplus - extern "C" { - #endif - int func_a(void); - #ifdef __cplusplus - } - #endif - [CODE] - - let with_ind =<< trim [CODE] - #ifdef __cplusplus - extern "C" { - #endif - int func_a(void); - #ifdef __cplusplus - } - #endif - [CODE] - new - setlocal cindent cinoptions=E0 - call setline(1, without_ind) - call feedkeys("gg=G", 'tx') - call assert_equal(with_ind, getline(1, '$')) - - setlocal cinoptions=E-s - call setline(1, with_ind) - call feedkeys("gg=G", 'tx') - call assert_equal(without_ind, getline(1, '$')) - - setlocal cinoptions=Es - let tests = [ - \ ['recognized', ['extern "C" {'], "\t\t;"], - \ ['recognized', ['extern "C++" {'], "\t\t;"], - \ ['recognized', ['extern /* com */ "C"{'], "\t\t;"], - \ ['recognized', ['extern"C"{'], "\t\t;"], - \ ['recognized', ['extern "C"', '{'], "\t\t;"], - \ ['not recognized', ['extern {'], "\t;"], - \ ['not recognized', ['extern /*"C"*/{'], "\t;"], - \ ['not recognized', ['extern "C" //{'], ";"], - \ ['not recognized', ['extern "C" /*{*/'], ";"], - \ ] - - for pair in tests - let lines = pair[1] - call setline(1, lines) - call feedkeys(len(lines) . "Go;", 'tx') - call assert_equal(pair[2], getline(len(lines) + 1), 'Failed for "' . string(lines) . '"') - endfor - - bwipe! -endfunc - -func Test_cindent_rawstring() - new - setl cindent - call feedkeys("i" . - \ "int main() {\" . - \ "R\"(\" . - \ ")\";\" . - \ "statement;\", "x") - call assert_equal("\tstatement;", getline(line('.'))) - bw! -endfunc - -func Test_cindent_expr() - new - func! MyIndentFunction() - return v:lnum == 1 ? shiftwidth() : 0 - endfunc - setl expandtab sw=8 indentkeys+=; indentexpr=MyIndentFunction() - let testinput =<< trim [CODE] - var_a = something() - b = something() - [CODE] - call setline(1, testinput) - call cursor(1, 1) - call feedkeys("^\j$A;\", 'tnix') - let expected =<< [CODE] - var_a = something(); -b = something(); -[CODE] - call assert_equal(expected, getline(1, '$')) - - %d - let testinput =<< [CODE] - var_a = something() - b = something() -[CODE] - call setline(1, testinput) - call cursor(1, 1) - call feedkeys("^\j$A;\", 'tnix') - let expected =<< [CODE] - var_a = something(); - b = something() -[CODE] - call assert_equal(expected, getline(1, '$')) - bw! -endfunc - -func Test_cindent_func() - new - setlocal cindent - call setline(1, ['int main(void)', '{', 'return 0;', '}']) - call assert_equal(-1, cindent(0)) - call assert_equal(&sw, 3->cindent()) - call assert_equal(-1, cindent(line('$')+1)) - bwipe! -endfunc - -func Test_cindent_1() - new - setl cindent ts=4 sw=4 - setl cino& sts& - - let code =<< trim [CODE] - /* start of AUTO matically checked vim: set ts=4 : */ - { - if (test) - cmd1; - cmd2; - } - - { - if (test) - cmd1; - else - cmd2; - } - - { - if (test) - { - cmd1; - cmd2; - } - } - - { - if (test) - { - cmd1; - else - } - } - - { - while (this) - if (test) - cmd1; - cmd2; - } - - { - while (this) - if (test) - cmd1; - else - cmd2; - } - - { - if (test) - { - cmd; - } - - if (test) - cmd; - } - - { - if (test) { - cmd; - } - - if (test) cmd; - } - - { - cmd1; - for (blah) - while (this) - if (test) - cmd2; - cmd3; - } - - { - cmd1; - for (blah) - while (this) - if (test) - cmd2; - cmd3; - - if (test) - { - cmd1; - cmd2; - cmd3; - } - } - - - /* Test for 'cindent' do/while mixed with if/else: */ - - { - do - if (asdf) - asdfasd; - while (cond); - - do - if (asdf) - while (asdf) - asdf; - while (asdf); - } - - /* Test for 'cindent' with two ) on a continuation line */ - { - if (asdfasdf;asldkfj asdlkfj as;ldkfj sal;d - aal;sdkjf ( ;asldfkja;sldfk - al;sdjfka ;slkdf ) sa;ldkjfsa dlk;) - line up here; - } - - - /* C++ tests: */ - - // foo() these three lines should remain in column 0 - // { - // } - - /* Test for continuation and unterminated lines: */ - { - i = 99 + 14325 + - 21345 + - 21345 + - 21345 + ( 21345 + - 21345) + - 2345 + - 1234; - c = 1; - } - - /* - testje for indent with empty line - - here */ - - { - if (testing && - not a joke || - line up here) - hay; - if (testing && - (not a joke || testing - )line up here) - hay; - if (testing && - (not a joke || testing - line up here)) - hay; - } - - - { - switch (c) - { - case xx: - do - if (asdf) - do - asdfasdf; - while (asdf); - else - asdfasdf; - while (cond); - case yy: - case xx: - case zz: - testing; - } - } - - { - if (cond) { - foo; - } - else - { - bar; - } - } - - { - if (alskdfj ;alsdkfjal;skdjf (;sadlkfsa ;dlkf j;alksdfj ;alskdjf - alsdkfj (asldk;fj - awith cino=(0 ;lf this one goes to below the paren with == - ;laksjfd ;lsakdjf ;alskdf asd) - asdfasdf;))) - asdfasdf; - } - - int - func(a, b) - int a; - int c; - { - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3) - ) - } - - { - while (asd) - { - if (asdf) - if (test) - if (that) - { - if (asdf) - do - cdasd; - while (as - df); - } - else - if (asdf) - asdf; - else - asdf; - asdf; - } - } - - { - s = "/*"; b = ';' - s = "/*"; b = ';'; - a = b; - } - - { - switch (a) - { - case a: - switch (t) - { - case 1: - cmd; - break; - case 2: - cmd; - break; - } - cmd; - break; - case b: - { - int i; - cmd; - } - break; - case c: { - int i; - cmd; - } - case d: if (cond && - test) { /* this line doesn't work right */ - int i; - cmd; - } - break; - } - } - - { - if (!(vim_strchr(p_cpo, CPO_BUFOPTGLOB) != NULL && entering) && - (bp_to->b_p_initialized || - (!entering && vim_strchr(p_cpo, CPO_BUFOPT) != NULL))) - return; - label : - asdf = asdf ? - asdf : asdf; - asdf = asdf ? - asdf: asdf; - } - - /* Special Comments : This function has the added complexity (compared */ - /* : to addtolist) of having to check for a detail */ - /* : texture and add that to the list first. */ - - char *(array[100]) = { - "testje", - "foo", - "bar", - } - - enum soppie - { - yes = 0, - no, - maybe - }; - - typedef enum soppie - { - yes = 0, - no, - maybe - }; - - static enum - { - yes = 0, - no, - maybe - } soppie; - - public static enum - { - yes = 0, - no, - maybe - } soppie; - - static private enum - { - yes = 0, - no, - maybe - } soppie; - - { - int a, - b; - } - - { - struct Type - { - int i; - char *str; - } var[] = - { - 0, "zero", - 1, "one", - 2, "two", - 3, "three" - }; - - float matrix[3][3] = - { - { - 0, - 1, - 2 - }, - { - 3, - 4, - 5 - }, - { - 6, - 7, - 8 - } - }; - } - - { - /* blah ( blah */ - /* where does this go? */ - - /* blah ( blah */ - cmd; - - func(arg1, - /* comment */ - arg2); - a; - { - b; - { - c; /* Hey, NOW it indents?! */ - } - } - - { - func(arg1, - arg2, - arg3); - /* Hey, what am I doing here? Is this coz of the ","? */ - } - } - - main () - { - if (cond) - { - a = b; - } - if (cond) { - a = c; - } - if (cond) - a = d; - return; - } - - { - case 2: if (asdf && - asdfasdf) - aasdf; - a = 9; - case 3: if (asdf) - aasdf; - a = 9; - case 4: x = 1; - y = 2; - - label: if (asdf) - here; - - label: if (asdf && - asdfasdf) - { - } - - label: if (asdf && - asdfasdf) { - there; - } - - label: if (asdf && - asdfasdf) - there; - } - - { - /* - hello with ":set comments= cino=c5" - */ - - /* - hello with ":set comments= cino=" - */ - } - - - { - if (a < b) { - a = a + 1; - } else - a = a + 2; - - if (a) - do { - testing; - } while (asdfasdf); - a = b + 1; - asdfasdf - } - - { - for ( int i = 0; - i < 10; i++ ) - { - } - i = 0; - } - - class bob - { - int foo() {return 1;} - int bar; - } - - main() - { - while(1) - if (foo) - { - bar; - } - else { - asdf; - } - misplacedline; - } - - { - if (clipboard.state == SELECT_DONE - && ((row == clipboard.start.lnum - && col >= clipboard.start.col) - || row > clipboard.start.lnum)) - } - - { - if (1) {i += 4;} - where_am_i; - return 0; - } - - { - { - } // sdf(asdf - if (asdf) - asd; - } - - { - label1: - label2: - } - - { - int fooRet = foo(pBar1, false /*fKB*/, - true /*fPTB*/, 3 /*nT*/, false /*fDF*/); - f() { - for ( i = 0; - i < m; - /* c */ i++ ) { - a = b; - } - } - } - - { - f1(/*comment*/); - f2(); - } - - { - do { - if (foo) { - } else - ; - } while (foo); - foo(); // was wrong - } - - int x; // no extra indent because of the ; - void func() - { - } - - char *tab[] = {"aaa", - "};", /* }; */ NULL} - int indented; - {} - - char *a[] = {"aaa", "bbb", - "ccc", NULL}; - // here - - char *tab[] = {"aaa", - "xx", /* xx */}; /* asdf */ - int not_indented; - - { - do { - switch (bla) - { - case 1: if (foo) - bar; - } - } while (boo); - wrong; - } - - int foo, - bar; - int foo; - - #if defined(foo) \ - && defined(bar) - char * xx = "asdf\ - foo\ - bor"; - int x; - - char *foo = "asdf\ - asdf\ - asdf", - *bar; - - void f() - { - #if defined(foo) \ - && defined(bar) - char *foo = "asdf\ - asdf\ - asdf", - *bar; - { - int i; - char *foo = "asdf\ - asdf\ - asdf", - *bar; - } - #endif - } - #endif - - int y; // comment - // comment - - // comment - - { - Constructor(int a, - int b ) : BaseClass(a) - { - } - } - - void foo() - { - char one, - two; - struct bla piet, - jan; - enum foo kees, - jannie; - static unsigned sdf, - krap; - unsigned int piet, - jan; - int - kees, - jan; - } - - { - t(int f, - int d); // ) - d(); - } - - Constructor::Constructor(int a, - int b - ) : - BaseClass(a, - b, - c), - mMember(b), - { - } - - Constructor::Constructor(int a, - int b ) : - BaseClass(a) - { - } - - Constructor::Constructor(int a, - int b ) /*x*/ : /*x*/ BaseClass(a), - member(b) - { - } - - A::A(int a, int b) - : aa(a), - bb(b), - cc(c) - { - } - - class CAbc : - public BaseClass1, - protected BaseClass2 - { - int Test() { return FALSE; } - int Test1() { return TRUE; } - - CAbc(int a, int b ) : - BaseClass(a) - { - switch(xxx) - { - case abc: - asdf(); - break; - - case 999: - baer(); - break; - } - } - - public: // <-- this was incorrectly indented before!! - void testfall(); - protected: - void testfall(); - }; - - class CAbc : public BaseClass1, - protected BaseClass2 - { - }; - - static struct - { - int a; - int b; - } variable[COUNT] = - { - { - 123, - 456 - }, - { - 123, - 456 - } - }; - - static struct - { - int a; - int b; - } variable[COUNT] = - { - { 123, 456 }, - { 123, 456 } - }; - - void asdf() /* ind_maxparen may cause trouble here */ - { - if ((0 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1)) break; - } - - foo() - { - a = cond ? foo() : asdf - + asdf; - - a = cond ? - foo() : asdf - + asdf; - } - - int main(void) - { - if (a) - if (b) - 2; - else 3; - next_line_of_code(); - } - - barry() - { - Foo::Foo (int one, - int two) - : something(4) - {} - } - - barry() - { - Foo::Foo (int one, int two) - : something(4) - {} - } - - Constructor::Constructor(int a, - int b - ) : - BaseClass(a, - b, - c), - mMember(b) - { - } - int main () - { - if (lala) - do - ++(*lolo); - while (lili - && lele); - lulu; - } - - int main () - { - switch (c) - { - case 'c': if (cond) - { - } - } - } - - main() - { - (void) MyFancyFuasdfadsfnction( - argument); - } - - main() - { - char foo[] = "/*"; - /* as - df */ - hello - } - - /* valid namespaces with normal indent */ - namespace - { - { - 111111111111; - } - } - namespace /* test */ - { - 11111111111111111; - } - namespace // test - { - 111111111111111111; - } - namespace - { - 111111111111111111; - } - namespace test - { - 111111111111111111; - } - namespace{ - 111111111111111111; - } - namespace test{ - 111111111111111111; - } - namespace { - 111111111111111111; - } - namespace test { - 111111111111111111; - namespace test2 { - 22222222222222222; - } - } - inline namespace { - 111111111111111111; - } - inline /* test */ namespace { - 111111111111111111; - } - inline/* test */namespace { - 111111111111111111; - } - - /* invalid namespaces use block indent */ - namespace test test2 { - 111111111111111111111; - } - namespace11111111111 { - 111111111111; - } - namespace() { - 1111111111111; - } - namespace() - { - 111111111111111111; - } - namespace test test2 - { - 1111111111111111111; - } - namespace111111111 - { - 111111111111111111; - } - inlinenamespace { - 111111111111111111; - } - - void getstring() { - /* Raw strings */ - const char* s = R"( - test { - # comment - field: 123 - } - )"; - } - - void getstring() { - const char* s = R"foo( - test { - # comment - field: 123 - } - )foo"; - } - - { - int a[4] = { - [0] = 0, - [1] = 1, - [2] = 2, - [3] = 3, - }; - } - - { - a = b[2] - + 3; - } - - { - if (1) - /* aaaaa - * bbbbb - */ - a = 1; - } - - void func() - { - switch (foo) - { - case (bar): - if (baz()) - quux(); - break; - case (shmoo): - if (!bar) - { - } - case (foo1): - switch (bar) - { - case baz: - baz_f(); - break; - } - break; - default: - baz(); - baz(); - break; - } - } - - /* end of AUTO */ - [CODE] - - call append(0, code) - normal gg - call search('start of AUTO') - exe "normal =/end of AUTO\" - - let expected =<< trim [CODE] - /* start of AUTO matically checked vim: set ts=4 : */ - { - if (test) - cmd1; - cmd2; - } - - { - if (test) - cmd1; - else - cmd2; - } - - { - if (test) - { - cmd1; - cmd2; - } - } - - { - if (test) - { - cmd1; - else - } - } - - { - while (this) - if (test) - cmd1; - cmd2; - } - - { - while (this) - if (test) - cmd1; - else - cmd2; - } - - { - if (test) - { - cmd; - } - - if (test) - cmd; - } - - { - if (test) { - cmd; - } - - if (test) cmd; - } - - { - cmd1; - for (blah) - while (this) - if (test) - cmd2; - cmd3; - } - - { - cmd1; - for (blah) - while (this) - if (test) - cmd2; - cmd3; - - if (test) - { - cmd1; - cmd2; - cmd3; - } - } - - - /* Test for 'cindent' do/while mixed with if/else: */ - - { - do - if (asdf) - asdfasd; - while (cond); - - do - if (asdf) - while (asdf) - asdf; - while (asdf); - } - - /* Test for 'cindent' with two ) on a continuation line */ - { - if (asdfasdf;asldkfj asdlkfj as;ldkfj sal;d - aal;sdkjf ( ;asldfkja;sldfk - al;sdjfka ;slkdf ) sa;ldkjfsa dlk;) - line up here; - } - - - /* C++ tests: */ - - // foo() these three lines should remain in column 0 - // { - // } - - /* Test for continuation and unterminated lines: */ - { - i = 99 + 14325 + - 21345 + - 21345 + - 21345 + ( 21345 + - 21345) + - 2345 + - 1234; - c = 1; - } - - /* - testje for indent with empty line - - here */ - - { - if (testing && - not a joke || - line up here) - hay; - if (testing && - (not a joke || testing - )line up here) - hay; - if (testing && - (not a joke || testing - line up here)) - hay; - } - - - { - switch (c) - { - case xx: - do - if (asdf) - do - asdfasdf; - while (asdf); - else - asdfasdf; - while (cond); - case yy: - case xx: - case zz: - testing; - } - } - - { - if (cond) { - foo; - } - else - { - bar; - } - } - - { - if (alskdfj ;alsdkfjal;skdjf (;sadlkfsa ;dlkf j;alksdfj ;alskdjf - alsdkfj (asldk;fj - awith cino=(0 ;lf this one goes to below the paren with == - ;laksjfd ;lsakdjf ;alskdf asd) - asdfasdf;))) - asdfasdf; - } - - int - func(a, b) - int a; - int c; - { - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3) - ) - } - - { - while (asd) - { - if (asdf) - if (test) - if (that) - { - if (asdf) - do - cdasd; - while (as - df); - } - else - if (asdf) - asdf; - else - asdf; - asdf; - } - } - - { - s = "/*"; b = ';' - s = "/*"; b = ';'; - a = b; - } - - { - switch (a) - { - case a: - switch (t) - { - case 1: - cmd; - break; - case 2: - cmd; - break; - } - cmd; - break; - case b: - { - int i; - cmd; - } - break; - case c: { - int i; - cmd; - } - case d: if (cond && - test) { /* this line doesn't work right */ - int i; - cmd; - } - break; - } - } - - { - if (!(vim_strchr(p_cpo, CPO_BUFOPTGLOB) != NULL && entering) && - (bp_to->b_p_initialized || - (!entering && vim_strchr(p_cpo, CPO_BUFOPT) != NULL))) - return; - label : - asdf = asdf ? - asdf : asdf; - asdf = asdf ? - asdf: asdf; - } - - /* Special Comments : This function has the added complexity (compared */ - /* : to addtolist) of having to check for a detail */ - /* : texture and add that to the list first. */ - - char *(array[100]) = { - "testje", - "foo", - "bar", - } - - enum soppie - { - yes = 0, - no, - maybe - }; - - typedef enum soppie - { - yes = 0, - no, - maybe - }; - - static enum - { - yes = 0, - no, - maybe - } soppie; - - public static enum - { - yes = 0, - no, - maybe - } soppie; - - static private enum - { - yes = 0, - no, - maybe - } soppie; - - { - int a, - b; - } - - { - struct Type - { - int i; - char *str; - } var[] = - { - 0, "zero", - 1, "one", - 2, "two", - 3, "three" - }; - - float matrix[3][3] = - { - { - 0, - 1, - 2 - }, - { - 3, - 4, - 5 - }, - { - 6, - 7, - 8 - } - }; - } - - { - /* blah ( blah */ - /* where does this go? */ - - /* blah ( blah */ - cmd; - - func(arg1, - /* comment */ - arg2); - a; - { - b; - { - c; /* Hey, NOW it indents?! */ - } - } - - { - func(arg1, - arg2, - arg3); - /* Hey, what am I doing here? Is this coz of the ","? */ - } - } - - main () - { - if (cond) - { - a = b; - } - if (cond) { - a = c; - } - if (cond) - a = d; - return; - } - - { - case 2: if (asdf && - asdfasdf) - aasdf; - a = 9; - case 3: if (asdf) - aasdf; - a = 9; - case 4: x = 1; - y = 2; - - label: if (asdf) - here; - - label: if (asdf && - asdfasdf) - { - } - - label: if (asdf && - asdfasdf) { - there; - } - - label: if (asdf && - asdfasdf) - there; - } - - { - /* - hello with ":set comments= cino=c5" - */ - - /* - hello with ":set comments= cino=" - */ - } - - - { - if (a < b) { - a = a + 1; - } else - a = a + 2; - - if (a) - do { - testing; - } while (asdfasdf); - a = b + 1; - asdfasdf - } - - { - for ( int i = 0; - i < 10; i++ ) - { - } - i = 0; - } - - class bob - { - int foo() {return 1;} - int bar; - } - - main() - { - while(1) - if (foo) - { - bar; - } - else { - asdf; - } - misplacedline; - } - - { - if (clipboard.state == SELECT_DONE - && ((row == clipboard.start.lnum - && col >= clipboard.start.col) - || row > clipboard.start.lnum)) - } - - { - if (1) {i += 4;} - where_am_i; - return 0; - } - - { - { - } // sdf(asdf - if (asdf) - asd; - } - - { - label1: - label2: - } - - { - int fooRet = foo(pBar1, false /*fKB*/, - true /*fPTB*/, 3 /*nT*/, false /*fDF*/); - f() { - for ( i = 0; - i < m; - /* c */ i++ ) { - a = b; - } - } - } - - { - f1(/*comment*/); - f2(); - } - - { - do { - if (foo) { - } else - ; - } while (foo); - foo(); // was wrong - } - - int x; // no extra indent because of the ; - void func() - { - } - - char *tab[] = {"aaa", - "};", /* }; */ NULL} - int indented; - {} - - char *a[] = {"aaa", "bbb", - "ccc", NULL}; - // here - - char *tab[] = {"aaa", - "xx", /* xx */}; /* asdf */ - int not_indented; - - { - do { - switch (bla) - { - case 1: if (foo) - bar; - } - } while (boo); - wrong; - } - - int foo, - bar; - int foo; - - #if defined(foo) \ - && defined(bar) - char * xx = "asdf\ - foo\ - bor"; - int x; - - char *foo = "asdf\ - asdf\ - asdf", - *bar; - - void f() - { - #if defined(foo) \ - && defined(bar) - char *foo = "asdf\ - asdf\ - asdf", - *bar; - { - int i; - char *foo = "asdf\ - asdf\ - asdf", - *bar; - } - #endif - } - #endif - - int y; // comment - // comment - - // comment - - { - Constructor(int a, - int b ) : BaseClass(a) - { - } - } - - void foo() - { - char one, - two; - struct bla piet, - jan; - enum foo kees, - jannie; - static unsigned sdf, - krap; - unsigned int piet, - jan; - int - kees, - jan; - } - - { - t(int f, - int d); // ) - d(); - } - - Constructor::Constructor(int a, - int b - ) : - BaseClass(a, - b, - c), - mMember(b), - { - } - - Constructor::Constructor(int a, - int b ) : - BaseClass(a) - { - } - - Constructor::Constructor(int a, - int b ) /*x*/ : /*x*/ BaseClass(a), - member(b) - { - } - - A::A(int a, int b) - : aa(a), - bb(b), - cc(c) - { - } - - class CAbc : - public BaseClass1, - protected BaseClass2 - { - int Test() { return FALSE; } - int Test1() { return TRUE; } - - CAbc(int a, int b ) : - BaseClass(a) - { - switch(xxx) - { - case abc: - asdf(); - break; - - case 999: - baer(); - break; - } - } - - public: // <-- this was incorrectly indented before!! - void testfall(); - protected: - void testfall(); - }; - - class CAbc : public BaseClass1, - protected BaseClass2 - { - }; - - static struct - { - int a; - int b; - } variable[COUNT] = - { - { - 123, - 456 - }, - { - 123, - 456 - } - }; - - static struct - { - int a; - int b; - } variable[COUNT] = - { - { 123, 456 }, - { 123, 456 } - }; - - void asdf() /* ind_maxparen may cause trouble here */ - { - if ((0 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1 - && 1)) break; - } - - foo() - { - a = cond ? foo() : asdf - + asdf; - - a = cond ? - foo() : asdf - + asdf; - } - - int main(void) - { - if (a) - if (b) - 2; - else 3; - next_line_of_code(); - } - - barry() - { - Foo::Foo (int one, - int two) - : something(4) - {} - } - - barry() - { - Foo::Foo (int one, int two) - : something(4) - {} - } - - Constructor::Constructor(int a, - int b - ) : - BaseClass(a, - b, - c), - mMember(b) - { - } - int main () - { - if (lala) - do - ++(*lolo); - while (lili - && lele); - lulu; - } - - int main () - { - switch (c) - { - case 'c': if (cond) - { - } - } - } - - main() - { - (void) MyFancyFuasdfadsfnction( - argument); - } - - main() - { - char foo[] = "/*"; - /* as - df */ - hello - } - - /* valid namespaces with normal indent */ - namespace - { - { - 111111111111; - } - } - namespace /* test */ - { - 11111111111111111; - } - namespace // test - { - 111111111111111111; - } - namespace - { - 111111111111111111; - } - namespace test - { - 111111111111111111; - } - namespace{ - 111111111111111111; - } - namespace test{ - 111111111111111111; - } - namespace { - 111111111111111111; - } - namespace test { - 111111111111111111; - namespace test2 { - 22222222222222222; - } - } - inline namespace { - 111111111111111111; - } - inline /* test */ namespace { - 111111111111111111; - } - inline/* test */namespace { - 111111111111111111; - } - - /* invalid namespaces use block indent */ - namespace test test2 { - 111111111111111111111; - } - namespace11111111111 { - 111111111111; - } - namespace() { - 1111111111111; - } - namespace() - { - 111111111111111111; - } - namespace test test2 - { - 1111111111111111111; - } - namespace111111111 - { - 111111111111111111; - } - inlinenamespace { - 111111111111111111; - } - - void getstring() { - /* Raw strings */ - const char* s = R"( - test { - # comment - field: 123 - } - )"; - } - - void getstring() { - const char* s = R"foo( - test { - # comment - field: 123 - } - )foo"; - } - - { - int a[4] = { - [0] = 0, - [1] = 1, - [2] = 2, - [3] = 3, - }; - } - - { - a = b[2] - + 3; - } - - { - if (1) - /* aaaaa - * bbbbb - */ - a = 1; - } - - void func() - { - switch (foo) - { - case (bar): - if (baz()) - quux(); - break; - case (shmoo): - if (!bar) - { - } - case (foo1): - switch (bar) - { - case baz: - baz_f(); - break; - } - break; - default: - baz(); - baz(); - break; - } - } - - /* end of AUTO */ - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_2() - new - setl cindent ts=4 sw=4 - setl tw=0 noai fo=croq - let &wm = &columns - 20 - - let code =<< trim [CODE] - { - - /* this is - * a real serious important big - * comment - */ - /* insert " about life, the universe, and the rest" after "serious" */ - } - [CODE] - - call append(0, code) - normal gg - call search('serious', 'e') - normal a about life, the universe, and the rest - - let expected =<< trim [CODE] - { - - /* this is - * a real serious - * about life, the - * universe, and the - * rest important big - * comment - */ - /* insert " about life, the universe, and the rest" after "serious" */ - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - set wm& - enew! | close -endfunc - -func Test_cindent_3() - new - setl nocindent ts=4 sw=4 - - let code =<< trim [CODE] - { - /* - * Testing for comments, without 'cin' set - */ - - /* - * what happens here? - */ - - /* - the end of the comment, try inserting a line below */ - - /* how about - this one */ - } - [CODE] - - call append(0, code) - normal gg - call search('comments') - normal joabout life - call search('happens') - normal jothere - call search('below') - normal oline - call search('this') - normal Ohello - - let expected =<< trim [CODE] - { - /* - * Testing for comments, without 'cin' set - */ - about life - - /* - * what happens here? - */ - there - - /* - the end of the comment, try inserting a line below */ - line - - /* how about - hello - this one */ - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_4() - new - setl cindent ts=4 sw=4 - - let code =<< trim [CODE] - { - var = this + that + vec[0] * vec[0] - + vec[1] * vec[1] - + vec2[2] * vec[2]; - } - [CODE] - - call append(0, code) - normal gg - call search('vec2') - normal == - - let expected =<< trim [CODE] - { - var = this + that + vec[0] * vec[0] - + vec[1] * vec[1] - + vec2[2] * vec[2]; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_5() - new - setl cindent ts=4 sw=4 - setl cino=}4 - - let code =<< trim [CODE] - { - asdf asdflkajds f; - if (tes & ting) { - asdf asdf asdf ; - asdfa sdf asdf; - } - testing1; - if (tes & ting) - { - asdf asdf asdf ; - asdfa sdf asdf; - } - testing2; - } - [CODE] - - call append(0, code) - normal gg - call search('testing1') - exe "normal k2==/testing2\" - normal k2== - - let expected =<< trim [CODE] - { - asdf asdflkajds f; - if (tes & ting) { - asdf asdf asdf ; - asdfa sdf asdf; - } - testing1; - if (tes & ting) - { - asdf asdf asdf ; - asdfa sdf asdf; - } - testing2; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_6() - new - setl cindent ts=4 sw=4 - setl cino=(0,)20 - - let code =<< trim [CODE] - main ( int first_par, /* - * Comment for - * first par - */ - int second_par /* - * Comment for - * second par - */ - ) - { - func( first_par, /* - * Comment for - * first par - */ - second_par /* - * Comment for - * second par - */ - ); - - } - [CODE] - - call append(0, code) - normal gg - call search('main') - normal =][ - - let expected =<< trim [CODE] - main ( int first_par, /* - * Comment for - * first par - */ - int second_par /* - * Comment for - * second par - */ - ) - { - func( first_par, /* - * Comment for - * first par - */ - second_par /* - * Comment for - * second par - */ - ); - - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_7() - new - setl cindent ts=4 sw=4 - setl cino=es,n0s - - let code =<< trim [CODE] - main(void) - { - /* Make sure that cino=X0s is not parsed like cino=Xs. */ - if (cond) - foo(); - else - { - bar(); - } - } - [CODE] - - call append(0, code) - normal gg - call search('main') - normal =][ - - let expected =<< trim [CODE] - main(void) - { - /* Make sure that cino=X0s is not parsed like cino=Xs. */ - if (cond) - foo(); - else - { - bar(); - } - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_8() - new - setl cindent ts=4 sw=4 - setl cino= - - let code =<< trim [CODE] - - { - do - { - if () - { - if () - asdf; - else - asdf; - } - } while (); - cmd; /* this should go under the } */ - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - - { - do - { - if () - { - if () - asdf; - else - asdf; - } - } while (); - cmd; /* this should go under the } */ - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_9() - new - setl cindent ts=4 sw=4 - - let code =<< trim [CODE] - - void f() - { - if ( k() ) { - l(); - - } else { /* Start (two words) end */ - m(); - } - - n(); - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - - void f() - { - if ( k() ) { - l(); - - } else { /* Start (two words) end */ - m(); - } - - n(); - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_10() - new - setl cindent ts=4 sw=4 - setl cino={s,e-s - - let code =<< trim [CODE] - - void f() - { - if ( k() ) - { - l(); - } else { /* Start (two words) end */ - m(); - } - n(); /* should be under the if () */ - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - - void f() - { - if ( k() ) - { - l(); - } else { /* Start (two words) end */ - m(); - } - n(); /* should be under the if () */ - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_11() - new - setl cindent ts=4 sw=4 - setl cino={s,fs - - let code =<< trim [CODE] - void bar(void) - { - static array[2][2] = - { - { 1, 2 }, - { 3, 4 }, - } - - while (a) - { - foo(&a); - } - - { - int a; - { - a = a + 1; - } - } - b = a; - } - - void func(void) - { - a = 1; - { - b = 2; - } - c = 3; - d = 4; - } - /* foo */ - [CODE] - - call append(0, code) - normal gg - exe "normal ]]=/ foo\" - - let expected =<< trim [CODE] - void bar(void) - { - static array[2][2] = - { - { 1, 2 }, - { 3, 4 }, - } - - while (a) - { - foo(&a); - } - - { - int a; - { - a = a + 1; - } - } - b = a; - } - - void func(void) - { - a = 1; - { - b = 2; - } - c = 3; - d = 4; - } - /* foo */ - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_12() - new - setl cindent ts=4 sw=4 - setl cino= - - let code =<< trim [CODE] - a() - { - do { - a = a + - a; - } while ( a ); /* add text under this line */ - if ( a ) - a; - } - [CODE] - - call append(0, code) - normal gg - call search('while') - normal ohere - - let expected =<< trim [CODE] - a() - { - do { - a = a + - a; - } while ( a ); /* add text under this line */ - here - if ( a ) - a; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_13() - new - setl cindent ts=4 sw=4 - setl cino= com= - - let code =<< trim [CODE] - a() - { - label1: - /* hmm */ - // comment - } - [CODE] - - call append(0, code) - normal gg - call search('comment') - exe "normal olabel2: b();\rlabel3 /* post */:\r/* pre */ label4:\r" . - \ "f(/*com*/);\rif (/*com*/)\rcmd();" - - let expected =<< trim [CODE] - a() - { - label1: - /* hmm */ - // comment - label2: b(); - label3 /* post */: - /* pre */ label4: - f(/*com*/); - if (/*com*/) - cmd(); - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_14() - new - setl cindent ts=4 sw=4 - setl comments& comments^=s:/*,m:**,ex:*/ - - let code =<< trim [CODE] - /* - * A simple comment - */ - - /* - ** A different comment - */ - [CODE] - - call append(0, code) - normal gg - call search('simple') - normal =5j - - let expected =<< trim [CODE] - /* - * A simple comment - */ - - /* - ** A different comment - */ - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_15() - new - setl cindent ts=4 sw=4 - setl cino=c0 - setl comments& comments-=s1:/* comments^=s0:/* - - let code =<< trim [CODE] - void f() - { - - /********* - A comment. - *********/ - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void f() - { - - /********* - A comment. - *********/ - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_16() - new - setl cindent ts=4 sw=4 - setl cino=c0,C1 - setl comments& comments-=s1:/* comments^=s0:/* - - let code =<< trim [CODE] - void f() - { - - /********* - A comment. - *********/ - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void f() - { - - /********* - A comment. - *********/ - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_17() - new - setl cindent ts=4 sw=4 - setl cino= - - let code =<< trim [CODE] - void f() - { - c = c1 && - ( - c2 || - c3 - ) && c4; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void f() - { - c = c1 && - ( - c2 || - c3 - ) && c4; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_18() - new - setl cindent ts=4 sw=4 - setl cino=(s - - let code =<< trim [CODE] - void f() - { - c = c1 && - ( - c2 || - c3 - ) && c4; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void f() - { - c = c1 && - ( - c2 || - c3 - ) && c4; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_19() - new - setl cindent ts=4 sw=4 - set cino=(s,U1 - - let code =<< trim [CODE] - void f() - { - c = c1 && - ( - c2 || - c3 - ) && c4; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void f() - { - c = c1 && - ( - c2 || - c3 - ) && c4; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_20() - new - setl cindent ts=4 sw=4 - setl cino=(0 - - let code =<< trim [CODE] - void f() - { - if ( c1 - && ( c2 - || c3)) - foo; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void f() - { - if ( c1 - && ( c2 - || c3)) - foo; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_21() - new - setl cindent ts=4 sw=4 - setl cino=(0,w1 - - let code =<< trim [CODE] - void f() - { - if ( c1 - && ( c2 - || c3)) - foo; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void f() - { - if ( c1 - && ( c2 - || c3)) - foo; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_22() - new - setl cindent ts=4 sw=4 - setl cino=(s - - let code =<< trim [CODE] - void f() - { - c = c1 && ( - c2 || - c3 - ) && c4; - if ( - c1 && c2 - ) - foo; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void f() - { - c = c1 && ( - c2 || - c3 - ) && c4; - if ( - c1 && c2 - ) - foo; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_23() - new - setl cindent ts=4 sw=4 - setl cino=(s,m1 - - let code =<< trim [CODE] - void f() - { - c = c1 && ( - c2 || - c3 - ) && c4; - if ( - c1 && c2 - ) - foo; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void f() - { - c = c1 && ( - c2 || - c3 - ) && c4; - if ( - c1 && c2 - ) - foo; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_24() - new - setl cindent ts=4 sw=4 - setl cino=b1 - - let code =<< trim [CODE] - void f() - { - switch (x) - { - case 1: - a = b; - break; - default: - a = 0; - break; - } - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void f() - { - switch (x) - { - case 1: - a = b; - break; - default: - a = 0; - break; - } - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_25() - new - setl cindent ts=4 sw=4 - setl cino=(0,W5 - - let code =<< trim [CODE] - void f() - { - invokeme( - argu, - ment); - invokeme( - argu, - ment - ); - invokeme(argu, - ment - ); - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void f() - { - invokeme( - argu, - ment); - invokeme( - argu, - ment - ); - invokeme(argu, - ment - ); - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_26() - new - setl cindent ts=4 sw=4 - setl cino=/6 - - let code =<< trim [CODE] - void f() - { - statement; - // comment 1 - // comment 2 - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void f() - { - statement; - // comment 1 - // comment 2 - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_27() - new - setl cindent ts=4 sw=4 - setl cino= - - let code =<< trim [CODE] - void f() - { - statement; - // comment 1 - // comment 2 - } - [CODE] - - call append(0, code) - normal gg - exe "normal ]]/comment 1/+1\==" - - let expected =<< trim [CODE] - void f() - { - statement; - // comment 1 - // comment 2 - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_28() - new - setl cindent ts=4 sw=4 - setl cino=g0 - - let code =<< trim [CODE] - class CAbc - { - int Test() { return FALSE; } - - public: // comment - void testfall(); - protected: - void testfall(); - }; - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - class CAbc - { - int Test() { return FALSE; } - - public: // comment - void testfall(); - protected: - void testfall(); - }; - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_29() - new - setl cindent ts=4 sw=4 - setl cino=(0,gs,hs - - let code =<< trim [CODE] - class Foo : public Bar - { - public: - virtual void method1(void) = 0; - virtual void method2(int arg1, - int arg2, - int arg3) = 0; - }; - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - class Foo : public Bar - { - public: - virtual void method1(void) = 0; - virtual void method2(int arg1, - int arg2, - int arg3) = 0; - }; - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_30() - new - setl cindent ts=4 sw=4 - setl cino=+20 - - let code =<< [CODE] - void -foo() -{ - if (a) - { - } else - asdf; -} -[CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< [CODE] - void -foo() -{ - if (a) - { - } else - asdf; -} - -[CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_31() - new - setl cindent ts=4 sw=4 - setl cino=(0,W2s - - let code =<< trim [CODE] - - { - averylongfunctionnamelongfunctionnameaverylongfunctionname()->asd( - asdasdf, - func(asdf, - asdfadsf), - asdfasdf - ); - - /* those are ugly, but consequent */ - - func()->asd(asdasdf, - averylongfunctionname( - abc, - dec)->averylongfunctionname( - asdfadsf, - asdfasdf, - asdfasdf, - ), - func(asdfadf, - asdfasdf - ), - asdasdf - ); - - averylongfunctionnameaverylongfunctionnameavery()->asd(fasdf( - abc, - dec)->asdfasdfasdf( - asdfadsf, - asdfasdf, - asdfasdf, - ), - func(asdfadf, - asdfasdf), - asdasdf - ); - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - - { - averylongfunctionnamelongfunctionnameaverylongfunctionname()->asd( - asdasdf, - func(asdf, - asdfadsf), - asdfasdf - ); - - /* those are ugly, but consequent */ - - func()->asd(asdasdf, - averylongfunctionname( - abc, - dec)->averylongfunctionname( - asdfadsf, - asdfasdf, - asdfasdf, - ), - func(asdfadf, - asdfasdf - ), - asdasdf - ); - - averylongfunctionnameaverylongfunctionnameavery()->asd(fasdf( - abc, - dec)->asdfasdfasdf( - asdfadsf, - asdfasdf, - asdfasdf, - ), - func(asdfadf, - asdfasdf), - asdasdf - ); - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_32() - new - setl cindent ts=4 sw=4 - setl cino=M1 - - let code =<< trim [CODE] - int main () - { - if (cond1 && - cond2 - ) - foo; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - int main () - { - if (cond1 && - cond2 - ) - foo; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_33() - new - setl cindent ts=4 sw=4 - setl cino=(0,ts - - let code =<< trim [CODE] - void func(int a - #if defined(FOO) - , int b - , int c - #endif - ) - { - } - [CODE] - - call append(0, code) - normal gg - normal 2j=][ - - let expected =<< trim [CODE] - void func(int a - #if defined(FOO) - , int b - , int c - #endif - ) - { - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_34() - new - setl cindent ts=4 sw=4 - setl cino=(0 - - let code =<< trim [CODE] - - void - func(int a - #if defined(FOO) - , int b - , int c - #endif - ) - { - } - [CODE] - - call append(0, code) - normal gg - normal =][ - - let expected =<< trim [CODE] - - void - func(int a - #if defined(FOO) - , int b - , int c - #endif - ) - { - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_35() - new - setl cindent ts=4 sw=4 - setl cino& - - let code =<< trim [CODE] - void func(void) - { - if(x==y) - if(y==z) - foo=1; - else { bar=1; - baz=2; - } - printf("Foo!\n"); - } - - void func1(void) - { - char* tab[] = {"foo", "bar", - "baz", "quux", - "this line used", "to be indented incorrectly"}; - foo(); - } - - void func2(void) - { - int tab[] = - {1, 2, - 3, 4, - 5, 6}; - - printf("This line used to be indented incorrectly.\n"); - } - - int foo[] - #ifdef BAR - - = { 1, 2, 3, - 4, 5, 6 } - - #endif - ; - int baz; - - void func3(void) - { - int tab[] = { - 1, 2, - 3, 4, - 5, 6}; - - printf("Don't you dare indent this line incorrectly!\n"); - } - - void - func4(a, b, - c) - int a; - int b; - int c; - { - } - - void - func5( - int a, - int b) - { - } - - void - func6( - int a) - { - } - [CODE] - - call append(0, code) - normal gg - normal ]]=7][ - - let expected =<< trim [CODE] - void func(void) - { - if(x==y) - if(y==z) - foo=1; - else { bar=1; - baz=2; - } - printf("Foo!\n"); - } - - void func1(void) - { - char* tab[] = {"foo", "bar", - "baz", "quux", - "this line used", "to be indented incorrectly"}; - foo(); - } - - void func2(void) - { - int tab[] = - {1, 2, - 3, 4, - 5, 6}; - - printf("This line used to be indented incorrectly.\n"); - } - - int foo[] - #ifdef BAR - - = { 1, 2, 3, - 4, 5, 6 } - - #endif - ; - int baz; - - void func3(void) - { - int tab[] = { - 1, 2, - 3, 4, - 5, 6}; - - printf("Don't you dare indent this line incorrectly!\n"); - } - - void - func4(a, b, - c) - int a; - int b; - int c; - { - } - - void - func5( - int a, - int b) - { - } - - void - func6( - int a) - { - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_36() - new - setl cindent ts=4 sw=4 - setl cino& - setl cino+=l1 - - let code =<< trim [CODE] - void func(void) - { - int tab[] = - { - 1, 2, 3, - 4, 5, 6}; - - printf("Indent this line correctly!\n"); - - switch (foo) - { - case bar: - printf("bar"); - break; - case baz: { - printf("baz"); - break; - } - case quux: - printf("But don't break the indentation of this instruction\n"); - break; - } - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void func(void) - { - int tab[] = - { - 1, 2, 3, - 4, 5, 6}; - - printf("Indent this line correctly!\n"); - - switch (foo) - { - case bar: - printf("bar"); - break; - case baz: { - printf("baz"); - break; - } - case quux: - printf("But don't break the indentation of this instruction\n"); - break; - } - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_37() - new - setl cindent ts=4 sw=4 - setl cino& - - let code =<< trim [CODE] - void func(void) - { - cout << "a" - << "b" - << ") :" - << "c"; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void func(void) - { - cout << "a" - << "b" - << ") :" - << "c"; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_38() - new - setl cindent ts=4 sw=4 - setl com=s1:/*,m:*,ex:*/ - - let code =<< trim [CODE] - void func(void) - { - /* - * This is a comment. - */ - } - [CODE] - - call append(0, code) - normal gg - normal ]]3jofoo(); - - let expected =<< trim [CODE] - void func(void) - { - /* - * This is a comment. - */ - foo(); - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_39() - new - setl cindent ts=4 sw=4 - setl cino& - - let code =<< trim [CODE] - void func(void) - { - for (int i = 0; i < 10; ++i) - if (i & 1) { - foo(1); - } else - foo(0); - baz(); - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void func(void) - { - for (int i = 0; i < 10; ++i) - if (i & 1) { - foo(1); - } else - foo(0); - baz(); - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_40() - new - setl cindent ts=4 sw=4 - setl cino=k2s,(0 - - let code =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - - if ( c1 - && ( c2 - || c3)) - foo; - func( c1 - && ( c2 - || c3)) - foo; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - - if ( c1 - && ( c2 - || c3)) - foo; - func( c1 - && ( c2 - || c3)) - foo; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_41() - new - setl cindent ts=4 sw=4 - setl cino=k2s,(s - - let code =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - - if ( c1 - && ( c2 - || c3)) - foo; - func( c1 - && ( c2 - || c3)) - foo; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - - if ( c1 - && ( c2 - || c3)) - foo; - func( c1 - && ( c2 - || c3)) - foo; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_42() - new - setl cindent ts=4 sw=4 - setl cino=k2s,(s,U1 - - let code =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - if (c123456789 - && (c22345 - || c3)) - printf("foo\n"); - - c = c1 && - ( - c2 || - c3 - ) && c4; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - if (c123456789 - && (c22345 - || c3)) - printf("foo\n"); - - c = c1 && - ( - c2 || - c3 - ) && c4; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_43() - new - setl cindent ts=4 sw=4 - setl cino=k2s,(0,W4 - - let code =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - if (c123456789 - && (c22345 - || c3)) - printf("foo\n"); - - if ( c1 - && ( c2 - || c3)) - foo; - - a_long_line( - argument, - argument); - a_short_line(argument, - argument); - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - if (c123456789 - && (c22345 - || c3)) - printf("foo\n"); - - if ( c1 - && ( c2 - || c3)) - foo; - - a_long_line( - argument, - argument); - a_short_line(argument, - argument); - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_44() - new - setl cindent ts=4 sw=4 - setl cino=k2s,u2 - - let code =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - if (c123456789 - && (c22345 - || c3)) - printf("foo\n"); - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - if (c123456789 - && (c22345 - || c3)) - printf("foo\n"); - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_45() - new - setl cindent ts=4 sw=4 - setl cino=k2s,(0,w1 - - let code =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - if (c123456789 - && (c22345 - || c3)) - printf("foo\n"); - - if ( c1 - && ( c2 - || c3)) - foo; - func( c1 - && ( c2 - || c3)) - foo; - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - if (c123456789 - && (c22345 - || c3)) - printf("foo\n"); - - if ( c1 - && ( c2 - || c3)) - foo; - func( c1 - && ( c2 - || c3)) - foo; - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_46() - new - setl cindent ts=4 sw=4 - setl cino=k2,(s - - let code =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - } - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - void func(void) - { - if (condition1 - && condition2) - action(); - function(argument1 - && argument2); - - if (c1 && (c2 || - c3)) - foo; - if (c1 && - (c2 || c3)) - { - } - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_47() - new - setl cindent ts=4 sw=4 - setl cino=N-s - - let code =<< trim [CODE] - NAMESPACESTART - /* valid namespaces with normal indent */ - namespace - { - { - 111111111111; - } - } - namespace /* test */ - { - 11111111111111111; - } - namespace // test - { - 111111111111111111; - } - namespace - { - 111111111111111111; - } - namespace test - { - 111111111111111111; - } - namespace test::cpp17 - { - 111111111111111111; - } - namespace ::incorrectcpp17 - { - 111111111111111111; - } - namespace test::incorrectcpp17:: - { - 111111111111111111; - } - namespace test:incorrectcpp17 - { - 111111111111111111; - } - namespace test:::incorrectcpp17 - { - 111111111111111111; - } - namespace{ - 111111111111111111; - } - namespace test{ - 111111111111111111; - } - namespace { - 111111111111111111; - } - namespace test { - 111111111111111111; - namespace test2 { - 22222222222222222; - } - } - inline namespace { - 111111111111111111; - } - inline /* test */ namespace { - 111111111111111111; - } - inline/* test */namespace { - 111111111111111111; - } - - /* invalid namespaces use block indent */ - namespace test test2 { - 111111111111111111111; - } - namespace11111111111 { - 111111111111; - } - namespace() { - 1111111111111; - } - namespace() - { - 111111111111111111; - } - namespace test test2 - { - 1111111111111111111; - } - namespace111111111 - { - 111111111111111111; - } - inlinenamespace { - 111111111111111111; - } - NAMESPACEEND - [CODE] - - call append(0, code) - normal gg - call search('^NAMESPACESTART') - exe "normal =/^NAMESPACEEND\n" - - let expected =<< trim [CODE] - NAMESPACESTART - /* valid namespaces with normal indent */ - namespace - { - { - 111111111111; - } - } - namespace /* test */ - { - 11111111111111111; - } - namespace // test - { - 111111111111111111; - } - namespace - { - 111111111111111111; - } - namespace test - { - 111111111111111111; - } - namespace test::cpp17 - { - 111111111111111111; - } - namespace ::incorrectcpp17 - { - 111111111111111111; - } - namespace test::incorrectcpp17:: - { - 111111111111111111; - } - namespace test:incorrectcpp17 - { - 111111111111111111; - } - namespace test:::incorrectcpp17 - { - 111111111111111111; - } - namespace{ - 111111111111111111; - } - namespace test{ - 111111111111111111; - } - namespace { - 111111111111111111; - } - namespace test { - 111111111111111111; - namespace test2 { - 22222222222222222; - } - } - inline namespace { - 111111111111111111; - } - inline /* test */ namespace { - 111111111111111111; - } - inline/* test */namespace { - 111111111111111111; - } - - /* invalid namespaces use block indent */ - namespace test test2 { - 111111111111111111111; - } - namespace11111111111 { - 111111111111; - } - namespace() { - 1111111111111; - } - namespace() - { - 111111111111111111; - } - namespace test test2 - { - 1111111111111111111; - } - namespace111111111 - { - 111111111111111111; - } - inlinenamespace { - 111111111111111111; - } - NAMESPACEEND - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_48() - new - setl cindent ts=4 sw=4 - setl cino=j1,J1 - - let code =<< trim [CODE] - JSSTART - var bar = { - foo: { - that: this, - some: ok, - }, - "bar":{ - a : 2, - b: "123abc", - x: 4, - "y": 5 - } - } - JSEND - [CODE] - - call append(0, code) - normal gg - call search('^JSSTART') - exe "normal =/^JSEND\n" - - let expected =<< trim [CODE] - JSSTART - var bar = { - foo: { - that: this, - some: ok, - }, - "bar":{ - a : 2, - b: "123abc", - x: 4, - "y": 5 - } - } - JSEND - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_49() - new - setl cindent ts=4 sw=4 - setl cino=j1,J1 - - let code =<< trim [CODE] - JSSTART - var foo = [ - 1, - 2, - 3 - ]; - JSEND - [CODE] - - call append(0, code) - normal gg - call search('^JSSTART') - exe "normal =/^JSEND\n" - - let expected =<< trim [CODE] - JSSTART - var foo = [ - 1, - 2, - 3 - ]; - JSEND - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_50() - new - setl cindent ts=4 sw=4 - setl cino=j1,J1 - - let code =<< trim [CODE] - JSSTART - function bar() { - var foo = [ - 1, - 2, - 3 - ]; - } - JSEND - [CODE] - - call append(0, code) - normal gg - call search('^JSSTART') - exe "normal =/^JSEND\n" - - let expected =<< trim [CODE] - JSSTART - function bar() { - var foo = [ - 1, - 2, - 3 - ]; - } - JSEND - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_51() - new - setl cindent ts=4 sw=4 - setl cino=j1,J1 - - let code =<< trim [CODE] - JSSTART - (function($){ - - if (cond && - cond) { - stmt; - } - window.something.left = - (width - 50 + offset) + "px"; - var class_name='myclass'; - - function private_method() { - } - - var public_method={ - method: function(options,args){ - private_method(); - } - } - - function init(options) { - - $(this).data(class_name+'_public',$.extend({},{ - foo: 'bar', - bar: 2, - foobar: [ - 1, - 2, - 3 - ], - callback: function(){ - return true; - } - }, options||{})); - } - - $.fn[class_name]=function() { - - var _arguments=arguments; - return this.each(function(){ - - var options=$(this).data(class_name+'_public'); - if (!options) { - init.apply(this,_arguments); - - } else { - var method=public_method[_arguments[0]]; - - if (typeof(method)!='function') { - console.log(class_name+' has no method "'+_arguments[0]+'"'); - return false; - } - _arguments[0]=options; - method.apply(this,_arguments); - } - }); - } - - })(jQuery); - JSEND - [CODE] - - call append(0, code) - normal gg - call search('^JSSTART') - exe "normal =/^JSEND\n" - - let expected =<< trim [CODE] - JSSTART - (function($){ - - if (cond && - cond) { - stmt; - } - window.something.left = - (width - 50 + offset) + "px"; - var class_name='myclass'; - - function private_method() { - } - - var public_method={ - method: function(options,args){ - private_method(); - } - } - - function init(options) { - - $(this).data(class_name+'_public',$.extend({},{ - foo: 'bar', - bar: 2, - foobar: [ - 1, - 2, - 3 - ], - callback: function(){ - return true; - } - }, options||{})); - } - - $.fn[class_name]=function() { - - var _arguments=arguments; - return this.each(function(){ - - var options=$(this).data(class_name+'_public'); - if (!options) { - init.apply(this,_arguments); - - } else { - var method=public_method[_arguments[0]]; - - if (typeof(method)!='function') { - console.log(class_name+' has no method "'+_arguments[0]+'"'); - return false; - } - _arguments[0]=options; - method.apply(this,_arguments); - } - }); - } - - })(jQuery); - JSEND - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_52() - new - setl cindent ts=4 sw=4 - setl cino=j1,J1 - - let code =<< trim [CODE] - JSSTART - function init(options) { - $(this).data(class_name+'_public',$.extend({},{ - foo: 'bar', - bar: 2, - foobar: [ - 1, - 2, - 3 - ], - callback: function(){ - return true; - } - }, options||{})); - } - JSEND - [CODE] - - call append(0, code) - normal gg - call search('^JSSTART') - exe "normal =/^JSEND\n" - - let expected =<< trim [CODE] - JSSTART - function init(options) { - $(this).data(class_name+'_public',$.extend({},{ - foo: 'bar', - bar: 2, - foobar: [ - 1, - 2, - 3 - ], - callback: function(){ - return true; - } - }, options||{})); - } - JSEND - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_53() - new - setl cindent ts=4 sw=4 - setl cino=j1,J1 - - let code =<< trim [CODE] - JSSTART - (function($){ - function init(options) { - $(this).data(class_name+'_public',$.extend({},{ - foo: 'bar', - bar: 2, - foobar: [ - 1, - 2, - 3 - ], - callback: function(){ - return true; - } - }, options||{})); - } - })(jQuery); - JSEND - [CODE] - - call append(0, code) - normal gg - call search('^JSSTART') - exe "normal =/^JSEND\n" - - let expected =<< trim [CODE] - JSSTART - (function($){ - function init(options) { - $(this).data(class_name+'_public',$.extend({},{ - foo: 'bar', - bar: 2, - foobar: [ - 1, - 2, - 3 - ], - callback: function(){ - return true; - } - }, options||{})); - } - })(jQuery); - JSEND - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_54() - new - setl cindent ts=4 sw=4 - setl cino=j1,J1,+2 - - let code =<< trim [CODE] - JSSTART - // Results of JavaScript indent - // 1 - (function(){ - var a = [ - 'a', - 'b', - 'c', - 'd', - 'e', - 'f', - 'g', - 'h', - 'i' - ]; - }()) - - // 2 - (function(){ - var a = [ - 0 + - 5 * - 9 * - 'a', - 'b', - 0 + - 5 * - 9 * - 'c', - 'd', - 'e', - 'f', - 'g', - 'h', - 'i' - ]; - }()) - - // 3 - (function(){ - var a = [ - 0 + - // comment 1 - 5 * - /* comment 2 */ - 9 * - 'a', - 'b', - 0 + - 5 * - 9 * - 'c', - 'd', - 'e', - 'f', - 'g', - 'h', - 'i' - ]; - }()) - - // 4 - { - var a = [ - 0, - 1 - ]; - var b; - var c; - } - - // 5 - { - var a = [ - [ - 0 - ], - 2, - 3 - ]; - } - - // 6 - { - var a = [ - [ - 0, - 1 - ], - 2, - 3 - ]; - } - - // 7 - { - var a = [ - // [ - 0, - // 1 - // ], - 2, - 3 - ]; - } - - // 8 - var x = [ - (function(){ - var a, - b, - c, - d, - e, - f, - g, - h, - i; - }) - ]; - - // 9 - var a = [ - 0 + - 5 * - 9 * - 'a', - 'b', - 0 + - 5 * - 9 * - 'c', - 'd', - 'e', - 'f', - 'g', - 'h', - 'i' - ]; - - // 10 - var a, - b, - c, - d, - e, - f, - g, - h, - i; - JSEND - [CODE] - - call append(0, code) - normal gg - call search('^JSSTART') - exe "normal =/^JSEND\n" - - let expected =<< trim [CODE] - JSSTART - // Results of JavaScript indent - // 1 - (function(){ - var a = [ - 'a', - 'b', - 'c', - 'd', - 'e', - 'f', - 'g', - 'h', - 'i' - ]; - }()) - - // 2 - (function(){ - var a = [ - 0 + - 5 * - 9 * - 'a', - 'b', - 0 + - 5 * - 9 * - 'c', - 'd', - 'e', - 'f', - 'g', - 'h', - 'i' - ]; - }()) - - // 3 - (function(){ - var a = [ - 0 + - // comment 1 - 5 * - /* comment 2 */ - 9 * - 'a', - 'b', - 0 + - 5 * - 9 * - 'c', - 'd', - 'e', - 'f', - 'g', - 'h', - 'i' - ]; - }()) - - // 4 - { - var a = [ - 0, - 1 - ]; - var b; - var c; - } - - // 5 - { - var a = [ - [ - 0 - ], - 2, - 3 - ]; - } - - // 6 - { - var a = [ - [ - 0, - 1 - ], - 2, - 3 - ]; - } - - // 7 - { - var a = [ - // [ - 0, - // 1 - // ], - 2, - 3 - ]; - } - - // 8 - var x = [ - (function(){ - var a, - b, - c, - d, - e, - f, - g, - h, - i; - }) - ]; - - // 9 - var a = [ - 0 + - 5 * - 9 * - 'a', - 'b', - 0 + - 5 * - 9 * - 'c', - 'd', - 'e', - 'f', - 'g', - 'h', - 'i' - ]; - - // 10 - var a, - b, - c, - d, - e, - f, - g, - h, - i; - JSEND - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_55() - new - setl cindent ts=4 sw=4 - setl cino& - - let code =<< trim [CODE] - /* start of define */ - { - } - #define AAA \ - BBB\ - CCC - - #define CNT \ - 1 + \ - 2 + \ - 4 - /* end of define */ - [CODE] - - call append(0, code) - normal gg - call search('start of define') - exe "normal =/end of define\n" - - let expected =<< trim [CODE] - /* start of define */ - { - } - #define AAA \ - BBB\ - CCC - - #define CNT \ - 1 + \ - 2 + \ - 4 - /* end of define */ - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_56() - new - setl cindent ts=4 sw=4 - setl cino& - - let code =<< trim [CODE] - { - a = second/*bug*/*line; - } - [CODE] - - call append(0, code) - normal gg - call search('a = second') - normal ox - - let expected =<< trim [CODE] - { - a = second/*bug*/*line; - x - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -" this was going beyond the end of the line. -func Test_cindent_case() - new - call setline(1, 'case x: // x') - 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 - sil norm o0('\0=L - bwipe! -endfunc - -func Test_cindent_scopedecls() - new - setl cindent ts=4 sw=4 - setl cino=g0 - setl cinsd+=public\ slots,signals - - let code =<< trim [CODE] - class Foo - { - public: - virtual void foo() = 0; - public slots: - void onBar(); - signals: - void baz(); - private: - int x; - }; - [CODE] - - call append(0, code) - normal gg - normal ]]=][ - - let expected =<< trim [CODE] - class Foo - { - public: - virtual void foo() = 0; - public slots: - void onBar(); - signals: - void baz(); - private: - int x; - }; - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_cindent_pragma() - new - setl cindent ts=4 sw=4 - setl cino=Ps - - let code =<< trim [CODE] - { - #pragma omp parallel - { - #pragma omp task - foo(); - # pragma omp taskwait - } - } - [CODE] - - call append(0, code) - normal gg - normal =G - - let expected =<< trim [CODE] - { - #pragma omp parallel - { - #pragma omp task - foo(); - # pragma omp taskwait - } - } - - [CODE] - - call assert_equal(expected, getline(1, '$')) - enew! | close -endfunc - -func Test_backslash_at_end_of_line() - new - exe "norm v>O'\\\-" - exe "norm \=" - bwipe! -endfunc - -func Test_find_brace_backwards() - " this was looking beyond the end of the line - new - norm R/* - norm o0{ - norm o// - norm V{= - call assert_equal(['/*', ' 0{', '//'], getline(1, 3)) - bwipe! -endfunc - - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_cjk_linebreak.vim b/src/nvim/testdir/test_cjk_linebreak.vim deleted file mode 100644 index dfaa8fa1af..0000000000 --- a/src/nvim/testdir/test_cjk_linebreak.vim +++ /dev/null @@ -1,97 +0,0 @@ -scriptencoding utf-8 - -func Run_cjk_linebreak_after(rigorous) - set textwidth=12 - for punct in [ - \ '!', '%', ')', ',', ':', ';', '>', '?', ']', '}', '’', 'â€', '†', '‡', - \ '…', '‰', '‱', '‼', 'â‡', 'âˆ', 'â‰', '℃', '℉', 'ã€', '。', '〉', '》', - \ 'ã€', 'ã€', '】', '〕', '〗', '〙', '〛', 'ï¼', ')', ',', '.', ':', - \ 'ï¼›', '?', 'ï¼½', 'ï½'] - call setline('.', '这是一个测试' .. punct.'试试 CJK 行ç¦åˆ™è¡¥ä¸ã€‚') - normal gqq - if a:rigorous - call assert_equal('这是一个测', getline(1)) - else - call assert_equal('这是一个测试' .. punct, getline(1)) - endif - %d_ - endfor -endfunc - -func Test_cjk_linebreak_after() - set formatoptions=croqn2mB1j - call Run_cjk_linebreak_after(0) -endfunc - -func Test_cjk_linebreak_after_rigorous() - set formatoptions=croqn2mB1j] - call Run_cjk_linebreak_after(1) -endfunc - -func Run_cjk_linebreak_before() - set textwidth=12 - for punct in [ - \ '(', '<', '[', '`', '{', '‘', '“', '〈', '《', '「', '『', 'ã€', '〔', - \ '〖', '〘', '〚', '(', 'ï¼»', 'ï½›'] - call setline('.', '这是个测试' .. punct.'试试 CJK 行ç¦åˆ™è¡¥ä¸ã€‚') - normal gqq - call assert_equal('这是个测试', getline(1)) - %d_ - endfor -endfunc - -func Test_cjk_linebreak_before() - set formatoptions=croqn2mB1j - call Run_cjk_linebreak_before() -endfunc - -func Test_cjk_linebreak_before_rigorous() - set formatoptions=croqn2mB1j] - call Run_cjk_linebreak_before() -endfunc - -func Run_cjk_linebreak_nobetween(rigorous) - " …… must not start a line - call setline('.', '这是个测试……试试 CJK 行ç¦åˆ™è¡¥ä¸ã€‚') - set textwidth=12 ambiwidth=double - normal gqq - if a:rigorous - call assert_equal('这是个测', getline(1)) - else - call assert_equal('这是个测试……', getline(1)) - endif - %d_ - - call setline('.', '这是一个测试……试试 CJK 行ç¦åˆ™è¡¥ä¸ã€‚') - set textwidth=12 ambiwidth=double - normal gqq - call assert_equal('这是一个测', getline(1)) - %d_ - - " but —— can - call setline('.', '这是个测试——试试 CJK 行ç¦åˆ™è¡¥ä¸ã€‚') - set textwidth=12 ambiwidth=double - normal gqq - call assert_equal('这是个测试', getline(1)) -endfunc - -func Test_cjk_linebreak_nobetween() - set formatoptions=croqn2mB1j - call Run_cjk_linebreak_nobetween(0) -endfunc - -func Test_cjk_linebreak_nobetween_rigorous() - set formatoptions=croqn2mB1j] - call Run_cjk_linebreak_nobetween(1) -endfunc - -func Test_cjk_linebreak_join_punct() - for punct in ['——', '〗', ',', '。', '……'] - call setline(1, '文本文本' .. punct) - call setline(2, 'English') - set formatoptions=croqn2mB1j - normal ggJ - call assert_equal('文本文本' .. punct.'English', getline(1)) - %d_ - endfor -endfunc diff --git a/src/nvim/testdir/test_clientserver.vim b/src/nvim/testdir/test_clientserver.vim deleted file mode 100644 index d8b29f6c42..0000000000 --- a/src/nvim/testdir/test_clientserver.vim +++ /dev/null @@ -1,195 +0,0 @@ -" Tests for the +clientserver feature. - -source check.vim -CheckFeature job - -if !has('clientserver') - call assert_fails('call remote_startserver("local")', 'E942:') -endif - -CheckFeature clientserver - -source shared.vim - -func Check_X11_Connection() - if has('x11') - CheckEnv DISPLAY - try - call remote_send('xxx', '') - catch - if v:exception =~ 'E240:' - throw 'Skipped: no connection to the X server' - endif - " ignore other errors - endtry - endif -endfunc - -func Test_client_server() - let cmd = GetVimCommand() - if cmd == '' - return - endif - call Check_X11_Connection() - - let name = 'XVIMTEST' - let cmd .= ' --servername ' . name - let job = job_start(cmd, {'stoponexit': 'kill', 'out_io': 'null'}) - call WaitForAssert({-> assert_equal("run", job_status(job))}) - - " Takes a short while for the server to be active. - " When using valgrind it takes much longer. - call WaitForAssert({-> assert_match(name, serverlist())}) - - if !has('win32') - if RunVim([], [], '--serverlist >Xtest_serverlist') - let lines = readfile('Xtest_serverlist') - call assert_true(index(lines, 'XVIMTEST') >= 0) - endif - call delete('Xtest_serverlist') - endif - - eval name->remote_foreground() - - call remote_send(name, ":let testvar = 'yes'\") - call WaitFor('remote_expr("' . name . '", "exists(\"testvar\") ? testvar : \"\"", "", 1) == "yes"') - call assert_equal('yes', remote_expr(name, "testvar", "", 2)) - call assert_fails("let x=remote_expr(name, '2+x')", 'E449:') - call assert_fails("let x=remote_expr('[], '2+2')", 'E116:') - - if has('unix') && has('gui') && !has('gui_running') - " Running in a terminal and the GUI is available: Tell the server to open - " the GUI and check that the remote command still works. - " Need to wait for the GUI to start up, otherwise the send hangs in trying - " to send to the terminal window. - if has('gui_motif') - " For this GUI ignore the 'failed to create input context' error. - call remote_send(name, ":call test_ignore_error('E285') | gui -f\") - else - call remote_send(name, ":gui -f\") - endif - " Wait for the server to be up and answering requests. - " When using valgrind this can be very, very slow. - sleep 1 - call WaitForAssert({-> assert_match('\d', name->remote_expr("v:version", "", 1))}, 10000) - - call remote_send(name, ":let testvar = 'maybe'\") - call WaitForAssert({-> assert_equal('maybe', remote_expr(name, "testvar", "", 2))}) - endif - - call assert_fails('call remote_send("XXX", ":let testvar = ''yes''\")', 'E241') - - call writefile(['one'], 'Xclientfile') - let cmd = GetVimProg() .. ' --servername ' .. name .. ' --remote Xclientfile' - call system(cmd) - call WaitForAssert({-> assert_equal('Xclientfile', remote_expr(name, "bufname()", "", 2))}) - call WaitForAssert({-> assert_equal('one', remote_expr(name, "getline(1)", "", 2))}) - call writefile(['one', 'two'], 'Xclientfile') - call system(cmd) - call WaitForAssert({-> assert_equal('two', remote_expr(name, "getline(2)", "", 2))}) - call delete('Xclientfile') - - " Expression evaluated locally. - if v:servername == '' - eval 'MYSELF'->remote_startserver() - " May get MYSELF1 when running the test again. - call assert_match('MYSELF', v:servername) - call assert_fails("call remote_startserver('MYSELF')", 'E941:') - endif - let g:testvar = 'myself' - call assert_equal('myself', remote_expr(v:servername, 'testvar')) - call remote_send(v:servername, ":let g:testvar2 = 75\") - call feedkeys('', 'x') - call assert_equal(75, g:testvar2) - call assert_fails('let v = remote_expr(v:servername, "/2")', ['E15:.*/2']) - - call remote_send(name, ":call server2client(expand(''), 'got it')\", 'g:myserverid') - call assert_equal('got it', g:myserverid->remote_read(2)) - - call remote_send(name, ":eval expand('')->server2client('another')\", 'g:myserverid') - let peek_result = 'nothing' - let r = g:myserverid->remote_peek('peek_result') - " unpredictable whether the result is already available. - if r > 0 - call assert_equal('another', peek_result) - elseif r == 0 - call assert_equal('nothing', peek_result) - else - call assert_report('remote_peek() failed') - endif - let g:peek_result = 'empty' - call WaitFor('remote_peek(g:myserverid, "g:peek_result") > 0') - call assert_equal('another', g:peek_result) - call assert_equal('another', remote_read(g:myserverid, 2)) - - if !has('gui_running') - " In GUI vim, the following tests display a dialog box - - let cmd = GetVimProg() .. ' --servername ' .. name - - " Run a separate instance to send a command to the server - call remote_expr(name, 'execute("only")') - call system(cmd .. ' --remote-send ":new Xfile"') - call assert_equal('2', remote_expr(name, 'winnr("$")')) - call assert_equal('Xfile', remote_expr(name, 'winbufnr(1)->bufname()')) - call remote_expr(name, 'execute("only")') - - " Invoke a remote-expr. On MS-Windows, the returned value has a carriage - " return. - let l = system(cmd .. ' --remote-expr "2 + 2"') - call assert_equal(['4'], split(l, "\n")) - - " Edit multiple files using --remote - call system(cmd .. ' --remote Xfile1 Xfile2 Xfile3') - call assert_match(".*Xfile1\n.*Xfile2\n.*Xfile3\n", remote_expr(name, 'argv()')) - eval name->remote_send(":%bw!\") - - " Edit files in separate tab pages - call system(cmd .. ' --remote-tab Xfile1 Xfile2 Xfile3') - call WaitForAssert({-> assert_equal('3', remote_expr(name, 'tabpagenr("$")'))}) - call assert_match('.*\remote_send(":%bw!\") - - " Edit a file using --remote-wait - eval name->remote_send(":source $VIMRUNTIME/plugin/rrhelper.vim\") - call system(cmd .. ' --remote-wait +enew Xfile1') - call assert_match('.*\remote_send(":%bw!\") - - " Edit files using --remote-tab-wait - call system(cmd .. ' --remote-tabwait +tabonly\|enew Xfile1 Xfile2') - call assert_equal('1', remote_expr(name, 'tabpagenr("$")')) - eval name->remote_send(":%bw!\") - - " Error cases - if v:lang == "C" || v:lang =~ '^[Ee]n' - let l = split(system(cmd .. ' --remote +pwd'), "\n") - call assert_equal("Argument missing after: \"+pwd\"", l[1]) - endif - let l = system(cmd .. ' --remote-expr "abcd"') - call assert_match('^E449: ', l) - endif - - eval name->remote_send(":%bw!\") - eval name->remote_send(":qa!\") - try - call WaitForAssert({-> assert_equal("dead", job_status(job))}) - finally - if job_status(job) != 'dead' - call assert_report('Server did not exit') - call job_stop(job, 'kill') - endif - endtry - - call assert_fails('call remote_startserver([])', 'E730:') - call assert_fails("let x = remote_peek([])", 'E730:') - call assert_fails("let x = remote_read('vim10')", - \ has('unix') ? ['E573:.*vim10'] : 'E277:') - call assert_fails("call server2client('abc', 'xyz')", - \ has('unix') ? ['E573:.*abc'] : 'E258:') -endfunc - -" Uncomment this line to get a debugging log -" call ch_logfile('channellog', 'w') - -" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_close_count.vim b/src/nvim/testdir/test_close_count.vim deleted file mode 100644 index 1f9adba32d..0000000000 --- a/src/nvim/testdir/test_close_count.vim +++ /dev/null @@ -1,174 +0,0 @@ - -" Tests for :[count]close! command -func Test_close_count() - enew! | only - - let wids = [win_getid()] - for i in range(5) - new - call add(wids, win_getid()) - endfor - - 4wincmd w - close! - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[5], wids[4], wids[3], wids[1], wids[0]], ids) - - 1close! - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[4], wids[3], wids[1], wids[0]], ids) - - $close! - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[4], wids[3], wids[1]], ids) - - 1wincmd w - 2close! - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[4], wids[1]], ids) - - 1wincmd w - new - call add(wids, win_getid()) - new - call add(wids, win_getid()) - 2wincmd w - -1close! - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[6], wids[4], wids[1]], ids) - - 2wincmd w - +1close! - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[6], wids[4]], ids) - - only! -endfunc - -" Tests for :[count]hide command -func Test_hide_count() - enew! | only - - let wids = [win_getid()] - for i in range(5) - new - call add(wids, win_getid()) - endfor - - 4wincmd w - .hide - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[5], wids[4], wids[3], wids[1], wids[0]], ids) - - 1hide - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[4], wids[3], wids[1], wids[0]], ids) - - $hide - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[4], wids[3], wids[1]], ids) - - 1wincmd w - 2hide - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[4], wids[1]], ids) - - 1wincmd w - new - call add(wids, win_getid()) - new - call add(wids, win_getid()) - 3wincmd w - -hide - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[7], wids[4], wids[1]], ids) - - 2wincmd w - +hide - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[7], wids[4]], ids) - - only! -endfunc - -" Tests for :[count]close! command with 'hidden' -func Test_hidden_close_count() - enew! | only - - let wids = [win_getid()] - for i in range(5) - new - call add(wids, win_getid()) - endfor - - set hidden - - $ hide - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[5], wids[4], wids[3], wids[2], wids[1]], ids) - - $-1 close! - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[5], wids[4], wids[3], wids[1]], ids) - - 1wincmd w - .+close! - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[5], wids[3], wids[1]], ids) - - set nohidden - only! -endfunc - -" Tests for 'CTRL-W c' command to close windows. -func Test_winclose_command() - enew! | only - - let wids = [win_getid()] - for i in range(5) - new - call add(wids, win_getid()) - endfor - - set hidden - - 4wincmd w - exe "normal \c" - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[5], wids[4], wids[3], wids[1], wids[0]], ids) - - exe "normal 1\c" - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[4], wids[3], wids[1], wids[0]], ids) - - exe "normal 9\c" - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[4], wids[3], wids[1]], ids) - - 1wincmd w - exe "normal 2\c" - let ids = [] - windo call add(ids, win_getid()) - call assert_equal([wids[4], wids[1]], ids) - - set nohidden - only! -endfunc diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim deleted file mode 100644 index 1dceb43e5d..0000000000 --- a/src/nvim/testdir/test_cmdline.vim +++ /dev/null @@ -1,3586 +0,0 @@ -" Tests for editing the command line. - -source check.vim -source screendump.vim -source view_util.vim -source shared.vim - -func SetUp() - func SaveLastScreenLine() - let g:Sline = Screenline(&lines - 1) - return '' - endfunc - cnoremap SaveLastScreenLine() -endfunc - -func TearDown() - delfunc SaveLastScreenLine - cunmap -endfunc - -func Test_complete_tab() - call writefile(['testfile'], 'Xtestfile') - call feedkeys(":e Xtest\t\r", "tx") - call assert_equal('testfile', getline(1)) - - " Pressing after '%' completes the current file, also on MS-Windows - call feedkeys(":e %\t\r", "tx") - call assert_equal('e Xtestfile', @:) - call delete('Xtestfile') -endfunc - -func Test_complete_list() - " We can't see the output, but at least we check the code runs properly. - call feedkeys(":e test\\r", "tx") - call assert_equal('test', expand('%:t')) - - " If a command doesn't support completion, then CTRL-D should be literally - " used. - call feedkeys(":chistory \\\"\", 'xt') - call assert_equal("\"chistory \", @:) - - " Test for displaying the tail of the completion matches - set wildmode=longest,full - call mkdir('Xtest') - call writefile([], 'Xtest/a.c') - call writefile([], 'Xtest/a.h') - let g:Sline = '' - call feedkeys(":e Xtest/\\\\"\", 'xt') - call assert_equal('a.c a.h', g:Sline) - call assert_equal('"e Xtest/', @:) - if has('win32') - " Test for 'completeslash' - set completeslash=backslash - call feedkeys(":e Xtest\\\"\", 'xt') - call assert_equal('"e Xtest\', @:) - call feedkeys(":e Xtest/\\\"\", 'xt') - call assert_equal('"e Xtest\a.', @:) - set completeslash=slash - call feedkeys(":e Xtest\\\"\", 'xt') - call assert_equal('"e Xtest/', @:) - call feedkeys(":e Xtest\\\\\"\", 'xt') - call assert_equal('"e Xtest/a.', @:) - set completeslash& - endif - - " Test for displaying the tail with wildcards - let g:Sline = '' - call feedkeys(":e Xtes?/\\\\"\", 'xt') - call assert_equal('Xtest/a.c Xtest/a.h', g:Sline) - call assert_equal('"e Xtes?/', @:) - let g:Sline = '' - call feedkeys(":e Xtes*/\\\\"\", 'xt') - call assert_equal('Xtest/a.c Xtest/a.h', g:Sline) - call assert_equal('"e Xtes*/', @:) - let g:Sline = '' - call feedkeys(":e Xtes[/\\\\"\", 'xt') - call assert_equal(':e Xtes[/', g:Sline) - call assert_equal('"e Xtes[/', @:) - - call delete('Xtest', 'rf') - set wildmode& -endfunc - -func Test_complete_wildmenu() - call mkdir('Xdir1/Xdir2', 'p') - call writefile(['testfile1'], 'Xdir1/Xtestfile1') - call writefile(['testfile2'], 'Xdir1/Xtestfile2') - call writefile(['testfile3'], 'Xdir1/Xdir2/Xtestfile3') - call writefile(['testfile3'], 'Xdir1/Xdir2/Xtestfile4') - set wildmenu - - " Pressing completes, and moves to next files when pressing again. - call feedkeys(":e Xdir1/\\\", 'tx') - call assert_equal('testfile1', getline(1)) - call feedkeys(":e Xdir1/\\\\", 'tx') - call assert_equal('testfile2', getline(1)) - - " is like but begin with the last match and then go to - " previous. - call feedkeys(":e Xdir1/Xtest\\", 'tx') - call assert_equal('testfile2', getline(1)) - call feedkeys(":e Xdir1/Xtest\\\", 'tx') - call assert_equal('testfile1', getline(1)) - - " / to move to previous/next file. - call feedkeys(":e Xdir1/\\\", 'tx') - call assert_equal('testfile1', getline(1)) - call feedkeys(":e Xdir1/\\\\", 'tx') - call assert_equal('testfile2', getline(1)) - call feedkeys(":e Xdir1/\\\\\", 'tx') - call assert_equal('testfile1', getline(1)) - - " / to go up/down directories. - call feedkeys(":e Xdir1/\\\", 'tx') - call assert_equal('testfile3', getline(1)) - call feedkeys(":e Xdir1/\\\\\", 'tx') - call assert_equal('testfile1', getline(1)) - - " this fails in some Unix GUIs, not sure why - if !has('unix') || !has('gui_running') - " / mappings to go up/down directories when 'wildcharm' is - " different than 'wildchar'. - set wildcharm= - cnoremap - cnoremap - call feedkeys(":e Xdir1/\\\", 'tx') - call assert_equal('testfile3', getline(1)) - call feedkeys(":e Xdir1/\\\\", 'tx') - call assert_equal('testfile1', getline(1)) - set wildcharm=0 - cunmap - cunmap - endif - - " Test for canceling the wild menu by adding a character - redrawstatus - call feedkeys(":e Xdir1/\x\\"\", 'xt') - call assert_equal('"e Xdir1/Xdir2/x', @:) - - " Completion using a relative path - cd Xdir1/Xdir2 - call feedkeys(":e ../\\\\\\"\", 'tx') - call assert_equal('"e Xtestfile3 Xtestfile4', @:) - cd - - - " test for wildmenumode() - cnoremap wildmenumode() - call feedkeys(":cd Xdir\\\\"\", 'tx') - call assert_equal('"cd Xdir1/0', @:) - call feedkeys(":e Xdir1/\\\\"\", 'tx') - call assert_equal('"e Xdir1/Xdir2/1', @:) - cunmap - - " Test for canceling the wild menu by pressing or . - " After this pressing or should not change the selection. - call feedkeys(":sign \\\\\\\"\", 'tx') - call assert_equal('"sign define', @:) - call histadd('cmd', 'TestWildMenu') - call feedkeys(":sign \\\\\\\"\", 'tx') - call assert_equal('"TestWildMenu', @:) - - " cleanup - %bwipe - call delete('Xdir1', 'rf') - set nowildmenu -endfunc - -func Test_wildmenu_screendump() - CheckScreendump - - let lines =<< trim [SCRIPT] - set wildmenu hlsearch - [SCRIPT] - call writefile(lines, 'XTest_wildmenu') - - let buf = RunVimInTerminal('-S XTest_wildmenu', {'rows': 8}) - call term_sendkeys(buf, ":vim\") - call VerifyScreenDump(buf, 'Test_wildmenu_1', {}) - - call term_sendkeys(buf, "\") - call VerifyScreenDump(buf, 'Test_wildmenu_2', {}) - - call term_sendkeys(buf, "\") - call VerifyScreenDump(buf, 'Test_wildmenu_3', {}) - - call term_sendkeys(buf, "\") - call VerifyScreenDump(buf, 'Test_wildmenu_4', {}) - call term_sendkeys(buf, "\") - - " clean up - call StopVimInTerminal(buf) - call delete('XTest_wildmenu') -endfunc - -func Test_redraw_in_autocmd() - CheckScreendump - - let lines =<< trim END - set cmdheight=2 - autocmd CmdlineChanged * redraw - END - call writefile(lines, 'XTest_redraw', 'D') - - let buf = RunVimInTerminal('-S XTest_redraw', {'rows': 8}) - call term_sendkeys(buf, ":for i in range(3)\") - call VerifyScreenDump(buf, 'Test_redraw_in_autocmd_1', {}) - - call term_sendkeys(buf, "let i =") - call VerifyScreenDump(buf, 'Test_redraw_in_autocmd_2', {}) - - " clean up - call term_sendkeys(buf, "\") - call StopVimInTerminal(buf) -endfunc - -func Test_redrawstatus_in_autocmd() - CheckScreendump - - let lines =<< trim END - set laststatus=2 - set statusline=%=:%{getcmdline()} - autocmd CmdlineChanged * redrawstatus - END - call writefile(lines, 'XTest_redrawstatus', 'D') - - let buf = RunVimInTerminal('-S XTest_redrawstatus', {'rows': 8}) - " :redrawstatus is postponed if messages have scrolled - call term_sendkeys(buf, ":echo \"one\\ntwo\\nthree\\nfour\"\") - call term_sendkeys(buf, ":foobar") - call VerifyScreenDump(buf, 'Test_redrawstatus_in_autocmd_1', {}) - " it is not postponed if messages have not scrolled - call term_sendkeys(buf, "\:for in in range(3)") - call VerifyScreenDump(buf, 'Test_redrawstatus_in_autocmd_2', {}) - " with cmdheight=1 messages have scrolled when typing :endfor - call term_sendkeys(buf, "\:endfor") - call VerifyScreenDump(buf, 'Test_redrawstatus_in_autocmd_3', {}) - call term_sendkeys(buf, "\:set cmdheight=2\") - " with cmdheight=2 messages haven't scrolled when typing :for or :endfor - call term_sendkeys(buf, ":for in in range(3)") - call VerifyScreenDump(buf, 'Test_redrawstatus_in_autocmd_4', {}) - call term_sendkeys(buf, "\:endfor") - call VerifyScreenDump(buf, 'Test_redrawstatus_in_autocmd_5', {}) - - " clean up - call term_sendkeys(buf, "\") - call StopVimInTerminal(buf) -endfunc - -func Test_changing_cmdheight() - CheckScreendump - - let lines =<< trim END - set cmdheight=1 laststatus=2 - func EchoTwo() - set laststatus=2 - set cmdheight=5 - echo 'foo' - echo 'bar' - set cmdheight=1 - endfunc - END - call writefile(lines, 'XTest_cmdheight', 'D') - - let buf = RunVimInTerminal('-S XTest_cmdheight', {'rows': 8}) - call term_sendkeys(buf, ":resize -3\") - call VerifyScreenDump(buf, 'Test_changing_cmdheight_1', {}) - - " using the space available doesn't change the status line - call term_sendkeys(buf, ":set cmdheight+=3\") - call VerifyScreenDump(buf, 'Test_changing_cmdheight_2', {}) - - " using more space moves the status line up - call term_sendkeys(buf, ":set cmdheight+=1\") - call VerifyScreenDump(buf, 'Test_changing_cmdheight_3', {}) - - " reducing cmdheight moves status line down - call term_sendkeys(buf, ":set cmdheight-=2\") - call VerifyScreenDump(buf, 'Test_changing_cmdheight_4', {}) - - " reducing window size and then setting cmdheight - call term_sendkeys(buf, ":resize -1\") - call term_sendkeys(buf, ":set cmdheight=1\") - call VerifyScreenDump(buf, 'Test_changing_cmdheight_5', {}) - - " setting 'cmdheight' works after outputting two messages - call term_sendkeys(buf, ":call EchoTwo()\") - call VerifyScreenDump(buf, 'Test_changing_cmdheight_6', {}) - - " clean up - call StopVimInTerminal(buf) -endfunc - -func Test_cmdheight_tabline() - CheckScreendump - - let buf = RunVimInTerminal('-c "set ls=2" -c "set stal=2" -c "set cmdheight=1"', {'rows': 6}) - call VerifyScreenDump(buf, 'Test_cmdheight_tabline_1', {}) - - " clean up - call StopVimInTerminal(buf) -endfunc - -func Test_map_completion() - call feedkeys(":map \\"\", 'xt') - call assert_equal('"map ', getreg(':')) - call feedkeys(":map