From eba8a9ca1d94f43b7fe2e92d5a2caa144dd68d0d Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Fri, 21 Feb 2020 22:05:59 -0500 Subject: [PATCH 01/20] vim-patch:8.1.1510: a plugin cannot easily expand a command like done internally Problem: A plugin cannot easily expand a command like done internally. Solution: Add the expandcmd() function. (Yegappan Lakshmanan, closes vim/vim#4514) https://github.com/vim/vim/commit/80dad48c5095d30873a42ec82628bdb213125d8e --- runtime/doc/eval.txt | 9 ++++++ runtime/doc/usr_41.txt | 1 + src/nvim/eval.lua | 1 + src/nvim/eval/funcs.c | 25 +++++++++++++++++ test/functional/legacy/expand_spec.lua | 39 ++++++++++++++++++++++++++ 5 files changed, 75 insertions(+) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index ce0218f1dd..c687d15689 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2110,6 +2110,7 @@ extend({expr1}, {expr2} [, {expr3}]) exp({expr}) Float exponential of {expr} expand({expr} [, {nosuf} [, {list}]]) any expand special keywords in {expr} +expandcmd({expr}) String expand {expr} like with `:edit` feedkeys({string} [, {mode}]) Number add key sequence to typeahead buffer filereadable({file}) Number |TRUE| if {file} is a readable file filewritable({file}) Number |TRUE| if {file} is a writable file @@ -3733,6 +3734,14 @@ expand({expr} [, {nosuf} [, {list}]]) *expand()* See |glob()| for finding existing files. See |system()| for getting the raw output of an external command. +expandcmd({expr}) *expandcmd()* + Expand special items in {expr} like what is done for an Ex + command such as `:edit`. This expands special keywords, like + with |expand()|, and environment variables, anywhere in + {expr}. Returns the expanded string. + Example: > + :echo expandcmd('make %<.o') +< extend({expr1}, {expr2} [, {expr3}]) *extend()* {expr1} and {expr2} must be both |Lists| or both |Dictionaries|. diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 5f9253cbd0..234f7801ab 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -609,6 +609,7 @@ String manipulation: *string-functions* strcharpart() get part of a string using char index strgetchar() get character from a string using char index expand() expand special keywords + expandcmd() expand a command like done for `:edit` iconv() convert text from one encoding to another byteidx() byte index of a character in a string byteidxcomp() like byteidx() but count composing characters diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 4654f8cef6..d3e769a7ef 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -102,6 +102,7 @@ return { exists={args=1}, exp={args=1, func="float_op_wrapper", data="&exp"}, expand={args={1, 3}}, + expandcmd={args=1}, extend={args={2, 3}}, feedkeys={args={1, 2}}, file_readable={args=1, func='f_filereadable'}, -- obsolete diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index be8e35b1de..c89c72c3de 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2103,6 +2103,31 @@ static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) menu_get((char_u *)tv_get_string(&argvars[0]), modes, rettv->vval.v_list); } +// "expandcmd()" function +// Expand all the special characters in a command string. +static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + char_u *errormsg = NULL; + + rettv->v_type = VAR_STRING; + char_u *cmdstr = (char_u *)xstrdup(tv_get_string(&argvars[0])); + + exarg_T eap = { + .cmd = cmdstr, + .arg = cmdstr, + .usefilter = false, + .nextcmd = NULL, + .cmdidx = CMD_USER, + }; + eap.argt |= NOSPC; + + expand_filename(&eap, &cmdstr, &errormsg); + if (errormsg != NULL && *errormsg != NUL) { + EMSG(errormsg); + } + rettv->vval.v_string = cmdstr; +} + /* * "extend(list, list [, idx])" function * "extend(dict, dict [, action])" function diff --git a/test/functional/legacy/expand_spec.lua b/test/functional/legacy/expand_spec.lua index 1b735080f4..f238128b31 100644 --- a/test/functional/legacy/expand_spec.lua +++ b/test/functional/legacy/expand_spec.lua @@ -70,6 +70,40 @@ describe('expand file name', function() call assert_match('\~', expand('%:p')) bwipe! endfunc + + func Test_expandcmd() + let $FOO = 'Test' + call assert_equal('e x/Test/y', expandcmd('e x/$FOO/y')) + unlet $FOO + + new + edit Xfile1 + call assert_equal('e Xfile1', expandcmd('e %')) + edit Xfile2 + edit Xfile1 + call assert_equal('e Xfile2', expandcmd('e #')) + edit Xfile2 + edit Xfile3 + edit Xfile4 + let bnum = bufnr('Xfile2') + call assert_equal('e Xfile2', expandcmd('e #' . bnum)) + call setline('.', 'Vim!@#') + call assert_equal('e Vim', expandcmd('e ')) + call assert_equal('e Vim!@#', expandcmd('e ')) + enew! + edit Xfile.java + call assert_equal('e Xfile.py', expandcmd('e %:r.py')) + call assert_equal('make abc.java', expandcmd('make abc.%:e')) + call assert_equal('make Xabc.java', expandcmd('make %:s?file?abc?')) + edit a1a2a3.rb + call assert_equal('make b1b2b3.rb a1a2a3 Xfile.o', expandcmd('make %:gs?a?b? %< #<.o')) + + call assert_fails('call expandcmd("make ")', 'E495:') + call assert_fails('call expandcmd("make ")', 'E495:') + enew + call assert_fails('call expandcmd("make %")', 'E499:') + close + endfunc ]]) end) @@ -87,4 +121,9 @@ describe('expand file name', function() call('Test_expand_tilde_filename') expected_empty() end) + + it('works with expandcmd()', function() + call('Test_expandcmd') + expected_empty() + end) end) From 0eb2f2be6004f50113dfe1e2457afd5f27107f1c Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 22 Feb 2020 11:18:05 -0500 Subject: [PATCH 02/20] 'clang/Logic error': zero-init MarkTreeIter vars --- src/nvim/extmark.c | 14 +++++++------- src/nvim/marktree.c | 5 +++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index d00943c1be..e77b556024 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -86,7 +86,7 @@ uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t id, extmark_del(buf, ns_id, id); } else { // TODO(bfredl): we need to do more if "revising" a decoration mark. - MarkTreeIter itr[1]; + MarkTreeIter itr[1] = { 0 }; old_pos = marktree_lookup(buf->b_marktree, old_mark, itr); assert(itr->node); if (old_pos.row == row && old_pos.col == col) { @@ -119,7 +119,7 @@ revised: static bool extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col) { - MarkTreeIter itr[1]; + MarkTreeIter itr[1] = { 0 }; mtpos_t pos = marktree_lookup(buf->b_marktree, mark, itr); if (pos.row == -1) { return false; @@ -147,7 +147,7 @@ bool extmark_del(buf_T *buf, uint64_t ns_id, uint64_t id) return false; } - MarkTreeIter itr[1]; + MarkTreeIter itr[1] = { 0 }; mtpos_t pos = marktree_lookup(buf->b_marktree, mark, itr); assert(pos.row >= 0); marktree_del_itr(buf->b_marktree, itr, false); @@ -207,7 +207,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id, delete_set = map_new(uint64_t, uint64_t)(); } - MarkTreeIter itr[1]; + MarkTreeIter itr[1] = { 0 }; marktree_itr_get(buf->b_marktree, l_row, l_col, itr); while (true) { mtmark_t mark = marktree_itr_current(itr); @@ -276,7 +276,7 @@ ExtmarkArray extmark_get(buf_T *buf, uint64_t ns_id, int64_t amount, bool reverse) { ExtmarkArray array = KV_INITIAL_VALUE; - MarkTreeIter itr[1]; + MarkTreeIter itr[1] = { 0 }; // Find all the marks marktree_itr_get_ext(buf->b_marktree, (mtpos_t){ l_row, l_col }, itr, reverse, false, NULL); @@ -396,7 +396,7 @@ void u_extmark_copy(buf_T *buf, ExtmarkUndoObject undo; - MarkTreeIter itr[1]; + MarkTreeIter itr[1] = { 0 }; marktree_itr_get(buf->b_marktree, l_row, l_col, itr); while (true) { mtmark_t mark = marktree_itr_current(itr); @@ -738,7 +738,7 @@ void clear_virttext(VirtText *text) VirtText *extmark_find_virttext(buf_T *buf, int row, uint64_t ns_id) { - MarkTreeIter itr[1]; + MarkTreeIter itr[1] = { 0 }; marktree_itr_get(buf->b_marktree, row, 0, itr); while (true) { mtmark_t mark = marktree_itr_current(itr); diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c index a46ec715a0..6dd452b5af 100644 --- a/src/nvim/marktree.c +++ b/src/nvim/marktree.c @@ -849,7 +849,8 @@ bool marktree_splice(MarkTree *b, bool same_line = old_extent.row == 0 && new_extent.row == 0; unrelative(start, &old_extent); unrelative(start, &new_extent); - MarkTreeIter itr[1], enditr[1]; + MarkTreeIter itr[1] = { 0 }; + MarkTreeIter enditr[1] = { 0 }; mtpos_t oldbase[MT_MAX_DEPTH]; @@ -1003,7 +1004,7 @@ void marktree_move_region(MarkTree *b, mtpos_t start = { start_row, start_col }, size = { extent_row, extent_col }; mtpos_t end = size; unrelative(start, &end); - MarkTreeIter itr[1]; + MarkTreeIter itr[1] = { 0 }; marktree_itr_get_ext(b, start, itr, false, true, NULL); kvec_t(mtkey_t) saved = KV_INITIAL_VALUE; while (itr->node) { From 607240a8bac80f02d812084d3146b4372ddae6dd Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 22 Feb 2020 12:09:21 -0500 Subject: [PATCH 03/20] pvs/v1048: variable was assigned same value --- src/nvim/eval/funcs.c | 1 - src/nvim/indent_c.c | 9 +++------ src/nvim/ops.c | 40 ++++++++++++++++++++-------------------- src/nvim/os/shell.c | 1 - 4 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c89c72c3de..25e57d54f0 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5297,7 +5297,6 @@ static void f_list2str(typval_T *argvars, typval_T *rettv, FunPtr fptr) }); ga_append(&ga, NUL); - rettv->v_type = VAR_STRING; rettv->vval.v_string = ga.ga_data; } diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c index 67a7e58ed7..bb443161ef 100644 --- a/src/nvim/indent_c.c +++ b/src/nvim/indent_c.c @@ -3372,11 +3372,9 @@ term_again: continue; } - /* - * Are we at the start of a cpp base class declaration or - * constructor initialization? - */ /* XXX */ - n = false; + // Are we at the start of a cpp base class declaration or + // constructor initialization? XXX + n = 0; if (curbuf->b_ind_cpp_baseclass != 0 && theline[0] != '{') { n = cin_is_cpp_baseclass(&cache_cpp_baseclass); l = get_cursor_line_ptr(); @@ -3409,7 +3407,6 @@ term_again: * } foo, * bar; */ - n = 0; if (cin_ends_in(l, (char_u *)",", NULL) || (*l != NUL && (n = l[STRLEN(l) - 1]) == '\\')) { /* take us back to opening paren */ diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 735a33ca97..4ac12e868f 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -2534,7 +2534,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) case kMTCharWise: { colnr_T startcol = 0, endcol = MAXCOL; - int is_oneChar = FALSE; + int is_oneChar = false; colnr_T cs, ce; p = ml_get(lnum); bd.startspaces = 0; @@ -2565,8 +2565,8 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) && utf_head_off(p, p + endcol) == 0)) { if (oap->start.lnum == oap->end.lnum && oap->start.col == oap->end.col) { - /* Special case: inside a single char */ - is_oneChar = TRUE; + // Special case: inside a single char + is_oneChar = true; bd.startspaces = oap->end.coladd - oap->start.coladd + oap->inclusive; endcol = startcol; @@ -4425,8 +4425,8 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bdp->textlen = 0; bdp->start_vcol = 0; bdp->end_vcol = 0; - bdp->is_short = FALSE; - bdp->is_oneChar = FALSE; + bdp->is_short = false; + bdp->is_oneChar = false; bdp->pre_whitesp = 0; bdp->pre_whitesp_c = 0; bdp->end_char_vcols = 0; @@ -4452,9 +4452,10 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bdp->start_char_vcols = incr; if (bdp->start_vcol < oap->start_vcol) { /* line too short */ bdp->end_vcol = bdp->start_vcol; - bdp->is_short = TRUE; - if (!is_del || oap->op_type == OP_APPEND) + bdp->is_short = true; + if (!is_del || oap->op_type == OP_APPEND) { bdp->endspaces = oap->end_vcol - oap->start_vcol + 1; + } } else { /* notice: this converts partly selected Multibyte characters to * spaces, too. */ @@ -4463,11 +4464,11 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bdp->startspaces = bdp->start_char_vcols - bdp->startspaces; pend = pstart; bdp->end_vcol = bdp->start_vcol; - if (bdp->end_vcol > oap->end_vcol) { /* it's all in one character */ - bdp->is_oneChar = TRUE; - if (oap->op_type == OP_INSERT) + if (bdp->end_vcol > oap->end_vcol) { // it's all in one character + bdp->is_oneChar = true; + if (oap->op_type == OP_INSERT) { bdp->endspaces = bdp->start_char_vcols - bdp->startspaces; - else if (oap->op_type == OP_APPEND) { + } else if (oap->op_type == OP_APPEND) { bdp->startspaces += oap->end_vcol - oap->start_vcol + 1; bdp->endspaces = bdp->start_char_vcols - bdp->startspaces; } else { @@ -4492,17 +4493,16 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, if (bdp->end_vcol <= oap->end_vcol && (!is_del || oap->op_type == OP_APPEND - || oap->op_type == OP_REPLACE)) { /* line too short */ - bdp->is_short = TRUE; - /* Alternative: include spaces to fill up the block. - * Disadvantage: can lead to trailing spaces when the line is - * short where the text is put */ - /* if (!is_del || oap->op_type == OP_APPEND) */ - if (oap->op_type == OP_APPEND || virtual_op) + || oap->op_type == OP_REPLACE)) { // line too short + bdp->is_short = true; + // Alternative: include spaces to fill up the block. + // Disadvantage: can lead to trailing spaces when the line is + // short where the text is put + // if (!is_del || oap->op_type == OP_APPEND) + if (oap->op_type == OP_APPEND || virtual_op) { bdp->endspaces = oap->end_vcol - bdp->end_vcol + oap->inclusive; - else - bdp->endspaces = 0; /* replace doesn't add characters */ + } } else if (bdp->end_vcol > oap->end_vcol) { bdp->endspaces = bdp->end_vcol - oap->end_vcol - 1; if (!is_del && bdp->endspaces) { diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 3b8470182a..6294d5e4e2 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -448,7 +448,6 @@ int os_expand_wildcards(int num_pat, char_u **pat, int *num_file, } else { buffer[len] = NUL; } - i = 0; for (p = buffer; p < buffer + len; p++) { if (*p == NUL || (*p == ' ' && check_spaces)) { // count entry i++; From 4de2957a997bc54a968e40cebc51a42f29afb39c Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 22 Feb 2020 14:54:41 -0500 Subject: [PATCH 04/20] vim-patch:8.0.1587: inserting from the clipboard doesn't work literally Problem: inserting from the clipboard doesn't work literally Solution: When pasting from the * or + register always assume literally. https://github.com/vim/vim/commit/3324d0a86421a634572758dcfde917547f4d4c67 --- src/nvim/ops.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 4ac12e868f..5457400b76 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -842,6 +842,15 @@ static bool is_append_register(int regname) return ASCII_ISUPPER(regname); } +/// @see get_yank_register +/// @returns true when register should be inserted literally +/// (selection or clipboard) +static inline bool is_literal_register(int regname) + FUNC_ATTR_CONST +{ + return regname == '*' || regname == '+'; +} + /// Returns a copy of contents in register `name` /// for use in do_put. Should be freed by caller. yankreg_T *copy_register(int name) @@ -1152,11 +1161,12 @@ static int put_in_typebuf( */ int insert_reg( int regname, - int literally /* insert literally, not as if typed */ + bool literally_arg // insert literally, not as if typed ) { int retval = OK; bool allocated; + const bool literally = literally_arg || is_literal_register(regname); /* * It is possible to get into an endless loop by having CTRL-R a in @@ -1326,12 +1336,14 @@ bool get_spec_reg( /// register contents will be interpreted as commands. /// /// @param regname Register name. -/// @param literally Insert text literally instead of "as typed". +/// @param literally_arg Insert text literally instead of "as typed". /// @param remcr When true, don't add CR characters. /// /// @returns FAIL for failure, OK otherwise -bool cmdline_paste_reg(int regname, bool literally, bool remcr) +bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr) { + const bool literally = literally_arg || is_literal_register(regname); + yankreg_T *reg = get_yank_register(regname, YREG_PASTE); if (reg->y_array == NULL) return FAIL; From 55e3f211105c3ab2fb16ac677847d695b31b1ae2 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 22 Feb 2020 15:35:11 -0500 Subject: [PATCH 05/20] vim-patch:8.2.0133: invalid memory access with search command Problem: Invalid memory access with search command. Solution: When :normal runs out of characters in bracketed paste mode break out of the loop.(closes vim/vim#5511) https://github.com/vim/vim/commit/98a336dd497d3422e7efeef9f24cc9e25aeb8a49 --- src/nvim/testdir/test_search.vim | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim index 5d99027ca5..acce8dc42f 100644 --- a/src/nvim/testdir/test_search.vim +++ b/src/nvim/testdir/test_search.vim @@ -698,3 +698,8 @@ func Test_search_display_pattern() set norl endif endfunc + +func Test_search_special() + " this was causing illegal memory access + exe "norm /\x80PS" +endfunc From fa6518b1da17b19a78a2c3491f2f793665e6b7c3 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 22 Feb 2020 15:47:41 -0500 Subject: [PATCH 06/20] vim-patch:8.2.0135: bracketed paste can still cause invalid memory access Problem: Bracketed paste can still cause invalid memory access. (Dominique Pelle) Solution: Check for NULL pointer. https://github.com/vim/vim/commit/fe4bbac1166f2e4e3fa18cb966ec7305198c8176 --- src/nvim/testdir/test_search.vim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim index acce8dc42f..8036dea29f 100644 --- a/src/nvim/testdir/test_search.vim +++ b/src/nvim/testdir/test_search.vim @@ -700,6 +700,7 @@ func Test_search_display_pattern() endfunc func Test_search_special() - " this was causing illegal memory access + " this was causing illegal memory access and an endless loop + set t_PE= exe "norm /\x80PS" endfunc From a78e8f6e1bef38bd0ad10f0681f30c43c56d703b Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sun, 23 Feb 2020 09:48:18 -0500 Subject: [PATCH 07/20] vim-patch:8.1.0253: saving and restoring window title does not always work Problem: Saving and restoring window title does not always work. Solution: Use the stack push and pop commands. (Kouichi Iwamoto, closes vim/vim#3059) https://github.com/vim/vim/commit/40385dbcdfb44885f2e9b83e1e0285aeb8a0c2a8 --- src/nvim/option.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/nvim/option.c b/src/nvim/option.c index 478c9a0ff8..5f1c73480e 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -6073,10 +6073,8 @@ void buf_copy_options(buf_T *buf, int flags) save_p_isk = buf->b_p_isk; buf->b_p_isk = NULL; } - /* - * Always free the allocated strings. - * If not already initialized, set 'readonly' and copy 'fileformat'. - */ + // Always free the allocated strings. If not already initialized, + // reset 'readonly' and copy 'fileformat'. if (!buf->b_p_initialized) { free_buf_options(buf, true); buf->b_p_ro = false; // don't copy readonly From ab38df2fc5185a058323a6efc440805eea9fc1f4 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sun, 23 Feb 2020 18:28:11 -0500 Subject: [PATCH 08/20] vim-patch:8.1.1642: may use uninitialized variable Problem: May use uninitialized variable. (Patrick Palka) Solution: Initialize variables earlier. (closes vim/vim#4623) https://github.com/vim/vim/commit/ec572ad6a6cb0d4e71901951a70a4f038d48cb17 --- src/nvim/globals.h | 6 +++--- src/nvim/screen.c | 30 +++++++++++++++--------------- src/nvim/testdir/test_number.vim | 11 +++++++++++ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 323c6cf9c3..9069c5adcb 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -412,9 +412,9 @@ EXTERN vimmenu_T *root_menu INIT(= NULL); */ EXTERN int sys_menu INIT(= FALSE); -/* While redrawing the screen this flag is set. It means the screen size - * ('lines' and 'rows') must not be changed. */ -EXTERN int updating_screen INIT(= FALSE); +// While redrawing the screen this flag is set. It means the screen size +// ('lines' and 'rows') must not be changed. +EXTERN int updating_screen INIT(= 0); /* * All windows are linked in a list. firstwin points to the first entry, diff --git a/src/nvim/screen.c b/src/nvim/screen.c index b6da02d9c3..4cdfec9670 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -334,10 +334,10 @@ int update_screen(int type) } return FAIL; } + updating_screen = 1; - updating_screen = TRUE; - ++display_tick; /* let syntax code know we're in a next round of - * display updating */ + display_tick++; // let syntax code know we're in a next round of + // display updating // Tricky: vim code can reset msg_scrolled behind our back, so need // separate bookkeeping for now. @@ -565,7 +565,7 @@ int update_screen(int type) wp->w_buffer->b_mod_set = false; } - updating_screen = FALSE; + updating_screen = 0; /* Clear or redraw the command line. Done last, because scrolling may * mess up the command line. */ @@ -2215,9 +2215,10 @@ win_line ( int n_skip = 0; /* nr of chars to skip for 'nowrap' */ - int fromcol = 0, tocol = 0; // start/end of inverting + int fromcol = -10; // start of inverting + int tocol = MAXCOL; // end of inverting int fromcol_prev = -2; // start of inverting after cursor - int noinvcur = false; // don't invert the cursor + bool noinvcur = false; // don't invert the cursor pos_T *top, *bot; int lnum_in_visual_area = false; pos_T pos; @@ -2416,27 +2417,26 @@ win_line ( capcol_lnum = 0; } - // - // handle visual active in this window - // - fromcol = -10; - tocol = MAXCOL; + // handle Visual active in this window if (VIsual_active && wp->w_buffer == curwin->w_buffer) { - // Visual is after curwin->w_cursor if (ltoreq(curwin->w_cursor, VIsual)) { + // Visual is after curwin->w_cursor top = &curwin->w_cursor; bot = &VIsual; - } else { // Visual is before curwin->w_cursor + } else { + // Visual is before curwin->w_cursor top = &VIsual; bot = &curwin->w_cursor; } lnum_in_visual_area = (lnum >= top->lnum && lnum <= bot->lnum); - if (VIsual_mode == Ctrl_V) { // block mode + if (VIsual_mode == Ctrl_V) { + // block mode if (lnum_in_visual_area) { fromcol = wp->w_old_cursor_fcol; tocol = wp->w_old_cursor_lcol; } - } else { // non-block mode + } else { + // non-block mode if (lnum > top->lnum && lnum <= bot->lnum) { fromcol = 0; } else if (lnum == top->lnum) { diff --git a/src/nvim/testdir/test_number.vim b/src/nvim/testdir/test_number.vim index 59debcea0d..3c9afc41d5 100644 --- a/src/nvim/testdir/test_number.vim +++ b/src/nvim/testdir/test_number.vim @@ -252,3 +252,14 @@ func Test_numberwidth_adjusted() call s:compare_lines(expect, lines) call s:close_windows() endfunc + +" This was causing a memcheck error +func Test_relativenumber_uninitialised() + new + set rnu + call setline(1, ["a", "b"]) + redraw + call feedkeys("j", 'xt') + redraw + bwipe! +endfunc From 3618fe9e8c67276bc262c6cde8526f42016c2f84 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Mon, 24 Feb 2020 20:25:57 -0500 Subject: [PATCH 09/20] vim-patch:8.1.0883: missing some changes for Ex commands Problem: Missing some changes for Ex commands. Solution: Add mising changes in header file. https://github.com/vim/vim/commit/54d6fe5e60c0c488a424c078963ead40ae7dc397 --- src/nvim/ex_cmds.lua | 39 ++++++++++++++------------- src/nvim/ex_cmds_defs.h | 59 +++++++++++++++++++++-------------------- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index f7aa8a994a..252af409c0 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -24,6 +24,7 @@ local SBOXOK = 0x80000 local CMDWIN = 0x100000 local MODIFY = 0x200000 local EXFLAGS = 0x400000 +local RESTRICT = 0x800000 local FILES = bit.bor(XFILE, EXTRA) local WORD1 = bit.bor(EXTRA, NOSPC) local FILE1 = bit.bor(FILES, NOSPC) @@ -1582,19 +1583,19 @@ return { }, { command='lua', - flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_lua', }, { command='luado', - flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_luado', }, { command='luafile', - flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_luafile', }, @@ -1924,13 +1925,13 @@ return { }, { command='perl', - flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, SBOXOK, CMDWIN), + flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, SBOXOK, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_script_ni', }, { command='perldo', - flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_ni', }, @@ -2056,67 +2057,67 @@ return { }, { command='python', - flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_python', }, { command='pydo', - flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_pydo', }, { command='pyfile', - flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_pyfile', }, { command='py3', - flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_python3', }, { command='py3do', - flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_pydo3', }, { command='python3', - flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_python3', }, { command='py3file', - flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_py3file', }, { command='pyx', - flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_pyx', }, { command='pyxdo', - flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_pyxdo', }, { command='pythonx', - flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_pyx', }, { command='pyxfile', - flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_pyxfile', }, @@ -2242,19 +2243,19 @@ return { }, { command='ruby', - flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_ruby', }, { command='rubydo', - flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_rubydo', }, { command='rubyfile', - flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN), + flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, RESTRICT), addr_type=ADDR_LINES, func='ex_rubyfile', }, diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index d25d81658c..1f0560ae48 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -36,35 +36,36 @@ // 4. Add documentation in ../doc/xxx.txt. Add a tag for both the short and // long name of the command. -#define RANGE 0x001 /* allow a linespecs */ -#define BANG 0x002 /* allow a ! after the command name */ -#define EXTRA 0x004 /* allow extra args after command name */ -#define XFILE 0x008 /* expand wildcards in extra part */ -#define NOSPC 0x010 /* no spaces allowed in the extra part */ -#define DFLALL 0x020 /* default file range is 1,$ */ -#define WHOLEFOLD 0x040 /* extend range to include whole fold also - when less than two numbers given */ -#define NEEDARG 0x080 /* argument required */ -#define TRLBAR 0x100 /* check for trailing vertical bar */ -#define REGSTR 0x200 /* allow "x for register designation */ -#define COUNT 0x400 /* allow count in argument, after command */ -#define NOTRLCOM 0x800 /* no trailing comment allowed */ -#define ZEROR 0x1000 /* zero line number allowed */ -#define USECTRLV 0x2000 /* do not remove CTRL-V from argument */ -#define NOTADR 0x4000 /* number before command is not an address */ -#define EDITCMD 0x8000 /* allow "+command" argument */ -#define BUFNAME 0x10000 /* accepts buffer name */ -#define BUFUNL 0x20000 /* accepts unlisted buffer too */ -#define ARGOPT 0x40000 /* allow "++opt=val" argument */ -#define SBOXOK 0x80000 /* allowed in the sandbox */ -#define CMDWIN 0x100000 /* allowed in cmdline window; when missing - * disallows editing another buffer when - * curbuf_lock is set */ -#define MODIFY 0x200000 /* forbidden in non-'modifiable' buffer */ -#define EXFLAGS 0x400000 /* allow flags after count in argument */ -#define FILES (XFILE | EXTRA) /* multiple extra files allowed */ -#define WORD1 (EXTRA | NOSPC) /* one extra word allowed */ -#define FILE1 (FILES | NOSPC) /* 1 file allowed, defaults to current file */ +#define RANGE 0x001 // allow a linespecs +#define BANG 0x002 // allow a ! after the command name +#define EXTRA 0x004 // allow extra args after command name +#define XFILE 0x008 // expand wildcards in extra part +#define NOSPC 0x010 // no spaces allowed in the extra part +#define DFLALL 0x020 // default file range is 1,$ +#define WHOLEFOLD 0x040 // extend range to include whole fold also + // when less than two numbers given +#define NEEDARG 0x080 // argument required +#define TRLBAR 0x100 // check for trailing vertical bar +#define REGSTR 0x200 // allow "x for register designation +#define COUNT 0x400 // allow count in argument, after command +#define NOTRLCOM 0x800 // no trailing comment allowed +#define ZEROR 0x1000 // zero line number allowed +#define USECTRLV 0x2000 // do not remove CTRL-V from argument +#define NOTADR 0x4000 // number before command is not an address +#define EDITCMD 0x8000 // allow "+command" argument +#define BUFNAME 0x10000 // accepts buffer name +#define BUFUNL 0x20000 // accepts unlisted buffer too +#define ARGOPT 0x40000 // allow "++opt=val" argument +#define SBOXOK 0x80000 // allowed in the sandbox +#define CMDWIN 0x100000 // allowed in cmdline window; when missing + // disallows editing another buffer when + // curbuf_lock is set +#define MODIFY 0x200000 // forbidden in non-'modifiable' buffer +#define EXFLAGS 0x400000 // allow flags after count in argument +#define RESTRICT 0x800000L // forbidden in restricted mode +#define FILES (XFILE | EXTRA) // multiple extra files allowed +#define WORD1 (EXTRA | NOSPC) // one extra word allowed +#define FILE1 (FILES | NOSPC) // 1 file allowed, defaults to current file // values for cmd_addr_type #define ADDR_LINES 0 From d846f47cc88cd36da5ad8fd7e716552c80e3b418 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Mon, 24 Feb 2020 20:33:43 -0500 Subject: [PATCH 10/20] vim-patch:8.1.0881: can execute shell commands in rvim through interfaces Problem: Can execute shell commands in rvim through interfaces. Solution: Disable using interfaces in restricted mode. Allow for writing file with writefile(), histadd() and a few others. https://github.com/vim/vim/commit/8c62a08faf89663e5633dc5036cd8695c80f1075 --- runtime/doc/starting.txt | 13 +++- src/nvim/eval/funcs.c | 9 +-- src/nvim/ex_cmds.c | 18 ++--- src/nvim/ex_docmd.c | 6 +- src/nvim/testdir/test_restricted.vim | 107 +++++++++++++++++++++++++++ 5 files changed, 134 insertions(+), 19 deletions(-) create mode 100644 src/nvim/testdir/test_restricted.vim diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index e3f0d593a7..af7d233619 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -184,12 +184,17 @@ argument. the 'modifiable' and 'write' options can be set to enable changes and writing. - *-Z* *restricted-mode* *E145* + *-Z* *restricted-mode* *E145* *E981* -Z Restricted mode. All commands that make use of an external shell are disabled. This includes suspending with CTRL-Z, - ":sh", filtering, the system() function, backtick expansion, - delete(), rename(), mkdir(), writefile(), libcall(), - jobstart(), etc. + ":sh", filtering, the system() function, backtick expansion + and libcall(). + Also disallowed are delete(), rename(), mkdir(), jobstart(), + etc. + Interfaces, such as Python, Ruby and Lua, are also disabled, + since they could be used to execute shell commands. + Note that the user may still find a loophole to execute a + shell command, it has only been made difficult. -e *-e* *-E* -E Start Nvim in Ex mode |gQ|. diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 25e57d54f0..6d67279e64 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4317,7 +4317,7 @@ static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) HistoryType histype; rettv->vval.v_number = false; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } const char *str = tv_get_string_chk(&argvars[0]); // NULL on type error @@ -7779,8 +7779,7 @@ static void f_setbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - if (check_restricted() - || check_secure() + if (check_secure() || !tv_check_str_or_nr(&argvars[0])) { return; } @@ -8284,7 +8283,7 @@ static void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -11005,7 +11004,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index bc6821f60f..ba66b666e0 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -3008,18 +3008,18 @@ void ex_z(exarg_T *eap) ex_no_reprint = true; } -/* - * Check if the restricted flag is set. - * If so, give an error message and return TRUE. - * Otherwise, return FALSE. - */ -int check_restricted(void) +// Check if the restricted flag is set. +// If so, give an error message and return true. +// Otherwise, return false. +bool check_restricted(void) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { if (restricted) { - EMSG(_("E145: Shell commands not allowed in restricted mode")); - return TRUE; + EMSG(_("E145: Shell commands and some functionality not allowed" + " in restricted mode")); + return true; } - return FALSE; + return false; } /* diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 28ecaf684a..abe394dc3a 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -1783,10 +1783,14 @@ static char_u * do_one_cmd(char_u **cmdlinep, if (!ea.skip) { if (sandbox != 0 && !(ea.argt & SBOXOK)) { - /* Command not allowed in sandbox. */ + // Command not allowed in sandbox. errormsg = (char_u *)_(e_sandbox); goto doend; } + if (restricted != 0 && (ea.argt & RESTRICT)) { + errormsg = (char_u *)_("E981: Command not allowed in restricted mode"); + goto doend; + } if (!MODIFIABLE(curbuf) && (ea.argt & MODIFY) // allow :put in terminals && (!curbuf->terminal || ea.cmdidx != CMD_put)) { diff --git a/src/nvim/testdir/test_restricted.vim b/src/nvim/testdir/test_restricted.vim new file mode 100644 index 0000000000..9dd937cf3e --- /dev/null +++ b/src/nvim/testdir/test_restricted.vim @@ -0,0 +1,107 @@ +" Test for "rvim" or "vim -Z" + +source shared.vim + +func Test_restricted() + let cmd = GetVimCommand('Xrestricted') + if cmd == '' + return + endif + + call writefile([ + \ "silent !ls", + \ "call writefile([v:errmsg], 'Xrestrout')", + \ "qa!", + \ ], 'Xrestricted') + call system(cmd . ' -Z') + call assert_match('E145:', join(readfile('Xrestrout'))) + + call delete('Xrestricted') + call delete('Xrestrout') +endfunc + +func Run_restricted_test(ex_cmd, error) + let cmd = GetVimCommand('Xrestricted') + if cmd == '' + return + endif + + call writefile([ + \ a:ex_cmd, + \ "call writefile([v:errmsg], 'Xrestrout')", + \ "qa!", + \ ], 'Xrestricted') + call system(cmd . ' -Z') + call assert_match(a:error, join(readfile('Xrestrout'))) + + call delete('Xrestricted') + call delete('Xrestrout') +endfunc + +func Test_restricted_lua() + if !has('lua') + throw 'Skipped: Lua is not supported' + endif + call Run_restricted_test('lua print("Hello, Vim!")', 'E981:') + call Run_restricted_test('luado return "hello"', 'E981:') + call Run_restricted_test('luafile somefile', 'E981:') + call Run_restricted_test('call luaeval("expression")', 'E145:') +endfunc + +func Test_restricted_mzscheme() + if !has('mzscheme') + throw 'Skipped: MzScheme is not supported' + endif + call Run_restricted_test('mzscheme statement', 'E981:') + call Run_restricted_test('mzfile somefile', 'E981:') + call Run_restricted_test('call mzeval("expression")', 'E145:') +endfunc + +func Test_restricted_perl() + if !has('perl') + throw 'Skipped: Perl is not supported' + endif + " TODO: how to make Safe mode fail? + " call Run_restricted_test('perl system("ls")', 'E981:') + " call Run_restricted_test('perldo system("hello")', 'E981:') + " call Run_restricted_test('perlfile somefile', 'E981:') + " call Run_restricted_test('call perleval("system(\"ls\")")', 'E145:') +endfunc + +func Test_restricted_python() + if !has('python') + throw 'Skipped: Python is not supported' + endif + call Run_restricted_test('python print "hello"', 'E981:') + call Run_restricted_test('pydo return "hello"', 'E981:') + call Run_restricted_test('pyfile somefile', 'E981:') + call Run_restricted_test('call pyeval("expression")', 'E145:') +endfunc + +func Test_restricted_python3() + if !has('python3') + throw 'Skipped: Python3 is not supported' + endif + call Run_restricted_test('py3 print "hello"', 'E981:') + call Run_restricted_test('py3do return "hello"', 'E981:') + call Run_restricted_test('py3file somefile', 'E981:') + call Run_restricted_test('call py3eval("expression")', 'E145:') +endfunc + +func Test_restricted_ruby() + if !has('ruby') + throw 'Skipped: Ruby is not supported' + endif + call Run_restricted_test('ruby print "Hello"', 'E981:') + call Run_restricted_test('rubydo print "Hello"', 'E981:') + call Run_restricted_test('rubyfile somefile', 'E981:') +endfunc + +func Test_restricted_tcl() + if !has('tcl') + throw 'Skipped: Tcl is not supported' + endif + call Run_restricted_test('tcl puts "Hello"', 'E981:') + call Run_restricted_test('tcldo puts "Hello"', 'E981:') + call Run_restricted_test('tclfile somefile', 'E981:') +endfunc From 2a818f8901558b30a393b79d77466a5b3a57d6c6 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Mon, 24 Feb 2020 20:59:56 -0500 Subject: [PATCH 11/20] vim-patch:8.1.0885: test for restricted hangs on MS-Windows GUI Problem: Test for restricted hangs on MS-Windows GUI. Solution: Skip the test. https://github.com/vim/vim/commit/18c5632cab09e5e51320f55005f310920648f35b --- src/nvim/testdir/test_restricted.vim | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/nvim/testdir/test_restricted.vim b/src/nvim/testdir/test_restricted.vim index 9dd937cf3e..85da94c418 100644 --- a/src/nvim/testdir/test_restricted.vim +++ b/src/nvim/testdir/test_restricted.vim @@ -2,6 +2,11 @@ source shared.vim +if has('win32') && has('gui') + " Win32 GUI shows a dialog instead of displaying the error in the last line. + finish +endif + func Test_restricted() let cmd = GetVimCommand('Xrestricted') if cmd == '' From ca3dba482c15d127b492c2431960d154ae88c98a Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Mon, 24 Feb 2020 21:03:39 -0500 Subject: [PATCH 12/20] vim-patch:8.1.0896: tests for restricted mode no run for MS-Windows GUI Problem: Tests for restricted mode no run for MS-Windows GUI. Solution: Make tests also work in MS-Windows GUI. https://github.com/vim/vim/commit/5a6698169d10833abad88c98e5a332ddde5d110d --- src/nvim/testdir/test_restricted.vim | 35 +++++++++++----------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/src/nvim/testdir/test_restricted.vim b/src/nvim/testdir/test_restricted.vim index 85da94c418..a29f7c33d3 100644 --- a/src/nvim/testdir/test_restricted.vim +++ b/src/nvim/testdir/test_restricted.vim @@ -2,27 +2,13 @@ source shared.vim -if has('win32') && has('gui') - " Win32 GUI shows a dialog instead of displaying the error in the last line. - finish -endif +"if has('win32') && has('gui') +" " Win32 GUI shows a dialog instead of displaying the error in the last line. +" finish +"endif func Test_restricted() - let cmd = GetVimCommand('Xrestricted') - if cmd == '' - return - endif - - call writefile([ - \ "silent !ls", - \ "call writefile([v:errmsg], 'Xrestrout')", - \ "qa!", - \ ], 'Xrestricted') - call system(cmd . ' -Z') - call assert_match('E145:', join(readfile('Xrestrout'))) - - call delete('Xrestricted') - call delete('Xrestrout') + call Run_restricted_test('!ls', 'E145:') endfunc func Run_restricted_test(ex_cmd, error) @@ -31,10 +17,15 @@ func Run_restricted_test(ex_cmd, error) return endif + " Use a VimEnter autocommand to avoid that the error message is displayed in + " a dialog with an OK button. call writefile([ - \ a:ex_cmd, - \ "call writefile([v:errmsg], 'Xrestrout')", - \ "qa!", + \ "func Init()", + \ " silent! " . a:ex_cmd, + \ " call writefile([v:errmsg], 'Xrestrout')", + \ " qa!", + \ "endfunc", + \ "au VimEnter * call Init()", \ ], 'Xrestricted') call system(cmd . ' -Z') call assert_match(a:error, join(readfile('Xrestrout'))) From 1caa85b677bc287883895558281d23e1fd55817e Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Tue, 25 Feb 2020 00:30:42 -0500 Subject: [PATCH 13/20] vim-patch:8.1.1466: not updating priority on existing sign Problem: Not updating priority on existing sign. Solution: Set the sign priority. Add a test. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/58a7f87c8653b4cb5b0794b6b88e2ec140d3d2c3 --- runtime/doc/eval.txt | 2 +- runtime/doc/sign.txt | 10 ++++++---- src/nvim/sign.c | 1 + src/nvim/testdir/test_signs.vim | 18 ++++++++++++++++++ 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index c687d15689..29c5c37bcd 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -7818,7 +7818,7 @@ sign_getplaced([{expr} [, {dict}]]) *sign_getplaced()* priority sign priority The returned signs in a buffer are ordered by their line - number. + number and priority. Returns an empty list on failure or if there are no placed signs. diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index 4e0d91dae0..e3ba4ba181 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -176,9 +176,9 @@ See |sign_place()| for the equivalent Vim script function. By default, the sign is assigned a default priority of 10. To assign a different priority value, use "priority={prio}" to - specify a value. The priority is used to determine the - highlight group used when multiple signs are placed on the - same line. + specify a value. The priority is used to determine the sign + that is displayed when multiple signs are placed on the same + line. Examples: > :sign place 5 line=3 name=sign1 file=a.py @@ -198,7 +198,9 @@ See |sign_place()| for the equivalent Vim script function. it (e.g., when the debugger has stopped at a breakpoint). The optional "group={group}" attribute can be used before - "file=" to select a sign in a particular group. + "file=" to select a sign in a particular group. The optional + "priority={prio}" attribute can be used to change the priority + of an existing sign. :sign place {id} name={name} [buffer={nr}] Same, but use buffer {nr}. If the buffer argument is not diff --git a/src/nvim/sign.c b/src/nvim/sign.c index 23dd447744..e81d09aa4b 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -284,6 +284,7 @@ void buf_addsign( && sign_in_group(sign, groupname)) { // Update an existing sign sign->typenr = typenr; + sign->priority = prio; return; } else if (lnum < sign->lnum) { insert_sign_by_lnum_prio(buf, prev, id, groupname, prio, lnum, typenr); diff --git a/src/nvim/testdir/test_signs.vim b/src/nvim/testdir/test_signs.vim index ef4b227215..806bd4b68b 100644 --- a/src/nvim/testdir/test_signs.vim +++ b/src/nvim/testdir/test_signs.vim @@ -1127,6 +1127,24 @@ func Test_sign_priority() \ 'priority' : 10}], \ s[0].signs) + " Place multiple signs with same id on a line with different priority + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 5, 'priority' : 20}) + call sign_place(1, '', 'sign2', 'Xsign', + \ {'lnum' : 5, 'priority' : 10}) + let s = sign_getplaced('Xsign', {'lnum' : 5}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign2', 'lnum' : 5, 'group' : '', + \ 'priority' : 10}], + \ s[0].signs) + call sign_place(1, '', 'sign2', 'Xsign', + \ {'lnum' : 5, 'priority' : 5}) + let s = sign_getplaced('Xsign', {'lnum' : 5}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign2', 'lnum' : 5, 'group' : '', + \ 'priority' : 5}], + \ s[0].signs) + " Error case call assert_fails("call sign_place(1, 'g1', 'sign1', 'Xsign', \ [])", 'E715:') From c6481f70c22899604b7707299bb96d0f0768334f Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Tue, 25 Feb 2020 00:35:19 -0500 Subject: [PATCH 14/20] vim-patch:8.1.1489: sign order wrong when priority was changed Problem: Sign order wrong when priority was changed. Solution: Reorder signs when priority is changed. (Yegappan Lakshmanan, closes vim/vim#4502) https://github.com/vim/vim/commit/64416127fc184b5544530afe818722679158f059 --- src/nvim/sign.c | 76 ++++++++ src/nvim/testdir/test_signs.vim | 295 ++++++++++++++++++++++++++++++++ 2 files changed, 371 insertions(+) diff --git a/src/nvim/sign.c b/src/nvim/sign.c index e81d09aa4b..baa9c6538f 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -265,6 +265,81 @@ dict_T * sign_get_info(signlist_T *sign) return d; } +// Sort the signs placed on the same line as "sign" by priority. Invoked after +// changing the priority of an already placed sign. Assumes the signs in the +// buffer are sorted by line number and priority. +static void sign_sort_by_prio_on_line(buf_T *buf, signlist_T *sign) + FUNC_ATTR_NONNULL_ALL +{ + // If there is only one sign in the buffer or only one sign on the line or + // the sign is already sorted by priority, then return. + if ((sign->prev == NULL + || sign->prev->lnum != sign->lnum + || sign->prev->priority > sign->priority) + && (sign->next == NULL + || sign->next->lnum != sign->lnum + || sign->next->priority < sign->priority)) { + return; + } + + // One or more signs on the same line as 'sign' + // Find a sign after which 'sign' should be inserted + + // First search backward for a sign with higher priority on the same line + signlist_T *p = sign; + while (p->prev != NULL + && p->prev->lnum == sign->lnum + && p->prev->priority <= sign->priority) { + p = p->prev; + } + if (p == sign) { + // Sign not found. Search forward for a sign with priority just before + // 'sign'. + p = sign->next; + while (p->next != NULL + && p->next->lnum == sign->lnum + && p->next->priority > sign->priority) { + p = p->next; + } + } + + // Remove 'sign' from the list + if (buf->b_signlist == sign) { + buf->b_signlist = sign->next; + } + if (sign->prev != NULL) { + sign->prev->next = sign->next; + } + if (sign->next != NULL) { + sign->next->prev = sign->prev; + } + sign->prev = NULL; + sign->next = NULL; + + // Re-insert 'sign' at the right place + if (p->priority <= sign->priority) { + // 'sign' has a higher priority and should be inserted before 'p' + sign->prev = p->prev; + sign->next = p; + p->prev = sign; + if (sign->prev != NULL) { + sign->prev->next = sign; + } + if (buf->b_signlist == p) { + buf->b_signlist = sign; + } + } else { + // 'sign' has a lower priority and should be inserted after 'p' + sign->prev = p; + sign->next = p->next; + p->next = sign; + if (sign->next != NULL) { + sign->next->prev = sign; + } + } +} + + /// Add the sign into the signlist. Find the right spot to do it though. void buf_addsign( buf_T *buf, // buffer to store sign in @@ -285,6 +360,7 @@ void buf_addsign( // Update an existing sign sign->typenr = typenr; sign->priority = prio; + sign_sort_by_prio_on_line(buf, sign); return; } else if (lnum < sign->lnum) { insert_sign_by_lnum_prio(buf, prev, id, groupname, prio, lnum, typenr); diff --git a/src/nvim/testdir/test_signs.vim b/src/nvim/testdir/test_signs.vim index 806bd4b68b..6af81e15c5 100644 --- a/src/nvim/testdir/test_signs.vim +++ b/src/nvim/testdir/test_signs.vim @@ -1127,6 +1127,301 @@ func Test_sign_priority() \ 'priority' : 10}], \ s[0].signs) + call sign_unplace('*') + + " Three signs on different lines with changing priorities + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 11, 'priority' : 50}) + call sign_place(2, '', 'sign2', 'Xsign', + \ {'lnum' : 12, 'priority' : 60}) + call sign_place(3, '', 'sign3', 'Xsign', + \ {'lnum' : 13, 'priority' : 70}) + call sign_place(2, '', 'sign2', 'Xsign', + \ {'lnum' : 12, 'priority' : 40}) + call sign_place(3, '', 'sign3', 'Xsign', + \ {'lnum' : 13, 'priority' : 30}) + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 11, 'priority' : 50}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 11, 'group' : '', + \ 'priority' : 50}, + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 12, 'group' : '', + \ 'priority' : 40}, + \ {'id' : 3, 'name' : 'sign3', 'lnum' : 13, 'group' : '', + \ 'priority' : 30}], + \ s[0].signs) + + call sign_unplace('*') + + " Two signs on the same line with changing priorities + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 20}) + call sign_place(2, '', 'sign2', 'Xsign', + \ {'lnum' : 4, 'priority' : 30}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 30}, + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}], + \ s[0].signs) + " Change the priority of the last sign to highest + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 40}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 40}, + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 30}], + \ s[0].signs) + " Change the priority of the first sign to lowest + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 25}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 30}, + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 25}], + \ s[0].signs) + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 45}) + call sign_place(2, '', 'sign2', 'Xsign', + \ {'lnum' : 4, 'priority' : 55}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 55}, + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 45}], + \ s[0].signs) + + call sign_unplace('*') + + " Three signs on the same line with changing priorities + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 40}) + call sign_place(2, '', 'sign2', 'Xsign', + \ {'lnum' : 4, 'priority' : 30}) + call sign_place(3, '', 'sign3', 'Xsign', + \ {'lnum' : 4, 'priority' : 20}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 40}, + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 30}, + \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}], + \ s[0].signs) + + " Change the priority of the middle sign to the highest + call sign_place(2, '', 'sign2', 'Xsign', + \ {'lnum' : 4, 'priority' : 50}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 50}, + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 40}, + \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}], + \ s[0].signs) + + " Change the priority of the middle sign to the lowest + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 15}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 50}, + \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 15}], + \ s[0].signs) + + " Change the priority of the last sign to the highest + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 55}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 55}, + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 50}, + \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}], + \ s[0].signs) + + " Change the priority of the first sign to the lowest + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 15}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 50}, + \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 15}], + \ s[0].signs) + + call sign_unplace('*') + + " Three signs on the same line with changing priorities along with other + " signs + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 2, 'priority' : 10}) + call sign_place(2, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 30}) + call sign_place(3, '', 'sign2', 'Xsign', + \ {'lnum' : 4, 'priority' : 20}) + call sign_place(4, '', 'sign3', 'Xsign', + \ {'lnum' : 4, 'priority' : 25}) + call sign_place(5, '', 'sign2', 'Xsign', + \ {'lnum' : 6, 'priority' : 80}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '', + \ 'priority' : 10}, + \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 30}, + \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 25}, + \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '', + \ 'priority' : 80}], + \ s[0].signs) + + " Change the priority of the first sign to lowest + call sign_place(2, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 15}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '', + \ 'priority' : 10}, + \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 25}, + \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 15}, + \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '', + \ 'priority' : 80}], + \ s[0].signs) + + " Change the priority of the last sign to highest + call sign_place(2, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 30}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '', + \ 'priority' : 10}, + \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 30}, + \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 25}, + \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '', + \ 'priority' : 80}], + \ s[0].signs) + + " Change the priority of the middle sign to lowest + call sign_place(4, '', 'sign3', 'Xsign', + \ {'lnum' : 4, 'priority' : 15}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '', + \ 'priority' : 10}, + \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 30}, + \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 15}, + \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '', + \ 'priority' : 80}], + \ s[0].signs) + + " Change the priority of the middle sign to highest + call sign_place(3, '', 'sign2', 'Xsign', + \ {'lnum' : 4, 'priority' : 35}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '', + \ 'priority' : 10}, + \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 35}, + \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 30}, + \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 15}, + \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '', + \ 'priority' : 80}], + \ s[0].signs) + + call sign_unplace('*') + + " Multiple signs with the same priority on the same line + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 20}) + call sign_place(2, '', 'sign2', 'Xsign', + \ {'lnum' : 4, 'priority' : 20}) + call sign_place(3, '', 'sign3', 'Xsign', + \ {'lnum' : 4, 'priority' : 20}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}], + \ s[0].signs) + " Place the last sign again with the same priority + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 20}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}], + \ s[0].signs) + " Place the first sign again with the same priority + call sign_place(1, '', 'sign1', 'Xsign', + \ {'lnum' : 4, 'priority' : 20}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}], + \ s[0].signs) + " Place the middle sign again with the same priority + call sign_place(3, '', 'sign3', 'Xsign', + \ {'lnum' : 4, 'priority' : 20}) + let s = sign_getplaced('Xsign', {'group' : '*'}) + call assert_equal([ + \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}, + \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '', + \ 'priority' : 20}], + \ s[0].signs) + + call sign_unplace('*') + " Place multiple signs with same id on a line with different priority call sign_place(1, '', 'sign1', 'Xsign', \ {'lnum' : 5, 'priority' : 20}) From b376bb49b5a1f71b05389857f324bc6820ede747 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Tue, 25 Feb 2020 00:43:06 -0500 Subject: [PATCH 15/20] vim-patch:8.1.1552: cursor position is wrong after sign column changes Problem: Cursor position is wrong after sign column appears or disappears. (Yegappan Lakshmanan) Solution: Call changed_line_abv_curs() instead of changed_cline_bef_curs(). https://github.com/vim/vim/commit/f85e40afc204c241c6a01023be3e7b8101d36367 --- src/nvim/sign.c | 10 +++++----- src/nvim/testdir/test_signs.vim | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/nvim/sign.c b/src/nvim/sign.c index baa9c6538f..079e95ada8 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -198,7 +198,7 @@ static void insert_sign( // column for signs. if (buf->b_signlist == NULL) { redraw_buf_later(buf, NOT_VALID); - changed_cline_bef_curs(); + changed_line_abv_curs(); } // first sign in signlist @@ -495,11 +495,11 @@ linenr_T buf_delsign( } } - // When deleted the last sign needs to redraw the windows to remove the - // sign column. + // When deleting the last sign the cursor position may change, because the + // sign columns no longer shows. And the 'signcolumn' may be hidden. if (buf->b_signlist == NULL) { redraw_buf_later(buf, NOT_VALID); - changed_cline_bef_curs(); + changed_line_abv_curs(); } return lnum; @@ -572,7 +572,7 @@ void buf_delete_signs(buf_T *buf, char_u *group) // When deleting the last sign need to redraw the windows to remove the // sign column. Not when curwin is NULL (this means we're exiting). if (buf->b_signlist != NULL && curwin != NULL) { - changed_cline_bef_curs(); + changed_line_abv_curs(); } lastp = &buf->b_signlist; diff --git a/src/nvim/testdir/test_signs.vim b/src/nvim/testdir/test_signs.vim index 6af81e15c5..dcbb546a2e 100644 --- a/src/nvim/testdir/test_signs.vim +++ b/src/nvim/testdir/test_signs.vim @@ -4,6 +4,8 @@ if !has('signs') finish endif +source screendump.vim + func Test_sign() new call setline(1, ['a', 'b', 'c', 'd']) @@ -1652,3 +1654,31 @@ func Test_sign_jump_func() sign undefine sign1 enew! | only! endfunc + +" Test for correct cursor position after the sign column appears or disappears. +func Test_sign_cursor_position() + if !CanRunVimInTerminal() + throw 'Skipped: cannot make screendumps' + endif + + let lines =<< trim END + call setline(1, [repeat('x', 75), 'mmmm', 'yyyy']) + call cursor(2,1) + sign define s1 texthl=Search text==> + redraw + sign place 10 line=2 name=s1 + END + call writefile(lines, 'XtestSigncolumn') + let buf = RunVimInTerminal('-S XtestSigncolumn', {'rows': 6}) + call VerifyScreenDump(buf, 'Test_sign_cursor_01', {}) + + " update cursor position calculation + call term_sendkeys(buf, "lh") + call term_sendkeys(buf, ":sign unplace 10\") + call VerifyScreenDump(buf, 'Test_sign_cursor_02', {}) + + + " clean up + call StopVimInTerminal(buf) + call delete('XtestSigncolumn') +endfunc From c40bb2de7ac5cfb3e2b6d45591f0fea8642be1cd Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Tue, 25 Feb 2020 23:03:14 -0500 Subject: [PATCH 16/20] vim-patch:8.1.0939: no completion for sign group names Problem: No completion for sign group names. Solution: Add completion for sign group names and buffer names. (Yegappan Lakshmanan, closes vim/vim#3980) https://github.com/vim/vim/commit/3678f65d43d10b36dc62738aab2f341fa1e18a32 --- src/nvim/charset.c | 1 + src/nvim/sign.c | 115 +++++++++++++++++++++----------- src/nvim/testdir/test_signs.vim | 64 ++++++++++++++++-- 3 files changed, 138 insertions(+), 42 deletions(-) diff --git a/src/nvim/charset.c b/src/nvim/charset.c index 0f9e2e23c0..f9d5adbc12 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -1570,6 +1570,7 @@ char_u* skiptohex(char_u *q) /// /// @return Pointer to the next whitespace or NUL character. char_u *skiptowhite(const char_u *p) + FUNC_ATTR_NONNULL_ALL { while (*p != ' ' && *p != '\t' && *p != NUL) { p++; diff --git a/src/nvim/sign.c b/src/nvim/sign.c index 079e95ada8..e22a177178 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -1608,10 +1608,44 @@ static enum EXP_SUBCMD, // expand :sign sub-commands EXP_DEFINE, // expand :sign define {name} args EXP_PLACE, // expand :sign place {id} args + EXP_LIST, // expand :sign place args EXP_UNPLACE, // expand :sign unplace" - EXP_SIGN_NAMES // expand with name of placed signs + EXP_SIGN_NAMES, // expand with name of placed signs + EXP_SIGN_GROUPS, // expand with name of placed sign groups } expand_what; +// Return the n'th sign name (used for command line completion) +static char_u *get_nth_sign_name(int idx) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + // Complete with name of signs already defined + int current_idx = 0; + for (sign_T *sp = first_sign; sp != NULL; sp = sp->sn_next) { + if (current_idx++ == idx) { + return sp->sn_name; + } + } + return NULL; +} + +// Return the n'th sign group name (used for command line completion) +static char_u *get_nth_sign_group_name(int idx) +{ + // Complete with name of sign groups already defined + int current_idx = 0; + int todo = (int)sg_table.ht_used; + for (hashitem_T *hi = sg_table.ht_array; todo > 0; hi++) { + if (!HASHITEM_EMPTY(hi)) { + todo--; + if (current_idx++ == idx) { + signgroup_T *const group = HI2SG(hi); + return group->sg_name; + } + } + } + return NULL; +} + /// Function given to ExpandGeneric() to obtain the sign command /// expansion. char_u * get_sign_name(expand_T *xp, int idx) @@ -1629,20 +1663,18 @@ char_u * get_sign_name(expand_T *xp, int idx) "buffer=", NULL }; return (char_u *)place_arg[idx]; } + case EXP_LIST: { + char *list_arg[] = { "group=", "file=", "buffer=", NULL }; + return (char_u *)list_arg[idx]; + } case EXP_UNPLACE: { char *unplace_arg[] = { "group=", "file=", "buffer=", NULL }; return (char_u *)unplace_arg[idx]; } - case EXP_SIGN_NAMES: { - // Complete with name of signs already defined - int current_idx = 0; - for (sign_T *sp = first_sign; sp != NULL; sp = sp->sn_next) { - if (current_idx++ == idx) { - return sp->sn_name; - } - } - } - return NULL; + case EXP_SIGN_NAMES: + return get_nth_sign_name(idx); + case EXP_SIGN_GROUPS: + return get_nth_sign_group_name(idx); default: return NULL; } @@ -1651,7 +1683,6 @@ char_u * get_sign_name(expand_T *xp, int idx) /// Handle command line completion for :sign command. void set_context_in_sign_cmd(expand_T *xp, char_u *arg) { - char_u *p; char_u *end_subcmd; char_u *last; int cmd_idx; @@ -1675,26 +1706,6 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg) // | // begin_subcmd_args begin_subcmd_args = skipwhite(end_subcmd); - p = skiptowhite(begin_subcmd_args); - if (*p == NUL) { - // - // Expand first argument of subcmd when possible. - // For ":jump {id}" and ":unplace {id}", we could - // possibly expand the ids of all signs already placed. - // - xp->xp_pattern = begin_subcmd_args; - switch (cmd_idx) { - case SIGNCMD_LIST: - case SIGNCMD_UNDEFINE: - // :sign list - // :sign undefine - expand_what = EXP_SIGN_NAMES; - break; - default: - xp->xp_context = EXPAND_NOTHING; - } - return; - } // Expand last argument of subcmd. // @@ -1703,6 +1714,7 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg) // p // Loop until reaching last argument. + char_u *p = begin_subcmd_args; do { p = skipwhite(p); last = p; @@ -1722,7 +1734,20 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg) expand_what = EXP_DEFINE; break; case SIGNCMD_PLACE: - expand_what = EXP_PLACE; + // List placed signs + if (ascii_isdigit(*begin_subcmd_args)) { + // :sign place {id} {args}... + expand_what = EXP_PLACE; + } else { + // :sign place {args}... + expand_what = EXP_LIST; + } + break; + case SIGNCMD_LIST: + case SIGNCMD_UNDEFINE: + // :sign list + // :sign undefine + expand_what = EXP_SIGN_NAMES; break; case SIGNCMD_JUMP: case SIGNCMD_UNPLACE: @@ -1736,19 +1761,33 @@ void set_context_in_sign_cmd(expand_T *xp, char_u *arg) xp->xp_pattern = p + 1; switch (cmd_idx) { case SIGNCMD_DEFINE: - if (STRNCMP(last, "texthl", p - last) == 0 - || STRNCMP(last, "linehl", p - last) == 0 - || STRNCMP(last, "numhl", p - last) == 0) { + if (STRNCMP(last, "texthl", 6) == 0 + || STRNCMP(last, "linehl", 6) == 0 + || STRNCMP(last, "numhl", 5) == 0) { xp->xp_context = EXPAND_HIGHLIGHT; - } else if (STRNCMP(last, "icon", p - last) == 0) { + } else if (STRNCMP(last, "icon", 4) == 0) { xp->xp_context = EXPAND_FILES; } else { xp->xp_context = EXPAND_NOTHING; } break; case SIGNCMD_PLACE: - if (STRNCMP(last, "name", p - last) == 0) { + if (STRNCMP(last, "name", 4) == 0) { expand_what = EXP_SIGN_NAMES; + } else if (STRNCMP(last, "group", 5) == 0) { + expand_what = EXP_SIGN_GROUPS; + } else if (STRNCMP(last, "file", 4) == 0) { + xp->xp_context = EXPAND_BUFFERS; + } else { + xp->xp_context = EXPAND_NOTHING; + } + break; + case SIGNCMD_UNPLACE: + case SIGNCMD_JUMP: + if (STRNCMP(last, "group", 5) == 0) { + expand_what = EXP_SIGN_GROUPS; + } else if (STRNCMP(last, "file", 4) == 0) { + xp->xp_context = EXPAND_BUFFERS; } else { xp->xp_context = EXPAND_NOTHING; } diff --git a/src/nvim/testdir/test_signs.vim b/src/nvim/testdir/test_signs.vim index dcbb546a2e..b80e41bd0c 100644 --- a/src/nvim/testdir/test_signs.vim +++ b/src/nvim/testdir/test_signs.vim @@ -212,13 +212,16 @@ func Test_sign_completion() call assert_equal('"sign define Sign linehl=SpellBad SpellCap ' . \ 'SpellLocal SpellRare', @:) - call writefile(['foo'], 'XsignOne') - call writefile(['bar'], 'XsignTwo') + call feedkeys(":sign define Sign texthl=Spell\\\"\", 'tx') + call assert_equal('"sign define Sign texthl=SpellBad SpellCap ' . + \ 'SpellLocal SpellRare', @:) + + call writefile(repeat(["Sun is shining"], 30), "XsignOne") + call writefile(repeat(["Sky is blue"], 30), "XsignTwo") call feedkeys(":sign define Sign icon=Xsig\\\"\", 'tx') call assert_equal('"sign define Sign icon=XsignOne XsignTwo', @:) - call delete('XsignOne') - call delete('XsignTwo') + " Test for completion of arguments to ':sign undefine' call feedkeys(":sign undefine \\\"\", 'tx') call assert_equal('"sign undefine Sign1 Sign2', @:) @@ -229,17 +232,70 @@ func Test_sign_completion() call feedkeys(":sign place 1 name=\\\"\", 'tx') call assert_equal('"sign place 1 name=Sign1 Sign2', @:) + edit XsignOne + sign place 1 name=Sign1 line=5 + sign place 1 name=Sign1 group=g1 line=10 + edit XsignTwo + sign place 1 name=Sign2 group=g2 line=15 + + " Test for completion of group= and file= arguments to ':sign place' + call feedkeys(":sign place 1 name=Sign1 file=Xsign\\\"\", 'tx') + call assert_equal('"sign place 1 name=Sign1 file=XsignOne XsignTwo', @:) + call feedkeys(":sign place 1 name=Sign1 group=\\\"\", 'tx') + call assert_equal('"sign place 1 name=Sign1 group=g1 g2', @:) + + " Test for completion of arguments to 'sign place' without sign identifier + call feedkeys(":sign place \\\"\", 'tx') + call assert_equal('"sign place buffer= file= group=', @:) + call feedkeys(":sign place file=Xsign\\\"\", 'tx') + call assert_equal('"sign place file=XsignOne XsignTwo', @:) + call feedkeys(":sign place group=\\\"\", 'tx') + call assert_equal('"sign place group=g1 g2', @:) + call feedkeys(":sign place group=g1 file=\\\"\", 'tx') + call assert_equal('"sign place group=g1 file=XsignOne XsignTwo', @:) + + " Test for completion of arguments to ':sign unplace' call feedkeys(":sign unplace 1 \\\"\", 'tx') call assert_equal('"sign unplace 1 buffer= file= group=', @:) + call feedkeys(":sign unplace 1 file=Xsign\\\"\", 'tx') + call assert_equal('"sign unplace 1 file=XsignOne XsignTwo', @:) + call feedkeys(":sign unplace 1 group=\\\"\", 'tx') + call assert_equal('"sign unplace 1 group=g1 g2', @:) + call feedkeys(":sign unplace 1 group=g2 file=Xsign\\\"\", 'tx') + call assert_equal('"sign unplace 1 group=g2 file=XsignOne XsignTwo', @:) + " Test for completion of arguments to ':sign list' call feedkeys(":sign list \\\"\", 'tx') call assert_equal('"sign list Sign1 Sign2', @:) + " Test for completion of arguments to ':sign jump' call feedkeys(":sign jump 1 \\\"\", 'tx') call assert_equal('"sign jump 1 buffer= file= group=', @:) + call feedkeys(":sign jump 1 file=Xsign\\\"\", 'tx') + call assert_equal('"sign jump 1 file=XsignOne XsignTwo', @:) + call feedkeys(":sign jump 1 group=\\\"\", 'tx') + call assert_equal('"sign jump 1 group=g1 g2', @:) + " Error cases + call feedkeys(":sign here\\\"\", 'tx') + call assert_equal('"sign here', @:) + call feedkeys(":sign define Sign here=\\\"\", 'tx') + call assert_equal("\"sign define Sign here=\", @:) + call feedkeys(":sign place 1 here=\\\"\", 'tx') + call assert_equal("\"sign place 1 here=\", @:) + call feedkeys(":sign jump 1 here=\\\"\", 'tx') + call assert_equal("\"sign jump 1 here=\", @:) + call feedkeys(":sign here there\\\"\", 'tx') + call assert_equal("\"sign here there\", @:) + call feedkeys(":sign here there=\\\"\", 'tx') + call assert_equal("\"sign here there=\", @:) + + sign unplace * group=* sign undefine Sign1 sign undefine Sign2 + enew + call delete('XsignOne') + call delete('XsignTwo') endfunc func Test_sign_invalid_commands() From 4ccbc8d56eb7aea41c87a835be52396b945a0143 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Wed, 26 Feb 2020 02:07:35 -0500 Subject: [PATCH 17/20] vim-patch:8.2.0108: when sign text is changed a manual redraw is needed Problem: When sign text is changed a manual redraw is needed. (Pontus Lietzler) Solution: Redraw automatically. (closes vim/vim#5455) https://github.com/vim/vim/commit/bf0acff012c2f75563c20241f1a5478534fe2c7a --- src/nvim/sign.c | 8 ++++++++ src/nvim/testdir/test_signs.vim | 8 ++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/nvim/sign.c b/src/nvim/sign.c index e22a177178..ab5d04d39b 100644 --- a/src/nvim/sign.c +++ b/src/nvim/sign.c @@ -831,6 +831,14 @@ int sign_define_by_name( } else { sp_prev->sn_next = sp; } + } else { + // Signs may already exist, a redraw is needed in windows with a + // non-empty sign list. + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + if (wp->w_buffer->b_signlist != NULL) { + redraw_buf_later(wp->w_buffer, NOT_VALID); + } + } } // set values for a defined sign. diff --git a/src/nvim/testdir/test_signs.vim b/src/nvim/testdir/test_signs.vim index b80e41bd0c..8b1927e4f0 100644 --- a/src/nvim/testdir/test_signs.vim +++ b/src/nvim/testdir/test_signs.vim @@ -1726,12 +1726,16 @@ func Test_sign_cursor_position() END call writefile(lines, 'XtestSigncolumn') let buf = RunVimInTerminal('-S XtestSigncolumn', {'rows': 6}) - call VerifyScreenDump(buf, 'Test_sign_cursor_01', {}) + call VerifyScreenDump(buf, 'Test_sign_cursor_1', {}) + + " Change the sign text + call term_sendkeys(buf, ":sign define s1 text=-)\") + call VerifyScreenDump(buf, 'Test_sign_cursor_2', {}) " update cursor position calculation call term_sendkeys(buf, "lh") call term_sendkeys(buf, ":sign unplace 10\") - call VerifyScreenDump(buf, 'Test_sign_cursor_02', {}) + call VerifyScreenDump(buf, 'Test_sign_cursor_3', {}) " clean up From e6c9db6ede33127909a913dd428eb63d71a24fcd Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Fri, 28 Feb 2020 03:10:25 -0500 Subject: [PATCH 18/20] vim-patch:8.1.1107: no test for 'visualbell' Problem: No test for 'visualbell'. Solution: Add a test. https://github.com/vim/vim/commit/b4e6a2d07510e18e6720d6b2ee0b029f95430964 --- src/nvim/testdir/test_options.vim | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index 29d391c232..5b9dd7b50a 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -511,3 +511,9 @@ func Test_shortmess_F2() bwipe bwipe endfunc + +func Test_visualbell() + set visualbell + call assert_beeps('normal 0h') + set novisualbell +endfunc From ad0587133f6f805fb75c7bcfede48cd7d50fd556 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Fri, 28 Feb 2020 03:12:03 -0500 Subject: [PATCH 19/20] vim-patch:8.1.1108: test for 'visualbell' doesn't work Problem: Test for 'visualbell' doesn't work. Solution: Make 'belloff' empty. https://github.com/vim/vim/commit/7a66627cf43412604a28e0d99df8f96a29ff1c3a --- src/nvim/testdir/test_options.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index 5b9dd7b50a..c2f710358b 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -513,7 +513,9 @@ func Test_shortmess_F2() endfunc func Test_visualbell() + set belloff= set visualbell call assert_beeps('normal 0h') set novisualbell + set belloff=all endfunc From f1923d4b92239ef2ca280bf1ce6c5f6cc7cb4f1a Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 29 Feb 2020 15:19:23 -0500 Subject: [PATCH 20/20] vim-patch:8.1.1793: mixed comment style in globals Problem: Mixed comment style in globals. Solution: Use // comments where appropriate. https://github.com/vim/vim/commit/1ccaa35abf0706de3516b3013fe12964abada079 --- src/nvim/globals.h | 517 ++++++++++++++++++++------------------------- 1 file changed, 232 insertions(+), 285 deletions(-) diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 9069c5adcb..ccf704fe76 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -120,24 +120,20 @@ typedef off_t off_T; # endif #endif -/* - * When vgetc() is called, it sets mod_mask to the set of modifiers that are - * held down based on the MOD_MASK_* symbols that are read first. - */ -EXTERN int mod_mask INIT(= 0x0); /* current key modifiers */ +// When vgetc() is called, it sets mod_mask to the set of modifiers that are +// held down based on the MOD_MASK_* symbols that are read first. +EXTERN int mod_mask INIT(= 0x0); // current key modifiers EXTERN bool lua_attr_active INIT(= false); -/* - * Cmdline_row is the row where the command line starts, just below the - * last window. - * When the cmdline gets longer than the available space the screen gets - * scrolled up. After a CTRL-D (show matches), after hitting ':' after - * "hit return", and for the :global command, the command line is - * temporarily moved. The old position is restored with the next call to - * update_screen(). - */ +// Cmdline_row is the row where the command line starts, just below the +// last window. +// When the cmdline gets longer than the available space the screen gets +// scrolled up. After a CTRL-D (show matches), after hitting ':' after +// "hit return", and for the :global command, the command line is +// temporarily moved. The old position is restored with the next call to +// update_screen(). EXTERN int cmdline_row; EXTERN int redraw_cmdline INIT(= false); // cmdline must be redrawn @@ -149,42 +145,38 @@ EXTERN int cmdline_was_last_drawn INIT(= false); // cmdline was last drawn EXTERN int exec_from_reg INIT(= false); // executing register -/* - * When '$' is included in 'cpoptions' option set: - * When a change command is given that deletes only part of a line, a dollar - * is put at the end of the changed text. dollar_vcol is set to the virtual - * column of this '$'. -1 is used to indicate no $ is being displayed. - */ +// When '$' is included in 'cpoptions' option set: +// When a change command is given that deletes only part of a line, a dollar +// is put at the end of the changed text. dollar_vcol is set to the virtual +// column of this '$'. -1 is used to indicate no $ is being displayed. EXTERN colnr_T dollar_vcol INIT(= -1); -/* - * Variables for Insert mode completion. - */ +// Variables for Insert mode completion. -/* Length in bytes of the text being completed (this is deleted to be replaced - * by the match.) */ +// Length in bytes of the text being completed (this is deleted to be replaced +// by the match.) EXTERN int compl_length INIT(= 0); -/* Set when character typed while looking for matches and it means we should - * stop looking for matches. */ -EXTERN int compl_interrupted INIT(= FALSE); +// Set when character typed while looking for matches and it means we should +// stop looking for matches. +EXTERN int compl_interrupted INIT(= false); // Set when doing something for completion that may call edit() recursively, // which is not allowed. Also used to disable folding during completion EXTERN int compl_busy INIT(= false); -/* List of flags for method of completion. */ +// List of flags for method of completion. EXTERN int compl_cont_status INIT(= 0); -# define CONT_ADDING 1 /* "normal" or "adding" expansion */ -# define CONT_INTRPT (2 + 4) /* a ^X interrupted the current expansion */ - /* it's set only iff N_ADDS is set */ -# define CONT_N_ADDS 4 /* next ^X<> will add-new or expand-current */ -# define CONT_S_IPOS 8 /* next ^X<> will set initial_pos? - * if so, word-wise-expansion will set SOL */ -# define CONT_SOL 16 /* pattern includes start of line, just for - * word-wise expansion, not set for ^X^L */ -# define CONT_LOCAL 32 /* for ctrl_x_mode 0, ^X^P/^X^N do a local - * expansion, (eg use complete=.) */ +# define CONT_ADDING 1 // "normal" or "adding" expansion +# define CONT_INTRPT (2 + 4) // a ^X interrupted the current expansion + // it's set only iff N_ADDS is set +# define CONT_N_ADDS 4 // next ^X<> will add-new or expand-current +# define CONT_S_IPOS 8 // next ^X<> will set initial_pos? + // if so, word-wise-expansion will set SOL +# define CONT_SOL 16 // pattern includes start of line, just for + // word-wise expansion, not set for ^X^L +# define CONT_LOCAL 32 // for ctrl_x_mode 0, ^X^P/^X^N do a local + // expansion, (eg use complete=.) // state for putting characters in the message area EXTERN int cmdmsg_rl INIT(= false); // cmdline is drawn right to left @@ -200,49 +192,49 @@ EXTERN bool msg_scrolled_ign INIT(= false); EXTERN bool msg_did_scroll INIT(= false); -EXTERN char_u *keep_msg INIT(= NULL); /* msg to be shown after redraw */ -EXTERN int keep_msg_attr INIT(= 0); /* highlight attr for keep_msg */ -EXTERN int keep_msg_more INIT(= FALSE); /* keep_msg was set by msgmore() */ -EXTERN int need_fileinfo INIT(= FALSE); /* do fileinfo() after redraw */ -EXTERN int msg_scroll INIT(= FALSE); /* msg_start() will scroll */ -EXTERN int msg_didout INIT(= FALSE); /* msg_outstr() was used in line */ -EXTERN int msg_didany INIT(= FALSE); /* msg_outstr() was used at all */ -EXTERN int msg_nowait INIT(= FALSE); /* don't wait for this msg */ -EXTERN int emsg_off INIT(= 0); /* don't display errors for now, - unless 'debug' is set. */ -EXTERN int info_message INIT(= FALSE); /* printing informative message */ -EXTERN int msg_hist_off INIT(= FALSE); /* don't add messages to history */ -EXTERN int need_clr_eos INIT(= FALSE); /* need to clear text before - displaying a message. */ -EXTERN int emsg_skip INIT(= 0); /* don't display errors for - expression that is skipped */ -EXTERN int emsg_severe INIT(= FALSE); /* use message of next of several - emsg() calls for throw */ -EXTERN int did_endif INIT(= FALSE); /* just had ":endif" */ -EXTERN dict_T vimvardict; /* Dictionary with v: variables */ -EXTERN dict_T globvardict; /* Dictionary with g: variables */ -EXTERN int did_emsg; /* set by emsg() when the message - is displayed or thrown */ +EXTERN char_u *keep_msg INIT(= NULL); // msg to be shown after redraw +EXTERN int keep_msg_attr INIT(= 0); // highlight attr for keep_msg +EXTERN int keep_msg_more INIT(= false); // keep_msg was set by msgmore() +EXTERN int need_fileinfo INIT(= false); // do fileinfo() after redraw +EXTERN int msg_scroll INIT(= false); // msg_start() will scroll +EXTERN int msg_didout INIT(= false); // msg_outstr() was used in line +EXTERN int msg_didany INIT(= false); // msg_outstr() was used at all +EXTERN int msg_nowait INIT(= false); // don't wait for this msg +EXTERN int emsg_off INIT(= 0); // don't display errors for now, + // unless 'debug' is set. +EXTERN int info_message INIT(= false); // printing informative message +EXTERN int msg_hist_off INIT(= false); // don't add messages to history +EXTERN int need_clr_eos INIT(= false); // need to clear text before + // displaying a message. +EXTERN int emsg_skip INIT(= 0); // don't display errors for + // expression that is skipped +EXTERN int emsg_severe INIT(= false); // use message of next of several + // emsg() calls for throw +EXTERN int did_endif INIT(= false); // just had ":endif" +EXTERN dict_T vimvardict; // Dictionary with v: variables +EXTERN dict_T globvardict; // Dictionary with g: variables +EXTERN int did_emsg; // set by emsg() when the message + // is displayed or thrown EXTERN bool called_vim_beep; // set if vim_beep() is called -EXTERN int did_emsg_syntax; /* did_emsg set because of a - syntax error */ -EXTERN int called_emsg; /* always set by emsg() */ -EXTERN int ex_exitval INIT(= 0); /* exit value for ex mode */ -EXTERN int emsg_on_display INIT(= FALSE); /* there is an error message */ -EXTERN int rc_did_emsg INIT(= FALSE); /* vim_regcomp() called emsg() */ +EXTERN int did_emsg_syntax; // did_emsg set because of a + // syntax error +EXTERN int called_emsg; // always set by emsg() +EXTERN int ex_exitval INIT(= 0); // exit value for ex mode +EXTERN int emsg_on_display INIT(= false); // there is an error message +EXTERN int rc_did_emsg INIT(= false); // vim_regcomp() called emsg() -EXTERN int no_wait_return INIT(= 0); /* don't wait for return for now */ -EXTERN int need_wait_return INIT(= 0); /* need to wait for return later */ -EXTERN int did_wait_return INIT(= FALSE); /* wait_return() was used and - nothing written since then */ -EXTERN int need_maketitle INIT(= TRUE); /* call maketitle() soon */ +EXTERN int no_wait_return INIT(= 0); // don't wait for return for now +EXTERN int need_wait_return INIT(= 0); // need to wait for return later +EXTERN int did_wait_return INIT(= false); // wait_return() was used and + // nothing written since then +EXTERN int need_maketitle INIT(= true); // call maketitle() soon EXTERN int quit_more INIT(= false); // 'q' hit at "--more--" msg EXTERN int ex_keep_indent INIT(= false); // getexmodeline(): keep indent EXTERN int vgetc_busy INIT(= 0); // when inside vgetc() then > 0 -EXTERN int didset_vim INIT(= FALSE); /* did set $VIM ourselves */ -EXTERN int didset_vimruntime INIT(= FALSE); /* idem for $VIMRUNTIME */ +EXTERN int didset_vim INIT(= false); // did set $VIM ourselves +EXTERN int didset_vimruntime INIT(= false); // idem for $VIMRUNTIME /// Lines left before a "more" message. Ex mode needs to be able to reset this /// after you type something. @@ -250,8 +242,8 @@ EXTERN int lines_left INIT(= -1); // lines left for listing EXTERN int msg_no_more INIT(= false); // don't use more prompt, truncate // messages -EXTERN char_u *sourcing_name INIT( = NULL); /* name of error message source */ -EXTERN linenr_T sourcing_lnum INIT(= 0); /* line number of the source file */ +EXTERN char_u *sourcing_name INIT(= NULL); // name of error message source +EXTERN linenr_T sourcing_lnum INIT(= 0); // line number of the source file EXTERN int ex_nesting_level INIT(= 0); // nesting level EXTERN int debug_break_level INIT(= -1); // break below this level @@ -282,11 +274,11 @@ EXTERN int check_cstack INIT(= false); /// commands). EXTERN int trylevel INIT(= 0); -/// When "force_abort" is TRUE, always skip commands after an error message, +/// When "force_abort" is true, always skip commands after an error message, /// even after the outermost ":endif", ":endwhile" or ":endfor" or for a -/// function without the "abort" flag. It is set to TRUE when "trylevel" is +/// function without the "abort" flag. It is set to true when "trylevel" is /// non-zero (and ":silent!" was not used) or an exception is being thrown at -/// the time an error is detected. It is set to FALSE when "trylevel" gets +/// the time an error is detected. It is set to false when "trylevel" gets /// zero again and there was no error or interrupt or throw. EXTERN int force_abort INIT(= false); @@ -357,41 +349,38 @@ EXTERN int provider_call_nesting INIT(= 0); EXTERN int t_colors INIT(= 256); // int value of T_CCO -/* - * When highlight_match is TRUE, highlight a match, starting at the cursor - * position. Search_match_lines is the number of lines after the match (0 for - * a match within one line), search_match_endcol the column number of the - * character just after the match in the last line. - */ -EXTERN int highlight_match INIT(= FALSE); /* show search match pos */ -EXTERN linenr_T search_match_lines; /* lines of of matched string */ -EXTERN colnr_T search_match_endcol; /* col nr of match end */ +// When highlight_match is true, highlight a match, starting at the cursor +// position. Search_match_lines is the number of lines after the match (0 for +// a match within one line), search_match_endcol the column number of the +// character just after the match in the last line. +EXTERN int highlight_match INIT(= false); // show search match pos +EXTERN linenr_T search_match_lines; // lines of of matched string +EXTERN colnr_T search_match_endcol; // col nr of match end -EXTERN int no_smartcase INIT(= FALSE); /* don't use 'smartcase' once */ +EXTERN int no_smartcase INIT(= false); // don't use 'smartcase' once -EXTERN int need_check_timestamps INIT(= FALSE); /* need to check file - timestamps asap */ -EXTERN int did_check_timestamps INIT(= FALSE); /* did check timestamps - recently */ -EXTERN int no_check_timestamps INIT(= 0); /* Don't check timestamps */ +EXTERN int need_check_timestamps INIT(= false); // need to check file + // timestamps asap +EXTERN int did_check_timestamps INIT(= false); // did check timestamps + // recently +EXTERN int no_check_timestamps INIT(= 0); // Don't check timestamps -EXTERN int autocmd_busy INIT(= FALSE); /* Is apply_autocmds() busy? */ -EXTERN int autocmd_no_enter INIT(= FALSE); /* *Enter autocmds disabled */ -EXTERN int autocmd_no_leave INIT(= FALSE); /* *Leave autocmds disabled */ -EXTERN int modified_was_set; /* did ":set modified" */ -EXTERN int did_filetype INIT(= FALSE); /* FileType event found */ -EXTERN int keep_filetype INIT(= FALSE); /* value for did_filetype when - starting to execute - autocommands */ +EXTERN int autocmd_busy INIT(= false); // Is apply_autocmds() busy? +EXTERN int autocmd_no_enter INIT(= false); // *Enter autocmds disabled +EXTERN int autocmd_no_leave INIT(= false); // *Leave autocmds disabled +EXTERN int modified_was_set; // did ":set modified" +EXTERN int did_filetype INIT(= false); // FileType event found +// value for did_filetype when starting to execute autocommands +EXTERN int keep_filetype INIT(= false); // When deleting the current buffer, another one must be loaded. // If we know which one is preferred, au_new_curbuf is set to it. EXTERN bufref_T au_new_curbuf INIT(= { NULL, 0, 0 }); -// When deleting a buffer/window and autocmd_busy is TRUE, do not free the +// When deleting a buffer/window and autocmd_busy is true, do not free the // buffer/window. but link it in the list starting with // au_pending_free_buf/ap_pending_free_win, using b_next/w_next. -// Free the buffer/window when autocmd_busy is being set to FALSE. +// Free the buffer/window when autocmd_busy is being set to false. EXTERN buf_T *au_pending_free_buf INIT(= NULL); EXTERN win_T *au_pending_free_win INIT(= NULL); @@ -399,31 +388,27 @@ EXTERN win_T *au_pending_free_win INIT(= NULL); EXTERN int mouse_grid; EXTERN int mouse_row; EXTERN int mouse_col; -EXTERN bool mouse_past_bottom INIT(= false); /* mouse below last line */ -EXTERN bool mouse_past_eol INIT(= false); /* mouse right of line */ -EXTERN int mouse_dragging INIT(= 0); /* extending Visual area with - mouse dragging */ +EXTERN bool mouse_past_bottom INIT(= false); // mouse below last line +EXTERN bool mouse_past_eol INIT(= false); // mouse right of line +EXTERN int mouse_dragging INIT(= 0); // extending Visual area with + // mouse dragging -/* The root of the menu hierarchy. */ +// The root of the menu hierarchy. EXTERN vimmenu_T *root_menu INIT(= NULL); -/* - * While defining the system menu, sys_menu is TRUE. This avoids - * overruling of menus that the user already defined. - */ -EXTERN int sys_menu INIT(= FALSE); +// While defining the system menu, sys_menu is true. This avoids +// overruling of menus that the user already defined. +EXTERN int sys_menu INIT(= false); // While redrawing the screen this flag is set. It means the screen size // ('lines' and 'rows') must not be changed. EXTERN int updating_screen INIT(= 0); -/* - * All windows are linked in a list. firstwin points to the first entry, - * lastwin to the last entry (can be the same as firstwin) and curwin to the - * currently active window. - */ -EXTERN win_T *firstwin; /* first window */ -EXTERN win_T *lastwin; /* last window */ -EXTERN win_T *prevwin INIT(= NULL); /* previous window */ +// All windows are linked in a list. firstwin points to the first entry, +// lastwin to the last entry (can be the same as firstwin) and curwin to the +// currently active window. +EXTERN win_T *firstwin; // first window +EXTERN win_T *lastwin; // last window +EXTERN win_T *prevwin INIT(= NULL); // previous window # define ONE_WINDOW (firstwin == lastwin) # define FOR_ALL_FRAMES(frp, first_frame) \ for (frp = first_frame; frp != NULL; frp = frp->fr_next) // NOLINT @@ -439,33 +424,27 @@ EXTERN win_T *prevwin INIT(= NULL); /* previous window */ for (win_T *wp = ((tp) == curtab) \ ? firstwin : (tp)->tp_firstwin; wp != NULL; wp = wp->w_next) -EXTERN win_T *curwin; /* currently active window */ +EXTERN win_T *curwin; // currently active window -EXTERN win_T *aucmd_win; /* window used in aucmd_prepbuf() */ -EXTERN int aucmd_win_used INIT(= FALSE); /* aucmd_win is being used */ +EXTERN win_T *aucmd_win; // window used in aucmd_prepbuf() +EXTERN int aucmd_win_used INIT(= false); // aucmd_win is being used -/* - * The window layout is kept in a tree of frames. topframe points to the top - * of the tree. - */ -EXTERN frame_T *topframe; /* top of the window frame tree */ +// The window layout is kept in a tree of frames. topframe points to the top +// of the tree. +EXTERN frame_T *topframe; // top of the window frame tree -/* - * Tab pages are alternative topframes. "first_tabpage" points to the first - * one in the list, "curtab" is the current one. - */ +// Tab pages are alternative topframes. "first_tabpage" points to the first +// one in the list, "curtab" is the current one. EXTERN tabpage_T *first_tabpage; EXTERN tabpage_T *lastused_tabpage; EXTERN tabpage_T *curtab; -EXTERN int redraw_tabline INIT(= FALSE); /* need to redraw tabline */ +EXTERN int redraw_tabline INIT(= false); // need to redraw tabline // Iterates over all tabs in the tab list # define FOR_ALL_TABS(tp) for (tabpage_T *tp = first_tabpage; tp != NULL; tp = tp->tp_next) -/* - * All buffers are linked in a list. 'firstbuf' points to the first entry, - * 'lastbuf' to the last entry and 'curbuf' to the currently active buffer. - */ +// All buffers are linked in a list. 'firstbuf' points to the first entry, +// 'lastbuf' to the last entry and 'curbuf' to the currently active buffer. EXTERN buf_T *firstbuf INIT(= NULL); // first buffer EXTERN buf_T *lastbuf INIT(= NULL); // last buffer EXTERN buf_T *curbuf INIT(= NULL); // currently active buffer @@ -481,23 +460,19 @@ EXTERN buf_T *curbuf INIT(= NULL); // currently active buffer for (sign = buf->b_signlist; sign != NULL; sign = sign->next) // NOLINT -/* - * List of files being edited (global argument list). curwin->w_alist points - * to this when the window is using the global argument list. - */ -EXTERN alist_T global_alist; /* global argument list */ +// List of files being edited (global argument list). curwin->w_alist points +// to this when the window is using the global argument list. +EXTERN alist_T global_alist; // global argument list EXTERN int max_alist_id INIT(= 0); ///< the previous argument list id EXTERN bool arg_had_last INIT(= false); // accessed last file in // global_alist -EXTERN int ru_col; /* column for ruler */ -EXTERN int ru_wid; /* 'rulerfmt' width of ruler when non-zero */ -EXTERN int sc_col; /* column for shown command */ +EXTERN int ru_col; // column for ruler +EXTERN int ru_wid; // 'rulerfmt' width of ruler when non-zero +EXTERN int sc_col; // column for shown command -// // When starting or exiting some things are done differently (e.g. screen // updating). -// // First NO_SCREEN, then NO_BUFFERS, then 0 when startup finished. EXTERN int starting INIT(= NO_SCREEN); @@ -546,98 +521,78 @@ EXTERN int VIsual_select INIT(= false); EXTERN int VIsual_reselect; /// Type of Visual mode. EXTERN int VIsual_mode INIT(= 'v'); -/// TRUE when redoing Visual. +/// true when redoing Visual. EXTERN int redo_VIsual_busy INIT(= false); /// When pasting text with the middle mouse button in visual mode with /// restart_edit set, remember where it started so we can set Insstart. EXTERN pos_T where_paste_started; -/* - * This flag is used to make auto-indent work right on lines where only a - * or is typed. It is set when an auto-indent is done, and - * reset when any other editing is done on the line. If an or - * is received, and did_ai is TRUE, the line is truncated. - */ +// This flag is used to make auto-indent work right on lines where only a +// or is typed. It is set when an auto-indent is done, and +// reset when any other editing is done on the line. If an or +// is received, and did_ai is true, the line is truncated. EXTERN bool did_ai INIT(= false); -/* - * Column of first char after autoindent. 0 when no autoindent done. Used - * when 'backspace' is 0, to avoid backspacing over autoindent. - */ +// Column of first char after autoindent. 0 when no autoindent done. Used +// when 'backspace' is 0, to avoid backspacing over autoindent. EXTERN colnr_T ai_col INIT(= 0); -/* - * This is a character which will end a start-middle-end comment when typed as - * the first character on a new line. It is taken from the last character of - * the "end" comment leader when the COM_AUTO_END flag is given for that - * comment end in 'comments'. It is only valid when did_ai is TRUE. - */ +// This is a character which will end a start-middle-end comment when typed as +// the first character on a new line. It is taken from the last character of +// the "end" comment leader when the COM_AUTO_END flag is given for that +// comment end in 'comments'. It is only valid when did_ai is true. EXTERN int end_comment_pending INIT(= NUL); -/* - * This flag is set after a ":syncbind" to let the check_scrollbind() function - * know that it should not attempt to perform scrollbinding due to the scroll - * that was a result of the ":syncbind." (Otherwise, check_scrollbind() will - * undo some of the work done by ":syncbind.") -ralston - */ -EXTERN int did_syncbind INIT(= FALSE); +// This flag is set after a ":syncbind" to let the check_scrollbind() function +// know that it should not attempt to perform scrollbinding due to the scroll +// that was a result of the ":syncbind." (Otherwise, check_scrollbind() will +// undo some of the work done by ":syncbind.") -ralston +EXTERN int did_syncbind INIT(= false); -/* - * This flag is set when a smart indent has been performed. When the next typed - * character is a '{' the inserted tab will be deleted again. - */ +// This flag is set when a smart indent has been performed. When the next typed +// character is a '{' the inserted tab will be deleted again. EXTERN bool did_si INIT(= false); -/* - * This flag is set after an auto indent. If the next typed character is a '}' - * one indent will be removed. - */ +// This flag is set after an auto indent. If the next typed character is a '}' +// one indent will be removed. EXTERN bool can_si INIT(= false); -/* - * This flag is set after an "O" command. If the next typed character is a '{' - * one indent will be removed. - */ +// This flag is set after an "O" command. If the next typed character is a '{' +// one indent will be removed. EXTERN bool can_si_back INIT(= false); // w_cursor before formatting text. EXTERN pos_T saved_cursor INIT(= { 0, 0, 0 }); -/* - * Stuff for insert mode. - */ -EXTERN pos_T Insstart; /* This is where the latest - * insert/append mode started. */ +// Stuff for insert mode. +EXTERN pos_T Insstart; // This is where the latest + // insert/append mode started. // This is where the latest insert/append mode started. In contrast to // Insstart, this won't be reset by certain keys and is needed for // op_insert(), to detect correctly where inserting by the user started. EXTERN pos_T Insstart_orig; -/* - * Stuff for VREPLACE mode. - */ -EXTERN int orig_line_count INIT(= 0); /* Line count when "gR" started */ -EXTERN int vr_lines_changed INIT(= 0); /* #Lines changed by "gR" so far */ +// Stuff for VREPLACE mode. +EXTERN int orig_line_count INIT(= 0); // Line count when "gR" started +EXTERN int vr_lines_changed INIT(= 0); // #Lines changed by "gR" so far // increase around internal delete/replace EXTERN int inhibit_delete_count INIT(= 0); -/* - * These flags are set based upon 'fileencoding'. - * Note that "enc_utf8" is also set for "unicode", because the characters are - * internally stored as UTF-8 (to avoid trouble with NUL bytes). - */ -# define DBCS_JPN 932 /* japan */ -# define DBCS_JPNU 9932 /* euc-jp */ -# define DBCS_KOR 949 /* korea */ -# define DBCS_KORU 9949 /* euc-kr */ -# define DBCS_CHS 936 /* chinese */ -# define DBCS_CHSU 9936 /* euc-cn */ -# define DBCS_CHT 950 /* taiwan */ -# define DBCS_CHTU 9950 /* euc-tw */ -# define DBCS_2BYTE 1 /* 2byte- */ +// These flags are set based upon 'fileencoding'. +// Note that "enc_utf8" is also set for "unicode", because the characters are +// internally stored as UTF-8 (to avoid trouble with NUL bytes). +# define DBCS_JPN 932 // japan +# define DBCS_JPNU 9932 // euc-jp +# define DBCS_KOR 949 // korea +# define DBCS_KORU 9949 // euc-kr +# define DBCS_CHS 936 // chinese +# define DBCS_CHSU 9936 // euc-cn +# define DBCS_CHT 950 // taiwan +# define DBCS_CHTU 9950 // euc-tw +# define DBCS_2BYTE 1 // 2byte- # define DBCS_DEBUG -1 // mbyte flags that used to depend on 'encoding'. These are now deprecated, as @@ -678,40 +633,40 @@ EXTERN int u_sync_once INIT(= 0); // Call u_sync() once when evaluating EXTERN bool force_restart_edit INIT(= false); // force restart_edit after // ex_normal returns -EXTERN int restart_edit INIT(= 0); /* call edit when next cmd finished */ -EXTERN int arrow_used; /* Normally FALSE, set to TRUE after - * hitting cursor key in insert mode. - * Used by vgetorpeek() to decide when - * to call u_sync() */ -EXTERN int ins_at_eol INIT(= FALSE); /* put cursor after eol when - restarting edit after CTRL-O */ +EXTERN int restart_edit INIT(= 0); // call edit when next cmd finished +EXTERN int arrow_used; // Normally false, set to true after + // hitting cursor key in insert mode. + // Used by vgetorpeek() to decide when + // to call u_sync() +EXTERN int ins_at_eol INIT(= false); // put cursor after eol when + // restarting edit after CTRL-O EXTERN char_u *edit_submode INIT(= NULL); // msg for CTRL-X submode EXTERN char_u *edit_submode_pre INIT(= NULL); // prepended to edit_submode EXTERN char_u *edit_submode_extra INIT(= NULL); // appended to edit_submode EXTERN hlf_T edit_submode_highl; // highl. method for extra info -EXTERN int no_abbr INIT(= TRUE); /* TRUE when no abbreviations loaded */ +EXTERN int no_abbr INIT(= true); // true when no abbreviations loaded EXTERN int mapped_ctrl_c INIT(= 0); // Modes where CTRL-C is mapped. -EXTERN cmdmod_T cmdmod; /* Ex command modifiers */ +EXTERN cmdmod_T cmdmod; // Ex command modifiers EXTERN int msg_silent INIT(= 0); // don't print messages EXTERN int emsg_silent INIT(= 0); // don't print error messages EXTERN bool emsg_noredir INIT(= false); // don't redirect error messages EXTERN bool cmd_silent INIT(= false); // don't echo the command line -/* Values for swap_exists_action: what to do when swap file already exists */ -#define SEA_NONE 0 /* don't use dialog */ -#define SEA_DIALOG 1 /* use dialog when possible */ -#define SEA_QUIT 2 /* quit editing the file */ -#define SEA_RECOVER 3 /* recover the file */ +// Values for swap_exists_action: what to do when swap file already exists +#define SEA_NONE 0 // don't use dialog +#define SEA_DIALOG 1 // use dialog when possible +#define SEA_QUIT 2 // quit editing the file +#define SEA_RECOVER 3 // recover the file EXTERN int swap_exists_action INIT(= SEA_NONE); -/* For dialog when swap file already - * exists. */ -EXTERN int swap_exists_did_quit INIT(= FALSE); -/* Selected "quit" at the dialog. */ +// For dialog when swap file already +// exists. +EXTERN int swap_exists_did_quit INIT(= false); +// Selected "quit" at the dialog. EXTERN char_u IObuff[IOSIZE]; ///< Buffer for sprintf, I/O, etc. EXTERN char_u NameBuff[MAXPATHL]; ///< Buffer for expanding file names @@ -724,11 +679,11 @@ IOSIZE #endif ]; -/* When non-zero, postpone redrawing. */ +// When non-zero, postpone redrawing. EXTERN int RedrawingDisabled INIT(= 0); -EXTERN int readonlymode INIT(= FALSE); /* Set to TRUE for "view" */ -EXTERN int recoverymode INIT(= FALSE); /* Set to TRUE for "-r" option */ +EXTERN int readonlymode INIT(= false); // Set to true for "view" +EXTERN int recoverymode INIT(= false); // Set to true for "-r" option // typeahead buffer EXTERN typebuf_T typebuf INIT(= { NULL, NULL, 0, 0, 0, 0, 0, 0, 0 }); @@ -738,7 +693,7 @@ EXTERN int ex_normal_lock INIT(= 0); // forbid use of ex_normal() EXTERN int ignore_script INIT(= false); // ignore script input EXTERN int stop_insert_mode; // for ":stopinsert" and 'insertmode' EXTERN bool KeyTyped; // true if user typed current char -EXTERN int KeyStuffed; // TRUE if current char from stuffbuf +EXTERN int KeyStuffed; // true if current char from stuffbuf EXTERN int maptick INIT(= 0); // tick for each non-mapped char EXTERN int must_redraw INIT(= 0); // type of redraw necessary @@ -754,15 +709,15 @@ EXTERN FILE *scriptout INIT(= NULL); ///< Stream to write script to. // volatile because it is used in a signal handler. EXTERN volatile int got_int INIT(= false); // set to true when interrupt // signal occurred -EXTERN int bangredo INIT(= FALSE); /* set to TRUE with ! command */ -EXTERN int searchcmdlen; /* length of previous search cmd */ -EXTERN int reg_do_extmatch INIT(= 0); /* Used when compiling regexp: - * REX_SET to allow \z\(...\), - * REX_USE to allow \z\1 et al. */ -EXTERN reg_extmatch_T *re_extmatch_in INIT(= NULL); /* Used by vim_regexec(): - * strings for \z\1...\z\9 */ -EXTERN reg_extmatch_T *re_extmatch_out INIT(= NULL); /* Set by vim_regexec() - * to store \z\(...\) matches */ +EXTERN int bangredo INIT(= false); // set to true with ! command +EXTERN int searchcmdlen; // length of previous search cmd +EXTERN int reg_do_extmatch INIT(= 0); // Used when compiling regexp: + // REX_SET to allow \z\(...\), + // REX_USE to allow \z\1 et al. +// Used by vim_regexec(): strings for \z\1...\z\9 +EXTERN reg_extmatch_T *re_extmatch_in INIT(= NULL); +// Set by vim_regexec() to store \z\(...\) matches +EXTERN reg_extmatch_T *re_extmatch_out INIT(= NULL); EXTERN int did_outofmem_msg INIT(= false); // set after out of memory msg @@ -781,11 +736,11 @@ EXTERN int autocmd_bufnr INIT(= 0); // fnum for on cmdline EXTERN char_u *autocmd_match INIT(= NULL); // name for on cmdline EXTERN int did_cursorhold INIT(= false); // set when CursorHold t'gerd -EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */ -EXTERN int postponed_split_flags INIT(= 0); /* args for win_split() */ -EXTERN int postponed_split_tab INIT(= 0); /* cmdmod.tab */ -EXTERN int g_do_tagpreview INIT(= 0); /* for tag preview commands: - height of preview window */ +EXTERN int postponed_split INIT(= 0); // for CTRL-W CTRL-] command +EXTERN int postponed_split_flags INIT(= 0); // args for win_split() +EXTERN int postponed_split_tab INIT(= 0); // cmdmod.tab +EXTERN int g_do_tagpreview INIT(= 0); // for tag preview commands: + // height of preview window EXTERN int g_tag_at_cursor INIT(= false); // whether the tag command comes // from the command line (0) or was // invoked as a normal command (1) @@ -793,15 +748,13 @@ EXTERN int g_tag_at_cursor INIT(= false); // whether the tag command comes EXTERN int replace_offset INIT(= 0); // offset for replace_push() EXTERN char_u *escape_chars INIT(= (char_u *)" \t\\\"|"); -/* need backslash in cmd line */ +// need backslash in cmd line -EXTERN int keep_help_flag INIT(= FALSE); /* doing :ta from help file */ +EXTERN int keep_help_flag INIT(= false); // doing :ta from help file -/* - * When a string option is NULL (which only happens in out-of-memory - * situations), it is set to empty_option, to avoid having to check for NULL - * everywhere. - */ +// When a string option is NULL (which only happens in out-of-memory +// situations), it is set to empty_option, to avoid having to check for NULL +// everywhere. EXTERN char_u *empty_option INIT(= (char_u *)""); EXTERN int redir_off INIT(= false); // no redirection for a moment @@ -810,10 +763,10 @@ 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 char_u 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 */ +EXTERN int save_p_ls INIT(= -1); // Save 'laststatus' setting +EXTERN int save_p_wmh INIT(= -1); // Save 'winminheight' setting EXTERN int wild_menu_showing INIT(= 0); enum { WM_SHOWN = 1, ///< wildmenu showing @@ -822,10 +775,8 @@ enum { }; -/* - * Some file names are stored in pathdef.c, which is generated from the - * Makefile to make their value depend on the Makefile. - */ +// Some file names are stored in pathdef.c, which is generated from the +// Makefile to make their value depend on the Makefile. #ifdef HAVE_PATHDEF extern char *default_vim_dir; extern char *default_vimruntime_dir; @@ -834,14 +785,14 @@ extern char_u *compiled_user; extern char_u *compiled_sys; #endif -/* When a window has a local directory, the absolute path of the global - * current directory is stored here (in allocated memory). If the current - * directory is not a local directory, globaldir is NULL. */ +// When a window has a local directory, the absolute path of the global +// current directory is stored here (in allocated memory). If the current +// directory is not a local directory, globaldir is NULL. EXTERN char_u *globaldir INIT(= NULL); -/* Whether 'keymodel' contains "stopsel" and "startsel". */ -EXTERN int km_stopsel INIT(= FALSE); -EXTERN int km_startsel INIT(= FALSE); +// Whether 'keymodel' contains "stopsel" and "startsel". +EXTERN int km_stopsel INIT(= false); +EXTERN int km_startsel INIT(= false); EXTERN int cedit_key INIT(= -1); ///< key value of 'cedit' option EXTERN int cmdwin_type INIT(= 0); ///< type of cmdline window or 0 @@ -850,18 +801,16 @@ EXTERN int cmdwin_level INIT(= 0); ///< cmdline recursion level EXTERN char_u no_lines_msg[] INIT(= N_("--No lines in buffer--")); -/* - * When ":global" is used to number of substitutions and changed lines is - * accumulated until it's finished. - * Also used for ":spellrepall". - */ -EXTERN long sub_nsubs; /* total number of substitutions */ -EXTERN linenr_T sub_nlines; /* total number of lines changed */ +// When ":global" is used to number of substitutions and changed lines is +// accumulated until it's finished. +// Also used for ":spellrepall". +EXTERN long sub_nsubs; // total number of substitutions +EXTERN linenr_T sub_nlines; // total number of lines changed -/* table to store parsed 'wildmode' */ +// table to store parsed 'wildmode' EXTERN char_u wim_flags[4]; -/* whether titlestring and iconstring contains statusline syntax */ +// whether titlestring and iconstring contains statusline syntax # define STL_IN_ICON 1 # define STL_IN_TITLE 2 EXTERN int stl_syntax INIT(= 0); @@ -869,7 +818,7 @@ EXTERN int stl_syntax INIT(= 0); // don't use 'hlsearch' temporarily EXTERN bool no_hlsearch INIT(= false); -/* Page number used for %N in 'pageheader' and 'guitablabel'. */ +// Page number used for %N in 'pageheader' and 'guitablabel'. EXTERN linenr_T printer_page_num; @@ -887,18 +836,16 @@ EXTERN char pseps[2] INIT(= { '\\', 0 }); // normal path separator string // kNone when no operator is being executed, kFalse otherwise. EXTERN TriState virtual_op INIT(= kNone); -/* Display tick, incremented for each call to update_screen() */ +// Display tick, incremented for each call to update_screen() EXTERN disptick_T display_tick INIT(= 0); -/* Line in which spell checking wasn't highlighted because it touched the - * cursor position in Insert mode. */ +// Line in which spell checking wasn't highlighted because it touched the +// cursor position in Insert mode. EXTERN linenr_T spell_redraw_lnum INIT(= 0); -/* - * The error messages that can be shared are included here. - * Excluded are errors that are only used once and debugging messages. - */ +// The error messages that can be shared are included here. +// Excluded are errors that are only used once and debugging messages. EXTERN char_u e_abort[] INIT(= N_("E470: Command aborted")); EXTERN char_u e_afterinit[] INIT(= N_( "E905: Cannot set this option after startup")); @@ -1070,7 +1017,7 @@ EXTERN char line_msg[] INIT(= N_(" line ")); // For undo we need to know the lowest time possible. EXTERN time_t starttime; -EXTERN FILE *time_fd INIT(= NULL); /* where to write startup timing */ +EXTERN FILE *time_fd INIT(= NULL); // where to write startup timing // Some compilers warn for not using a return value, but in some situations we // can't do anything useful with the value. Assign to this variable to avoid @@ -1106,4 +1053,4 @@ typedef enum { #define MIN_CD_SCOPE kCdScopeWindow #define MAX_CD_SCOPE kCdScopeGlobal -#endif /* NVIM_GLOBALS_H */ +#endif // NVIM_GLOBALS_H