From 271fa08a35b8d320d3a40db4ddae83b698fdd4fb Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 2 Jan 2020 14:02:16 +0100 Subject: [PATCH 01/42] patch 8.2.0077: settagstack() cannot truncate at current index Problem: settagstack() cannot truncate at current index. Solution: Add the "t" action. (Yegappan Lakshmanan, closes #5417) --- runtime/doc/eval.txt | 18 ++++++++++++++---- src/evalfunc.c | 3 ++- src/tag.c | 31 +++++++++++++++++++++++++------ src/testdir/test_tagjump.vim | 22 ++++++++++++++++++++++ src/version.c | 2 ++ 5 files changed, 65 insertions(+), 11 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index f06a727623..dceae48ea5 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -8774,11 +8774,21 @@ settagstack({nr}, {dict} [, {action}]) *settagstack()* {nr} can be the window number or the |window-ID|. For a list of supported items in {dict}, refer to - |gettagstack()| + |gettagstack()|. "curidx" takes effect before changing the tag + stack. *E962* - If {action} is not present or is set to 'r', then the tag - stack is replaced. If {action} is set to 'a', then new entries - from {dict} are pushed onto the tag stack. + How the tag stack is modified depends on the {action} + argument: + - If {action} is not present or is set to 'r', then the tag + stack is replaced. + - If {action} is set to 'a', then new entries from {dict} are + pushed (added) onto the tag stack. + - If {action} is set to 't', then all the entries from the + current entry in the tag stack or "curidx" in {dict} are + removed and then new entries are pushed to the stack. + + The current index is set to one after the length of the tag + stack after the modification. Returns zero for success, -1 for failure. diff --git a/src/evalfunc.c b/src/evalfunc.c index 489ab424a9..af43fb96ec 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -6776,7 +6776,8 @@ f_settagstack(typval_T *argvars, typval_T *rettv) actstr = tv_get_string_chk(&argvars[2]); if (actstr == NULL) return; - if ((*actstr == 'r' || *actstr == 'a') && actstr[1] == NUL) + if ((*actstr == 'r' || *actstr == 'a' || *actstr == 't') + && actstr[1] == NUL) action = *actstr; else { diff --git a/src/tag.c b/src/tag.c index c00f5fb723..4f897fa607 100644 --- a/src/tag.c +++ b/src/tag.c @@ -4224,13 +4224,16 @@ tagstack_set_curidx(win_T *wp, int curidx) /* * Set the tag stack entries of the specified window. - * 'action' is set to either 'a' for append or 'r' for replace. + * 'action' is set to one of: + * 'a' for append + * 'r' for replace + * 't' for truncate */ int set_tagstack(win_T *wp, dict_T *d, int action) { dictitem_T *di; - list_T *l; + list_T *l = NULL; #ifdef FEAT_EVAL // not allowed to alter the tag stack entries from inside tagfunc @@ -4249,16 +4252,32 @@ set_tagstack(win_T *wp, dict_T *d, int action) return FAIL; } l = di->di_tv.vval.v_list; + } - if (action == 'r') + if ((di = dict_find(d, (char_u *)"curidx", -1)) != NULL) + tagstack_set_curidx(wp, (int)tv_get_number(&di->di_tv) - 1); + + if (action == 't') // truncate the stack + { + taggy_T *tagstack = wp->w_tagstack; + int tagstackidx = wp->w_tagstackidx; + int tagstacklen = wp->w_tagstacklen; + // delete all the tag stack entries above the current entry + while (tagstackidx < tagstacklen) + tagstack_clear_entry(&tagstack[--tagstacklen]); + wp->w_tagstacklen = tagstacklen; + } + + if (l != NULL) + { + if (action == 'r') // replace the stack tagstack_clear(wp); tagstack_push_items(wp, l); + // set the current index after the last entry + wp->w_tagstackidx = wp->w_tagstacklen; } - if ((di = dict_find(d, (char_u *)"curidx", -1)) != NULL) - tagstack_set_curidx(wp, (int)tv_get_number(&di->di_tv) - 1); - return OK; } #endif diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim index 14ba1f78dd..8d32883da2 100644 --- a/src/testdir/test_tagjump.vim +++ b/src/testdir/test_tagjump.vim @@ -348,6 +348,28 @@ func Test_getsettagstack() \ {'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 'a') call assert_equal('abc', gettagstack().items[19].tagname) + " truncate the tag stack + call settagstack(1, + \ {'curidx' : 9, + \ 'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 't') + let t = gettagstack() + call assert_equal(9, t.length) + call assert_equal(10, t.curidx) + + " truncate the tag stack without pushing any new items + call settagstack(1, {'curidx' : 5}, 't') + let t = gettagstack() + call assert_equal(4, t.length) + call assert_equal(5, t.curidx) + + " truncate an empty tag stack and push new items + call settagstack(1, {'items' : []}) + call settagstack(1, + \ {'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 't') + let t = gettagstack() + call assert_equal(1, t.length) + call assert_equal(2, t.curidx) + " Tag with multiple matches call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", \ "two\tXfile1\t1", diff --git a/src/version.c b/src/version.c index 263ffb0125..118dad505b 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 77, /**/ 76, /**/ From b9adef79eca6f95bc7376ff3a6a383e436c5d6ea Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 2 Jan 2020 14:31:22 +0100 Subject: [PATCH 02/42] patch 8.2.0078: expanding works differently the second time Problem: Expanding works differently the second time. Solution: Keep the expanded name when redefining a function. (closes #5425) --- src/testdir/test_vimscript.vim | 17 +++++++++++++++++ src/userfunc.c | 6 +++++- src/version.c | 2 ++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vimscript.vim b/src/testdir/test_vimscript.vim index 89112dead2..c890fb779a 100644 --- a/src/testdir/test_vimscript.vim +++ b/src/testdir/test_vimscript.vim @@ -1642,6 +1642,23 @@ func Test_script_local_func() enew! | close endfunc +func Test_script_expand_sfile() + let lines =<< trim END + func s:snr() + return expand('') + endfunc + let g:result = s:snr() + END + call writefile(lines, 'Xexpand') + source Xexpand + call assert_match('\d\+_snr', g:result) + source Xexpand + call assert_match('\d\+_snr', g:result) + + call delete('Xexpand') + unlet g:result +endfunc + func Test_compound_assignment_operators() " Test for number let x = 1 diff --git a/src/userfunc.c b/src/userfunc.c index a8bc34ae81..95862fe875 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -2572,9 +2572,13 @@ ex_function(exarg_T *eap) } else { - // redefine existing function + char_u *exp_name = fp->uf_name_exp; + + // redefine existing function, keep the expanded name VIM_CLEAR(name); + fp->uf_name_exp = NULL; func_clear_items(fp); + fp->uf_name_exp = exp_name; #ifdef FEAT_PROFILE fp->uf_profiling = FALSE; fp->uf_prof_initialized = FALSE; diff --git a/src/version.c b/src/version.c index 118dad505b..4516eb71bc 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 78, /**/ 77, /**/ From 7fc4785ea19306b7e94beb61f226cf40c32b1aba Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 2 Jan 2020 16:38:07 +0100 Subject: [PATCH 03/42] patch 8.2.0079: Python 3 unicode test still fails on MS-Windows Problem: Python 3 unicode test still fails on MS-Windows. Solution: Do not set 'encoding' to "euc-tw" on MS-Windows. --- src/testdir/test_python3.vim | 6 +++--- src/version.c | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/testdir/test_python3.vim b/src/testdir/test_python3.vim index 4cb5094567..aec7721af3 100644 --- a/src/testdir/test_python3.vim +++ b/src/testdir/test_python3.vim @@ -180,10 +180,10 @@ func Test_unicode() if !has('win32') set encoding=debug py3 print('hello') - endif - set encoding=euc-tw - py3 print('hello') + set encoding=euc-tw + py3 print('hello') + endif set encoding=utf8 endfunc diff --git a/src/version.c b/src/version.c index 4516eb71bc..052b6341e1 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 79, /**/ 78, /**/ From d7df279808f75f7a4af8dd48deae73a9b727ac3b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 2 Jan 2020 21:34:42 +0100 Subject: [PATCH 04/42] Update a few runtime files. --- runtime/autoload/dist/ft.vim | 4 ++-- runtime/doc/eval.txt | 2 +- runtime/doc/message.txt | 2 +- runtime/doc/options.txt | 2 +- runtime/doc/tags | 4 +++- runtime/doc/tagsrch.txt | 6 +++--- runtime/doc/todo.txt | 13 +++++++++---- runtime/doc/version8.txt | 3 +-- 8 files changed, 21 insertions(+), 15 deletions(-) diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim index e85ffc763b..5c43ba280c 100644 --- a/runtime/autoload/dist/ft.vim +++ b/runtime/autoload/dist/ft.vim @@ -1,7 +1,7 @@ " Vim functions for file type detection " " Maintainer: Bram Moolenaar -" Last Change: 2019 Mar 08 +" Last Change: 2020 Jan 02 " These functions are moved here from runtime/filetype.vim to make startup " faster. @@ -298,7 +298,7 @@ endfunc func dist#ft#FTmms() let n = 1 - while n < 10 + while n < 20 let line = getline(n) if line =~ '^\s*\(%\|//\)' || line =~ '^\*' setf mmix diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index dceae48ea5..09d663e537 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 8.2. Last change: 2019 Dec 17 +*eval.txt* For Vim version 8.2. Last change: 2020 Jan 02 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/message.txt b/runtime/doc/message.txt index 9e4937bff0..b49c6535dc 100644 --- a/runtime/doc/message.txt +++ b/runtime/doc/message.txt @@ -1,4 +1,4 @@ -*message.txt* For Vim version 8.2. Last change: 2019 Oct 19 +*message.txt* For Vim version 8.2. Last change: 2020 Jan 01 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 0fd23a48b8..f65d46fecf 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 8.2. Last change: 2019 Dec 18 +*options.txt* For Vim version 8.2. Last change: 2020 Jan 01 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/tags b/runtime/doc/tags index 2199de1fdd..1aff075b23 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -4061,6 +4061,7 @@ E287 mbyte.txt /*E287* E288 mbyte.txt /*E288* E289 mbyte.txt /*E289* E29 change.txt /*E29* +E292 message.txt /*E292* E293 message.txt /*E293* E294 message.txt /*E294* E295 message.txt /*E295* @@ -4753,7 +4754,7 @@ E947 terminal.txt /*E947* E948 terminal.txt /*E948* E949 editing.txt /*E949* E95 message.txt /*E95* -E950 message.txt /*E950* +E950 options.txt /*E950* E951 pattern.txt /*E951* E952 autocmd.txt /*E952* E953 terminal.txt /*E953* @@ -10056,6 +10057,7 @@ windows.txt windows.txt /*windows.txt* windows95 os_win32.txt /*windows95* windows98 os_win32.txt /*windows98* windowsme os_win32.txt /*windowsme* +windowsversion() eval.txt /*windowsversion()* winheight() eval.txt /*winheight()* winid windows.txt /*winid* winlayout() eval.txt /*winlayout()* diff --git a/runtime/doc/tagsrch.txt b/runtime/doc/tagsrch.txt index 8b3d20d653..1f8eed4f87 100644 --- a/runtime/doc/tagsrch.txt +++ b/runtime/doc/tagsrch.txt @@ -1,4 +1,4 @@ -*tagsrch.txt* For Vim version 8.2. Last change: 2019 Nov 07 +*tagsrch.txt* For Vim version 8.2. Last change: 2019 Dec 27 VIM REFERENCE MANUAL by Bram Moolenaar @@ -210,14 +210,14 @@ the same entry. Example output: > - nr pri kind tag file + # pri kind tag file 1 F f mch_delay os_amiga.c mch_delay(msec, ignoreinput) > 2 F f mch_delay os_msdos.c mch_delay(msec, ignoreinput) 3 F f mch_delay os_unix.c mch_delay(msec, ignoreinput) - Enter nr of choice ( to abort): + Type number and (empty cancels): < See |tag-priority| for the "pri" column. Note that this depends on the current file, thus using diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index d41e0d87a8..38eb91c02e 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1,4 +1,4 @@ -*todo.txt* For Vim version 8.2. Last change: 2019 Dec 24 +*todo.txt* For Vim version 8.2. Last change: 2020 Jan 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -38,6 +38,8 @@ browser use: https://github.com/vim/vim/issues/1234 *known-bugs* -------------------- Known bugs and current work ----------------------- +- Implement prop_find() issue #4970 Done by Ryan Hackett, #5421 + Include ipv6 syntax changes? (DJ Lucas, #5360) Still have /* */ comments: @@ -50,7 +52,9 @@ Popup windows: input? Sort-of possible by creating a hidden terminal and opening a popup with that buffer: #4063. - Use popup (or popup menu) for command line completion -- Implement flip option +- When using a popup for the info of a completion menu, and there is not + enough space, let the popup overlap with the menu. (#4544) +- Implement flip option. - Make redrawing more efficient and avoid flicker: - put popup menu also in popup_mask? - Any other commands to disable in a popup window? @@ -58,7 +62,6 @@ Popup windows: - Figure out the size and position better if wrapping inserts indent Text properties: -- Implement prop_find() issue #4970 - Text properties spanning more than one line - See remarks at top of src/textprop.c @@ -125,7 +128,7 @@ Terminal emulator window: conversions. Error numbers available: -E292, E362, E366, E450, E451, E452, +E362, E366, E450, E451, E452, E453, E454, E460, E489, E491, E565, E578, E610, E611, E653, E654, E856, E857, E860, E861, E863, E889, E900 @@ -192,6 +195,8 @@ It can replace the BeOS code, which is likely not used anymore. Now on github: #1856. Updated Oct 2017 Got permission to include this under the Vim license. +Add "t" action to settagstack(): truncate and add new entries. (#5405) + Result of synID() sometimes wrong in help files. (#5252) Problem showing a line if the number column width changes when using "o". diff --git a/runtime/doc/version8.txt b/runtime/doc/version8.txt index 86478a36ec..0e7c2b7f99 100644 --- a/runtime/doc/version8.txt +++ b/runtime/doc/version8.txt @@ -1,4 +1,4 @@ -*version8.txt* For Vim version 8.2. Last change: 2019 Dec 21 +*version8.txt* For Vim version 8.2. Last change: 2019 Dec 29 VIM REFERENCE MANUAL by Bram Moolenaar @@ -26004,7 +26004,6 @@ Added commands: `:tlmenu` `:tlnoremenu` `:tlunmenu` - `:wsverb` `:xrestore` Added options: From 509ff0688df557155feb7312a0129428eb5d8fc1 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 2 Jan 2020 22:38:49 +0100 Subject: [PATCH 05/42] patch 8.2.0080: globals using INIT4() are not in the tags file Problem: Globals using INIT4() are not in the tags file. Solution: Adjust the tags command. --- src/auto/configure | 6 +++--- src/configure.ac | 6 +++--- src/version.c | 2 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/auto/configure b/src/auto/configure index b7c1c11e80..993049573a 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -14306,11 +14306,11 @@ fi $as_echo_n "checking how to create tags... " >&6; } test -f tags && mv tags tags.save if (eval ctags --version /dev/null | grep Exuberant) < /dev/null 1>&5 2>&1; then - TAGPRG="ctags -I INIT+ --fields=+S" + TAGPRG="ctags -I INIT+,INIT2+,INIT3+,INIT4+,INIT5+ --fields=+S" elif (eval exctags --version /dev/null | grep Exuberant) < /dev/null 1>&5 2>&1; then - TAGPRG="exctags -I INIT+ --fields=+S" + TAGPRG="exctags -I INIT+,INIT2+,INIT3+,INIT4+,INIT5+ --fields=+S" elif (eval exuberant-ctags --version /dev/null | grep Exuberant) < /dev/null 1>&5 2>&1; then - TAGPRG="exuberant-ctags -I INIT+ --fields=+S" + TAGPRG="exuberant-ctags -I INIT+,INIT2+,INIT3+,INIT4+,INIT5+ --fields=+S" else TAGPRG="ctags" (eval etags /dev/null) < /dev/null 1>&5 2>&1 && TAGPRG="etags" diff --git a/src/configure.ac b/src/configure.ac index fd93b78227..d440a465ca 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -4236,11 +4236,11 @@ dnl -i+m to test for older Exuberant ctags AC_MSG_CHECKING(how to create tags) test -f tags && mv tags tags.save if (eval ctags --version /dev/null | grep Exuberant) < /dev/null 1>&AC_FD_CC 2>&1; then - TAGPRG="ctags -I INIT+ --fields=+S" + TAGPRG="ctags -I INIT+,INIT2+,INIT3+,INIT4+,INIT5+ --fields=+S" elif (eval exctags --version /dev/null | grep Exuberant) < /dev/null 1>&AC_FD_CC 2>&1; then - TAGPRG="exctags -I INIT+ --fields=+S" + TAGPRG="exctags -I INIT+,INIT2+,INIT3+,INIT4+,INIT5+ --fields=+S" elif (eval exuberant-ctags --version /dev/null | grep Exuberant) < /dev/null 1>&AC_FD_CC 2>&1; then - TAGPRG="exuberant-ctags -I INIT+ --fields=+S" + TAGPRG="exuberant-ctags -I INIT+,INIT2+,INIT3+,INIT4+,INIT5+ --fields=+S" else TAGPRG="ctags" (eval etags /dev/null) < /dev/null 1>&AC_FD_CC 2>&1 && TAGPRG="etags" diff --git a/src/version.c b/src/version.c index 052b6341e1..626c382937 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 80, /**/ 79, /**/ From 467c32bd72efea09677f173fef7a3465d9ab7826 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 3 Jan 2020 19:12:09 +0100 Subject: [PATCH 06/42] patch 8.2.0081: MS-Windows also need the change to support INIT4() Problem: MS-Windows also need the change to support INIT4(). Solution: Add the ctags arguments. (Ken Takata) --- src/Make_cyg_ming.mak | 2 +- src/Make_mvc.mak | 2 +- src/version.c | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index 32fa35cc77..3c878cbfb6 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -115,7 +115,7 @@ endif ifndef CTAGS # this assumes ctags is Exuberant ctags -CTAGS = ctags -I INIT+ --fields=+S +CTAGS = ctags -I INIT+,INIT2+,INIT3+,INIT4+,INIT5+ --fields=+S endif # Link against the shared version of libstdc++ by default. Set diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index 2718a05b7c..8694f7496a 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -334,7 +334,7 @@ FEATURES = HUGE !ifndef CTAGS # this assumes ctags is Exuberant ctags -CTAGS = ctags -I INIT+ --fields=+S +CTAGS = ctags -I INIT+,INIT2+,INIT3+,INIT4+,INIT5+ --fields=+S !endif !ifndef CSCOPE diff --git a/src/version.c b/src/version.c index 626c382937..cff754f28d 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 81, /**/ 80, /**/ From f10997a1543eb0724d882da3678bacd44e647141 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 3 Jan 2020 21:00:02 +0100 Subject: [PATCH 07/42] patch 8.2.0082: when reusing a buffer listeners are not cleared Problem: When reusing a buffer listeners are not cleared. (Axel Forsman) Solution: Clear listeners when reusing a buffer. (closes #5431) --- src/buffer.c | 1 + src/testdir/test_listener.vim | 31 +++++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 34 insertions(+) diff --git a/src/buffer.c b/src/buffer.c index eb6b287728..0a68d484e5 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -979,6 +979,7 @@ free_buffer_stuff( hash_init(&buf->b_vars->dv_hashtab); init_changedtick(buf); CHANGEDTICK(buf) = tick; + remove_listeners(buf); } #endif uc_clear(&buf->b_ucmds); // clear local user commands diff --git a/src/testdir/test_listener.vim b/src/testdir/test_listener.vim index a7815dc046..a263abadd2 100644 --- a/src/testdir/test_listener.vim +++ b/src/testdir/test_listener.vim @@ -295,3 +295,34 @@ func Test_listener_undo_line_number() delfunc EchoChanges call listener_remove(lid) endfunc + +func Test_listener_cleared_newbuf() + func Listener(bufnr, start, end, added, changes) + let g:gotCalled += 1 + endfunc + new + " check that listening works + let g:gotCalled = 0 + let lid = listener_add("Listener") + call feedkeys("axxx\", 'xt') + call listener_flush(bufnr()) + call assert_equal(1, g:gotCalled) + %bwipe! + let bufnr = bufnr() + let b:testing = 123 + let lid = listener_add("Listener") + enew! + " check buffer is reused + call assert_equal(bufnr, bufnr()) + call assert_false(exists('b:testing')) + + " check that listening stops when reusing the buffer + let g:gotCalled = 0 + call feedkeys("axxx\", 'xt') + call listener_flush(bufnr()) + call assert_equal(0, g:gotCalled) + unlet g:gotCalled + + bwipe! + delfunc Listener +endfunc diff --git a/src/version.c b/src/version.c index cff754f28d..6dd07bb686 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 82, /**/ 81, /**/ From 5cb0b93d52fa5c12ca50a18509947ee6459bb7a8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 3 Jan 2020 21:25:59 +0100 Subject: [PATCH 08/42] patch 8.2.0083: text properties wrong when tabs and spaces are exchanged Problem: Text properties wrong when tabs and spaces are exchanged. Solution: Take text properties into account. (Nobuhiro Takasaki, closes #5427) --- src/edit.c | 14 ++++++++++---- src/testdir/test_textprop.vim | 36 +++++++++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/edit.c b/src/edit.c index c67f67cb39..d2e45dd2f0 100644 --- a/src/edit.c +++ b/src/edit.c @@ -5601,14 +5601,20 @@ ins_tab(void) i = cursor->col - fpos.col; if (i > 0) { - STRMOVE(ptr, ptr + i); +#ifdef FEAT_PROP_POPUP + if (!(State & VREPLACE_FLAG)) + { + mch_memmove(ptr, ptr + i, curbuf->b_ml.ml_line_len - i + - (ptr - curbuf->b_ml.ml_line_ptr)); + curbuf->b_ml.ml_line_len -= i; + } + else +#endif + STRMOVE(ptr, ptr + i); // correct replace stack. if ((State & REPLACE_FLAG) && !(State & VREPLACE_FLAG)) for (temp = i; --temp >= 0; ) replace_join(repl_off); -#ifdef FEAT_PROP_POPUP - curbuf->b_ml.ml_line_len -= i; -#endif } #ifdef FEAT_NETBEANS_INTG if (netbeans_active()) diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim index ded56a8600..54b42c1467 100644 --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -925,3 +925,39 @@ func Test_proptype_substitute2() call assert_equal(expected, prop_list(1)) bwipe! endfunc + +func Test_textprop_noexpandtab() + %bwipe! + new + let save_ts = &tabstop + set tabstop=8 + let save_sts = &softtabstop + set softtabstop=4 + let save_sw = &shiftwidth + set shiftwidth=4 + let save_et = &expandtab + set noexpandtab + let save_fdm = &foldmethod + set foldmethod=marker + call feedkeys("\\0Ca\\\", "tx") + call prop_type_add('test', {'highlight': 'ErrorMsg'}) + call prop_add(1, 1, {'end_col': 2, 'type': 'test'}) + call feedkeys("0i\", "tx") + call prop_remove({'type': 'test'}) + call prop_add(1, 2, {'end_col': 3, 'type': 'test'}) + call feedkeys("A\\", "tx") + call prop_remove({'type': 'test'}) + try + " It is correct that this does not pass + call prop_add(1, 6, {'end_col': 7, 'type': 'test'}) + " Has already collapsed here, start_col:6 does not result in an error + call feedkeys("A\\", "tx") + catch /^Vim\%((\a\+)\)\=:E964/ + endtry + call prop_remove({'type': 'test'}) + let &foldmethod = save_fdm + let &expandtab = save_et + let &shiftwidth = save_sw + let &softtabstop = save_sts + let &tabstop = save_ts +endfunc diff --git a/src/version.c b/src/version.c index 6dd07bb686..3c8feee7c0 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 83, /**/ 82, /**/ From 0892832bb6c7e322fcae8560eaad5a8140ee4a06 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 4 Jan 2020 14:32:48 +0100 Subject: [PATCH 09/42] patch 8.2.0084: complete item "user_data" can only be a string Problem: Complete item "user_data" can only be a string. Solution: Accept any type of variable. (closes #5412) --- runtime/doc/insert.txt | 3 +- src/dict.c | 40 +++++++++++++++++++++++++- src/eval.c | 4 +-- src/insexpand.c | 41 +++++++++++++++++---------- src/proto/dict.pro | 4 ++- src/testdir/test_ins_complete.vim | 47 ++++++++++++++++--------------- src/version.c | 2 ++ 7 files changed, 98 insertions(+), 43 deletions(-) diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index 419213dba5..fa7c0f7c45 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -1108,7 +1108,8 @@ items: empty when non-zero this match will be added even when it is an empty string user_data custom data which is associated with the item and - available in |v:completed_item| + available in |v:completed_item|; it can be any type; + defaults to an empty string All of these except "icase", "equal", "dup" and "empty" must be a string. If an item does not meet these requirements then an error message is given and diff --git a/src/dict.c b/src/dict.c index 5022a5fd01..f170937b61 100644 --- a/src/dict.c +++ b/src/dict.c @@ -447,6 +447,27 @@ dict_add_list(dict_T *d, char *key, list_T *list) return OK; } +/* + * Add a typval_T entry to dictionary "d". + * Returns FAIL when out of memory and when key already exists. + */ + int +dict_add_tv(dict_T *d, char *key, typval_T *tv) +{ + dictitem_T *item; + + item = dictitem_alloc((char_u *)key); + if (item == NULL) + return FAIL; + copy_tv(tv, &item->di_tv); + if (dict_add(d, item) == FAIL) + { + dictitem_free(item); + return FAIL; + } + return OK; +} + /* * Add a callback to dictionary "d". * Returns FAIL when out of memory and when key already exists. @@ -589,6 +610,23 @@ dict_find(dict_T *d, char_u *key, int len) return HI2DI(hi); } +/* + * Get a typval_T item from a dictionary and copy it into "rettv". + * Returns FAIL if the entry doesn't exist or out of memory. + */ + int +dict_get_tv(dict_T *d, char_u *key, typval_T *rettv) +{ + dictitem_T *di; + char_u *s; + + di = dict_find(d, key, -1); + if (di == NULL) + return FAIL; + copy_tv(&di->di_tv, rettv); + return OK; +} + /* * Get a string item from a dictionary. * When "save" is TRUE allocate memory for it. @@ -745,7 +783,7 @@ get_literal_key(char_u **arg, typval_T *tv) * Return OK or FAIL. Returns NOTDONE for {expr}. */ int -dict_get_tv(char_u **arg, typval_T *rettv, int evaluate, int literal) +eval_dict(char_u **arg, typval_T *rettv, int evaluate, int literal) { dict_T *d = NULL; typval_T tvkey; diff --git a/src/eval.c b/src/eval.c index 04abbabae5..2a2d9d463e 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2656,7 +2656,7 @@ eval7( case '#': if ((*arg)[1] == '{') { ++*arg; - ret = dict_get_tv(arg, rettv, evaluate, TRUE); + ret = eval_dict(arg, rettv, evaluate, TRUE); } else ret = NOTDONE; @@ -2668,7 +2668,7 @@ eval7( */ case '{': ret = get_lambda_tv(arg, rettv, evaluate); if (ret == NOTDONE) - ret = dict_get_tv(arg, rettv, evaluate, FALSE); + ret = eval_dict(arg, rettv, evaluate, FALSE); break; /* diff --git a/src/insexpand.c b/src/insexpand.c index 1cada4fd10..7407647490 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -91,8 +91,7 @@ static char *ctrl_x_mode_names[] = { #define CPT_MENU 1 // "menu" #define CPT_KIND 2 // "kind" #define CPT_INFO 3 // "info" -#define CPT_USER_DATA 4 // "user data" -#define CPT_COUNT 5 // Number of entries +#define CPT_COUNT 4 // Number of entries /* * Structure used to store one match for insert completion. @@ -104,6 +103,7 @@ struct compl_S compl_T *cp_prev; char_u *cp_str; // matched text char_u *(cp_text[CPT_COUNT]); // text for the menu + typval_T cp_user_data; char_u *cp_fname; // file containing the match, allocated when // cp_flags has CP_FREE_FNAME int cp_flags; // CP_ values @@ -187,7 +187,7 @@ static expand_T compl_xp; static int compl_opt_refresh_always = FALSE; static int compl_opt_suppress_empty = FALSE; -static int ins_compl_add(char_u *str, int len, char_u *fname, char_u **cptext, int cdir, int flags, int adup); +static int ins_compl_add(char_u *str, int len, char_u *fname, char_u **cptext, typval_T *user_data, int cdir, int flags, int adup); static void ins_compl_longest_match(compl_T *match); static void ins_compl_del_pum(void); static void ins_compl_files(int count, char_u **files, int thesaurus, int flags, regmatch_T *regmatch, char_u *buf, int *dir); @@ -560,7 +560,7 @@ ins_compl_add_infercase( if (icase) flags |= CP_ICASE; - return ins_compl_add(str, len, fname, NULL, dir, flags, FALSE); + return ins_compl_add(str, len, fname, NULL, NULL, dir, flags, FALSE); } /* @@ -574,10 +574,11 @@ ins_compl_add( char_u *str, int len, char_u *fname, - char_u **cptext, // extra text for popup menu or NULL + char_u **cptext, // extra text for popup menu or NULL + typval_T *user_data, // "user_data" entry or NULL int cdir, int flags_arg, - int adup) // accept duplicate match + int adup) // accept duplicate match { compl_T *match; int dir = (cdir == 0 ? compl_direction : cdir); @@ -646,6 +647,8 @@ ins_compl_add( if (cptext[i] != NULL && *cptext[i] != NUL) match->cp_text[i] = vim_strsave(cptext[i]); } + if (user_data != NULL) + match->cp_user_data = *user_data; // Link the new match structure in the list of matches. if (compl_first_match == NULL) @@ -783,7 +786,7 @@ ins_compl_add_matches( int dir = compl_direction; for (i = 0; i < num_matches && add_r != FAIL; i++) - if ((add_r = ins_compl_add(matches[i], -1, NULL, NULL, dir, + if ((add_r = ins_compl_add(matches[i], -1, NULL, NULL, NULL, dir, icase ? CP_ICASE : 0, FALSE)) == OK) // if dir was BACKWARD then honor it just once dir = FORWARD; @@ -952,7 +955,10 @@ ins_compl_dict_alloc(compl_T *match) dict_add_string(dict, "menu", match->cp_text[CPT_MENU]); dict_add_string(dict, "kind", match->cp_text[CPT_KIND]); dict_add_string(dict, "info", match->cp_text[CPT_INFO]); - dict_add_string(dict, "user_data", match->cp_text[CPT_USER_DATA]); + if (match->cp_user_data.v_type == VAR_UNKNOWN) + dict_add_string(dict, "user_data", (char_u *)""); + else + dict_add_tv(dict, "user_data", &match->cp_user_data); } return dict; } @@ -1453,6 +1459,7 @@ ins_compl_free(void) vim_free(match->cp_fname); for (i = 0; i < CPT_COUNT; ++i) vim_free(match->cp_text[i]); + clear_tv(&match->cp_user_data); vim_free(match); } while (compl_curr_match != NULL && compl_curr_match != compl_first_match); compl_first_match = compl_curr_match = NULL; @@ -2264,7 +2271,9 @@ ins_compl_add_tv(typval_T *tv, int dir) int empty = FALSE; int flags = 0; char_u *(cptext[CPT_COUNT]); + typval_T user_data; + user_data.v_type = VAR_UNKNOWN; if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) { word = dict_get_string(tv->vval.v_dict, (char_u *)"word", FALSE); @@ -2276,8 +2285,7 @@ ins_compl_add_tv(typval_T *tv, int dir) (char_u *)"kind", FALSE); cptext[CPT_INFO] = dict_get_string(tv->vval.v_dict, (char_u *)"info", FALSE); - cptext[CPT_USER_DATA] = dict_get_string(tv->vval.v_dict, - (char_u *)"user_data", FALSE); + dict_get_tv(tv->vval.v_dict, (char_u *)"user_data", &user_data); if (dict_get_string(tv->vval.v_dict, (char_u *)"icase", FALSE) != NULL && dict_get_number(tv->vval.v_dict, (char_u *)"icase")) flags |= CP_ICASE; @@ -2296,7 +2304,7 @@ ins_compl_add_tv(typval_T *tv, int dir) } if (word == NULL || (!empty && *word == NUL)) return FAIL; - return ins_compl_add(word, -1, NULL, cptext, dir, flags, dup); + return ins_compl_add(word, -1, NULL, cptext, &user_data, dir, flags, dup); } /* @@ -2373,7 +2381,7 @@ set_completion(colnr_T startcol, list_T *list) if (p_ic) flags |= CP_ICASE; if (compl_orig_text == NULL || ins_compl_add(compl_orig_text, - -1, NULL, NULL, 0, flags, FALSE) != OK) + -1, NULL, NULL, NULL, 0, flags, FALSE) != OK) return; ctrl_x_mode = CTRL_X_EVAL; @@ -2541,8 +2549,11 @@ get_complete_info(list_T *what_list, dict_T *retdict) dict_add_string(di, "menu", match->cp_text[CPT_MENU]); dict_add_string(di, "kind", match->cp_text[CPT_KIND]); dict_add_string(di, "info", match->cp_text[CPT_INFO]); - dict_add_string(di, "user_data", - match->cp_text[CPT_USER_DATA]); + if (match->cp_user_data.v_type == VAR_UNKNOWN) + // Add an empty string for backwards compatibility + dict_add_string(di, "user_data", (char_u *)""); + else + dict_add_tv(di, "user_data", &match->cp_user_data); } match = match->cp_next; } @@ -3893,7 +3904,7 @@ ins_complete(int c, int enable_pum) if (p_ic) flags |= CP_ICASE; if (compl_orig_text == NULL || ins_compl_add(compl_orig_text, - -1, NULL, NULL, 0, flags, FALSE) != OK) + -1, NULL, NULL, NULL, 0, flags, FALSE) != OK) { VIM_CLEAR(compl_pattern); VIM_CLEAR(compl_orig_text); diff --git a/src/proto/dict.pro b/src/proto/dict.pro index 3185edc8c3..75519a4047 100644 --- a/src/proto/dict.pro +++ b/src/proto/dict.pro @@ -18,18 +18,20 @@ int dict_add_special(dict_T *d, char *key, varnumber_T nr); int dict_add_string(dict_T *d, char *key, char_u *str); int dict_add_string_len(dict_T *d, char *key, char_u *str, int len); int dict_add_list(dict_T *d, char *key, list_T *list); +int dict_add_tv(dict_T *d, char *key, typval_T *tv); int dict_add_callback(dict_T *d, char *key, callback_T *cb); void dict_iterate_start(typval_T *var, dict_iterator_T *iter); char_u *dict_iterate_next(dict_iterator_T *iter, typval_T **tv_result); int dict_add_dict(dict_T *d, char *key, dict_T *dict); long dict_len(dict_T *d); dictitem_T *dict_find(dict_T *d, char_u *key, int len); +int dict_get_tv(dict_T *d, char_u *key, typval_T *rettv); char_u *dict_get_string(dict_T *d, char_u *key, int save); varnumber_T dict_get_number(dict_T *d, char_u *key); varnumber_T dict_get_number_def(dict_T *d, char_u *key, int def); varnumber_T dict_get_number_check(dict_T *d, char_u *key); char_u *dict2string(typval_T *tv, int copyID, int restore_copyID); -int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate, int literal); +int eval_dict(char_u **arg, typval_T *rettv, int evaluate, int literal); void dict_extend(dict_T *d1, dict_T *d2, char_u *action); dictitem_T *dict_lookup(hashitem_T *hi); int dict_equal(dict_T *d1, dict_T *d2, int ic, int recursive); diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index 95954f536b..bec6ffc6f9 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -158,17 +158,17 @@ func s:CompleteDone_CompleteFuncDict( findstart, base ) endif return { - \ 'words': [ - \ { - \ 'word': 'aword', - \ 'abbr': 'wrd', - \ 'menu': 'extra text', - \ 'info': 'words are cool', - \ 'kind': 'W', - \ 'user_data': 'test' - \ } - \ ] - \ } + \ 'words': [ + \ { + \ 'word': 'aword', + \ 'abbr': 'wrd', + \ 'menu': 'extra text', + \ 'info': 'words are cool', + \ 'kind': 'W', + \ 'user_data': 'test' + \ } + \ ] + \ } endfunc func s:CompleteDone_CheckCompletedItemNone() @@ -222,16 +222,17 @@ func s:CompleteDone_CompleteFuncDictNoUserData(findstart, base) endif return { - \ 'words': [ - \ { - \ 'word': 'aword', - \ 'abbr': 'wrd', - \ 'menu': 'extra text', - \ 'info': 'words are cool', - \ 'kind': 'W' - \ } - \ ] - \ } + \ 'words': [ + \ { + \ 'word': 'aword', + \ 'abbr': 'wrd', + \ 'menu': 'extra text', + \ 'info': 'words are cool', + \ 'kind': 'W', + \ 'user_data': ['one', 'two'], + \ } + \ ] + \ } endfunc func s:CompleteDone_CheckCompletedItemDictNoUserData() @@ -240,7 +241,7 @@ func s:CompleteDone_CheckCompletedItemDictNoUserData() call assert_equal( 'extra text', v:completed_item[ 'menu' ] ) call assert_equal( 'words are cool', v:completed_item[ 'info' ] ) call assert_equal( 'W', v:completed_item[ 'kind' ] ) - call assert_equal( '', v:completed_item[ 'user_data' ] ) + call assert_equal( ['one', 'two'], v:completed_item[ 'user_data' ] ) let s:called_completedone = 1 endfunc @@ -252,7 +253,7 @@ func Test_CompleteDoneDictNoUserData() execute "normal a\\\" set completefunc& - call assert_equal('', v:completed_item[ 'user_data' ]) + call assert_equal(['one', 'two'], v:completed_item[ 'user_data' ]) call assert_true(s:called_completedone) let s:called_completedone = 0 diff --git a/src/version.c b/src/version.c index 3c8feee7c0..6b2c9c82c6 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 84, /**/ 83, /**/ From 3d8a513b46b586cb5d2893e7f28c5f51c4dfdc17 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 4 Jan 2020 16:13:49 +0100 Subject: [PATCH 10/42] patch 8.2.0085: dead code in builtin functions Problem: Dead code in builtin functions. Solution: Clean up the code. --- src/evalvars.c | 14 ++++++-------- src/sound.c | 6 ------ src/textprop.c | 2 +- src/version.c | 2 ++ 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/evalvars.c b/src/evalvars.c index 3aaae13b45..6ec5c25dce 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -2980,7 +2980,7 @@ getwinvar( * "setwinvar()" and "settabwinvar()" functions */ static void -setwinvar(typval_T *argvars, typval_T *rettv UNUSED, int off) +setwinvar(typval_T *argvars, int off) { win_T *win; win_T *save_curwin; @@ -3381,15 +3381,13 @@ f_getbufvar(typval_T *argvars, typval_T *rettv) * "settabvar()" function */ void -f_settabvar(typval_T *argvars, typval_T *rettv) +f_settabvar(typval_T *argvars, typval_T *rettv UNUSED) { tabpage_T *save_curtab; tabpage_T *tp; char_u *varname, *tabvarname; typval_T *varp; - rettv->vval.v_number = 0; - if (check_secure()) return; @@ -3421,18 +3419,18 @@ f_settabvar(typval_T *argvars, typval_T *rettv) * "settabwinvar()" function */ void -f_settabwinvar(typval_T *argvars, typval_T *rettv) +f_settabwinvar(typval_T *argvars, typval_T *rettv UNUSED) { - setwinvar(argvars, rettv, 1); + setwinvar(argvars, 1); } /* * "setwinvar()" function */ void -f_setwinvar(typval_T *argvars, typval_T *rettv) +f_setwinvar(typval_T *argvars, typval_T *rettv UNUSED) { - setwinvar(argvars, rettv, 0); + setwinvar(argvars, 0); } /* diff --git a/src/sound.c b/src/sound.c index c3052fd243..9d91f6c086 100644 --- a/src/sound.c +++ b/src/sound.c @@ -351,9 +351,6 @@ f_sound_playevent(typval_T *argvars, typval_T *rettv) { WCHAR *wp; - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = 0; - wp = enc_to_utf16(tv_get_string(&argvars[0]), NULL); if (wp == NULL) return; @@ -375,9 +372,6 @@ f_sound_playfile(typval_T *argvars, typval_T *rettv) char buf[32]; MCIERROR err; - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = 0; - esc = vim_strsave_shellescape(tv_get_string(&argvars[0]), FALSE, FALSE); len = STRLEN(esc) + 5 + 18 + 1; diff --git a/src/textprop.c b/src/textprop.c index fa3830cb20..dfd30dd4f5 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -885,7 +885,7 @@ f_prop_type_delete(typval_T *argvars, typval_T *rettv UNUSED) * prop_type_get({name} [, {bufnr}]) */ void -f_prop_type_get(typval_T *argvars, typval_T *rettv UNUSED) +f_prop_type_get(typval_T *argvars, typval_T *rettv) { char_u *name = tv_get_string(&argvars[0]); diff --git a/src/version.c b/src/version.c index 6b2c9c82c6..d159ceb306 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 85, /**/ 84, /**/ From ab782c5b6f127b84f56e546004352de66e7cf66b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 4 Jan 2020 19:00:11 +0100 Subject: [PATCH 11/42] patch 8.2.0086: build error for small version Problem: Build error for small version. (Tony Mechelynck) Solution: Only use "user_data" with the +eval feature. Remove unused variable. --- src/dict.c | 1 - src/insexpand.c | 6 ++++++ src/version.c | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/dict.c b/src/dict.c index f170937b61..a9a909bc2a 100644 --- a/src/dict.c +++ b/src/dict.c @@ -618,7 +618,6 @@ dict_find(dict_T *d, char_u *key, int len) dict_get_tv(dict_T *d, char_u *key, typval_T *rettv) { dictitem_T *di; - char_u *s; di = dict_find(d, key, -1); if (di == NULL) diff --git a/src/insexpand.c b/src/insexpand.c index 7407647490..acddd2658c 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -103,7 +103,9 @@ struct compl_S compl_T *cp_prev; char_u *cp_str; // matched text char_u *(cp_text[CPT_COUNT]); // text for the menu +#ifdef FEAT_EVAL typval_T cp_user_data; +#endif char_u *cp_fname; // file containing the match, allocated when // cp_flags has CP_FREE_FNAME int cp_flags; // CP_ values @@ -647,8 +649,10 @@ ins_compl_add( if (cptext[i] != NULL && *cptext[i] != NUL) match->cp_text[i] = vim_strsave(cptext[i]); } +#ifdef FEAT_EVAL if (user_data != NULL) match->cp_user_data = *user_data; +#endif // Link the new match structure in the list of matches. if (compl_first_match == NULL) @@ -1459,7 +1463,9 @@ ins_compl_free(void) vim_free(match->cp_fname); for (i = 0; i < CPT_COUNT; ++i) vim_free(match->cp_text[i]); +#ifdef FEAT_EVAL clear_tv(&match->cp_user_data); +#endif vim_free(match); } while (compl_curr_match != NULL && compl_curr_match != compl_first_match); compl_first_match = compl_curr_match = NULL; diff --git a/src/version.c b/src/version.c index d159ceb306..eff491dc03 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 86, /**/ 85, /**/ From 61d7c0d52ca40ab8488c36e619d1e46503affd0b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 5 Jan 2020 14:38:40 +0100 Subject: [PATCH 12/42] patch 8.2.0087: crash in command line expansion when out of memory Problem: Crash in command line expansion when out of memory. Solution: Check for NULL pointer. Also make ExpandGeneric() static. (Dominique Pelle, closes #5437) --- src/cmdexpand.c | 18 ++++++++++++++---- src/proto/cmdexpand.pro | 1 - src/version.c | 2 ++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/cmdexpand.c b/src/cmdexpand.c index 9dc78ed5c3..d788e27565 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -16,6 +16,9 @@ static int cmd_showtail; // Only show path tail in lists ? static void set_expand_context(expand_T *xp); +static int ExpandGeneric(expand_T *xp, regmatch_T *regmatch, + int *num_file, char_u ***file, + char_u *((*func)(expand_T *, int)), int escaped); static int ExpandFromContext(expand_T *xp, char_u *, int *, char_u ***, int); static int expand_showtail(expand_T *xp); static int expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, int flagsarg); @@ -2214,7 +2217,7 @@ ExpandFromContext( * * Returns OK when no problems encountered, FAIL for error (out of memory). */ - int + static int ExpandGeneric( expand_T *xp, regmatch_T *regmatch, @@ -2250,6 +2253,13 @@ ExpandGeneric( str = vim_strsave_escaped(str, (char_u *)" \t\\."); else str = vim_strsave(str); + if (str == NULL) + { + FreeWild(count, *file); + *num_file = 0; + *file = NULL; + return FAIL; + } (*file)[count] = str; # ifdef FEAT_MENU if (func == get_menu_names && str != NULL) @@ -2268,13 +2278,14 @@ ExpandGeneric( { if (count == 0) return OK; - *num_file = count; *file = ALLOC_MULT(char_u *, count); if (*file == NULL) { - *file = (char_u **)""; + *num_file = 0; + *file = NULL; return FAIL; } + *num_file = count; count = 0; } } @@ -2297,7 +2308,6 @@ ExpandGeneric( // they don't show up when getting normal highlight names by ID. reset_expand_highlight(); #endif - return OK; } diff --git a/src/proto/cmdexpand.pro b/src/proto/cmdexpand.pro index f2cea9ff9c..523565942d 100644 --- a/src/proto/cmdexpand.pro +++ b/src/proto/cmdexpand.pro @@ -8,7 +8,6 @@ char_u *sm_gettail(char_u *s); char_u *addstar(char_u *fname, int len, int context); void set_cmd_context(expand_T *xp, char_u *str, int len, int col, int use_ccline); int expand_cmdline(expand_T *xp, char_u *str, int col, int *matchcount, char_u ***matches); -int ExpandGeneric(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file, char_u *((*func)(expand_T *, int)), int escaped); void globpath(char_u *path, char_u *file, garray_T *ga, int expand_options); void f_getcompletion(typval_T *argvars, typval_T *rettv); /* vim: set ft=c : */ diff --git a/src/version.c b/src/version.c index eff491dc03..dfa31a77e6 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 87, /**/ 86, /**/ From 830c1afc9d2cd5819a05c71d4e0b1f748a8c0519 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 5 Jan 2020 20:35:44 +0100 Subject: [PATCH 13/42] patch 8.2.0088: insufficient tests for tags; bug in using extra tag field Problem: Insufficient tests for tags; bug in using extra tag field when using an ex command to position the cursor. Solution: Fix the bug, add more tests. (Yegappan Lakshmanan, closes #5439) --- runtime/doc/tagsrch.txt | 13 +- src/tag.c | 4 +- src/testdir/test_ins_complete.vim | 28 +++ src/testdir/test_tagfunc.vim | 24 +++ src/testdir/test_tagjump.vim | 289 ++++++++++++++++++++++++++++++ src/testdir/test_taglist.vim | 96 ++++++++++ src/version.c | 2 + 7 files changed, 448 insertions(+), 8 deletions(-) diff --git a/runtime/doc/tagsrch.txt b/runtime/doc/tagsrch.txt index 1f8eed4f87..f57b9c5297 100644 --- a/runtime/doc/tagsrch.txt +++ b/runtime/doc/tagsrch.txt @@ -344,11 +344,11 @@ the same as above, with a "p" prepended. A static tag is a tag that is defined for a specific file. In a C program this could be a static function. -In Vi jumping to a tag sets the current search pattern. This means that -the "n" command after jumping to a tag does not search for the same pattern -that it did before jumping to the tag. Vim does not do this as we consider it -to be a bug. You can still find the tag search pattern in the search history. -If you really want the old Vi behavior, set the 't' flag in 'cpoptions'. +In Vi jumping to a tag sets the current search pattern. This means that the +"n" command after jumping to a tag does not search for the same pattern that +it did before jumping to the tag. Vim does not do this as we consider it to +be a bug. If you really want the old Vi behavior, set the 't' flag in +'cpoptions'. *tag-binary-search* Vim uses binary searching in the tags file to find the desired tag quickly @@ -426,8 +426,7 @@ would otherwise go unnoticed. Example: > In Vi the ":tag" command sets the last search pattern when the tag is searched for. In Vim this is not done, the previous search pattern is still remembered, -unless the 't' flag is present in 'cpoptions'. The search pattern is always -put in the search history, so you can modify it if searching fails. +unless the 't' flag is present in 'cpoptions'. *emacs-tags* *emacs_tags* *E430* Emacs style tag files are only supported if Vim was compiled with the diff --git a/src/tag.c b/src/tag.c index 4f897fa607..aaf19c9738 100644 --- a/src/tag.c +++ b/src/tag.c @@ -3808,6 +3808,7 @@ test_for_current( find_extra(char_u **pp) { char_u *str = *pp; + char_u first_char = **pp; // Repeat for addresses separated with ';' for (;;) @@ -3817,7 +3818,7 @@ find_extra(char_u **pp) else if (*str == '/' || *str == '?') { str = skip_regexp(str + 1, *str, FALSE, NULL); - if (*str != **pp) + if (*str != first_char) str = NULL; else ++str; @@ -3837,6 +3838,7 @@ find_extra(char_u **pp) || !(VIM_ISDIGIT(str[1]) || str[1] == '/' || str[1] == '?')) break; ++str; // skip ';' + first_char = *str; } if (str != NULL && STRNCMP(str, ";\"", 2) == 0) diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index bec6ffc6f9..c9d93ceb1e 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -432,3 +432,31 @@ func Test_pum_with_preview_win() call StopVimInTerminal(buf) call delete('Xpreviewscript') endfunc + +" Test for inserting the tag search pattern in insert mode +func Test_ins_compl_tag_sft() + call writefile([ + \ "!_TAG_FILE_ENCODING\tutf-8\t//", + \ "first\tXfoo\t/^int first() {}$/", + \ "second\tXfoo\t/^int second() {}$/", + \ "third\tXfoo\t/^int third() {}$/"], + \ 'Xtags') + set tags=Xtags + let code =<< trim [CODE] + int first() {} + int second() {} + int third() {} + [CODE] + call writefile(code, 'Xfoo') + + enew + set showfulltag + exe "normal isec\\\\" + call assert_equal('int second() {}', getline(1)) + set noshowfulltag + + call delete('Xtags') + call delete('Xfoo') + set tags& + %bwipe! +endfunc diff --git a/src/testdir/test_tagfunc.vim b/src/testdir/test_tagfunc.vim index 242aa3a235..97782ae21d 100644 --- a/src/testdir/test_tagfunc.vim +++ b/src/testdir/test_tagfunc.vim @@ -81,4 +81,28 @@ func Test_tagfunc() call delete('Xfile1') endfunc +" Test for modifying the tag stack from a tag function and jumping to a tag +" from a tag function +func Test_tagfunc_settagstack() + func Mytagfunc1(pat, flags, info) + call settagstack(1, {'tagname' : 'mytag', 'from' : [0, 10, 1, 0]}) + return [{'name' : 'mytag', 'filename' : 'Xtest', 'cmd' : '1'}] + endfunc + set tagfunc=Mytagfunc1 + call writefile([''], 'Xtest') + call assert_fails('tag xyz', 'E986:') + + func Mytagfunc2(pat, flags, info) + tag test_tag + return [{'name' : 'mytag', 'filename' : 'Xtest', 'cmd' : '1'}] + endfunc + set tagfunc=Mytagfunc2 + call assert_fails('tag xyz', 'E986:') + + call delete('Xtest') + set tagfunc& + delfunc Mytagfunc1 + delfunc Mytagfunc2 +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim index 8d32883da2..d7bc2992ee 100644 --- a/src/testdir/test_tagjump.vim +++ b/src/testdir/test_tagjump.vim @@ -578,4 +578,293 @@ func Test_tagline() set tags& endfunc +" Test for expanding environment variable in a tag file name +func Test_tag_envvar() + call writefile(["Func1\t$FOO\t/^Func1/"], 'Xtags') + set tags=Xtags + + let $FOO='TagTestEnv' + + let caught_exception = v:false + try + tag Func1 + catch /E429:/ + call assert_match('E429:.*"TagTestEnv".*', v:exception) + let caught_exception = v:true + endtry + call assert_true(caught_exception) + + set tags& + call delete('Xtags') + unlet $FOO +endfunc + +" Test for :ptag +func Test_ptag() + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "second\tXfile1\t2", + \ "third\tXfile1\t3",], + \ 'Xtags') + set tags=Xtags + call writefile(['first', 'second', 'third'], 'Xfile1') + + enew | only + ptag third + call assert_equal(2, winnr()) + call assert_equal(2, winnr('$')) + call assert_equal(1, getwinvar(1, '&previewwindow')) + call assert_equal(0, getwinvar(2, '&previewwindow')) + wincmd w + call assert_equal(3, line('.')) + + " jump to the tag again + ptag third + call assert_equal(3, line('.')) + + " close the preview window + pclose + call assert_equal(1, winnr('$')) + + call delete('Xfile1') + call delete('Xtags') + set tags& +endfunc + +" Tests for guessing the tag location +func Test_tag_guess() + call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", + \ "func1\tXfoo\t/^int func1(int x)/", + \ "func2\tXfoo\t/^int func2(int y)/", + \ "func3\tXfoo\t/^func3/", + \ "func4\tXfoo\t/^func4/"], + \ 'Xtags') + set tags=Xtags + let code =<< trim [CODE] + + int FUNC1 (int x) { } + int + func2 (int y) { } + int * func3 () { } + + [CODE] + call writefile(code, 'Xfoo') + + let v:statusmsg = '' + ta func1 + call assert_match('E435:', v:statusmsg) + call assert_equal(2, line('.')) + let v:statusmsg = '' + ta func2 + call assert_match('E435:', v:statusmsg) + call assert_equal(4, line('.')) + let v:statusmsg = '' + ta func3 + call assert_match('E435:', v:statusmsg) + call assert_equal(5, line('.')) + call assert_fails('ta func4', 'E434:') + + call delete('Xtags') + call delete('Xfoo') + set tags& +endfunc + +" Test for an unsorted tags file +func Test_tag_sort() + call writefile([ + \ "first\tXfoo\t1", + \ "ten\tXfoo\t3", + \ "six\tXfoo\t2"], + \ 'Xtags') + set tags=Xtags + let code =<< trim [CODE] + int first() {} + int six() {} + int ten() {} + [CODE] + call writefile(code, 'Xfoo') + + call assert_fails('tag first', 'E432:') + + call delete('Xtags') + call delete('Xfoo') + set tags& + %bwipe +endfunc + +" Test for an unsorted tags file +func Test_tag_fold() + call writefile([ + \ "!_TAG_FILE_ENCODING\tutf-8\t//", + \ "!_TAG_FILE_SORTED\t2\t/0=unsorted, 1=sorted, 2=foldcase/", + \ "first\tXfoo\t1", + \ "second\tXfoo\t2", + \ "third\tXfoo\t3"], + \ 'Xtags') + set tags=Xtags + let code =<< trim [CODE] + int first() {} + int second() {} + int third() {} + [CODE] + call writefile(code, 'Xfoo') + + enew + tag second + call assert_equal('Xfoo', bufname('')) + call assert_equal(2, line('.')) + + call delete('Xtags') + call delete('Xfoo') + set tags& + %bwipe +endfunc + +" Test for the :ltag command +func Test_ltag() + call writefile([ + \ "!_TAG_FILE_ENCODING\tutf-8\t//", + \ "first\tXfoo\t1", + \ "second\tXfoo\t/^int second() {}$/", + \ "third\tXfoo\t3"], + \ 'Xtags') + set tags=Xtags + let code =<< trim [CODE] + int first() {} + int second() {} + int third() {} + [CODE] + call writefile(code, 'Xfoo') + + enew + call setloclist(0, [], 'f') + ltag third + call assert_equal('Xfoo', bufname('')) + call assert_equal(3, line('.')) + call assert_equal([{'lnum': 3, 'bufnr': bufnr('Xfoo'), 'col': 0, + \ 'pattern': '', 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '', + \ 'module': '', 'text': 'third'}], getloclist(0)) + + ltag second + call assert_equal(2, line('.')) + call assert_equal([{'lnum': 0, 'bufnr': bufnr('Xfoo'), 'col': 0, + \ 'pattern': '^\Vint second() {}\$', 'valid': 1, 'vcol': 0, 'nr': 0, + \ 'type': '', 'module': '', 'text': 'second'}], getloclist(0)) + + call delete('Xtags') + call delete('Xfoo') + set tags& + %bwipe +endfunc + +" Test for setting the last search pattern to the tag search pattern +" when cpoptions has 't' +func Test_tag_last_search_pat() + call writefile([ + \ "!_TAG_FILE_ENCODING\tutf-8\t//", + \ "first\tXfoo\t/^int first() {}/", + \ "second\tXfoo\t/^int second() {}/", + \ "third\tXfoo\t/^int third() {}/"], + \ 'Xtags') + set tags=Xtags + let code =<< trim [CODE] + int first() {} + int second() {} + int third() {} + [CODE] + call writefile(code, 'Xfoo') + + enew + let save_cpo = &cpo + set cpo+=t + let @/ = '' + tag second + call assert_equal('^int second() {}', @/) + let &cpo = save_cpo + + call delete('Xtags') + call delete('Xfoo') + set tags& + %bwipe +endfunc + +" Test for jumping to a tag when the tag stack is full +func Test_tag_stack_full() + let l = [] + for i in range(10, 31) + let l += ["var" .. i .. "\tXfoo\t/^int var" .. i .. ";$/"] + endfor + call writefile(l, 'Xtags') + set tags=Xtags + + let l = [] + for i in range(10, 31) + let l += ["int var" .. i .. ";"] + endfor + call writefile(l, 'Xfoo') + + enew + for i in range(10, 30) + exe "tag var" .. i + endfor + let l = gettagstack() + call assert_equal(20, l.length) + call assert_equal('var11', l.items[0].tagname) + tag var31 + let l = gettagstack() + call assert_equal('var12', l.items[0].tagname) + call assert_equal('var31', l.items[19].tagname) + + " Jump from the top of the stack + call assert_fails('tag', 'E556:') + + " Pop from an unsaved buffer + enew! + call append(1, "sample text") + call assert_fails('pop', 'E37:') + call assert_equal(21, gettagstack().curidx) + enew! + + " Pop all the entries in the tag stack + call assert_fails('30pop', 'E555:') + + " Pop the tag stack when it is empty + call settagstack(1, {'items' : []}) + call assert_fails('pop', 'E73:') + + call delete('Xtags') + call delete('Xfoo') + set tags& + %bwipe +endfunc + +" Test for browsing multiple matching tags +func Test_tag_multimatch() + call writefile([ + \ "!_TAG_FILE_ENCODING\tutf-8\t//", + \ "first\tXfoo\t1", + \ "first\tXfoo\t2", + \ "first\tXfoo\t3"], + \ 'Xtags') + set tags=Xtags + let code =<< trim [CODE] + int first() {} + int first() {} + int first() {} + [CODE] + call writefile(code, 'Xfoo') + + tag first + tlast + call assert_equal(3, line('.')) + call assert_fails('tnext', 'E428:') + tfirst + call assert_equal(1, line('.')) + call assert_fails('tprev', 'E425:') + + call delete('Xtags') + call delete('Xfoo') + set tags& + %bwipe +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_taglist.vim b/src/testdir/test_taglist.vim index 824adc013b..0f2615d520 100644 --- a/src/testdir/test_taglist.vim +++ b/src/testdir/test_taglist.vim @@ -115,3 +115,99 @@ func Test_tagsfile_without_trailing_newline() call delete('Xtags') set tags& endfunc + +" Test for ignoring comments in a tags file +func Test_tagfile_ignore_comments() + call writefile([ + \ "!_TAG_PROGRAM_NAME /Test tags generator/", + \ "FBar\tXfoo\t2" .. ';"' .. "\textrafield\tf", + \ "!_TAG_FILE_FORMAT 2 /extended format/", + \ ], 'Xtags') + set tags=Xtags + + let l = taglist('.*') + call assert_equal(1, len(l)) + call assert_equal('FBar', l[0].name) + + set tags& + call delete('Xtags') +endfunc + +" Test for using an excmd in a tags file to position the cursor (instead of a +" search pattern or a line number) +func Test_tagfile_excmd() + call writefile([ + \ "vFoo\tXfoo\tcall cursor(3, 4)" .. '|;"' .. "\tv", + \ ], 'Xtags') + set tags=Xtags + + let l = taglist('.*') + call assert_equal([{ + \ 'cmd' : 'call cursor(3, 4)', + \ 'static' : 0, + \ 'name' : 'vFoo', + \ 'kind' : 'v', + \ 'filename' : 'Xfoo'}], l) + + set tags& + call delete('Xtags') +endfunc + +" Test for duplicate fields in a tag in a tags file +func Test_duplicate_field() + call writefile([ + \ "vFoo\tXfoo\t4" .. ';"' .. "\ttypename:int\ttypename:int\tv", + \ ], 'Xtags') + set tags=Xtags + + let l = taglist('.*') + call assert_equal([{ + \ 'cmd' : '4', + \ 'static' : 0, + \ 'name' : 'vFoo', + \ 'kind' : 'v', + \ 'typename' : 'int', + \ 'filename' : 'Xfoo'}], l) + + set tags& + call delete('Xtags') +endfunc + +" Test for tag address with ; +func Test_tag_addr_with_semicolon() + call writefile([ + \ "Func1\tXfoo\t6;/^Func1/" .. ';"' .. "\tf" + \ ], 'Xtags') + set tags=Xtags + + let l = taglist('.*') + call assert_equal([{ + \ 'cmd' : '6;/^Func1/', + \ 'static' : 0, + \ 'name' : 'Func1', + \ 'kind' : 'f', + \ 'filename' : 'Xfoo'}], l) + + set tags& + call delete('Xtags') +endfunc + +" Test for format error in a tags file +func Test_format_error() + call writefile(['vFoo-Xfoo-4'], 'Xtags') + set tags=Xtags + + let caught_exception = v:false + try + let l = taglist('.*') + catch /E431:/ + " test succeeded + let caught_exception = v:true + catch + call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint) + endtry + call assert_true(caught_exception) + + set tags& + call delete('Xtags') +endfunc diff --git a/src/version.c b/src/version.c index dfa31a77e6..c34675f46c 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 88, /**/ 87, /**/ From f0f8055102c264b1d0c0a79bf742dc126fb447b9 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 5 Jan 2020 22:05:49 +0100 Subject: [PATCH 14/42] patch 8.2.0089: crash when running out of memory in :setfiletype completion Problem: Crash when running out of memory in :setfiletype completion. Solution: Do not allocate memory. (Dominique Pelle, closes #5438) --- src/cmdexpand.c | 9 +++------ src/version.c | 2 ++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/cmdexpand.c b/src/cmdexpand.c index d788e27565..210b5f9819 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -2633,16 +2633,13 @@ globpath( ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT|expand_options); if (ga_grow(ga, num_p) == OK) - { + // take over the pointers and put them in "ga" for (i = 0; i < num_p; ++i) { - ((char_u **)ga->ga_data)[ga->ga_len] = - vim_strnsave(p[i], (int)STRLEN(p[i])); + ((char_u **)ga->ga_data)[ga->ga_len] = p[i]; ++ga->ga_len; } - } - - FreeWild(num_p, p); + vim_free(p); } } } diff --git a/src/version.c b/src/version.c index c34675f46c..c82f379cd8 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 89, /**/ 88, /**/ From b376ace1aeaa7614debc725487d75c8f756dd773 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 5 Jan 2020 22:10:31 +0100 Subject: [PATCH 15/42] patch 8.2.0090: generated files show up in git status Problem: Generated files show up in git status. Solution: Ignore a few more files. --- .gitignore | 2 ++ src/version.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 81b3b11060..2dc119476c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ src/auto/gui_gtk_gresources.h src/objects/.dirstamp src/objects src/tags +src/types.vim # We do need src/auto/configure. src/auto/config.cache @@ -86,6 +87,7 @@ src/kword_test # Generated by "make install" runtime/doc/tags +runtime/doc/doctags # Generated by "make shadow". The directory names could be anything but we # restrict them to shadow (the default) or shadow-* diff --git a/src/version.c b/src/version.c index c82f379cd8..43300cbecc 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 90, /**/ 89, /**/ From 4d7a248b644b647340ed1a25729e2ed586a54864 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 6 Jan 2020 19:53:43 +0100 Subject: [PATCH 16/42] patch 8.2.0091: compiler warnings for size_t / int types Problem: Compiler warnings for size_t / int types. Solution: Change type to size_t. (Mike Williams) --- src/scriptfile.c | 6 +++--- src/version.c | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/scriptfile.c b/src/scriptfile.c index 783e6bc757..38516c360a 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -97,10 +97,10 @@ estack_sfile(void) { estack_T *entry; #ifdef FEAT_EVAL - int len; + size_t len; int idx; char *res; - int done; + size_t done; #endif entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1; @@ -126,7 +126,7 @@ estack_sfile(void) len += STRLEN(entry->es_name) + 15; } - res = (char *)alloc(len); + res = (char *)alloc((int)len); if (res != NULL) { STRCPY(res, "function "); diff --git a/src/version.c b/src/version.c index 43300cbecc..d235ae7a44 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 91, /**/ 90, /**/ From a1353b5352f0797fc651a0dd363876f1c2fa60c5 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 6 Jan 2020 20:09:13 +0100 Subject: [PATCH 17/42] patch 8.2.0092: tags functionality insufficiently tested Problem: Tags functionality insufficiently tested. Solution: Add more tags tests. (Yegappan Lakshmanan, closes #5446) --- src/testdir/test_tagjump.vim | 178 ++++++++++++++++++++++++++++++++++- src/version.c | 2 + 2 files changed, 175 insertions(+), 5 deletions(-) diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim index d7bc2992ee..47b9ffb459 100644 --- a/src/testdir/test_tagjump.vim +++ b/src/testdir/test_tagjump.vim @@ -600,7 +600,7 @@ func Test_tag_envvar() endfunc " Test for :ptag -func Test_ptag() +func Test_tag_preview() call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//", \ "second\tXfile1\t2", \ "third\tXfile1\t3",], @@ -614,11 +614,19 @@ func Test_ptag() call assert_equal(2, winnr('$')) call assert_equal(1, getwinvar(1, '&previewwindow')) call assert_equal(0, getwinvar(2, '&previewwindow')) - wincmd w + wincmd P call assert_equal(3, line('.')) " jump to the tag again + wincmd w ptag third + wincmd P + call assert_equal(3, line('.')) + + " jump to the newer tag + wincmd w + ptag + wincmd P call assert_equal(3, line('.')) " close the preview window @@ -787,8 +795,8 @@ func Test_tag_last_search_pat() %bwipe endfunc -" Test for jumping to a tag when the tag stack is full -func Test_tag_stack_full() +" Tag stack tests +func Test_tag_stack() let l = [] for i in range(10, 31) let l += ["var" .. i .. "\tXfoo\t/^int var" .. i .. ";$/"] @@ -802,6 +810,7 @@ func Test_tag_stack_full() endfor call writefile(l, 'Xfoo') + " Jump to a tag when the tag stack is full. Oldest entry should be removed. enew for i in range(10, 30) exe "tag var" .. i @@ -814,9 +823,15 @@ func Test_tag_stack_full() call assert_equal('var12', l.items[0].tagname) call assert_equal('var31', l.items[19].tagname) - " Jump from the top of the stack + " Use tnext with a single match + call assert_fails('tnext', 'E427:') + + " Jump to newest entry from the top of the stack call assert_fails('tag', 'E556:') + " Pop with zero count from the top of the stack + call assert_fails('0pop', 'E556:') + " Pop from an unsaved buffer enew! call append(1, "sample text") @@ -827,6 +842,13 @@ func Test_tag_stack_full() " Pop all the entries in the tag stack call assert_fails('30pop', 'E555:') + " Pop with a count when already at the bottom of the stack + call assert_fails('exe "normal 4\"', 'E555:') + call assert_equal(1, gettagstack().curidx) + + " Jump to newest entry from the bottom of the stack with zero count + call assert_fails('0tag', 'E555:') + " Pop the tag stack when it is empty call settagstack(1, {'items' : []}) call assert_fails('pop', 'E73:') @@ -853,6 +875,7 @@ func Test_tag_multimatch() [CODE] call writefile(code, 'Xfoo') + call settagstack(1, {'items' : []}) tag first tlast call assert_equal(3, line('.')) @@ -861,6 +884,151 @@ func Test_tag_multimatch() call assert_equal(1, line('.')) call assert_fails('tprev', 'E425:') + tlast + call feedkeys("5\", 't') + tselect first + call assert_equal(2, gettagstack().curidx) + + set ignorecase + tag FIRST + tnext + call assert_equal(2, line('.')) + set ignorecase& + + call delete('Xtags') + call delete('Xfoo') + set tags& + %bwipe +endfunc + +" Test for previewing multiple matching tags +func Test_preview_tag_multimatch() + call writefile([ + \ "!_TAG_FILE_ENCODING\tutf-8\t//", + \ "first\tXfoo\t1", + \ "first\tXfoo\t2", + \ "first\tXfoo\t3"], + \ 'Xtags') + set tags=Xtags + let code =<< trim [CODE] + int first() {} + int first() {} + int first() {} + [CODE] + call writefile(code, 'Xfoo') + + enew | only + ptag first + ptlast + wincmd P + call assert_equal(3, line('.')) + wincmd w + call assert_fails('ptnext', 'E428:') + ptprev + wincmd P + call assert_equal(2, line('.')) + wincmd w + ptfirst + wincmd P + call assert_equal(1, line('.')) + wincmd w + call assert_fails('ptprev', 'E425:') + ptnext + wincmd P + call assert_equal(2, line('.')) + wincmd w + ptlast + call feedkeys("5\", 't') + ptselect first + wincmd P + call assert_equal(3, line('.')) + + pclose + + call delete('Xtags') + call delete('Xfoo') + set tags& + %bwipe +endfunc + +" Test for jumping to multiple matching tags across multiple :tags commands +func Test_tnext_multimatch() + call writefile([ + \ "!_TAG_FILE_ENCODING\tutf-8\t//", + \ "first\tXfoo1\t1", + \ "first\tXfoo2\t1", + \ "first\tXfoo3\t1"], + \ 'Xtags') + set tags=Xtags + let code =<< trim [CODE] + int first() {} + [CODE] + call writefile(code, 'Xfoo1') + call writefile(code, 'Xfoo2') + call writefile(code, 'Xfoo3') + + tag first + tag first + pop + tnext + tnext + call assert_fails('tnext', 'E428:') + + call delete('Xtags') + call delete('Xfoo1') + call delete('Xfoo2') + call delete('Xfoo3') + set tags& + %bwipe +endfunc + +" Test for jumping to multiple matching tags in non-existing files +func Test_multimatch_non_existing_files() + call writefile([ + \ "!_TAG_FILE_ENCODING\tutf-8\t//", + \ "first\tXfoo1\t1", + \ "first\tXfoo2\t1", + \ "first\tXfoo3\t1"], + \ 'Xtags') + set tags=Xtags + + call settagstack(1, {'items' : []}) + call assert_fails('tag first', 'E429:') + call assert_equal(3, gettagstack().items[0].matchnr) + + call delete('Xtags') + set tags& + %bwipe +endfunc + +func Test_tselect_listing() + call writefile([ + \ "!_TAG_FILE_ENCODING\tutf-8\t//", + \ "first\tXfoo\t1" .. ';"' .. "\tv\ttyperef:typename:int\tfile:", + \ "first\tXfoo\t2" .. ';"' .. "\tv\ttyperef:typename:char\tfile:"], + \ 'Xtags') + set tags=Xtags + + let code =<< trim [CODE] + static int first; + static char first; + [CODE] + call writefile(code, 'Xfoo') + + call feedkeys("\", "t") + let l = split(execute("tselect first"), "\n") + let expected =<< [DATA] + # pri kind tag file + 1 FS v first Xfoo + typeref:typename:int + 1 + 2 FS v first Xfoo + typeref:typename:char + 2 +Type number and (empty cancels): +[DATA] + call assert_equal(expected, l) + call delete('Xtags') call delete('Xfoo') set tags& diff --git a/src/version.c b/src/version.c index d235ae7a44..28590ad44e 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 92, /**/ 91, /**/ From 7b94e77132eabdf0e43abca57e2ffeb961545174 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 6 Jan 2020 21:03:24 +0100 Subject: [PATCH 18/42] patch 8.2.0093: win_splitmove() can make Vim hang Problem: win_splitmove() can make Vim hang. Solution: Check windows exists in the current tab page. (closes #5444) --- src/evalwindow.c | 3 ++- src/testdir/test_window_cmd.vim | 4 ++++ src/version.c | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/evalwindow.c b/src/evalwindow.c index 34d202e0ad..672bfc13c9 100644 --- a/src/evalwindow.c +++ b/src/evalwindow.c @@ -808,7 +808,8 @@ f_win_splitmove(typval_T *argvars, typval_T *rettv) wp = find_win_by_nr_or_id(&argvars[0]); targetwin = find_win_by_nr_or_id(&argvars[1]); - if (wp == NULL || targetwin == NULL || wp == targetwin) + if (wp == NULL || targetwin == NULL || wp == targetwin + || !win_valid(wp) || !win_valid(targetwin)) { emsg(_(e_invalwindow)); rettv->vval.v_number = -1; diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index d543ef7e63..87c1f1f25a 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -927,6 +927,10 @@ func Test_win_splitmove() call assert_fails('call win_splitmove(winnr(), 123)', 'E957:') call assert_fails('call win_splitmove(123, winnr())', 'E957:') call assert_fails('call win_splitmove(winnr(), winnr())', 'E957:') + + tabnew + call assert_fails('call win_splitmove(1, win_getid(1, 1))', 'E957:') + tabclose endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 28590ad44e..36dee83d27 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 93, /**/ 92, /**/ From e73b38f8e10c220a382270f69e24cad08d3bf792 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 6 Jan 2020 21:22:09 +0100 Subject: [PATCH 19/42] patch 8.2.0094: MS-Windows: cannot build with Strawberry Perl 5.30 Problem: MS-Windows: cannot build with Strawberry Perl 5.30. Solution: Define __builtin_expect() as a workaround. (Ken Takata, closes #5267) --- src/if_perl.xs | 3 +++ src/version.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/if_perl.xs b/src/if_perl.xs index 099d386776..fd9d3d730f 100644 --- a/src/if_perl.xs +++ b/src/if_perl.xs @@ -47,6 +47,9 @@ /* Work around for using MSVC and ActivePerl 5.18. */ #ifdef _MSC_VER # define __inline__ __inline + +// Work around for using MSVC and Strawberry Perl 5.30. +# define __builtin_expect(expr, val) (expr) #endif #ifdef __GNUC__ diff --git a/src/version.c b/src/version.c index 36dee83d27..41a6d37012 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 94, /**/ 93, /**/ From 1860bde9d31bbb0ba857f6284f6332a7134030dd Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 6 Jan 2020 21:47:21 +0100 Subject: [PATCH 20/42] patch 8.2.0095: cannot specify exit code for :cquit Problem: Cannot specify exit code for :cquit. Solution: Add optional argument. (Thinca, Yegappan Lakshmanan, closes #5442) --- runtime/doc/quickfix.txt | 13 +++++++++++-- src/ex_cmds.h | 2 +- src/ex_docmd.c | 4 ++-- src/testdir/test_quickfix.vim | 25 +++++++++++++++++++++++++ src/version.c | 2 ++ 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index 5879727d2b..ae45819156 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -229,8 +229,17 @@ processing a quickfix or location list command, it will be aborted. current window is used instead of the quickfix list. *:cq* *:cquit* -:cq[uit][!] Quit Vim with an error code, so that the compiler - will not compile the same file again. +:cq[uit][!] +:{N}cq[uit][!] +:cq[uit][!] {N} Quit Vim with error code {N}. {N} defaults to one. + Useful when Vim is called from another program: + e.g., a compiler will not compile the same file again, + `git commit` will abort the committing process, `fc` + (built-in for shells like bash and zsh) will not + execute the command, etc. will not compile the same + file again. + {N} can also be zero, in which case Vim exits + normally. WARNING: All changes in files are lost! Also when the [!] is not used. It works like ":qall!" |:qall|, except that Vim returns a non-zero exit code. diff --git a/src/ex_cmds.h b/src/ex_cmds.h index 14b43bda44..928b1100d8 100644 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -407,7 +407,7 @@ EXCMD(CMD_cpfile, "cpfile", ex_cnext, EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG, ADDR_OTHER), EXCMD(CMD_cquit, "cquit", ex_cquit, - EX_TRLBAR|EX_BANG, + EX_RANGE|EX_COUNT|EX_ZEROR|EX_TRLBAR|EX_BANG, ADDR_NONE), EXCMD(CMD_crewind, "crewind", ex_cc, EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG, diff --git a/src/ex_docmd.c b/src/ex_docmd.c index a3442edbe7..de8fb49617 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -4920,8 +4920,8 @@ ex_quit(exarg_T *eap) static void ex_cquit(exarg_T *eap UNUSED) { - getout(1); // this does not always pass on the exit code to the Manx - // compiler. why? + // this does not always pass on the exit code to the Manx compiler. why? + getout(eap->addr_count > 0 ? (int)eap->line2 : EXIT_FAILURE); } /* diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index f7c73f4c38..b7b4281962 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -4674,4 +4674,29 @@ func Test_search_in_dirstack() call delete('Xtestdir', 'rf') endfunc +" Test for :cquit +func Test_cquit() + " Exit Vim with a non-zero value + if RunVim([], ["cquit 7"], '') + call assert_equal(7, v:shell_error) + endif + + if RunVim([], ["50cquit"], '') + call assert_equal(50, v:shell_error) + endif + + " Exit Vim with default value + if RunVim([], ["cquit"], '') + call assert_equal(1, v:shell_error) + endif + + " Exit Vim with zero value + if RunVim([], ["cquit 0"], '') + call assert_equal(0, v:shell_error) + endif + + " Exit Vim with negative value + call assert_fails('-3cquit', 'E16:') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 41a6d37012..d007585eac 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 95, /**/ 94, /**/ From fbcdf671f08cd2c7e60f35574231df0421112d99 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 6 Jan 2020 23:07:48 +0100 Subject: [PATCH 21/42] patch 8.2.0096: cannot create tiny popup window in last column Problem: Cannot create tiny popup window in last column. (Daniel Steinberg) Solution: Remove position limit. (closes #5447) --- src/popupwin.c | 4 +- src/testdir/dumps/Test_popupwin_20.dump | 10 ++-- src/testdir/dumps/Test_popupwin_21.dump | 10 ++-- src/testdir/test_popupwin.vim | 78 +++++++++++++++++-------- src/version.c | 2 + 5 files changed, 67 insertions(+), 37 deletions(-) diff --git a/src/popupwin.c b/src/popupwin.c index e65b4bf440..c6296dfd2f 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -1222,8 +1222,8 @@ popup_adjust_position(win_T *wp) || wp->w_popup_pos == POPPOS_BOTLEFT)) { wp->w_wincol = wantcol - 1; - if (wp->w_wincol >= Columns - 3) - wp->w_wincol = Columns - 3; + if (wp->w_wincol >= Columns - 1) + wp->w_wincol = Columns - 1; } } diff --git a/src/testdir/dumps/Test_popupwin_20.dump b/src/testdir/dumps/Test_popupwin_20.dump index 2989cd1301..707db58dd2 100644 --- a/src/testdir/dumps/Test_popupwin_20.dump +++ b/src/testdir/dumps/Test_popupwin_20.dump @@ -1,9 +1,9 @@ >1+0&#ffffff0| @73 -|2| |++0#0000001#ffd7ff255|-@11|+| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|+|-@11|+| @18 -|3| ||+0#0000001#ffd7ff255|h|e|l@1|o| |b|o|r|d|e|r||| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255|h|e|l@1|o| |p|a|d@1|i|n|g| | +0#0000000#ffffff0@4||| @11||| @18 -|4| |++0#0000001#ffd7ff255|-@11|+| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4||| |h|e|l@1|o| |b|o|t|h| ||| @18 -|5| @40||| @11||| @18 -|6| |++0#0000001#ffd7ff255|-@8| +0#0000000#ffffff0@9| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|+|-@11|+| @18 +|2| |++0#0000001#ffd7ff255|-@11|+| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|+|-@11|+| @15|X+0#0000001#ffd7ff255| +0#0000000#ffffff0@1 +|3| ||+0#0000001#ffd7ff255|h|e|l@1|o| |b|o|r|d|e|r||| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255|h|e|l@1|o| |p|a|d@1|i|n|g| | +0#0000000#ffffff0@4||| @11||| @16|X+0#0000001#ffd7ff255| +0#0000000#ffffff0 +|4| |++0#0000001#ffd7ff255|-@11|+| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4||| |h|e|l@1|o| |b|o|t|h| ||| @17|X+0#0000001#ffd7ff255 +|5+0#0000000#ffffff0| @40||| @11||| @17|X+0#0000001#ffd7ff255 +|6+0#0000000#ffffff0| |++0#0000001#ffd7ff255|-@8| +0#0000000#ffffff0@9| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|+|-@11|+| @18 |7| ||+0#0000001#ffd7ff255|b|o|r|d|e|r| |T|L| +0#0000000#ffffff0@9| +0#0000001#ffd7ff255@3|p|a|d@1|i|n|g|s| @2| +0#0000000#ffffff0@37 |8| @20| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@12||+0#0000001#ffd7ff255| @2|w|r|a|p@1|e|d| |l|o|n|g|e|r| |t|e| @2|| |9+0#0000000#ffffff0| @20| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@12||+0#0000001#ffd7ff255| @2|x|t| @17|| diff --git a/src/testdir/dumps/Test_popupwin_21.dump b/src/testdir/dumps/Test_popupwin_21.dump index 68594f98e6..9b6f4d000d 100644 --- a/src/testdir/dumps/Test_popupwin_21.dump +++ b/src/testdir/dumps/Test_popupwin_21.dump @@ -1,9 +1,9 @@ >1+0&#ffffff0| @73 -|2| |╔+0#0000001#ffd7ff255|═@11|╗| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|╔|═@11|╗| @18 -|3| |║+0#0000001#ffd7ff255|h|e|l@1|o| |b|o|r|d|e|r|║| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255|h|e|l@1|o| |p|a|d@1|i|n|g| | +0#0000000#ffffff0@4|║| @11|║| @18 -|4| |╚+0#0000001#ffd7ff255|═@11|╝| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|║| |h|e|l@1|o| |b|o|t|h| |║| @18 -|5| @40|║| @11|║| @18 -|6| |╔+0#0000001#ffd7ff255|═@8| +0#0000000#ffffff0@9| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|╚|═@11|╝| @18 +|2| |╔+0#0000001#ffd7ff255|═@11|╗| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|╔|═@11|╗| @15|X+0#0000001#ffd7ff255| +0#0000000#ffffff0@1 +|3| |║+0#0000001#ffd7ff255|h|e|l@1|o| |b|o|r|d|e|r|║| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255|h|e|l@1|o| |p|a|d@1|i|n|g| | +0#0000000#ffffff0@4|║| @11|║| @16|X+0#0000001#ffd7ff255| +0#0000000#ffffff0 +|4| |╚+0#0000001#ffd7ff255|═@11|╝| +0#0000000#ffffff0@5| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|║| |h|e|l@1|o| |b|o|t|h| |║| @17|X+0#0000001#ffd7ff255 +|5+0#0000000#ffffff0| @40|║| @11|║| @17|X+0#0000001#ffd7ff255 +|6+0#0000000#ffffff0| |╔+0#0000001#ffd7ff255|═@8| +0#0000000#ffffff0@9| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@4|╚|═@11|╝| @18 |7| |║+0#0000001#ffd7ff255|b|o|r|d|e|r| |T|L| +0#0000000#ffffff0@9| +0#0000001#ffd7ff255@3|p|a|d@1|i|n|g|s| @2| +0#0000000#ffffff0@37 |8| @20| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@12|║+0#0000001#ffd7ff255| @2|w|r|a|p@1|e|d| |l|o|n|g|e|r| |t|e| @2|║ |9+0#0000000#ffffff0| @20| +0#0000001#ffd7ff255@14| +0#0000000#ffffff0@12|║+0#0000001#ffd7ff255| @2|x|t| @17|║ diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index d5ee7160a1..94ea423c1b 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -89,6 +89,10 @@ func Test_popup_with_border_and_padding() call popup_create('paddings', #{line: 6, col: 23, padding: [1, 3, 2, 4]}) call popup_create('wrapped longer text', #{line: 8, col: 55, padding: [0, 3, 0, 3], border: [0, 1, 0, 1]}) call popup_create('right aligned text', #{line: 11, col: 56, wrap: 0, padding: [0, 3, 0, 3], border: [0, 1, 0, 1]}) + call popup_create('X', #{line: 2, col: 73}) + call popup_create('X', #{line: 3, col: 74}) + call popup_create('X', #{line: 4, col: 75}) + call popup_create('X', #{line: 5, col: 76}) END call insert(lines, iter == 1 ? '' : 'set enc=latin1') call writefile(lines, 'XtestPopupBorder') @@ -1634,8 +1638,8 @@ func s:VerifyPosition(p, msg, line, col, width, height) endfunc func Test_popup_position_adjust() - " Anything placed past 2 cells from of the right of the screen is moved to the - " left. + " Anything placed past the last cell on the right of the screen is moved to + " the left. " " When wrapping is disabled, we also shift to the left to display on the " screen, unless fixed is set. @@ -1643,24 +1647,11 @@ func Test_popup_position_adjust() " Entries for cases which don't vary based on wrapping. " Format is per tests described below let both_wrap_tests = [ - \ ['a', 5, &columns, 5, &columns - 2, 1, 1], - \ ['b', 5, &columns + 1, 5, &columns - 2, 1, 1], - \ ['c', 5, &columns - 1, 5, &columns - 2, 1, 1], + \ ['a', 5, &columns, 5, &columns, 1, 1], + \ ['b', 5, &columns + 1, 5, &columns, 1, 1], + \ ['c', 5, &columns - 1, 5, &columns - 1, 1, 1], \ ['d', 5, &columns - 2, 5, &columns - 2, 1, 1], - \ ['e', 5, &columns - 3, 5, &columns - 3, 1, 1], - \ - \ ['aa', 5, &columns, 5, &columns - 2, 2, 1], - \ ['bb', 5, &columns + 1, 5, &columns - 2, 2, 1], - \ ['cc', 5, &columns - 1, 5, &columns - 2, 2, 1], - \ ['dd', 5, &columns - 2, 5, &columns - 2, 2, 1], - \ ['ee', 5, &columns - 3, 5, &columns - 3, 2, 1], - \ - \ ['aaa', 5, &columns, 5, &columns - 2, 3, 1], - \ ['bbb', 5, &columns + 1, 5, &columns - 2, 3, 1], - \ ['ccc', 5, &columns - 1, 5, &columns - 2, 3, 1], - \ ['ddd', 5, &columns - 2, 5, &columns - 2, 3, 1], - \ ['eee', 5, &columns - 3, 5, &columns - 3, 3, 1], - \ ] + \ ['e', 5, &columns - 3, 5, &columns - 3, 1, 1]] " these test groups are dicts with: " - comment: something to identify the group of tests by @@ -1681,11 +1672,24 @@ func Test_popup_position_adjust() \ pos: 'botleft', \ }, \ tests: both_wrap_tests + [ - \ ['aaaa', 5, &columns, 4, &columns - 2, 3, 2], - \ ['bbbb', 5, &columns + 1, 4, &columns - 2, 3, 2], - \ ['cccc', 5, &columns - 1, 4, &columns - 2, 3, 2], + \ ['aa', 5, &columns, 4, &columns, 1, 2], + \ ['bb', 5, &columns + 1, 4, &columns, 1, 2], + \ ['cc', 5, &columns - 1, 5, &columns - 1, 2, 1], + \ ['dd', 5, &columns - 2, 5, &columns - 2, 2, 1], + \ ['ee', 5, &columns - 3, 5, &columns - 3, 2, 1], + \ + \ ['aaa', 5, &columns, 3, &columns, 1, 3], + \ ['bbb', 5, &columns + 1, 3, &columns, 1, 3], + \ ['ccc', 5, &columns - 1, 4, &columns - 1, 2, 2], + \ ['ddd', 5, &columns - 2, 5, &columns - 2, 3, 1], + \ ['eee', 5, &columns - 3, 5, &columns - 3, 3, 1], + \ + \ ['aaaa', 5, &columns, 2, &columns, 1, 4], + \ ['bbbb', 5, &columns + 1, 2, &columns, 1, 4], + \ ['cccc', 5, &columns - 1, 4, &columns - 1, 2, 2], \ ['dddd', 5, &columns - 2, 4, &columns - 2, 3, 2], \ ['eeee', 5, &columns - 3, 5, &columns - 3, 4, 1], + \ ['eeee', 5, &columns - 4, 5, &columns - 4, 4, 1], \ ], \ }, \ #{ @@ -1695,6 +1699,18 @@ func Test_popup_position_adjust() \ pos: 'botleft', \ }, \ tests: both_wrap_tests + [ + \ ['aa', 5, &columns, 5, &columns - 1, 2, 1], + \ ['bb', 5, &columns + 1, 5, &columns - 1, 2, 1], + \ ['cc', 5, &columns - 1, 5, &columns - 1, 2, 1], + \ ['dd', 5, &columns - 2, 5, &columns - 2, 2, 1], + \ ['ee', 5, &columns - 3, 5, &columns - 3, 2, 1], + \ + \ ['aaa', 5, &columns, 5, &columns - 2, 3, 1], + \ ['bbb', 5, &columns + 1, 5, &columns - 2, 3, 1], + \ ['ccc', 5, &columns - 1, 5, &columns - 2, 3, 1], + \ ['ddd', 5, &columns - 2, 5, &columns - 2, 3, 1], + \ ['eee', 5, &columns - 3, 5, &columns - 3, 3, 1], + \ \ ['aaaa', 5, &columns, 5, &columns - 3, 4, 1], \ ['bbbb', 5, &columns + 1, 5, &columns - 3, 4, 1], \ ['cccc', 5, &columns - 1, 5, &columns - 3, 4, 1], @@ -1710,9 +1726,21 @@ func Test_popup_position_adjust() \ pos: 'botleft', \ }, \ tests: both_wrap_tests + [ - \ ['aaaa', 5, &columns, 5, &columns - 2, 3, 1], - \ ['bbbb', 5, &columns + 1, 5, &columns - 2, 3, 1], - \ ['cccc', 5, &columns - 1, 5, &columns - 2, 3, 1], + \ ['aa', 5, &columns, 5, &columns, 1, 1], + \ ['bb', 5, &columns + 1, 5, &columns, 1, 1], + \ ['cc', 5, &columns - 1, 5, &columns - 1, 2, 1], + \ ['dd', 5, &columns - 2, 5, &columns - 2, 2, 1], + \ ['ee', 5, &columns - 3, 5, &columns - 3, 2, 1], + \ + \ ['aaa', 5, &columns, 5, &columns, 1, 1], + \ ['bbb', 5, &columns + 1, 5, &columns, 1, 1], + \ ['ccc', 5, &columns - 1, 5, &columns - 1, 2, 1], + \ ['ddd', 5, &columns - 2, 5, &columns - 2, 3, 1], + \ ['eee', 5, &columns - 3, 5, &columns - 3, 3, 1], + \ + \ ['aaaa', 5, &columns, 5, &columns, 1, 1], + \ ['bbbb', 5, &columns + 1, 5, &columns, 1, 1], + \ ['cccc', 5, &columns - 1, 5, &columns - 1, 2, 1], \ ['dddd', 5, &columns - 2, 5, &columns - 2, 3, 1], \ ['eeee', 5, &columns - 3, 5, &columns - 3, 4, 1], \ ], diff --git a/src/version.c b/src/version.c index d007585eac..f51df26c4b 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 96, /**/ 95, /**/ From ce6db0273f2c4359f48d75103a42991aa481f14e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 7 Jan 2020 20:11:42 +0100 Subject: [PATCH 22/42] patch 8.2.0097: crash with autocommand and spellfile Problem: Crash with autocommand and spellfile. (Tim Pope) Solution: Do not pop exestack when not pushed. (closes #5450) --- src/spellfile.c | 5 ++++- src/testdir/test_autocmd.vim | 22 ++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/spellfile.c b/src/spellfile.c index 6cad202fd3..fa450f33dd 100644 --- a/src/spellfile.c +++ b/src/spellfile.c @@ -352,6 +352,7 @@ spell_load_file( slang_T *lp = NULL; int c = 0; int res; + int did_estack_push = FALSE; fd = mch_fopen((char *)fname, "r"); if (fd == NULL) @@ -392,6 +393,7 @@ spell_load_file( // Set sourcing_name, so that error messages mention the file name. estack_push(ETYPE_SPELL, fname, 0); + did_estack_push = TRUE; /* *
: @@ -578,7 +580,8 @@ spell_load_file( endOK: if (fd != NULL) fclose(fd); - estack_pop(); + if (did_estack_push) + estack_pop(); return lp; } diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index ab02402398..23deec6c30 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -2335,3 +2335,25 @@ func Test_BufWrite_lockmarks() call delete('Xtest') call delete('Xtest2') endfunc + +func Test_FileType_spell() + if !isdirectory('/tmp') + throw "Skipped: requires /tmp directory" + endif + + " this was crashing with an invalid free() + setglobal spellfile=/tmp/en.utf-8.add + augroup crash + autocmd! + autocmd BufNewFile,BufReadPost crashfile setf somefiletype + autocmd BufNewFile,BufReadPost crashfile set ft=anotherfiletype + autocmd FileType anotherfiletype setlocal spell + augroup END + func! NoCrash() abort + edit /tmp/crashfile + endfunc + call NoCrash() + + au! crash + setglobal spellfile= +endfunc diff --git a/src/version.c b/src/version.c index f51df26c4b..b476e25a4c 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 97, /**/ 96, /**/ From e31ee86859528a7ffe00405645547d494e522fa8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 7 Jan 2020 20:59:34 +0100 Subject: [PATCH 23/42] patch 8.2.0098: exe stack length can be wrong without being detected Problem: Exe stack length can be wrong without being detected. Solution: Add a check when ABORT_ON_INTERNAL_ERROR is defined. --- src/autocmd.c | 3 +++ src/buffer.c | 3 +++ src/ex_docmd.c | 3 +++ src/macros.h | 12 ++++++++++++ src/main.c | 9 +++++++++ src/map.c | 3 +++ src/scriptfile.c | 3 +++ src/spellfile.c | 5 +++++ src/userfunc.c | 3 +++ src/version.c | 2 ++ 10 files changed, 46 insertions(+) diff --git a/src/autocmd.c b/src/autocmd.c index 983a155c60..13aa065ec8 100644 --- a/src/autocmd.c +++ b/src/autocmd.c @@ -1827,6 +1827,7 @@ apply_autocmds_group( int did_save_redobuff = FALSE; save_redo_T save_redo; int save_KeyTyped = KeyTyped; + ESTACK_CHECK_DECLARATION /* * Quickly return if there are no autocommands for this event or @@ -2021,6 +2022,7 @@ apply_autocmds_group( // name and lnum are filled in later estack_push(ETYPE_AUCMD, NULL, 0); + ESTACK_CHECK_SETUP #ifdef FEAT_EVAL save_current_sctx = current_sctx; @@ -2124,6 +2126,7 @@ apply_autocmds_group( filechangeshell_busy = FALSE; autocmd_nested = save_autocmd_nested; vim_free(SOURCING_NAME); + ESTACK_CHECK_NOW estack_pop(); vim_free(autocmd_fname); autocmd_fname = save_autocmd_fname; diff --git a/src/buffer.c b/src/buffer.c index 0a68d484e5..f56ff0b625 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -5287,6 +5287,7 @@ chk_modeline( #ifdef FEAT_EVAL sctx_T save_current_sctx; #endif + ESTACK_CHECK_DECLARATION prev = -1; for (s = ml_get(lnum); *s != NUL; ++s) @@ -5330,6 +5331,7 @@ chk_modeline( // prepare for emsg() estack_push(ETYPE_MODELINE, (char_u *)"modelines", lnum); + ESTACK_CHECK_SETUP end = FALSE; while (end == FALSE) @@ -5390,6 +5392,7 @@ chk_modeline( s = e + 1; // advance to next part } + ESTACK_CHECK_NOW estack_pop(); vim_free(linecopy); } diff --git a/src/ex_docmd.c b/src/ex_docmd.c index de8fb49617..e11ad08d43 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -645,6 +645,7 @@ do_cmdline( # define cmd_cookie cookie #endif static int call_depth = 0; // recursiveness + ESTACK_CHECK_DECLARATION #ifdef FEAT_EVAL // For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory @@ -1260,6 +1261,7 @@ do_cmdline( estack_push(ETYPE_EXCEPT, current_exception->throw_name, current_exception->throw_lnum); + ESTACK_CHECK_SETUP current_exception->throw_name = NULL; discard_current_exception(); // uses IObuff if 'verbose' @@ -1284,6 +1286,7 @@ do_cmdline( vim_free(p); } vim_free(SOURCING_NAME); + ESTACK_CHECK_NOW estack_pop(); } diff --git a/src/macros.h b/src/macros.h index ca7e4b5d0b..455705ca4f 100644 --- a/src/macros.h +++ b/src/macros.h @@ -344,3 +344,15 @@ #else # define ERROR_IF_POPUP_WINDOW 0 #endif + + +#ifdef ABORT_ON_INTERNAL_ERROR +# define ESTACK_CHECK_DECLARATION int estack_len_before; +# define ESTACK_CHECK_SETUP estack_len_before = exestack.ga_len; +# define ESTACK_CHECK_NOW if (estack_len_before != exestack.ga_len) \ + siemsg("Exestack length expected: %d, actual: %d", estack_len_before, exestack.ga_len); +#else +# define ESTACK_CHECK_DECLARATION +# define ESTACK_CHECK_SETUP +# define ESTACK_CHECK_NOW +#endif diff --git a/src/main.c b/src/main.c index 51b8970b9b..117c2072e6 100644 --- a/src/main.c +++ b/src/main.c @@ -3086,16 +3086,19 @@ exe_pre_commands(mparm_T *parmp) char_u **cmds = parmp->pre_commands; int cnt = parmp->n_pre_commands; int i; + ESTACK_CHECK_DECLARATION if (cnt > 0) { curwin->w_cursor.lnum = 0; // just in case.. estack_push(ETYPE_ARGS, (char_u *)_("pre-vimrc command line"), 0); + ESTACK_CHECK_SETUP # ifdef FEAT_EVAL current_sctx.sc_sid = SID_CMDARG; # endif for (i = 0; i < cnt; ++i) do_cmdline_cmd(cmds[i]); + ESTACK_CHECK_NOW estack_pop(); # ifdef FEAT_EVAL current_sctx.sc_sid = 0; @@ -3111,6 +3114,7 @@ exe_pre_commands(mparm_T *parmp) exe_commands(mparm_T *parmp) { int i; + ESTACK_CHECK_DECLARATION /* * We start commands on line 0, make "vim +/pat file" match a @@ -3121,6 +3125,7 @@ exe_commands(mparm_T *parmp) if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1) curwin->w_cursor.lnum = 0; estack_push(ETYPE_ARGS, (char_u *)"command line", 0); + ESTACK_CHECK_SETUP #ifdef FEAT_EVAL current_sctx.sc_sid = SID_CARG; current_sctx.sc_seq = 0; @@ -3131,6 +3136,7 @@ exe_commands(mparm_T *parmp) if (parmp->cmds_tofree[i]) vim_free(parmp->commands[i]); } + ESTACK_CHECK_NOW estack_pop(); #ifdef FEAT_EVAL current_sctx.sc_sid = 0; @@ -3340,12 +3346,14 @@ process_env( #ifdef FEAT_EVAL sctx_T save_current_sctx; #endif + ESTACK_CHECK_DECLARATION if ((initstr = mch_getenv(env)) != NULL && *initstr != NUL) { if (is_viminit) vimrc_found(NULL, NULL); estack_push(ETYPE_ENV, env, 0); + ESTACK_CHECK_SETUP #ifdef FEAT_EVAL save_current_sctx = current_sctx; current_sctx.sc_sid = SID_ENV; @@ -3355,6 +3363,7 @@ process_env( #endif do_cmdline_cmd(initstr); + ESTACK_CHECK_NOW estack_pop(); #ifdef FEAT_EVAL current_sctx = save_current_sctx; diff --git a/src/map.c b/src/map.c index 451190d445..31c288201d 100644 --- a/src/map.c +++ b/src/map.c @@ -1918,10 +1918,12 @@ check_map_keycodes(void) int abbr; int hash; buf_T *bp; + ESTACK_CHECK_DECLARATION validate_maphash(); // avoids giving error messages estack_push(ETYPE_INTERNAL, (char_u *)"mappings", 0); + ESTACK_CHECK_SETUP // Do this once for each buffer, and then once for global // mappings/abbreviations with bp == NULL @@ -1978,6 +1980,7 @@ check_map_keycodes(void) if (bp == NULL) break; } + ESTACK_CHECK_NOW estack_pop(); } diff --git a/src/scriptfile.c b/src/scriptfile.c index 38516c360a..a1755416b4 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1099,6 +1099,7 @@ do_source( proftime_T wait_start; #endif int trigger_source_post = FALSE; + ESTACK_CHECK_DECLARATION p = expand_env_save(fname); if (p == NULL) @@ -1216,6 +1217,7 @@ do_source( // Keep the sourcing name/lnum, for recursive calls. estack_push(ETYPE_SCRIPT, fname_exp, 0); + ESTACK_CHECK_SETUP #ifdef STARTUPTIME if (time_fd != NULL) @@ -1355,6 +1357,7 @@ do_source( if (got_int) emsg(_(e_interr)); + ESTACK_CHECK_NOW estack_pop(); if (p_verbose > 1) { diff --git a/src/spellfile.c b/src/spellfile.c index fa450f33dd..c3e53b330b 100644 --- a/src/spellfile.c +++ b/src/spellfile.c @@ -353,6 +353,7 @@ spell_load_file( int c = 0; int res; int did_estack_push = FALSE; + ESTACK_CHECK_DECLARATION fd = mch_fopen((char *)fname, "r"); if (fd == NULL) @@ -393,6 +394,7 @@ spell_load_file( // Set sourcing_name, so that error messages mention the file name. estack_push(ETYPE_SPELL, fname, 0); + ESTACK_CHECK_SETUP did_estack_push = TRUE; /* @@ -581,7 +583,10 @@ spell_load_file( if (fd != NULL) fclose(fd); if (did_estack_push) + { + ESTACK_CHECK_NOW estack_pop(); + } return lp; } diff --git a/src/userfunc.c b/src/userfunc.c index 95862fe875..29e0fac050 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -793,6 +793,7 @@ call_user_func( proftime_T call_start; int started_profiling = FALSE; #endif + ESTACK_CHECK_DECLARATION // If depth of calling is getting too high, don't execute the function if (depth >= p_mfd) @@ -969,6 +970,7 @@ call_user_func( } estack_push_ufunc(ETYPE_UFUNC, fp, 1); + ESTACK_CHECK_SETUP if (p_verbose >= 12) { ++no_wait_return; @@ -1115,6 +1117,7 @@ call_user_func( --no_wait_return; } + ESTACK_CHECK_NOW estack_pop(); current_sctx = save_current_sctx; #ifdef FEAT_PROFILE diff --git a/src/version.c b/src/version.c index b476e25a4c..c466c29b24 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 98, /**/ 97, /**/ From 8b7aa2f9b238df916c161cdacda032c25d72a0ae Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 7 Jan 2020 21:05:49 +0100 Subject: [PATCH 24/42] patch 8.2.0099: use of NULL pointer when out of memory Problem: Use of NULL pointer when out of memory. Solution: Check for NULL pointer. (Dominique Pelle, closes #5449) --- src/cmdexpand.c | 12 +++++++++--- src/version.c | 2 ++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/cmdexpand.c b/src/cmdexpand.c index 210b5f9819..b5da922fd1 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -2327,7 +2327,7 @@ expand_shellcmd( char_u *path = NULL; int mustfree = FALSE; garray_T ga; - char_u *buf = alloc(MAXPATHL); + char_u *buf; size_t l; char_u *s, *e; int flags = flagsarg; @@ -2337,12 +2337,18 @@ expand_shellcmd( hashitem_T *hi; hash_T hash; + buf = alloc(MAXPATHL); if (buf == NULL) return FAIL; - // for ":set path=" and ":set tags=" halve backslashes for escaped - // space + // for ":set path=" and ":set tags=" halve backslashes for escaped space pat = vim_strsave(filepat); + if (pat == NULL) + { + vim_free(buf); + return FAIL; + } + for (i = 0; pat[i]; ++i) if (pat[i] == '\\' && pat[i + 1] == ' ') STRMOVE(pat + i, pat + i + 1); diff --git a/src/version.c b/src/version.c index c466c29b24..8322eb31de 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 99, /**/ 98, /**/ From 41a4141ecb36cd871c6e87f6fbc12fa81653b6be Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 7 Jan 2020 21:32:19 +0100 Subject: [PATCH 25/42] patch 8.2.0100: macros for Ruby are too complicated Problem: Macros for Ruby are too complicated. Solution: Do not use DYNAMIC_RUBY_VER, use RUBY_VERSION. (Ken Takata, closes #5452) --- src/Make_cyg_ming.mak | 3 - src/Make_mvc.mak | 5 +- src/auto/configure | 2 +- src/configure.ac | 2 +- src/if_ruby.c | 164 +++++++++++++++++++++--------------------- src/version.c | 2 + 6 files changed, 87 insertions(+), 91 deletions(-) diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index 3c878cbfb6..f9c795bfef 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -569,11 +569,8 @@ ifdef RUBY CFLAGS += -DFEAT_RUBY $(RUBYINC) ifeq (yes, $(DYNAMIC_RUBY)) CFLAGS += -DDYNAMIC_RUBY -DDYNAMIC_RUBY_DLL=\"$(RUBY_INSTALL_NAME).dll\" -CFLAGS += -DDYNAMIC_RUBY_VER=$(RUBY_VER) endif - ifeq (no, $(DYNAMIC_RUBY)) CFLAGS += -DRUBY_VERSION=$(RUBY_VER) - endif ifneq ($(findstring w64-mingw32,$(CC)),) # A workaround for MinGW-w64 CFLAGS += -DHAVE_STRUCT_TIMESPEC -DHAVE_STRUCT_TIMEZONE diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index 8694f7496a..eb71296146 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -1193,10 +1193,11 @@ RUBY_LIB = $(RUBY)\lib\$(RUBY_INSTALL_NAME).lib # Do we want to load Ruby dynamically? ! if "$(DYNAMIC_RUBY)" == "yes" ! message Ruby DLL will be loaded dynamically -CFLAGS = $(CFLAGS) -DDYNAMIC_RUBY -DDYNAMIC_RUBY_VER=$(RUBY_VER) \ - -DDYNAMIC_RUBY_DLL=\"$(RUBY_INSTALL_NAME).dll\" +CFLAGS = $(CFLAGS) -DDYNAMIC_RUBY \ + -DDYNAMIC_RUBY_DLL=\"$(RUBY_INSTALL_NAME).dll\" ! undef RUBY_LIB ! endif +CFLAGS = $(CFLAGS) -DRUBY_VERSION=$(RUBY_VER) !endif # RUBY # diff --git a/src/auto/configure b/src/auto/configure index 993049573a..1b5094e972 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -7622,7 +7622,7 @@ $as_echo "$rubyhdrdir" >&6; } fi $as_echo "#define DYNAMIC_RUBY 1" >>confdefs.h - RUBY_CFLAGS="-DDYNAMIC_RUBY_DLL=\\\"$libruby_soname\\\" -DDYNAMIC_RUBY_VER=$rubyversion $RUBY_CFLAGS" + RUBY_CFLAGS="-DDYNAMIC_RUBY_DLL=\\\"$libruby_soname\\\" $RUBY_CFLAGS" RUBY_LIBS= fi else diff --git a/src/configure.ac b/src/configure.ac index d440a465ca..a098da82ec 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -1966,7 +1966,7 @@ if test "$enable_rubyinterp" = "yes" -o "$enable_rubyinterp" = "dynamic"; then libruby_soname=`$vi_cv_path_ruby -r rbconfig -e "puts $ruby_rbconfig::CONFIG[['LIBRUBY_SO']]"` fi AC_DEFINE(DYNAMIC_RUBY) - RUBY_CFLAGS="-DDYNAMIC_RUBY_DLL=\\\"$libruby_soname\\\" -DDYNAMIC_RUBY_VER=$rubyversion $RUBY_CFLAGS" + RUBY_CFLAGS="-DDYNAMIC_RUBY_DLL=\\\"$libruby_soname\\\" $RUBY_CFLAGS" RUBY_LIBS= fi else diff --git a/src/if_ruby.c b/src/if_ruby.c index 00783c8d71..68d55821fc 100644 --- a/src/if_ruby.c +++ b/src/if_ruby.c @@ -20,7 +20,7 @@ #include #ifdef _WIN32 -# if !defined(DYNAMIC_RUBY_VER) || (DYNAMIC_RUBY_VER < 18) +# if !defined(DYNAMIC_RUBY) || (RUBY_VERSION < 18) # define NT # endif # ifndef DYNAMIC_RUBY @@ -32,7 +32,7 @@ # define RUBYEXTERN extern #endif -#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 24 +#if defined(DYNAMIC_RUBY) && RUBY_VERSION >= 24 # define USE_RUBY_INTEGER #endif @@ -47,14 +47,14 @@ # if defined(USE_RUBY_INTEGER) # define rb_cInteger (*dll_rb_cInteger) # endif -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20 +# if RUBY_VERSION >= 20 # define rb_cFloat (*dll_rb_cFloat) # endif # define rb_cNilClass (*dll_rb_cNilClass) # define rb_cString (*dll_rb_cString) # define rb_cSymbol (*dll_rb_cSymbol) # define rb_cTrueClass (*dll_rb_cTrueClass) -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +# if RUBY_VERSION >= 18 /* * On ver 1.8, all Ruby functions are exported with "__declspec(dllimport)" * in ruby.h. But it causes trouble for these variables, because it is @@ -71,29 +71,14 @@ # undef _WIN32_WINNT #endif -#if (defined(RUBY_VERSION) && RUBY_VERSION >= 19) \ - || (defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19) -# define RUBY19_OR_LATER 1 -#endif - -#if (defined(RUBY_VERSION) && RUBY_VERSION >= 20) \ - || (defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20) -# define RUBY20_OR_LATER 1 -#endif - -#if (defined(RUBY_VERSION) && RUBY_VERSION >= 21) \ - || (defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 21) -# define RUBY21_OR_LATER 1 -#endif - -#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19 +#if defined(DYNAMIC_RUBY) && RUBY_VERSION >= 19 // Ruby 1.9 defines a number of static functions which use rb_num2long and // rb_int2big # define rb_num2long rb_num2long_stub # define rb_int2big rb_int2big_stub #endif -#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19 \ +#if defined(DYNAMIC_RUBY) && RUBY_VERSION >= 19 \ && VIM_SIZEOF_INT < VIM_SIZEOF_LONG // Ruby 1.9 defines a number of static functions which use rb_fix2int and // rb_num2int if VIM_SIZEOF_INT < VIM_SIZEOF_LONG (64bit) @@ -101,24 +86,24 @@ # define rb_num2int rb_num2int_stub #endif -#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21 +#if defined(DYNAMIC_RUBY) && RUBY_VERSION == 21 // Ruby 2.1 adds new GC called RGenGC and RARRAY_PTR uses // rb_gc_writebarrier_unprotect_promoted if USE_RGENGC # define rb_gc_writebarrier_unprotect_promoted rb_gc_writebarrier_unprotect_promoted_stub #endif -#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22 +#if defined(DYNAMIC_RUBY) && RUBY_VERSION >= 22 # define rb_gc_writebarrier_unprotect rb_gc_writebarrier_unprotect_stub #endif -#if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 26 +#if defined(DYNAMIC_RUBY) && RUBY_VERSION >= 26 # define rb_ary_detransient rb_ary_detransient_stub #endif #include -#ifdef RUBY19_OR_LATER +#if RUBY_VERSION >= 19 # include #endif -#ifndef RUBY19_OR_LATER +#if RUBY_VERSION <= 18 # include // for ST_STOP and ST_CONTINUE #endif @@ -139,7 +124,7 @@ * The old Data_XXX macro family was deprecated on Ruby 2.2. * Use TypedData_XXX if available. */ -#if defined(TypedData_Wrap_Struct) && defined(RUBY20_OR_LATER) +#if defined(TypedData_Wrap_Struct) && (RUBY_VERSION >= 20) # define USE_TYPEDDATA 1 #endif @@ -210,7 +195,7 @@ static void ruby_io_init(void); static void ruby_vim_init(void); static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv); -#if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK) +#if (RUBY_VERSION >= 19) || defined(RUBY_INIT_STACK) # if defined(__ia64) && !defined(ruby_init_stack) # define ruby_init_stack(addr) ruby_init_stack((addr), rb_ia64_bsp()) # endif @@ -233,7 +218,7 @@ static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv); # endif # define rb_class_path dll_rb_class_path # ifdef USE_TYPEDDATA -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 23 +# if RUBY_VERSION >= 23 # define rb_data_typed_object_wrap dll_rb_data_typed_object_wrap # else # define rb_data_typed_object_alloc dll_rb_data_typed_object_alloc @@ -256,7 +241,7 @@ static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv); # define rb_eRuntimeError (*dll_rb_eRuntimeError) # define rb_eStandardError (*dll_rb_eStandardError) # define rb_eval_string_protect dll_rb_eval_string_protect -# ifdef RUBY21_OR_LATER +# if RUBY_VERSION >= 21 # define rb_funcallv dll_rb_funcallv # else # define rb_funcall2 dll_rb_funcall2 @@ -274,7 +259,7 @@ static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv); # define rb_intern dll_rb_intern # if VIM_SIZEOF_INT < VIM_SIZEOF_LONG // 64 bits only -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER <= 18 +# if RUBY_VERSION <= 18 # define rb_fix2int dll_rb_fix2int # define rb_num2int dll_rb_num2int # endif @@ -285,10 +270,10 @@ static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv); # define rb_lastline_set dll_rb_lastline_set # define rb_protect dll_rb_protect # define rb_load dll_rb_load -# ifndef RUBY19_OR_LATER +# if RUBY_VERSION <= 18 # define rb_num2long dll_rb_num2long # endif -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER <= 19 +# if RUBY_VERSION <= 19 # define rb_num2ulong dll_rb_num2ulong # endif # define rb_obj_alloc dll_rb_obj_alloc @@ -309,7 +294,7 @@ static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv); # else # define rb_str_new2 dll_rb_str_new2 # endif -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +# if RUBY_VERSION >= 18 # define rb_string_value dll_rb_string_value # define rb_string_value_ptr dll_rb_string_value_ptr # define rb_float_new dll_rb_float_new @@ -320,7 +305,7 @@ static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv); # endif # define rb_ary_new4 dll_rb_ary_new4 # define rb_ary_push dll_rb_ary_push -# if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK) +# if (RUBY_VERSION >= 19) || defined(RUBY_INIT_STACK) # ifdef __ia64 # define rb_ia64_bsp dll_rb_ia64_bsp # undef ruby_init_stack @@ -332,7 +317,7 @@ static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv); # else # define rb_str2cstr dll_rb_str2cstr # endif -# ifdef RUBY19_OR_LATER +# if RUBY_VERSION >= 19 # define rb_errinfo dll_rb_errinfo # else # define ruby_errinfo (*dll_ruby_errinfo) @@ -340,17 +325,17 @@ static int ruby_convert_to_vim_value(VALUE val, typval_T *rettv); # define ruby_init dll_ruby_init # define ruby_init_loadpath dll_ruby_init_loadpath # ifdef MSWIN -# ifdef RUBY19_OR_LATER +# if RUBY_VERSION >= 19 # define ruby_sysinit dll_ruby_sysinit # else # define NtInitialize dll_NtInitialize # endif -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +# if RUBY_VERSION >= 18 # define rb_w32_snprintf dll_rb_w32_snprintf # endif # endif -# ifdef RUBY19_OR_LATER +# if RUBY_VERSION >= 19 # define ruby_script dll_ruby_script # define rb_enc_find_index dll_rb_enc_find_index # define rb_enc_find dll_rb_enc_find @@ -370,7 +355,7 @@ VALUE *dll_rb_cFixnum; # if defined(USE_RUBY_INTEGER) VALUE *dll_rb_cInteger; # endif -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20 +# if RUBY_VERSION >= 20 VALUE *dll_rb_cFloat; # endif VALUE *dll_rb_cNilClass; @@ -385,7 +370,7 @@ static void *(*dll_rb_check_typeddata) (VALUE,const rb_data_type_t *); # endif static VALUE (*dll_rb_class_path) (VALUE); # ifdef USE_TYPEDDATA -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 23 +# if RUBY_VERSION >= 23 static VALUE (*dll_rb_data_typed_object_wrap) (VALUE, void*, const rb_data_type_t *); # else static VALUE (*dll_rb_data_typed_object_alloc) (VALUE, void*, const rb_data_type_t *); @@ -408,7 +393,7 @@ static VALUE *dll_rb_eIndexError; static VALUE *dll_rb_eRuntimeError; static VALUE *dll_rb_eStandardError; static VALUE (*dll_rb_eval_string_protect) (const char*, int*); -# ifdef RUBY21_OR_LATER +# if RUBY_VERSION >= 21 static VALUE (*dll_rb_funcallv) (VALUE, ID, int, const VALUE*); # else static VALUE (*dll_rb_funcall2) (VALUE, ID, int, const VALUE*); @@ -436,7 +421,7 @@ static VALUE (*dll_rb_obj_alloc) (VALUE); static VALUE (*dll_rb_obj_as_string) (VALUE); static VALUE (*dll_rb_obj_id) (VALUE); static void (*dll_rb_raise) (VALUE, const char*, ...); -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +# if RUBY_VERSION >= 18 static VALUE (*dll_rb_string_value) (volatile VALUE*); # else static char *(*dll_rb_str2cstr) (VALUE,int*); @@ -450,7 +435,7 @@ static VALUE (*dll_rb_str_new_cstr) (const char*); # else static VALUE (*dll_rb_str_new2) (const char*); # endif -# ifdef RUBY19_OR_LATER +# if RUBY_VERSION >= 19 static VALUE (*dll_rb_errinfo) (void); # else static VALUE *dll_ruby_errinfo; @@ -458,25 +443,25 @@ static VALUE *dll_ruby_errinfo; static void (*dll_ruby_init) (void); static void (*dll_ruby_init_loadpath) (void); # ifdef MSWIN -# ifdef RUBY19_OR_LATER +# if RUBY_VERSION >= 19 static void (*dll_ruby_sysinit) (int*, char***); # else static void (*dll_NtInitialize) (int*, char***); # endif -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +# if RUBY_VERSION >= 18 static int (*dll_rb_w32_snprintf)(char*, size_t, const char*, ...); # endif # endif -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +# if RUBY_VERSION >= 18 static char * (*dll_rb_string_value_ptr) (volatile VALUE*); static VALUE (*dll_rb_float_new) (double); static VALUE (*dll_rb_ary_new) (void); static VALUE (*dll_rb_ary_new4) (long n, const VALUE *elts); static VALUE (*dll_rb_ary_push) (VALUE, VALUE); -# if DYNAMIC_RUBY_VER >= 26 +# if RUBY_VERSION >= 26 static void (*dll_rb_ary_detransient) (VALUE); # endif -# if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK) +# if (RUBY_VERSION >= 19) || defined(RUBY_INIT_STACK) # ifdef __ia64 static void * (*dll_rb_ia64_bsp) (void); static void (*dll_ruby_init_stack)(VALUE*, void*); @@ -485,11 +470,11 @@ static void (*dll_ruby_init_stack)(VALUE*); # endif # endif # endif -# ifdef RUBY19_OR_LATER +# if RUBY_VERSION >= 19 static VALUE (*dll_rb_int2big)(SIGNED_VALUE); # endif -# ifdef RUBY19_OR_LATER +# if RUBY_VERSION >= 19 static void (*dll_ruby_script) (const char*); static int (*dll_rb_enc_find_index) (const char*); static rb_encoding* (*dll_rb_enc_find) (const char*); @@ -500,15 +485,15 @@ static void* (*ruby_options)(int, char**); # endif # if defined(USE_RGENGC) && USE_RGENGC -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21 +# if RUBY_VERSION == 21 static void (*dll_rb_gc_writebarrier_unprotect_promoted)(VALUE); # else static void (*dll_rb_gc_writebarrier_unprotect)(VALUE obj); # endif # endif -# if defined(RUBY19_OR_LATER) && !defined(PROTO) -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22 +# if (RUBY_VERSION >= 19) && !defined(PROTO) +# if RUBY_VERSION >= 22 long rb_num2long_stub(VALUE x) # else @@ -518,7 +503,7 @@ rb_num2long_stub(VALUE x) { return dll_rb_num2long(x); } -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 26 +# if RUBY_VERSION >= 26 VALUE rb_int2big_stub(intptr_t x) # else @@ -528,8 +513,7 @@ rb_int2big_stub(SIGNED_VALUE x) { return dll_rb_int2big(x); } -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 19 \ - && VIM_SIZEOF_INT < VIM_SIZEOF_LONG +# if (RUBY_VERSION >= 19) && (VIM_SIZEOF_INT < VIM_SIZEOF_LONG) long rb_fix2int_stub(VALUE x) { @@ -541,13 +525,13 @@ rb_num2int_stub(VALUE x) return dll_rb_num2int(x); } # endif -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20 +# if RUBY_VERSION >= 20 VALUE rb_float_new_in_heap(double d) { return dll_rb_float_new(d); } -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 22 +# if RUBY_VERSION >= 22 unsigned long rb_num2ulong(VALUE x) # else @@ -562,7 +546,7 @@ rb_num2ulong(VALUE x) // Do not generate a prototype here, VALUE isn't always defined. # if defined(USE_RGENGC) && USE_RGENGC && !defined(PROTO) -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21 +# if RUBY_VERSION == 21 void rb_gc_writebarrier_unprotect_promoted_stub(VALUE obj) { @@ -577,7 +561,7 @@ rb_gc_writebarrier_unprotect_stub(VALUE obj) # endif # endif -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 26 +# if RUBY_VERSION >= 26 void rb_ary_detransient_stub(VALUE x) { @@ -603,7 +587,7 @@ static struct # else {"rb_cFixnum", (RUBY_PROC*)&dll_rb_cFixnum}, # endif -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 20 +# if RUBY_VERSION >= 20 {"rb_cFloat", (RUBY_PROC*)&dll_rb_cFloat}, # endif {"rb_cNilClass", (RUBY_PROC*)&dll_rb_cNilClass}, @@ -618,7 +602,7 @@ static struct # endif {"rb_class_path", (RUBY_PROC*)&dll_rb_class_path}, # ifdef USE_TYPEDDATA -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 23 +# if RUBY_VERSION >= 23 {"rb_data_typed_object_wrap", (RUBY_PROC*)&dll_rb_data_typed_object_wrap}, # else {"rb_data_typed_object_alloc", (RUBY_PROC*)&dll_rb_data_typed_object_alloc}, @@ -641,7 +625,7 @@ static struct {"rb_eRuntimeError", (RUBY_PROC*)&dll_rb_eRuntimeError}, {"rb_eStandardError", (RUBY_PROC*)&dll_rb_eStandardError}, {"rb_eval_string_protect", (RUBY_PROC*)&dll_rb_eval_string_protect}, -# ifdef RUBY21_OR_LATER +# if RUBY_VERSION >= 21 {"rb_funcallv", (RUBY_PROC*)&dll_rb_funcallv}, # else {"rb_funcall2", (RUBY_PROC*)&dll_rb_funcall2}, @@ -669,7 +653,7 @@ static struct {"rb_obj_as_string", (RUBY_PROC*)&dll_rb_obj_as_string}, {"rb_obj_id", (RUBY_PROC*)&dll_rb_obj_id}, {"rb_raise", (RUBY_PROC*)&dll_rb_raise}, -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +# if RUBY_VERSION >= 18 {"rb_string_value", (RUBY_PROC*)&dll_rb_string_value}, # else {"rb_str2cstr", (RUBY_PROC*)&dll_rb_str2cstr}, @@ -682,7 +666,7 @@ static struct # else {"rb_str_new2", (RUBY_PROC*)&dll_rb_str_new2}, # endif -# ifdef RUBY19_OR_LATER +# if RUBY_VERSION >= 19 {"rb_errinfo", (RUBY_PROC*)&dll_rb_errinfo}, # else {"ruby_errinfo", (RUBY_PROC*)&dll_ruby_errinfo}, @@ -690,18 +674,18 @@ static struct {"ruby_init", (RUBY_PROC*)&dll_ruby_init}, {"ruby_init_loadpath", (RUBY_PROC*)&dll_ruby_init_loadpath}, # ifdef MSWIN -# ifdef RUBY19_OR_LATER +# if RUBY_VERSION >= 19 {"ruby_sysinit", (RUBY_PROC*)&dll_ruby_sysinit}, # else {"NtInitialize", (RUBY_PROC*)&dll_NtInitialize}, # endif -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +# if RUBY_VERSION >= 18 {"rb_w32_snprintf", (RUBY_PROC*)&dll_rb_w32_snprintf}, # endif # endif -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER >= 18 +# if RUBY_VERSION >= 18 {"rb_string_value_ptr", (RUBY_PROC*)&dll_rb_string_value_ptr}, -# if DYNAMIC_RUBY_VER <= 19 +# if RUBY_VERSION <= 19 {"rb_float_new", (RUBY_PROC*)&dll_rb_float_new}, # else {"rb_float_new_in_heap", (RUBY_PROC*)&dll_rb_float_new}, @@ -713,11 +697,11 @@ static struct {"rb_ary_new4", (RUBY_PROC*)&dll_rb_ary_new4}, # endif {"rb_ary_push", (RUBY_PROC*)&dll_rb_ary_push}, -# if DYNAMIC_RUBY_VER >= 26 +# if RUBY_VERSION >= 26 {"rb_ary_detransient", (RUBY_PROC*)&dll_rb_ary_detransient}, # endif # endif -# ifdef RUBY19_OR_LATER +# if RUBY_VERSION >= 19 {"rb_int2big", (RUBY_PROC*)&dll_rb_int2big}, {"ruby_script", (RUBY_PROC*)&dll_ruby_script}, {"rb_enc_find_index", (RUBY_PROC*)&dll_rb_enc_find_index}, @@ -727,14 +711,14 @@ static struct {"rb_require", (RUBY_PROC*)&dll_rb_require}, {"ruby_options", (RUBY_PROC*)&dll_ruby_options}, # endif -# if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK) +# if (RUBY_VERSION >= 19) || defined(RUBY_INIT_STACK) # ifdef __ia64 {"rb_ia64_bsp", (RUBY_PROC*)&dll_rb_ia64_bsp}, # endif {"ruby_init_stack", (RUBY_PROC*)&dll_ruby_init_stack}, # endif # if defined(USE_RGENGC) && USE_RGENGC -# if defined(DYNAMIC_RUBY_VER) && DYNAMIC_RUBY_VER == 21 +# if RUBY_VERSION == 21 {"rb_gc_writebarrier_unprotect_promoted", (RUBY_PROC*)&dll_rb_gc_writebarrier_unprotect_promoted}, # else {"rb_gc_writebarrier_unprotect", (RUBY_PROC*)&dll_rb_gc_writebarrier_unprotect}, @@ -837,7 +821,7 @@ ex_ruby(exarg_T *eap) static VALUE vim_str2rb_enc_str(const char *s) { -#ifdef RUBY19_OR_LATER +#if RUBY_VERSION >= 19 int isnum; long lval; char_u *sval; @@ -858,7 +842,7 @@ vim_str2rb_enc_str(const char *s) static VALUE eval_enc_string_protect(const char *str, int *state) { -#ifdef RUBY19_OR_LATER +#if RUBY_VERSION >= 19 int isnum; long lval; char_u *sval; @@ -982,19 +966,19 @@ ensure_ruby_initialized(void) int argc = 1; char *argv[] = {"gvim.exe"}; char **argvp = argv; -# ifdef RUBY19_OR_LATER +# if RUBY_VERSION >= 19 ruby_sysinit(&argc, &argvp); # else NtInitialize(&argc, &argvp); # endif #endif { -#if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK) +#if (RUBY_VERSION >= 19) || defined(RUBY_INIT_STACK) ruby_init_stack(ruby_stack_start); #endif ruby_init(); } -#ifdef RUBY19_OR_LATER +#if RUBY_VERSION >= 19 { int dummy_argc = 2; char *dummy_argv[] = {"vim-ruby", "-e_=0"}; @@ -1022,7 +1006,7 @@ ensure_ruby_initialized(void) static void error_print(int state) { -#if !defined(DYNAMIC_RUBY) && !defined(RUBY19_OR_LATER) +#if !defined(DYNAMIC_RUBY) && (RUBY_VERSION <= 18) RUBYEXTERN VALUE ruby_errinfo; #endif VALUE error; @@ -1062,7 +1046,7 @@ error_print(int state) break; case TAG_RAISE: case TAG_FATAL: -#ifdef RUBY19_OR_LATER +#if RUBY_VERSION >= 19 error = rb_errinfo(); #else error = ruby_errinfo; @@ -1087,7 +1071,7 @@ error_print(int state) } attr = syn_name2attr((char_u *)"Error"); -# ifdef RUBY21_OR_LATER +# if RUBY_VERSION >= 21 bt = rb_funcallv(error, rb_intern("backtrace"), 0, 0); for (i = 0; i < RARRAY_LEN(bt); i++) msg_attr(RSTRING_PTR(RARRAY_AREF(bt, i)), attr); @@ -1242,7 +1226,13 @@ static size_t buffer_dsize(const void *buf); static const rb_data_type_t buffer_type = { "vim_buffer", - {0, 0, buffer_dsize, {0, 0}}, + {0, 0, buffer_dsize, +# if RUBY_VERSION >= 27 + 0, 0 +# else + {0, 0} +# endif + }, 0, 0, # ifdef RUBY_TYPED_FREE_IMMEDIATELY 0, @@ -1516,7 +1506,13 @@ static size_t window_dsize(const void *buf); static const rb_data_type_t window_type = { "vim_window", - {0, 0, window_dsize, {0, 0}}, + {0, 0, window_dsize, +# if RUBY_VERSION >= 27 + 0, 0 +# else + {0, 0} +# endif + }, 0, 0, # ifdef RUBY_TYPED_FREE_IMMEDIATELY 0, diff --git a/src/version.c b/src/version.c index 8322eb31de..1c68c1a46b 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 100, /**/ 99, /**/ From 9db2afe46d3208775d1c3075bbee073a17f8fdc6 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 8 Jan 2020 18:56:20 +0100 Subject: [PATCH 26/42] patch 8.2.0101: crash when passing null object to ":echomsg" Problem: Crash when passing null object to ":echomsg". Solution: Check for NULL pointer. (Yasuhiro Matsumoto, closes #5460) --- src/eval.c | 7 +++++++ src/testdir/test_messages.vim | 10 ++++++++++ src/version.c | 2 ++ 3 files changed, 19 insertions(+) diff --git a/src/eval.c b/src/eval.c index 2a2d9d463e..6e88c5c218 100644 --- a/src/eval.c +++ b/src/eval.c @@ -5682,6 +5682,7 @@ tv_stringify(typval_T *varp, char_u *buf) { if (varp->v_type == VAR_LIST || varp->v_type == VAR_DICT + || varp->v_type == VAR_BLOB || varp->v_type == VAR_FUNC || varp->v_type == VAR_PARTIAL || varp->v_type == VAR_FLOAT) @@ -6057,6 +6058,12 @@ ex_execute(exarg_T *eap) p = tv_get_string_buf(&rettv, buf); else p = tv_stringify(&rettv, buf); + if (p == NULL) + { + clear_tv(&rettv); + ret = FAIL; + break; + } len = (int)STRLEN(p); if (ga_grow(&ga, len + 2) == FAIL) { diff --git a/src/testdir/test_messages.vim b/src/testdir/test_messages.vim index 6bb553c36a..3e7d63c7dd 100644 --- a/src/testdir/test_messages.vim +++ b/src/testdir/test_messages.vim @@ -268,3 +268,13 @@ func Test_message_more() call term_sendkeys(buf, ':q!') call StopVimInTerminal(buf) endfunc + +func Test_null() + echom test_null_list() + echom test_null_dict() + echom test_null_blob() + echom test_null_job() + echom test_null_string() + echom test_null_channel() + echom test_null_partial() +endfunc diff --git a/src/version.c b/src/version.c index 1c68c1a46b..ba690bcc52 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 101, /**/ 100, /**/ From da292b07afb7ea5ec9f4b43a7326551922e29f3a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 8 Jan 2020 19:27:40 +0100 Subject: [PATCH 27/42] patch 8.2.0102: messages test fails in small version Problem: Messages test fails in small version. Solution: Only use test_null_job() when available. --- src/testdir/test_messages.vim | 6 ++++-- src/version.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_messages.vim b/src/testdir/test_messages.vim index 3e7d63c7dd..62a191ec8d 100644 --- a/src/testdir/test_messages.vim +++ b/src/testdir/test_messages.vim @@ -273,8 +273,10 @@ func Test_null() echom test_null_list() echom test_null_dict() echom test_null_blob() - echom test_null_job() echom test_null_string() - echom test_null_channel() echom test_null_partial() + if has('job') + echom test_null_job() + echom test_null_channel() + endif endfunc diff --git a/src/version.c b/src/version.c index ba690bcc52..a02b198c5c 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 102, /**/ 101, /**/ From e2a8f0773e91685843c062b1e48259712d5f2213 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 8 Jan 2020 19:32:18 +0100 Subject: [PATCH 28/42] patch 8.2.0103: using null object with execute() has strange effects Problem: Using null object with execute() has strange effects. Solution: Give an error message ofr Job and Channel. --- src/eval.c | 2 +- src/evalfunc.c | 6 ++++++ src/globals.h | 1 + src/testdir/test_execute_func.vim | 15 ++++++++++++--- src/version.c | 2 ++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/eval.c b/src/eval.c index 6e88c5c218..e0f27a0986 100644 --- a/src/eval.c +++ b/src/eval.c @@ -5667,7 +5667,7 @@ tv_get_string_buf_chk(typval_T *varp, char_u *buf) #endif break; case VAR_UNKNOWN: - emsg(_("E908: using an invalid value as a String")); + emsg(_(e_inval_string)); break; } return NULL; diff --git a/src/evalfunc.c b/src/evalfunc.c index af43fb96ec..f192506d84 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2015,6 +2015,12 @@ execute_common(typval_T *argvars, typval_T *rettv, int arg_off) return; ++list->lv_refcount; } + else if (argvars[arg_off].v_type == VAR_JOB + || argvars[arg_off].v_type == VAR_CHANNEL) + { + emsg(_(e_inval_string)); + return; + } else { cmd = tv_get_string_chk(&argvars[arg_off]); diff --git a/src/globals.h b/src/globals.h index e1738693de..34430d3e0f 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1599,6 +1599,7 @@ EXTERN char e_listreq[] INIT(= N_("E714: List required")); EXTERN char e_listblobreq[] INIT(= N_("E897: List or Blob required")); EXTERN char e_listdictarg[] INIT(= N_("E712: Argument of %s must be a List or Dictionary")); EXTERN char e_listdictblobarg[] INIT(= N_("E896: Argument of %s must be a List, Dictionary or Blob")); +EXTERN char e_inval_string[] INIT(= N_("E908: using an invalid value as a String")); #endif #ifdef FEAT_QUICKFIX EXTERN char e_readerrf[] INIT(= N_("E47: Error while reading errorfile")); diff --git a/src/testdir/test_execute_func.vim b/src/testdir/test_execute_func.vim index 7934e60846..30dcb6202d 100644 --- a/src/testdir/test_execute_func.vim +++ b/src/testdir/test_execute_func.vim @@ -38,8 +38,6 @@ func Test_execute_string() call assert_equal("\nsomething", execute('echo "something"', 'silent!')) call assert_equal("", execute('burp', 'silent!')) call assert_fails('call execute("echo \"x\"", 3.4)', 'E806:') - - call assert_equal("", execute(test_null_string())) endfunc func Test_execute_list() @@ -50,7 +48,6 @@ func Test_execute_list() call assert_equal("\n0\n1\n2\n3", execute(l)) call assert_equal("", execute([])) - call assert_equal("", execute(test_null_list())) endfunc func Test_execute_does_not_change_col() @@ -132,3 +129,15 @@ func Test_win_execute_other_tab() tabclose unlet xyz endfunc + +func Test_execute_null() + call assert_equal("", execute(test_null_string())) + call assert_equal("", execute(test_null_list())) + call assert_fails('call execute(test_null_dict())', 'E731:') + call assert_fails('call execute(test_null_blob())', 'E976:') + call assert_fails('call execute(test_null_partial())','E729:') + if has('job') + call assert_fails('call execute(test_null_job())', 'E908:') + call assert_fails('call execute(test_null_channel())', 'E908:') + endif +endfunc diff --git a/src/version.c b/src/version.c index a02b198c5c..54104ebac2 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 103, /**/ 102, /**/ From b662591e505e8523634a1c8ddfb7fe44fae880c6 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 8 Jan 2020 20:09:01 +0100 Subject: [PATCH 29/42] patch 8.2.0104: using channel or job with ":execute" has strange effects Problem: Using channel or job with ":execute" has strange effects. Solution: Give an error message for Job and Channel. --- src/eval.c | 10 +++++++++- src/testdir/test_eval_stuff.vim | 12 ++++++++++++ src/version.c | 2 ++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/eval.c b/src/eval.c index e0f27a0986..f8ba4dffa0 100644 --- a/src/eval.c +++ b/src/eval.c @@ -6055,7 +6055,15 @@ ex_execute(exarg_T *eap) char_u buf[NUMBUFLEN]; if (eap->cmdidx == CMD_execute) - p = tv_get_string_buf(&rettv, buf); + { + if (rettv.v_type == VAR_CHANNEL || rettv.v_type == VAR_JOB) + { + emsg(_(e_inval_string)); + p = NULL; + } + else + p = tv_get_string_buf(&rettv, buf); + } else p = tv_stringify(&rettv, buf); if (p == NULL) diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim index ec566da04a..53627557a0 100644 --- a/src/testdir/test_eval_stuff.vim +++ b/src/testdir/test_eval_stuff.vim @@ -216,3 +216,15 @@ func Test_scriptversion_fail() call assert_fails('source Xversionscript', 'E999:') call delete('Xversionscript') endfunc + +func Test_excute_null() + call assert_fails('execute test_null_list()', 'E730:') + call assert_fails('execute test_null_dict()', 'E731:') + call assert_fails('execute test_null_blob()', 'E976:') + execute test_null_string() + call assert_fails('execute test_null_partial()', 'E729:') + if has('job') + call assert_fails('execute test_null_job()', 'E908:') + call assert_fails('execute test_null_channel()', 'E908:') + endif +endfunc diff --git a/src/version.c b/src/version.c index 54104ebac2..3362ab5b54 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 104, /**/ 103, /**/ From c838626fea42ed5924ee6084d87d1b37b2d7b0ff Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 8 Jan 2020 21:43:02 +0100 Subject: [PATCH 30/42] patch 8.2.0105: Vim license not easy to find on github Problem: Vim license not easy to find on github. Solution: Add a separate LICENCE file. (closes #5458) --- Filelist | 1 + LICENSE | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 81 insertions(+) create mode 100644 LICENSE diff --git a/Filelist b/Filelist index ca72742fd5..6ebb3f7c96 100644 --- a/Filelist +++ b/Filelist @@ -652,6 +652,7 @@ SRC_EXTRA = \ RT_ALL = \ README.txt \ README.md \ + LICENSE \ CONTRIBUTING.md \ runtime/bugreport.vim \ runtime/doc/*.awk \ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..ecfbe5534e --- /dev/null +++ b/LICENSE @@ -0,0 +1,78 @@ +VIM LICENSE + +I) There are no restrictions on distributing unmodified copies of Vim except + that they must include this license text. You can also distribute + unmodified parts of Vim, likewise unrestricted except that they must + include this license text. You are also allowed to include executables + that you made from the unmodified Vim sources, plus your own usage + examples and Vim scripts. + +II) It is allowed to distribute a modified (or extended) version of Vim, + including executables and/or source code, when the following four + conditions are met: + 1) This license text must be included unmodified. + 2) The modified Vim must be distributed in one of the following five ways: + a) If you make changes to Vim yourself, you must clearly describe in + the distribution how to contact you. When the maintainer asks you + (in any way) for a copy of the modified Vim you distributed, you + must make your changes, including source code, available to the + maintainer without fee. The maintainer reserves the right to + include your changes in the official version of Vim. What the + maintainer will do with your changes and under what license they + will be distributed is negotiable. If there has been no negotiation + then this license, or a later version, also applies to your changes. + The current maintainer is Bram Moolenaar . If this + changes it will be announced in appropriate places (most likely + vim.sf.net, www.vim.org and/or comp.editors). When it is completely + impossible to contact the maintainer, the obligation to send him + your changes ceases. Once the maintainer has confirmed that he has + received your changes they will not have to be sent again. + b) If you have received a modified Vim that was distributed as + mentioned under a) you are allowed to further distribute it + unmodified, as mentioned at I). If you make additional changes the + text under a) applies to those changes. + c) Provide all the changes, including source code, with every copy of + the modified Vim you distribute. This may be done in the form of a + context diff. You can choose what license to use for new code you + add. The changes and their license must not restrict others from + making their own changes to the official version of Vim. + d) When you have a modified Vim which includes changes as mentioned + under c), you can distribute it without the source code for the + changes if the following three conditions are met: + - The license that applies to the changes permits you to distribute + the changes to the Vim maintainer without fee or restriction, and + permits the Vim maintainer to include the changes in the official + version of Vim without fee or restriction. + - You keep the changes for at least three years after last + distributing the corresponding modified Vim. When the maintainer + or someone who you distributed the modified Vim to asks you (in + any way) for the changes within this period, you must make them + available to him. + - You clearly describe in the distribution how to contact you. This + contact information must remain valid for at least three years + after last distributing the corresponding modified Vim, or as long + as possible. + e) When the GNU General Public License (GPL) applies to the changes, + you can distribute the modified Vim under the GNU GPL version 2 or + any later version. + 3) A message must be added, at least in the output of the ":version" + command and in the intro screen, such that the user of the modified Vim + is able to see that it was modified. When distributing as mentioned + under 2)e) adding the message is only required for as far as this does + not conflict with the license used for the changes. + 4) The contact information as required under 2)a) and 2)d) must not be + removed or changed, except that the person himself can make + corrections. + +III) If you distribute a modified version of Vim, you are encouraged to use + the Vim license for your changes and make them available to the + maintainer, including the source code. The preferred way to do this is + by e-mail or by uploading the files to a server and e-mailing the URL. + If the number of changes is small (e.g., a modified Makefile) e-mailing a + context diff will do. The e-mail address to be used is + + +IV) It is not allowed to remove this license from the distribution of the Vim + sources, parts of it or from a modified version. You may use this + license for previous Vim releases instead of the license that they came + with, at your option. diff --git a/src/version.c b/src/version.c index 3362ab5b54..1f54a4ae76 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 105, /**/ 104, /**/ From b16ad968499aeb29b6ff9be6cc64fb41522a4a5e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 8 Jan 2020 22:06:14 +0100 Subject: [PATCH 31/42] patch 8.2.0106: printf formats are not exactly right Problem: Printf formats are not exactly right. Solution: Adjust signed/unsigned conversions. (Frazer Clews, closes #5456) --- runtime/tools/ccfilter.c | 28 ++++++++++++++-------------- src/libvterm/src/parser.c | 2 +- src/libvterm/src/pen.c | 2 +- src/ui.c | 6 +++--- src/version.c | 2 ++ 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/runtime/tools/ccfilter.c b/runtime/tools/ccfilter.c index 8539e2a3dc..43489f16c2 100644 --- a/runtime/tools/ccfilter.c +++ b/runtime/tools/ccfilter.c @@ -184,7 +184,7 @@ int main( int argc, char *argv[] ) case COMPILER_GCC: Severity = 'e'; #ifdef GOTO_FROM_WHERE_INCLUDED - rv = sscanf( Line, "In file included from %[^:]:%u:", + rv = sscanf( Line, "In file included from %[^:]:%lu:", FileName, &Row ); if ( rv == 2 ) { @@ -193,11 +193,11 @@ int main( int argc, char *argv[] ) else #endif { - if ((rv = sscanf( Line, "%[^:]:%u: warning: %[^\n]", + if ((rv = sscanf( Line, "%[^:]:%lu: warning: %[^\n]", FileName, &Row, Reason ))==3) { Severity = 'w'; } else { - rv = sscanf( Line, "%[^:]:%u: %[^\n]", + rv = sscanf( Line, "%[^:]:%lu: %[^\n]", FileName, &Row, Reason ); } ok = ( rv == 3 ); @@ -205,24 +205,24 @@ int main( int argc, char *argv[] ) Col = (dec_col ? 1 : 0 ); break; case COMPILER_AIX: - rv = sscanf( Line, "\"%[^\"]\", line %u.%u: %*s (%c) %[^\n]", + rv = sscanf( Line, "\"%[^\"]\", line %lu.%lu: %*s (%c) %[^\n]", FileName, &Row, &Col, &Severity, Reason ); ok = ( rv == 5 ); break; case COMPILER_HPUX: - rv = sscanf( Line, "cc: \"%[^\"]\", line %u: %c%*[^:]: %[^\n]", + rv = sscanf( Line, "cc: \"%[^\"]\", line %lu: %c%*[^:]: %[^\n]", FileName, &Row, &Severity, Reason ); ok = ( rv == 4 ); Col = (dec_col ? 1 : 0 ); break; case COMPILER_SOLARIS: - rv = sscanf( Line, "\"%[^\"]\", line %u: warning: %[^\n]", + rv = sscanf( Line, "\"%[^\"]\", line %lu: warning: %[^\n]", FileName, &Row, Reason ); Severity = 'w'; ok = ( rv == 3 ); if ( rv != 3 ) { - rv = sscanf( Line, "\"%[^\"]\", line %u: %[^\n]", + rv = sscanf( Line, "\"%[^\"]\", line %lu: %[^\n]", FileName, &Row, Reason ); Severity = 'e'; ok = ( rv == 3 ); @@ -230,18 +230,18 @@ int main( int argc, char *argv[] ) Col = (dec_col ? 1 : 0 ); break; case COMPILER_ATT: - rv = sscanf( Line, "%c \"%[^\"]\",L%u/C%u%*[^:]:%[^\n]", + rv = sscanf( Line, "%c \"%[^\"]\",L%lu/C%lu%*[^:]:%[^\n]", &Severity, FileName, &Row, &Col, Reason ); ok = ( rv == 5 ); if (rv != 5) - { rv = sscanf( Line, "%c \"%[^\"]\",L%u/C%u: %[^\n]", + { rv = sscanf( Line, "%c \"%[^\"]\",L%lu/C%lu: %[^\n]", &Severity, FileName, &Row, &Col, Reason ); ok = ( rv == 5 ); } if (rv != 5) - { rv = sscanf( Line, "%c \"%[^\"]\",L%u: %[^\n]", + { rv = sscanf( Line, "%c \"%[^\"]\",L%lu: %[^\n]", &Severity, FileName, &Row, Reason ); ok = ( rv == 4 ); Col = (dec_col ? 1 : 0 ); @@ -272,10 +272,10 @@ int main( int argc, char *argv[] ) } else { - rv = sscanf( p+2, "%[^:]: %u: %[^\n]", + rv = sscanf( p+2, "%[^:]: %lu: %[^\n]", FileName, &Row, Reason ); if (rv != 3) - rv = sscanf( p+2, "%[^,], line %u: %[^\n]", + rv = sscanf( p+2, "%[^,], line %lu: %[^\n]", FileName, &Row, Reason ); ok = ( rv == 3 ); } @@ -315,10 +315,10 @@ int main( int argc, char *argv[] ) { for (p=Reason; (*p) && (isspace(*p)); p++); if ( BasePath[CWDlen] == 0 ) - printf( "%s:%u:%u:%c:%s\n", FileName, Row, Col, Severity, p ); + printf( "%s:%lu:%lu:%c:%s\n", FileName, Row, Col, Severity, p ); else { - printf( "%s/%s:%u:%u:%c:%s\n", &BasePath[CWDlen+1], FileName, Row, Col, Severity, p ); + printf( "%s/%s:%lu:%lu:%c:%s\n", &BasePath[CWDlen+1], FileName, Row, Col, Severity, p ); } } if (!prefetch) diff --git a/src/libvterm/src/parser.c b/src/libvterm/src/parser.c index 7d6d2175df..8a06c427b0 100644 --- a/src/libvterm/src/parser.c +++ b/src/libvterm/src/parser.c @@ -65,7 +65,7 @@ static void append_strbuffer(VTerm *vt, const char *str, size_t len) { if(len > vt->parser.strbuffer_len - vt->parser.strbuffer_cur) { len = vt->parser.strbuffer_len - vt->parser.strbuffer_cur; - DEBUG_LOG1("Truncating strbuffer preserve to %zd bytes\n", len); + DEBUG_LOG1("Truncating strbuffer preserve to %zu bytes\n", len); } if(len > 0) { diff --git a/src/libvterm/src/pen.c b/src/libvterm/src/pen.c index c55f6931f8..d34599da11 100644 --- a/src/libvterm/src/pen.c +++ b/src/libvterm/src/pen.c @@ -387,7 +387,7 @@ INTERNAL void vterm_state_setpen(VTermState *state, const long args[], int argco if (!done) { - DEBUG_LOG1("libvterm: Unhandled CSI SGR %lu\n", arg); + DEBUG_LOG1("libvterm: Unhandled CSI SGR %ld\n", arg); } while (CSI_ARG_HAS_MORE(args[argi++])) diff --git a/src/ui.c b/src/ui.c index f4f7bcf837..151857f6f4 100644 --- a/src/ui.c +++ b/src/ui.c @@ -1168,7 +1168,7 @@ clip_start_selection(int col, int row, int repeated_click) cb->prev = cb->start; #ifdef DEBUG_SELECTION - printf("Selection started at (%u,%u)\n", cb->start.lnum, cb->start.col); + printf("Selection started at (%ld,%d)\n", cb->start.lnum, cb->start.col); #endif } @@ -1203,7 +1203,7 @@ clip_process_selection( } #ifdef DEBUG_SELECTION - printf("Selection ended: (%u,%u) to (%u,%u)\n", cb->start.lnum, + printf("Selection ended: (%ld,%d) to (%ld,%d)\n", cb->start.lnum, cb->start.col, cb->end.lnum, cb->end.col); #endif if (clip_isautosel_star() @@ -1347,7 +1347,7 @@ clip_process_selection( cb->prev.col = col; #ifdef DEBUG_SELECTION - printf("Selection is: (%u,%u) to (%u,%u)\n", cb->start.lnum, + printf("Selection is: (%ld,%d) to (%ld,%d)\n", cb->start.lnum, cb->start.col, cb->end.lnum, cb->end.col); #endif } diff --git a/src/version.c b/src/version.c index 1f54a4ae76..af80600c0d 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 106, /**/ 105, /**/ From 4ba64418187995c96fc29e4e4f699cecd57013bd Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 9 Jan 2020 16:25:52 +0100 Subject: [PATCH 32/42] patch 8.2.0107: hgignore is out of sync from gitignore Problem: Hgignore is out of sync from gitignore. Solution: Add lines to hgignore. (Ken Takata) --- .hgignore | 2 ++ src/version.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.hgignore b/.hgignore index ff3d542046..d266dda091 100644 --- a/.hgignore +++ b/.hgignore @@ -10,6 +10,7 @@ src/auto/gui_gtk_gresources.h src/objects/.dirstamp src/objects src/tags +src/types.vim # We do need src/auto/configure. src/auto/config.cache @@ -86,6 +87,7 @@ src/kword_test # Generated by "make install" runtime/doc/tags +runtime/doc/doctags # Generated by "make shadow". The directory names could be anything but we # restrict them to shadow (the default) or shadow-* diff --git a/src/version.c b/src/version.c index af80600c0d..f15d748dc5 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 107, /**/ 106, /**/ From bf0acff012c2f75563c20241f1a5478534fe2c7a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 9 Jan 2020 21:01:59 +0100 Subject: [PATCH 33/42] 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 #5455) --- src/sign.c | 12 ++++++++++-- ...t_sign_cursor_01.dump => Test_sign_cursor_1.dump} | 0 src/testdir/dumps/Test_sign_cursor_2.dump | 6 ++++++ ...t_sign_cursor_02.dump => Test_sign_cursor_3.dump} | 0 src/testdir/test_signs.vim | 8 ++++++-- src/version.c | 2 ++ 6 files changed, 24 insertions(+), 4 deletions(-) rename src/testdir/dumps/{Test_sign_cursor_01.dump => Test_sign_cursor_1.dump} (100%) create mode 100644 src/testdir/dumps/Test_sign_cursor_2.dump rename src/testdir/dumps/{Test_sign_cursor_02.dump => Test_sign_cursor_3.dump} (100%) diff --git a/src/sign.c b/src/sign.c index 935ec3c74d..9d8d7ac8a3 100644 --- a/src/sign.c +++ b/src/sign.c @@ -1025,6 +1025,16 @@ sign_define_by_name( else sp_prev->sn_next = sp; } + else + { + win_T *wp; + + // Signs may already exist, a redraw is needed in windows with a + // non-empty sign list. + FOR_ALL_WINDOWS(wp) + if (wp->w_buffer->b_signlist != NULL) + redraw_buf_later(wp->w_buffer, NOT_VALID); + } // set values for a defined sign. if (icon != NULL) @@ -1781,10 +1791,8 @@ sign_get_placed( else { FOR_ALL_BUFFERS(buf) - { if (buf->b_signlist != NULL) sign_get_placed_in_buf(buf, 0, sign_id, sign_group, retlist); - } } } diff --git a/src/testdir/dumps/Test_sign_cursor_01.dump b/src/testdir/dumps/Test_sign_cursor_1.dump similarity index 100% rename from src/testdir/dumps/Test_sign_cursor_01.dump rename to src/testdir/dumps/Test_sign_cursor_1.dump diff --git a/src/testdir/dumps/Test_sign_cursor_2.dump b/src/testdir/dumps/Test_sign_cursor_2.dump new file mode 100644 index 0000000000..2d10a2ced5 --- /dev/null +++ b/src/testdir/dumps/Test_sign_cursor_2.dump @@ -0,0 +1,6 @@ +| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0@72 +| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0@1| @70 +|-+0&#ffff4012|)>m+0&#ffffff0@3| @68 +| +0#0000e05#a8a8a8255@1|y+0#0000000#ffffff0@3| @68 +|~+0#4040ff13&| @73 +|:+0#0000000&|s|i|g|n| |d|e|f|i|n|e| |s|1| |t|e|x|t|=|-|)| @33|2|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_sign_cursor_02.dump b/src/testdir/dumps/Test_sign_cursor_3.dump similarity index 100% rename from src/testdir/dumps/Test_sign_cursor_02.dump rename to src/testdir/dumps/Test_sign_cursor_3.dump diff --git a/src/testdir/test_signs.vim b/src/testdir/test_signs.vim index 862199cd3c..d480671d27 100644 --- a/src/testdir/test_signs.vim +++ b/src/testdir/test_signs.vim @@ -1747,12 +1747,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 diff --git a/src/version.c b/src/version.c index f15d748dc5..e06dfc6d1c 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 108, /**/ 107, /**/ From ac15fd8c6761763c8feedef1a2fbd8309f0a823c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 9 Jan 2020 21:35:48 +0100 Subject: [PATCH 34/42] patch 8.2.0109: corrupted text properties when expanding spaces Problem: Corrupted text properties when expanding spaces. Solution: Reallocate the line. (Nobuhiro Takasaki, closes #5457) --- src/edit.c | 20 ++++++++- src/testdir/test_textprop.vim | 77 ++++++++++++++++++++++++++++++----- src/version.c | 2 + 3 files changed, 86 insertions(+), 13 deletions(-) diff --git a/src/edit.c b/src/edit.c index d2e45dd2f0..8160fe5693 100644 --- a/src/edit.c +++ b/src/edit.c @@ -5604,9 +5604,25 @@ ins_tab(void) #ifdef FEAT_PROP_POPUP if (!(State & VREPLACE_FLAG)) { - mch_memmove(ptr, ptr + i, curbuf->b_ml.ml_line_len - i - - (ptr - curbuf->b_ml.ml_line_ptr)); + char_u *newp; + int col; + + newp = alloc(curbuf->b_ml.ml_line_len - i); + if (newp == NULL) + return FALSE; + + col = ptr - curbuf->b_ml.ml_line_ptr; + if (col > 0) + mch_memmove(newp, ptr - col, col); + mch_memmove(newp + col, ptr + i, + curbuf->b_ml.ml_line_len - col - i); + + if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) + vim_free(curbuf->b_ml.ml_line_ptr); + curbuf->b_ml.ml_line_ptr = newp; curbuf->b_ml.ml_line_len -= i; + curbuf->b_ml.ml_flags = + (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY; } else #endif diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim index 54b42c1467..c71f1a7d4d 100644 --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -926,19 +926,32 @@ func Test_proptype_substitute2() bwipe! endfunc +func SaveOptions() + let d = #{tabstop: &tabstop, + \ softtabstop: &softtabstop, + \ shiftwidth: &shiftwidth, + \ expandtab: &expandtab, + \ foldmethod: '"' .. &foldmethod .. '"', + \ } + return d +endfunc + +func RestoreOptions(dict) + for name in keys(a:dict) + exe 'let &' .. name .. ' = ' .. a:dict[name] + endfor +endfunc + func Test_textprop_noexpandtab() - %bwipe! new - let save_ts = &tabstop + let save_dict = SaveOptions() + set tabstop=8 - let save_sts = &softtabstop set softtabstop=4 - let save_sw = &shiftwidth set shiftwidth=4 - let save_et = &expandtab set noexpandtab - let save_fdm = &foldmethod set foldmethod=marker + call feedkeys("\\0Ca\\\", "tx") call prop_type_add('test', {'highlight': 'ErrorMsg'}) call prop_add(1, 1, {'end_col': 2, 'type': 'test'}) @@ -955,9 +968,51 @@ func Test_textprop_noexpandtab() catch /^Vim\%((\a\+)\)\=:E964/ endtry call prop_remove({'type': 'test'}) - let &foldmethod = save_fdm - let &expandtab = save_et - let &shiftwidth = save_sw - let &softtabstop = save_sts - let &tabstop = save_ts + call prop_type_delete('test') + + call RestoreOptions(save_dict) + bwipe! +endfunc + +func Test_textprop_noexpandtab_redraw() + new + let save_dict = SaveOptions() + + set tabstop=8 + set softtabstop=4 + set shiftwidth=4 + set noexpandtab + set foldmethod=marker + + call feedkeys("\\0Ca\\\\", "tx") + call prop_type_add('test', {'highlight': 'ErrorMsg'}) + call prop_add(1, 1, {'end_col': 2, 'type': 'test'}) + call feedkeys("0i\", "tx") + " Internally broken at the next line + call feedkeys("A\\", "tx") + redraw + " Index calculation failed internally on next line + call prop_add(1, 1, {'end_col': 2, 'type': 'test'}) + call prop_remove({'type': 'test', 'all': v:true}) + call prop_type_delete('test') + call prop_type_delete('test') + + call RestoreOptions(save_dict) + bwipe! +endfunc + +func Test_textprop_ins_str() + new + call setline(1, 'just some text') + call prop_type_add('test', {'highlight': 'ErrorMsg'}) + call prop_add(1, 1, {'end_col': 2, 'type': 'test'}) + call assert_equal([{'id': 0, 'col': 1, 'end': 1, 'type': 'test', 'length': 1, 'start': 1}], prop_list(1)) + + call feedkeys("foi\\", "tx") + call assert_equal('just some text', getline(1)) + call assert_equal([{'id': 0, 'col': 1, 'end': 1, 'type': 'test', 'length': 1, 'start': 1}], prop_list(1)) + + bwipe! + call prop_remove({'type': 'test'}) + call prop_type_delete('test') endfunc diff --git a/src/version.c b/src/version.c index e06dfc6d1c..815fc472af 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 109, /**/ 108, /**/ From 2963456ff2b740244b3a064785fe681b1998d75e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 9 Jan 2020 21:46:04 +0100 Subject: [PATCH 35/42] Update runtime files. --- runtime/autoload/getscript.vim | 4 +- runtime/autoload/netrw.vim | 83 +++++----- runtime/autoload/netrwSettings.vim | 2 +- runtime/autoload/tar.vim | 244 ++++++++++++++++++++++------- runtime/autoload/zip.vim | 33 ++-- runtime/doc/eval.txt | 38 ++--- runtime/doc/insert.txt | 2 +- runtime/doc/pi_getscript.txt | 14 +- runtime/doc/pi_logipat.txt | 12 +- runtime/doc/pi_netrw.txt | 31 ++-- runtime/doc/pi_tar.txt | 111 +++++++------ runtime/doc/pi_vimball.txt | 4 +- runtime/doc/pi_zip.txt | 15 +- runtime/doc/quickfix.txt | 2 +- runtime/doc/tags | 1 + runtime/doc/terminal.txt | 6 +- runtime/doc/todo.txt | 14 +- runtime/doc/uganda.txt | 2 +- runtime/plugin/getscriptPlugin.vim | 2 +- runtime/plugin/netrwPlugin.vim | 6 +- runtime/plugin/tarPlugin.vim | 4 +- runtime/plugin/zipPlugin.vim | 8 +- runtime/syntax/2html.vim | 4 +- 23 files changed, 405 insertions(+), 237 deletions(-) diff --git a/runtime/autoload/getscript.vim b/runtime/autoload/getscript.vim index f64c5f199d..8f854b93a9 100644 --- a/runtime/autoload/getscript.vim +++ b/runtime/autoload/getscript.vim @@ -22,7 +22,7 @@ if &cp endif if v:version < 702 echohl WarningMsg - echo "***warning*** this version of getscript needs vim 7.2" + echo "***warning*** this version of GetLatestVimScripts needs vim 7.2" echohl Normal finish endif @@ -236,7 +236,7 @@ fun! getscript#GetLatestVimScripts() " call Decho("..depscript<".depscript.">") " found a "GetLatestVimScripts: # #" line in the script; - " check if it's already in the datafile by searching backwards from llp1, + " check if its already in the datafile by searching backwards from llp1, " the (prior to reading in the plugin script) last line plus one of the GetLatestVimScripts.dat file, " for the script-id with no wrapping allowed. let curline = line(".") diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim index 26c4c92d06..f4cc89e474 100644 --- a/runtime/autoload/netrw.vim +++ b/runtime/autoload/netrw.vim @@ -1,8 +1,8 @@ " netrw.vim: Handles file transfer and remote directory listing across " AUTOLOAD SECTION -" Date: Nov 29, 2019 -" Version: 167 -" Maintainer: Charles E Campbell +" Date: Jan 07, 2020 +" Version: 168 +" Maintainer: Charles E Campbell " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim " Copyright: Copyright (C) 2016 Charles E. Campbell {{{1 " Permission is hereby granted to use and distribute this code, @@ -43,7 +43,7 @@ if exists("s:needspatches") endfor endif -let g:loaded_netrw = "v167" +let g:loaded_netrw = "v168" if !exists("s:NOTE") let s:NOTE = 0 let s:WARNING = 1 @@ -68,7 +68,7 @@ setl cpo&vim " Usage: netrw#ErrorMsg(s:NOTE | s:WARNING | s:ERROR,"some message",error-number) " netrw#ErrorMsg(s:NOTE | s:WARNING | s:ERROR,["message1","message2",...],error-number) " (this function can optionally take a list of messages) -" Mar 21, 2017 : max errnum currently is 105 +" Dec 2, 2019 : max errnum currently is 106 fun! netrw#ErrorMsg(level,msg,errnum) " call Dfunc("netrw#ErrorMsg(level=".a:level." msg<".a:msg."> errnum=".a:errnum.") g:netrw_use_errorwindow=".g:netrw_use_errorwindow) @@ -447,23 +447,9 @@ if !exists("g:netrw_localmovecmd") let g:netrw_localmovecmd= "" endif endif -if v:version < 704 || (v:version == 704 && !has("patch1107")) - " 1109 provides for delete(tmpdir,"d") which is what will be used - if exists("g:netrw_local_rmdir") - let g:netrw_localrmdir= g:netrw_local_rmdir - call netrw#ErrorMsg(s:NOTE,"g:netrw_local_rmdir is deprecated in favor of g:netrw_localrmdir",86) - endif - if has("win32") || has("win95") || has("win64") || has("win16") - if g:netrw_cygwin - call s:NetrwInit("g:netrw_localrmdir","rmdir") - else - let g:netrw_localrmdir = expand("$COMSPEC") - let g:netrw_localrmdiropt= " /c rmdir" - endif - else - call s:NetrwInit("g:netrw_localrmdir","rmdir") - endif -endif +" following serves as an example for how to insert a version&patch specific test +"if v:version < 704 || (v:version == 704 && !has("patch1107")) +"endif call s:NetrwInit("g:netrw_liststyle" , s:THINLIST) " sanity checks if g:netrw_liststyle < 0 || g:netrw_liststyle >= s:MAXLIST @@ -5217,8 +5203,8 @@ fun! netrw#BrowseX(fname,remote) if a:remote == 0 && isdirectory(a:fname) " if its really just a local directory, then do a "gf" instead " call Decho("remote≡0 and a:fname<".a:fname."> ".(isdirectory(a:fname)? "is a directory" : "is not a directory"),'~'.expand("")) -" call Decho("..appears to be a local directory; using gf instead",'~'.expand("")) - norm! gf +" call Decho("..appears to be a local directory; using e ".a:fname." instead",'~'.expand("")) + exe "e ".a:fname " call Dret("netrw#BrowseX") return elseif a:remote == 1 && a:fname !~ '^https\=:' && a:fname =~ '/$' @@ -7158,17 +7144,8 @@ fun! s:NetrwMarkFileCopy(islocal,...) " call Dret("s:NetrwMarkFileCopy : lcd failure") return endif - if v:version < 704 || (v:version == 704 && !has("patch1107")) - call s:NetrwExe("sil !".g:netrw_localrmdir.g:netrw_localrmdiropt." ".s:ShellEscape(tmpdir,1)) - if v:shell_error != 0 - call netrw#ErrorMsg(s:WARNING,"consider setting g:netrw_localrmdir<".g:netrw_localrmdir."> to something that works",80) -" " call Dret("s:NetrwMarkFileCopy : failed: sil !".g:netrw_localrmdir." ".s:ShellEscape(tmpdir,1) ) - return - endif - else - if delete(tmpdir,"d") - call netrw#ErrorMsg(s:ERROR,"unable to delete directory <".tmpdir.">!",103) - endif + if delete(tmpdir,"d") + call netrw#ErrorMsg(s:ERROR,"unable to delete directory <".tmpdir.">!",103) endif else if s:NetrwLcd(curdir) @@ -9587,6 +9564,7 @@ fun! s:NetrwWideListing() " call Decho("setl ma noro",'~'.expand("")) let b:netrw_cpf= 0 if line("$") >= w:netrw_bannercnt + " determine the maximum filename size; use that to set cpf exe 'sil NetrwKeepj '.w:netrw_bannercnt.',$g/^./if virtcol("$") > b:netrw_cpf|let b:netrw_cpf= virtcol("$")|endif' NetrwKeepj call histdel("/",-1) else @@ -9594,6 +9572,7 @@ fun! s:NetrwWideListing() " call Dret("NetrwWideListing") return endif + " allow for two spaces to separate columns let b:netrw_cpf= b:netrw_cpf + 2 " call Decho("b:netrw_cpf=max_filename_length+2=".b:netrw_cpf,'~'.expand("")) @@ -9621,10 +9600,11 @@ fun! s:NetrwWideListing() if newcolend > line("$") | let newcolend= line("$") | endif let newcolqty= newcolend - newcolstart exe newcolstart + " COMBAK: both of the visual-mode using lines below are problematic vis-a-vis @* if newcolqty == 0 exe "sil! NetrwKeepj norm! 0\$h\"ax".w:netrw_bannercnt."G$\"ap" else - exe "sil! NetrwKeepj norm! 0\".newcolqty.'j$h\"ax'.w:netrw_bannercnt.'G$\"ap' + exe "sil! NetrwKeepj norm! 0\".newcolqty.'j$h"ax'.w:netrw_bannercnt.'G$"ap' endif exe "sil! NetrwKeepj ".newcolstart.','.newcolend.'d _' exe 'sil! NetrwKeepj '.w:netrw_bannercnt @@ -11048,9 +11028,10 @@ fun! s:NetrwLocalRename(path) range " call Dfunc("NetrwLocalRename(path<".a:path.">)") " preparation for removing multiple files/directories - let ykeep = @@ - let ctr = a:firstline - let svpos = winsaveview() + let ykeep = @@ + let ctr = a:firstline + let svpos = winsaveview() + let all = 0 " call Decho("saving posn to svpos<".string(svpos).">",'~'.expand("")) " rename files given by the markfilelist @@ -11078,6 +11059,23 @@ fun! s:NetrwLocalRename(path) range let newname = substitute(oldname,subfrom,subto,'') endif endif + if !all && filereadable(newname) + call inputsave() + let response= input("File<".newname."> already exists; do you want to overwrite it? (y/all/n) ") + call inputrestore() + if response == "all" + let all= 1 + elseif response != "y" && response != "yes" + " refresh the directory +" call Decho("refresh the directory listing",'~'.expand("")) + NetrwKeepj call s:NetrwRefresh(1,s:NetrwBrowseChgDir(1,'./')) +" call Decho("restoring posn to svpos<".string(svpos).">",'~'.expand("")) + NetrwKeepj call winrestview(svpos) + let @@= ykeep +" call Dret("NetrwLocalRename") + return + endif + endif call rename(oldname,newname) endfor call s:NetrwUnmarkList(bufnr("%"),b:netrw_curdir) @@ -11101,14 +11099,14 @@ fun! s:NetrwLocalRename(path) range NetrwKeepj norm! 0 let oldname= s:ComposePath(a:path,curword) -" call Decho("oldname<".oldname.">",'~'.expand("")) +" call Decho("oldname<".oldname.">",'~'.expand("")) call inputsave() let newname= input("Moving ".oldname." to : ",substitute(oldname,'/*$','','e')) call inputrestore() call rename(oldname,newname) -" call Decho("renaming <".oldname."> to <".newname.">",'~'.expand("")) +" call Decho("renaming <".oldname."> to <".newname.">",'~'.expand("")) let ctr= ctr + 1 endwhile @@ -11896,6 +11894,9 @@ fun! s:NetrwExe(cmd) " call Decho("exe ".a:cmd,'~'.expand("")) exe a:cmd endif + if v:shell_error + call netrw#ErrorMsg(s:WARNING,"shell signalled an error",106) + endif " call Dret("s:NetrwExe : v:shell_error=".v:shell_error) endfun diff --git a/runtime/autoload/netrwSettings.vim b/runtime/autoload/netrwSettings.vim index 327db6a540..bed5cfc455 100644 --- a/runtime/autoload/netrwSettings.vim +++ b/runtime/autoload/netrwSettings.vim @@ -1,6 +1,6 @@ " netrwSettings.vim: makes netrw settings simpler " Date: Nov 09, 2016 -" Maintainer: Charles E Campbell +" Maintainer: Charles E Campbell " Version: 16 " Copyright: Copyright (C) 1999-2007 Charles E. Campbell {{{1 " Permission is hereby granted to use and distribute this code, diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim index dc670dbd14..3ed34fd0aa 100644 --- a/runtime/autoload/tar.vim +++ b/runtime/autoload/tar.vim @@ -1,13 +1,13 @@ " tar.vim: Handles browsing tarfiles " AUTOLOAD PORTION -" Date: Apr 17, 2013 -" Version: 29 -" Maintainer: Charles E Campbell -" License: Vim License (see vim's :help license) +" Date: Jan 07, 2020 +" Version: 32 +" Maintainer: Charles E Campbell +" License: Vim License (see vim's :help license) " " Contains many ideas from Michael Toren's " -" Copyright: Copyright (C) 2005-2011 Charles E. Campbell {{{1 +" Copyright: Copyright (C) 2005-2017 Charles E. Campbell {{{1 " Permission is hereby granted to use and distribute this code, " with or without modifications, provided that this copyright " notice is copied with it. Like anything else that's free, @@ -22,7 +22,7 @@ if &cp || exists("g:loaded_tar") finish endif -let g:loaded_tar= "v29" +let g:loaded_tar= "v32" if v:version < 702 echohl WarningMsg echo "***warning*** this version of tar needs vim 7.2" @@ -48,6 +48,9 @@ endif if !exists("g:tar_writeoptions") let g:tar_writeoptions= "uf" endif +if !exists("g:tar_delfile") + let g:tar_delfile="--delete -f" +endif if !exists("g:netrw_cygwin") if has("win32") || has("win95") || has("win64") || has("win16") if &shell =~ '\%(\\|\\)\%(\.exe\)\=$' @@ -109,6 +112,7 @@ fun! tar#Browse(tarfile) " sanity checks if !executable(g:tar_cmd) redraw! +" call Decho('***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system') echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system' let &report= repkeep " call Dret("tar#Browse") @@ -117,8 +121,9 @@ fun! tar#Browse(tarfile) if !filereadable(a:tarfile) " call Decho('a:tarfile<'.a:tarfile.'> not filereadable') if a:tarfile !~# '^\a\+://' - " if it's an url, don't complain, let url-handlers such as vim do its thing + " if its an url, don't complain, let url-handlers such as vim do its thing redraw! +" call Decho("***error*** (tar#Browse) File not readable<".a:tarfile.">") echohl Error | echo "***error*** (tar#Browse) File not readable<".a:tarfile.">" | echohl None endif let &report= repkeep @@ -152,12 +157,27 @@ fun! tar#Browse(tarfile) " assuming cygwin let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e') endif - let curlast= line("$") - if tarfile =~# '\.\(gz\|tgz\)$' - let gzip_command = s:get_gzip_command(tarfile) + + if tarfile =~# '\.\(gz\)$' " call Decho("1: exe silent r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ") - exe "sil! r! " . gzip_command . " -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - " + exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - " + + elseif tarfile =~# '\.\(tgz\)$' || tarfile =~# '\.\(tbz\)$' || tarfile =~# '\.\(txz\)$' + if has("unix") && executable("file") + let filekind= system("file ".shellescape(tarfile,1)) =~ "bzip2" + else + let filekind= "" + endif + + if filekind =~ "bzip2" + exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - " + elseif filekind =~ "XZ" + exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - " + else + exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - " + endif + elseif tarfile =~# '\.lrp' " call Decho("2: exe silent r! cat -- ".shellescape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - ") exe "sil! r! cat -- ".shellescape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - " @@ -184,7 +204,7 @@ fun! tar#Browse(tarfile) " call Dret("tar#Browse : a:tarfile<".a:tarfile.">") return endif - if line("$") == curlast || ( line("$") == (curlast + 1) && getline("$") =~ '\c\%(warning\|error\|inappropriate\|unrecognized\)') + if line("$") == curlast || ( line("$") == (curlast + 1) && getline("$") =~# '\c\%(warning\|error\|inappropriate\|unrecognized\)') redraw! echohl WarningMsg | echo "***warning*** (tar#Browse) ".a:tarfile." doesn't appear to be a tar file" | echohl None keepj sil! %d @@ -197,8 +217,13 @@ fun! tar#Browse(tarfile) return endif + " set up maps supported for tar setlocal noma nomod ro - noremap :call TarBrowseSelect() + noremap :call TarBrowseSelect() + noremap x :call tar#Extract() + if &mouse != "" + noremap :call TarBrowseSelect() + endif let &report= repkeep " call Dret("tar#Browse : b:tarfile<".b:tarfile.">") @@ -235,7 +260,8 @@ fun! s:TarBrowseSelect() let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e') endif - new + " open a new window (tar#Read will read a file into it) + noswapfile new if !exists("g:tar_nomax") || g:tar_nomax == 0 wincmd _ endif @@ -267,7 +293,7 @@ fun! tar#Read(fname,mode) if fname =~ '\.bz2$' && executable("bzcat") let decmp= "|bzcat" let doro = 1 - elseif fname =~ '\.gz$' && executable("zcat") + elseif fname =~ '\.t\=gz$' && executable("zcat") let decmp= "|zcat" let doro = 1 elseif fname =~ '\.lzma$' && executable("lzcat") @@ -291,20 +317,29 @@ fun! tar#Read(fname,mode) endif if tarfile =~# '\.bz2$' -" call Decho("7: exe silent r! bzip2 -d -c ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp) exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp - elseif tarfile =~# '\.\(gz\|tgz\)$' - let gzip_command = s:get_gzip_command(tarfile) -" call Decho("5: exe silent r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd.' -'.g:tar_readoptions.' - '.tar_secure.shellescape(fname,1)) - exe "sil! r! " . gzip_command . " -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + elseif tarfile =~# '\.\(gz\)$' + exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + + elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)' + if has("unix") && executable("file") + let filekind= system("file ".shellescape(tarfile,1)) + else + let filekind= "" + endif + if filekind =~ "bzip2" + exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + elseif filekind =~ "XZ" + exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + else + exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp + endif + elseif tarfile =~# '\.lrp$' -" call Decho("6: exe silent r! cat ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp) exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp elseif tarfile =~# '\.lzma$' -" call Decho("7: exe silent r! lzma -d -c ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp) exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp elseif tarfile =~# '\.\(xz\|txz\)$' -" call Decho("3: exe silent r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp) exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp else if tarfile =~ '^\s*-' @@ -348,13 +383,14 @@ fun! tar#Write(fname) " sanity checks if !executable(g:tar_cmd) redraw! - echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system' +" call Decho('***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system') let &report= repkeep " call Dret("tar#Write") return endif if !exists("*mkdir") redraw! +" call Decho("***error*** (tar#Write) sorry, mkdir() doesn't work on your system") echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None let &report= repkeep " call Dret("tar#Write") @@ -375,6 +411,7 @@ fun! tar#Write(fname) exe "cd ".fnameescape(tmpdir) catch /^Vim\%((\a\+)\)\=:E344/ redraw! +" call Decho("***error*** (tar#Write) cannot cd to temporary directory") echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None let &report= repkeep " call Dret("tar#Write") @@ -393,8 +430,6 @@ fun! tar#Write(fname) let tarfile = substitute(b:tarfile,'tarfile:\(.\{-}\)::.*$','\1','') let fname = substitute(b:tarfile,'tarfile:.\{-}::\(.*\)$','\1','') - let gzip_command = s:get_gzip_command(tarfile) - " handle compressed archives if tarfile =~# '\.bz2' call system("bzip2 -d -- ".shellescape(tarfile,0)) @@ -402,12 +437,12 @@ fun! tar#Write(fname) let compress= "bzip2 -- ".shellescape(tarfile,0) " call Decho("compress<".compress.">") elseif tarfile =~# '\.gz' - call system(gzip_command . " -d -- ".shellescape(tarfile,0)) + call system("gzip -d -- ".shellescape(tarfile,0)) let tarfile = substitute(tarfile,'\.gz','','e') let compress= "gzip -- ".shellescape(tarfile,0) " call Decho("compress<".compress.">") elseif tarfile =~# '\.tgz' - call system(gzip_command . " -d -- ".shellescape(tarfile,0)) + call system("gzip -d -- ".shellescape(tarfile,0)) let tarfile = substitute(tarfile,'\.tgz','.tar','e') let compress= "gzip -- ".shellescape(tarfile,0) let tgz = 1 @@ -427,6 +462,7 @@ fun! tar#Write(fname) if v:shell_error != 0 redraw! +" call Decho("***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname) echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname | echohl None else @@ -459,10 +495,11 @@ fun! tar#Write(fname) endif " delete old file from tarfile -" call Decho("system(".g:tar_cmd." --delete -f ".shellescape(tarfile,0)." -- ".shellescape(fname,0).")") - call system(g:tar_cmd." --delete -f ".shellescape(tarfile,0).tar_secure.shellescape(fname,0)) +" call Decho("system(".g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0)." -- ".shellescape(fname,0).")") + call system(g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0)) if v:shell_error != 0 redraw! +" call Decho("***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname)) echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None else @@ -471,6 +508,7 @@ fun! tar#Write(fname) call system(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0)) if v:shell_error != 0 redraw! +" call Decho("***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname)) echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None elseif exists("compress") " call Decho("call system(".compress.")") @@ -486,11 +524,11 @@ fun! tar#Write(fname) if s:tblfile_{winnr()} =~ '^\a\+://' " call Decho("handle writing <".tarfile."> across network to <".s:tblfile_{winnr()}.">") let tblfile= s:tblfile_{winnr()} - 1split|enew + 1split|noswapfile enew let binkeep= &l:binary let eikeep = &ei set binary ei=all - exe "e! ".fnameescape(tarfile) + exe "noswapfile e! ".fnameescape(tarfile) call netrw#NetWrite(tblfile) let &ei = eikeep let &l:binary = binkeep @@ -524,7 +562,7 @@ fun! tar#Diff(userfname,fname) " sets up b:tardiff_otherbuf variables so each buffer knows about the other (for closing purposes) diffthis wincmd v - exe "e ".fnameescape(fname) + exe "noswapfile e ".fnameescape(fname) diffthis else redraw! @@ -533,6 +571,119 @@ fun! tar#Diff(userfname,fname) " call Dret("tar#Diff") endfun +" --------------------------------------------------------------------- +" tar#Extract: extract a file from a (possibly compressed) tar archive {{{2 +fun! tar#Extract() +" call Dfunc("tar#Extract()") + + let repkeep= &report + set report=10 + let fname= getline(".") +" call Decho("fname<".fname.">") + + if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-' + redraw! + echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"' +" call Dret('tar#BrowseSelect : rejecting tarfile member<'.fname.'> because of embedded "-"') + return + endif + + " sanity check + if fname =~ '^"' + let &report= repkeep +" call Dret("TarBrowseSelect") + return + endif + + let tarball = expand("%") +" call Decho("tarball<".tarball.">") + let tarbase = substitute(tarball,'\..*$','','') +" call Decho("tarbase<".tarbase.">") + + let extractcmd= netrw#WinPath(g:tar_extractcmd) + if filereadable(tarbase.".tar") +" call Decho("system(".extractcmd." ".shellescape(tarbase).".tar ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tar ".shellescape(fname)) + if v:shell_error != 0 + echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar ".fname.": failed!" | echohl NONE +" call Decho("***error*** ".extractcmd." ".tarbase.".tar ".fname.": failed!") + else + echo "***note*** successfully extracted ".fname + endif + + elseif filereadable(tarbase.".tgz") + let extractcmd= substitute(extractcmd,"-","-z","") +" call Decho("system(".extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname)) + if v:shell_error != 0 + echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tgz ".fname.": failed!" | echohl NONE +" call Decho("***error*** ".extractcmd."t ".tarbase.".tgz ".fname.": failed!") + else + echo "***note*** successfully extracted ".fname + endif + + elseif filereadable(tarbase.".tar.gz") + let extractcmd= substitute(extractcmd,"-","-z","") +" call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.gz ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tar.gz ".shellescape(fname)) + if v:shell_error != 0 + echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.gz ".fname.": failed!" | echohl NONE +" call Decho("***error*** ".extractcmd." ".tarbase.".tar.gz ".fname.": failed!") + else + echo "***note*** successfully extracted ".fname + endif + + elseif filereadable(tarbase.".tbz") + let extractcmd= substitute(extractcmd,"-","-j","") +" call Decho("system(".extractcmd." ".shellescape(tarbase).".tbz ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tbz ".shellescape(fname)) + if v:shell_error != 0 + echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tbz ".fname.": failed!" | echohl NONE +" call Decho("***error*** ".extractcmd."j ".tarbase.".tbz ".fname.": failed!") + else + echo "***note*** successfully extracted ".fname + endif + + elseif filereadable(tarbase.".tar.bz2") + let extractcmd= substitute(extractcmd,"-","-j","") +" call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.bz2 ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tar.bz2 ".shellescape(fname)) + if v:shell_error != 0 + echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tar.bz2 ".fname.": failed!" | echohl NONE +" call Decho("***error*** ".extractcmd."j ".tarbase.".tar.bz2 ".fname.": failed!") + else + echo "***note*** successfully extracted ".fname + endif + + elseif filereadable(tarbase.".txz") + let extractcmd= substitute(extractcmd,"-","-J","") +" call Decho("system(".extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname)) + if v:shell_error != 0 + echohl Error | echo "***error*** ".extractcmd." ".tarbase.".txz ".fname.": failed!" | echohl NONE +" call Decho("***error*** ".extractcmd." ".tarbase.".txz ".fname.": failed!") + else + echo "***note*** successfully extracted ".fname + endif + + elseif filereadable(tarbase.".tar.xz") + let extractcmd= substitute(extractcmd,"-","-J","") +" call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname).")") + call system(extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname)) + if v:shell_error != 0 + echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.xz ".fname.": failed!" | echohl NONE +" call Decho("***error*** ".extractcmd." ".tarbase.".tar.xz ".fname.": failed!") + else + echo "***note*** successfully extracted ".fname + endif + endif + + " restore option + let &report= repkeep + +" call Dret("tar#Extract") +endfun + " --------------------------------------------------------------------- " s:Rmdir: {{{2 fun! s:Rmdir(fname) @@ -587,10 +738,7 @@ fun! tar#Vimuntar(...) " if necessary, decompress the tarball; then, extract it if tartail =~ '\.tgz' - let gzip_command = s:get_gzip_command(tarfile) - if executable(gzip_command) - silent exe "!" . gzip_command . " -d ".shellescape(tartail) - elseif executable("gunzip") + if executable("gunzip") silent exe "!gunzip ".shellescape(tartail) elseif executable("gzip") silent exe "!gzip -d ".shellescape(tartail) @@ -628,28 +776,6 @@ fun! tar#Vimuntar(...) " call Dret("tar#Vimuntar") endfun -func s:get_gzip_command(file) - " Try using the "file" command to get the actual compression type, since - " there is no standard way for the naming: ".tgz", ".tbz", ".txz", etc. - " If the "file" command doesn't work fall back to just using the file name. - if a:file =~# 'z$' - let filetype = system('file ' . a:file) - if filetype =~ 'bzip2 compressed' && executable('bzip2') - return 'bzip2' - endif - if filetype =~ 'XZ compressed' && executable('xz') - return 'xz' - endif - endif - if a:file =~# 'bz2$' - return 'bzip2' - endif - if a:file =~# 'xz$' - return 'xz' - endif - return 'gzip' -endfunc - " ===================================================================== " Modelines And Restoration: {{{1 let &cpo= s:keepcpo diff --git a/runtime/autoload/zip.vim b/runtime/autoload/zip.vim index ea086e0882..874f44559c 100644 --- a/runtime/autoload/zip.vim +++ b/runtime/autoload/zip.vim @@ -1,10 +1,10 @@ " zip.vim: Handles browsing zipfiles " AUTOLOAD PORTION -" Date: Sep 13, 2016 -" Version: 28 -" Maintainer: Charles E Campbell +" Date: Jan 07, 2020 +" Version: 30 +" Maintainer: Charles E Campbell " License: Vim License (see vim's :help license) -" Copyright: Copyright (C) 2005-2013 Charles E. Campbell {{{1 +" Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1 " Permission is hereby granted to use and distribute this code, " with or without modifications, provided that this copyright " notice is copied with it. Like anything else that's free, @@ -20,7 +20,7 @@ if &cp || exists("g:loaded_zip") finish endif -let g:loaded_zip= "v28" +let g:loaded_zip= "v30" if v:version < 702 echohl WarningMsg echo "***warning*** this version of zip needs vim 7.2 or later" @@ -65,14 +65,14 @@ endif " zip#Browse: {{{2 fun! zip#Browse(zipfile) " call Dfunc("zip#Browse(zipfile<".a:zipfile.">)") - " sanity check: ensure that the zipfile has "PK" as its first two letters + " sanity check: insure that the zipfile has "PK" as its first two letters " (zipped files have a leading PK as a "magic cookie") if !filereadable(a:zipfile) || readfile(a:zipfile, "", 1)[0] !~ '^PK' - exe "noautocmd e ".fnameescape(a:zipfile) + exe "noswapfile noautocmd noswapfile e ".fnameescape(a:zipfile) " call Dret("zip#Browse : not a zipfile<".a:zipfile.">") return " else " Decho -" call Decho("zip#Browse: a:zipfile<".a:zipfile."> passed PK test - it's a zip file") +" call Decho("zip#Browse: a:zipfile<".a:zipfile."> passed PK test - its a zip file") endif let repkeep= &report @@ -95,7 +95,7 @@ fun! zip#Browse(zipfile) endif if !filereadable(a:zipfile) if a:zipfile !~# '^\a\+://' - " if it's an url, don't complain, let url-handlers such as vim do its thing + " if its an url, don't complain, let url-handlers such as vim do its thing redraw! echohl Error | echo "***error*** (zip#Browse) File not readable<".a:zipfile.">" | echohl None " call inputsave()|call input("Press to continue")|call inputrestore() @@ -141,8 +141,11 @@ fun! zip#Browse(zipfile) " Maps associated with zip plugin setlocal noma nomod ro - noremap :call ZipBrowseSelect() - noremap x :call zip#Extract() + noremap :call ZipBrowseSelect() + noremap x :call zip#Extract() + if &mouse != "" + noremap :call ZipBrowseSelect() + endif let &report= repkeep " call Dret("zip#Browse") @@ -175,17 +178,17 @@ fun! s:ZipBrowseSelect() " get zipfile to the new-window let zipfile = b:zipfile - let curfile= expand("%") + let curfile = expand("%") " call Decho("zipfile<".zipfile.">") " call Decho("curfile<".curfile.">") - new + noswapfile new if !exists("g:zip_nomax") || g:zip_nomax == 0 wincmd _ endif let s:zipfile_{winnr()}= curfile " call Decho("exe e ".fnameescape("zipfile:".zipfile.'::'.fname)) - exe "e ".fnameescape("zipfile:".zipfile.'::'.fname) + exe "noswapfile e ".fnameescape("zipfile:".zipfile.'::'.fname) filetype detect let &report= repkeep @@ -339,7 +342,7 @@ fun! zip#Write(fname) let binkeep= &binary let eikeep = &ei set binary ei=all - exe "e! ".fnameescape(zipfile) + exe "noswapfile e! ".fnameescape(zipfile) call netrw#NetWrite(netzipfile) let &ei = eikeep let &binary = binkeep diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 09d663e537..d04d9595d5 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 8.2. Last change: 2020 Jan 02 +*eval.txt* For Vim version 8.2. Last change: 2020 Jan 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -3047,10 +3047,6 @@ argv([{nr} [, {winid}]) The {winid} argument specifies the window ID, see |argc()|. For the Vim command line arguments see |v:argv|. - -assert_ functions are documented here: |assert-functions-details| - - asin({expr}) *asin()* Return the arc sine of {expr} measured in radians, as a |Float| in the range of [-pi/2, pi/2]. @@ -3068,6 +3064,10 @@ asin({expr}) *asin()* {only available when compiled with the |+float| feature} +assert_ functions are documented here: |assert-functions-details| + + + atan({expr}) *atan()* Return the principal value of the arc tangent of {expr}, in the range [-pi/2, +pi/2] radians, as a |Float|. @@ -3935,13 +3935,6 @@ diff_hlID({lnum}, {col}) *diff_hlID()* Can also be used as a |method|: > GetLnum()->diff_hlID(col) -environ() *environ()* - Return all of environment variables as dictionary. You can - check if an environment variable exists like this: > - :echo has_key(environ(), 'HOME') -< Note that the variable name may be CamelCase; to ignore case - use this: > - :echo index(keys(environ()), 'HOME', 0, 1) != -1 empty({expr}) *empty()* Return the Number 1 if {expr} is empty, zero otherwise. @@ -3960,6 +3953,14 @@ empty({expr}) *empty()* Can also be used as a |method|: > mylist->empty() +environ() *environ()* + Return all of environment variables as dictionary. You can + check if an environment variable exists like this: > + :echo has_key(environ(), 'HOME') +< Note that the variable name may be CamelCase; to ignore case + use this: > + :echo index(keys(environ()), 'HOME', 0, 1) != -1 + escape({string}, {chars}) *escape()* Escape the characters in {chars} that occur in {string} with a backslash. Example: > @@ -7084,9 +7085,9 @@ matchstrpos({expr}, {pat} [, {start} [, {count}]]) *matchstrpos()* < *max()* max({expr}) Return the maximum value of all items in {expr}. - {expr} can be a list or a dictionary. For a dictionary, - it returns the maximum of all values in the dictionary. - If {expr} is neither a list nor a dictionary, or one of the + {expr} can be a List or a Dictionary. For a Dictionary, + it returns the maximum of all values in the Dictionary. + If {expr} is neither a List nor a Dictionary, or one of the items in {expr} cannot be used as a Number this results in an error. An empty |List| or |Dictionary| results in zero. @@ -7095,9 +7096,9 @@ max({expr}) Return the maximum value of all items in {expr}. < *min()* min({expr}) Return the minimum value of all items in {expr}. - {expr} can be a list or a dictionary. For a dictionary, - it returns the minimum of all values in the dictionary. - If {expr} is neither a list nor a dictionary, or one of the + {expr} can be a List or a Dictionary. For a Dictionary, + it returns the minimum of all values in the Dictionary. + If {expr} is neither a List nor a Dictionary, or one of the items in {expr} cannot be used as a Number this results in an error. An empty |List| or |Dictionary| results in zero. @@ -10360,6 +10361,7 @@ win_splitmove({nr}, {target} [, {options}]) *win_splitmove()* then closing {nr}. Both {nr} and {target} can be window numbers or |window-ID|s. + Both must be in the current tab page. Returns zero for success, non-zero for failure. diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index fa7c0f7c45..07e9eb5eda 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -1,4 +1,4 @@ -*insert.txt* For Vim version 8.2. Last change: 2019 Nov 26 +*insert.txt* For Vim version 8.2. Last change: 2020 Jan 04 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/pi_getscript.txt b/runtime/doc/pi_getscript.txt index 36b7c968cf..b22e20131a 100644 --- a/runtime/doc/pi_getscript.txt +++ b/runtime/doc/pi_getscript.txt @@ -1,15 +1,15 @@ -*pi_getscript.txt* For Vim version 8.2. Last change: 2017 Aug 01 +*pi_getscript.txt* For Vim version 7.0. Last change: 2013 Nov 29 > GETSCRIPT REFERENCE MANUAL by Charles E. Campbell < -Authors: Charles E. Campbell - (remove NOSPAM from the email address) +Author: Charles E. Campbell + (remove NOSPAM from the email address) *GetLatestVimScripts-copyright* Copyright: (c) 2004-2012 by Charles E. Campbell *glvs-copyright* The VIM LICENSE (see |copyright|) applies to the files in this package, including getscriptPlugin.vim, getscript.vim, GetLatestVimScripts.dist, and pi_getscript.txt, except use "getscript" - instead of "Vim". Like anything else that's free, getscript and its + instead of "VIM". Like anything else that's free, getscript and its associated files are provided *as is* and comes with no warranty of any kind, either expressed or implied. No guarantees of merchantability. No guarantees of suitability for any purpose. By @@ -68,7 +68,7 @@ Your computer needs to have wget or curl for GetLatestVimScripts to do its work. mv GetLatestVimScripts.dist GetLatestVimScripts.dat (edit GetLatestVimScripts.dat to install your own personal list of desired plugins -- see |GetLatestVimScripts_dat|) - + 3. Windows: vim getscript.vba :so % @@ -389,7 +389,7 @@ v36 Apr 22, 2013 : * (glts) suggested use of plugin/**/*.vim instead of plugin/*.vim in globpath() call. * (Andy Wokula) got warning message when setting g:loaded_getscriptPlugin -v35 Apr 07, 2012 : * (MengHuan Yu) pointed out that the script URL has +v35 Apr 07, 2012 : * (MengHuan Yu) pointed out that the script url has changed (somewhat). However, it doesn't work, and the original one does (under Linux). I'll make it yet-another-option. @@ -479,4 +479,4 @@ v2 May 14, 2003 : extracts name of item to be obtained from the and they became numbers. Fixes comparison. ============================================================================== -vim:tw=78:ts=8:noet:ft=help:fdm=marker +vim:tw=78:ts=8:ft=help:fdm=marker diff --git a/runtime/doc/pi_logipat.txt b/runtime/doc/pi_logipat.txt index 23db48700e..b9f435dfdf 100644 --- a/runtime/doc/pi_logipat.txt +++ b/runtime/doc/pi_logipat.txt @@ -1,7 +1,7 @@ -*pi_logipat.txt* Logical Patterns Jun 22, 2015 +*pi_logipat.txt* Logical Patterns May 01, 2019 -Author: Charles E. Campbell -Copyright: (c) 2004-2015 by Charles E. Campbell *logiPat-copyright* +Author: Charles E. Campbell +Copyright: (c) 2004-2016 by Charles E. Campbell *logiPat-copyright* The VIM LICENSE applies to LogiPat.vim and LogiPat.txt (see |copyright|) except use "LogiPat" instead of "Vim" No warranty, express or implied. Use At-Your-Own-Risk. @@ -28,12 +28,14 @@ Copyright: (c) 2004-2015 by Charles E. Campbell *logiPat-copyright* grouping ( ... ) patterns "pattern" + *logiPat-cmd* :LogiPat {boolean-logic pattern} *:LogiPat* :LogiPat is a command which takes a boolean-logic argument (|logiPat-arg|). :LP {boolean-logic pattern} *:LP* :LP is a shorthand command version of :LogiPat + (|logiPat-cmd|). :LPE {boolean-logic pattern} *:LPE* No search is done, but the conversion from the @@ -69,7 +71,7 @@ Copyright: (c) 2004-2015 by Charles E. Campbell *logiPat-copyright* < will search for lines containing the string :abc: > :LogiPat "ab""cd" -< will search for lines containing the string :ab"c: +< will search for lines containing the string :ab"cd: > :LogiPat !"abc" < will search for lines which don't contain the string :abc: @@ -117,4 +119,4 @@ Copyright: (c) 2004-2015 by Charles E. Campbell *logiPat-copyright* ============================================================================== -vim:tw=78:ts=8:noet:ft=help +vim:tw=78:ts=8:ft=help diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt index cd9020ce7c..2cce1d0373 100644 --- a/runtime/doc/pi_netrw.txt +++ b/runtime/doc/pi_netrw.txt @@ -1,9 +1,9 @@ -*pi_netrw.txt* For Vim version 8.2. Last change: 2019 Dec 10 +*pi_netrw.txt* For Vim version 8.2. Last change: 2020 Jan 07 ------------------------------------------------ NETRW REFERENCE MANUAL by Charles E. Campbell ------------------------------------------------ -Author: Charles E. Campbell +Author: Charles E. Campbell (remove NOSPAM from Campbell's email first) Copyright: Copyright (C) 2017 Charles E Campbell *netrw-copyright* @@ -1184,7 +1184,7 @@ One may easily "bookmark" the currently browsed directory by using > *.netrwbook* Bookmarks are retained in between sessions of vim in a file called .netrwbook as a |List|, which is typically stored in the first directory on the user's -'runtimepath'; entries are kept in sorted order. +runtimepath; entries are kept in sorted order. If there are marked files and/or directories, mb will add them to the bookmark list. @@ -1565,8 +1565,8 @@ So, for example: > file.rcs,v -> NFH_rcsCOMMAv() < If more such translations are necessary, please send me email: > - NdrOchip at ScampbellPfamily.AbizM - NOSPAM -with a request. + NcampObell@SdrPchip.AorgM-NOSPAM +with a request. (remove the embedded NOSPAM first) Associated setting variable: |g:netrw_browsex_viewer| @@ -3229,7 +3229,8 @@ If there are marked files: (see |netrw-mf|) R [query: reply with s/^\(.*\)\.c$/\1.cpp/] < This example will mark all *.c files and then rename them to *.cpp - files. + files. Netrw will protect you from overwriting local files without + confirmation, but not remote ones. The ctrl-X character has special meaning for renaming files: > @@ -3512,7 +3513,7 @@ Example: Clear netrw's marked file list via a mapping on gu > - Click "Add..." - Set External Editor (adjust path as needed, include the quotes and !.! at the end): - "c:\Program Files\Vim\vim81\gvim.exe" !.! + "c:\Program Files\Vim\vim70\gvim.exe" !.! - Check that the filetype in the box below is {asterisk}.{asterisk} (all files), or whatever types you want (cec: change {asterisk} to * ; I had to @@ -3762,8 +3763,8 @@ by obtaining a copy of the latest (often developmental) netrw at: The script is typically installed on systems as something like: > - /usr/local/share/vim/vim8x/plugin/netrwPlugin.vim - /usr/local/share/vim/vim8x/autoload/netrw.vim + /usr/local/share/vim/vim7x/plugin/netrwPlugin.vim + /usr/local/share/vim/vim7x/autoload/netrw.vim (see output of :echo &rtp) < which is loaded automatically at startup (assuming :set nocp). If you @@ -3836,12 +3837,18 @@ netrw: Please send that information to 's maintainer along with the o/s you're using and the vim version that you're using - (see |:version|) > - NdrOchip at ScampbellPfamily.AbizM - NOSPAM + (see |:version|) (remove the embedded NOSPAM first) > + NcampObell@SdrPchip.AorgM-NOSPAM < ============================================================================== 12. History *netrw-history* {{{1 + v169: Dec 20, 2019 * (reported by amkarthik) that netrw's x + (|netrw-x|) would throw an error when + attempting to open a local directory. + v168: Dec 12, 2019 * scp timeout error message not reported, + hopefully now fixed (Shane Xb Qian) + v167: Nov 29, 2019 * netrw does a save&restore on @* and @+. That causes problems with the clipboard. Now restores occurs only if @* or @+ have @@ -4279,7 +4286,7 @@ netrw: Vim editor by Bram Moolenaar (Thanks, Bram!) dav support by C Campbell fetch support by Bram Moolenaar and C Campbell - ftp support by C Campbell + ftp support by C Campbell http support by Bram Moolenaar rcp rsync support by C Campbell (suggested by Erik Warendorph) diff --git a/runtime/doc/pi_tar.txt b/runtime/doc/pi_tar.txt index bde8f6c483..a59a584348 100644 --- a/runtime/doc/pi_tar.txt +++ b/runtime/doc/pi_tar.txt @@ -1,12 +1,12 @@ -*pi_tar.txt* For Vim version 8.2. Last change: 2013 Apr 17 +*pi_tar.txt* For Vim version 8.2. Last change: 2020 Jan 07 +====================+ | Tar File Interface | +====================+ -Author: Charles E. Campbell +Author: Charles E. Campbell (remove NOSPAM from Campbell's email first) -Copyright 2005-2012: *tar-copyright* +Copyright 2005-2017: *tar-copyright* The VIM LICENSE (see |copyright|) applies to the files in this package, including tarPlugin.vim, tar.vim, and pi_tar.txt. Like anything else that's except use "tar.vim" instead of "VIM". Like @@ -104,48 +104,67 @@ Copyright 2005-2012: *tar-copyright* ============================================================================== 4. History *tar-history* - - v28 Jun 23, 2011 * a few more decompression options (tbz tb2 txz) - v27 May 31, 2011 * moved cygwin detection before g:tar_copycmd handling - * inserted additional |:keepj| modifiers - * changed silent to sil! (|:silent|) - v26 Aug 09, 2010 * uses buffer-local instead of window variables to hold - tarfile name - * inserted keepj before 0d to protect jump list - v25 Jun 19, 2010 * (Jan Steffens) added support for xz compression - v24 Apr 07, 2009 * :Untarvim command implemented - Sep 28, 2009 * Added lzma support - v22 Aug 08, 2008 * security fixes - v16 Jun 06, 2008 * tarfile:: used instead of tarfile: when editing files - inside tarballs. Fixes a problem with tarballs called - things like c:\abc.tar. (tnx to Bill McCarthy) - v14 May 09, 2008 * arno caught a security bug - May 28, 2008 * various security improvements. Now requires patch 299 - which provides the fnameescape() function - May 30, 2008 * allows one to view *.gz and *.bz2 files that are in - *.tar files. - v12 Sep 07, 2007 * &shq now used if not the empty string for g:tar_shq - v10 May 02, 2006 * now using "redraw then echo" to show messages, instead - of "echo and prompt user" - v9 May 02, 2006 * improved detection of masquerading as tar file - v8 May 02, 2006 * allows editing of files that merely masquerade as tar - files - v7 Mar 22, 2006 * work on making tar plugin work across network - Mar 27, 2006 * g:tar_cmd now available for users to change the name - of the tar program to be used. By default, of course, - it's "tar". - v6 Dec 21, 2005 * writing to files not in directories caused problems - - fixed (pointed out by Christian Robinson) - v5 Nov 22, 2005 * report option workaround installed - v3 Sep 16, 2005 * handles writing files in an archive back to the - archive - Oct 18, 2005 * used instead of in autocmds - Oct 18, 2005 * handles writing to compressed archives - Nov 03, 2005 * handles writing tarfiles across a network using - netrw#NetWrite() - v2 * converted to use Vim7's new autoload feature by - Bram Moolenaar - v1 (original) * Michael Toren (see http://michael.toren.net/code/) + v31 Apr 02, 2017 * (klartext) reported that browsing encrypted + files in a zip archive created unencrypted + swap files. I am applying a similar fix + used on zip.vim to tar.vim: new buffers + are opened with |:noswapfile|. + May 16, 2017 * When the mouse option isn't empty, the + leftmouse can be used to select a file + in the tar-file listing. + v30 Apr 22, 2014 * .tgz files are ambiguous: they may have been + compressed with either gzip or bzip2. Tar.vim + disambiguates by using unix's "file" command. + Feb 18, 2016 * Changed =~ to =~# where appropriate + Feb 18, 2017 * Now also permits xz decompression + v28 Jun 23, 2011 * a few more decompression options (tbz tb2 txz) + v27 May 31, 2011 * moved cygwin detection before g:tar_copycmd + handling + * inserted additional |:keepj| modifiers + * changed silent to sil! (|:silent|) + v26 Aug 09, 2010 * uses buffer-local instead of window variables + to hold tarfile name + * inserted keepj before 0d to protect jump list + v25 Jun 19, 2010 * (Jan Steffens) added support for xz + compression + v24 Apr 07, 2009 * :Untarvim command implemented + Sep 28, 2009 * Added lzma support + v22 Aug 08, 2008 * security fixes + v16 Jun 06, 2008 * tarfile:: used instead of tarfile: when + editing files inside tarballs. Fixes a + problem with tarballs called things like + c:\abc.tar. (tnx to Bill McCarthy) + v14 May 09, 2008 * arno caught a security bug + May 28, 2008 * various security improvements. Now requires + patch 299 which provides the fnameescape() + function + May 30, 2008 * allows one to view *.gz and *.bz2 files that + are in *.tar files. + v12 Sep 07, 2007 * &shq now used if not the empty string for + g:tar_shq + v10 May 02, 2006 * now using "redraw then echo" to show messages, + instead of "echo and prompt user" + v9 May 02, 2006 * improved detection of masquerading as tar file + v8 May 02, 2006 * allows editing of files that merely masquerade + as tar files + v7 Mar 22, 2006 * work on making tar plugin work across network + Mar 27, 2006 * g:tar_cmd now available for users to change + the name of the tar program to be used. By + default, of course, it's "tar". + v6 Dec 21, 2005 * writing to files not in directories caused + problems - fixed (pointed out by + Christian Robinson) + v5 Nov 22, 2005 * report option workaround installed + v3 Sep 16, 2005 * handles writing files in an archive back to + the archive + Oct 18, 2005 * used instead of in autocmds + Oct 18, 2005 * handles writing to compressed archives + Nov 03, 2005 * handles writing tarfiles across a network + using netrw#NetWrite() + v2 * converted to use Vim7's new autoload feature + by Bram Moolenaar + v1 (original) * Michael Toren + (see http://michael.toren.net/code/) ============================================================================== -vim:tw=78:ts=8:noet:ft=help +vim:tw=78:ts=8:ft=help diff --git a/runtime/doc/pi_vimball.txt b/runtime/doc/pi_vimball.txt index 2680ffd59a..0a5663717b 100644 --- a/runtime/doc/pi_vimball.txt +++ b/runtime/doc/pi_vimball.txt @@ -4,7 +4,7 @@ Vimball Archiver ---------------- -Author: Charles E. Campbell +Author: Charles E. Campbell (remove NOSPAM from Campbell's email first) Copyright: (c) 2004-2015 by Charles E. Campbell *Vimball-copyright* The VIM LICENSE (see |copyright|) applies to the files in this @@ -273,4 +273,4 @@ WINDOWS *vimball-windows* ============================================================================== -vim:tw=78:ts=8:noet:ft=help:fdm=marker +vim:tw=78:ts=8:ft=help:fdm=marker diff --git a/runtime/doc/pi_zip.txt b/runtime/doc/pi_zip.txt index 82d96cb787..098d5d796b 100644 --- a/runtime/doc/pi_zip.txt +++ b/runtime/doc/pi_zip.txt @@ -1,10 +1,10 @@ -*pi_zip.txt* For Vim version 8.2. Last change: 2016 Sep 13 +*pi_zip.txt* For Vim version 8.2. Last change: 2020 Jan 07 +====================+ | Zip File Interface | +====================+ -Author: Charles E. Campbell +Author: Charles E. Campbell (remove NOSPAM from Campbell's email first) Copyright: Copyright (C) 2005-2015 Charles E Campbell *zip-copyright* The VIM LICENSE (see |copyright|) applies to the files in this @@ -33,10 +33,11 @@ Copyright: Copyright (C) 2005-2015 Charles E Campbell *zip-copyright* also write to the file. Currently, one may not make a new file in zip archives via the plugin. + COMMANDS~ *zip-x* - x : may extract a listed file when the cursor is atop it + x : extract a listed file when the cursor is atop it - OPTIONS + OPTIONS~ *g:zip_nomax* @@ -101,6 +102,10 @@ Copyright: Copyright (C) 2005-2015 Charles E Campbell *zip-copyright* ============================================================================== 4. History *zip-history* {{{1 + v29 Apr 02, 2017 * (Klartext) reported that an encrypted zip file could + opened but the swapfile held unencrypted contents. + The solution is to edit the contents of a zip file + using the |:noswapfile| modifier. v28 Oct 08, 2014 * changed the sanity checks for executables to reflect the command actually to be attempted in zip#Read() and zip#Write() @@ -149,4 +154,4 @@ Copyright: Copyright (C) 2005-2015 Charles E Campbell *zip-copyright* v1 Sep 15, 2005 * Initial release, had browsing, reading, and writing ============================================================================== -vim:tw=78:ts=8:noet:ft=help:fdm=marker +vim:tw=78:ts=8:ft=help:fdm=marker diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index ae45819156..1013023be7 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -1,4 +1,4 @@ -*quickfix.txt* For Vim version 8.2. Last change: 2019 Dec 07 +*quickfix.txt* For Vim version 8.2. Last change: 2020 Jan 06 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/tags b/runtime/doc/tags index 1aff075b23..a477c44517 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -7557,6 +7557,7 @@ log10() eval.txt /*log10()* logiPat pi_logipat.txt /*logiPat* logiPat-arg pi_logipat.txt /*logiPat-arg* logiPat-caveat pi_logipat.txt /*logiPat-caveat* +logiPat-cmd pi_logipat.txt /*logiPat-cmd* logiPat-contents pi_logipat.txt /*logiPat-contents* logiPat-copyright pi_logipat.txt /*logiPat-copyright* logiPat-examples pi_logipat.txt /*logiPat-examples* diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt index f136426027..3eb84a3911 100644 --- a/runtime/doc/terminal.txt +++ b/runtime/doc/terminal.txt @@ -1,4 +1,4 @@ -*terminal.txt* For Vim version 8.2. Last change: 2019 Dec 07 +*terminal.txt* For Vim version 8.2. Last change: 2020 Jan 04 VIM REFERENCE MANUAL by Bram Moolenaar @@ -641,8 +641,8 @@ term_getsize({buf}) *term_getsize()* term_getstatus({buf}) *term_getstatus()* - Get the status of terminal {buf}. This returns a comma - separated list of these items: + Get the status of terminal {buf}. This returns a String with + a comma separated list of these items: running job is running finished job has finished normal in Terminal-Normal mode diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 38eb91c02e..7468b2a922 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1,4 +1,4 @@ -*todo.txt* For Vim version 8.2. Last change: 2020 Jan 02 +*todo.txt* For Vim version 8.2. Last change: 2020 Jan 06 VIM REFERENCE MANUAL by Bram Moolenaar @@ -209,6 +209,7 @@ When using :packadd files under "later" are not used, which is inconsistent with packages under "start". (xtal8, #1994) Patch to add new motion ]( and ]{. (Yasuhiro Matsumoto, #5320) +Or make "v" prefix work? Modeless selection doesn't work in gvim. (#4783) Caused by patch 8.1.1534. @@ -286,6 +287,10 @@ Patch to have text objects defined by arbitrary single characters. (Daniel Thau, 2013 Nov 20, 2014 Jan 29, 2014 Jan 31) Added tests (James McCoy, 2016 Aug 3, #958). Still needs more work. +":2resize +10" uses size of the current window, adds 10 and applies it to +window 2. User expects 10 to be added to size of window 2. (Daniel Steinberg, +#5443) + Patch for multi-byte characters in langmap and applying a mapping on them. (Christian Brabandt, 2015 Jun 12, update July 25) Is this the right solution? Need to cleanup langmap behavior: @@ -407,9 +412,6 @@ similar to check_due_timer(). Also see #3809. C syntax: {} inside () causes following {} to be highlighted as error. (Michalis Giannakidis, 2006 Jun 1) -Support setting the character displayed below the last line? Neovim uses -"eob:X" in 'fillchars'. - Check: __attribute__((format(printf, on semsg() and siemsg(). Where was this added? @@ -546,6 +548,8 @@ Add something like 'fillchars' local to window, but allow for specifying a highlight name. Esp. for the statusline. And "extends" and "precedes" are also useful without 'list' set. Also in 'fillchars' or another option? +Related: #3820 - Support setting the character displayed below the last line? +Neovim uses "eob:X" in 'fillchars'. Sourceforge Vim pages still have content, redirect from empty page. Check for PHP errors. (Wayne Davison, 2018 Oct 26) @@ -922,8 +926,6 @@ Patch from Christian Brabandt to preserve upper case marks when wiping out a buffer. (2013 Dec 9) Also fixes #2166? -Patch to add argument to :cquit. (Thinca, 2014 Oct 12) - Python: After "import vim" error messages only show the first line of the stack trace. (Yggdroot, 2017 Jul 28, #1887) diff --git a/runtime/doc/uganda.txt b/runtime/doc/uganda.txt index 05958471d2..8ea897575a 100644 --- a/runtime/doc/uganda.txt +++ b/runtime/doc/uganda.txt @@ -1,4 +1,4 @@ -*uganda.txt* For Vim version 8.2. Last change: 2019 Dec 07 +*uganda.txt* For Vim version 8.2. Last change: 2020 Jan 08 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/plugin/getscriptPlugin.vim b/runtime/plugin/getscriptPlugin.vim index fb0fbeab7b..8faa029f4d 100644 --- a/runtime/plugin/getscriptPlugin.vim +++ b/runtime/plugin/getscriptPlugin.vim @@ -30,7 +30,7 @@ set cpo&vim " Public Interface: {{{1 com! -nargs=0 GetLatestVimScripts call getscript#GetLatestVimScripts() com! -nargs=0 GetScripts call getscript#GetLatestVimScripts() -silent! com -nargs=0 GLVS call getscript#GetLatestVimScripts() +sil! com -nargs=0 GLVS call getscript#GetLatestVimScripts() " --------------------------------------------------------------------- " Restore Options: {{{1 diff --git a/runtime/plugin/netrwPlugin.vim b/runtime/plugin/netrwPlugin.vim index b20e9ae725..87302cf23b 100644 --- a/runtime/plugin/netrwPlugin.vim +++ b/runtime/plugin/netrwPlugin.vim @@ -1,7 +1,7 @@ " netrwPlugin.vim: Handles file transfer and remote directory listing across a network " PLUGIN SECTION -" Date: Feb 08, 2016 -" Maintainer: Charles E Campbell +" Date: Feb 08, 2016 - Jan 07, 2020 +" Maintainer: Charles E Campbell " GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim " Copyright: Copyright (C) 1999-2013 Charles E. Campbell {{{1 " Permission is hereby granted to use and distribute this code, @@ -20,7 +20,7 @@ if &cp || exists("g:loaded_netrwPlugin") finish endif -let g:loaded_netrwPlugin = "v167" +let g:loaded_netrwPlugin = "v168" let s:keepcpo = &cpo set cpo&vim "DechoRemOn diff --git a/runtime/plugin/tarPlugin.vim b/runtime/plugin/tarPlugin.vim index 6d9e6bd540..1fdd72c130 100644 --- a/runtime/plugin/tarPlugin.vim +++ b/runtime/plugin/tarPlugin.vim @@ -14,7 +14,7 @@ if &cp || exists("g:loaded_tarPlugin") finish endif -let g:loaded_tarPlugin = "v29" +let g:loaded_tarPlugin = "v32" let s:keepcpo = &cpo set cpo&vim @@ -39,8 +39,8 @@ augroup tar au BufReadCmd *.lrp call tar#Browse(expand("")) au BufReadCmd *.tar.bz2 call tar#Browse(expand("")) au BufReadCmd *.tar.Z call tar#Browse(expand("")) - au BufReadCmd *.tgz call tar#Browse(expand("")) au BufReadCmd *.tbz call tar#Browse(expand("")) + au BufReadCmd *.tgz call tar#Browse(expand("")) au BufReadCmd *.tar.lzma call tar#Browse(expand("")) au BufReadCmd *.tar.xz call tar#Browse(expand("")) au BufReadCmd *.txz call tar#Browse(expand("")) diff --git a/runtime/plugin/zipPlugin.vim b/runtime/plugin/zipPlugin.vim index c04d5344b1..4b90d3e43f 100644 --- a/runtime/plugin/zipPlugin.vim +++ b/runtime/plugin/zipPlugin.vim @@ -1,7 +1,7 @@ " zipPlugin.vim: Handles browsing zipfiles " PLUGIN PORTION -" Date: Sep 13, 2016 -" Maintainer: Charles E Campbell +" Date: Jan 07, 2020 +" Maintainer: Charles E Campbell " License: Vim License (see vim's :help license) " Copyright: Copyright (C) 2005-2016 Charles E. Campbell {{{1 " Permission is hereby granted to use and distribute this code, @@ -20,14 +20,14 @@ if &cp || exists("g:loaded_zipPlugin") finish endif -let g:loaded_zipPlugin = "v28" +let g:loaded_zipPlugin = "v30" let s:keepcpo = &cpo set cpo&vim " --------------------------------------------------------------------- " Options: {{{1 if !exists("g:zipPlugin_ext") - let g:zipPlugin_ext='*.apk,*.celzip,*.crtx,*.docm,*.docx,*.dotm,*.dotx,*.ear,*.epub,*.gcsx,*.glox,*.gqsx,*.ja,*.jar,*.kmz,*.oxt,*.potm,*.potx,*.ppam,*.ppsm,*.ppsx,*.pptm,*.pptx,*.sldx,*.thmx,*.vdw,*.war,*.wsz,*.xap,*.xlam,*.xlam,*.xlsb,*.xlsm,*.xlsx,*.xltm,*.xltx,*.xpi,*.zip' + let g:zipPlugin_ext='*.apk,*.celzip,*.crtx,*.docm,*.docx,*.dotm,*.dotx,*.ear,*.epub,*.gcsx,*.glox,*.gqsx,*.ja,*.jar,*.kmz,*.odb,*.odc,*.odf,*.odg,*.odi,*.odm,*.odp,*.ods,*.odt,*.otc,*.otf,*.otg,*.oth,*.oti,*.otp,*.ots,*.ott,*.oxt,*.potm,*.potx,*.ppam,*.ppsm,*.ppsx,*.pptm,*.pptx,*.sldx,*.thmx,*.vdw,*.war,*.wsz,*.xap,*.xlam,*.xlam,*.xlsb,*.xlsm,*.xlsx,*.xltm,*.xltx,*.xpi,*.zip' endif " --------------------------------------------------------------------- diff --git a/runtime/syntax/2html.vim b/runtime/syntax/2html.vim index 1e85bc509e..13504ed71f 100644 --- a/runtime/syntax/2html.vim +++ b/runtime/syntax/2html.vim @@ -1,6 +1,6 @@ " Vim syntax support file " Maintainer: Ben Fritz -" Last Change: 2019 Nov 13 +" Last Change: 2020 Jan 05 " " Additional contributors: " @@ -932,7 +932,7 @@ if s:settings.dynamic_folds \ "{", \ " var fold;", \ " fold = document.getElementById(objID);", - \ " if(fold.className == 'closed-fold')", + \ " if (fold.className == 'closed-fold')", \ " {", \ " fold.className = 'open-fold';", \ " }", From e05a89ac6399a8c7d164c99fdab6841d999a9128 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 10 Jan 2020 19:56:46 +0100 Subject: [PATCH 36/42] patch 8.2.0110: prop_find() is not implemented Problem: prop_find() is not implemented. Solution: Implement prop_find(). (Ryan Hackett, closes #5421, closes #4970) --- runtime/doc/textprop.txt | 21 ---- src/evalfunc.c | 1 + src/proto/textprop.pro | 1 + src/testdir/test_textprop.vim | 112 ++++++++++++++++++ src/textprop.c | 213 ++++++++++++++++++++++++++++++++-- src/version.c | 2 + 6 files changed, 319 insertions(+), 31 deletions(-) diff --git a/runtime/doc/textprop.txt b/runtime/doc/textprop.txt index 4fd688e7e6..98dbfdf4d6 100644 --- a/runtime/doc/textprop.txt +++ b/runtime/doc/textprop.txt @@ -154,8 +154,6 @@ prop_add({lnum}, {col}, {props}) added to. When not found, the global property types are used. If not found an error is given. - See |text-properties| for information about text properties. - Can also be used as a |method|: > GetLnum()->prop_add(col, props) @@ -168,14 +166,11 @@ prop_clear({lnum} [, {lnum-end} [, {props}]]) *prop_clear()* When {props} contains a "bufnr" item use this buffer, otherwise use the current buffer. - See |text-properties| for information about text properties. - Can also be used as a |method|: > GetLnum()->prop_clear() < *prop_find()* prop_find({props} [, {direction}]) - {not implemented yet} Search for a text property as specified with {props}: id property with this ID type property with this type name @@ -198,8 +193,6 @@ prop_find({props} [, {direction}]) as with prop_list(), and additionally an "lnum" entry. If no match is found then an empty Dict is returned. - See |text-properties| for information about text properties. - prop_list({lnum} [, {props}]) *prop_list()* Return a List with all text properties in line {lnum}. @@ -223,8 +216,6 @@ prop_list({lnum} [, {props}]) *prop_list()* When "end" is zero the property continues in the next line. The line break after this line is included. - See |text-properties| for information about text properties. - Can also be used as a |method|: > GetLnum()->prop_list() < @@ -248,8 +239,6 @@ prop_remove({props} [, {lnum} [, {lnum-end}]]) Returns the number of properties that were removed. - See |text-properties| for information about text properties. - Can also be used as a |method|: > GetProps()->prop_remove() @@ -275,8 +264,6 @@ prop_type_add({name}, {props}) *prop_type_add()* *E969* *E970* end_incl when TRUE inserts at the end position will be included in the text property - See |text-properties| for information about text properties. - Can also be used as a |method|: > GetPropName()->prop_type_add(props) @@ -285,8 +272,6 @@ prop_type_change({name}, {props}) *prop_type_change()* property with this name does not exist an error is given. The {props} argument is just like |prop_type_add()|. - See |text-properties| for information about text properties. - Can also be used as a |method|: > GetPropName()->prop_type_change(props) @@ -301,8 +286,6 @@ prop_type_delete({name} [, {props}]) *prop_type_delete()* When text property type {name} is not found there is no error. - See |text-properties| for information about text properties. - Can also be used as a |method|: > GetPropName()->prop_type_delete() @@ -316,8 +299,6 @@ prop_type_get([{name} [, {props}]) *prop_type_get()* {props} can contain a "bufnr" item. When it is given, use this buffer instead of the global property types. - See |text-properties| for information about text properties. - Can also be used as a |method|: > GetPropName()->prop_type_get() @@ -327,8 +308,6 @@ prop_type_list([{props}]) *prop_type_list()* {props} can contain a "bufnr" item. When it is given, use this buffer instead of the global property types. - See |text-properties| for information about text properties. - ============================================================================== 3. When text changes *text-prop-changes* diff --git a/src/evalfunc.c b/src/evalfunc.c index f192506d84..003d3b9ff2 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -620,6 +620,7 @@ static funcentry_T global_functions[] = #ifdef FEAT_PROP_POPUP {"prop_add", 3, 3, FEARG_1, f_prop_add}, {"prop_clear", 1, 3, FEARG_1, f_prop_clear}, + {"prop_find", 1, 2, FEARG_1, f_prop_find}, {"prop_list", 1, 2, FEARG_1, f_prop_list}, {"prop_remove", 1, 3, FEARG_1, f_prop_remove}, {"prop_type_add", 2, 2, FEARG_1, f_prop_type_add}, diff --git a/src/proto/textprop.pro b/src/proto/textprop.pro index 028e3d4b4f..30a846ef63 100644 --- a/src/proto/textprop.pro +++ b/src/proto/textprop.pro @@ -6,6 +6,7 @@ int get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int will_change); int find_visible_prop(win_T *wp, int type_id, int id, textprop_T *prop, linenr_T *found_lnum); proptype_T *text_prop_type_by_id(buf_T *buf, int id); void f_prop_clear(typval_T *argvars, typval_T *rettv); +void f_prop_find(typval_T *argvars, typval_T *rettv); void f_prop_list(typval_T *argvars, typval_T *rettv); void f_prop_remove(typval_T *argvars, typval_T *rettv); void f_prop_type_add(typval_T *argvars, typval_T *rettv); diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim index c71f1a7d4d..ca6fd746e6 100644 --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -103,6 +103,118 @@ func Get_expected_props() \ ] endfunc +func Test_prop_find() + new + call setline(1, ['one one one', 'twotwo', 'three', 'fourfour', 'five', 'sixsix']) + + " Add two text props on lines 1 and 5, and one spanning lines 2 to 4. + call prop_type_add('prop_name', {'highlight': 'Directory'}) + call prop_add(1, 5, {'type': 'prop_name', 'id': 10, 'length': 3}) + call prop_add(2, 4, {'type': 'prop_name', 'id': 11, 'end_lnum': 4, 'end_col': 9}) + call prop_add(5, 4, {'type': 'prop_name', 'id': 12, 'length': 1}) + + let expected = [ + \ {'lnum': 1, 'col': 5, 'length': 3, 'id': 10, 'type': 'prop_name', 'start': 1, 'end': 1}, + \ {'lnum': 2, 'col': 4, 'id': 11, 'type': 'prop_name', 'start': 1, 'end': 0}, + \ {'lnum': 5, 'col': 4, 'length': 1, 'id': 12, 'type': 'prop_name', 'start': 1, 'end': 1} + \ ] + + " Starting at line 5 col 1 this should find the prop at line 5 col 4. + call cursor(5,1) + let result = prop_find({'type': 'prop_name'}, 'f') + call assert_equal(expected[2], result) + + " With skipstart left at false (default), this should find the prop at line + " 5 col 4. + let result = prop_find({'type': 'prop_name', 'lnum': 5, 'col': 4}, 'b') + call assert_equal(expected[2], result) + + " With skipstart set to true, this should skip the prop at line 5 col 4. + let result = prop_find({'type': 'prop_name', 'lnum': 5, 'col': 4, 'skipstart': 1}, 'b') + unlet result.length + call assert_equal(expected[1], result) + + " Search backwards from line 1 col 10 to find the prop on the same line. + let result = prop_find({'type': 'prop_name', 'lnum': 1, 'col': 10}, 'b') + call assert_equal(expected[0], result) + + " with skipstart set to false, if the start position is anywhere between the + " start and end lines of a text prop (searching forward or backward), the + " result should be the prop on the first line (the line with 'start' set to 1). + call cursor(3,1) + let result = prop_find({'type': 'prop_name'}, 'f') + unlet result.length + call assert_equal(expected[1], result) + let result = prop_find({'type': 'prop_name'}, 'b') + unlet result.length + call assert_equal(expected[1], result) + + " with skipstart set to true, if the start position is anywhere between the + " start and end lines of a text prop (searching forward or backward), all lines + " of the prop will be skipped. + let result = prop_find({'type': 'prop_name', 'skipstart': 1}, 'b') + call assert_equal(expected[0], result) + let result = prop_find({'type': 'prop_name', 'skipstart': 1}, 'f') + call assert_equal(expected[2], result) + + " Use skipstart to search through all props with type name 'prop_name'. + " First forward... + let lnum = 1 + let col = 1 + let i = 0 + for exp in expected + let result = prop_find({'type': 'prop_name', 'lnum': lnum, 'col': col, 'skipstart': 1}, 'f') + if !has_key(exp, "length") + unlet result.length + endif + call assert_equal(exp, result) + let lnum = result.lnum + let col = result.col + let i = i + 1 + endfor + + " ...then backwards. + let lnum = 6 + let col = 4 + let i = 2 + while i >= 0 + let result = prop_find({'type': 'prop_name', 'lnum': lnum, 'col': col, 'skipstart': 1}, 'b') + if !has_key(expected[i], "length") + unlet result.length + endif + call assert_equal(expected[i], result) + let lnum = result.lnum + let col = result.col + let i = i - 1 + endwhile + + " Starting from line 6 col 1 search backwards for prop with id 10. + call cursor(6,1) + let result = prop_find({'id': 10, 'skipstart': 1}, 'b') + call assert_equal(expected[0], result) + + " Starting from line 1 col 1 search forwards for prop with id 12. + call cursor(1,1) + let result = prop_find({'id': 12}, 'f') + call assert_equal(expected[2], result) + + " Search for a prop with an unknown id. + let result = prop_find({'id': 999}, 'f') + call assert_equal({}, result) + + " Search backwards from the proceeding position of the prop with id 11 + " (at line num 2 col 4). This should return an empty dict. + let result = prop_find({'id': 11, 'lnum': 2, 'col': 3}, 'b') + call assert_equal({}, result) + + " When lnum is given and col is omitted, use column 1. + let result = prop_find({'type': 'prop_name', 'lnum': 1}, 'f') + call assert_equal(expected[0], result) + + call prop_clear(1,6) + call prop_type_delete('prop_name') +endfunc + func Test_prop_add() new call AddPropTypes() diff --git a/src/textprop.c b/src/textprop.c index dfd30dd4f5..4ddb42e9d3 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -468,6 +468,24 @@ find_type_by_id(hashtab_T *ht, int id) return NULL; } +/* + * Fill 'dict' with text properties in 'prop'. + */ + static void +prop_fill_dict(dict_T *dict, textprop_T *prop, buf_T *buf) +{ + proptype_T *pt; + + dict_add_number(dict, "col", prop->tp_col); + dict_add_number(dict, "length", prop->tp_len); + dict_add_number(dict, "id", prop->tp_id); + dict_add_number(dict, "start", !(prop->tp_flags & TP_FLAG_CONT_PREV)); + dict_add_number(dict, "end", !(prop->tp_flags & TP_FLAG_CONT_NEXT)); + pt = text_prop_type_by_id(buf, prop->tp_type); + if (pt != NULL) + dict_add_string(dict, "type", pt->pt_name); +} + /* * Find a property type by ID in "buf" or globally. * Returns NULL if not found. @@ -536,6 +554,190 @@ f_prop_clear(typval_T *argvars, typval_T *rettv UNUSED) redraw_buf_later(buf, NOT_VALID); } +/* + * prop_find({props} [, {direction}]) + */ + void +f_prop_find(typval_T *argvars, typval_T *rettv) +{ + pos_T *cursor = &curwin->w_cursor; + dict_T *dict; + buf_T *buf = curbuf; + dictitem_T *di; + int lnum_start; + int start_pos_has_prop = 0; + int seen_end = 0; + int id = -1; + int type_id = -1; + int skipstart = 0; + int lnum = -1; + int col = -1; + int dir = 1; // 1 = forward, -1 = backward + + if (argvars[0].v_type != VAR_DICT || argvars[0].vval.v_dict == NULL) + { + emsg(_(e_invarg)); + return; + } + dict = argvars[0].vval.v_dict; + + if (get_bufnr_from_arg(&argvars[0], &buf) == FAIL) + return; + if (buf->b_ml.ml_mfp == NULL) + return; + + if (argvars[1].v_type != VAR_UNKNOWN) + { + char_u *dir_s = tv_get_string(&argvars[1]); + + if (*dir_s == 'b') + dir = -1; + else if (*dir_s != 'f') + { + emsg(_(e_invarg)); + return; + } + } + + di = dict_find(dict, (char_u *)"lnum", -1); + if (di != NULL) + lnum = tv_get_number(&di->di_tv); + + di = dict_find(dict, (char_u *)"col", -1); + if (di != NULL) + col = tv_get_number(&di->di_tv); + + if (lnum == -1) + { + lnum = cursor->lnum; + col = cursor->col + 1; + } + else if (col == -1) + col = 1; + + if (lnum < 1 || lnum > buf->b_ml.ml_line_count) + { + emsg(_(e_invrange)); + return; + } + + di = dict_find(dict, (char_u *)"skipstart", -1); + if (di != NULL) + skipstart = tv_get_number(&di->di_tv); + + if (dict_find(dict, (char_u *)"id", -1) != NULL) + id = dict_get_number(dict, (char_u *)"id"); + if (dict_find(dict, (char_u *)"type", -1)) + { + char_u *name = dict_get_string(dict, (char_u *)"type", FALSE); + proptype_T *type = lookup_prop_type(name, buf); + + if (type == NULL) + return; + type_id = type->pt_id; + } + if (id == -1 && type_id == -1) + { + emsg(_("E968: Need at least one of 'id' or 'type'")); + return; + } + + lnum_start = lnum; + + if (rettv_dict_alloc(rettv) == FAIL) + return; + + while (1) + { + char_u *text = ml_get_buf(buf, lnum, FALSE); + size_t textlen = STRLEN(text) + 1; + int count = (int)((buf->b_ml.ml_line_len - textlen) + / sizeof(textprop_T)); + int i; + textprop_T prop; + int prop_start; + int prop_end; + + for (i = 0; i < count; ++i) + { + mch_memmove(&prop, text + textlen + i * sizeof(textprop_T), + sizeof(textprop_T)); + + if (prop.tp_id == id || prop.tp_type == type_id) + { + // Check if the starting position has text props. + if (lnum_start == lnum) + { + if (col >= prop.tp_col + && (col <= prop.tp_col + prop.tp_len-1)) + start_pos_has_prop = 1; + } + else + { + // Not at the first line of the search so adjust col to + // indicate that we're continuing from prev/next line. + if (dir < 0) + col = buf->b_ml.ml_line_len; + else + col = 1; + } + + prop_start = !(prop.tp_flags & TP_FLAG_CONT_PREV); + prop_end = !(prop.tp_flags & TP_FLAG_CONT_NEXT); + if (!prop_start && prop_end && dir > 0) + seen_end = 1; + + // Skip lines without the start flag. + if (!prop_start) + { + // Always search backwards for start when search started + // on a prop and we're not skipping. + if (start_pos_has_prop && !skipstart) + dir = -1; + break; + } + + // If skipstart is true, skip the prop at start pos (even if + // continued from another line). + if (start_pos_has_prop && skipstart && !seen_end) + { + start_pos_has_prop = 0; + break; + } + + if (dir < 0) + { + if (col < prop.tp_col) + break; + } + else + { + if (col > prop.tp_col + prop.tp_len-1) + break; + } + + prop_fill_dict(rettv->vval.v_dict, &prop, buf); + dict_add_number(rettv->vval.v_dict, "lnum", lnum); + + return; + } + } + + if (dir > 0) + { + if (lnum >= buf->b_ml.ml_line_count) + break; + lnum++; + } + else + { + if (lnum <= 1) + break; + lnum--; + } + } +} + /* * prop_list({lnum} [, {bufnr}]) */ @@ -564,7 +766,6 @@ f_prop_list(typval_T *argvars, typval_T *rettv) / sizeof(textprop_T)); int i; textprop_T prop; - proptype_T *pt; for (i = 0; i < count; ++i) { @@ -574,15 +775,7 @@ f_prop_list(typval_T *argvars, typval_T *rettv) break; mch_memmove(&prop, text + textlen + i * sizeof(textprop_T), sizeof(textprop_T)); - dict_add_number(d, "col", prop.tp_col); - dict_add_number(d, "length", prop.tp_len); - dict_add_number(d, "id", prop.tp_id); - dict_add_number(d, "start", !(prop.tp_flags & TP_FLAG_CONT_PREV)); - dict_add_number(d, "end", !(prop.tp_flags & TP_FLAG_CONT_NEXT)); - pt = text_prop_type_by_id(buf, prop.tp_type); - if (pt != NULL) - dict_add_string(d, "type", pt->pt_name); - + prop_fill_dict(d, &prop, buf); list_append_dict(rettv->vval.v_list, d); } } diff --git a/src/version.c b/src/version.c index 815fc472af..d6386adb88 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 110, /**/ 109, /**/ From 9b4a15d5dba354d2e1e02871470bad103f34769a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 11 Jan 2020 16:05:23 +0100 Subject: [PATCH 37/42] patch 8.2.0111: VAR_SPECIAL is also used for booleans Problem: VAR_SPECIAL is also used for booleans. Solution: Add VAR_BOOL for better type checking. --- src/dict.c | 10 +++++----- src/eval.c | 16 +++++++++++++++- src/evalfunc.c | 25 +++++++++++-------------- src/evalvars.c | 5 +++-- src/if_lua.c | 3 ++- src/if_mzsch.c | 4 ++-- src/if_py_both.h | 16 +++++++++------- src/if_ruby.c | 6 +++--- src/json.c | 12 +++++++++--- src/popupmenu.c | 2 +- src/proto/dict.pro | 2 +- src/structs.h | 3 ++- src/testing.c | 3 ++- src/version.c | 2 ++ src/vim.h | 10 +++++----- src/viminfo.c | 22 +++++++++++++++------- 16 files changed, 87 insertions(+), 54 deletions(-) diff --git a/src/dict.c b/src/dict.c index a9a909bc2a..f3f3521672 100644 --- a/src/dict.c +++ b/src/dict.c @@ -345,14 +345,14 @@ dict_add(dict_T *d, dictitem_T *item) * Returns FAIL when out of memory and when key already exists. */ static int -dict_add_number_special(dict_T *d, char *key, varnumber_T nr, int special) +dict_add_number_special(dict_T *d, char *key, varnumber_T nr, vartype_T vartype) { dictitem_T *item; item = dictitem_alloc((char_u *)key); if (item == NULL) return FAIL; - item->di_tv.v_type = special ? VAR_SPECIAL : VAR_NUMBER; + item->di_tv.v_type = vartype; item->di_tv.vval.v_number = nr; if (dict_add(d, item) == FAIL) { @@ -369,7 +369,7 @@ dict_add_number_special(dict_T *d, char *key, varnumber_T nr, int special) int dict_add_number(dict_T *d, char *key, varnumber_T nr) { - return dict_add_number_special(d, key, nr, FALSE); + return dict_add_number_special(d, key, nr, VAR_NUMBER); } /* @@ -377,9 +377,9 @@ dict_add_number(dict_T *d, char *key, varnumber_T nr) * Returns FAIL when out of memory and when key already exists. */ int -dict_add_special(dict_T *d, char *key, varnumber_T nr) +dict_add_bool(dict_T *d, char *key, varnumber_T nr) { - return dict_add_number_special(d, key, nr, TRUE); + return dict_add_number_special(d, key, nr, VAR_BOOL); } /* diff --git a/src/eval.c b/src/eval.c index f8ba4dffa0..48357d441d 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1246,7 +1246,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op) // Can't do anything with a Funcref, Dict, v:true on the right. if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT - && tv2->v_type != VAR_SPECIAL) + && tv2->v_type != VAR_BOOL && tv2->v_type != VAR_SPECIAL) { switch (tv1->v_type) { @@ -1254,6 +1254,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op) case VAR_DICT: case VAR_FUNC: case VAR_PARTIAL: + case VAR_BOOL: case VAR_SPECIAL: case VAR_JOB: case VAR_CHANNEL: @@ -3016,6 +3017,7 @@ eval_index( emsg(_(e_float_as_string)); return FAIL; #endif + case VAR_BOOL: case VAR_SPECIAL: case VAR_JOB: case VAR_CHANNEL: @@ -3131,6 +3133,7 @@ eval_index( case VAR_FUNC: case VAR_PARTIAL: case VAR_FLOAT: + case VAR_BOOL: case VAR_SPECIAL: case VAR_JOB: case VAR_CHANNEL: @@ -3777,6 +3780,7 @@ tv_equal( s2 = tv_get_string_buf(tv2, buf2); return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0); + case VAR_BOOL: case VAR_SPECIAL: return tv1->vval.v_number == tv2->vval.v_number; @@ -4531,6 +4535,7 @@ echo_string_core( break; #endif + case VAR_BOOL: case VAR_SPECIAL: *tofree = NULL; r = (char_u *)get_var_special_name(tv->vval.v_number); @@ -5359,6 +5364,7 @@ free_tv(typval_T *varp) case VAR_NUMBER: case VAR_FLOAT: case VAR_UNKNOWN: + case VAR_BOOL: case VAR_SPECIAL: break; } @@ -5399,6 +5405,7 @@ clear_tv(typval_T *varp) varp->vval.v_dict = NULL; break; case VAR_NUMBER: + case VAR_BOOL: case VAR_SPECIAL: varp->vval.v_number = 0; break; @@ -5480,6 +5487,7 @@ tv_get_number_chk(typval_T *varp, int *denote) case VAR_DICT: emsg(_("E728: Using a Dictionary as a Number")); break; + case VAR_BOOL: case VAR_SPECIAL: return varp->vval.v_number == VVAL_TRUE ? 1 : 0; case VAR_JOB: @@ -5529,6 +5537,9 @@ tv_get_float(typval_T *varp) case VAR_DICT: emsg(_("E894: Using a Dictionary as a Float")); break; + case VAR_BOOL: + emsg(_("E362: Using a boolean value as a Float")); + break; case VAR_SPECIAL: emsg(_("E907: Using a special value as a Float")); break; @@ -5618,6 +5629,7 @@ tv_get_string_buf_chk(typval_T *varp, char_u *buf) if (varp->vval.v_string != NULL) return varp->vval.v_string; return (char_u *)""; + case VAR_BOOL: case VAR_SPECIAL: STRCPY(buf, get_var_special_name(varp->vval.v_number)); return buf; @@ -5744,6 +5756,7 @@ copy_tv(typval_T *from, typval_T *to) switch (from->v_type) { case VAR_NUMBER: + case VAR_BOOL: case VAR_SPECIAL: to->vval.v_number = from->vval.v_number; break; @@ -5850,6 +5863,7 @@ item_copy( case VAR_STRING: case VAR_FUNC: case VAR_PARTIAL: + case VAR_BOOL: case VAR_SPECIAL: case VAR_JOB: case VAR_CHANNEL: diff --git a/src/evalfunc.c b/src/evalfunc.c index 003d3b9ff2..4465fc07c1 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -1067,7 +1067,7 @@ non_zero_arg(typval_T *argvars) { return ((argvars[0].v_type == VAR_NUMBER && argvars[0].vval.v_number != 0) - || (argvars[0].v_type == VAR_SPECIAL + || (argvars[0].v_type == VAR_BOOL && argvars[0].vval.v_number == VVAL_TRUE) || (argvars[0].v_type == VAR_STRING && argvars[0].vval.v_string != NULL @@ -1811,6 +1811,7 @@ f_empty(typval_T *argvars, typval_T *rettv) n = argvars[0].vval.v_dict == NULL || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0; break; + case VAR_BOOL: case VAR_SPECIAL: n = argvars[0].vval.v_number != VVAL_TRUE; break; @@ -4318,6 +4319,7 @@ f_len(typval_T *argvars, typval_T *rettv) rettv->vval.v_number = dict_len(argvars[0].vval.v_dict); break; case VAR_UNKNOWN: + case VAR_BOOL: case VAR_SPECIAL: case VAR_FLOAT: case VAR_FUNC: @@ -8341,20 +8343,15 @@ f_type(typval_T *argvars, typval_T *rettv) switch (argvars[0].v_type) { - case VAR_NUMBER: n = VAR_TYPE_NUMBER; break; - case VAR_STRING: n = VAR_TYPE_STRING; break; + case VAR_NUMBER: n = VAR_TYPE_NUMBER; break; + case VAR_STRING: n = VAR_TYPE_STRING; break; case VAR_PARTIAL: - case VAR_FUNC: n = VAR_TYPE_FUNC; break; - case VAR_LIST: n = VAR_TYPE_LIST; break; - case VAR_DICT: n = VAR_TYPE_DICT; break; - case VAR_FLOAT: n = VAR_TYPE_FLOAT; break; - case VAR_SPECIAL: - if (argvars[0].vval.v_number == VVAL_FALSE - || argvars[0].vval.v_number == VVAL_TRUE) - n = VAR_TYPE_BOOL; - else - n = VAR_TYPE_NONE; - break; + case VAR_FUNC: n = VAR_TYPE_FUNC; break; + case VAR_LIST: n = VAR_TYPE_LIST; break; + case VAR_DICT: n = VAR_TYPE_DICT; break; + case VAR_FLOAT: n = VAR_TYPE_FLOAT; break; + case VAR_BOOL: n = VAR_TYPE_BOOL; break; + case VAR_SPECIAL: n = VAR_TYPE_NONE; break; case VAR_JOB: n = VAR_TYPE_JOB; break; case VAR_CHANNEL: n = VAR_TYPE_CHANNEL; break; case VAR_BLOB: n = VAR_TYPE_BLOB; break; diff --git a/src/evalvars.c b/src/evalvars.c index 6ec5c25dce..fbe23c4f16 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -118,8 +118,8 @@ static struct vimvar {VV_NAME("option_command", VAR_STRING), VV_RO}, {VV_NAME("option_type", VAR_STRING), VV_RO}, {VV_NAME("errors", VAR_LIST), 0}, - {VV_NAME("false", VAR_SPECIAL), VV_RO}, - {VV_NAME("true", VAR_SPECIAL), VV_RO}, + {VV_NAME("false", VAR_BOOL), VV_RO}, + {VV_NAME("true", VAR_BOOL), VV_RO}, {VV_NAME("null", VAR_SPECIAL), VV_RO}, {VV_NAME("none", VAR_SPECIAL), VV_RO}, {VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO}, @@ -1675,6 +1675,7 @@ item_lock(typval_T *tv, int deep, int lock) case VAR_FUNC: case VAR_PARTIAL: case VAR_FLOAT: + case VAR_BOOL: case VAR_SPECIAL: case VAR_JOB: case VAR_CHANNEL: diff --git a/src/if_lua.c b/src/if_lua.c index 9b03c97aa8..b80b6c9e26 100644 --- a/src/if_lua.c +++ b/src/if_lua.c @@ -535,6 +535,7 @@ luaV_pushtypval(lua_State *L, typval_T *tv) case VAR_DICT: luaV_pushdict(L, tv->vval.v_dict); break; + case VAR_BOOL: case VAR_SPECIAL: if (tv->vval.v_number <= VVAL_TRUE) lua_pushinteger(L, (int) tv->vval.v_number); @@ -564,7 +565,7 @@ luaV_totypval(lua_State *L, int pos, typval_T *tv) switch (lua_type(L, pos)) { case LUA_TBOOLEAN: - tv->v_type = VAR_SPECIAL; + tv->v_type = VAR_BOOL; tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos); break; case LUA_TNIL: diff --git a/src/if_mzsch.c b/src/if_mzsch.c index bf0157a59e..e31d0e110c 100644 --- a/src/if_mzsch.c +++ b/src/if_mzsch.c @@ -3136,7 +3136,7 @@ vim_to_mzscheme_impl(typval_T *vim_value, int depth, Scheme_Hash_Table *visited) MZ_GC_UNREG(); } } - else if (vim_value->v_type == VAR_SPECIAL) + else if (vim_value->v_type == VAR_BOOL || vim_value->v_type == VAR_SPECIAL) { if (vim_value->vval.v_number <= VVAL_TRUE) result = scheme_make_integer((long)vim_value->vval.v_number); @@ -3218,7 +3218,7 @@ mzscheme_to_vim_impl(Scheme_Object *obj, typval_T *tv, int depth, } else if (SCHEME_BOOLP(obj)) { - tv->v_type = VAR_SPECIAL; + tv->v_type = VAR_BOOL; tv->vval.v_number = SCHEME_TRUEP(obj); } # ifdef FEAT_FLOAT diff --git a/src/if_py_both.h b/src/if_py_both.h index d816386558..af4b98dd06 100644 --- a/src/if_py_both.h +++ b/src/if_py_both.h @@ -844,23 +844,24 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict) } } } - else if (our_tv->v_type == VAR_SPECIAL) + else if (our_tv->v_type == VAR_BOOL) { if (our_tv->vval.v_number == VVAL_FALSE) { ret = Py_False; Py_INCREF(ret); } - else if (our_tv->vval.v_number == VVAL_TRUE) + else { ret = Py_True; Py_INCREF(ret); } - else - { - Py_INCREF(Py_None); - ret = Py_None; - } + return ret; + } + else if (our_tv->v_type == VAR_SPECIAL) + { + Py_INCREF(Py_None); + ret = Py_None; return ret; } else if (our_tv->v_type == VAR_BLOB) @@ -6389,6 +6390,7 @@ ConvertToPyObject(typval_T *tv) case VAR_JOB: Py_INCREF(Py_None); return Py_None; + case VAR_BOOL: case VAR_SPECIAL: switch (tv->vval.v_number) { diff --git a/src/if_ruby.c b/src/if_ruby.c index 68d55821fc..7f2a7d265e 100644 --- a/src/if_ruby.c +++ b/src/if_ruby.c @@ -1183,7 +1183,7 @@ vim_to_ruby(typval_T *tv) } } } - else if (tv->v_type == VAR_SPECIAL) + else if (tv->v_type == VAR_BOOL || tv->v_type == VAR_SPECIAL) { if (tv->vval.v_number == VVAL_TRUE) result = Qtrue; @@ -1827,11 +1827,11 @@ ruby_convert_to_vim_value(VALUE val, typval_T *rettv) rettv->vval.v_number = VVAL_NULL; break; case T_TRUE: - rettv->v_type = VAR_SPECIAL; + rettv->v_type = VAR_BOOL; rettv->vval.v_number = VVAL_TRUE; break; case T_FALSE: - rettv->v_type = VAR_SPECIAL; + rettv->v_type = VAR_BOOL; rettv->vval.v_number = VVAL_FALSE; break; case T_BIGNUM: diff --git a/src/json.c b/src/json.c index eedb6062af..64ef93fabb 100644 --- a/src/json.c +++ b/src/json.c @@ -193,11 +193,17 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options) switch (val->v_type) { - case VAR_SPECIAL: + case VAR_BOOL: switch (val->vval.v_number) { case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break; case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break; + } + break; + + case VAR_SPECIAL: + switch (val->vval.v_number) + { case VVAL_NONE: if ((options & JSON_JS) != 0 && (options & JSON_NO_NONE) == 0) // empty item @@ -818,7 +824,7 @@ json_decode_item(js_read_T *reader, typval_T *res, int options) reader->js_used += 5; if (cur_item != NULL) { - cur_item->v_type = VAR_SPECIAL; + cur_item->v_type = VAR_BOOL; cur_item->vval.v_number = VVAL_FALSE; } retval = OK; @@ -829,7 +835,7 @@ json_decode_item(js_read_T *reader, typval_T *res, int options) reader->js_used += 4; if (cur_item != NULL) { - cur_item->v_type = VAR_SPECIAL; + cur_item->v_type = VAR_BOOL; cur_item->vval.v_number = VVAL_TRUE; } retval = OK; diff --git a/src/popupmenu.c b/src/popupmenu.c index cccde47ada..0e4f9fef07 100644 --- a/src/popupmenu.c +++ b/src/popupmenu.c @@ -1076,7 +1076,7 @@ pum_set_event_info(dict_T *dict) dict_add_number(dict, "row", pum_row); dict_add_number(dict, "col", pum_col); dict_add_number(dict, "size", pum_size); - dict_add_special(dict, "scrollbar", pum_scrollbar ? VVAL_TRUE : VVAL_FALSE); + dict_add_bool(dict, "scrollbar", pum_scrollbar ? VVAL_TRUE : VVAL_FALSE); } #endif diff --git a/src/proto/dict.pro b/src/proto/dict.pro index 75519a4047..d9b35c3091 100644 --- a/src/proto/dict.pro +++ b/src/proto/dict.pro @@ -14,7 +14,7 @@ void dictitem_free(dictitem_T *item); dict_T *dict_copy(dict_T *orig, int deep, int copyID); int dict_add(dict_T *d, dictitem_T *item); int dict_add_number(dict_T *d, char *key, varnumber_T nr); -int dict_add_special(dict_T *d, char *key, varnumber_T nr); +int dict_add_bool(dict_T *d, char *key, varnumber_T nr); int dict_add_string(dict_T *d, char *key, char_u *str); int dict_add_string_len(dict_T *d, char *key, char_u *str, int len); int dict_add_list(dict_T *d, char *key, list_T *list); diff --git a/src/structs.h b/src/structs.h index 5f32e1d60d..ffd6734e42 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1313,7 +1313,8 @@ typedef enum VAR_LIST, // "v_list" is used VAR_DICT, // "v_dict" is used VAR_FLOAT, // "v_float" is used - VAR_SPECIAL, // "v_number" is used + VAR_BOOL, // "v_number" is VVAL_FALSE or VVAL_TRUE + VAR_SPECIAL, // "v_number" is VVAL_NONE or VVAL_NULL VAR_JOB, // "v_job" is used VAR_CHANNEL, // "v_channel" is used VAR_BLOB, // "v_blob" is used diff --git a/src/testing.c b/src/testing.c index 3e6ba8e03e..ac9beea435 100644 --- a/src/testing.c +++ b/src/testing.c @@ -222,7 +222,7 @@ assert_bool(typval_T *argvars, int isTrue) int error = FALSE; garray_T ga; - if (argvars[0].v_type == VAR_SPECIAL + if (argvars[0].v_type == VAR_BOOL && argvars[0].vval.v_number == (isTrue ? VVAL_TRUE : VVAL_FALSE)) return 0; if (argvars[0].v_type != VAR_NUMBER @@ -760,6 +760,7 @@ f_test_refcount(typval_T *argvars, typval_T *rettv) case VAR_UNKNOWN: case VAR_NUMBER: case VAR_FLOAT: + case VAR_BOOL: case VAR_SPECIAL: case VAR_STRING: break; diff --git a/src/version.c b/src/version.c index d6386adb88..7941733cff 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 111, /**/ 110, /**/ diff --git a/src/vim.h b/src/vim.h index 1fd24ad3fd..16949ae291 100644 --- a/src/vim.h +++ b/src/vim.h @@ -2019,11 +2019,11 @@ typedef int sock_T; #define VV_ARGV 93 #define VV_LEN 94 // number of v: vars -// used for v_number in VAR_SPECIAL -#define VVAL_FALSE 0L -#define VVAL_TRUE 1L -#define VVAL_NONE 2L -#define VVAL_NULL 3L +// used for v_number in VAR_BOOL and VAR_SPECIAL +#define VVAL_FALSE 0L // VAR_BOOL +#define VVAL_TRUE 1L // VAR_BOOL +#define VVAL_NONE 2L // VAR_SPECIAL +#define VVAL_NULL 3L // VAR_SPECIAL // Type values for type(). #define VAR_TYPE_NUMBER 0 diff --git a/src/viminfo.c b/src/viminfo.c index 308a9a6097..24cd4f7133 100644 --- a/src/viminfo.c +++ b/src/viminfo.c @@ -1233,7 +1233,12 @@ read_viminfo_varlist(vir_T *virp, int writing) (void)string2float(tab + 1, &tv.vval.v_float); #endif else + { tv.vval.v_number = atol((char *)tab + 1); + if (type == VAR_SPECIAL && (tv.vval.v_number == VVAL_FALSE + || tv.vval.v_number == VVAL_TRUE)) + tv.v_type = VAR_BOOL; + } if (type == VAR_DICT || type == VAR_LIST) { typval_T *etv = eval_expr(tv.vval.v_string, NULL); @@ -1312,12 +1317,13 @@ write_viminfo_varlist(FILE *fp) { switch (this_var->di_tv.v_type) { - case VAR_STRING: s = "STR"; break; - case VAR_NUMBER: s = "NUM"; break; - case VAR_FLOAT: s = "FLO"; break; - case VAR_DICT: s = "DIC"; break; - case VAR_LIST: s = "LIS"; break; - case VAR_BLOB: s = "BLO"; break; + case VAR_STRING: s = "STR"; break; + case VAR_NUMBER: s = "NUM"; break; + case VAR_FLOAT: s = "FLO"; break; + case VAR_DICT: s = "DIC"; break; + case VAR_LIST: s = "LIS"; break; + case VAR_BLOB: s = "BLO"; break; + case VAR_BOOL: s = "XPL"; break; // backwards compat. case VAR_SPECIAL: s = "XPL"; break; case VAR_UNKNOWN: @@ -1328,8 +1334,10 @@ write_viminfo_varlist(FILE *fp) continue; } fprintf(fp, "!%s\t%s\t", this_var->di_key, s); - if (this_var->di_tv.v_type == VAR_SPECIAL) + if (this_var->di_tv.v_type == VAR_BOOL + || this_var->di_tv.v_type == VAR_SPECIAL) { + // do not use "v:true" but "1" sprintf((char *)numbuf, "%ld", (long)this_var->di_tv.vval.v_number); p = numbuf; From 02ad46394e8f887b60fda994f8a5da2ac1937b23 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 12 Jan 2020 13:48:18 +0100 Subject: [PATCH 38/42] patch 8.2.0112: illegal memory access when using 'cindent' Problem: Illegal memory access when using 'cindent'. Solution: Check for NUL byte. (Dominique Pelle, closes #5470) --- src/cindent.c | 2 ++ src/testdir/test_cindent.vim | 9 +++++++++ src/version.c | 2 ++ 3 files changed, 13 insertions(+) diff --git a/src/cindent.c b/src/cindent.c index c7caed68f1..3dc7b16354 100644 --- a/src/cindent.c +++ b/src/cindent.c @@ -582,6 +582,8 @@ cin_iscase( for (s += 4; *s; ++s) { s = cin_skipcomment(s); + if (*s == NUL) + break; if (*s == ':') { if (s[1] == ':') // skip over "::" for C++ diff --git a/src/testdir/test_cindent.vim b/src/testdir/test_cindent.vim index 2cb3f24b7a..2d78be1ad9 100644 --- a/src/testdir/test_cindent.vim +++ b/src/testdir/test_cindent.vim @@ -5251,4 +5251,13 @@ func Test_cindent_56() enew! | close endfunc +" this was going beyond the end of the line. +func Test_cindent_case() + new + call setline(1, "case x: // x") + set cindent + norm! f:a: + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 7941733cff..508db61ef0 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 112, /**/ 111, /**/ From 9b24dfcb9f676e7f7a09a9062f0d05b2104a87eb Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 12 Jan 2020 15:46:08 +0100 Subject: [PATCH 39/42] patch 8.2.0113: "make cmdidxs" fails Problem: "make cmdidxs" fails. Solution: Allow address for ":cquit". Add --not-a-term to avoid a delay. --- src/Make_cyg_ming.mak | 2 +- src/Make_mvc.mak | 2 +- src/Makefile | 2 +- src/ex_cmds.h | 2 +- src/version.c | 2 ++ 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index f9c795bfef..f89d8dd366 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -1085,7 +1085,7 @@ endif # If this fails because you don't have Vim yet, first build and install Vim # without changes. cmdidxs: ex_cmds.h - vim --clean -X -u create_cmdidxs.vim + vim --clean -X --not-a-term -u create_cmdidxs.vim ########################################################################### INCL = vim.h alloc.h ascii.h ex_cmds.h feature.h globals.h \ diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index eb71296146..5704eac0f0 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -1417,7 +1417,7 @@ clean: testclean # If this fails because you don't have Vim yet, first build and install Vim # without changes. cmdidxs: ex_cmds.h - vim --clean -X -u create_cmdidxs.vim + vim --clean -X --not-a-term -u create_cmdidxs.vim test: cd testdir diff --git a/src/Makefile b/src/Makefile index 1c7094098e..08a3277543 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2064,7 +2064,7 @@ autoconf: # If this fails because you don't have Vim yet, first build and install Vim # without changes. cmdidxs: ex_cmds.h - vim --clean -X -u create_cmdidxs.vim + vim --clean -X --not-a-term -u create_cmdidxs.vim # The normal command to compile a .c file to its .o file. diff --git a/src/ex_cmds.h b/src/ex_cmds.h index 928b1100d8..36a8ad4c2c 100644 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -408,7 +408,7 @@ EXCMD(CMD_cpfile, "cpfile", ex_cnext, ADDR_OTHER), EXCMD(CMD_cquit, "cquit", ex_cquit, EX_RANGE|EX_COUNT|EX_ZEROR|EX_TRLBAR|EX_BANG, - ADDR_NONE), + ADDR_UNSIGNED), EXCMD(CMD_crewind, "crewind", ex_cc, EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG, ADDR_UNSIGNED), diff --git a/src/version.c b/src/version.c index 508db61ef0..ba4fa7f7e4 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 113, /**/ 112, /**/ From 7ebcba61b20d25d23109fff73d0346ad44ba1b3b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 12 Jan 2020 17:42:55 +0100 Subject: [PATCH 40/42] patch 8.2.0114: info about sourced scripts is scattered Problem: Info about sourced scripts is scattered. Solution: Use scriptitem_T for info about a script, including s: variables. Drop ga_scripts. --- src/eval.c | 3 +-- src/evalvars.c | 60 +++++++++++------------------------------------- src/scriptfile.c | 14 +++++++---- src/structs.h | 19 ++++++++++++++- src/version.c | 2 ++ 5 files changed, 45 insertions(+), 53 deletions(-) diff --git a/src/eval.c b/src/eval.c index 48357d441d..fe6dee1f1b 100644 --- a/src/eval.c +++ b/src/eval.c @@ -149,8 +149,7 @@ eval_init(void) eval_clear(void) { evalvars_clear(); - - free_scriptnames(); + free_scriptnames(); // must come after evalvars_clear(). free_locales(); // autoloaded script names diff --git a/src/evalvars.c b/src/evalvars.c index fbe23c4f16..d359c7f44c 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -163,18 +163,7 @@ static dict_T vimvardict; // Dictionary with v: variables // for VIM_VERSION_ defines #include "version.h" -/* - * Array to hold the hashtab with variables local to each sourced script. - * Each item holds a variable (nameless) that points to the dict_T. - */ -typedef struct -{ - dictitem_T sv_var; - dict_T sv_dict; -} scriptvar_T; - -static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL}; -#define SCRIPT_SV(id) (((scriptvar_T **)ga_scripts.ga_data)[(id) - 1]) +#define SCRIPT_SV(id) (SCRIPT_ITEM(id).sn_vars) #define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab) static void ex_let_const(exarg_T *eap, int is_const); @@ -289,14 +278,12 @@ evalvars_clear(void) // global variables vars_clear(&globvarht); - // Script-local variables. First clear all the variables and in a second - // loop free the scriptvar_T, because a variable in one script might hold - // a reference to the whole scope of another script. - for (i = 1; i <= ga_scripts.ga_len; ++i) + // Script-local variables. Clear all the variables here. + // The scriptvar_T is cleared later in free_scriptnames(), because a + // variable in one script might hold a reference to the whole scope of + // another script. + for (i = 1; i <= script_items.ga_len; ++i) vars_clear(&SCRIPT_VARS(i)); - for (i = 1; i <= ga_scripts.ga_len; ++i) - vim_free(SCRIPT_SV(i)); - ga_clear(&ga_scripts); } #endif @@ -318,7 +305,7 @@ garbage_collect_scriptvars(int copyID) int i; int abort = FALSE; - for (i = 1; i <= ga_scripts.ga_len; ++i) + for (i = 1; i <= script_items.ga_len; ++i) abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL); return abort; @@ -538,7 +525,7 @@ list_vim_vars(int *first) static void list_script_vars(int *first) { - if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len) + if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) list_hashtable_vars(&SCRIPT_VARS(current_sctx.sc_sid), "s:", FALSE, first); } @@ -2433,7 +2420,7 @@ find_var_ht(char_u *name, char_u **varname) return get_funccal_local_ht(); if (*name == 's' // script variable && current_sctx.sc_sid > 0 - && current_sctx.sc_sid <= ga_scripts.ga_len) + && current_sctx.sc_sid <= script_items.ga_len) return &SCRIPT_VARS(current_sctx.sc_sid); return NULL; } @@ -2461,32 +2448,13 @@ get_var_value(char_u *name) void new_script_vars(scid_T id) { - int i; - hashtab_T *ht; scriptvar_T *sv; - if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK) - { - // Re-allocating ga_data means that an ht_array pointing to - // ht_smallarray becomes invalid. We can recognize this: ht_mask is - // at its init value. Also reset "v_dict", it's always the same. - for (i = 1; i <= ga_scripts.ga_len; ++i) - { - ht = &SCRIPT_VARS(i); - if (ht->ht_mask == HT_INIT_SIZE - 1) - ht->ht_array = ht->ht_smallarray; - sv = SCRIPT_SV(i); - sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict; - } - - while (ga_scripts.ga_len < id) - { - sv = SCRIPT_SV(ga_scripts.ga_len + 1) = - ALLOC_CLEAR_ONE(scriptvar_T); - init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); - ++ga_scripts.ga_len; - } - } + sv = ALLOC_CLEAR_ONE(scriptvar_T); + if (sv == NULL) + return; + init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); + SCRIPT_ITEM(id).sn_vars = sv; } /* diff --git a/src/scriptfile.c b/src/scriptfile.c index a1755416b4..a574bf665b 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1236,7 +1236,7 @@ do_source( save_current_sctx = current_sctx; current_sctx.sc_lnum = 0; - current_sctx.sc_version = 1; + current_sctx.sc_version = 1; // default script version // Check if this script was sourced before to finds its SID. // If it's new, generate a new SID. @@ -1272,6 +1272,10 @@ do_source( { ++script_items.ga_len; SCRIPT_ITEM(script_items.ga_len).sn_name = NULL; + SCRIPT_ITEM(script_items.ga_len).sn_version = 1; + + // Allocate the local script variables to use for this script. + new_script_vars(script_items.ga_len); # ifdef FEAT_PROFILE SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE; # endif @@ -1289,9 +1293,6 @@ do_source( else si->sn_dev_valid = FALSE; # endif - - // Allocate the local script variables to use for this script. - new_script_vars(current_sctx.sc_sid); } # ifdef FEAT_PROFILE @@ -1483,6 +1484,8 @@ free_scriptnames(void) for (i = script_items.ga_len; i > 0; --i) { + // the variables themselves are cleared in evalvars_clear() + vim_free(SCRIPT_ITEM(i).sn_vars); vim_free(SCRIPT_ITEM(i).sn_name); # ifdef FEAT_PROFILE ga_clear(&SCRIPT_ITEM(i).sn_prl_ga); @@ -1791,7 +1794,10 @@ ex_scriptversion(exarg_T *eap UNUSED) else if (nr > 4) semsg(_("E999: scriptversion not supported: %d"), nr); else + { current_sctx.sc_version = nr; + SCRIPT_ITEM(current_sctx.sc_sid).sn_version = nr; + } #endif } diff --git a/src/structs.h b/src/structs.h index ffd6734e42..7e1508eb9c 100644 --- a/src/structs.h +++ b/src/structs.h @@ -74,6 +74,8 @@ typedef struct VimMenu vimmenu_T; * function was defined, "sourcing_lnum" is the line number inside the * function. When stored with a function, mapping, option, etc. "sc_lnum" is * the line number in the script "sc_sid". + * + * sc_version is also here, for convenience. */ typedef struct { scid_T sc_sid; // script ID @@ -1565,14 +1567,29 @@ struct funccal_entry { #define HIKEY2UF(p) ((ufunc_T *)((p) - offsetof(ufunc_T, uf_name))) #define HI2UF(hi) HIKEY2UF((hi)->hi_key) +/* + * Holds the hashtab with variables local to each sourced script. + * Each item holds a variable (nameless) that points to the dict_T. + */ +typedef struct +{ + dictitem_T sv_var; + dict_T sv_dict; +} scriptvar_T; + /* * Growarray to store info about already sourced scripts. * For Unix also store the dev/ino, so that we don't have to stat() each * script when going through the list. */ -typedef struct scriptitem_S +typedef struct { + scriptvar_T *sn_vars; // stores s: variables for this script + char_u *sn_name; + + int sn_version; // :scriptversion + # ifdef UNIX int sn_dev_valid; dev_t sn_dev; diff --git a/src/version.c b/src/version.c index ba4fa7f7e4..0dac41e7cf 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 114, /**/ 113, /**/ From 9df53b62de86f544b41bef5e964b7fc8ae5231e3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 13 Jan 2020 20:40:51 +0100 Subject: [PATCH 41/42] patch 8.2.0115: byte2line() does not work correctly with text properties Problem: Byte2line() does not work correctly with text properties. (Billie Cleek) Solution: Take the bytes of the text properties into account. (closes #5334) --- src/memline.c | 36 ++++++++++++++++++++++++++++++----- src/testdir/test_textprop.vim | 18 +++++++++++++++++- src/version.c | 2 ++ 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/memline.c b/src/memline.c index 860438cfcd..2ac47af117 100644 --- a/src/memline.c +++ b/src/memline.c @@ -5738,7 +5738,7 @@ ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp) count = (long)(buf->b_ml.ml_locked_high) - (long)(buf->b_ml.ml_locked_low) + 1; start_idx = idx = curline - buf->b_ml.ml_locked_low; - if (idx == 0)// first line in block, text at the end + if (idx == 0) // first line in block, text at the end text_end = dp->db_txt_end; else text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK); @@ -5752,13 +5752,38 @@ ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp) } else { +#ifdef FEAT_PROP_POPUP + long textprop_total = 0; + long textprop_size = 0; + char_u *l1, *l2; +#endif + extra = 0; - while (offset >= size - + text_end - (int)((dp->db_index[idx]) & DB_INDEX_MASK) - + ffdos) + for (;;) { +#ifdef FEAT_PROP_POPUP + if (buf->b_has_textprop) + { + // compensate for the extra bytes taken by textprops + l1 = (char_u *)dp + ((dp->db_index[idx]) & DB_INDEX_MASK); + l2 = (char_u *)dp + (idx == 0 ? dp->db_txt_end + : ((dp->db_index[idx - 1]) & DB_INDEX_MASK)); + textprop_size = (l2 - l1) - (STRLEN(l1) + 1); + } +#endif + if (!(offset >= size + + text_end - (int)((dp->db_index[idx]) & DB_INDEX_MASK) +#ifdef FEAT_PROP_POPUP + - textprop_total - textprop_size +#endif + + ffdos)) + break; + if (ffdos) size++; +#ifdef FEAT_PROP_POPUP + textprop_total += textprop_size; +#endif if (idx == count - 1) { extra = 1; @@ -5776,7 +5801,8 @@ ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp) // lengths. len = 0; for (i = start_idx; i <= idx; ++i) - len += (int)STRLEN((char_u *)dp + ((dp->db_index[i]) & DB_INDEX_MASK)) + 1; + len += (int)STRLEN((char_u *)dp + + ((dp->db_index[i]) & DB_INDEX_MASK)) + 1; } else #endif diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim index ca6fd746e6..32001b3622 100644 --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -664,7 +664,7 @@ func Test_prop_multiline() call prop_type_delete('comment') endfunc -func Test_prop_byteoff() +func Test_prop_line2byte() call prop_type_add('comment', {'highlight': 'Directory'}) new call setline(1, ['line1', 'second line', '']) @@ -677,6 +677,22 @@ func Test_prop_byteoff() call prop_type_delete('comment') endfunc +func Test_prop_byte2line() + new + set ff=unix + call setline(1, ['one one', 'two two', 'three three', 'four four', 'five']) + call assert_equal(4, byte2line(line2byte(4))) + call assert_equal(5, byte2line(line2byte(5))) + + call prop_type_add('prop', {'highlight': 'Directory'}) + call prop_add(3, 1, {'length': 5, 'type': 'prop'}) + call assert_equal(4, byte2line(line2byte(4))) + call assert_equal(5, byte2line(line2byte(5))) + + bwipe! + call prop_type_delete('prop') +endfunc + func Test_prop_undo() new call prop_type_add('comment', {'highlight': 'Directory'}) diff --git a/src/version.c b/src/version.c index 0dac41e7cf..2d502beac6 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 115, /**/ 114, /**/ From c10b521628f2b073fa231defa26f23937c91724d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 13 Jan 2020 20:54:51 +0100 Subject: [PATCH 42/42] patch 8.2.0116: BufEnter autocmd not triggered on ":tab drop" Problem: BufEnter autocmd not triggered on ":tab drop". (Andy Stewart) Solution: Decrement autocmd_no_enter for the last file. (closes #1660, closes #5473) --- src/arglist.c | 13 +++++++++++-- src/testdir/test_tabpage.vim | 28 ++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/arglist.c b/src/arglist.c index b1a6a0b2f5..942da86c22 100644 --- a/src/arglist.c +++ b/src/arglist.c @@ -864,6 +864,7 @@ do_arg_all( // int opened_len; // length of opened[] int use_firstwin = FALSE; // use first window for arglist + int tab_drop_empty_window = FALSE; int split_ret = OK; int p_ea_save; alist_T *alist; // argument list to be used @@ -1027,13 +1028,16 @@ do_arg_all( last_curwin = curwin; last_curtab = curtab; win_enter(lastwin, FALSE); - // ":drop all" should re-use an empty window to avoid "--remote-tab" + // ":tab drop file" should re-use an empty window to avoid "--remote-tab" // leaving an empty tab page when executed locally. if (keep_tabs && BUFEMPTY() && curbuf->b_nwindows == 1 && curbuf->b_ffname == NULL && !curbuf->b_changed) + { use_firstwin = TRUE; + tab_drop_empty_window = TRUE; + } - for (i = 0; i < count && i < opened_len && !got_int; ++i) + for (i = 0; i < count && !got_int; ++i) { if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1) arg_had_last = TRUE; @@ -1067,6 +1071,9 @@ do_arg_all( } else if (split_ret == OK) { + // trigger events for tab drop + if (tab_drop_empty_window && i == count - 1) + --autocmd_no_enter; if (!use_firstwin) // split current window { p_ea_save = p_ea; @@ -1091,6 +1098,8 @@ do_arg_all( ((buf_hide(curwin->w_buffer) || bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0) + ECMD_OLDBUF, curwin); + if (tab_drop_empty_window && i == count - 1) + ++autocmd_no_enter; if (use_firstwin) ++autocmd_no_leave; use_firstwin = FALSE; diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim index 392eecbf79..bf721a0b61 100644 --- a/src/testdir/test_tabpage.vim +++ b/src/testdir/test_tabpage.vim @@ -222,6 +222,34 @@ function Test_tabpage_with_autocmd() 1tabonly! endfunction +" Test autocommands on tab drop +function Test_tabpage_with_autocmd_tab_drop() + augroup TestTabpageGroup + au! + autocmd TabEnter * call add(s:li, 'TabEnter') + autocmd WinEnter * call add(s:li, 'WinEnter') + autocmd BufEnter * call add(s:li, 'BufEnter') + autocmd TabLeave * call add(s:li, 'TabLeave') + autocmd WinLeave * call add(s:li, 'WinLeave') + autocmd BufLeave * call add(s:li, 'BufLeave') + augroup END + + let s:li = [] + tab drop test1 + call assert_equal(['BufLeave', 'BufEnter'], s:li) + + let s:li = [] + tab drop test2 test3 + call assert_equal([ + \ 'TabLeave', 'TabEnter', 'TabLeave', 'TabEnter', + \ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter', + \ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter'], s:li) + + autocmd! TestTabpageGroup + augroup! TestTabpageGroup + 1tabonly! +endfunction + function Test_tabpage_with_tab_modifier() CheckFeature quickfix diff --git a/src/version.c b/src/version.c index 2d502beac6..1e79e03c68 100644 --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 116, /**/ 115, /**/