From c841afff6a89592f23710c6da5b0fea89b240937 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 25 Jul 2020 14:11:55 +0200 Subject: [PATCH 0001/1384] patch 8.2.1289: crash when using a custom completion function Problem: Crash when using a custom completion function. Solution: Initialize all of the expand_T. (closes #6532) --- src/cmdexpand.c | 13 ++----------- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/cmdexpand.c b/src/cmdexpand.c index a10fff8b3d0df2..fe82ab7d4ae852 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -494,18 +494,9 @@ ExpandOne( void ExpandInit(expand_T *xp) { - xp->xp_pattern = NULL; - xp->xp_pattern_len = 0; + CLEAR_POINTER(xp); xp->xp_backslash = XP_BS_NONE; -#ifndef BACKSLASH_IN_FILENAME - xp->xp_shell = FALSE; -#endif xp->xp_numfiles = -1; - xp->xp_files = NULL; -#if defined(FEAT_EVAL) - xp->xp_arg = NULL; -#endif - xp->xp_line = NULL; } /* @@ -2425,7 +2416,7 @@ expand_shellcmd( # if defined(FEAT_EVAL) /* * Call "user_expand_func()" to invoke a user defined Vim script function and - * return the result (either a string or a List). + * return the result (either a string, a List or NULL). */ static void * call_user_expand_func( diff --git a/src/version.c b/src/version.c index 14044481aa47d4..0bd3cb20a3184e 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1289, /**/ 1288, /**/ From 925e9fd6339981c1015410e1b6a6dd19e34f36cc Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 25 Jul 2020 15:41:11 +0200 Subject: [PATCH 0002/1384] patch 8.2.1290: Vim9: cannot replace a global function Problem: Vim9: cannot replace a global function. Solution: Allow for "!" on a global function. (closes #6524) Also fix that :delfunc on a :def function only made it empty. --- src/testdir/test_vim9_script.vim | 48 ++++++++++++++++++++++++++++++++ src/userfunc.c | 15 ++++++---- src/version.c | 2 ++ 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 3e2ced0a93f3b1..f7d195ea834c43 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -468,6 +468,54 @@ def Test_delfunction() 'enddef', 'DoThat()', ], 'E1084:') + + # Check that global :def function can be replaced and deleted + let lines =<< trim END + vim9script + def g:Global(): string + return "yes" + enddef + assert_equal("yes", g:Global()) + def! g:Global(): string + return "no" + enddef + assert_equal("no", g:Global()) + delfunc g:Global + assert_false(exists('*g:Global')) + END + CheckScriptSuccess(lines) + + # Check that global function can be replaced by a :def function and deleted + lines =<< trim END + vim9script + func g:Global() + return "yes" + endfunc + assert_equal("yes", g:Global()) + def! g:Global(): string + return "no" + enddef + assert_equal("no", g:Global()) + delfunc g:Global + assert_false(exists('*g:Global')) + END + CheckScriptSuccess(lines) + + # Check that global :def function can be replaced by a function and deleted + lines =<< trim END + vim9script + def g:Global(): string + return "yes" + enddef + assert_equal("yes", g:Global()) + func! g:Global() + return "no" + endfunc + assert_equal("no", g:Global()) + delfunc g:Global + assert_false(exists('*g:Global')) + END + CheckScriptSuccess(lines) enddef func Test_wrong_type() diff --git a/src/userfunc.c b/src/userfunc.c index bf026d85792802..3e566f334a7413 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -1148,6 +1148,8 @@ func_clear_free(ufunc_T *fp, int force) func_clear(fp, force); if (force || fp->uf_dfunc_idx == 0) func_free(fp, force); + else + fp->uf_flags |= FC_DEAD; } @@ -2557,12 +2559,6 @@ def_function(exarg_T *eap, char_u *name_arg) char_u *heredoc_trimmed = NULL; int vim9script = in_vim9script(); - if (vim9script && eap->forceit) - { - emsg(_(e_nobang)); - return NULL; - } - /* * ":function" without argument: list functions. */ @@ -2732,6 +2728,13 @@ def_function(exarg_T *eap, char_u *name_arg) } p = skipwhite(p + 1); + // In Vim9 script only global functions can be redefined. + if (vim9script && eap->forceit && !is_global) + { + emsg(_(e_nobang)); + goto ret_free; + } + ga_init2(&newlines, (int)sizeof(char_u *), 3); if (!eap->skip && name_arg == NULL) diff --git a/src/version.c b/src/version.c index 0bd3cb20a3184e..20365a0a4530f3 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1290, /**/ 1289, /**/ From 24aa48b7a265c24e18f0f978dfe0255e138e2b90 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 25 Jul 2020 16:33:02 +0200 Subject: [PATCH 0003/1384] patch 8.2.1291: Vim9: type of varargs items is not checked Problem: Vim9: type of varargs items is not checked. Solution: Check the list item types. (closes #6523) --- src/testdir/test_vim9_func.vim | 50 +++++++++++++++++++++++++++++++++- src/version.c | 2 ++ src/vim9execute.c | 20 +++++++++++++- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index ef98583fe3c04a..49be8f97a2527e 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -164,7 +164,55 @@ def Test_call_def_varargs() assert_equal('one,foo', MyDefVarargs('one')) assert_equal('one,two', MyDefVarargs('one', 'two')) assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three')) - call CheckDefFailure(['MyDefVarargs("one", 22)'], 'E1013: argument 2: type mismatch, expected string but got number') + CheckDefFailure(['MyDefVarargs("one", 22)'], + 'E1013: argument 2: type mismatch, expected string but got number') + CheckDefFailure(['MyDefVarargs("one", "two", 123)'], + 'E1013: argument 3: type mismatch, expected string but got number') + + let lines =<< trim END + vim9script + def Func(...l: list) + echo l + enddef + Func('a', 'b', 'c') + END + CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + def Func(...l: list) + echo l + enddef + Func() + END + CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + def Func(...l: list) + echo l + enddef + Func(1, 2, 3) + END + CheckScriptFailure(lines, 'E1013:') + + lines =<< trim END + vim9script + def Func(...l: list) + echo l + enddef + Func('a', 9) + END + CheckScriptFailure(lines, 'E1013:') + + lines =<< trim END + vim9script + def Func(...l: list) + echo l + enddef + Func(1, 'a') + END + CheckScriptFailure(lines, 'E1013:') enddef let s:value = '' diff --git a/src/version.c b/src/version.c index 20365a0a4530f3..8934011f6557bc 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1291, /**/ 1290, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index ab8142d23cb449..e52df61ac136d1 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -755,9 +755,27 @@ call_def_function( argc -= vararg_count; if (exe_newlist(vararg_count, &ectx) == FAIL) goto failed_early; + + // Check the type of the list items. + tv = STACK_TV_BOT(-1); + if (ufunc->uf_va_type != NULL + && ufunc->uf_va_type->tt_member != &t_any + && tv->vval.v_list != NULL) + { + type_T *expected = ufunc->uf_va_type->tt_member; + listitem_T *li = tv->vval.v_list->lv_first; + + for (idx = 0; idx < vararg_count; ++idx) + { + if (check_typval_type(expected, &li->li_tv) == FAIL) + goto failed_early; + li = li->li_next; + } + } + if (defcount > 0) // Move varargs list to below missing default arguments. - *STACK_TV_BOT(defcount- 1) = *STACK_TV_BOT(-1); + *STACK_TV_BOT(defcount - 1) = *STACK_TV_BOT(-1); --ectx.ec_stack.ga_len; } From 2afc3b4f776a4fe2bb22d0a79e77012d79b4ec1e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 25 Jul 2020 16:53:12 +0200 Subject: [PATCH 0004/1384] patch 8.2.1292: AIDL filetype not recognized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: AIDL filetype not recognized. Solution: Add filetype detection. (Dominique Pellé, closes #6533) --- runtime/filetype.vim | 3 +++ src/testdir/test_filetype.vim | 1 + src/version.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 7c76b12ee38bb2..80ea2949cc1cfa 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -88,6 +88,9 @@ endif " AHDL au BufNewFile,BufRead *.tdf setf ahdl +" AIDL +au BufNewFile,BufRead *.aidl setf aidl + " AMPL au BufNewFile,BufRead *.run setf ampl diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 8ec8355c2461c2..2e517c0bb9753c 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -54,6 +54,7 @@ let s:filename_checks = { \ 'acedb': ['file.wrm'], \ 'ada': ['file.adb', 'file.ads', 'file.ada', 'file.gpr'], \ 'ahdl': ['file.tdf'], + \ 'aidl': ['file.aidl'], \ 'alsaconf': ['.asoundrc', '/usr/share/alsa/alsa.conf', '/etc/asound.conf'], \ 'aml': ['file.aml'], \ 'ampl': ['file.run'], diff --git a/src/version.c b/src/version.c index 8934011f6557bc..3611fe6a4b8897 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1292, /**/ 1291, /**/ From 2d6b20d6a9a034b39f79a7dbb889fb5d859583ae Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 25 Jul 2020 19:30:59 +0200 Subject: [PATCH 0005/1384] patch 8.2.1293: Vim9: error when using vim9script in TextYankPost Problem: Vim9: error when using vim9script in TextYankPost. Solution: Use EX_LOCKOK instead of the EX_CMDWIN flag for command that can be used when text is locked. (closes #6529) --- src/testdir/test_vim9_script.vim | 30 ++++++++++++++++++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 4 +++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index f7d195ea834c43..ac76e8d5bce047 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1708,6 +1708,10 @@ def Test_execute_cmd() assert_equal('execute-var-var', getline(1)) bwipe! + let n = true + execute 'echomsg' (n ? '"true"' : '"no"') + assert_match('^true$', Screenline(&lines)) + call CheckDefFailure(['execute xxx'], 'E1001:') call CheckDefFailure(['execute "cmd"# comment'], 'E488:') enddef @@ -2634,6 +2638,32 @@ def Test_vim9_copen() quit enddef +" test using a vim9script that is auto-loaded from an autocmd +def Test_vim9_autoload() + let lines =<< trim END + vim9script + def foo#test() + echomsg getreg('"') + enddef + END + + mkdir('Xdir/autoload', 'p') + writefile(lines, 'Xdir/autoload/foo.vim') + let save_rtp = &rtp + exe 'set rtp^=' .. getcwd() .. '/Xdir' + augroup test + autocmd TextYankPost * call foo#test() + augroup END + + normal Y + + augroup test + autocmd! + augroup END + delete('Xdir', 'rf') + &rtp = save_rtp +enddef + " Keep this last, it messes up highlighting. def Test_substitute_cmd() new diff --git a/src/version.c b/src/version.c index 3611fe6a4b8897..05f37526d4ed25 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1293, /**/ 1292, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 53bfb6c48e034e..746c9aa1a2d5b7 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3755,7 +3755,9 @@ compile_subscript( } } - if (*p == '(') + // Do not skip over white space to find the "(", "exeucte 'x' ()" is + // not a function call. + if (**arg == '(') { garray_T *stack = &cctx->ctx_type_stack; type_T *type; From 37394ff75270877a032422abcd079a6732a29730 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 25 Jul 2020 19:38:18 +0200 Subject: [PATCH 0006/1384] patch 8.2.1294: Vim9: error when using vim9script in TextYankPost Problem: Vim9: error when using vim9script in TextYankPost. Solution: Use EX_LOCKOK instead of the EX_CMDWIN flag for command that can be used when text is locked. (closes #6529) --- src/ex_cmds.h | 641 +++++++++++++++++++++++++------------------------ src/ex_docmd.c | 20 +- src/version.c | 2 + 3 files changed, 338 insertions(+), 325 deletions(-) diff --git a/src/ex_cmds.h b/src/ex_cmds.h index 1c1956239c0ba6..9ae85f0f31780c 100644 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -47,13 +47,14 @@ #define EX_BUFUNL 0x10000 // accepts unlisted buffer too #define EX_ARGOPT 0x20000 // allow "++opt=val" argument #define EX_SBOXOK 0x40000 // allowed in the sandbox -#define EX_CMDWIN 0x80000 // allowed in cmdline window; when missing - // disallows editing another buffer when - // curbuf_lock is set +#define EX_CMDWIN 0x80000 // allowed in cmdline window #define EX_MODIFY 0x100000 // forbidden in non-'modifiable' buffer #define EX_FLAGS 0x200000 // allow flags after count in argument #define EX_RESTRICT 0x400000 // forbidden in restricted mode #define EX_EXPAND 0x800000 // expands wildcards later +#define EX_LOCK_OK 0x1000000 // command can be executed when textlock is + // set; when missing disallows editing another + // buffer when curbuf_lock is set #define EX_FILES (EX_XFILE | EX_EXTRA) // multiple extra files allowed #define EX_FILE1 (EX_FILES | EX_NOSPC) // 1 file, defaults to current file @@ -109,13 +110,13 @@ enum CMD_index #endif { EXCMD(CMD_append, "append", ex_append, - EX_BANG|EX_RANGE|EX_ZEROR|EX_TRLBAR|EX_CMDWIN|EX_MODIFY, + EX_BANG|EX_RANGE|EX_ZEROR|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_abbreviate, "abbreviate", ex_abbreviate, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_abclear, "abclear", ex_abclear, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_aboveleft, "aboveleft", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, @@ -124,10 +125,10 @@ EXCMD(CMD_all, "all", ex_all, EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_amenu, "amenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_anoremenu, "anoremenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_args, "args", ex_args, EX_BANG|EX_FILES|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, @@ -154,16 +155,16 @@ EXCMD(CMD_argument, "argument", ex_argument, EX_BANG|EX_RANGE|EX_COUNT|EX_EXTRA|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_ARGUMENTS), EXCMD(CMD_ascii, "ascii", do_ascii, - EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_autocmd, "autocmd", ex_autocmd, - EX_BANG|EX_EXTRA|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_augroup, "augroup", ex_autocmd, - EX_BANG|EX_WORD1|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_aunmenu, "aunmenu", ex_menu, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_buffer, "buffer", ex_buffer, EX_BANG|EX_RANGE|EX_BUFNAME|EX_BUFUNL|EX_COUNT|EX_EXTRA|EX_CMDARG|EX_TRLBAR, @@ -175,13 +176,13 @@ EXCMD(CMD_ball, "ball", ex_buffer_all, EX_RANGE|EX_COUNT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_badd, "badd", ex_edit, - EX_NEEDARG|EX_FILE1|EX_CMDARG|EX_TRLBAR|EX_CMDWIN, + EX_NEEDARG|EX_FILE1|EX_CMDARG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_bdelete, "bdelete", ex_bunload, EX_BANG|EX_RANGE|EX_BUFNAME|EX_COUNT|EX_EXTRA|EX_TRLBAR, ADDR_BUFFERS), EXCMD(CMD_behave, "behave", ex_behave, - EX_BANG|EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_belowright, "belowright", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, @@ -208,22 +209,22 @@ EXCMD(CMD_brewind, "brewind", ex_brewind, EX_BANG|EX_RANGE|EX_CMDARG|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_break, "break", ex_break, - EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_breakadd, "breakadd", ex_breakadd, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_breakdel, "breakdel", ex_breakdel, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_breaklist, "breaklist", ex_breaklist, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_browse, "browse", ex_wrongmodifier, - EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN, + EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_buffers, "buffers", buflist_list, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_bufdo, "bufdo", ex_listdo, EX_BANG|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_RANGE|EX_DFLALL, @@ -235,7 +236,7 @@ EXCMD(CMD_bwipeout, "bwipeout", ex_bunload, EX_BANG|EX_RANGE|EX_BUFNAME|EX_BUFUNL|EX_COUNT|EX_EXTRA|EX_TRLBAR, ADDR_BUFFERS), EXCMD(CMD_change, "change", ex_change, - EX_BANG|EX_WHOLEFOLD|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_MODIFY, + EX_BANG|EX_WHOLEFOLD|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_cNext, "cNext", ex_cnext, EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG, @@ -244,10 +245,10 @@ EXCMD(CMD_cNfile, "cNfile", ex_cnext, EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG, ADDR_UNSIGNED), EXCMD(CMD_cabbrev, "cabbrev", ex_abbreviate, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_cabclear, "cabclear", ex_abclear, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_cabove, "cabove", ex_cbelow, EX_RANGE|EX_COUNT|EX_TRLBAR, @@ -265,10 +266,10 @@ EXCMD(CMD_cafter, "cafter", ex_cbelow, EX_RANGE|EX_COUNT|EX_TRLBAR, ADDR_UNSIGNED), EXCMD(CMD_call, "call", ex_call, - EX_RANGE|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_RANGE|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_catch, "catch", ex_catch, - EX_EXTRA|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_cbuffer, "cbuffer", ex_cbuffer, EX_BANG|EX_RANGE|EX_WORD1|EX_TRLBAR, @@ -289,13 +290,13 @@ EXCMD(CMD_cclose, "cclose", ex_cclose, EX_TRLBAR, ADDR_NONE), EXCMD(CMD_cd, "cd", ex_cd, - EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_cdo, "cdo", ex_listdo, EX_BANG|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_RANGE|EX_DFLALL, ADDR_QUICKFIX_VALID), EXCMD(CMD_center, "center", ex_align, - EX_TRLBAR|EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_MODIFY, + EX_TRLBAR|EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_cexpr, "cexpr", ex_cexpr, EX_NEEDARG|EX_WORD1|EX_NOTRLCOM|EX_BANG, @@ -319,13 +320,13 @@ EXCMD(CMD_cgetexpr, "cgetexpr", ex_cexpr, EX_NEEDARG|EX_WORD1|EX_NOTRLCOM, ADDR_NONE), EXCMD(CMD_chdir, "chdir", ex_cd, - EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_changes, "changes", ex_changes, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_checkpath, "checkpath", ex_checkpath, - EX_TRLBAR|EX_BANG|EX_CMDWIN, + EX_TRLBAR|EX_BANG|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_checktime, "checktime", ex_checktime, EX_RANGE|EX_BUFNAME|EX_COUNT|EX_EXTRA|EX_TRLBAR, @@ -334,25 +335,25 @@ EXCMD(CMD_chistory, "chistory", qf_history, EX_RANGE|EX_COUNT|EX_TRLBAR, ADDR_UNSIGNED), EXCMD(CMD_clist, "clist", qf_list, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_clast, "clast", ex_cc, EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG, ADDR_UNSIGNED), EXCMD(CMD_close, "close", ex_close, - EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_WINDOWS), EXCMD(CMD_clearjumps, "clearjumps", ex_clearjumps, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_cmap, "cmap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_cmapclear, "cmapclear", ex_mapclear, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_cmenu, "cmenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_cnext, "cnext", ex_cnext, EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG, @@ -364,40 +365,40 @@ EXCMD(CMD_cnfile, "cnfile", ex_cnext, EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG, ADDR_UNSIGNED), EXCMD(CMD_cnoremap, "cnoremap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_cnoreabbrev, "cnoreabbrev", ex_abbreviate, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_cnoremenu, "cnoremenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_copy, "copy", ex_copymove, - EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_MODIFY, + EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_colder, "colder", qf_age, EX_RANGE|EX_COUNT|EX_TRLBAR, ADDR_UNSIGNED), EXCMD(CMD_colorscheme, "colorscheme", ex_colorscheme, - EX_WORD1|EX_TRLBAR|EX_CMDWIN, + EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_command, "command", ex_command, - EX_EXTRA|EX_BANG|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_BANG|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_comclear, "comclear", ex_comclear, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_compiler, "compiler", ex_compiler, - EX_BANG|EX_TRLBAR|EX_WORD1|EX_CMDWIN, + EX_BANG|EX_TRLBAR|EX_WORD1|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_continue, "continue", ex_continue, - EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_confirm, "confirm", ex_wrongmodifier, - EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN, + EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_const, "const", ex_let, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_copen, "copen", ex_copen, EX_RANGE|EX_COUNT|EX_TRLBAR, @@ -421,43 +422,43 @@ EXCMD(CMD_cstag, "cstag", ex_cstag, EX_BANG|EX_TRLBAR|EX_WORD1, ADDR_NONE), EXCMD(CMD_cunmap, "cunmap", ex_unmap, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_cunabbrev, "cunabbrev", ex_abbreviate, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_cunmenu, "cunmenu", ex_menu, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_cwindow, "cwindow", ex_cwindow, EX_RANGE|EX_COUNT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_delete, "delete", ex_operators, - EX_RANGE|EX_WHOLEFOLD|EX_REGSTR|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_MODIFY, + EX_RANGE|EX_WHOLEFOLD|EX_REGSTR|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_delmarks, "delmarks", ex_delmarks, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_debug, "debug", ex_debug, - EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_debuggreedy, "debuggreedy", ex_debuggreedy, - EX_RANGE|EX_ZEROR|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_def, "def", ex_function, - EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_defcompile, "defcompile", ex_defcompile, - EX_SBOXOK|EX_CMDWIN|EX_TRLBAR, + EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_delcommand, "delcommand", ex_delcommand, - EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN, + EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_delfunction, "delfunction", ex_delfunction, - EX_BANG|EX_NEEDARG|EX_WORD1|EX_CMDWIN, + EX_BANG|EX_NEEDARG|EX_WORD1|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_display, "display", ex_display, - EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_diffupdate, "diffupdate", ex_diffupdate, EX_BANG|EX_TRLBAR, @@ -481,28 +482,28 @@ EXCMD(CMD_diffthis, "diffthis", ex_diffthis, EX_TRLBAR, ADDR_NONE), EXCMD(CMD_digraphs, "digraphs", ex_digraphs, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_disassemble, "disassemble", ex_disassemble, - EX_EXTRA|EX_NEEDARG|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_NEEDARG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_djump, "djump", ex_findpat, EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA, ADDR_LINES), EXCMD(CMD_dlist, "dlist", ex_findpat, - EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN, + EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_doautocmd, "doautocmd", ex_doautocmd, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_doautoall, "doautoall", ex_doautoall, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_drop, "drop", ex_drop, EX_FILES|EX_CMDARG|EX_NEEDARG|EX_ARGOPT|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_dsearch, "dsearch", ex_findpat, - EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN, + EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_dsplit, "dsplit", ex_findpat, EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA, @@ -511,64 +512,64 @@ EXCMD(CMD_edit, "edit", ex_edit, EX_BANG|EX_FILE1|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_earlier, "earlier", ex_later, - EX_TRLBAR|EX_EXTRA|EX_NOSPC|EX_CMDWIN, + EX_TRLBAR|EX_EXTRA|EX_NOSPC|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_echo, "echo", ex_echo, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_echoerr, "echoerr", ex_execute, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_echohl, "echohl", ex_echohl, - EX_EXTRA|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_echomsg, "echomsg", ex_execute, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_echon, "echon", ex_echo, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_else, "else", ex_else, - EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_elseif, "elseif", ex_else, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_emenu, "emenu", ex_emenu, - EX_NEEDARG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_RANGE|EX_CMDWIN, + EX_NEEDARG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_RANGE|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_endif, "endif", ex_endif, - EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_enddef, "enddef", ex_endfunction, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_endfunction, "endfunction", ex_endfunction, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_endfor, "endfor", ex_endwhile, - EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_endtry, "endtry", ex_endtry, - EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_endwhile, "endwhile", ex_endwhile, - EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_enew, "enew", ex_edit, EX_BANG|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_eval, "eval", ex_eval, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_ex, "ex", ex_edit, EX_BANG|EX_FILE1|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_execute, "execute", ex_execute, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_exit, "exit", ex_exit, - EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILE1|EX_ARGOPT|EX_DFLALL|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILE1|EX_ARGOPT|EX_DFLALL|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_export, "export", ex_export, EX_EXTRA|EX_NOTRLCOM, @@ -580,10 +581,10 @@ EXCMD(CMD_file, "file", ex_file, EX_RANGE|EX_ZEROR|EX_BANG|EX_FILE1|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_files, "files", buflist_list, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_filetype, "filetype", ex_filetype, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_filter, "filter", ex_wrongmodifier, EX_BANG|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, @@ -592,22 +593,22 @@ EXCMD(CMD_find, "find", ex_find, EX_RANGE|EX_BANG|EX_FILE1|EX_CMDARG|EX_ARGOPT|EX_TRLBAR|EX_NEEDARG, ADDR_OTHER), EXCMD(CMD_finally, "finally", ex_finally, - EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_finish, "finish", ex_finish, - EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_first, "first", ex_rewind, EX_EXTRA|EX_BANG|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_fixdel, "fixdel", do_fixdel, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_fold, "fold", ex_fold, - EX_RANGE|EX_WHOLEFOLD|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_foldclose, "foldclose", ex_foldopen, - EX_RANGE|EX_BANG|EX_WHOLEFOLD|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_RANGE|EX_BANG|EX_WHOLEFOLD|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_folddoopen, "folddoopen", ex_folddo, EX_RANGE|EX_DFLALL|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, @@ -616,19 +617,19 @@ EXCMD(CMD_folddoclosed, "folddoclosed", ex_folddo, EX_RANGE|EX_DFLALL|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, ADDR_LINES), EXCMD(CMD_foldopen, "foldopen", ex_foldopen, - EX_RANGE|EX_BANG|EX_WHOLEFOLD|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_RANGE|EX_BANG|EX_WHOLEFOLD|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_for, "for", ex_while, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_function, "function", ex_function, - EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_global, "global", ex_global, - EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_EXTRA|EX_DFLALL|EX_SBOXOK|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_EXTRA|EX_DFLALL|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_goto, "goto", ex_goto, - EX_RANGE|EX_COUNT|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_RANGE|EX_COUNT|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_grep, "grep", ex_make, EX_RANGE|EX_BANG|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_XFILE, @@ -637,10 +638,10 @@ EXCMD(CMD_grepadd, "grepadd", ex_make, EX_RANGE|EX_BANG|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_XFILE, ADDR_OTHER), EXCMD(CMD_gui, "gui", ex_gui, - EX_BANG|EX_FILES|EX_CMDARG|EX_ARGOPT|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILES|EX_CMDARG|EX_ARGOPT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_gvim, "gvim", ex_gui, - EX_BANG|EX_FILES|EX_CMDARG|EX_ARGOPT|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILES|EX_CMDARG|EX_ARGOPT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_help, "help", ex_help, EX_BANG|EX_EXTRA|EX_NOTRLCOM, @@ -655,85 +656,85 @@ EXCMD(CMD_helpgrep, "helpgrep", ex_helpgrep, EX_EXTRA|EX_NOTRLCOM|EX_NEEDARG, ADDR_NONE), EXCMD(CMD_helptags, "helptags", ex_helptags, - EX_NEEDARG|EX_FILES|EX_TRLBAR|EX_CMDWIN, + EX_NEEDARG|EX_FILES|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_hardcopy, "hardcopy", ex_hardcopy, EX_RANGE|EX_COUNT|EX_EXTRA|EX_EXPAND|EX_TRLBAR|EX_DFLALL|EX_BANG, ADDR_LINES), EXCMD(CMD_highlight, "highlight", ex_highlight, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_hide, "hide", ex_hide, EX_BANG|EX_RANGE|EX_COUNT|EX_EXTRA|EX_TRLBAR, ADDR_WINDOWS), EXCMD(CMD_history, "history", ex_history, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_insert, "insert", ex_append, - EX_BANG|EX_RANGE|EX_TRLBAR|EX_CMDWIN|EX_MODIFY, + EX_BANG|EX_RANGE|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_iabbrev, "iabbrev", ex_abbreviate, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_iabclear, "iabclear", ex_abclear, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_if, "if", ex_if, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_ijump, "ijump", ex_findpat, EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA, ADDR_LINES), EXCMD(CMD_ilist, "ilist", ex_findpat, - EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN, + EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_imap, "imap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_imapclear, "imapclear", ex_mapclear, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_imenu, "imenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_import, "import", ex_import, EX_EXTRA|EX_NOTRLCOM, ADDR_NONE), EXCMD(CMD_inoremap, "inoremap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_inoreabbrev, "inoreabbrev", ex_abbreviate, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_inoremenu, "inoremenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_intro, "intro", ex_intro, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_isearch, "isearch", ex_findpat, - EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN, + EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_isplit, "isplit", ex_findpat, EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA, ADDR_LINES), EXCMD(CMD_iunmap, "iunmap", ex_unmap, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_iunabbrev, "iunabbrev", ex_abbreviate, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_iunmenu, "iunmenu", ex_menu, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_join, "join", ex_join, - EX_BANG|EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_MODIFY, + EX_BANG|EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_jumps, "jumps", ex_jumps, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_k, "k", ex_mark, - EX_RANGE|EX_WORD1|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_RANGE|EX_WORD1|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_keepmarks, "keepmarks", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, @@ -748,7 +749,7 @@ EXCMD(CMD_keepalt, "keepalt", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, ADDR_NONE), EXCMD(CMD_list, "list", ex_print, - EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_lNext, "lNext", ex_cnext, EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG, @@ -763,7 +764,7 @@ EXCMD(CMD_labove, "labove", ex_cbelow, EX_RANGE|EX_COUNT|EX_TRLBAR, ADDR_UNSIGNED), EXCMD(CMD_language, "language", ex_language, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_laddexpr, "laddexpr", ex_cexpr, EX_NEEDARG|EX_WORD1|EX_NOTRLCOM, @@ -778,7 +779,7 @@ EXCMD(CMD_lafter, "lafter", ex_cbelow, EX_RANGE|EX_COUNT|EX_TRLBAR, ADDR_UNSIGNED), EXCMD(CMD_later, "later", ex_later, - EX_TRLBAR|EX_EXTRA|EX_NOSPC|EX_CMDWIN, + EX_TRLBAR|EX_EXTRA|EX_NOSPC|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_lbuffer, "lbuffer", ex_cbuffer, EX_BANG|EX_RANGE|EX_WORD1|EX_TRLBAR, @@ -793,10 +794,10 @@ EXCMD(CMD_lbottom, "lbottom", ex_cbottom, EX_TRLBAR, ADDR_NONE), EXCMD(CMD_lcd, "lcd", ex_cd, - EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_lchdir, "lchdir", ex_cd, - EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_lclose, "lclose", ex_cclose, EX_RANGE|EX_COUNT|EX_TRLBAR, @@ -808,13 +809,13 @@ EXCMD(CMD_ldo, "ldo", ex_listdo, EX_BANG|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_RANGE|EX_DFLALL, ADDR_QUICKFIX_VALID), EXCMD(CMD_left, "left", ex_align, - EX_TRLBAR|EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_MODIFY, + EX_TRLBAR|EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_leftabove, "leftabove", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, ADDR_NONE), EXCMD(CMD_let, "let", ex_let, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_lexpr, "lexpr", ex_cexpr, EX_NEEDARG|EX_WORD1|EX_NOTRLCOM|EX_BANG, @@ -856,19 +857,19 @@ EXCMD(CMD_llast, "llast", ex_cc, EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG, ADDR_UNSIGNED), EXCMD(CMD_llist, "llist", qf_list, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_lmap, "lmap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_lmapclear, "lmapclear", ex_mapclear, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_lmake, "lmake", ex_make, EX_BANG|EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_XFILE, ADDR_NONE), EXCMD(CMD_lnoremap, "lnoremap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_lnext, "lnext", ex_cnext, EX_RANGE|EX_COUNT|EX_TRLBAR|EX_BANG, @@ -883,13 +884,13 @@ EXCMD(CMD_loadview, "loadview", ex_loadview, EX_FILE1|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_loadkeymap, "loadkeymap", ex_loadkeymap, - EX_CMDWIN, + EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_lockmarks, "lockmarks", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, ADDR_NONE), EXCMD(CMD_lockvar, "lockvar", ex_lockvar, - EX_BANG|EX_EXTRA|EX_NEEDARG|EX_SBOXOK|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_NEEDARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_lolder, "lolder", qf_age, EX_RANGE|EX_COUNT|EX_TRLBAR, @@ -910,16 +911,16 @@ EXCMD(CMD_ltag, "ltag", ex_tag, EX_TRLBAR|EX_BANG|EX_WORD1, ADDR_NONE), EXCMD(CMD_lunmap, "lunmap", ex_unmap, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_lua, "lua", ex_lua, - EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_luado, "luado", ex_luado, - EX_RANGE|EX_DFLALL|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_DFLALL|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_luafile, "luafile", ex_luafile, - EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_lvimgrep, "lvimgrep", ex_vimgrep, EX_RANGE|EX_BANG|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_XFILE, @@ -931,40 +932,40 @@ EXCMD(CMD_lwindow, "lwindow", ex_cwindow, EX_RANGE|EX_COUNT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_ls, "ls", buflist_list, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_move, "move", ex_copymove, - EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_MODIFY, + EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_mark, "mark", ex_mark, - EX_RANGE|EX_WORD1|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_RANGE|EX_WORD1|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_make, "make", ex_make, EX_BANG|EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_XFILE, ADDR_NONE), EXCMD(CMD_map, "map", ex_map, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_mapclear, "mapclear", ex_mapclear, - EX_EXTRA|EX_BANG|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_BANG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_marks, "marks", ex_marks, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_match, "match", ex_match, - EX_RANGE|EX_EXTRA|EX_CMDWIN, + EX_RANGE|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_menu, "menu", ex_menu, - EX_RANGE|EX_ZEROR|EX_BANG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_BANG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_menutranslate, "menutranslate", ex_menutranslate, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_messages, "messages", ex_messages, - EX_EXTRA|EX_TRLBAR|EX_RANGE|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_RANGE|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_mkexrc, "mkexrc", ex_mkrc, - EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_mksession, "mksession", ex_mkrc, EX_BANG|EX_FILE1|EX_TRLBAR, @@ -973,19 +974,19 @@ EXCMD(CMD_mkspell, "mkspell", ex_mkspell, EX_BANG|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_XFILE, ADDR_NONE), EXCMD(CMD_mkvimrc, "mkvimrc", ex_mkrc, - EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_mkview, "mkview", ex_mkrc, EX_BANG|EX_FILE1|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_mode, "mode", ex_mode, - EX_WORD1|EX_TRLBAR|EX_CMDWIN, + EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_mzscheme, "mzscheme", ex_mzscheme, - EX_RANGE|EX_EXTRA|EX_DFLALL|EX_NEEDARG|EX_CMDWIN|EX_SBOXOK|EX_RESTRICT, + EX_RANGE|EX_EXTRA|EX_DFLALL|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_SBOXOK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_mzfile, "mzfile", ex_mzfile, - EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_next, "next", ex_next, EX_RANGE|EX_BANG|EX_FILES|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, @@ -994,112 +995,112 @@ EXCMD(CMD_nbkey, "nbkey", ex_nbkey, EX_EXTRA|EX_NEEDARG, ADDR_NONE), EXCMD(CMD_nbclose, "nbclose", ex_nbclose, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_nbstart, "nbstart", ex_nbstart, - EX_WORD1|EX_TRLBAR|EX_CMDWIN, + EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_new, "new", ex_splitview, EX_BANG|EX_FILE1|EX_RANGE|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_nmap, "nmap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_nmapclear, "nmapclear", ex_mapclear, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_nmenu, "nmenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_nnoremap, "nnoremap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_nnoremenu, "nnoremenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_noremap, "noremap", ex_map, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_noautocmd, "noautocmd", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, ADDR_NONE), EXCMD(CMD_nohlsearch, "nohlsearch", ex_nohlsearch, - EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_noreabbrev, "noreabbrev", ex_abbreviate, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_noremenu, "noremenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_BANG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_BANG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_noswapfile, "noswapfile", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, ADDR_NONE), EXCMD(CMD_normal, "normal", ex_normal, - EX_RANGE|EX_BANG|EX_EXTRA|EX_NEEDARG|EX_NOTRLCOM|EX_CTRLV|EX_SBOXOK|EX_CMDWIN, + EX_RANGE|EX_BANG|EX_EXTRA|EX_NEEDARG|EX_NOTRLCOM|EX_CTRLV|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_number, "number", ex_print, - EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_nunmap, "nunmap", ex_unmap, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_nunmenu, "nunmenu", ex_menu, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_open, "open", ex_open, EX_RANGE|EX_BANG|EX_EXTRA, ADDR_LINES), EXCMD(CMD_oldfiles, "oldfiles", ex_oldfiles, - EX_BANG|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_BANG|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_omap, "omap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_omapclear, "omapclear", ex_mapclear, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_omenu, "omenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_only, "only", ex_only, EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR, ADDR_WINDOWS), EXCMD(CMD_onoremap, "onoremap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_onoremenu, "onoremenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_options, "options", ex_options, EX_TRLBAR, ADDR_NONE), EXCMD(CMD_ounmap, "ounmap", ex_unmap, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_ounmenu, "ounmenu", ex_menu, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_ownsyntax, "ownsyntax", ex_ownsyntax, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_print, "print", ex_print, - EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_SBOXOK, + EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_SBOXOK, ADDR_LINES), EXCMD(CMD_packadd, "packadd", ex_packadd, - EX_BANG|EX_FILE1|EX_NEEDARG|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_BANG|EX_FILE1|EX_NEEDARG|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_packloadall, "packloadall", ex_packloadall, - EX_BANG|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_BANG|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_pclose, "pclose", ex_pclose, EX_BANG|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_perl, "perl", ex_perl, - EX_RANGE|EX_EXTRA|EX_DFLALL|EX_NEEDARG|EX_SBOXOK|EX_CMDWIN, + EX_RANGE|EX_EXTRA|EX_DFLALL|EX_NEEDARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_perldo, "perldo", ex_perldo, - EX_RANGE|EX_EXTRA|EX_DFLALL|EX_NEEDARG|EX_CMDWIN, + EX_RANGE|EX_EXTRA|EX_DFLALL|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_pedit, "pedit", ex_pedit, EX_BANG|EX_FILE1|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, @@ -1108,7 +1109,7 @@ EXCMD(CMD_pop, "pop", ex_tag, EX_RANGE|EX_BANG|EX_COUNT|EX_TRLBAR|EX_ZEROR, ADDR_OTHER), EXCMD(CMD_popup, "popup", ex_popup, - EX_NEEDARG|EX_EXTRA|EX_BANG|EX_TRLBAR|EX_NOTRLCOM|EX_CMDWIN, + EX_NEEDARG|EX_EXTRA|EX_BANG|EX_TRLBAR|EX_NOTRLCOM|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_ppop, "ppop", ex_ptag, EX_RANGE|EX_BANG|EX_COUNT|EX_TRLBAR|EX_ZEROR, @@ -1120,16 +1121,16 @@ EXCMD(CMD_previous, "previous", ex_previous, EX_EXTRA|EX_RANGE|EX_COUNT|EX_BANG|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_promptfind, "promptfind", gui_mch_find_dialog, - EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_promptrepl, "promptrepl", gui_mch_replace_dialog, - EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_profile, "profile", ex_profile, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_profdel, "profdel", ex_breakdel, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_psearch, "psearch", ex_psearch, EX_BANG|EX_RANGE|EX_WHOLEFOLD|EX_DFLALL|EX_EXTRA, @@ -1162,115 +1163,115 @@ EXCMD(CMD_ptselect, "ptselect", ex_ptag, EX_BANG|EX_TRLBAR|EX_WORD1, ADDR_NONE), EXCMD(CMD_put, "put", ex_put, - EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_REGSTR|EX_TRLBAR|EX_ZEROR|EX_CMDWIN|EX_MODIFY, + EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_REGSTR|EX_TRLBAR|EX_ZEROR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_pwd, "pwd", ex_pwd, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_python, "python", ex_python, - EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_pydo, "pydo", ex_pydo, - EX_RANGE|EX_DFLALL|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_DFLALL|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_pyfile, "pyfile", ex_pyfile, - EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_py3, "py3", ex_py3, - EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_py3do, "py3do", ex_py3do, - EX_RANGE|EX_DFLALL|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_DFLALL|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_python3, "python3", ex_py3, - EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_py3file, "py3file", ex_py3file, - EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_pyx, "pyx", ex_pyx, - EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_pyxdo, "pyxdo", ex_pyxdo, - EX_RANGE|EX_DFLALL|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_DFLALL|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_pythonx, "pythonx", ex_pyx, - EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_pyxfile, "pyxfile", ex_pyxfile, - EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_quit, "quit", ex_quit, - EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_WINDOWS), EXCMD(CMD_quitall, "quitall", ex_quit_all, EX_BANG|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_qall, "qall", ex_quit_all, - EX_BANG|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_read, "read", ex_read, - EX_BANG|EX_RANGE|EX_WHOLEFOLD|EX_FILE1|EX_ARGOPT|EX_TRLBAR|EX_ZEROR|EX_CMDWIN|EX_MODIFY, + EX_BANG|EX_RANGE|EX_WHOLEFOLD|EX_FILE1|EX_ARGOPT|EX_TRLBAR|EX_ZEROR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_recover, "recover", ex_recover, EX_BANG|EX_FILE1|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_redo, "redo", ex_redo, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_redir, "redir", ex_redir, - EX_BANG|EX_FILES|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILES|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_redraw, "redraw", ex_redraw, - EX_BANG|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_redrawstatus, "redrawstatus", ex_redrawstatus, - EX_BANG|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_redrawtabline, "redrawtabline", ex_redrawtabline, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_registers, "registers", ex_display, - EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_resize, "resize", ex_resize, - EX_RANGE|EX_TRLBAR|EX_WORD1|EX_CMDWIN, + EX_RANGE|EX_TRLBAR|EX_WORD1|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_retab, "retab", ex_retab, - EX_TRLBAR|EX_RANGE|EX_WHOLEFOLD|EX_DFLALL|EX_BANG|EX_WORD1|EX_CMDWIN|EX_MODIFY, + EX_TRLBAR|EX_RANGE|EX_WHOLEFOLD|EX_DFLALL|EX_BANG|EX_WORD1|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_return, "return", ex_return, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_rewind, "rewind", ex_rewind, EX_EXTRA|EX_BANG|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_right, "right", ex_align, - EX_TRLBAR|EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_MODIFY, + EX_TRLBAR|EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_rightbelow, "rightbelow", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, ADDR_NONE), EXCMD(CMD_runtime, "runtime", ex_runtime, - EX_BANG|EX_NEEDARG|EX_FILES|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_BANG|EX_NEEDARG|EX_FILES|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_ruby, "ruby", ex_ruby, - EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_rubydo, "rubydo", ex_rubydo, - EX_RANGE|EX_DFLALL|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_DFLALL|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_rubyfile, "rubyfile", ex_rubyfile, - EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_rundo, "rundo", ex_rundo, EX_NEEDARG|EX_FILE1, ADDR_NONE), EXCMD(CMD_rviminfo, "rviminfo", ex_viminfo, - EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_substitute, "substitute", do_sub, - EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_sNext, "sNext", ex_previous, EX_EXTRA|EX_RANGE|EX_COUNT|EX_BANG|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, @@ -1285,7 +1286,7 @@ EXCMD(CMD_sandbox, "sandbox", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, ADDR_NONE), EXCMD(CMD_saveas, "saveas", ex_write, - EX_BANG|EX_FILE1|EX_ARGOPT|EX_CMDWIN|EX_TRLBAR, + EX_BANG|EX_FILE1|EX_ARGOPT|EX_CMDWIN|EX_LOCK_OK|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_sbuffer, "sbuffer", ex_buffer, EX_BANG|EX_RANGE|EX_BUFNAME|EX_BUFUNL|EX_COUNT|EX_EXTRA|EX_CMDARG|EX_TRLBAR, @@ -1315,28 +1316,28 @@ EXCMD(CMD_sbrewind, "sbrewind", ex_brewind, EX_CMDARG|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_scriptnames, "scriptnames", ex_scriptnames, - EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_RANGE|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_scriptencoding, "scriptencoding", ex_scriptencoding, - EX_WORD1|EX_TRLBAR|EX_CMDWIN, + EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_scriptversion, "scriptversion", ex_scriptversion, - EX_WORD1|EX_TRLBAR|EX_CMDWIN, + EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_scscope, "scscope", ex_scscope, EX_EXTRA|EX_NOTRLCOM, ADDR_NONE), EXCMD(CMD_set, "set", ex_set, - EX_BANG|EX_TRLBAR|EX_EXTRA|EX_CMDWIN|EX_SBOXOK, + EX_BANG|EX_TRLBAR|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_SBOXOK, ADDR_NONE), EXCMD(CMD_setfiletype, "setfiletype", ex_setfiletype, - EX_TRLBAR|EX_EXTRA|EX_NEEDARG|EX_CMDWIN, + EX_TRLBAR|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_setglobal, "setglobal", ex_set, - EX_BANG|EX_TRLBAR|EX_EXTRA|EX_CMDWIN|EX_SBOXOK, + EX_BANG|EX_TRLBAR|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_SBOXOK, ADDR_NONE), EXCMD(CMD_setlocal, "setlocal", ex_set, - EX_BANG|EX_TRLBAR|EX_EXTRA|EX_CMDWIN|EX_SBOXOK, + EX_BANG|EX_TRLBAR|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_SBOXOK, ADDR_NONE), EXCMD(CMD_sfind, "sfind", ex_splitview, EX_BANG|EX_FILE1|EX_RANGE|EX_CMDARG|EX_ARGOPT|EX_TRLBAR|EX_NEEDARG, @@ -1345,49 +1346,49 @@ EXCMD(CMD_sfirst, "sfirst", ex_rewind, EX_EXTRA|EX_BANG|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_shell, "shell", ex_shell, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_simalt, "simalt", ex_simalt, - EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN, + EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_sign, "sign", ex_sign, - EX_NEEDARG|EX_RANGE|EX_EXTRA|EX_CMDWIN, + EX_NEEDARG|EX_RANGE|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_silent, "silent", ex_wrongmodifier, - EX_NEEDARG|EX_EXTRA|EX_BANG|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_NEEDARG|EX_EXTRA|EX_BANG|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_sleep, "sleep", ex_sleep, - EX_RANGE|EX_COUNT|EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_COUNT|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_slast, "slast", ex_last, EX_EXTRA|EX_BANG|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_smagic, "smagic", ex_submagic, - EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_smap, "smap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_smapclear, "smapclear", ex_mapclear, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_smenu, "smenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_snext, "snext", ex_next, EX_RANGE|EX_BANG|EX_FILES|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_snomagic, "snomagic", ex_submagic, - EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_snoremap, "snoremap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_snoremenu, "snoremenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_source, "source", ex_source, - EX_BANG|EX_FILE1|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_BANG|EX_FILE1|EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_sort, "sort", ex_sort, EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_BANG|EX_EXTRA|EX_NOTRLCOM|EX_MODIFY, @@ -1423,22 +1424,22 @@ EXCMD(CMD_srewind, "srewind", ex_rewind, EX_EXTRA|EX_BANG|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_stop, "stop", ex_stop, - EX_TRLBAR|EX_BANG|EX_CMDWIN, + EX_TRLBAR|EX_BANG|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_stag, "stag", ex_stag, EX_RANGE|EX_BANG|EX_WORD1|EX_TRLBAR|EX_ZEROR, ADDR_OTHER), EXCMD(CMD_startinsert, "startinsert", ex_startinsert, - EX_BANG|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_startgreplace, "startgreplace", ex_startinsert, - EX_BANG|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_startreplace, "startreplace", ex_startinsert, - EX_BANG|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_stopinsert, "stopinsert", ex_stopinsert, - EX_BANG|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_stjump, "stjump", ex_stag, EX_BANG|EX_TRLBAR|EX_WORD1, @@ -1450,34 +1451,34 @@ EXCMD(CMD_sunhide, "sunhide", ex_buffer_all, EX_RANGE|EX_COUNT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_sunmap, "sunmap", ex_unmap, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_sunmenu, "sunmenu", ex_menu, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_suspend, "suspend", ex_stop, - EX_TRLBAR|EX_BANG|EX_CMDWIN, + EX_TRLBAR|EX_BANG|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_sview, "sview", ex_splitview, EX_BANG|EX_FILE1|EX_RANGE|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_swapname, "swapname", ex_swapname, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_syntax, "syntax", ex_syntax, - EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_syntime, "syntime", ex_syntime, - EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN, + EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_syncbind, "syncbind", ex_syncbind, EX_TRLBAR, ADDR_NONE), EXCMD(CMD_smile, "smile", ex_smile, - EX_TRLBAR|EX_CMDWIN|EX_SBOXOK, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_SBOXOK, ADDR_NONE), EXCMD(CMD_t, "t", ex_copymove, - EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_MODIFY, + EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_tNext, "tNext", ex_tag, EX_RANGE|EX_BANG|EX_TRLBAR|EX_ZEROR, @@ -1486,13 +1487,13 @@ EXCMD(CMD_tag, "tag", ex_tag, EX_RANGE|EX_BANG|EX_WORD1|EX_TRLBAR|EX_ZEROR, ADDR_OTHER), EXCMD(CMD_tags, "tags", do_tags, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_tab, "tab", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, ADDR_NONE), EXCMD(CMD_tabclose, "tabclose", ex_tabclose, - EX_BANG|EX_RANGE|EX_ZEROR|EX_EXTRA|EX_NOSPC|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_RANGE|EX_ZEROR|EX_EXTRA|EX_NOSPC|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_TABS), EXCMD(CMD_tabdo, "tabdo", ex_listdo, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_RANGE|EX_DFLALL, @@ -1519,7 +1520,7 @@ EXCMD(CMD_tabnew, "tabnew", ex_splitview, EX_BANG|EX_FILE1|EX_RANGE|EX_ZEROR|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_TABS), EXCMD(CMD_tabonly, "tabonly", ex_tabonly, - EX_BANG|EX_RANGE|EX_ZEROR|EX_EXTRA|EX_NOSPC|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_RANGE|EX_ZEROR|EX_EXTRA|EX_NOSPC|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_TABS), EXCMD(CMD_tabprevious, "tabprevious", ex_tabnext, EX_RANGE|EX_ZEROR|EX_EXTRA|EX_NOSPC|EX_TRLBAR, @@ -1531,34 +1532,34 @@ EXCMD(CMD_tabrewind, "tabrewind", ex_tabnext, EX_TRLBAR, ADDR_NONE), EXCMD(CMD_tabs, "tabs", ex_tabs, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_tcd, "tcd", ex_cd, - EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_tchdir, "tchdir", ex_cd, - EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_tcl, "tcl", ex_tcl, - EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_tcldo, "tcldo", ex_tcldo, - EX_RANGE|EX_DFLALL|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_DFLALL|EX_EXTRA|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_tclfile, "tclfile", ex_tclfile, - EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_RESTRICT, + EX_RANGE|EX_FILE1|EX_NEEDARG|EX_CMDWIN|EX_LOCK_OK|EX_RESTRICT, ADDR_LINES), EXCMD(CMD_tearoff, "tearoff", ex_tearoff, - EX_NEEDARG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CMDWIN, + EX_NEEDARG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_terminal, "terminal", ex_terminal, - EX_RANGE|EX_BANG|EX_FILES|EX_CMDWIN, + EX_RANGE|EX_BANG|EX_FILES|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_tfirst, "tfirst", ex_tag, EX_RANGE|EX_BANG|EX_TRLBAR|EX_ZEROR, ADDR_OTHER), EXCMD(CMD_throw, "throw", ex_throw, - EX_EXTRA|EX_NEEDARG|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NEEDARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_tjump, "tjump", ex_tag, EX_BANG|EX_TRLBAR|EX_WORD1, @@ -1567,28 +1568,28 @@ EXCMD(CMD_tlast, "tlast", ex_tag, EX_BANG|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_tlmenu, "tlmenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_tlnoremenu, "tlnoremenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_tlunmenu, "tlunmenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_tmenu, "tmenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_tmap, "tmap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_tmapclear, "tmapclear", ex_mapclear, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_tnext, "tnext", ex_tag, EX_RANGE|EX_BANG|EX_TRLBAR|EX_ZEROR, ADDR_OTHER), EXCMD(CMD_tnoremap, "tnoremap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_topleft, "topleft", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, @@ -1600,58 +1601,58 @@ EXCMD(CMD_trewind, "trewind", ex_tag, EX_RANGE|EX_BANG|EX_TRLBAR|EX_ZEROR, ADDR_OTHER), EXCMD(CMD_try, "try", ex_try, - EX_TRLBAR|EX_SBOXOK|EX_CMDWIN, + EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_tselect, "tselect", ex_tag, EX_BANG|EX_TRLBAR|EX_WORD1, ADDR_NONE), EXCMD(CMD_tunmenu, "tunmenu", ex_menu, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_tunmap, "tunmap", ex_unmap, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_undo, "undo", ex_undo, - EX_RANGE|EX_COUNT|EX_ZEROR|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_COUNT|EX_ZEROR|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_undojoin, "undojoin", ex_undojoin, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_undolist, "undolist", ex_undolist, - EX_TRLBAR|EX_CMDWIN, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_unabbreviate, "unabbreviate", ex_abbreviate, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_unhide, "unhide", ex_buffer_all, EX_RANGE|EX_COUNT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_unlet, "unlet", ex_unlet, - EX_BANG|EX_EXTRA|EX_NEEDARG|EX_SBOXOK|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_NEEDARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_unlockvar, "unlockvar", ex_lockvar, - EX_BANG|EX_EXTRA|EX_NEEDARG|EX_SBOXOK|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_NEEDARG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_unmap, "unmap", ex_unmap, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_unmenu, "unmenu", ex_menu, - EX_BANG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_BANG|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_unsilent, "unsilent", ex_wrongmodifier, - EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_update, "update", ex_update, EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILE1|EX_ARGOPT|EX_DFLALL|EX_TRLBAR, ADDR_LINES), EXCMD(CMD_vglobal, "vglobal", ex_global, - EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_DFLALL|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_DFLALL|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_version, "version", ex_version, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_verbose, "verbose", ex_wrongmodifier, - EX_NEEDARG|EX_RANGE|EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_NEEDARG|EX_RANGE|EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_vertical, "vertical", ex_wrongmodifier, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM, @@ -1669,61 +1670,61 @@ EXCMD(CMD_vimgrepadd, "vimgrepadd", ex_vimgrep, EX_RANGE|EX_BANG|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_XFILE, ADDR_OTHER), EXCMD(CMD_vim9script, "vim9script", ex_vim9script, - 0, + EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_viusage, "viusage", ex_viusage, EX_TRLBAR, ADDR_NONE), EXCMD(CMD_vmap, "vmap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_vmapclear, "vmapclear", ex_mapclear, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_vmenu, "vmenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_vnoremap, "vnoremap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_vnew, "vnew", ex_splitview, EX_BANG|EX_FILE1|EX_RANGE|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_vnoremenu, "vnoremenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_vsplit, "vsplit", ex_splitview, EX_BANG|EX_FILE1|EX_RANGE|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_vunmap, "vunmap", ex_unmap, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_vunmenu, "vunmenu", ex_menu, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_write, "write", ex_write, - EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILE1|EX_ARGOPT|EX_DFLALL|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILE1|EX_ARGOPT|EX_DFLALL|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_wNext, "wNext", ex_wnext, EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILE1|EX_ARGOPT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_wall, "wall", do_wqall, - EX_BANG|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_while, "while", ex_while, - EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN, + EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_winsize, "winsize", ex_winsize, EX_EXTRA|EX_NEEDARG|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_wincmd, "wincmd", ex_wincmd, - EX_NEEDARG|EX_WORD1|EX_RANGE|EX_CMDWIN, + EX_NEEDARG|EX_WORD1|EX_RANGE|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_windo, "windo", ex_listdo, EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_RANGE|EX_DFLALL, ADDR_WINDOWS), EXCMD(CMD_winpos, "winpos", ex_winpos, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_wnext, "wnext", ex_wnext, EX_RANGE|EX_BANG|EX_FILE1|EX_ARGOPT|EX_TRLBAR, @@ -1741,72 +1742,72 @@ EXCMD(CMD_wundo, "wundo", ex_wundo, EX_BANG|EX_NEEDARG|EX_FILE1, ADDR_NONE), EXCMD(CMD_wviminfo, "wviminfo", ex_viminfo, - EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN, + EX_BANG|EX_FILE1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_xit, "xit", ex_exit, - EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILE1|EX_ARGOPT|EX_DFLALL|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILE1|EX_ARGOPT|EX_DFLALL|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_xall, "xall", do_wqall, EX_BANG|EX_TRLBAR, ADDR_NONE), EXCMD(CMD_xmap, "xmap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_xmapclear, "xmapclear", ex_mapclear, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_xmenu, "xmenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_xnoremap, "xnoremap", ex_map, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_xnoremenu, "xnoremenu", ex_menu, - EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_xrestore, "xrestore", ex_xrestore, - EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_xunmap, "xunmap", ex_unmap, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_xunmenu, "xunmenu", ex_menu, - EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN, + EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_yank, "yank", ex_operators, - EX_RANGE|EX_WHOLEFOLD|EX_REGSTR|EX_COUNT|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_REGSTR|EX_COUNT|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_z, "z", ex_z, - EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_FLAGS|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), // commands that don't start with a letter EXCMD(CMD_bang, "!", ex_bang, - EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILES|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILES|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_pound, "#", ex_print, - EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_and, "&", do_sub, - EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_MODIFY, + EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_star, "*", ex_at, - EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_lshift, "<", ex_operators, - EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_MODIFY, + EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_equal, "=", ex_equal, - EX_RANGE|EX_TRLBAR|EX_DFLALL|EX_FLAGS|EX_CMDWIN, + EX_RANGE|EX_TRLBAR|EX_DFLALL|EX_FLAGS|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_rshift, ">", ex_operators, - EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_MODIFY, + EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), EXCMD(CMD_at, "@", ex_at, - EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_tilde, "~", do_sub, - EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_MODIFY, + EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), // commands that start with an uppercase letter @@ -1814,7 +1815,7 @@ EXCMD(CMD_Next, "Next", ex_previous, EX_EXTRA|EX_RANGE|EX_COUNT|EX_BANG|EX_CMDARG|EX_ARGOPT|EX_TRLBAR, ADDR_OTHER), EXCMD(CMD_Print, "Print", ex_print, - EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN, + EX_RANGE|EX_WHOLEFOLD|EX_COUNT|EX_FLAGS|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_X, "X", ex_X, EX_TRLBAR, diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 5459cfd7b83a24..04c3b465a7dd40 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -2061,12 +2061,22 @@ do_one_cmd( goto doend; } - if (text_locked() && !(ea.argt & EX_CMDWIN) - && !IS_USER_CMDIDX(ea.cmdidx)) + if (!IS_USER_CMDIDX(ea.cmdidx)) { - // Command not allowed when editing the command line. - errormsg = _(get_text_locked_msg()); - goto doend; +#ifdef FEAT_CMDWIN + if (cmdwin_type != 0 && !(ea.argt & EX_CMDWIN)) + { + // Command not allowed in the command line window + errormsg = _(e_cmdwin); + goto doend; + } +#endif + if (text_locked() && !(ea.argt & EX_LOCK_OK)) + { + // Command not allowed when text is locked + errormsg = _(get_text_locked_msg()); + goto doend; + } } // Disallow editing another buffer when "curbuf_lock" is set. diff --git a/src/version.c b/src/version.c index 05f37526d4ed25..27015c2ae8d386 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1294, /**/ 1293, /**/ From 7d40b8a532fa2ce768f200ab118870d17875a7fe Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 26 Jul 2020 12:52:59 +0200 Subject: [PATCH 0007/1384] patch 8.2.1295: tests 44 and 99 are old style Problem: Tests 44 and 99 are old style. Solution: Convert to new style tests. (Yegappan Lakshmanan, closes #6536) --- src/Makefile | 5 +- src/testdir/Make_all.mak | 4 +- src/testdir/Make_vms.mms | 2 +- src/testdir/test44.in | 81 -------------------- src/testdir/test44.ok | 25 ------- src/testdir/test99.in | 69 ----------------- src/testdir/test99.ok | 23 ------ src/testdir/test_regexp_utf8.vim | 124 +++++++++++++++++++++++++++++++ src/version.c | 2 + 9 files changed, 130 insertions(+), 205 deletions(-) delete mode 100644 src/testdir/test44.in delete mode 100644 src/testdir/test44.ok delete mode 100644 src/testdir/test99.in delete mode 100644 src/testdir/test99.ok diff --git a/src/Makefile b/src/Makefile index 8ac7dc58beb7fd..9ce61aa018c7c3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2311,10 +2311,9 @@ test_libvterm: # Run individual OLD style test. # These do not depend on the executable, compile it when needed. test1 \ - test42 test44 test49 \ + test42 test49 \ test52 test59 \ - test70 \ - test99: + test70: cd testdir; rm -f $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE) # Run individual NEW style test. diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index d5176671565485..b2d9ac6f0f84d5 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -14,9 +14,7 @@ SCRIPTS_FIRST = \ # Tests that run on all systems. SCRIPTS_ALL = \ test42.out \ - test44.out \ - test70.out \ - test99.out + test70.out # Tests that run on most systems, but not on Amiga. SCRIPTS_MORE1 = \ diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms index 991a2f773b590a..352e5539ebc1fe 100644 --- a/src/testdir/Make_vms.mms +++ b/src/testdir/Make_vms.mms @@ -74,7 +74,7 @@ VIMPROG = <->vim.exe .SUFFIXES : .out .in SCRIPT = test1.out \ - test42.out test44.out test49.out test77a.out test99.out + test42.out test49.out test77a.out # Known problems: # diff --git a/src/testdir/test44.in b/src/testdir/test44.in deleted file mode 100644 index 712639237791ee..00000000000000 --- a/src/testdir/test44.in +++ /dev/null @@ -1,81 +0,0 @@ -Tests for regexp with multi-byte encoding and various magic settings. -Test matchstr() with a count and multi-byte chars. -See test99 for exactly the same test with re=2. - -STARTTEST -:so mbyte.vim -:set nocompatible encoding=utf-8 termencoding=latin1 viminfo+=nviminfo -:set re=1 -/^1 -/a*b\{2}c\+/e -x/\Md\*e\{2}f\+/e -x:set nomagic -/g\*h\{2}i\+/e -x/\mj*k\{2}l\+/e -x/\vm*n{2}o+/e -x/\V^aa$ -x:set magic -/\v(a)(b)\2\1\1/e -x/\V[ab]\(\[xy]\)\1 -x:" Now search for multi-byte without composing char -/ม -x:" Now search for multi-byte with composing char -/ม่ -x:" find word by change of word class -/ち\<カヨ\>は -x:" Test \%u, [\u] and friends -:" c -/\%u20ac -x:" d -/[\u4f7f\u5929]\+ -x:" e -/\%U12345678 -x:" f -/[\U1234abcd\u1234\uabcd] -x:" g -/\%d21879b -x:" j Test backwards search from a multi-byte char -/x -x?. -x:" k -:let @w=':%s#comb[i]nations#œ̄ṣ́m̥̄ᾱ̆́#g' -:@w -:" -:" l Test what 7.3.192 fixed -/^l -:s/ \?/ /g -:?^1?,$w! test.out -:e! test.out -G:put =matchstr(\"אבגד\", \".\", 0, 2) " ב -:put =matchstr(\"אבגד\", \"..\", 0, 2) " בג -:put =matchstr(\"אבגד\", \".\", 0, 0) " א -:put =matchstr(\"אבגד\", \".\", 4, -1) " ג -:new -:$put =['dog(a', 'cat('] -/(/e+ -"ayn:bd! -:$put ='' -G"ap -:w! -:qa! -ENDTEST - -1 a aa abb abbccc -2 d dd dee deefff -3 g gg ghh ghhiii -4 j jj jkk jkklll -5 m mm mnn mnnooo -6 x ^aa$ x -7 (a)(b) abbaa -8 axx [ab]xx -9 หม่x อมx -a อมx หม่x -b ちカヨは -c x ¬€x -d 天使x -e y -f z -g a啷bb -j 0123❤x -k combinations -l äö üᾱ̆́ diff --git a/src/testdir/test44.ok b/src/testdir/test44.ok deleted file mode 100644 index 45774d7cbb8299..00000000000000 --- a/src/testdir/test44.ok +++ /dev/null @@ -1,25 +0,0 @@ -1 a aa abb abbcc -2 d dd dee deeff -3 g gg ghh ghhii -4 j jj jkk jkkll -5 m mm mnn mnnoo -6 x aa$ x -7 (a)(b) abba -8 axx ab]xx -9 หม่x อx -a อมx หx -b カヨは -c x ¬x -d 使x -e y -f z -g abb -j 012❤ -k œ̄ṣ́m̥̄ᾱ̆́ - l ä ö ü ᾱ̆́ -ב -בג -א -ג -a -cat( diff --git a/src/testdir/test99.in b/src/testdir/test99.in deleted file mode 100644 index 3961244c79692f..00000000000000 --- a/src/testdir/test99.in +++ /dev/null @@ -1,69 +0,0 @@ -Tests for regexp with multi-byte encoding and various magic settings. -Test matchstr() with a count and multi-byte chars. -See test44 for exactly the same test with re=1. - -STARTTEST -:so mbyte.vim -:set nocompatible encoding=utf-8 termencoding=latin1 viminfo+=nviminfo -:set re=2 -/^1 -/a*b\{2}c\+/e -x/\Md\*e\{2}f\+/e -x:set nomagic -/g\*h\{2}i\+/e -x/\mj*k\{2}l\+/e -x/\vm*n{2}o+/e -x/\V^aa$ -x:set magic -/\v(a)(b)\2\1\1/e -x/\V[ab]\(\[xy]\)\1 -x:" Now search for multi-byte without composing char -/ม -x:" Now search for multi-byte with composing char -/ม่ -x:" find word by change of word class -/ち\<カヨ\>は -x:" Test \%u, [\u] and friends -/\%u20ac -x/[\u4f7f\u5929]\+ -x/\%U12345678 -x/[\U1234abcd\u1234\uabcd] -x/\%d21879b -x:" Test backwards search from a multi-byte char -/x -x?. -x:let @w=':%s#comb[i]nations#œ̄ṣ́m̥̄ᾱ̆́#g' -:@w -:" -:" l Test what 7.3.192 fixed -/^l -:s/ \?/ /g -:?^1?,$w! test.out -:e! test.out -G:put =matchstr(\"אבגד\", \".\", 0, 2) " ב -:put =matchstr(\"אבגד\", \"..\", 0, 2) " בג -:put =matchstr(\"אבגד\", \".\", 0, 0) " א -:put =matchstr(\"אבגד\", \".\", 4, -1) " ג -:w! -:qa! -ENDTEST - -1 a aa abb abbccc -2 d dd dee deefff -3 g gg ghh ghhiii -4 j jj jkk jkklll -5 m mm mnn mnnooo -6 x ^aa$ x -7 (a)(b) abbaa -8 axx [ab]xx -9 หม่x อมx -a อมx หม่x -b ちカヨは -c x ¬€x -d 天使x -e y -f z -g a啷bb -j 0123❤x -k combinations -l äö üᾱ̆́ diff --git a/src/testdir/test99.ok b/src/testdir/test99.ok deleted file mode 100644 index dea3665cf6080f..00000000000000 --- a/src/testdir/test99.ok +++ /dev/null @@ -1,23 +0,0 @@ -1 a aa abb abbcc -2 d dd dee deeff -3 g gg ghh ghhii -4 j jj jkk jkkll -5 m mm mnn mnnoo -6 x aa$ x -7 (a)(b) abba -8 axx ab]xx -9 หม่x อx -a อมx หx -b カヨは -c x ¬x -d 使x -e y -f z -g abb -j 012❤ -k œ̄ṣ́m̥̄ᾱ̆́ - l ä ö ü ᾱ̆́ -ב -בג -א -ג diff --git a/src/testdir/test_regexp_utf8.vim b/src/testdir/test_regexp_utf8.vim index 5100b378a90d7a..cc7df9ed5940e5 100644 --- a/src/testdir/test_regexp_utf8.vim +++ b/src/testdir/test_regexp_utf8.vim @@ -377,4 +377,128 @@ func Test_regexp_ignore_case() set regexpengine& endfunc +" Tests for regexp with multi-byte encoding and various magic settings +func Run_regexp_multibyte_magic() + let text =<< trim END + 1 a aa abb abbccc + 2 d dd dee deefff + 3 g gg ghh ghhiii + 4 j jj jkk jkklll + 5 m mm mnn mnnooo + 6 x ^aa$ x + 7 (a)(b) abbaa + 8 axx [ab]xx + 9 หม่x อมx + a อมx หม่x + b ちカヨは + c x ¬€x + d 天使x + e y + f z + g a啷bb + j 0123❤x + k combinations + l äö üᾱ̆́ + END + + new + call setline(1, text) + exe 'normal /a*b\{2}c\+/e' .. "\x" + call assert_equal('1 a aa abb abbcc', getline('.')) + exe 'normal /\Md\*e\{2}f\+/e' .. "\x" + call assert_equal('2 d dd dee deeff', getline('.')) + set nomagic + exe 'normal /g\*h\{2}i\+/e' .. "\x" + call assert_equal('3 g gg ghh ghhii', getline('.')) + exe 'normal /\mj*k\{2}l\+/e' .. "\x" + call assert_equal('4 j jj jkk jkkll', getline('.')) + exe 'normal /\vm*n{2}o+/e' .. "\x" + call assert_equal('5 m mm mnn mnnoo', getline('.')) + exe 'normal /\V^aa$/' .. "\x" + call assert_equal('6 x aa$ x', getline('.')) + set magic + exe 'normal /\v(a)(b)\2\1\1/e' .. "\x" + call assert_equal('7 (a)(b) abba', getline('.')) + exe 'normal /\V[ab]\(\[xy]\)\1' .. "\x" + call assert_equal('8 axx ab]xx', getline('.')) + + " search for multi-byte without composing char + exe 'normal /ม' .. "\x" + call assert_equal('9 หม่x อx', getline('.')) + + " search for multi-byte with composing char + exe 'normal /ม่' .. "\x" + call assert_equal('a อมx หx', getline('.')) + + " find word by change of word class + exe 'normal /ち\<カヨ\>は' .. "\x" + call assert_equal('b カヨは', getline('.')) + + " Test \%u, [\u] and friends + " c + exe 'normal /\%u20ac' .. "\x" + call assert_equal('c x ¬x', getline('.')) + " d + exe 'normal /[\u4f7f\u5929]\+' .. "\x" + call assert_equal('d 使x', getline('.')) + " e + exe 'normal /\%U12345678' .. "\x" + call assert_equal('e y', getline('.')) + " f + exe 'normal /[\U1234abcd\u1234\uabcd]' .. "\x" + call assert_equal('f z', getline('.')) + " g + exe 'normal /\%d21879b' .. "\x" + call assert_equal('g abb', getline('.')) + + " j Test backwards search from a multi-byte char + exe "normal /x\x?.\x" + call assert_equal('j 012❤', getline('.')) + " k + let @w=':%s#comb[i]nations#œ̄ṣ́m̥̄ᾱ̆́#g' + @w + call assert_equal('k œ̄ṣ́m̥̄ᾱ̆́', getline(18)) + + close! +endfunc + +func Test_regexp_multibyte_magic() + set regexpengine=1 + call Run_regexp_multibyte_magic() + set regexpengine=2 + call Run_regexp_multibyte_magic() + set regexpengine& +endfunc + +" Test for 7.3.192 +" command ":s/ \?/ /g" splits multi-byte characters into bytes +func Test_split_multibyte_to_bytes() + new + call setline(1, 'l äö üᾱ̆́') + s/ \?/ /g + call assert_equal(' l ä ö ü ᾱ̆́', getline(1)) + close! +endfunc + +" Test for matchstr() with multibyte characters +func Test_matchstr_multibyte() + new + call assert_equal('ב', matchstr("אבגד", ".", 0, 2)) + call assert_equal('בג', matchstr("אבגד", "..", 0, 2)) + call assert_equal('א', matchstr("אבגד", ".", 0, 0)) + call assert_equal('ג', matchstr("אבגד", ".", 4, -1)) + close! +endfunc + +" Test for 7.4.636 +" A search with end offset gets stuck at end of file. +func Test_search_with_end_offset() + new + call setline(1, ['', 'dog(a', 'cat(']) + exe "normal /(/e+" .. "\" + normal "ayn + call assert_equal("a\ncat(", @a) + close! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 27015c2ae8d386..fe9b7872094830 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1295, /**/ 1294, /**/ From d66cdcd43a598825add743bc95642cd8ed705252 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 26 Jul 2020 13:27:16 +0200 Subject: [PATCH 0008/1384] patch 8.2.1296: some part of using 'smarcase' was not tested MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Some part of using 'smarcase' was not tested. Solution: Add more tests. (Dominique Pellé, closes #6538) --- src/testdir/test_search.vim | 21 ++++++++++++++++++++- src/version.c | 2 ++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_search.vim b/src/testdir/test_search.vim index 93b68a78a3693c..9769fb2625c7f2 100644 --- a/src/testdir/test_search.vim +++ b/src/testdir/test_search.vim @@ -608,7 +608,7 @@ func Test_search_cmdline6() endfunc func Test_search_cmdline7() - " Test that an pressing in an empty command line + " Test that pressing in an empty command line " does not move the cursor CheckOption incsearch @@ -1642,6 +1642,25 @@ func Test_search_smartcase() set ignorecase& smartcase& close! +endfun + +" Test 'smartcase' with utf-8. +func Test_search_smartcase_utf8() + new + let save_enc = &encoding + set encoding=utf8 ignorecase smartcase + + call setline(1, 'Café cafÉ') + 1s/café/x/g + call assert_equal('x x', getline(1)) + + call setline(1, 'Café cafÉ') + 1s/cafÉ/x/g + call assert_equal('Café x', getline(1)) + + set ignorecase& smartcase& + let &encoding = save_enc + close! endfunc " Test searching past the end of a file diff --git a/src/version.c b/src/version.c index fe9b7872094830..6a5f19951e5e89 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1296, /**/ 1295, /**/ From a5d0423fa16f18b4576a2a07e50034e489587a7d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 26 Jul 2020 15:37:02 +0200 Subject: [PATCH 0009/1384] patch 8.2.1297: when a test fails it's often not easy to see where Problem: When a test fails it's often not easy to see what the call stack is. Solution: Add more entries from the call stack in the exception message. --- runtime/doc/cmdline.txt | 16 +++++--- src/debugger.c | 6 +-- src/ex_docmd.c | 11 +++-- src/ex_eval.c | 4 +- src/message.c | 2 +- src/proto/scriptfile.pro | 2 +- src/scriptfile.c | 70 ++++++++++++++++++-------------- src/testdir/test_expand_func.vim | 56 +++++++++++++++---------- src/testing.c | 2 +- src/version.c | 2 + 10 files changed, 102 insertions(+), 69 deletions(-) diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index ecaa73e894974b..8e4e2a0180d309 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -876,7 +876,7 @@ Also see |`=|. *:* ** *:* ** *:* ** *:* ** *:* ** *:* ** - *:* ** + *:* ** *:* ** *:* ** *:* ** *:* ** *E499* *E500* Note: these are typed literally, they are not special keys! @@ -903,12 +903,16 @@ Note: these are typed literally, they are not special keys! events). When executing a ":source" command, is replaced with the file name of the sourced file. *E498* - When executing a function, is replaced with: - "function {function-name}[{lnum}]" - function call nesting is indicated like this: - "function {function-name1}[{lnum}]..{function-name2}[{lnum}]" + When executing a function, is replaced with the call stack, + as with (this is for backwards compatibility, using + is preferred). Note that filename-modifiers are useless when is - used inside a function. + not used inside a script. + is replaced with the call stack, using + "function {function-name}[{lnum}]" for a function line + and "script {file-name}[{lnum}]" for a script line, and + ".." in between items. E.g.: + "function {function-name1}[{lnum}]..{function-name2}[{lnum}]" When executing a ":source" command, is replaced with the line number. *E842* When executing a function it's the line number relative to diff --git a/src/debugger.c b/src/debugger.c index 91ab5ee1fa26dd..00fb9c8f8bc09d 100644 --- a/src/debugger.c +++ b/src/debugger.c @@ -105,7 +105,7 @@ do_debug(char_u *cmd) vim_free(debug_newval); debug_newval = NULL; } - sname = estack_sfile(); + sname = estack_sfile(FALSE); if (sname != NULL) msg((char *)sname); vim_free(sname); @@ -344,7 +344,7 @@ do_checkbacktracelevel(void) } else { - char_u *sname = estack_sfile(); + char_u *sname = estack_sfile(FALSE); int max = get_maxbacktrace_level(sname); if (debug_backtrace_level > max) @@ -365,7 +365,7 @@ do_showbacktrace(char_u *cmd) int i = 0; int max; - sname = estack_sfile(); + sname = estack_sfile(FALSE); max = get_maxbacktrace_level(sname); if (sname != NULL) { diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 04c3b465a7dd40..987e92dea9c85d 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -8268,8 +8268,10 @@ find_cmdline_var(char_u *src, int *usedlen) #define SPEC_SFILE (SPEC_CFILE + 1) "", // ":so" file line number #define SPEC_SLNUM (SPEC_SFILE + 1) + "", // call stack +#define SPEC_STACK (SPEC_SLNUM + 1) "", // autocommand file name -#define SPEC_AFILE (SPEC_SLNUM + 1) +#define SPEC_AFILE (SPEC_STACK + 1) "", // autocommand buffer number #define SPEC_ABUF (SPEC_AFILE + 1) "", // autocommand match name @@ -8520,10 +8522,13 @@ eval_vars( break; case SPEC_SFILE: // file name for ":so" command - result = estack_sfile(); + case SPEC_STACK: // call stack + result = estack_sfile(spec_idx == SPEC_SFILE); if (result == NULL) { - *errormsg = _("E498: no :source file name to substitute for \"\""); + *errormsg = spec_idx == SPEC_SFILE + ? _("E498: no :source file name to substitute for \"\"") + : _("E489: no call stack to substitute for \"\""); return NULL; } resultbuf = result; // remember allocated string diff --git a/src/ex_eval.c b/src/ex_eval.c index f0ffaffdde8c22..58088a0706f43b 100644 --- a/src/ex_eval.c +++ b/src/ex_eval.c @@ -290,7 +290,7 @@ cause_errthrow( // Get the source name and lnum now, it may change before // reaching do_errthrow(). - elem->sfile = estack_sfile(); + elem->sfile = estack_sfile(FALSE); elem->slnum = SOURCING_LNUM; } } @@ -549,7 +549,7 @@ throw_exception(void *value, except_type_T type, char_u *cmdname) } else { - excp->throw_name = estack_sfile(); + excp->throw_name = estack_sfile(FALSE); if (excp->throw_name == NULL) excp->throw_name = vim_strsave((char_u *)""); if (excp->throw_name == NULL) diff --git a/src/message.c b/src/message.c index 76ec456795273b..91b2fe23721b8d 100644 --- a/src/message.c +++ b/src/message.c @@ -461,7 +461,7 @@ get_emsg_source(void) if (SOURCING_NAME != NULL && other_sourcing_name()) { - char_u *sname = estack_sfile(); + char_u *sname = estack_sfile(FALSE); char_u *tofree = sname; if (sname == NULL) diff --git a/src/proto/scriptfile.pro b/src/proto/scriptfile.pro index fd4c1047389612..00f1301eeeefb6 100644 --- a/src/proto/scriptfile.pro +++ b/src/proto/scriptfile.pro @@ -4,7 +4,7 @@ estack_T *estack_push(etype_T type, char_u *name, long lnum); estack_T *estack_push_ufunc(ufunc_T *ufunc, long lnum); int estack_top_is_ufunc(ufunc_T *ufunc, long lnum); estack_T *estack_pop(void); -char_u *estack_sfile(void); +char_u *estack_sfile(int is_sfile); void ex_runtime(exarg_T *eap); int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); int do_in_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); diff --git a/src/scriptfile.c b/src/scriptfile.c index ce269a1cd2ac27..ce9c15d31bb0aa 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -111,58 +111,68 @@ estack_pop(void) /* * Get the current value for in allocated memory. + * "is_sfile" is TRUE for itself. */ char_u * -estack_sfile(void) +estack_sfile(int is_sfile) { estack_T *entry; #ifdef FEAT_EVAL + garray_T ga; size_t len; int idx; - char *res; - size_t done; + etype_T last_type = ETYPE_SCRIPT; + char *type_name; #endif entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1; - if (entry->es_name == NULL) - return NULL; #ifdef FEAT_EVAL - if (entry->es_info.ufunc == NULL) + if (is_sfile && entry->es_type != ETYPE_UFUNC) #endif + { + if (entry->es_name == NULL) + return NULL; return vim_strsave(entry->es_name); - + } #ifdef FEAT_EVAL + // Give information about each stack entry up to the root. // For a function we compose the call stack, as it was done in the past: // "function One[123]..Two[456]..Three" - len = STRLEN(entry->es_name) + 10; - for (idx = exestack.ga_len - 2; idx >= 0; --idx) + ga_init2(&ga, sizeof(char), 100); + for (idx = 0; idx < exestack.ga_len; ++idx) { entry = ((estack_T *)exestack.ga_data) + idx; - if (entry->es_name == NULL || entry->es_info.ufunc == NULL) + if (entry->es_name != NULL) { - ++idx; - break; + len = STRLEN(entry->es_name) + 15; + type_name = ""; + if (entry->es_type != last_type) + { + switch (entry->es_type) + { + case ETYPE_SCRIPT: type_name = "script "; break; + case ETYPE_UFUNC: type_name = "function "; break; + default: type_name = ""; break; + } + last_type = entry->es_type; + } + len += STRLEN(type_name); + if (ga_grow(&ga, len) == FAIL) + break; + if (idx == exestack.ga_len - 1 || entry->es_lnum == 0) + // For the bottom entry: do not add the line number, it is used + // in . Also leave it out when the number is not set. + vim_snprintf(ga.ga_data + ga.ga_len, len, "%s%s%s", + type_name, entry->es_name, + idx == exestack.ga_len - 1 ? "" : ".."); + else + vim_snprintf(ga.ga_data + ga.ga_len, len, "%s%s[%ld]..", + type_name, entry->es_name, entry->es_lnum); + ga.ga_len += STRLEN(ga.ga_data + ga.ga_len); } - len += STRLEN(entry->es_name) + 15; } - res = (char *)alloc((int)len); - if (res != NULL) - { - STRCPY(res, "function "); - while (idx < exestack.ga_len - 1) - { - done = STRLEN(res); - entry = ((estack_T *)exestack.ga_data) + idx; - vim_snprintf(res + done, len - done, "%s[%ld]..", - entry->es_name, entry->es_lnum); - ++idx; - } - done = STRLEN(res); - entry = ((estack_T *)exestack.ga_data) + idx; - vim_snprintf(res + done, len - done, "%s", entry->es_name); - } - return (char_u *)res; + return (char_u *)ga.ga_data; #endif } diff --git a/src/testdir/test_expand_func.vim b/src/testdir/test_expand_func.vim index 18437b75880b8d..41673e50afd985 100644 --- a/src/testdir/test_expand_func.vim +++ b/src/testdir/test_expand_func.vim @@ -16,17 +16,47 @@ func s:expand_sflnum() return str2nr(expand('')) endfunc -func Test_expand_sfile() +" This test depends on the location in the test file, put it first. +func Test_expand_sflnum() + call assert_equal(5, s:sflnum) + call assert_equal(22, str2nr(expand(''))) + + " Line-continuation + call assert_equal( + \ 25, + \ str2nr(expand(''))) + + " Call in script-local function + call assert_equal(16, s:expand_sflnum()) + + " Call in command + command Flnum echo expand('') + call assert_equal(34, str2nr(trim(execute('Flnum')))) + delcommand Flnum +endfunc + +func Test_expand_sfile_and_stack() call assert_match('test_expand_func\.vim$', s:sfile) - call assert_match('^function .*\.\.Test_expand_sfile$', expand('')) + let expected = 'script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack$' + call assert_match(expected , expand('')) + call assert_match(expected , expand('')) " Call in script-local function - call assert_match('^function .*\.\.Test_expand_sfile\[5\]\.\.\d\+_expand_sfile$', s:expand_sfile()) + call assert_match('script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack\[7\]\.\.\d\+_expand_sfile$', s:expand_sfile()) " Call in command command Sfile echo expand('') - call assert_match('^function .*\.\.Test_expand_sfile$', trim(execute('Sfile'))) + call assert_match('script .*testdir/runtest.vim\[\d\+\]\.\.function RunTheTest\[\d\+\]\.\.Test_expand_sfile_and_stack$', trim(execute('Sfile'))) delcommand Sfile + + " Use from sourced script. + let lines =<< trim END + let g:stack_value = expand('') + END + call writefile(lines, 'Xstack') + source Xstack + call assert_match('\'))) - - " Line-continuation - call assert_equal( - \ 55, - \ str2nr(expand(''))) - - " Call in script-local function - call assert_equal(16, s:expand_sflnum()) - - " Call in command - command Flnum echo expand('') - call assert_equal(64, str2nr(trim(execute('Flnum')))) - delcommand Flnum -endfunc - func Test_expand() new call assert_equal("", expand('%:S')) diff --git a/src/testing.c b/src/testing.c index de89bd9fd7fe98..137d5fe9f708ef 100644 --- a/src/testing.c +++ b/src/testing.c @@ -22,7 +22,7 @@ prepare_assert_error(garray_T *gap) { char buf[NUMBUFLEN]; - char_u *sname = estack_sfile(); + char_u *sname = estack_sfile(FALSE); ga_init2(gap, 1, 100); if (sname != NULL) diff --git a/src/version.c b/src/version.c index 6a5f19951e5e89..c45c15519c501c 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1297, /**/ 1296, /**/ From cb4f69c2fd9ea81331c4aa54877fde612d182a51 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 26 Jul 2020 15:51:06 +0200 Subject: [PATCH 0010/1384] patch 8.2.1298: compiler warning for unused argument in small version Problem: Compiler warning for unused argument in small version. Solution: Add UNUSED. --- src/scriptfile.c | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scriptfile.c b/src/scriptfile.c index ce9c15d31bb0aa..2a8320832ee7b2 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -114,7 +114,7 @@ estack_pop(void) * "is_sfile" is TRUE for itself. */ char_u * -estack_sfile(int is_sfile) +estack_sfile(int is_sfile UNUSED) { estack_T *entry; #ifdef FEAT_EVAL diff --git a/src/version.c b/src/version.c index c45c15519c501c..58a434a1b667bf 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1298, /**/ 1297, /**/ From d3bb6a82a51d549bbd597bb4e94d8f074009be2a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 26 Jul 2020 15:55:25 +0200 Subject: [PATCH 0011/1384] patch 8.2.1299: compiler warning for using size_t for int and void pointer Problem: Compiler warning for using size_t for int and void pointer. Solution: Add type casts. --- src/scriptfile.c | 8 ++++---- src/version.c | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/scriptfile.c b/src/scriptfile.c index 2a8320832ee7b2..b93e3513807f07 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -157,18 +157,18 @@ estack_sfile(int is_sfile UNUSED) last_type = entry->es_type; } len += STRLEN(type_name); - if (ga_grow(&ga, len) == FAIL) + if (ga_grow(&ga, (int)len) == FAIL) break; if (idx == exestack.ga_len - 1 || entry->es_lnum == 0) // For the bottom entry: do not add the line number, it is used // in . Also leave it out when the number is not set. - vim_snprintf(ga.ga_data + ga.ga_len, len, "%s%s%s", + vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s%s", type_name, entry->es_name, idx == exestack.ga_len - 1 ? "" : ".."); else - vim_snprintf(ga.ga_data + ga.ga_len, len, "%s%s[%ld]..", + vim_snprintf((char *)ga.ga_data + ga.ga_len, len, "%s%s[%ld]..", type_name, entry->es_name, entry->es_lnum); - ga.ga_len += STRLEN(ga.ga_data + ga.ga_len); + ga.ga_len += (int)STRLEN((char *)ga.ga_data + ga.ga_len); } } diff --git a/src/version.c b/src/version.c index 58a434a1b667bf..93bcc43247dc57 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1299, /**/ 1298, /**/ From 2547aa930b59f5e2bcb70e81d5a57ed461e59b4f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 26 Jul 2020 17:00:44 +0200 Subject: [PATCH 0012/1384] Update runtime files. --- runtime/autoload/decada.vim | 2 +- runtime/doc/arabic.txt | 4 +- runtime/doc/change.txt | 2 +- runtime/doc/cmdline.txt | 2 +- runtime/doc/digraph.txt | 4 +- runtime/doc/eval.txt | 6 +- runtime/doc/ft_sql.txt | 6 +- runtime/doc/map.txt | 9 +- runtime/doc/mbyte.txt | 10 +- runtime/doc/options.txt | 3 +- runtime/doc/os_unix.txt | 4 +- runtime/doc/repeat.txt | 2 +- runtime/doc/rileft.txt | 2 +- runtime/doc/sign.txt | 2 +- runtime/doc/syntax.txt | 2 +- runtime/doc/tags | 4 + runtime/doc/testing.txt | 2 +- runtime/doc/todo.txt | 72 +- runtime/doc/usr_27.txt | 2 +- runtime/doc/usr_90.txt | 2 +- runtime/doc/version6.txt | 2 +- runtime/doc/vim-da.1 | 2 +- runtime/doc/vim-da.UTF-8.1 | 2 +- runtime/doc/vim-fr.1 | 2 +- runtime/doc/vim-fr.UTF-8.1 | 2 +- runtime/doc/vim-it.1 | 2 +- runtime/doc/vim-it.UTF-8.1 | 2 +- runtime/doc/vim-pl.1 | 2 +- runtime/doc/vim-pl.UTF-8.1 | 2 +- runtime/doc/vim-tr.1 | 2 +- runtime/doc/vim-tr.UTF-8.1 | 2 +- runtime/doc/vim.1 | 2 +- runtime/doc/vim.man | 2 +- runtime/doc/vim9.txt | 61 +- runtime/ftplugin/cpp.vim | 9 +- runtime/ftplugin/diff.vim | 5 +- runtime/ftplugin/vim.vim | 4 +- runtime/indent/vim.vim | 3 +- .../dist/opt/termdebug/plugin/termdebug.vim | 2 +- runtime/syntax/aidl.vim | 23 + runtime/syntax/tex.vim | 53 +- runtime/syntax/vim.vim | 44 +- runtime/tutor/tutor.eo | 26 +- runtime/tutor/tutor.eo.utf-8 | 26 +- src/po/eo.po | 818 +++++++++++------- 45 files changed, 768 insertions(+), 474 deletions(-) create mode 100644 runtime/syntax/aidl.vim diff --git a/runtime/autoload/decada.vim b/runtime/autoload/decada.vim index 7741ff05728459..5124429a75914a 100644 --- a/runtime/autoload/decada.vim +++ b/runtime/autoload/decada.vim @@ -25,7 +25,7 @@ function decada#Unit_Name () dict " {{{1 " Convert filename into acs unit: " 1: remove the file extenstion. " 2: replace all double '_' or '-' with an dot (which denotes a separate) - " 3: remove a trailing '_' (wich denotes a specification) + " 3: remove a trailing '_' (which denotes a specification) return substitute (substitute (expand ("%:t:r"), '__\|-', ".", "g"), '_$', "", '') endfunction decada#Unit_Name " }}}1 diff --git a/runtime/doc/arabic.txt b/runtime/doc/arabic.txt index 97733b5db359f4..d1a92df64936f3 100644 --- a/runtime/doc/arabic.txt +++ b/runtime/doc/arabic.txt @@ -77,7 +77,7 @@ Arabic requires ISO-8859-6 as well as Presentation Form-B fonts (without Form-B, Arabic will _NOT_ be usable). It is highly recommended that users search for so-called 'ISO-10646-1' fonts. Do an Internet search or check www.arabeyes.org for further -info on where to attain the necessary Arabic fonts. +info on where to obtain the necessary Arabic fonts. Font Installation @@ -123,7 +123,7 @@ o Setting the appropriate character Encoding > :set encoding=utf-8 < - to your .vimrc file (entering the command manually into you Vim + to your .vimrc file (entering the command manually into your Vim window is highly discouraged). In short, include ':set encoding=utf-8' to your .vimrc file. diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 96177f35fcce19..36f72448cc46c7 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1755,7 +1755,7 @@ Some examples: Automatic formatting *auto-format* *autoformat* When the 'a' flag is present in 'formatoptions' text is formatted -automatically when inserting text or deleting text. This works nice for +automatically when inserting text or deleting text. This works nicely for editing text paragraphs. A few hints on how to use this: - You need to properly define paragraphs. The simplest is paragraphs that are diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index 8e4e2a0180d309..d2b3f6b460b74b 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -1,4 +1,4 @@ -*cmdline.txt* For Vim version 8.2. Last change: 2020 Apr 23 +*cmdline.txt* For Vim version 8.2. Last change: 2020 Jul 26 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/digraph.txt b/runtime/doc/digraph.txt index 191dc7bb113206..e24f7e945a343c 100644 --- a/runtime/doc/digraph.txt +++ b/runtime/doc/digraph.txt @@ -1,4 +1,4 @@ -*digraph.txt* For Vim version 8.2. Last change: 2019 May 05 +*digraph.txt* For Vim version 8.2. Last change: 2020 Jul 16 VIM REFERENCE MANUAL by Bram Moolenaar @@ -33,6 +33,8 @@ An alternative is using the 'keymap' option. it is the Unicode character, see |digraph-encoding|. Example: > :digr e: 235 a: 228 +< You can use `:exe` to enter a hex number: > + :exe 'digr += ' .. 0x2A72 < Avoid defining a digraph with '_' (underscore) as the first character, it has a special meaning in the future. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index ed4f8aab0ee01e..d8994ef00cf39d 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 Jul 19 +*eval.txt* For Vim version 8.2. Last change: 2020 Jul 21 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1994,6 +1994,8 @@ v:mouse_col Column number for a mouse click obtained with |getchar()|. *v:none* *none-variable* *None* v:none An empty String. Used to put an empty item in JSON. See |json_encode()|. + This can also be used as a function argument to use the + default value, see |none-function_argument|. When used as a number this evaluates to zero. When used as a string this evaluates to "v:none". > echo v:none @@ -11710,7 +11712,7 @@ The argument default expressions are evaluated at the time of the function call, not definition. Thus it is possible to use an expression which is invalid the moment the function is defined. The expressions are also only evaluated when arguments are not specified during a call. - + *none-function_argument* You can pass |v:none| to use the default expression. Note that this means you cannot pass v:none as an ordinary value when an argument has a default expression. diff --git a/runtime/doc/ft_sql.txt b/runtime/doc/ft_sql.txt index dbafa283447f00..e8490d50fb2e3e 100644 --- a/runtime/doc/ft_sql.txt +++ b/runtime/doc/ft_sql.txt @@ -312,7 +312,7 @@ can create any of the following: > $VIM/vimfiles/indent/sqlite.vim No changes are necessary to the SQLSetType function. It will automatically -pickup the new SQL files and load them when you issue the SQLSetType command. +pick up the new SQL files and load them when you issue the SQLSetType command. ============================================================================== @@ -519,7 +519,7 @@ beginning with those characters. > 4.3.2 Column Completion: *sql-completion-columns* The SQL completion plugin can also display a list of columns for particular -tables. The column completion is trigger via c. +tables. The column completion is triggered via c. NOTE: The following example uses to trigger a column list while the popup window is active. @@ -727,7 +727,7 @@ your platform (often a case on *nix) you define the following variable in your |vimrc|: > let g:omni_sql_no_default_maps = 1 -Do no edit ftplugin/sql.vim directly! If you change this file your changes +Do not edit ftplugin/sql.vim directly! If you change this file your changes will be over written on future updates. Vim has a special directory structure which allows you to make customizations without changing the files that are included with the Vim distribution. If you wish to customize the maps diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index c142f231b5c865..0ad43d449b7820 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -843,11 +843,10 @@ When modifyOtherKeys is enabled you can map and : > imap {{{ Without modifyOtherKeys and are indistinguishable from Esc. -A known side effect effect is that in Insert mode the raw escape sequence is -inserted after the CTRL-V key. This can be used to check whether -modifyOtherKeys is enabled: In Insert mode type CTRL-SHIFT-V CTRL-V, if you -get one byte then modifyOtherKeys is off, if you get <1b>27;5;118~ then it is -on. +A known side effect is that in Insert mode the raw escape sequence is inserted +after the CTRL-V key. This can be used to check whether modifyOtherKeys is +enabled: In Insert mode type CTRL-SHIFT-V CTRL-V, if you get one byte then +modifyOtherKeys is off, if you get <1b>27;5;118~ then it is on. When the 'esckeys' option is off, then modifyOtherKeys will be disabled in Insert mode to avoid every key with a modifier causing Insert mode to end. diff --git a/runtime/doc/mbyte.txt b/runtime/doc/mbyte.txt index 6a973fdc0d8107..bbfd5d38cf447b 100644 --- a/runtime/doc/mbyte.txt +++ b/runtime/doc/mbyte.txt @@ -128,7 +128,7 @@ There are several ways to enter multi-byte characters: - For MS-Windows IME can be used. See |IME|. - For all systems keymaps can be used. See |mbyte-keymap|. -The options 'iminsert', 'imsearch' and 'imcmdline' can be used to chose +The options 'iminsert', 'imsearch' and 'imcmdline' can be used to choose the different input methods or disable them temporarily. ============================================================================== @@ -141,8 +141,8 @@ in, or just use a certain locale inside Vim. WHAT IS A LOCALE? *locale* -There are many of languages in the world. And there are different cultures -and environments at least as much as the number of languages. A linguistic +There are many languages in the world. And there are different cultures and +environments at least as many as the number of languages. A linguistic environment corresponding to an area is called "locale". This includes information about the used language, the charset, collating order for sorting, date format, currency format and so on. For Vim only the language and charset @@ -889,7 +889,7 @@ input_server_name is your |IM-server| name (check your |IM-server| your_input_style is one of |OverTheSpot|, |OffTheSpot|, |Root|. See also |xim-input-style|. -*international may not necessary if you use X11R6. +*international may not be necessary if you use X11R6. *.inputMethod and *.preeditType are optional if you use X11R6. For example, when you are using kinput2 as |IM-server|, > @@ -952,7 +952,7 @@ automatically. This works on not only insert-normal mode, but also search-command input and replace mode. -The options 'iminsert', 'imsearch' and 'imcmdline' can be used to chose +The options 'iminsert', 'imsearch' and 'imcmdline' can be used to choose the different input methods or disable them temporarily. WHAT IS IME diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 6a9e2ed0e88aa1..d98307e30a9956 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 8.2. Last change: 2020 Jul 05 +*options.txt* For Vim version 8.2. Last change: 2020 Jul 18 VIM REFERENCE MANUAL by Bram Moolenaar @@ -7711,7 +7711,6 @@ A jump table for the options with a short description can be found at |Q_op|. on Amiga: "amiga" on Haiku: "xterm" on Mac: "mac-ansi" - on MiNT: "vt52" on Unix: "ansi" on VMS: "ansi" on Win 32: "win32") diff --git a/runtime/doc/os_unix.txt b/runtime/doc/os_unix.txt index 68788424f1182e..fa49db87501fed 100644 --- a/runtime/doc/os_unix.txt +++ b/runtime/doc/os_unix.txt @@ -30,8 +30,8 @@ can be changed at compile time. Because terminal updating under Unix is often slow (e.g. serial line terminal, shell window in suntools), the 'showcmd' and 'ruler' options -are default off. If you have a fast terminal, try setting them on. You might -also want to set 'ttyfast'. +are off by default. If you have a fast terminal, try setting them on. You +might also want to set 'ttyfast'. When using Vim in an xterm the mouse clicks can be used by Vim by setting 'mouse' to "a". If there is access to an X-server gui style copy/paste will diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt index 7b0efddbb8b8d6..d14e7d9180f962 100644 --- a/runtime/doc/repeat.txt +++ b/runtime/doc/repeat.txt @@ -642,7 +642,7 @@ disallowed though. This assumes you write one or more plugins that you distribute as a package. If you have two unrelated plugins you would use two packages, so that Vim -users can chose what they include or not. Or you can decide to use one +users can choose what they include or not. Or you can decide to use one package with optional plugins, and tell the user to add the ones he wants with `:packadd`. diff --git a/runtime/doc/rileft.txt b/runtime/doc/rileft.txt index 7a6c8c8608c895..81ced875cdebbb 100644 --- a/runtime/doc/rileft.txt +++ b/runtime/doc/rileft.txt @@ -69,7 +69,7 @@ o Invocations + 'rightleft' ('rl') sets window orientation to right-to-left. + 'delcombine' ('deco'), boolean, if editing UTF-8 encoded languages, allows one to remove a composing character which gets superimposed - on those that proceeded them (some languages require this). + on those that preceded them (some languages require this). + 'rightleftcmd' ('rlc') sets the command-line within certain modes (such as search) to be utilized in right-to-left orientation as well. diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index a8ce68541424af..1e88a62ffa0ddc 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -78,7 +78,7 @@ used by popup windows where 'cursorline' is set. *sign-priority* Each placed sign is assigned a priority value. When multiple signs are placed on the same line, the attributes of the sign with the highest priority is used -independent of the sign group. The default priority for a sign is 10. The +independently of the sign group. The default priority for a sign is 10. The priority is assigned at the time of placing a sign. When the line on which the sign is placed is deleted, the sign is moved to the diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 2096a34b518732..8effaf55a0b72c 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -1937,7 +1937,7 @@ new highlightings for the following groups.: Debug, DebugSpecial, DebugString, DebugBoolean, DebugType which are used for the statement itself, special characters used in debug strings, strings, boolean constants and types (this, super) respectively. I -have opted to chose another background for those statements. +have opted to choose another background for those statements. Javadoc is a program that takes special comments out of Java program files and creates HTML pages. The standard configuration will highlight this HTML code diff --git a/runtime/doc/tags b/runtime/doc/tags index 96022b70df6802..243b25ac60709f 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -1979,6 +1979,7 @@ $VIM_POSIX vi_diff.txt /*$VIM_POSIX* : cmdline.txt /*:* : cmdline.txt /*:* : cmdline.txt /*:* +: cmdline.txt /*:* := various.txt /*:=* :> change.txt /*:>* :? cmdline.txt /*:?* @@ -3647,6 +3648,7 @@ $VIM_POSIX vi_diff.txt /*$VIM_POSIX* cmdline.txt /** cmdline.txt /** cmdline.txt /** + cmdline.txt /** intro.txt /** term.txt /** term.txt /** @@ -3898,6 +3900,7 @@ E1050 vim9.txt /*E1050* E107 eval.txt /*E107* E108 eval.txt /*E108* E109 eval.txt /*E109* +E1092 vim9.txt /*E1092* E1094 vim9.txt /*E1094* E11 cmdline.txt /*E11* E110 eval.txt /*E110* @@ -8198,6 +8201,7 @@ no_plugin_maps filetype.txt /*no_plugin_maps* nocombine syntax.txt /*nocombine* non-greedy pattern.txt /*non-greedy* non-zero-arg eval.txt /*non-zero-arg* +none-function_argument eval.txt /*none-function_argument* none-variable eval.txt /*none-variable* normal-index index.txt /*normal-index* not-compatible usr_01.txt /*not-compatible* diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt index 53ed0818e47cbf..f1173a1f0bac73 100644 --- a/runtime/doc/testing.txt +++ b/runtime/doc/testing.txt @@ -1,4 +1,4 @@ -*testing.txt* For Vim version 8.2. Last change: 2020 Jul 09 +*testing.txt* For Vim version 8.2. Last change: 2020 Jul 11 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index a04a5112b411c3..f9ebf2d58ed82b 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 Jul 10 +*todo.txt* For Vim version 8.2. Last change: 2020 Jul 26 VIM REFERENCE MANUAL by Bram Moolenaar @@ -39,25 +39,36 @@ browser use: https://github.com/vim/vim/issues/1234 -------------------- Known bugs and current work ----------------------- Making everything work: -- in Vim9 script expressions are evaluated differently, not using a type. - e.g. "'' == 0" does not give an error and evaluates to true. -- cannot put # comment after assert() in :def function -- more return types depending on the first argument, like sort(). +- more items in https://github.com/vim/vim/issues/6507 +- More "goto failed" with check for trylevel. +- memory leak in test_vim9_script - Check that when sourcing a Vim9 script, only the global items can be used. - :put with a "=" register argument doesn't work, need to find the expression and compile it. (#6397) -- should "'text'->method()" work? 't is a range, but 'text isn't. +- At the script level, keep script variables local to the block they are + declared in? Need to remember what variables were declared and delete them + when leaving the block. +- Implement { } block at the script level. +- need to check type when a declaration specifies a type: #6507 + let nr: number = 'asdf' +- Make map() give an error if the resulting type is wrong. + Add mapnew() to create a new List/Dict for the result, which can have a + different value type. +- Implement "export {one, two three}". +- ISN_CHECKTYPE could use check_argtype() - Slice of list: [1, 2, 3][1:2]. +- give error for variable name: + let p = function('NoSuchFunc') - Give runtime error if function argument is wrong. def Increment(nr: number) range(3)->Increment() - Expand `=expr` in :next, :argedit, :argadd, :argdelete, :drop - Expand `=expr` in :vimgrep, :vimgrepadd, :lvimgrep, :lvimgrepadd - Expand `=expr` in :mkspell -- Make "true" and "false" work in vim9script - Test that a function defined inside a :def function is local to that function, g: functions can be defined and script-local functions cannot be defined. +- Support passing v:none to use the default argument value. (#6504) - make 0 == 'string' fail on the script level, like inside :def. - Check that when using a user function name without prefix, it does not find a global function. Prefixing g: is required. @@ -77,10 +88,6 @@ Making everything work: - memory leaks in test_vim9_cmd - When evaluating constants for script variables, some functions could work: has('asdf'), len('string') -- Support type for ":let"/":const" at script level for Vim9 script. - (Ben Jackson, #5671) - Can we share the code from ex_let_const() between direct execution and - compiling? - Implement "as Name" in "import Item as Name from ..." - Disallow unlet for local/script/imported vars - Make "++nr" work. @@ -91,6 +98,7 @@ Making everything work: - eval_expr() call in dbg_parsearg() and debuggy_find() - has() is compiled as a constant, but some checks are dynamic. Check for dynamic values, such as "gui_running". +- Implement command modifiers, such as "silent". (#6530) New syntax and functionality: Improve error checking: - "echo Func()" is an error if Func() does not return anything. @@ -139,11 +147,15 @@ Further improvements: Popup windows: - Cursor not updated before a redraw, making it jump. (#5943) +- Add a termcap entry for changing the cursor when it goes under the popup and + back. like t_SI and t_EI (t_SU and t_EU, where "U" means under?) - With terminal in popup, allow for popup_hide() to temporarily hide it.? - Fire some autocommand event after a new popup window was created and positioned? PopupNew? Could be used to set some options or move it out of the way. (#5737) However, it may also cause trouble, changing the popup of another plugin. +- Add a way to use popup_menu() synchronously: instead of invoking the + callback, return the choice. (Ben Jackson, #6534) - Use popup (or popup menu) for command line completion - 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) @@ -199,6 +211,9 @@ Terminal debugger: Terminal emulator window: - No support for underline color, t_8u. +- When in terminal-Normal mode when the job finishes, the cursor jumps to the + end but the window is not updated. This only happens when typing "a". + :term bash -c "for V in {0..5}; do echo $V; sleep 1; done" - When started with ":terminal ++close" and the shell exits but there is a background process, the window remains open, because the channel still exists (and output still shows). Perhaps close the window when an explicit @@ -238,7 +253,7 @@ Terminal emulator window: conversions. Error numbers available: -E489, E610, E611, E653, E856 +E610, E611, E653 Remove SPACE_IN_FILENAME ? It is only used for completion. @@ -269,8 +284,15 @@ autocommands for the buffer lifecycle: BufIsRenamed (after buffer ID gets another name) The buffer list and windows are locked, no changes possible -How about removing Atari MiNT support? - src/Make_mint.mak, src/os_mint.h, matches with __MINT__ +Make it possible to map (console and GUI): #6457 + 0x27 or is this ? + 0x28 + 0x29 + 0x30 + 0x31 + +Patch for Template string: #4634 +Have another look at the implementation. Add the <=> (spaceship) operator and "cond ?< expr ?= expr ?> expr" replace this: @@ -281,6 +303,13 @@ Add the <=> (spaceship) operator and "cond ?< expr ?= expr ?> expr" let res = GetLeftFunc() <=> GetRightFunc() ?< lower ?= equal ?> upper Patch to make :q work with local arglist. (Christian Brabandt, #6286) +Lua: updating wrong buffer when using newly created, unloaded buffer. +(#6539) + +When "+ register is set then "" points to it. If another Vim grabs the "+ +register, then "" doesn't contain anything. Make it still follow "+. +(#6435) + Patch to fix drawing error with DirectX. (James Grant, #5688) Causes flicker on resizing. Workaround from Ken Takata. How about only setting the attribute when part of the Vim window is offscreen? @@ -347,6 +376,10 @@ Test loose_clipboard() by selecting text before suspending. Undo puts cursor in wrong line after "cG" undo. +Implement completion for "breakadd". Should expand the second argument, e.g. +"func", and then function names after ":breakadd func". Including +script-local functions. + :unmap gives error but does remove the mapping. (Antony Scriven, 2019 Dec 19) @@ -386,10 +419,6 @@ behavior of i_CTRl-R_CTRL-R differs from documentation. (Paul Desmond Parker, goes to any buffer, and then :bnext skips help buffers, since they are unlisted. (#4478) -Patch for Template string: #4634 -Copies the text twice, not very efficient. Requires a separate implementation -for Vim9 script, compiling the string parts and expressions. - Statusline highlighting error, off by one. (#5599) ":find" with 'path' set to "data*" does not find files, while completion does @@ -1928,13 +1957,6 @@ Szamotulski, 2012 Nov 8) Session file creation: 'autochdir' causes trouble. Keep it off until after loading all files. -MS-Windows resizing problems: -- Windows window on screen positioning: Patch by Yukihiro Nakadaira, 2012 Jun - 20. Uses getWindowRect() instead of GetWindowPlacement() -- Win32: When the taskbar is at the top of the screen creating the tabbar - causes the window to move unnecessarily. (William E. Skeith III, 2012 Jan - 12) Patch: 2012 Jan 13 Needs more work (2012 Feb 2) - 'iminsert' global value set when using ":setlocal iminsert"? (Wu, 2012 Jun 23) Patch to append regexp to tag commands to make it possible to select one out diff --git a/runtime/doc/usr_27.txt b/runtime/doc/usr_27.txt index 47368441a34f07..fa8fdb6e1145a1 100644 --- a/runtime/doc/usr_27.txt +++ b/runtime/doc/usr_27.txt @@ -434,7 +434,7 @@ redefined without changing the search pattern. /\f\+ -The "\f" items stands for file name characters. Thus this matches a sequence +The "\f" item stands for file name characters. Thus this matches a sequence of characters that can be a file name. Which characters can be part of a file name depends on the system you are using. On MS-Windows, the backslash is included, on Unix it is not. This is diff --git a/runtime/doc/usr_90.txt b/runtime/doc/usr_90.txt index d5381a708b657c..c1f3641f0f21c8 100644 --- a/runtime/doc/usr_90.txt +++ b/runtime/doc/usr_90.txt @@ -226,7 +226,7 @@ We will use "82" here, which is version 8.2. This is all you need for the second method. Just launch the executable, and follow the prompts. -For the first method you must chose one of the binary archives. These are +For the first method you must choose one of the binary archives. These are available: gvim82.zip The normal MS-Windows GUI version. diff --git a/runtime/doc/version6.txt b/runtime/doc/version6.txt index 355cc79b51c0e2..3cd105b89c76c0 100644 --- a/runtime/doc/version6.txt +++ b/runtime/doc/version6.txt @@ -7882,7 +7882,7 @@ Files: src/buffer.c, src/ex_cmds.c, src/fileio.c, src/globals.h, Patch 6.1.221 Problem: Changing case may not work properly, depending on the current locale. -Solution: Add the 'casemap' option to let the user chose how changing case +Solution: Add the 'casemap' option to let the user choose how changing case is to be done. Also fix lowering case when an UTF-8 character doesn't keep the same byte length. diff --git a/runtime/doc/vim-da.1 b/runtime/doc/vim-da.1 index 3437bbcd2d985c..669974132f53c1 100644 --- a/runtime/doc/vim-da.1 +++ b/runtime/doc/vim-da.1 @@ -147,7 +147,7 @@ Se ":help search\-pattern" for tilg {kommando} fortolkes som en Ex-kommando. Hvis {kommando} indeholder mellemrum, s skal den omsluttes af dobbelte citationstegn (det afhnger af den skal der bruges). -Eksempel: Vim "+set si" main.c +Eksempel: vim "+set si" main.c .br Bemrk: Du kan bruge op til 10 "+"- eller "\-c"-kommandoer. .TP diff --git a/runtime/doc/vim-da.UTF-8.1 b/runtime/doc/vim-da.UTF-8.1 index f619e4a0548228..97e06a02b19c48 100644 --- a/runtime/doc/vim-da.UTF-8.1 +++ b/runtime/doc/vim-da.UTF-8.1 @@ -147,7 +147,7 @@ Se ":help search\-pattern" for tilgængelige søgemønstre. {kommando} fortolkes som en Ex-kommando. Hvis {kommando} indeholder mellemrum, så skal den omsluttes af dobbelte citationstegn (det afhænger af den skal der bruges). -Eksempel: Vim "+set si" main.c +Eksempel: vim "+set si" main.c .br Bemærk: Du kan bruge op til 10 "+"- eller "\-c"-kommandoer. .TP diff --git a/runtime/doc/vim-fr.1 b/runtime/doc/vim-fr.1 index 209ab915c951f2..ede25ff2cc224b 100644 --- a/runtime/doc/vim-fr.1 +++ b/runtime/doc/vim-fr.1 @@ -156,7 +156,7 @@ Ex {commande} est interprte comme une commande Ex. Si la {commande} contient des espaces, elle doit tre entoure de doubles-apostrophes (cela dpend du shell utilis). -Exemple : Vim "+set si" main.c +Exemple : vim "+set si" main.c .br Note : vous pouvez utiliser jusqu' 10 commandes "+" ou "\-c". .TP diff --git a/runtime/doc/vim-fr.UTF-8.1 b/runtime/doc/vim-fr.UTF-8.1 index 67be1066733595..453772229e98cf 100644 --- a/runtime/doc/vim-fr.UTF-8.1 +++ b/runtime/doc/vim-fr.UTF-8.1 @@ -156,7 +156,7 @@ Exécute {commande} après la lecture du premier fichier. {commande} est interprétée comme une commande Ex. Si la {commande} contient des espaces, elle doit être entourée de doubles-apostrophes (cela dépend du shell utilisé). -Exemple : Vim "+set si" main.c +Exemple : vim "+set si" main.c .br Note : vous pouvez utiliser jusqu'à 10 commandes "+" ou "\-c". .TP diff --git a/runtime/doc/vim-it.1 b/runtime/doc/vim-it.1 index 0ab3eff0d2ed2a..75d0ea94d036b4 100644 --- a/runtime/doc/vim-it.1 +++ b/runtime/doc/vim-it.1 @@ -150,7 +150,7 @@ primo file {comando} interpretato come un comando Ex. Se il {comando} contiene spazi deve essere incluso fra doppi apici (o altro delimitatore, a seconda della shell che si sta usando). -Esempio: Vim "+set si" main.c +Esempio: vim "+set si" main.c .br Note: Si possono avere fino a 10 comandi "+" o "\-c". .TP diff --git a/runtime/doc/vim-it.UTF-8.1 b/runtime/doc/vim-it.UTF-8.1 index 51e7e043da20d0..80c18262f5a695 100644 --- a/runtime/doc/vim-it.UTF-8.1 +++ b/runtime/doc/vim-it.UTF-8.1 @@ -150,7 +150,7 @@ primo file è stato letto. {comando} è interpretato come un comando Ex. Se il {comando} contiene spazi deve essere incluso fra doppi apici (o altro delimitatore, a seconda della shell che si sta usando). -Esempio: Vim "+set si" main.c +Esempio: vim "+set si" main.c .br Note: Si possono avere fino a 10 comandi "+" o "\-c". .TP diff --git a/runtime/doc/vim-pl.1 b/runtime/doc/vim-pl.1 index d506b33c98691f..c1ec05f03227cb 100644 --- a/runtime/doc/vim-pl.1 +++ b/runtime/doc/vim-pl.1 @@ -150,7 +150,7 @@ wzorce wyszukiwania. {polecenie} jest interpretowane jako polecenie Ex. Jeli {poleceni} zawiera biae znaki musi by umieszczone w podwjnych cudzysowach (zaley to od uywanej powoki). -Przykad: Vim "+set si" main.c +Przykad: vim "+set si" main.c .br Uwaga: Mona uy do 10 polece "+" lub "\-c". .TP diff --git a/runtime/doc/vim-pl.UTF-8.1 b/runtime/doc/vim-pl.UTF-8.1 index f3551d2f635d34..26c1b11de20f09 100644 --- a/runtime/doc/vim-pl.UTF-8.1 +++ b/runtime/doc/vim-pl.UTF-8.1 @@ -150,7 +150,7 @@ wzorce wyszukiwania. {polecenie} jest interpretowane jako polecenie Ex. Jeśli {poleceni} zawiera białe znaki musi być umieszczone w podwójnych cudzysłowach (zależy to od używanej powłoki). -Przykład: Vim "+set si" main.c +Przykład: vim "+set si" main.c .br Uwaga: Można użyć do 10 poleceń "+" lub "\-c". .TP diff --git a/runtime/doc/vim-tr.1 b/runtime/doc/vim-tr.1 index c1f5a35290413e..8e7bb4f4121163 100644 --- a/runtime/doc/vim-tr.1 +++ b/runtime/doc/vim-tr.1 @@ -145,7 +145,7 @@ Kullan {komut} bir Ex komutu olarak iletilir. Eer {komut} boluk ieriyorsa ift trnak ierisine alnmaldr (bu kullanlan kabua baldr). -rnek: Vim "+set si" main.c +rnek: vim "+set si" main.c .br Not: 10 taneye kadar "+" veya "\-c" komutu kullanabilirsiniz. .TP diff --git a/runtime/doc/vim-tr.UTF-8.1 b/runtime/doc/vim-tr.UTF-8.1 index 0e25734633be02..c41980541b1301 100644 --- a/runtime/doc/vim-tr.UTF-8.1 +++ b/runtime/doc/vim-tr.UTF-8.1 @@ -145,7 +145,7 @@ Kullanılabilir arama dizgileri için ":help search\-pattern" yazın. {komut} bir Ex komutu olarak işletilir. Eğer {komut} boşluk içeriyorsa çift tırnak içerisine alınmalıdır (bu kullanılan kabuğa bağlıdır). -Örnek: Vim "+set si" main.c +Örnek: vim "+set si" main.c .br Not: 10 taneye kadar "+" veya "\-c" komutu kullanabilirsiniz. .TP diff --git a/runtime/doc/vim.1 b/runtime/doc/vim.1 index d19317d4dc0cba..a2ca0e28a3493e 100644 --- a/runtime/doc/vim.1 +++ b/runtime/doc/vim.1 @@ -146,7 +146,7 @@ See ":help search\-pattern" for the available search patterns. {command} is interpreted as an Ex command. If the {command} contains spaces it must be enclosed in double quotes (this depends on the shell that is used). -Example: Vim "+set si" main.c +Example: vim "+set si" main.c .br Note: You can use up to 10 "+" or "\-c" commands. .TP diff --git a/runtime/doc/vim.man b/runtime/doc/vim.man index c90547574df2aa..e905a82e6d1c1f 100644 --- a/runtime/doc/vim.man +++ b/runtime/doc/vim.man @@ -110,7 +110,7 @@ OPTIONS read. {command} is interpreted as an Ex command. If the {command} contains spaces it must be enclosed in double quotes (this depends on the shell that is used). Example: - Vim "+set si" main.c + vim "+set si" main.c Note: You can use up to 10 "+" or "-c" commands. -S {file} {file} will be sourced after the first file has been read. diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 748dd7cd553674..2ba2275274e176 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -1,4 +1,4 @@ -*vim9.txt* For Vim version 8.2. Last change: 2020 Jul 17 +*vim9.txt* For Vim version 8.2. Last change: 2020 Jul 25 VIM REFERENCE MANUAL by Bram Moolenaar @@ -184,8 +184,9 @@ To intentionally avoid a variable being available later, a block can be used: echo temp " Error! An existing variable cannot be assigned to with `:let`, since that implies a -declaration. An exception is global variables: these can be both used with -and without `:let`, because there is no rule about where they are declared. +declaration. Global, window, tab, buffer and Vim variables can only be used +without `:let`, because they are are not really declared, they can also be +deleted with `:unlet`. Variables cannot shadow previously defined variables. Variables may shadow Ex commands, rename the variable if needed. @@ -194,12 +195,19 @@ Global variables and user defined functions must be prefixed with "g:", also at the script level. > vim9script let script_local = 'text' - let g:global = 'value' + g:global = 'value' let Funcref = g:ThatFunction Since "&opt = value" is now assigning a value to option "opt", ":&" cannot be used to repeat a `:substitute` command. + *E1092* +Declaring more than one variable at a time, using the unpack notation, is +currently not supported: > + let [v1, v2] = GetValues() # Error! +That is because the type needs to be inferred from the list item type, which +isn't that easy. + Omitting :call and :eval ~ @@ -209,15 +217,15 @@ Using `:call` is still possible, but this is discouraged. A method call without `eval` is possible, so long as the start is an identifier or can't be an Ex command. It does NOT work for string constants: > - myList->add(123) " works - g:myList->add(123) " works - [1, 2, 3]->Process() " works - #{a: 1, b: 2}->Process() " works - {'a': 1, 'b': 2}->Process() " works - "foobar"->Process() " does NOT work - ("foobar")->Process() " works - 'foobar'->Process() " does NOT work - ('foobar')->Process() " works + myList->add(123) # works + g:myList->add(123) # works + [1, 2, 3]->Process() # works + #{a: 1, b: 2}->Process() # works + {'a': 1, 'b': 2}->Process() # works + "foobar"->Process() # does NOT work + ("foobar")->Process() # works + 'foobar'->Process() # does NOT work + ('foobar')->Process() # works In case there is ambiguity between a function name and an Ex command, use ":" to make clear you want to use the Ex command. For example, there is both the @@ -277,10 +285,14 @@ possible just before or after the operator. For example: > ? PosFunc(arg) : NegFunc(arg) +For a method call using "->" and a member using a dot, a line break is allowed +before it: > let result = GetBuilder() ->BuilderSetWidth(333) ->BuilderSetHeight(777) ->BuilderBuild() + let result = MyDict + .member < *E1050* To make it possible for the operator at the start of the line to be @@ -486,19 +498,20 @@ THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE When the caller omits an argument the {value} is used. The function will be compiled into instructions when - called, or when `:defcompile` is used. Syntax and - type errors will be produced at that time. + called, or when `:disassemble` or `:defcompile` is + used. Syntax and type errors will be produced at that + time. - NOTE: It is possible to nest `:def` inside another - `:def`, but it is not possible to nest `:def` inside - `:function`, for backwards compatibility. + It is possible to nest `:def` inside another `:def` or + `:function` up to about 50 levels deep. [!] is used as with `:function`. Note that in Vim9 script script-local functions cannot be deleted or redefined later in the same script. *:enddef* -:enddef End of a function defined with `:def`. +:enddef End of a function defined with `:def`. It should be on + a line by its own. If the script the function is defined in is Vim9 script, then script-local @@ -559,7 +572,7 @@ Not supported yet: tuple These types can be used in declarations, but no value will have this type: - {type}|{type} + {type}|{type} {not implemented yet} void any @@ -661,19 +674,15 @@ The original value of 'cpoptions' is restored at the end of the script. Export ~ *:export* *:exp* -Exporting one item can be written as: > +Exporting an item can be written as: > export const EXPORTED_CONST = 1234 export let someValue = ... export def MyFunc() ... export class MyClass ... As this suggests, only constants, variables, `:def` functions and classes can -be exported. +be exported. {classes are not implemented yet} -Alternatively, an export statement can be used to export several already -defined (otherwise script-local) items: > - export {EXPORTED_CONST, someValue, MyFunc, MyClass} -< *E1042* `:export` can only be used in Vim9 script, at the script level. diff --git a/runtime/ftplugin/cpp.vim b/runtime/ftplugin/cpp.vim index 8c3f211da8f58a..f9d31cbec357ff 100644 --- a/runtime/ftplugin/cpp.vim +++ b/runtime/ftplugin/cpp.vim @@ -1,12 +1,17 @@ " Vim filetype plugin file " Language: C++ " Maintainer: Bram Moolenaar -" Last Change: 2001 Jan 15 +" Last Change: 2020 Jul 26 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") finish endif -" Behaves just like C +" Behaves mostly just like C runtime! ftplugin/c.vim ftplugin/c_*.vim ftplugin/c/*.vim + +" C++ uses templates with +" Disabled, because it gives an error for typing an unmatched ">". +" set matchpairs+=<:> +" let b:undo_ftplugin ..= ' | setl matchpairs<' diff --git a/runtime/ftplugin/diff.vim b/runtime/ftplugin/diff.vim index 3fe1b84a043785..04642904756e02 100644 --- a/runtime/ftplugin/diff.vim +++ b/runtime/ftplugin/diff.vim @@ -1,7 +1,7 @@ " Vim filetype plugin file " Language: Diff " Maintainer: Bram Moolenaar -" Last Change: 2005 Jul 27 +" Last Change: 2020 Jul 18 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -13,3 +13,6 @@ let b:undo_ftplugin = "setl modeline<" " Don't use modelines in a diff, they apply to the diffed file setlocal nomodeline + +" If there are comments they start with # +let &commentstring = "# %s" diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim index b2db4ab9fd1be8..b2d571093db043 100644 --- a/runtime/ftplugin/vim.vim +++ b/runtime/ftplugin/vim.vim @@ -1,7 +1,7 @@ " Vim filetype plugin " Language: Vim " Maintainer: Bram Moolenaar -" Last Change: 2020 Jul 06 +" Last Change: 2020 Jul 26 " Only do this when not done yet for this buffer if exists("b:did_ftplugin") @@ -83,7 +83,7 @@ endif if exists("loaded_matchit") let b:match_ignorecase = 0 let b:match_words = - \ '\<\%(fu\%[nction]\|def\)\>:\:\<\%(endf\%[unction]\|enddef\)\>,' . + \ '\<\%(fu\%[nction]\|def\)\>[^(]:\:\<\%(endf\%[unction]\|enddef\)\>,' . \ '\<\(wh\%[ile]\|for\)\>:\:\:\,' . \ '\:\:\,' . \ '{:},' . diff --git a/runtime/indent/vim.vim b/runtime/indent/vim.vim index b0c0a3916a40d4..3809943388c794 100644 --- a/runtime/indent/vim.vim +++ b/runtime/indent/vim.vim @@ -1,7 +1,7 @@ " Vim indent file " Language: Vim script " Maintainer: Bram Moolenaar -" Last Change: 2019 Oct 31 +" Last Change: 2020 Jul 19 " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -11,6 +11,7 @@ let b:did_indent = 1 setlocal indentexpr=GetVimIndent() setlocal indentkeys+==end,=},=else,=cat,=fina,=END,0\\,0=\"\\\ +setlocal indentkeys-=0# let b:undo_indent = "setl indentkeys< indentexpr<" diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index ace01227891834..6680b48cce02db 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -2,7 +2,7 @@ " " Author: Bram Moolenaar " Copyright: Vim license applies, see ":help license" -" Last Change: 2020 Jun 12 +" Last Change: 2020 Jul 12 " " WORK IN PROGRESS - Only the basics work " Note: On MS-Windows you need a recent version of gdb. The one included with diff --git a/runtime/syntax/aidl.vim b/runtime/syntax/aidl.vim new file mode 100644 index 00000000000000..1947ab97d8b2c2 --- /dev/null +++ b/runtime/syntax/aidl.vim @@ -0,0 +1,23 @@ +" Vim syntax file +" Language: aidl (Android Interface Definition Language) +" https://developer.android.com/guide/components/aidl +" Maintainer: Dominique Pelle +" LastChange: 2020/07/25 + +" Quit when a syntax file was already loaded. +if exists("b:current_syntax") + finish +endif + +source :p:h/java.vim + +syn keyword aidlParamDir in out inout +syn keyword aidlKeyword oneway parcelable + +" Needed for the 'in', 'out', 'inout' keywords to be highlighted. +syn cluster javaTop add=aidlParamDir + +hi def link aidlParamDir StorageClass +hi def link aidlKeyword Keyword + +let b:current_syntax = "aidl" diff --git a/runtime/syntax/tex.vim b/runtime/syntax/tex.vim index b3a8f96b6b9267..ec0f7b99bdfccf 100644 --- a/runtime/syntax/tex.vim +++ b/runtime/syntax/tex.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: TeX " Maintainer: Charles E. Campbell -" Last Change: Jun 07, 2020 -" Version: 118 +" Last Change: Jun 29, 2020 +" Version: 119 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TEX " " Notes: {{{1 @@ -147,6 +147,11 @@ if exists("g:tex_nospell") && g:tex_nospell else let s:tex_nospell = 0 endif +if exists("g:tex_matchcheck") + let s:tex_matchcheck= g:tex_matchcheck +else + let s:tex_matchcheck= '[({[]' +endif if exists("g:tex_excludematcher") let s:tex_excludematcher= g:tex_excludematcher else @@ -205,27 +210,41 @@ if !exists("g:tex_no_math") endif endif -" Try to flag {} and () mismatches: {{{1 +" Try to flag {}, [], and () mismatches: {{{1 if s:tex_fast =~# 'm' if !s:tex_no_error - syn region texMatcher matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchGroup,texError - syn region texMatcher matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchGroup,texError,@NoSpell - syn region texMatcherNM matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchNMGroup,texError - syn region texMatcherNM matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchNMGroup,texError,@NoSpell + if s:tex_matchcheck =~ '{' + syn region texMatcher matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchGroup,texError + syn region texMatcherNM matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchNMGroup,texError + endif + if s:tex_matchcheck =~ '\[' + syn region texMatcher matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchGroup,texError,@NoSpell + syn region texMatcherNM matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchNMGroup,texError,@NoSpell + endif else - syn region texMatcher matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchGroup - syn region texMatcher matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchGroup - syn region texMatcherNM matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchNMGroup - syn region texMatcherNM matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchNMGroup + if s:tex_matchcheck =~ '{' + syn region texMatcher matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchGroup + syn region texMatcherNM matchgroup=Delimiter start="{" skip="\\\\\|\\[{}]" end="}" transparent contains=@texMatchNMGroup + endif + if s:tex_matchcheck =~ '\[' + syn region texMatcher matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchGroup + syn region texMatcherNM matchgroup=Delimiter start="\[" end="]" transparent contains=@texMatchNMGroup + endif endif - if !s:tex_nospell - syn region texParen start="(" end=")" transparent contains=@texMatchGroup,@Spell - else - syn region texParen start="(" end=")" transparent contains=@texMatchGroup + if s:tex_matchcheck =~ '(' + if !s:tex_nospell + syn region texParen start="(" end=")" transparent contains=@texMatchGroup,@Spell + else + syn region texParen start="(" end=")" transparent contains=@texMatchGroup + endif endif endif if !s:tex_no_error - syn match texError "[}\])]" + if s:tex_matchcheck =~ '(' + syn match texError "[}\]]" + else + syn match texError "[}\])]" + endif endif if s:tex_fast =~# 'M' if !exists("g:tex_no_math") @@ -756,7 +775,7 @@ if has("conceal") && &enc == 'utf-8' \ ['ldots' , '…'], \ ['le' , '≤'], \ ['left|' , '|'], - \ ['left\|' , '‖'], + \ ['left\\|' , '‖'], \ ['left(' , '('], \ ['left\[' , '['], \ ['left\\{' , '{'], diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index d01cc40bb94eef..9b20392fa22040 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -1,8 +1,8 @@ " Vim syntax file " Language: Vim 8.0 script " Maintainer: Charles E. Campbell -" Last Change: Jun 01, 20200 -" Version: 8.0-37 +" Last Change: July 15, 2020 +" Version: 8.0-41 " URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_VIM " Automatically generated keyword lists: {{{1 @@ -29,14 +29,14 @@ syn match vimCommand contained "\" syn keyword vimStdPlugin contained Arguments Break Cfilter Clear Continue DiffOrig Evaluate Finish Gdb Lfilter Man N[ext] Over P[rint] Program Run S Source Step Stop Termdebug TermdebugCommand TOhtml Winbar XMLent XMLns " vimOptions are caught only when contained in a vimSet {{{2 -syn keyword vimOption contained acd ambw arshape background ballooneval bex bl brk buftype cf cinkeys cmdwinheight com completeslash cpoptions cscoperelative csre cursorcolumn delcombine digraph eadirection emo equalprg expandtab fdls fex fileignorecase fml foldlevel formatexpr gcr go guifontset helpheight history hlsearch imaf ims includeexpr infercase iskeyword keywordprg laststatus lispwords lrm magic maxfuncdepth menuitems mm modifiable mousemodel mzq numberwidth opfunc patchexpr pfn pp printfont pumwidth pythonthreehome re restorescreen ro rulerformat scl scs sft shellredir shiftwidth showmatch signcolumn smarttab sp spf srr startofline suffixes switchbuf ta tagfunc tbi term termwintype tgc titlelen toolbariconsize ttimeout ttymouse twt undofile varsofttabstop verbosefile viminfofile wak weirdinvert wig wildoptions winheight wm wrapscan -syn keyword vimOption contained ai anti autochdir backspace balloonevalterm bexpr bo browsedir casemap cfu cino cmp comments concealcursor cpp cscopetag cst cursorline dex dip eb emoji errorbells exrc fdm ff filetype fmr foldlevelstart formatlistpat gd gp guifontwide helplang hk ic imak imsearch incsearch insertmode isp km lazyredraw list ls makeef maxmapdepth mfd mmd modified mouses mzquantum nuw osfiletype patchmode ph preserveindent printheader pvh pyx readonly revins rop runtimepath scr sect sh shellslash shm showmode siso smc spc spl ss statusline suffixesadd sws tabline taglength tbidi termbidi terse tgst titleold top ttimeoutlen ttyscroll tx undolevels vartabstop vfile virtualedit warn wfh wildchar wim winminheight wmh write -syn keyword vimOption contained akm antialias autoindent backup balloonexpr bg bomb bs cb ch cinoptions cms commentstring conceallevel cpt cscopetagorder csto cursorlineopt dg dir ed enc errorfile fcl fdn ffs fillchars fo foldmarker formatoptions gdefault grepformat guiheadroom hf hkmap icon imc imsf inde is isprint kmp lbr listchars lsp makeencoding maxmem mh mmp more mouseshape mzschemedll odev pa path pheader previewheight printmbcharset pvp pyxversion redrawtime ri rs sb scroll sections shcf shelltemp shortmess showtabline sj smd spell splitbelow ssl stl sw sxe tabpagemax tagrelative tbis termencoding textauto thesaurus titlestring tpm ttm ttytype uc undoreload vb vi visualbell wb wfw wildcharm winaltkeys winminwidth wmnu writeany -syn keyword vimOption contained al ar autoread backupcopy bdir bh breakat bsdir cc charconvert cinw co compatible confirm crb cscopeverbose csverb cwh dict directory edcompatible encoding errorformat fcs fdo fic fixendofline foldclose foldmethod formatprg gfm grepprg guioptions hh hkmapp iconstring imcmdline imst indentexpr isf joinspaces kp lcs lm luadll makeprg maxmempattern mis mmt mouse mouset mzschemegcdll oft packpath pdev pi previewpopup printmbfont pvw qe regexpengine rightleft rtp sbo scrollbind secure shell shelltype shortname shq slm sn spellcapcheck splitright ssop stmp swapfile sxq tabstop tags tbs termguicolors textmode tildeop tl tr tty tw udf updatecount vbs viewdir vop wc wh wildignore wincolor winptydll wmw writebackup -syn keyword vimOption contained aleph arab autowrite backupdir bdlay bin breakindent bsk ccv ci cinwords cocu complete copyindent cryptmethod csl cuc debug dictionary display ef endofline esckeys fdc fdt fileencoding fixeol foldcolumn foldminlines fp gfn gtl guipty hi hkp ignorecase imd imstatusfunc indentkeys isfname js langmap linebreak lmap lw mat maxmemtot mkspellmem mod mousef mousetime nf ofu para penc pm previewwindow printoptions pw qftf relativenumber rightleftcmd ru sbr scrollfocus sel shellcmdflag shellxescape showbreak si sm so spellfile spr st sts swapsync syn tag tagstack tc termwinkey textwidth timeout tm ts ttybuiltin twk udir updatetime vdir viewoptions vsts wcm whichwrap wildignorecase window winwidth wop writedelay -syn keyword vimOption contained allowrevins arabic autowriteall backupext belloff binary breakindentopt bt cd cin clipboard cole completefunc cot cscopepathcomp cspc cul deco diff dy efm eol et fde fen fileencodings fk foldenable foldnestmax fs gfs gtt guitablabel hid hl im imdisable imstyle indk isi key langmenu lines lnr lz matchpairs mco ml modeline mousefocus mp nrformats omnifunc paragraphs perldll pmbcs printdevice prompt pythondll quickfixtextfunc remap rl rubydll sc scrolljump selection shellpipe shellxquote showcmd sidescroll smartcase softtabstop spelllang sps sta su swb synmaxcol tagbsearch tal tcldll termwinscroll tf timeoutlen to tsl ttyfast tws ul ur ve vif vts wcr wi wildmenu winfixheight wiv wrap ws -syn keyword vimOption contained altkeymap arabicshape aw backupskip beval bk bri bufhidden cdpath cindent cm colorcolumn completeopt cp cscopeprg csprg culopt def diffexpr ea ei ep eventignore fdi fenc fileformat fkmap foldexpr foldopen fsync gfw guicursor guitabtooltip hidden hlg imactivatefunc imi inc inex isident keymap langnoremap linespace loadplugins ma matchtime mef mle modelineexpr mousehide mps nu opendevice paste pex pmbfn printencoding pt pythonhome quoteescape renderoptions rlc ruf scb scrolloff selectmode shellquote shiftround showfulltag sidescrolloff smartindent sol spellsuggest sr stal sua swf syntax tagcase tb tenc termwinsize tfu title toolbar tsr ttym twsl undodir ut verbose viminfo wa wd wic wildmode winfixwidth wiw wrapmargin ww -syn keyword vimOption contained ambiwidth ari awa balloondelay bevalterm bkc briopt buflisted cedit cink cmdheight columns completepopup cpo cscopequickfix csqf cursorbind define diffopt ead ek equalalways ex fdl fencs fileformats flp foldignore foldtext ft ghr guifont helpfile highlight hls imactivatekey iminsert include inf isk keymodel langremap lisp lpl macatsui maxcombine menc mls modelines mousem msm number operatorfunc pastetoggle pexpr popt printexpr pumheight pythonthreedll rdt report rnu ruler scf scrollopt sessionoptions +syn keyword vimOption contained acd ambw arshape background ballooneval bex bl brk buftype cf cinkeys cmdwinheight com completeslash cpoptions cscoperelative csre cursorcolumn delcombine digraph eadirection emo equalprg expandtab fdls fex fileignorecase fml foldlevel formatexpr gcr go guifontset helpheight history hlsearch imaf ims includeexpr infercase iskeyword keywordprg laststatus lispwords lrm magic maxfuncdepth menuitems mm modifiable mousemodel mzq numberwidth opfunc patchexpr pfn pp printfont pumwidth pythonthreehome re restorescreen ro rulerformat scl scs sft shellslash shortmess showtabline sj smd spell spl srr startofline suffixes switchbuf ta tagfunc tbi term termwintype tgc titlelen toolbariconsize ttimeout ttymouse twt undofile varsofttabstop verbosefile viminfofile wak weirdinvert wig wildoptions winheight wm wrapscan +syn keyword vimOption contained ai anti autochdir backspace balloonevalterm bexpr bo browsedir casemap cfu cino cmp comments concealcursor cpp cscopetag cst cursorline dex dip eb emoji errorbells exrc fdm ff filetype fmr foldlevelstart formatlistpat gd gp guifontwide helplang hk ic imak imsearch incsearch insertmode isp km lazyredraw list ls makeef maxmapdepth mfd mmd modified mouses mzquantum nuw osfiletype patchmode ph preserveindent printheader pvh pyx readonly revins rop runtimepath scr sect sh shelltemp shortname shq slm sn spellcapcheck splitbelow ss statusline suffixesadd sws tabline taglength tbidi termbidi terse tgst titleold top ttimeoutlen ttyscroll tx undolevels vartabstop vfile virtualedit warn wfh wildchar wim winminheight wmh write +syn keyword vimOption contained akm antialias autoindent backup balloonexpr bg bomb bs cb ch cinoptions cms commentstring conceallevel cpt cscopetagorder csto cursorlineopt dg dir ed enc errorfile fcl fdn ffs fillchars fo foldmarker formatoptions gdefault grepformat guiheadroom hf hkmap icon imc imsf inde is isprint kmp lbr listchars lsp makeencoding maxmem mh mmp more mouseshape mzschemedll odev pa path pheader previewheight printmbcharset pvp pyxversion redrawtime ri rs sb scroll sections shcf shelltype showbreak si sm so spellfile splitright ssl stl sw sxe tabpagemax tagrelative tbis termencoding textauto thesaurus titlestring tpm ttm ttytype uc undoreload vb vi visualbell wb wfw wildcharm winaltkeys winminwidth wmnu writeany +syn keyword vimOption contained al ar autoread backupcopy bdir bh breakat bsdir cc charconvert cinw co compatible confirm crb cscopeverbose csverb cwh dict directory edcompatible encoding errorformat fcs fdo fic fixendofline foldclose foldmethod formatprg gfm grepprg guioptions hh hkmapp iconstring imcmdline imst indentexpr isf joinspaces kp lcs lm luadll makeprg maxmempattern mis mmt mouse mouset mzschemegcdll oft packpath pdev pi previewpopup printmbfont pvw qe regexpengine rightleft rtp sbo scrollbind secure shell shellxescape showcmd sidescroll smartcase softtabstop spelllang spo ssop stmp swapfile sxq tabstop tags tbs termguicolors textmode tildeop tl tr tty tw udf updatecount vbs viewdir vop wc wh wildignore wincolor winptydll wmw writebackup +syn keyword vimOption contained aleph arab autowrite backupdir bdlay bin breakindent bsk ccv ci cinwords cocu complete copyindent cryptmethod csl cuc debug dictionary display ef endofline esckeys fdc fdt fileencoding fixeol foldcolumn foldminlines fp gfn gtl guipty hi hkp ignorecase imd imstatusfunc indentkeys isfname js langmap linebreak lmap lw mat maxmemtot mkspellmem mod mousef mousetime nf ofu para penc pm previewwindow printoptions pw qftf relativenumber rightleftcmd ru sbr scrollfocus sel shellcmdflag shellxquote showfulltag sidescrolloff smartindent sol spelloptions spr st sts swapsync syn tag tagstack tc termwinkey textwidth timeout tm ts ttybuiltin twk udir updatetime vdir viewoptions vsts wcm whichwrap wildignorecase window winwidth wop writedelay +syn keyword vimOption contained allowrevins arabic autowriteall backupext belloff binary breakindentopt bt cd cin clipboard cole completefunc cot cscopepathcomp cspc cul deco diff dy efm eol et fde fen fileencodings fk foldenable foldnestmax fs gfs gtt guitablabel hid hl im imdisable imstyle indk isi key langmenu lines lnr lz matchpairs mco ml modeline mousefocus mp nrformats omnifunc paragraphs perldll pmbcs printdevice prompt pythondll quickfixtextfunc remap rl rubydll sc scrolljump selection shellpipe shiftround showmatch signcolumn smarttab sp spellsuggest sps sta su swb synmaxcol tagbsearch tal tcldll termwinscroll tf timeoutlen to tsl ttyfast tws ul ur ve vif vts wcr wi wildmenu winfixheight wiv wrap ws +syn keyword vimOption contained altkeymap arabicshape aw backupskip beval bk bri bufhidden cdpath cindent cm colorcolumn completeopt cp cscopeprg csprg culopt def diffexpr ea ei ep eventignore fdi fenc fileformat fkmap foldexpr foldopen fsync gfw guicursor guitabtooltip hidden hlg imactivatefunc imi inc inex isident keymap langnoremap linespace loadplugins ma matchtime mef mle modelineexpr mousehide mps nu opendevice paste pex pmbfn printencoding pt pythonhome quoteescape renderoptions rlc ruf scb scrolloff selectmode shellquote shiftwidth showmode siso smc spc spf sr stal sua swf syntax tagcase tb tenc termwinsize tfu title toolbar tsr ttym twsl undodir ut verbose viminfo wa wd wic wildmode winfixwidth wiw wrapmargin ww +syn keyword vimOption contained ambiwidth ari awa balloondelay bevalterm bkc briopt buflisted cedit cink cmdheight columns completepopup cpo cscopequickfix csqf cursorbind define diffopt ead ek equalalways ex fdl fencs fileformats flp foldignore foldtext ft ghr guifont helpfile highlight hls imactivatekey iminsert include inf isk keymodel langremap lisp lpl macatsui maxcombine menc mls modelines mousem msm number operatorfunc pastetoggle pexpr popt printexpr pumheight pythonthreedll rdt report rnu ruler scf scrollopt sessionoptions shellredir shm " vimOptions: These are the turn-off setting variants {{{2 syn keyword vimOption contained noacd noallowrevins noantialias noarabic noarshape noautoread noaw noballooneval nobevalterm nobk nobreakindent nocf nocindent nocopyindent nocscoperelative nocsre nocuc nocursorcolumn nodelcombine nodigraph noed noemo noeol noesckeys noexpandtab nofic nofixeol nofoldenable nogd nohid nohkmap nohls noicon noimc noimdisable noinfercase nojoinspaces nolangremap nolinebreak nolnr nolrm nomacatsui noml nomod nomodelineexpr nomodified nomousef nomousehide nonumber noopendevice nopi nopreviewwindow nopvw norelativenumber norestorescreen nori norl noro noru nosb noscb noscrollbind noscs nosft noshelltemp noshortname noshowfulltag noshowmode nosm nosmartindent nosmd nosol nosplitbelow nospr nossl nostartofline noswapfile nota notagrelative notbi notbs noterse notextmode notgst notimeout noto notr nottybuiltin notx noundofile novisualbell nowarn noweirdinvert nowfw nowildignorecase nowinfixheight nowiv nowrap nowrite nowritebackup @@ -66,8 +66,8 @@ syn keyword vimErrSetting contained bioskey biosk conskey consk autoprint beauti " AutoCmd Events {{{2 syn case ignore -syn keyword vimAutoEvent contained BufAdd BufDelete BufFilePost BufHidden BufNew BufRead BufReadPost BufUnload BufWinEnter BufWinLeave BufWipeout BufWrite BufWriteCmd BufWritePost BufWritePre CmdlineChanged CmdlineEnter CmdlineLeave CmdUndefined CmdwinEnter CmdwinLeave ColorScheme ColorSchemePre CompleteChanged CompleteDone CompleteDonePre CursorHold CursorHoldI CursorMoved CursorMovedI DiffUpdated DirChanged EncodingChanged ExitPre FileAppendCmd FileAppendPost FileAppendPre FileChangedRO FileChangedShell FileChangedShellPost FileEncoding FileReadCmd FileReadPost FileReadPre FileType FileWriteCmd FileWritePost FileWritePre FilterReadPost FilterReadPre FilterWritePost FilterWritePre FocusGained FocusLost FuncUndefined GUIEnter GUIFailed InsertChange InsertCharPre InsertEnter InsertLeave MenuPopup OptionSet QuickFixCmdPost QuickFixCmdPre QuitPre RemoteReply SafeState SafeStateAgain SessionLoadPost ShellCmdPost ShellFilterPost SourceCmd SourcePost SourcePre SpellFileMissing StdinReadPost StdinReadPre SwapExists Syntax TabClosed TabEnter TabLeave TabNew TermChanged TerminalOpen TerminalWinOpen TermResponse TextChanged TextChangedI TextChangedP TextYankPost User VimEnter VimLeave VimLeavePre VimResized WinEnter WinLeave WinNew -syn keyword vimAutoEvent contained BufCreate BufEnter BufFilePre BufLeave BufNewFile BufReadCmd BufReadPre +syn keyword vimAutoEvent contained BufAdd BufDelete BufFilePost BufHidden BufNew BufRead BufReadPost BufUnload BufWinLeave BufWipeout BufWrite BufWriteCmd BufWritePost BufWritePre CmdlineChanged CmdlineEnter CmdlineLeave CmdUndefined CmdwinEnter CmdwinLeave ColorScheme ColorSchemePre CompleteChanged CompleteDone CompleteDonePre CursorHold CursorHoldI CursorMoved CursorMovedI DiffUpdated DirChanged EncodingChanged ExitPre FileAppendCmd FileAppendPost FileAppendPre FileChangedRO FileChangedShell FileChangedShellPost FileEncoding FileReadCmd FileReadPost FileReadPre FileType FileWriteCmd FileWritePost FileWritePre FilterReadPost FilterReadPre FilterWritePost FilterWritePre FocusGained FocusLost FuncUndefined GUIEnter GUIFailed InsertChange InsertCharPre InsertEnter InsertLeave MenuPopup OptionSet QuickFixCmdPost QuickFixCmdPre QuitPre RemoteReply SafeState SafeStateAgain SessionLoadPost ShellCmdPost ShellFilterPost SigUSR1 SourceCmd SourcePost SourcePre SpellFileMissing StdinReadPost StdinReadPre SwapExists Syntax TabClosed TabEnter TabLeave TabNew TermChanged TerminalOpen TerminalWinOpen TermResponse TextChanged TextChangedI TextChangedP TextYankPost User VimEnter VimLeave VimLeavePre VimResized WinEnter WinLeave WinNew +syn keyword vimAutoEvent contained BufCreate BufEnter BufFilePre BufLeave BufNewFile BufReadCmd BufReadPre BufWinEnter " Highlight commonly used Groupnames {{{2 syn keyword vimGroup contained Comment Constant String Character Number Boolean Float Identifier Function Statement Conditional Repeat Label Operator Keyword Exception PreProc Include Define Macro PreCondit Type StorageClass Structure Typedef Special SpecialChar Tag Delimiter SpecialComment Debug Underlined Ignore Error Todo @@ -78,11 +78,11 @@ syn match vimHLGroup contained "Conceal" syn case match " Function Names {{{2 -syn keyword vimFuncName contained abs appendbufline asin assert_fails assert_notmatch balloon_gettext bufadd bufname byteidx char2nr ch_evalexpr ch_log ch_readraw cindent complete_check cosh deepcopy diff_hlID eval exists feedkeys findfile fnamemodify foldtextresult get getchar getcmdtype getenv getftype getmarklist getqflist gettabwinvar getwinposy has histdel hostname inputdialog insert islocked job_setoptions js_decode len lispindent localtime maparg matchaddpos matchstr mkdir or popup_clear popup_filter_yesno popup_hide popup_notification prevnonblank prop_add prop_type_add pum_getpos rand reduce reltimestr remote_send resolve screenchar screenstring searchpairpos setbufvar setline setreg sha256 sign_getplaced sign_unplace sort sound_stop srand strcharpart stridx strridx swapinfo synIDtrans tabpagenr tanh term_getaltscreen term_getline term_gettty term_setapi term_wait test_garbagecollect_soon test_null_dict test_null_string test_setmouse timer_info tolower trunc uniq wildmenumode win_execute win_gotoid winlayout winrestview winwidth -syn keyword vimFuncName contained acos argc assert_beeps assert_false assert_report balloon_show bufexists bufnr byteidxcomp ch_canread ch_evalraw ch_logfile ch_sendexpr clearmatches complete_info count delete echoraw eventhandler exp filereadable float2nr foldclosed foreground getbufinfo getcharmod getcmdwintype getfontname getimstatus getmatches getreg gettagstack getwinvar has_key histget iconv inputlist interrupt isnan job_start js_encode libcall list2str log mapcheck matcharg matchstrpos mode pathshorten popup_close popup_findinfo popup_list popup_setoptions printf prop_clear prop_type_change pumvisible range reg_executing remote_expr remote_startserver reverse screenchars search searchpos setcharsearch setloclist settabvar shellescape sign_jump sign_unplacelist sound_clear spellbadword state strchars string strtrans swapname synstack tabpagewinnr tempname term_getansicolors term_getscrolled term_list term_setkill test_alloc_fail test_getvalue test_null_function test_option_not_set test_settime timer_pause toupper type values winbufnr win_findbuf winheight winline winsaveview wordcount -syn keyword vimFuncName contained add argidx assert_equal assert_inrange assert_true balloon_split buflisted bufwinid call ch_close ch_getbufnr ch_open ch_sendraw col confirm cscope_connection deletebufline empty executable expand filewritable floor foldclosedend funcref getbufline getcharsearch getcompletion getfperm getjumplist getmousepos getregtype getwininfo glob haslocaldir histnr indent inputrestore invert items job_status json_decode libcallnr listener_add log10 mapset matchdelete max mzeval perleval popup_create popup_findpreview popup_locate popup_settext prompt_setcallback prop_find prop_type_delete py3eval readdir reg_recording remote_foreground remove round screencol searchcount server2client setcmdpos setmatches settabwinvar shiftwidth sign_place simplify soundfold spellsuggest str2float strdisplaywidth strlen strwidth synconcealed system tagfiles term_dumpdiff term_getattr term_getsize term_scrape term_setrestore test_autochdir test_ignore_error test_null_job test_override test_srand_seed timer_start tr undofile virtcol wincol win_getid win_id2tabwin winnr win_screenpos writefile -syn keyword vimFuncName contained and arglistid assert_equalfile assert_match atan browse bufload bufwinnr ceil ch_close_in ch_getjob ch_read ch_setoptions complete copy cursor did_filetype environ execute expandcmd filter fmod foldlevel function getbufvar getcmdline getcurpos getfsize getline getpid gettabinfo getwinpos glob2regpat hasmapto hlexists index inputsave isdirectory job_getchannel job_stop json_encode line listener_flush luaeval match matchend menu_info nextnonblank popup_atcursor popup_dialog popup_getoptions popup_menu popup_show prompt_setinterrupt prop_list prop_type_get pyeval readdirex reltime remote_peek rename rubyeval screenpos searchdecl serverlist setenv setpos settagstack sign_define sign_placelist sin sound_playevent split str2list strftime strpart submatch synID systemlist taglist term_dumpload term_getcursor term_getstatus term_sendkeys term_setsize test_feedinput test_null_blob test_null_list test_refcount test_unknown timer_stop trim undotree visualmode windowsversion win_gettype win_id2win winrestcmd win_splitmove xor -syn keyword vimFuncName contained append argv assert_exception assert_notequal atan2 browsedir bufloaded byte2line changenr chdir ch_info ch_readblob ch_status complete_add cos debugbreak diff_filler escape exepath extend finddir fnameescape foldtext garbagecollect getchangelist getcmdpos getcwd getftime getloclist getpos gettabvar getwinposx globpath histadd hlID input inputsecret isinf job_info join keys line2byte listener_remove map matchadd matchlist min nr2char popup_beval popup_filter_menu popup_getpos popup_move pow prompt_setprompt prop_remove prop_type_list pyxeval readfile reltimefloat remote_read repeat screenattr screenrow searchpair setbufline setfperm setqflist setwinvar sign_getdefined sign_undefine sinh sound_playfile sqrt str2nr strgetchar strptime substitute synIDattr tabpagebuflist tan term_dumpwrite term_getjob term_gettitle term_setansicolors term_start test_garbagecollect_now test_null_channel test_null_partial test_scrollbar test_void timer_stopall +syn keyword vimFuncName contained abs appendbufline asin assert_fails assert_notmatch balloon_gettext bufadd bufname byteidx char2nr ch_evalexpr ch_log ch_readraw cindent complete_check cosh deepcopy diff_hlID eval exists feedkeys findfile fnameescape foldtext garbagecollect getchangelist getcmdpos getcwd getftime getloclist getpos gettabinfo getwinpos glob2regpat hasmapto hlexists index inputsave isdirectory job_getchannel job_stop json_encode line listener_flush luaeval match matchend menu_info nextnonblank popup_atcursor popup_dialog popup_getoptions popup_menu popup_show prompt_setinterrupt prop_list prop_type_get pyeval readdirex reltime remote_peek rename rubyeval screenpos searchdecl serverlist setenv setpos settagstack sign_define sign_placelist sin sound_playevent split str2list strftime strpart submatch synID systemlist taglist term_dumpload term_getcursor term_getstatus term_scrape term_setrestore test_autochdir test_ignore_error test_null_job test_override test_srand_seed timer_start tr undotree wildmenumode win_execute win_gotoid winlayout winrestview winwidth +syn keyword vimFuncName contained acos argc assert_beeps assert_false assert_report balloon_show bufexists bufnr byteidxcomp ch_canread ch_evalraw ch_logfile ch_sendexpr clearmatches complete_info count delete echoraw eventhandler exp filereadable flatten fnamemodify foldtextresult get getchar getcmdtype getenv getftype getmarklist getqflist gettabvar getwinposx globpath histadd hlID input inputsecret isinf job_info join keys line2byte listener_remove map matchadd matchlist min nr2char popup_beval popup_filter_menu popup_getpos popup_move pow prompt_setprompt prop_remove prop_type_list pyxeval readfile reltimefloat remote_read repeat screenattr screenrow searchpair setbufline setfperm setqflist setwinvar sign_getdefined sign_undefine sinh sound_playfile sqrt str2nr strgetchar strptime substitute synIDattr tabpagebuflist tan term_dumpwrite term_getjob term_gettitle term_sendkeys term_setsize test_feedinput test_null_blob test_null_list test_refcount test_unknown timer_stop trim uniq winbufnr win_findbuf winheight winline winsaveview wordcount +syn keyword vimFuncName contained add argidx assert_equal assert_inrange assert_true balloon_split buflisted bufwinid call ch_close ch_getbufnr ch_open ch_sendraw col confirm cscope_connection deletebufline empty executable expand filewritable float2nr foldclosed foreground getbufinfo getcharmod getcmdwintype getfontname getimstatus getmatches getreg gettabwinvar getwinposy has histdel hostname inputdialog insert islocked job_setoptions js_decode len lispindent localtime maparg matchaddpos matchstr mkdir or popup_clear popup_filter_yesno popup_hide popup_notification prevnonblank prop_add prop_type_add pum_getpos rand reduce reltimestr remote_send resolve screenchar screenstring searchpairpos setbufvar setline setreg sha256 sign_getplaced sign_unplace sort sound_stop srand strcharpart stridx strridx swapinfo synIDtrans tabpagenr tanh term_getaltscreen term_getline term_gettty term_setansicolors term_start test_garbagecollect_now test_null_channel test_null_partial test_scrollbar test_void timer_stopall trunc values wincol win_getid win_id2tabwin winnr win_screenpos writefile +syn keyword vimFuncName contained and arglistid assert_equalfile assert_match atan browse bufload bufwinnr ceil ch_close_in ch_getjob ch_read ch_setoptions complete copy cursor did_filetype environ execute expandcmd filter floor foldclosedend funcref getbufline getcharsearch getcompletion getfperm getjumplist getmousepos getreginfo gettagstack getwinvar has_key histget iconv inputlist interrupt isnan job_start js_encode libcall list2str log mapcheck matcharg matchstrpos mode pathshorten popup_close popup_findinfo popup_list popup_setoptions printf prop_clear prop_type_change pumvisible range reg_executing remote_expr remote_startserver reverse screenchars search searchpos setcharsearch setloclist settabvar shellescape sign_jump sign_unplacelist sound_clear spellbadword state strchars string strtrans swapname synstack tabpagewinnr tempname term_getansicolors term_getscrolled terminalprops term_setapi term_wait test_garbagecollect_soon test_null_dict test_null_string test_setmouse timer_info tolower type virtcol windowsversion win_gettype win_id2win winrestcmd win_splitmove xor +syn keyword vimFuncName contained append argv assert_exception assert_notequal atan2 browsedir bufloaded byte2line changenr chdir ch_info ch_readblob ch_status complete_add cos debugbreak diff_filler escape exepath extend finddir fmod foldlevel function getbufvar getcmdline getcurpos getfsize getline getpid getregtype getwininfo glob haslocaldir histnr indent inputrestore invert items job_status json_decode libcallnr listener_add log10 mapset matchdelete max mzeval perleval popup_create popup_findpreview popup_locate popup_settext prompt_setcallback prop_find prop_type_delete py3eval readdir reg_recording remote_foreground remove round screencol searchcount server2client setcmdpos setmatches settabwinvar shiftwidth sign_place simplify soundfold spellsuggest str2float strdisplaywidth strlen strwidth synconcealed system tagfiles term_dumpdiff term_getattr term_getsize term_list term_setkill test_alloc_fail test_getvalue test_null_function test_option_not_set test_settime timer_pause toupper undofile visualmode "--- syntax here and above generated by mkvimvim --- " Special Vim Highlighting (not automatic) {{{1 @@ -295,6 +295,7 @@ syn match vimComment +\\)\=\%(\w\+\.\)*\I[a-zA-Z0-9_.]*\)\ze\s*(" contains=vimFuncName,vimUserFunc,vimExecute syn match vimUserFunc contained "\%(\%([sSgGbBwWtTlL]:\|<[sS][iI][dD]>\)\=\%(\w\+\.\)*\I[a-zA-Z0-9_.]*\)\|\<\u[a-zA-Z0-9.]*\>\|\" contains=vimNotation +" User Command Highlighting: {{{2 +syn match vimUsrCmd '^\s*\zs\u\w*.*$' + " Errors And Warnings: {{{2 " ==================== if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_novimfunctionerror") @@ -598,7 +602,7 @@ syn match vimHiGuiFontname contained "'[a-zA-Z\-* ]\+'" syn match vimHiGuiRgb contained "#\x\{6}" " Highlighting: hi group key=arg ... {{{2 -syn cluster vimHiCluster contains=vimGroup,vimHiGroup,vimHiTerm,vimHiCTerm,vimHiStartStop,vimHiCtermFgBg,vimHiGui,vimHiGuiFont,vimHiGuiFgBg,vimHiKeyError,vimNotation +syn cluster vimHiCluster contains=vimGroup,vimHiGroup,vimHiTerm,vimHiCTerm,vimHiStartStop,vimHiCtermFgBg,vimHiCtermul,vimHiGui,vimHiGuiFont,vimHiGuiFgBg,vimHiKeyError,vimNotation syn region vimHiKeyList contained oneline start="\i\+" skip="\\\\\|\\|" end="$\||" contains=@vimHiCluster if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_vimhikeyerror") syn match vimHiKeyError contained "\i\+="he=e-1 @@ -607,6 +611,7 @@ syn match vimHiTerm contained "\cterm="he=e-1 nextgroup=vimHiAttribList syn match vimHiStartStop contained "\c\(start\|stop\)="he=e-1 nextgroup=vimHiTermcap,vimOption syn match vimHiCTerm contained "\ccterm="he=e-1 nextgroup=vimHiAttribList syn match vimHiCtermFgBg contained "\ccterm[fb]g="he=e-1 nextgroup=vimHiNmbr,vimHiCtermColor,vimFgBgAttrib,vimHiCtermError +syn match vimHiCtermul contained "\cctermul="he=e-1 nextgroup=vimHiNmbr,vimHiCtermColor,vimFgBgAttrib,vimHiCtermError syn match vimHiGui contained "\cgui="he=e-1 nextgroup=vimHiAttribList syn match vimHiGuiFont contained "\cfont="he=e-1 nextgroup=vimHiFontname syn match vimHiGuiFgBg contained "\cgui\%([fb]g\|sp\)="he=e-1 nextgroup=vimHiGroup,vimHiGuiFontname,vimHiGuiRgb,vimFgBgAttrib @@ -629,7 +634,7 @@ syn match vimCtrlChar "[- -]" " Beginners - Patterns that involve ^ {{{2 " ========= syn match vimLineComment +^[ \t:]*".*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle -syn match vim9LineComment +^[ \t:]\+#.*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle +syn match vim9LineComment +^[ \t:]*#.*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle syn match vimCommentTitle '"\s*\%([sS]:\|\h\w*#\)\=\u\w*\(\s\+\u\w*\)*:'hs=s+1 contained contains=vimCommentTitleLeader,vimTodo,@vimCommentGroup syn match vimContinue "^\s*\\" syn region vimString start="^\s*\\\z(['"]\)" skip='\\\\\|\\\z1' end="\z1" oneline keepend contains=@vimStringGroup,vimContinue @@ -877,6 +882,7 @@ if !exists("skip_vim_syntax_inits") hi def link vimError Error hi def link vimFBVar vimVar hi def link vimFgBgAttrib vimHiAttrib + hi def link vimHiCtermul vimHiTerm hi def link vimFold Folded hi def link vimFTCmd vimCommand hi def link vimFTOption vimSynType diff --git a/runtime/tutor/tutor.eo b/runtime/tutor/tutor.eo index 11a0b9d00235e8..b11d145e9fb153 100644 --- a/runtime/tutor/tutor.eo +++ b/runtime/tutor/tutor.eo @@ -7,7 +7,7 @@ fasonita por priskribi sufiajn komandojn, por ke vi kapablu uzi Vim kun sufia facileco. - La tempo bezonata por plenumi la kurson estas 25-30 minutoj, kaj dependas + La tempo bezonata por plenumi la kurson estas 30 minutoj, kaj dependas de kiom da tempo estas uzata por eksperimenti. ATENTU: @@ -100,7 +100,7 @@ RIMARKO: Trairante la instruilon, ne provu memori, lernu per la uzo. 1. Movu la kursoron al la unua suba linio markita per --->. 2. Por igi la unuan linion sama kiel la dua, movu la kursoron sur la unuan - signon post kie la teksto estas enmetenda. + signon anta kie la teksto estas enmetenda. 3. Premu i kaj tajpu la bezonatajn aldonojn. @@ -200,7 +200,7 @@ Nun da 1. Premu por certigi, ke vi estas en normala reimo. - 2. Movu la kursoron al la linio markita per --->. + 2. Movu la kursoron al la suba linio markita per --->. 3. Movu la kursoron al la komenco de vorto, kiu forviendas. @@ -225,7 +225,7 @@ Nun da 1. Premu por certigi, ke vi estas en normala reimo. - 2. Movu la kursoron sur la suban linion markita per --->. + 2. Movu la kursoron al la suba linio markita per --->. 3. Movu la kursoron e la fino de la usta linio (POST la unua . ). @@ -296,10 +296,10 @@ RIMARKO: Premo de nur la movo en Normala re 1. Movu la kursoron e la unua MAJUSKLA vorto en la linio markita per --->. - 2. Tajpu d2w por forvii la du MAJUSKLAJN vortojn + 2. Tajpu d2w por forvii la du MAJUSKLAJN vortojn. 3. Ripetu paojn 1 is 2 per malsama nombro por forvii la sinsekvajn - MAJUSKLAJN vortojn per unu komando + MAJUSKLAJN vortojn per unu komando. ---> Tiu AB CDE linio FGHI JK LMN OP de vortoj estas Q RS TUV purigita. @@ -379,7 +379,7 @@ RIMARKO: Premo de nur la movo en Normala re ** Tajpu p por meti tekston forviitan antae post la kursoro. ** - 1. Movu la kursoron e la unua ---> suba linio. + 1. Movu la kursoron e la unua suba linio markita per --->. 2. Tajpu dd por forvii la linion kaj konservi in ene de reistro de Vim. @@ -652,7 +652,7 @@ RIMARKO: Se vi volus eliri el Vim kaj restartigi la dosiero estus precize same kiel kopio de la instruilo kiam vi konservis in. - 5. Nun forviu la dosieron tajpante (WINDOWS): :!del TESTO + 5. Nun forviu la dosieron tajpante (VINDOZO): :!del TESTO a (UNIKSO): :!rm TESTO @@ -713,7 +713,7 @@ RIMARKO: Vi nun povas legi la eliron de ekstera komando. Ekzemple, 1. :!komando plenumas eksteran komandon. Iuj utilaj ekzemploj estas: - (WINDOWS) (UNIKSO) + (VINDOZO) (UNIKSO) :!dir :!ls - listigas dosierujon :!del DOSIERNOMO :!rm DOSIERNOMO - forvias la dosieron DOSIERNOMO @@ -808,7 +808,7 @@ RIMARKO: Anstata ** Uzu la y operatoron por kopii tekston, kaj p por alglui in ** - 1. Iru al la linio markita per ---> sube kaj poziciu la kursoron post "a)". + 1. Iru al la suba linio markita per ---> kaj poziciu la kursoron post "a)". 2. Komencu la Viduman reimon per v kaj movu la kursoron tuj anta "unua". @@ -914,7 +914,7 @@ RIMARKO: Se vi deziras ignori usklecon por nur unu ser 1. Ekredaktu la dosieron "vimrc". Tio dependas de via sistemo: :e ~/.vimrc por Unikso - :e $VIM/_vimrc por Windows + :e $VIM/_vimrc por Vindozo 2. Nun legu la enhavon de la ekzempla "vimrc" :r $VIMRUNTIME/vimrc_example.vim @@ -945,7 +945,7 @@ RIMARKO: Se vi deziras ignori usklecon por nur unu ser 6. Nun aldonu spaceton kaj la komencon de ekzistanta nomo: :edit DOSI - 7. Premu . Vim kompletigos la nomon (se i estas unika) + 7. Premu d. Vim kompletigos la nomon (se i estas unika) RIMARKO: Kompletigo funkcias por multaj komandoj. Nur provu premi CTRL-D kaj . Estas aparte utila por :help . @@ -986,6 +986,6 @@ RIMARKO: Kompletigo funkcias por multaj komandoj. Nur provu premi CTRL-D kaj Esperantigita fare de Dominique Pell, 2008-04-01 Retpoto: dominique.pelle@gmail.com - Lasta ano: 2018-12-02 + Lasta ano: 2020-07-19 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/runtime/tutor/tutor.eo.utf-8 b/runtime/tutor/tutor.eo.utf-8 index 1b3873c13dad4d..a11c5554baaa06 100644 --- a/runtime/tutor/tutor.eo.utf-8 +++ b/runtime/tutor/tutor.eo.utf-8 @@ -7,7 +7,7 @@ fasonita por priskribi sufiĉajn komandojn, por ke vi kapablu uzi Vim kun sufiĉa facileco. - La tempo bezonata por plenumi la kurson estas 25-30 minutoj, kaj dependas + La tempo bezonata por plenumi la kurson estas 30 minutoj, kaj dependas de kiom da tempo estas uzata por eksperimenti. ATENTU: @@ -100,7 +100,7 @@ RIMARKO: Trairante la instruilon, ne provu memori, lernu per la uzo. 1. Movu la kursoron al la unua suba linio markita per --->. 2. Por igi la unuan linion sama kiel la dua, movu la kursoron sur la unuan - signon post kie la teksto estas enmetenda. + signon antaŭ kie la teksto estas enmetenda. 3. Premu i kaj tajpu la bezonatajn aldonojn. @@ -200,7 +200,7 @@ Nun daŭrigu al la leciono 2. 1. Premu por certigi, ke vi estas en normala reĝimo. - 2. Movu la kursoron al la linio markita per --->. + 2. Movu la kursoron al la suba linio markita per --->. 3. Movu la kursoron al la komenco de vorto, kiu forviŝendas. @@ -225,7 +225,7 @@ Nun daŭrigu al la leciono 2. 1. Premu por certigi, ke vi estas en normala reĝimo. - 2. Movu la kursoron sur la suban linion markita per --->. + 2. Movu la kursoron al la suba linio markita per --->. 3. Movu la kursoron ĉe la fino de la ĝusta linio (POST la unua . ). @@ -296,10 +296,10 @@ RIMARKO: Premo de nur la movo en Normala reĝimo sen operatoro movos 1. Movu la kursoron ĉe la unua MAJUSKLA vorto en la linio markita per --->. - 2. Tajpu d2w por forviŝi la du MAJUSKLAJN vortojn + 2. Tajpu d2w por forviŝi la du MAJUSKLAJN vortojn. 3. Ripetu paŝojn 1 ĝis 2 per malsama nombro por forviŝi la sinsekvajn - MAJUSKLAJN vortojn per unu komando + MAJUSKLAJN vortojn per unu komando. ---> Tiu AB CDE linio FGHI JK LMN OP de vortoj estas Q RS TUV purigita. @@ -379,7 +379,7 @@ RIMARKO: Premo de nur la movo en Normala reĝimo sen operatoro movos ** Tajpu p por meti tekston forviŝitan antaŭe post la kursoro. ** - 1. Movu la kursoron ĉe la unua ---> suba linio. + 1. Movu la kursoron ĉe la unua suba linio markita per --->. 2. Tajpu dd por forviŝi la linion kaj konservi ĝin ene de reĝistro de Vim. @@ -652,7 +652,7 @@ RIMARKO: Se vi volus eliri el Vim kaj restartigi ĝin denove per vim TESTO, la dosiero estus precize same kiel kopio de la instruilo kiam vi konservis ĝin. - 5. Nun forviŝu la dosieron tajpante (WINDOWS): :!del TESTO + 5. Nun forviŝu la dosieron tajpante (VINDOZO): :!del TESTO aŭ (UNIKSO): :!rm TESTO @@ -713,7 +713,7 @@ RIMARKO: Vi nun povas legi la eliron de ekstera komando. Ekzemple, 1. :!komando plenumas eksteran komandon. Iuj utilaj ekzemploj estas: - (WINDOWS) (UNIKSO) + (VINDOZO) (UNIKSO) :!dir :!ls - listigas dosierujon :!del DOSIERNOMO :!rm DOSIERNOMO - forviŝas la dosieron DOSIERNOMO @@ -808,7 +808,7 @@ RIMARKO: Anstataŭiga reĝimo estas same kiel Enmeta reĝimo, sed ĉiu signo ** Uzu la y operatoron por kopii tekston, kaj p por alglui ĝin ** - 1. Iru al la linio markita per ---> sube kaj poziciu la kursoron post "a)". + 1. Iru al la suba linio markita per ---> kaj poziciu la kursoron post "a)". 2. Komencu la Viduman reĝimon per v kaj movu la kursoron tuj antaŭ "unua". @@ -914,7 +914,7 @@ RIMARKO: Se vi deziras ignori usklecon por nur unu serĉa komando, uzu \c 1. Ekredaktu la dosieron "vimrc". Tio dependas de via sistemo: :e ~/.vimrc por Unikso - :e $VIM/_vimrc por Windows + :e $VIM/_vimrc por Vindozo 2. Nun legu la enhavon de la ekzempla "vimrc" :r $VIMRUNTIME/vimrc_example.vim @@ -945,7 +945,7 @@ RIMARKO: Se vi deziras ignori usklecon por nur unu serĉa komando, uzu \c 6. Nun aldonu spaceton kaj la komencon de ekzistanta nomo: :edit DOSI - 7. Premu . Vim kompletigos la nomon (se ĝi estas unika) + 7. Premu d. Vim kompletigos la nomon (se ĝi estas unika) RIMARKO: Kompletigo funkcias por multaj komandoj. Nur provu premi CTRL-D kaj . Estas aparte utila por :help . @@ -986,6 +986,6 @@ RIMARKO: Kompletigo funkcias por multaj komandoj. Nur provu premi CTRL-D kaj Esperantigita fare de Dominique Pellé, 2008-04-01 Retpoŝto: dominique.pelle@gmail.com - Lasta ŝanĝo: 2018-12-02 + Lasta ŝanĝo: 2020-07-19 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/po/eo.po b/src/po/eo.po index 521522bb8a84c6..5f0da207b5ae4d 100644 --- a/src/po/eo.po +++ b/src/po/eo.po @@ -17,8 +17,8 @@ msgid "" msgstr "" "Project-Id-Version: Vim 8.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-02-15 21:05+0100\n" -"PO-Revision-Date: 2020-02-15 23:59+0100\n" +"POT-Creation-Date: 2020-07-19 07:51+0200\n" +"PO-Revision-Date: 2020-07-19 09:39+0200\n" "Last-Translator: Dominique PELLÉ \n" "Language-Team: Esperanto\n" "Language: eo\n" @@ -226,9 +226,6 @@ msgstr "[Modifita]" msgid "[Not edited]" msgstr "[Ne redaktita]" -msgid "[New file]" -msgstr "[Nova dosiero]" - msgid "[Read errors]" msgstr "[Eraroj de legado]" @@ -287,6 +284,12 @@ msgstr "AVERTO: La dosiero estas ŝanĝita de post kiam ĝi estis legita!!!" msgid "Do you really want to write to it" msgstr "Ĉu vi vere volas skribi al ĝi" +msgid "[New]" +msgstr "[Nova]" + +msgid "[New File]" +msgstr "[Nova dosiero]" + msgid "E676: No matching autocommands for acwrite buffer" msgstr "E676: Neniu kongrua aŭtokomando por la bufro acwrite" @@ -378,12 +381,6 @@ msgstr "[konvertita]" msgid "[Device]" msgstr "[Aparatdosiero]" -msgid "[New]" -msgstr "[Nova]" - -msgid "[New File]" -msgstr "[Nova dosiero]" - msgid " [a]" msgstr " [a]" @@ -421,12 +418,16 @@ msgstr "W10: Averto: Ŝanĝo de nurlegebla dosiero" msgid "E902: Cannot connect to port" msgstr "E902: Ne eblas konekti al pordo" +msgid "E898: socket() in channel_connect()" +msgstr "E898: socket() en channel_connect()" + +#, c-format +msgid "E901: getaddrinfo() in channel_open(): %s" +msgstr "E901: getaddrinfo() en channel_open(): %s" + msgid "E901: gethostbyname() in channel_open()" msgstr "E901: gethostbyname() en channel_open()" -msgid "E898: socket() in channel_open()" -msgstr "E898: gethostbyname() en channel_open()" - msgid "E903: received command with non-string argument" msgstr "E903: ricevis komandon kun argumento, kiu ne estas ĉeno" @@ -471,6 +472,47 @@ msgstr "E918: bufro devas esti ŝargita: %s" msgid "E916: not a valid job" msgstr "E916: nevalida tasko" +msgid "No display" +msgstr "Neniu ekrano" + +msgid ": Send failed.\n" +msgstr ": Sendo malsukcesis.\n" + +msgid ": Send failed. Trying to execute locally\n" +msgstr ": Sendo malsukcesis. Provo de loka plenumo\n" + +#, c-format +msgid "%d of %d edited" +msgstr "%d de %d redaktita(j)" + +msgid "No display: Send expression failed.\n" +msgstr "Neniu ekrano: Sendado de esprimo malsukcesis.\n" + +msgid ": Send expression failed.\n" +msgstr ": Sendado de esprimo malsukcesis.\n" + +msgid "E240: No connection to the X server" +msgstr "E240: Neniu konekto al X-servilo" + +#, c-format +msgid "E241: Unable to send to %s" +msgstr "E241: Ne eblas sendi al %s" + +msgid "E277: Unable to read a server reply" +msgstr "E277: Ne eblas legi respondon de servilo" + +msgid "E941: already started a server" +msgstr "E941: servilo jam lanĉita" + +msgid "E942: +clientserver feature not available" +msgstr "E942: la eblo +clientserver ne disponeblas" + +msgid "E258: Unable to send to client" +msgstr "E258: Ne eblas sendi al kliento" + +msgid "Used CUT_BUFFER0 instead of empty selection" +msgstr "Uzis CUT_BUFFER0 anstataŭ malplenan apartigon" + msgid "tagname" msgstr "nomo de etikedo" @@ -692,9 +734,6 @@ msgstr "E791: Malplena rikordo en klavmapo" msgid "E719: Cannot use [:] with a Dictionary" msgstr "E719: Uzo de [:] ne eblas kun Vortaro" -msgid "E806: using Float as a String" -msgstr "E806: uzo de Glitpunktnombro kiel Ĉeno" - msgid "E689: Can only index a List, Dictionary or Blob" msgstr "E689: Nur eblas indeksi Liston, Vortaron aŭ BLOB-on" @@ -728,87 +767,12 @@ msgstr "E695: Ne eblas indeksi Funcref" msgid "E909: Cannot index a special variable" msgstr "E909: Ne eblas indeksi specialan variablon" -#, c-format -msgid "E112: Option name missing: %s" -msgstr "E112: Mankas nomo de opcio: %s" - -msgid "E973: Blob literal should have an even number of hex characters" -msgstr "E973: BLOB-a literalo devus havi paran nombron de deksesumaj signoj" - -#, c-format -msgid "E114: Missing quote: %s" -msgstr "E114: Mankas citilo: %s" - -#, c-format -msgid "E115: Missing quote: %s" -msgstr "E115: Mankas citilo: %s" - msgid "Not enough memory to set references, garbage collection aborted!" msgstr "Ne sufiĉa memoro por valorigi referencojn, senrubigado ĉesigita!" msgid "E724: variable nested too deep for displaying" msgstr "E724: variablo ingita tro profunde por vidigi" -msgid "E805: Using a Float as a Number" -msgstr "E805: Uzo de Glitpunktnombro kiel Nombro" - -msgid "E703: Using a Funcref as a Number" -msgstr "E703: Uzo de Funcref kiel Nombro" - -msgid "E745: Using a List as a Number" -msgstr "E745: Uzo de Listo kiel Nombro" - -msgid "E728: Using a Dictionary as a Number" -msgstr "E728: Uzo de Vortaro kiel Nombro" - -msgid "E910: Using a Job as a Number" -msgstr "E910: Uzo de Tasko kiel Nombro" - -msgid "E913: Using a Channel as a Number" -msgstr "E913: Uzo de Kanalo kiel Nombro" - -msgid "E974: Using a Blob as a Number" -msgstr "E974: Uzo de BLOB-o kiel Nombro" - -msgid "E891: Using a Funcref as a Float" -msgstr "E891: Uzo de Funcref kiel Glitpunktnombro" - -msgid "E892: Using a String as a Float" -msgstr "E892: Uzo de Ĉeno kiel Glitpunktnombro" - -msgid "E893: Using a List as a Float" -msgstr "E893: Uzo de Listo kiel Glitpunktnombro" - -msgid "E894: Using a Dictionary as a Float" -msgstr "E894: Uzo de Vortaro kiel Glitpunktnombro" - -msgid "E362: Using a boolean value as a Float" -msgstr "E362: Uzo de bulea valoro kiel Glitpunktnombro" - -msgid "E907: Using a special value as a Float" -msgstr "E907: Uzo de speciala valoro kiel Glitpunktnombro" - -msgid "E911: Using a Job as a Float" -msgstr "E911: Uzo de Tasko kiel Glitpunktnombro" - -msgid "E914: Using a Channel as a Float" -msgstr "E914: Uzo de Kanalo kiel Glitpunktnombro" - -msgid "E975: Using a Blob as a Float" -msgstr "E975: Uzo de BLOB-o kiel Glitpunktnombro" - -msgid "E729: using Funcref as a String" -msgstr "E729: uzo de Funcref kiel Ĉeno" - -msgid "E730: using List as a String" -msgstr "E730: uzo de Listo kiel Ĉeno" - -msgid "E731: using Dictionary as a String" -msgstr "E731: uzo de Vortaro kiel Ĉeno" - -msgid "E976: using Blob as a String" -msgstr "E976: uzo de BLOB-o kiel Ĉeno" - msgid "E698: variable nested too deep for making a copy" msgstr "E698: variablo ingita tro profunde por fari kopion" @@ -819,24 +783,6 @@ msgstr "" "\n" "\tLaste ŝaltita de " -msgid "E977: Can only compare Blob with Blob" -msgstr "E977: Eblas nur kompari BLOB-on kun BLOB-o" - -msgid "E691: Can only compare List with List" -msgstr "E691: Eblas nur kompari Liston kun Listo" - -msgid "E692: Invalid operation for List" -msgstr "E692: Nevalida operacio de Listoj" - -msgid "E735: Can only compare Dictionary with Dictionary" -msgstr "E735: Eblas nur kompari Vortaron kun Vortaro" - -msgid "E736: Invalid operation for Dictionary" -msgstr "E736: Nevalida operacio de Vortaro" - -msgid "E694: Invalid operation for Funcrefs" -msgstr "E694: Nevalida operacio de Funcref-oj" - msgid "E808: Number or Float required" msgstr "E808: Nombro aŭ Glitpunktnombro bezonata" @@ -882,25 +828,6 @@ msgstr "E726: Paŝo estas nul" msgid "E727: Start past end" msgstr "E727: Komenco preter fino" -msgid "E240: No connection to the X server" -msgstr "E240: Neniu konekto al X-servilo" - -#, c-format -msgid "E241: Unable to send to %s" -msgstr "E241: Ne eblas sendi al %s" - -msgid "E277: Unable to read a server reply" -msgstr "E277: Ne eblas legi respondon de servilo" - -msgid "E941: already started a server" -msgstr "E941: servilo jam lanĉita" - -msgid "E942: +clientserver feature not available" -msgstr "E942: la eblo +clientserver ne disponeblas" - -msgid "E258: Unable to send to client" -msgstr "E258: Ne eblas sendi al kliento" - #, c-format msgid "E962: Invalid action: '%s'" msgstr "E962: Nevalida ago: '%s'" @@ -931,8 +858,8 @@ msgstr "E687: Malpli da celoj ol Listeroj" msgid "E688: More targets than List items" msgstr "E688: Pli da celoj ol Listeroj" -msgid "Double ; in list of variables" -msgstr "Duobla ; en listo de variabloj" +msgid "E452: Double ; in list of variables" +msgstr "E452: Du ; en listo de variabloj" #, c-format msgid "E738: Can't list variables for %s" @@ -948,10 +875,6 @@ msgstr "E996: Ne eblas ŝlosi reĝistron" msgid "E108: No such variable: \"%s\"" msgstr "E108: Ne estas tia variablo: \"%s\"" -#, c-format -msgid "E940: Cannot lock or unlock variable %s" -msgstr "E940: Ne eblas ŝlosi aŭ malŝlosi variablon %s" - msgid "E743: variable nested too deep for (un)lock" msgstr "E743: variablo ingita tro profunde por (mal)ŝlosi" @@ -1483,6 +1406,9 @@ msgstr "E601: \":try\" ingita tro profunde" msgid "E604: :catch after :finally" msgstr "E604: \":catch\" post \":finally\"" +msgid "E193: :enddef not inside a function" +msgstr "E193: \":enddef\" ekster funkcio" + msgid "E193: :endfunction not inside a function" msgstr "E193: \":endfunction\" ekster funkcio" @@ -1591,10 +1517,10 @@ msgstr[0] "%ld linio, " msgstr[1] "%ld linioj, " #, c-format -msgid "%lld character" -msgid_plural "%lld characters" -msgstr[0] "%lld signo" -msgstr[1] "%lld signoj" +msgid "%lld byte" +msgid_plural "%lld bytes" +msgstr[0] "%lld bajto" +msgstr[1] "%lld bajtoj" msgid "[noeol]" msgstr "[sen EOL]" @@ -1679,6 +1605,9 @@ msgstr "" msgid "E655: Too many symbolic links (cycle?)" msgstr "E655: Tro da simbolaj ligiloj (ĉu estas ciklo?)" +msgid "writefile() first argument must be a List or a Blob" +msgstr "unua argumento de writefile() devas esti Listo aŭ BLOB-o" + msgid "Select Directory dialog" msgstr "Dialogujo de dosiera elekto" @@ -1691,6 +1620,9 @@ msgstr "Dialogujo de dosiera malfermo" msgid "E338: Sorry, no file browser in console mode" msgstr "E338: Bedaŭrinde ne estas dosierfoliumilo en konzola reĝimo" +msgid "no matches" +msgstr "neniuj kongruoj" + msgid "E854: path too long for completion" msgstr "E854: tro longa vojo por kompletigo" @@ -1775,10 +1707,6 @@ msgstr "E231: 'guifontwide' nevalida" msgid "E599: Value of 'imactivatekey' is invalid" msgstr "E599: Valoro de 'imactivatekey' estas nevalida" -#, c-format -msgid "E254: Cannot allocate color %s" -msgstr "E254: Ne eblas disponigi koloron %s" - msgid "No match at cursor, finding next" msgstr "Neniu kongruo ĉe kursorpozicio, trovas sekvan" @@ -2005,6 +1933,25 @@ msgstr "Larĝo de font0: %d" msgid "Font%d width: %d" msgstr "Larĝo de font%d: %d" +msgid "E284: Cannot set IC values" +msgstr "E284: Ne eblas agordi valorojn de IC" + +msgid "E285: Failed to create input context" +msgstr "E285: Kreado de eniga kunteksto malsukcesis" + +msgid "E286: Failed to open input method" +msgstr "E286: Malfermo de eniga metodo malsukcesis" + +msgid "E287: Warning: Could not set destroy callback to IM" +msgstr "E287: Averto: Ne eblis agordi detruan reagfunkcion al IM" + +msgid "E288: input method doesn't support any style" +msgstr "E288: eniga metodo subtenas neniun stilon" + +# DP: mi ne scias, kio estas "preedit" +msgid "E289: input method doesn't support my preedit type" +msgstr "E289: eniga metodo ne subtenas mian antaŭredaktan tipon" + msgid "Invalid font specification" msgstr "Nevalida tiparo specifita" @@ -2169,6 +2116,9 @@ msgstr "E419: Nekonata malfona koloro" msgid "E420: BG color unknown" msgstr "E420: Nekonata fona koloro" +msgid "E453: UL color unknown" +msgstr "E453: Nekonata koloro de UL" + #, c-format msgid "E421: Color name or number not recognized: %s" msgstr "E421: Kolora nomo aŭ nombro nerekonita: %s" @@ -2193,29 +2143,6 @@ msgstr "W18: Nevalida signo en nomo de grupo" msgid "E849: Too many highlight and syntax groups" msgstr "E849: Tro da emfazaj kaj sintaksaj grupoj" -#, c-format -msgid "E799: Invalid ID: %d (must be greater than or equal to 1)" -msgstr "E799: Nevalida ID: %d (devas esti egala aŭ pli granda ol 1)" - -#, c-format -msgid "E801: ID already taken: %d" -msgstr "E801: ID jam uzata: %d" - -msgid "E290: List or number required" -msgstr "E290: Listo aŭ nombro bezonata" - -#, c-format -msgid "E802: Invalid ID: %d (must be greater than or equal to 1)" -msgstr "E802: Nevalida ID: %d (devas esti egala aŭ pli granda ol 1)" - -#, c-format -msgid "E803: ID not found: %d" -msgstr "E803: ID netrovita: %d" - -#, c-format -msgid "E798: ID is reserved for \":match\": %d" -msgstr "E798: ID estas rezervita por \":match\": %d" - msgid "Add a new database" msgstr "Aldoni novan datumbazon" @@ -2700,6 +2627,10 @@ msgstr "kongruo %d de %d" msgid "match %d" msgstr "kongruo %d" +#, c-format +msgid "E491: json decode error at '%s'" +msgstr "E491: eraro dum json-malkodado: '%s'" + #, c-format msgid "E938: Duplicate key in JSON: \"%s\"" msgstr "E938: Ripetita ŝlosilo en JSON: \"%s\"" @@ -2708,14 +2639,16 @@ msgstr "E938: Ripetita ŝlosilo en JSON: \"%s\"" msgid "E899: Argument of %s must be a List or Blob" msgstr "E899: Argumento de %s devas esti Listo aŭ BLOB-o" +msgid "E900: maxdepth must be non-negative number" +msgstr "E900: maxdepth ne povas esti negativa nombro" + +msgid "flatten() argument" +msgstr "argumento de flatten()" + #, c-format msgid "E696: Missing comma in List: %s" msgstr "E696: Mankas komo en Listo: %s" -#, c-format -msgid "E697: Missing end of List ']': %s" -msgstr "E697: Mankas fino de Listo ']': %s" - msgid "sort() argument" msgstr "argumento de sort()" @@ -3160,25 +3093,6 @@ msgstr "-P \tMalfermi Vim en gepatra aplikaĵo" msgid "--windowid \tOpen Vim inside another win32 widget" msgstr "--windowid \tMalfermi Vim en alia win32 fenestraĵo" -msgid "No display" -msgstr "Neniu ekrano" - -msgid ": Send failed.\n" -msgstr ": Sendo malsukcesis.\n" - -msgid ": Send failed. Trying to execute locally\n" -msgstr ": Sendo malsukcesis. Provo de loka plenumo\n" - -#, c-format -msgid "%d of %d edited" -msgstr "%d de %d redaktita(j)" - -msgid "No display: Send expression failed.\n" -msgstr "Neniu ekrano: Sendado de esprimo malsukcesis.\n" - -msgid ": Send expression failed.\n" -msgstr ": Sendado de esprimo malsukcesis.\n" - #, c-format msgid "E224: global abbreviation already exists for %s" msgstr "E224: malloka mallongigo jam ekzistas por %s" @@ -3204,6 +3118,9 @@ msgstr "Neniu mapo trovita" msgid "E228: makemap: Illegal mode" msgstr "E228: makemap: Nevalida reĝimo" +msgid "E460: entries missing in mapset() dict argument" +msgstr "E460: mankas eroj en vortara argumento de mapset()" + #, c-format msgid "E357: 'langmap': Matching character missing for %s" msgstr "E357: 'langmap': Kongrua signo mankas por %s" @@ -3240,27 +3157,31 @@ msgstr "" "\n" "ŝanĝo linio kol teksto" -msgid "E543: Not a valid codepage" -msgstr "E543: Nevalida kodpaĝo" +#, c-format +msgid "E799: Invalid ID: %d (must be greater than or equal to 1)" +msgstr "E799: Nevalida ID: %d (devas esti egala aŭ pli granda ol 1)" -msgid "E284: Cannot set IC values" -msgstr "E284: Ne eblas agordi valorojn de IC" +#, c-format +msgid "E801: ID already taken: %d" +msgstr "E801: ID jam uzata: %d" -msgid "E285: Failed to create input context" -msgstr "E285: Kreado de eniga kunteksto malsukcesis" +msgid "E290: List or number required" +msgstr "E290: Listo aŭ nombro bezonata" -msgid "E286: Failed to open input method" -msgstr "E286: Malfermo de eniga metodo malsukcesis" +#, c-format +msgid "E802: Invalid ID: %d (must be greater than or equal to 1)" +msgstr "E802: Nevalida ID: %d (devas esti egala aŭ pli granda ol 1)" -msgid "E287: Warning: Could not set destroy callback to IM" -msgstr "E287: Averto: Ne eblis agordi detruan reagfunkcion al IM" +#, c-format +msgid "E803: ID not found: %d" +msgstr "E803: ID netrovita: %d" -msgid "E288: input method doesn't support any style" -msgstr "E288: eniga metodo subtenas neniun stilon" +#, c-format +msgid "E798: ID is reserved for \":match\": %d" +msgstr "E798: ID estas rezervita por \":match\": %d" -# DP: mi ne scias, kio estas "preedit" -msgid "E289: input method doesn't support my preedit type" -msgstr "E289: eniga metodo ne subtenas mian antaŭredaktan tipon" +msgid "E543: Not a valid codepage" +msgstr "E543: Nevalida kodpaĝo" msgid "E293: block was not locked" msgstr "E293: bloko ne estis ŝlosita" @@ -3840,12 +3761,12 @@ msgstr "E807: Atendis Glitpunktnombron kiel argumenton de printf()" msgid "E767: Too many arguments to printf()" msgstr "E767: Tro da argumentoj al printf()" -msgid "Type number and or click with mouse (empty cancels): " +msgid "Type number and or click with the mouse (q or empty cancels): " msgstr "" -"Tajpu nombron kaj aŭ alklaku per la muso (malpleno rezignas): " +"Tajpu nombron kaj aŭ alklaku per la muso (q aŭ malpleno rezignas): " -msgid "Type number and (empty cancels): " -msgstr "Tajpu nombron kaj (malpleno rezignas): " +msgid "Type number and (q or empty cancels): " +msgstr "Tajpu nombron kaj (q aŭ malpleno rezignas): " #, c-format msgid "%ld more line" @@ -3983,6 +3904,12 @@ msgid_plural "%ld lines changed" msgstr[0] "%ld linio ŝanĝita" msgstr[1] "%ld linioj ŝanĝitaj" +#, c-format +msgid "%d line changed" +msgid_plural "%d lines changed" +msgstr[0] "%d linio ŝanĝita" +msgstr[1] "%d linioj ŝanĝitaj" + #, c-format msgid "%ld Cols; " msgstr "%ld Kolumnoj; " @@ -4416,6 +4343,9 @@ msgstr "Averto de Vim" msgid "shell returned %d" msgstr "la ŝelo liveris %d" +msgid "E861: Cannot open a second popup with a terminal" +msgstr "E861: Ne eblas malfermi duan ŝprucfenestron kun terminalo" + msgid "E450: buffer number, text or a list required" msgstr "E450: numero de bufro, teksto aŭ listo bezonata" @@ -4507,6 +4437,9 @@ msgstr "E683: Dosiernomo mankas aŭ nevalida ŝablono" msgid "Cannot open file \"%s\"" msgstr "Ne eblas malfermi dosieron \"%s\"" +msgid "cannot have both a list and a \"what\" argument" +msgstr "ne eblas havi ambaŭ Liston kaj argumenton \"what\"" + msgid "E681: Buffer is not loaded" msgstr "E681: Bufro ne estas ŝargita" @@ -4561,6 +4494,10 @@ msgstr "E70: Malplena %s%%[]" msgid "E956: Cannot use pattern recursively" msgstr "E956: Ne eblas uzi ŝablonon rekursie" +#, c-format +msgid "E654: missing delimiter after search pattern: %s" +msgstr "E654: mankas disigilo post ŝablono de serĉo: %s" + #, c-format msgid "E554: Syntax error in %s{...}" msgstr "E554: Sintaksa eraro en %s{...}" @@ -4643,13 +4580,13 @@ msgstr "E866: (NFA-regulesprimo) Mispoziciigita %c" msgid "E877: (NFA regexp) Invalid character class: %d" msgstr "E877: (NFA-regulesprimo) Nevalida klaso de signoj: %d" +msgid "E951: \\% value too large" +msgstr "E951: tro larĝa valoro de \\%" + #, c-format msgid "E867: (NFA) Unknown operator '\\z%c'" msgstr "E867: (NFA) Nekonata operatoro '\\z%c'" -msgid "E951: \\% value too large" -msgstr "E951: tro larĝa valoro de \\%" - #, c-format msgid "E867: (NFA) Unknown operator '\\%%%c'" msgstr "E867: (NFA) Nekonata operatoro '\\%%%c'" @@ -4994,9 +4931,6 @@ msgstr " (NETROVITA)" msgid " (not supported)" msgstr " (nesubtenata)" -msgid "E756: Spell checking is not enabled" -msgstr "E756: Literumilo ne estas ŝaltita" - #, c-format msgid "Warning: Cannot find word list \"%s_%s.spl\" or \"%s_ascii.spl\"" msgstr "Averto: Ne eblas trovi vortliston \"%s_%s.spl\" aŭ \"%s_ascii.spl\"" @@ -5240,32 +5174,36 @@ msgid "Reading word file %s..." msgstr "Legado de dosiero de vortoj %s..." #, c-format -msgid "Duplicate /encoding= line ignored in %s line %d: %s" -msgstr "Ripetita linio /encoding= ignorita en %s linio %d: %s" +msgid "Conversion failure for word in %s line %ld: %s" +msgstr "Malsukceso dum konverto de vorto en %s linio %ld: %s" + +#, c-format +msgid "Duplicate /encoding= line ignored in %s line %ld: %s" +msgstr "Ripetita linio /encoding= ignorita en %s linio %ld: %s" #, c-format -msgid "/encoding= line after word ignored in %s line %d: %s" -msgstr "Linio /encoding= post vorto ignorita en %s linio %d: %s" +msgid "/encoding= line after word ignored in %s line %ld: %s" +msgstr "Linio /encoding= post vorto ignorita en %s linio %ld: %s" #, c-format -msgid "Duplicate /regions= line ignored in %s line %d: %s" -msgstr "Ripetita linio /regions= ignorita en %s linio %d: %s" +msgid "Duplicate /regions= line ignored in %s line %ld: %s" +msgstr "Ripetita linio /regions= ignorita en %s linio %ld: %s" #, c-format -msgid "Too many regions in %s line %d: %s" -msgstr "Tro da regionoj en %s linio %d: %s" +msgid "Too many regions in %s line %ld: %s" +msgstr "Tro da regionoj en %s linio %ld: %s" #, c-format -msgid "/ line ignored in %s line %d: %s" -msgstr "Linio / ignorita en %s linio %d: %s" +msgid "/ line ignored in %s line %ld: %s" +msgstr "Linio / ignorita en %s linio %ld: %s" #, c-format -msgid "Invalid region nr in %s line %d: %s" -msgstr "Nevalida regiono nr en %s linio %d: %s" +msgid "Invalid region nr in %s line %ld: %s" +msgstr "Nevalida regiono nr en %s linio %ld: %s" #, c-format -msgid "Unrecognized flags in %s line %d: %s" -msgstr "Nekonata flago en %s linio %d: %s" +msgid "Unrecognized flags in %s line %ld: %s" +msgstr "Nekonata flago en %s linio %ld: %s" #, c-format msgid "Ignored %d words with non-ASCII characters" @@ -5275,8 +5213,8 @@ msgid "E845: Insufficient memory, word list will be incomplete" msgstr "E845: Ne sufiĉe da memoro, vortlisto estos nekompleta." #, c-format -msgid "Compressed %d of %d nodes; %d (%d%%) remaining" -msgstr "Densigis %d de %d nodoj; %d (%d%%) restantaj" +msgid "Compressed %s: %ld of %ld nodes; %ld (%ld%%) remaining" +msgstr "Densigis %s: %ld de %ld nodoj; %ld (%ld%%) restantaj" msgid "Reading back spell file..." msgstr "Relegas la dosieron de literumo..." @@ -5354,6 +5292,10 @@ msgstr "Anstataŭigi \"%.*s\" per:" msgid " < \"%.*s\"" msgstr " < \"%.*s\"" +#, c-format +msgid "E390: Illegal argument: %s" +msgstr "E390: Nevalida argumento: %s" + msgid "No Syntax items defined for this buffer" msgstr "Neniu sintaksa elemento difinita por tiu bufro" @@ -5366,16 +5308,18 @@ msgstr "sintakso de conceal ŝaltata" msgid "syntax conceal off" msgstr "sintakso de conceal malŝaltita" -#, c-format -msgid "E390: Illegal argument: %s" -msgstr "E390: Nevalida argumento: %s" - msgid "syntax case ignore" msgstr "sintakso ignoras usklecon" msgid "syntax case match" msgstr "sintakso konsideras usklecon" +msgid "syntax foldlevel start" +msgstr "agordo de faldo: «syntax foldlevel start»" + +msgid "syntax foldlevel minimum" +msgstr "agordo de faldo: «syntax foldlevel minimum»" + msgid "syntax spell toplevel" msgstr "literumado en teksto sen sintaksa grupo" @@ -5387,10 +5331,10 @@ msgstr "" "literumado en teksto sen sintaksa grupo, nur se ne estas @Spell aŭ @NoSpell" msgid "syntax iskeyword " -msgstr "sintakso iskeyword " +msgstr "emfaza agordo «syntax iskeyword» ŝaltita" msgid "syntax iskeyword not set" -msgstr "sintakso iskeyword ne ŝaltita" +msgstr "emfaza agordo «syntax iskeyword» neŝaltita" #, c-format msgid "E391: No such syntax cluster: %s" @@ -5694,6 +5638,12 @@ msgstr "E955: Ne estas bufro de terminalo" msgid "E982: ConPTY is not available" msgstr "E982: ConPTY ne disponeblas" +msgid "" +"E856: assert_fails() second argument must be a string or a list with one or " +"two strings" +msgstr "E856: dua argumento de assert_fails() devas esti ĉeno aŭ listo kun " +"unu aŭ du ĉenoj" + #, c-format msgid "E971: Property type %s does not exist" msgstr "E971: Tipo de eco %s ne ekzistas" @@ -5718,6 +5668,9 @@ msgstr "E967: difekta informo de eco de teksto" msgid "E968: Need at least one of 'id' or 'type'" msgstr "E968: Bezonas almenaŭ 'id' aŭ 'type'" +msgid "E860: Need 'id' and 'type' with 'both'" +msgstr "E860: 'id' kaj 'type' kun 'both' bezonata" + #, c-format msgid "E969: Property type %s already defined" msgstr "E969: tipo de eco %s jam difinita" @@ -5738,15 +5691,105 @@ msgid_plural "%ld seconds ago" msgstr[0] "antaŭ %ld sekundo" msgstr[1] "antaŭ %ld sekundoj" +msgid "E805: Using a Float as a Number" +msgstr "E805: Uzo de Glitpunktnombro kiel Nombro" + +msgid "E703: Using a Funcref as a Number" +msgstr "E703: Uzo de Funcref kiel Nombro" + +msgid "E745: Using a List as a Number" +msgstr "E745: Uzo de Listo kiel Nombro" + +msgid "E728: Using a Dictionary as a Number" +msgstr "E728: Uzo de Vortaro kiel Nombro" + +msgid "E910: Using a Job as a Number" +msgstr "E910: Uzo de Tasko kiel Nombro" + +msgid "E913: Using a Channel as a Number" +msgstr "E913: Uzo de Kanalo kiel Nombro" + +msgid "E974: Using a Blob as a Number" +msgstr "E974: Uzo de BLOB-o kiel Nombro" + +msgid "E891: Using a Funcref as a Float" +msgstr "E891: Uzo de Funcref kiel Glitpunktnombro" + +msgid "E892: Using a String as a Float" +msgstr "E892: Uzo de Ĉeno kiel Glitpunktnombro" + +msgid "E893: Using a List as a Float" +msgstr "E893: Uzo de Listo kiel Glitpunktnombro" + +msgid "E894: Using a Dictionary as a Float" +msgstr "E894: Uzo de Vortaro kiel Glitpunktnombro" + +msgid "E362: Using a boolean value as a Float" +msgstr "E362: Uzo de bulea valoro kiel Glitpunktnombro" + +msgid "E907: Using a special value as a Float" +msgstr "E907: Uzo de speciala valoro kiel Glitpunktnombro" + +msgid "E911: Using a Job as a Float" +msgstr "E911: Uzo de Tasko kiel Glitpunktnombro" + +msgid "E914: Using a Channel as a Float" +msgstr "E914: Uzo de Kanalo kiel Glitpunktnombro" + +msgid "E975: Using a Blob as a Float" +msgstr "E975: Uzo de BLOB-o kiel Glitpunktnombro" + +msgid "E729: using Funcref as a String" +msgstr "E729: uzo de Funcref kiel Ĉeno" + +msgid "E730: using List as a String" +msgstr "E730: uzo de Listo kiel Ĉeno" + +msgid "E731: using Dictionary as a String" +msgstr "E731: uzo de Vortaro kiel Ĉeno" + +msgid "E976: using Blob as a String" +msgstr "E976: uzo de BLOB-o kiel Ĉeno" + +msgid "E977: Can only compare Blob with Blob" +msgstr "E977: Eblas nur kompari BLOB-on kun BLOB-o" + +msgid "E691: Can only compare List with List" +msgstr "E691: Eblas nur kompari Liston kun Listo" + +msgid "E692: Invalid operation for List" +msgstr "E692: Nevalida operacio de Listoj" + +msgid "E735: Can only compare Dictionary with Dictionary" +msgstr "E735: Eblas nur kompari Vortaron kun Vortaro" + +msgid "E736: Invalid operation for Dictionary" +msgstr "E736: Nevalida operacio de Vortaro" + +msgid "E694: Invalid operation for Funcrefs" +msgstr "E694: Nevalida operacio de Funcref-oj" + +#, c-format +msgid "E112: Option name missing: %s" +msgstr "E112: Mankas nomo de opcio: %s" + +msgid "E973: Blob literal should have an even number of hex characters" +msgstr "E973: BLOB-a literalo devus havi paran nombron de deksesumaj signoj" + +#, c-format +msgid "E114: Missing quote: %s" +msgstr "E114: Mankas citilo: %s" + +#, c-format +msgid "E115: Missing quote: %s" +msgstr "E115: Mankas citilo: %s" + msgid "new shell started\n" msgstr "nova ŝelo lanĉita\n" msgid "Vim: Error reading input, exiting...\n" msgstr "Vim: Eraro dum legado de eniro, elironta...\n" -msgid "Used CUT_BUFFER0 instead of empty selection" -msgstr "Uzis CUT_BUFFER0 anstataŭ malplenan apartigon" - msgid "E881: Line count changed unexpectedly" msgstr "E881: Nombro de linioj ŝanĝiĝis neatendite" @@ -5961,8 +6004,13 @@ msgstr "E125: Nevalida argumento: %s" msgid "E853: Duplicate argument name: %s" msgstr "E853: Ripetita nomo de argumento: %s" -msgid "E1059: No white space allowed before :" -msgstr "E1059: Neniu spaceto permesebla antaŭ :" +#, c-format +msgid "E1059: No white space allowed before colon: %s" +msgstr "E1059: Neniu spaceto permesebla antaŭ dupunkto: %s:" + +#, c-format +msgid "E1077: Missing argument type for %s" +msgstr "E1077: Mankas tipo de argumento por %s" msgid "E1055: Missing name after ..." msgstr "E1055: Mankas nomo post ..." @@ -5970,6 +6018,10 @@ msgstr "E1055: Mankas nomo post ..." msgid "E989: Non-default argument follows default argument" msgstr "E989: Ne defaŭlta argumento post defaŭlta argumento" +#, c-format +msgid "E451: Expected }: %s" +msgstr "E451: Atendis }: %s" + #, c-format msgid "E740: Too many arguments for function %s" msgstr "E740: Tro da argumentoj por funkcio: %s" @@ -6023,6 +6075,9 @@ msgstr "E128: Nomo de funkcio devas eki per majusklo aŭ per \"s:\": %s" msgid "E884: Function name cannot contain a colon: %s" msgstr "E884: Nomo de funkcio ne povas enhavi dupunkton: %s" +msgid "E454: function list was modified" +msgstr "E454: listo de funkcioj ŝanĝiĝis" + #, c-format msgid "E123: Undefined function: %s" msgstr "E123: Nedifinita funkcio: %s" @@ -6075,6 +6130,10 @@ msgstr "E746: Nomo de funkcio ne kongruas kun dosiernomo de skripto: %s" msgid "E131: Cannot delete function %s: It is in use" msgstr "E131: Ne eblas forviŝi funkcion %s: Estas nuntempe uzata" +#, c-format +msgid "E1084: Cannot delete Vim9 script function %s" +msgstr "E1084: Ne eblas forviŝi funkcion de Vim9-skripto: %s" + msgid "E133: :return not inside a function" msgstr "E133: \":return\" ekster funkcio" @@ -6231,6 +6290,9 @@ msgstr "kun grafika interfaco X11-neXtaw." msgid "with X11-Athena GUI." msgstr "kun grafika interfaco X11-Athena." +msgid "with Haiku GUI." +msgstr "kun grafika interfaco Haiku." + msgid "with Photon GUI." msgstr "kun grafika interfaco Photon." @@ -6393,8 +6455,23 @@ msgstr "E1001: variablo ne trovita: %s" msgid "E1002: Syntax error at %s" msgstr "E1002: Sintaksa eraro en %s" -msgid "E1035: wrong argument type for +" -msgstr "E1035: nevalida tipo de argumento por +" +#, c-format +msgid "E1006: %s is used as an argument" +msgstr "E1006: %s estas uzata kiel argumento" + +msgid "E1031: Cannot use void value" +msgstr "E1031: Ne eblas uzi vakan valoron" + +#, c-format +msgid "E1013: type mismatch, expected %s but got %s" +msgstr "E1013: miskongruo de tipo, atendis %s sed ricevis %s" + +#, c-format +msgid "E1013: argument %d: type mismatch, expected %s but got %s" +msgstr "E1013: miskongruo de tipo en argumento %d: atendis %s sed ricevis %s" + +msgid "E1051: wrong argument type for +" +msgstr "E1051: nevalida tipo de argumento por +" #, c-format msgid "E1036: %c requires number or float arguments" @@ -6408,19 +6485,12 @@ msgid "E1037: Cannot use \"%s\" with %s" msgstr "E1037: Ne eblas uzi \"%s\" kun %s" #, c-format -msgid "E1037: Cannot compare %s with %s" -msgstr "E1037: Ne eblas kompari %s kun %s" +msgid "E1072: Cannot compare %s with %s" +msgstr "E1072: Ne eblas kompari %s kun %s" #, c-format -msgid "E1004: white space required before and after '%s'" -msgstr "E1004: spacetoj bezonataj ĉirkaŭ '%s'" - -#, c-format -msgid "E1006: %s is used as an argument" -msgstr "E1006: %s estas uzata kiel argumento" - -msgid "E1007: No white space allowed before <" -msgstr "E1007: Neniu spaceto permesebla antaŭ ol <" +msgid "E1085: Not a callable type: %s" +msgstr "E1085: Ne estas alvokebla tipo: %s" msgid "E1008: Missing " msgstr "E1008: Mankas " @@ -6428,13 +6498,29 @@ msgstr "E1008: Mankas " msgid "E1009: Missing > after type" msgstr "E1009: Mankas > post tipo" -msgid "E1055: This Vim is not compiled with float support" -msgstr "E1055: Tiu Vim ne estis kompilita kun glitpunktnombra eblo." +msgid "E1076: This Vim is not compiled with float support" +msgstr "E1076: Tiu Vim ne estis kompilita kun glitpunktnombra eblo" + +msgid "E1007: mandatory argument after optional argument" +msgstr "E1007: deviga argumento post nedeviga argumento" + +msgid "E740: Too many argument types" +msgstr "E740: Tro da tipoj de argumento" #, c-format msgid "E1010: Type not recognized: %s" msgstr "E1010: Tipo nerekonita: %s" +msgid "E1097: line incomplete" +msgstr "E1097: nekompleta linio" + +#, c-format +msgid "E1060: expected dot after name: %s" +msgstr "E1060: atendis punkton post nomo: %s" + +msgid "E1074: no white space allowed after dot" +msgstr "E1074: Neniu spaceto permesebla post punkto" + #, c-format msgid "E1050: Item not found: %s" msgstr "E1050: Ero netrovita: %s" @@ -6443,41 +6529,46 @@ msgstr "E1050: Ero netrovita: %s" msgid "E1011: name too long: %s" msgstr "E1011: nomo tro longa: %s" -#, c-format -msgid "E1013: type mismatch, expected %s but got %s" -msgstr "E1013: miskongruo de tipo, atendis %s sed ricevis %s" - #, c-format msgid "E1014: Invalid key: %s" msgstr "E1014: Nevalida ŝlosilo: %s" +msgid "[end of lines]" +msgstr "[fino de linioj]" + #, c-format msgid "E1015: Name expected: %s" msgstr "E1015: Nomo atendita: %s" +msgid "E1096: Returning a value in a function without a return type" +msgstr "E1096: liveraĵo en funkcio sen tipo de liveraĵo" + msgid "E1003: Missing return value" msgstr "E1003: Mankas liveraĵo" +msgid "global" +msgstr "malloka variablo" + +msgid "buffer" +msgstr "bufro" + +msgid "window" +msgstr "fenestro" + +msgid "tab" +msgstr "langeto" + +msgid "E1092: Cannot use a list for a declaration" +msgstr "E1092: Ne eblas uzi liston por deklaro" + #, c-format msgid "E1052: Cannot declare an option: %s" msgstr "E1052: Ne eblas deklari opcion: %s" -#, c-format -msgid "E1065: Cannot declare an environment variable: %s" -msgstr "E1065: Ne eblas deklari medivariablon: %s" - #, c-format msgid "E1066: Cannot declare a register: %s" msgstr "E1066: Ne eblas deklari reĝistron: %s" -#, c-format -msgid "E1016: Cannot declare a global variable: %s" -msgstr "E1016: Ne eblas deklari mallokan variablon %s" - -#, c-format -msgid "E1064: Cannot declare a v: variable: %s" -msgstr "E1064: Ne eblas deklari v:-variablon %s" - #, c-format msgid "E1034: Cannot use reserved name %s" msgstr "E1034: Ne eblas uzi rezervitan nomon %s" @@ -6494,26 +6585,40 @@ msgstr "E1018: Ne eblas valorizi konstanton: %s" msgid "E1054: Variable already declared in the script: %s" msgstr "E1054: Variablo jam deklarita en la skripto: %s" +#, c-format +msgid "E1082: Cannot use a namespaced variable: %s" +msgstr "E1082: ne eblas uzi variablon en nomspaco: %s" + +#, c-format +msgid "E1089: unknown variable: %s" +msgstr "E1089: Nekonata variablo: %s" + +msgid "E1019: Can only concatenate to string" +msgstr "E1019: Nur eblas kunmeti al ĉeno" + #, c-format msgid "E1020: cannot use an operator on a new variable: %s" msgstr "E1020: ne eblas uzi operatoron kun nova variablo: %s" -msgid "E1031: Cannot use void value" -msgstr "E1031: Ne eblas uzi vakan valoron" +msgid "E1087: cannot use an index when declaring a variable" +msgstr "E1087: Ne eblas uzi indekson en deklaro de variablo" -msgid "E1021: const requires a value" -msgstr "E1021: konstanto bezonas valoron" +#, c-format +msgid "E1088: cannot use an index on %s" +msgstr "E1088: Ne eblas uzi indekson en %s" -msgid "E1022: type or initialization required" -msgstr "E1022: tipo aŭ pravalorizo bezonata" +#, c-format +msgid "E1090: Cannot assign to argument %s" +msgstr "E1090: Ne eblas valorizi argumenton %s" + +#, c-format +msgid "E1081: Cannot unlet %s" +msgstr "E1081: Ne eblas uzi \"unlet %s\"" #, c-format msgid "E1023: variable already defined: %s" msgstr "E1023: variablo jam difinita: %s" -msgid "E1024: need a List to iterate over" -msgstr "E1024: Listo bezonata por iteracii" - msgid "E1033: catch unreachable after catch-all" msgstr "E1033: kaptokodobloko neatingebla post kapto de ĉiuj esceptoj" @@ -6524,36 +6629,64 @@ msgstr "E1067: Nekongrua disigilo: %s" msgid "E1032: missing :catch or :finally" msgstr "E1032: mankas :catch aŭ :finally" +msgid "E1083: missing backtick" +msgstr "E1083: Mankas malapostrofo" + #, c-format msgid "E488: Trailing characters: %s" msgstr "E488: Vostaj signoj: %s" +msgid "E1025: using } outside of a block scope" +msgstr "E1025: uzo de } ekster amplekso de kodbloko" + +msgid "E1095: Unreachable code after :return" +msgstr "E1095: Neatingebla fontkodo post :return" + +msgid "E1086: Cannot use :function inside :def" +msgstr "E1086: Ne eblas uzi \":function\" en \":def\"" + +#, c-format +msgid "E476: Invalid command: %s" +msgstr "E476: Nevalida komando: %s" + msgid "E1026: Missing }" msgstr "E1026: Mankas }" msgid "E1027: Missing return statement" msgstr "E1027: Mankas revenordono" -#, c-format -msgid "E121: Undefined variable: g:%s" -msgstr "E121: Nedifinita variablo: g:%s" +msgid "E1028: compile_def_function failed" +msgstr "E1028: compile_def_function malsukcesis" #, c-format -msgid "E1060: Invalid environment variable name: %s" -msgstr "E1060: Nevalida nomo de medivariablo: %s" +msgid "E1091: Function is not compiled: %s" +msgstr "E1091: Netradukita funkcio: %s" -msgid "E1051: Expected string or number" -msgstr "E1051: Atendis ĉenon aŭ nombron" +#, c-format +msgid "E121: Undefined variable: %c:%s" +msgstr "E121: Nedifinita variablo: %c:%s" #, c-format msgid "E1029: Expected %s but got %s" msgstr "E1029: Atendis %s sed ricevis %s" +#, c-format +msgid "E1093: Expected %d items but got %d" +msgstr "E1093: Atendis %d eroj sed ricevis %d" + +#, c-format +msgid "E1061: Cannot find function %s" +msgstr "E1061: Ne eblas trovi funkcion: %s" + +#, c-format +msgid "E1062: Function %s is not compiled" +msgstr "E1062: Funkcio %s ne estas tradukita" + msgid "E1030: Using a String as a Number" msgstr "E1030: Uzo de Ĉeno kiel Nombro" -msgid "E1042: import/export can only be used in vim9script" -msgstr "E1042: importo/eksporto nur uzeblas en vim9script" +msgid "E1042: export can only be used in vim9script" +msgstr "E1042: eksporto nur uzeblas en vim9script" msgid "E1038: vim9script can only be used in a script" msgstr "E1038: :vim9script nur uzeblas en skripto" @@ -6567,18 +6700,8 @@ msgstr "E1044: eksporto kun nevalida argumento" msgid "E1043: Invalid command after :export" msgstr "E1043: Nevalida komando post :export" -msgid "E1045: Missing \"as\" after *" -msgstr "E1045: Mankas \"as\" post *" - -msgid "E1045: Missing \"from\"" -msgstr "E1045: Mankas \"from\"" - -msgid "E1045: Invalid string after \"from\"" -msgstr "E1045: Nevalida ĉeno post \"from\"" - -#, c-format -msgid "E1053: Could not import \"%s\"" -msgstr "E1053: Ne eblis importi \"%s\"" +msgid "E1094: import can only be used in a script" +msgstr "E1094: importo nur uzeblas en skripto" #, c-format msgid "E1049: Item not exported in script: %s" @@ -6588,11 +6711,24 @@ msgstr "E1049: Ero ne estas eksportita en skripto: %s" msgid "E1048: Item not found in script: %s" msgstr "E1048: Ero ne trovita en skripto: %s" +msgid "E1047: syntax error in import" +msgstr "E1047: Sintaksa eraro en importo" + msgid "E1046: Missing comma in import" msgstr "E1046: Mankas komo en importo" -msgid "E1047: syntax error in import" -msgstr "E1047: Sintaksa eraro en importo" +msgid "E1045: Missing \"as\" after *" +msgstr "E1045: Mankas \"as\" post *" + +msgid "E1070: Missing \"from\"" +msgstr "E1070: Mankas \"from\"" + +msgid "E1071: Invalid string after \"from\"" +msgstr "E1071: Nevalida ĉeno post \"from\"" + +#, c-format +msgid "E1053: Could not import \"%s\"" +msgstr "E1053: Ne eblis importi \"%s\"" msgid "" "\n" @@ -6723,8 +6859,8 @@ msgid "# Value of 'encoding' when this file was written\n" msgstr "# Valoro de 'encoding' kiam tiu dosiero estis kreita\n" #, c-format -msgid "Reading viminfo file \"%s\"%s%s%s" -msgstr "Legado de dosiero viminfo \"%s\"%s%s%s" +msgid "Reading viminfo file \"%s\"%s%s%s%s" +msgstr "Legado de dosiero viminfo \"%s\"%s%s%s%s" msgid " info" msgstr " informo" @@ -6783,9 +6919,6 @@ msgstr "E443: Ne eblas rotacii kiam alia fenestro estas dividita" msgid "E444: Cannot close last window" msgstr "E444: Ne eblas fermi la lastan fenestron" -msgid "E813: Cannot close autocmd or popup window" -msgstr "E813: Ne eblas fermi la ŝprucfenestron aŭ fenestron de aŭtokomandoj" - msgid "E814: Cannot close window, only autocmd window would remain" msgstr "E814: Ne eblas fermi fenestron, nur la fenestro de aŭtokomandoj restus" @@ -6948,6 +7081,9 @@ msgstr "E476: Nevalida komando" msgid "E17: \"%s\" is a directory" msgstr "E17: \"%s\" estas dosierujo" +msgid "E756: Spell checking is not possible" +msgstr "E756: malpermesata literumilo" + #, c-format msgid "E364: Library call failed for \"%s()\"" msgstr "E364: Alvoko al biblioteko malsukcesis por \"%s()\"" @@ -7156,9 +7292,16 @@ msgstr "E716: Ŝlosilo malekzistas en Vortaro: %s" msgid "E714: List required" msgstr "E714: Listo bezonata" +msgid "E1090: List, Dict or Blob required" +msgstr "E1090: Listo, Vortaro aŭ BLOB-o bezonata" + msgid "E897: List or Blob required" msgstr "E897: Listo aŭ BLOB-o bezonata" +#, c-format +msgid "E697: Missing end of List ']': %s" +msgstr "E697: Mankas fino de Listo ']': %s" + #, c-format msgid "E712: Argument of %s must be a List or Dictionary" msgstr "E712: Argumento de %s devas esti Listo aŭ Vortaro" @@ -7183,6 +7326,14 @@ msgstr "E113: Nekonata opcio: %s" msgid "E18: Unexpected characters in :let" msgstr "E18: Neatenditaj signoj en \":let\"" +#, c-format +msgid "E998: Reduce of an empty %s with no initial value" +msgstr "E998: Redukto de malplena %s sen komenca valoro" + +#, c-format +msgid "E857: Dictionary key \"%s\" required" +msgstr "E857: Ŝlosilo \"%s\" de vortaro bezonata" + msgid "E47: Error while reading errorfile" msgstr "E47: Eraro dum legado de erardosiero" @@ -7192,6 +7343,12 @@ msgstr "E48: Nepermesebla en sabloludejo" msgid "E523: Not allowed here" msgstr "E523: Nepermesebla tie" +msgid "E578: Not allowed to change text here" +msgstr "E578: ŝanĝo de teksto nepermesebla tie" + +msgid "E565: Not allowed to change text or change window" +msgstr "E565: Ne eblas ŝanĝi tekston aŭ fenestron" + msgid "E359: Screen mode setting not supported" msgstr "E359: Reĝimo de ekrano ne subtenata" @@ -7301,6 +7458,9 @@ msgstr "E764: La opcio '%s' ne estas ŝaltita" msgid "E850: Invalid register name" msgstr "E850: Nevalida nomo de reĝistro" +msgid "E806: using Float as a String" +msgstr "E806: uzo de Glitpunktnombro kiel Ĉeno" + #, c-format msgid "E919: Directory not found in '%s': \"%s\"" msgstr "E919: Dosierujo ne trovita en '%s': \"%s\"" @@ -7308,6 +7468,9 @@ msgstr "E919: Dosierujo ne trovita en '%s': \"%s\"" msgid "E952: Autocommand caused recursive behavior" msgstr "E952: Aŭtokomandoj kaŭzis rekursian konduton" +msgid "E813: Cannot close autocmd or popup window" +msgstr "E813: Ne eblas fermi la ŝprucfenestron aŭ fenestron de aŭtokomandoj" + msgid "E328: Menu only exists in another mode" msgstr "E328: Menuo nur ekzistas en alia reĝimo" @@ -7349,6 +7512,43 @@ msgstr "E587: \":break\" sen \":while\" aŭ \":for\"" msgid "E274: No white space allowed before parenthesis" msgstr "E274: Neniu spaceto permesebla antaŭ ol komenca krampo" +#, c-format +msgid "E1004: white space required before and after '%s'" +msgstr "E1004: spacetoj bezonataj ĉirkaŭ '%s'" + +#, c-format +msgid "E1069: white space required after '%s'" +msgstr "E1069: spaceto bezonata post '%s'" + +#, c-format +msgid "E1068: No white space allowed before '%s'" +msgstr "E1068: Neniu spaceto permesebla antaŭ '%s'" + +#, c-format +msgid "E940: Cannot lock or unlock variable %s" +msgstr "E940: Ne eblas ŝlosi aŭ malŝlosi variablon %s" + +msgid "E1021: const requires a value" +msgstr "E1021: konstanto bezonas valoron" + +msgid "E1022: type or initialization required" +msgstr "E1022: tipo aŭ pravalorizo bezonata" + +#, c-format +msgid "E1016: Cannot declare a %s variable: %s" +msgstr "E1016: Ne eblas deklari %s-variablon: %s" + +#, c-format +msgid "E1016: Cannot declare an environment variable: %s" +msgstr "E1016: Ne eblas deklari medivariablon: %s" + +msgid "E1050: Colon required before a range" +msgstr "E1050: Dupunkto bezonata antaŭ amplekso" + +#, c-format +msgid "E254: Cannot allocate color %s" +msgstr "E254: Ne eblas disponigi koloron %s" + msgid "search hit TOP, continuing at BOTTOM" msgstr "serĉo atingis SUPRON, daŭrigonte al SUBO" From 4fc224ca1cf2a8991c5ea17682a742c6ad5ad0f3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 26 Jul 2020 17:56:25 +0200 Subject: [PATCH 0013/1384] patch 8.2.1300: Vim9: optional argument type not parsed properly Problem: Vim9: optional argument type not parsed properly. Solution: Skip over the "?". (issue #6507) --- src/evalvars.c | 2 +- src/proto/vim9compile.pro | 2 +- src/testdir/test_vim9_func.vim | 13 +++++++++++++ src/userfunc.c | 4 ++-- src/version.c | 2 ++ src/vim9compile.c | 25 ++++++++++++++++++------- 6 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/evalvars.c b/src/evalvars.c index e11fdac41fb3af..f409f8c0066a1f 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -1013,7 +1013,7 @@ skip_var_one(char_u *arg, int include_type) if (end == arg + 2 && end[-1] == ':') --end; if (*end == ':') - end = skip_type(skipwhite(end + 1)); + end = skip_type(skipwhite(end + 1), FALSE); } return end; } diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro index 6bf3eb315d3d05..4108c04af4eb09 100644 --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -6,7 +6,7 @@ type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap); int check_typval_type(type_T *expected, typval_T *actual_tv); int check_type(type_T *expected, type_T *actual, int give_msg); int check_compare_types(exptype_T type, typval_T *tv1, typval_T *tv2); -char_u *skip_type(char_u *start); +char_u *skip_type(char_u *start, int optional); type_T *parse_type(char_u **arg, garray_T *type_gap); char *vartype_name(vartype_T type); char *type_name(type_T *type, char **tofree); diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 49be8f97a2527e..ade1fd145914c7 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -350,6 +350,19 @@ def Test_call_funcref() let Funcref: func(string) = function('UseNumber') END CheckScriptFailure(lines, 'E1013: type mismatch, expected func(string) but got func(number)') + + lines =<< trim END + vim9script + def EchoNr(nr = 34) + g:echo = nr + enddef + let Funcref: func(?number) = function('EchoNr') + Funcref() + assert_equal(34, g:echo) + Funcref(123) + assert_equal(123, g:echo) + END + CheckScriptSuccess(lines) enddef let SomeFunc = function('len') diff --git a/src/userfunc.c b/src/userfunc.c index 3e566f334a7413..d17e807dc616ce 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -123,7 +123,7 @@ one_function_arg(char_u *arg, garray_T *newargs, garray_T *argtypes, int skip) return arg; } type = skipwhite(p); - p = skip_type(type); + p = skip_type(type, TRUE); type = vim_strnsave(type, p - type); } else if (*skipwhite(p) != '=') @@ -2778,7 +2778,7 @@ def_function(exarg_T *eap, char_u *name_arg) if (*p == ':') { ret_type = skipwhite(p + 1); - p = skip_type(ret_type); + p = skip_type(ret_type, FALSE); if (p > ret_type) { ret_type = vim_strnsave(ret_type, p - ret_type); diff --git a/src/version.c b/src/version.c index 93bcc43247dc57..68c7cf5013512b 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1300, /**/ 1299, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 746c9aa1a2d5b7..1354a38b2c79a1 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -534,8 +534,16 @@ typval2type(typval_T *tv, garray_T *type_gap) if (name != NULL) // TODO: how about a builtin function? ufunc = find_func(name, FALSE, NULL); - if (ufunc != NULL && ufunc->uf_func_type != NULL) - return ufunc->uf_func_type; + if (ufunc != NULL) + { + // May need to get the argument types from default values by + // compiling the function. + if (ufunc->uf_def_status == UF_TO_BE_COMPILED + && compile_def_function(ufunc, TRUE, NULL) == FAIL) + return NULL; + if (ufunc->uf_func_type != NULL) + return ufunc->uf_func_type; + } } actual = alloc_type(type_gap); @@ -1916,12 +1924,15 @@ free_locals(cctx_T *cctx) /* * Skip over a type definition and return a pointer to just after it. + * When "optional" is TRUE then a leading "?" is accepted. */ char_u * -skip_type(char_u *start) +skip_type(char_u *start, int optional) { char_u *p = start; + if (optional && *p == '?') + ++p; while (ASCII_ISALNUM(*p) || *p == '_') ++p; @@ -1929,7 +1940,7 @@ skip_type(char_u *start) if (*skipwhite(p) == '<') { p = skipwhite(p); - p = skip_type(skipwhite(p + 1)); + p = skip_type(skipwhite(p + 1), FALSE); p = skipwhite(p); if (*p == '>') ++p; @@ -1945,7 +1956,7 @@ skip_type(char_u *start) { char_u *sp = p; - p = skip_type(p); + p = skip_type(p, TRUE); if (p == sp) return p; // syntax error if (*p == ',') @@ -1954,7 +1965,7 @@ skip_type(char_u *start) if (*p == ')') { if (p[1] == ':') - p = skip_type(skipwhite(p + 2)); + p = skip_type(skipwhite(p + 2), FALSE); else ++p; } @@ -1962,7 +1973,7 @@ skip_type(char_u *start) else { // handle func: return_type - p = skip_type(skipwhite(p + 1)); + p = skip_type(skipwhite(p + 1), FALSE); } } From ace6132aa8c5fce9d4965e1f2e3a42071815b9de Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 26 Jul 2020 18:16:58 +0200 Subject: [PATCH 0014/1384] patch 8.2.1301: Vim9: varargs argument type not parsed properly Problem: Vim9: varargs argument type not parsed properly. Solution: Skip over the "...". (issue #6507) --- src/testdir/test_vim9_func.vim | 13 +++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 2 ++ 3 files changed, 17 insertions(+) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index ade1fd145914c7..0d39d576498408 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -363,6 +363,19 @@ def Test_call_funcref() assert_equal(123, g:echo) END CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + def EchoList(...l: list) + g:echo = l + enddef + let Funcref: func(...list) = function('EchoList') + Funcref() + assert_equal([], g:echo) + Funcref(1, 2, 3) + assert_equal([1, 2, 3], g:echo) + END + CheckScriptSuccess(lines) enddef let SomeFunc = function('len') diff --git a/src/version.c b/src/version.c index 68c7cf5013512b..2481434407c52b 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1301, /**/ 1300, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 1354a38b2c79a1..31e761284e26ec 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1956,6 +1956,8 @@ skip_type(char_u *start, int optional) { char_u *sp = p; + if (STRNCMP(p, "...", 3) == 0) + p += 3; p = skip_type(p, TRUE); if (p == sp) return p; // syntax error From 01865ade85d2508639e24aaca5948b09fb284a82 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 26 Jul 2020 18:33:09 +0200 Subject: [PATCH 0015/1384] patch 8.2.1302: Vim9: varargs arg after optional arg does not work Problem: Vim9: varargs arg after optional arg does not work Solution: Check for the "..." first. (issue #6507) --- src/testdir/test_vim9_func.vim | 22 ++++++++++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 10 +++++----- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 0d39d576498408..c05e98e70451a5 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -376,6 +376,28 @@ def Test_call_funcref() assert_equal([1, 2, 3], g:echo) END CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + def OptAndVar(nr: number, opt = 12, ...l: list): number + g:optarg = opt + g:listarg = l + return nr + enddef + let Funcref: func(number, ?number, ...list): number = function('OptAndVar') + assert_equal(10, Funcref(10)) + assert_equal(12, g:optarg) + assert_equal([], g:listarg) + + assert_equal(11, Funcref(11, 22)) + assert_equal(22, g:optarg) + assert_equal([], g:listarg) + + assert_equal(17, Funcref(17, 18, 1, 2, 3)) + assert_equal(18, g:optarg) + assert_equal([1, 2, 3], g:listarg) + END + CheckScriptSuccess(lines) enddef let SomeFunc = function('len') diff --git a/src/version.c b/src/version.c index 2481434407c52b..e969ab0f3529f8 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1302, /**/ 1301, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 31e761284e26ec..8efb1f672fd8e2 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2106,16 +2106,16 @@ parse_type(char_u **arg, garray_T *type_gap) first_optional = argcount; ++p; } - else if (first_optional != -1) - { - emsg(_("E1007: mandatory argument after optional argument")); - return &t_any; - } else if (STRNCMP(p, "...", 3) == 0) { flags |= TTFLAG_VARARGS; p += 3; } + else if (first_optional != -1) + { + emsg(_("E1007: mandatory argument after optional argument")); + return &t_any; + } arg_type[argcount++] = parse_type(&p, type_gap); From 6d585f4c5c8d120f768dd61bfd32f6e57ad562a7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 26 Jul 2020 22:20:54 +0200 Subject: [PATCH 0016/1384] patch 8.2.1303: calling popup_setoptions() resets 'signcolumn' Problem: Calling popup_setoptions() resets 'signcolumn'. Solution: Only set 'signcolumn' when creating the popup. (closes #6542) --- src/popupwin.c | 6 ++++-- src/testdir/test_popupwin.vim | 10 ++++++++++ src/version.c | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/popupwin.c b/src/popupwin.c index fc69c90d9d7cd7..d2b7f22f0b91a1 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -740,8 +740,6 @@ apply_general_options(win_T *wp, dict_T *dict) set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1, str, OPT_FREE|OPT_LOCAL, 0); - set_string_option_direct_in_win(wp, (char_u *)"signcolumn", -1, - (char_u *)"no", OPT_FREE|OPT_LOCAL, 0); set_padding_border(dict, wp->w_popup_padding, "padding", 999); set_padding_border(dict, wp->w_popup_border, "border", 1); @@ -946,6 +944,10 @@ apply_options(win_T *wp, dict_T *dict) int nr; apply_move_options(wp, dict); + + set_string_option_direct_in_win(wp, (char_u *)"signcolumn", -1, + (char_u *)"no", OPT_FREE|OPT_LOCAL, 0); + apply_general_options(wp, dict); nr = dict_get_number(dict, (char_u *)"hidden"); diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index 054d479efd37ae..beb6870b6de43b 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -3115,6 +3115,11 @@ func Test_popupmenu_info_border() call term_sendkeys(buf, "a\\") call VerifyScreenDump(buf, 'Test_popupwin_infopopup_8', {}) + call term_sendkeys(buf, " \") + call term_sendkeys(buf, ":set completepopup+=width:10\") + call term_sendkeys(buf, "a\\") + call VerifyScreenDump(buf, 'Test_popupwin_infopopup_9', {}) + call term_sendkeys(buf, "\") call StopVimInTerminal(buf) call delete('XtestInfoPopup') @@ -3436,6 +3441,11 @@ func Test_popupwin_atcursor_far_right() normal! ggg$ let winid = popup_atcursor(repeat('x', 500), #{moved: 'any', border: []}) + " 'signcolumn' was getting reset + call setwinvar(winid, '&signcolumn', 'yes') + call popup_setoptions(winid, {'zindex': 1000}) + call assert_equal('yes', getwinvar(winid, '&signcolumn')) + call popup_close(winid) bwipe! set signcolumn& diff --git a/src/version.c b/src/version.c index e969ab0f3529f8..73ab8c3998eb71 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1303, /**/ 1302, /**/ From 6ca6ca48898750dd55cad13c88a9c1dfd7fdaad5 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 27 Jul 2020 19:47:07 +0200 Subject: [PATCH 0017/1384] patch 8.2.1304: debug backtrace isn't tested much Problem: Debug backtrace isn't tested much. Solution: Add more specific tests. (Ben Jackson, closes #6540) --- src/testdir/runtest.vim | 5 + src/testdir/test_debugger.vim | 452 +++++++++++++++++++++++++++++++++- src/version.c | 2 + 3 files changed, 453 insertions(+), 6 deletions(-) diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim index 3cf2a506c975e4..6cc7202dc7037f 100644 --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -13,6 +13,9 @@ " For csh: " setenv TEST_FILTER Test_channel " +" While working on a test you can make $TEST_NO_RETRY non-empty to not retry: +" export TEST_NO_RETRY=yes +" " To ignore failure for tests that are known to fail in a certain environment, " set $TEST_MAY_FAIL to a comma separated list of function names. E.g. for " sh/bash: @@ -440,9 +443,11 @@ for g:testfunc in sort(s:tests) call RunTheTest(g:testfunc) " Repeat a flaky test. Give up when: + " - $TEST_NO_RETRY is not empty " - it fails again with the same message " - it fails five times (with a different message) if len(v:errors) > 0 + \ $TEST_NO_RETRY == '' \ && (index(s:flaky_tests, g:testfunc) >= 0 \ || g:test_is_flaky) while 1 diff --git a/src/testdir/test_debugger.vim b/src/testdir/test_debugger.vim index a99154a5af19c9..e019617e685d57 100644 --- a/src/testdir/test_debugger.vim +++ b/src/testdir/test_debugger.vim @@ -4,6 +4,19 @@ source shared.vim source screendump.vim source check.vim +func CheckDbgOutput(buf, lines, options = {}) + " Verify the expected output + let lnum = 20 - len(a:lines) + for l in a:lines + if get(a:options, 'match', 'equal') ==# 'pattern' + call WaitForAssert({-> assert_match(l, term_getline(a:buf, lnum))}, 200) + else + call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, 200) + endif + let lnum += 1 + endfor +endfunc + " Run a Vim debugger command " If the expected output argument is supplied, then check for it. func RunDbgCmd(buf, cmd, ...) @@ -11,12 +24,11 @@ func RunDbgCmd(buf, cmd, ...) call TermWait(a:buf) if a:0 != 0 - " Verify the expected output - let lnum = 20 - len(a:1) - for l in a:1 - call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, 200) - let lnum += 1 - endfor + let options = #{match: 'equal'} + if a:0 > 1 + call extend(options, a:2) + endif + call CheckDbgOutput(a:buf, a:1, options) endif endfunc @@ -315,3 +327,431 @@ func Test_Debugger() call delete('Xtest.vim') endfunc + +func Test_Backtrace_Through_Source() + CheckRunVimInTerminal + + let file1 =<< trim END + func SourceAnotherFile() + source Xtest2.vim + endfunc + + func CallAFunction() + call SourceAnotherFile() + call File2Function() + endfunc + + func GlobalFunction() + call CallAFunction() + endfunc + END + call writefile(file1, 'Xtest1.vim') + + let file2 =<< trim END + func DoAThing() + echo "DoAThing" + endfunc + + func File2Function() + call DoAThing() + endfunc + + call File2Function() + END + call writefile(file2, 'Xtest2.vim') + + let buf = RunVimInTerminal('-S Xtest1.vim', {}) + + call RunDbgCmd(buf, + \ ':debug call GlobalFunction()', + \ ['cmd: call GlobalFunction()']) + call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()']) + + call RunDbgCmd(buf, 'backtrace', ['>backtrace', + \ '->0 function GlobalFunction', + \ 'line 1: call CallAFunction()']) + + call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()']) + call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim']) + + call RunDbgCmd(buf, 'backtrace', ['>backtrace', + \ ' 2 function GlobalFunction[1]', + \ ' 1 CallAFunction[1]', + \ '->0 SourceAnotherFile', + \ 'line 1: source Xtest2.vim']) + + " Step into the 'source' command. Note that we print the full trace all the + " way though the source command. + call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 3 function GlobalFunction[1]', + \ ' 2 CallAFunction[1]', + \ ' 1 SourceAnotherFile[1]', + \ '->0 script ' .. getcwd() .. '/Xtest2.vim', + \ 'line 1: func DoAThing()']) + + " step until we have another meaninfgul trace + call RunDbgCmd(buf, 'step', ['line 5: func File2Function()']) + call RunDbgCmd(buf, 'step', ['line 9: call File2Function()']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 3 function GlobalFunction[1]', + \ ' 2 CallAFunction[1]', + \ ' 1 SourceAnotherFile[1]', + \ '->0 script ' .. getcwd() .. '/Xtest2.vim', + \ 'line 9: call File2Function()']) + + call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()']) + call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 5 function GlobalFunction[1]', + \ ' 4 CallAFunction[1]', + \ ' 3 SourceAnotherFile[1]', + \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]', + \ ' 1 function File2Function[1]', + \ '->0 DoAThing', + \ 'line 1: echo "DoAThing"']) + + " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim + call RunDbgCmd(buf, 'step', ['line 1: End of function']) + call RunDbgCmd(buf, 'step', ['line 1: End of function']) + call RunDbgCmd(buf, 'step', ['line 10: End of sourced file']) + call RunDbgCmd(buf, 'step', ['line 1: End of function']) + call RunDbgCmd(buf, 'step', ['line 2: call File2Function()']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 1 function GlobalFunction[1]', + \ '->0 CallAFunction', + \ 'line 2: call File2Function()']) + + call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 2 function GlobalFunction[1]', + \ ' 1 CallAFunction[2]', + \ '->0 File2Function', + \ 'line 1: call DoAThing()']) + + call StopVimInTerminal(buf) + call delete('Xtest1.vim') + call delete('Xtest2.vim') +endfunc + +func Test_Backtrace_Autocmd() + CheckRunVimInTerminal + + let file1 =<< trim END + func SourceAnotherFile() + source Xtest2.vim + endfunc + + func CallAFunction() + call SourceAnotherFile() + call File2Function() + endfunc + + func GlobalFunction() + call CallAFunction() + endfunc + + au User TestGlobalFunction :call GlobalFunction() | echo "Done" + END + call writefile(file1, 'Xtest1.vim') + + let file2 =<< trim END + func DoAThing() + echo "DoAThing" + endfunc + + func File2Function() + call DoAThing() + endfunc + + call File2Function() + END + call writefile(file2, 'Xtest2.vim') + + let buf = RunVimInTerminal('-S Xtest1.vim', {}) + + call RunDbgCmd(buf, + \ ':debug doautocmd User TestGlobalFunction', + \ ['cmd: doautocmd User TestGlobalFunction']) + call RunDbgCmd(buf, 'step', ['cmd: call GlobalFunction() | echo "Done"']) + + " At this point the ontly thing in the stack is the autocommand + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ '->0 User Autocommands for "TestGlobalFunction"', + \ 'cmd: call GlobalFunction() | echo "Done"']) + + " And now we're back into the call stack + call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 1 User Autocommands for "TestGlobalFunction"', + \ '->0 function GlobalFunction', + \ 'line 1: call CallAFunction()']) + + call RunDbgCmd(buf, 'step', ['line 1: call SourceAnotherFile()']) + call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim']) + + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 3 User Autocommands for "TestGlobalFunction"', + \ ' 2 function GlobalFunction[1]', + \ ' 1 CallAFunction[1]', + \ '->0 SourceAnotherFile', + \ 'line 1: source Xtest2.vim']) + + " Step into the 'source' command. Note that we print the full trace all the + " way though the source command. + call RunDbgCmd(buf, 'step', ['line 1: func DoAThing()']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 4 User Autocommands for "TestGlobalFunction"', + \ ' 3 function GlobalFunction[1]', + \ ' 2 CallAFunction[1]', + \ ' 1 SourceAnotherFile[1]', + \ '->0 script ' .. getcwd() .. '/Xtest2.vim', + \ 'line 1: func DoAThing()']) + + " step until we have another meaninfgul trace + call RunDbgCmd(buf, 'step', ['line 5: func File2Function()']) + call RunDbgCmd(buf, 'step', ['line 9: call File2Function()']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 4 User Autocommands for "TestGlobalFunction"', + \ ' 3 function GlobalFunction[1]', + \ ' 2 CallAFunction[1]', + \ ' 1 SourceAnotherFile[1]', + \ '->0 script ' .. getcwd() .. '/Xtest2.vim', + \ 'line 9: call File2Function()']) + + call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()']) + call RunDbgCmd(buf, 'step', ['line 1: echo "DoAThing"']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 6 User Autocommands for "TestGlobalFunction"', + \ ' 5 function GlobalFunction[1]', + \ ' 4 CallAFunction[1]', + \ ' 3 SourceAnotherFile[1]', + \ ' 2 script ' .. getcwd() .. '/Xtest2.vim[9]', + \ ' 1 function File2Function[1]', + \ '->0 DoAThing', + \ 'line 1: echo "DoAThing"']) + + " Now, step (back to Xfile1.vim), and call the function _in_ Xfile2.vim + call RunDbgCmd(buf, 'step', ['line 1: End of function']) + call RunDbgCmd(buf, 'step', ['line 1: End of function']) + call RunDbgCmd(buf, 'step', ['line 10: End of sourced file']) + call RunDbgCmd(buf, 'step', ['line 1: End of function']) + call RunDbgCmd(buf, 'step', ['line 2: call File2Function()']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 2 User Autocommands for "TestGlobalFunction"', + \ ' 1 function GlobalFunction[1]', + \ '->0 CallAFunction', + \ 'line 2: call File2Function()']) + + call RunDbgCmd(buf, 'step', ['line 1: call DoAThing()']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 3 User Autocommands for "TestGlobalFunction"', + \ ' 2 function GlobalFunction[1]', + \ ' 1 CallAFunction[2]', + \ '->0 File2Function', + \ 'line 1: call DoAThing()']) + + + " Now unwind so that we get back to the original autocommand (and the second + " cmd echo "Done") + call RunDbgCmd(buf, 'finish', ['line 1: End of function']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 3 User Autocommands for "TestGlobalFunction"', + \ ' 2 function GlobalFunction[1]', + \ ' 1 CallAFunction[2]', + \ '->0 File2Function', + \ 'line 1: End of function']) + + call RunDbgCmd(buf, 'finish', ['line 2: End of function']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 2 User Autocommands for "TestGlobalFunction"', + \ ' 1 function GlobalFunction[1]', + \ '->0 CallAFunction', + \ 'line 2: End of function']) + + call RunDbgCmd(buf, 'finish', ['line 1: End of function']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 1 User Autocommands for "TestGlobalFunction"', + \ '->0 function GlobalFunction', + \ 'line 1: End of function']) + + call RunDbgCmd(buf, 'step', ['cmd: echo "Done"']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ '->0 User Autocommands for "TestGlobalFunction"', + \ 'cmd: echo "Done"']) + + call StopVimInTerminal(buf) + call delete('Xtest1.vim') + call delete('Xtest2.vim') +endfunc + +func Test_Backtrace_CmdLine() + CheckRunVimInTerminal + + let file1 =<< trim END + func SourceAnotherFile() + source Xtest2.vim + endfunc + + func CallAFunction() + call SourceAnotherFile() + call File2Function() + endfunc + + func GlobalFunction() + call CallAFunction() + endfunc + + au User TestGlobalFunction :call GlobalFunction() | echo "Done" + END + call writefile(file1, 'Xtest1.vim') + + let file2 =<< trim END + func DoAThing() + echo "DoAThing" + endfunc + + func File2Function() + call DoAThing() + endfunc + + call File2Function() + END + call writefile(file2, 'Xtest2.vim') + + let buf = RunVimInTerminal( + \ '-S Xtest1.vim -c "debug call GlobalFunction()"', + \ {'wait_for_ruler': 0}) + + " Need to wait for the vim-in-terminal to be ready + call CheckDbgOutput(buf, ['command line', + \ 'cmd: call GlobalFunction()']) + + " At this point the ontly thing in the stack is the cmdline + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ '->0 command line', + \ 'cmd: call GlobalFunction()']) + + " And now we're back into the call stack + call RunDbgCmd(buf, 'step', ['line 1: call CallAFunction()']) + call RunDbgCmd(buf, 'backtrace', [ + \ '>backtrace', + \ ' 1 command line', + \ '->0 function GlobalFunction', + \ 'line 1: call CallAFunction()']) + + call StopVimInTerminal(buf) + call delete('Xtest1.vim') + call delete('Xtest2.vim') +endfunc + +func Test_Backtrace_DefFunction() + CheckRunVimInTerminal + + let file1 =<< trim END + vim9script + import File2Function from './Xtest2.vim' + + def SourceAnotherFile() + source Xtest2.vim + enddef + + def CallAFunction() + SourceAnotherFile() + File2Function() + enddef + + def g:GlobalFunction() + CallAFunction() + enddef + + defcompile + END + call writefile(file1, 'Xtest1.vim') + + let file2 =<< trim END + vim9script + + def DoAThing(): number + let a = 100 * 2 + a += 3 + return a + enddef + + export def File2Function() + DoAThing() + enddef + + defcompile + File2Function() + END + call writefile(file2, 'Xtest2.vim') + + let buf = RunVimInTerminal('-S Xtest1.vim', {}) + + call RunDbgCmd(buf, + \ ':debug call GlobalFunction()', + \ ['cmd: call GlobalFunction()']) + + " FIXME: Vim9 lines are not debugged! + call RunDbgCmd(buf, 'step', ['line 1: source Xtest2.vim']) + + " But they do appear in the backtrace + call RunDbgCmd(buf, 'backtrace', [ + \ '\V>backtrace', + \ '\V 2 function GlobalFunction[1]', + \ '\V 1 \.\*_CallAFunction[1]', + \ '\V->0 \.\*_SourceAnotherFile', + \ '\Vline 1: source Xtest2.vim'], + \ #{match: 'pattern'}) + + + call RunDbgCmd(buf, 'step', ['line 1: vim9script']) + call RunDbgCmd(buf, 'step', ['line 3: def DoAThing(): number']) + call RunDbgCmd(buf, 'step', ['line 9: export def File2Function()']) + call RunDbgCmd(buf, 'step', ['line 9: def File2Function()']) + call RunDbgCmd(buf, 'step', ['line 13: defcompile']) + call RunDbgCmd(buf, 'step', ['line 14: File2Function()']) + call RunDbgCmd(buf, 'backtrace', [ + \ '\V>backtrace', + \ '\V 3 function GlobalFunction[1]', + \ '\V 2 \.\*_CallAFunction[1]', + \ '\V 1 \.\*_SourceAnotherFile[1]', + \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim', + \ '\Vline 14: File2Function()'], + \ #{match: 'pattern'}) + + " Don't step into compiled functions... + call RunDbgCmd(buf, 'step', ['line 15: End of sourced file']) + call RunDbgCmd(buf, 'backtrace', [ + \ '\V>backtrace', + \ '\V 3 function GlobalFunction[1]', + \ '\V 2 \.\*_CallAFunction[1]', + \ '\V 1 \.\*_SourceAnotherFile[1]', + \ '\V->0 script ' .. getcwd() .. '/Xtest2.vim', + \ '\Vline 15: End of sourced file'], + \ #{match: 'pattern'}) + + + call StopVimInTerminal(buf) + call delete('Xtest1.vim') + call delete('Xtest2.vim') +endfunc diff --git a/src/version.c b/src/version.c index 73ab8c3998eb71..c41d9321885133 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1304, /**/ 1303, /**/ From 622b3568fa1baf07671d31390815fb0a55a99891 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 27 Jul 2020 20:02:41 +0200 Subject: [PATCH 0018/1384] patch 8.2.1305: some tests are still old style Problem: Some tests are still old style. Solution: Convert tests 52 and 70 to new style. (Yegappan Lakshmanan, closes #6544) Fix error in FinishTesting(). --- src/Makefile | 5 +- src/testdir/Make_all.mak | 18 ++---- src/testdir/Make_amiga.mak | 6 -- src/testdir/Make_vms.mms | 27 +------- src/testdir/runtest.vim | 2 +- src/testdir/test52.in | 65 ------------------- src/testdir/test52.ok | 18 ------ src/testdir/test70.in | 63 ------------------ src/testdir/test70.ok | 6 -- src/testdir/test_mzscheme.vim | 62 ++++++++++++++++++ src/testdir/test_writefile.vim | 114 +++++++++++++++++++++++++++++++++ src/version.c | 2 + 12 files changed, 190 insertions(+), 198 deletions(-) delete mode 100644 src/testdir/test52.in delete mode 100644 src/testdir/test52.ok delete mode 100644 src/testdir/test70.in delete mode 100644 src/testdir/test70.ok create mode 100644 src/testdir/test_mzscheme.vim diff --git a/src/Makefile b/src/Makefile index 9ce61aa018c7c3..bbf80d32632b09 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2310,10 +2310,7 @@ test_libvterm: # Run individual OLD style test. # These do not depend on the executable, compile it when needed. -test1 \ - test42 test49 \ - test52 test59 \ - test70: +test1 test42 test49 test59: cd testdir; rm -f $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE) # Run individual NEW style test. diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index b2d9ac6f0f84d5..a25a480dd312db 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -8,25 +8,19 @@ NO_PLUGINS = --noplugin --not-a-term NO_INITS = -U NONE $(NO_PLUGINS) # The first script creates small.vim. -SCRIPTS_FIRST = \ - test1.out +SCRIPTS_FIRST = test1.out # Tests that run on all systems. -SCRIPTS_ALL = \ - test42.out \ - test70.out +SCRIPTS_ALL = test42.out # Tests that run on most systems, but not on Amiga. -SCRIPTS_MORE1 = \ - test52.out +SCRIPTS_MORE1 = # Tests that run on most systems, but not on Amiga and DOS/Windows. -SCRIPTS_MORE2 = \ - test49.out +SCRIPTS_MORE2 = test49.out # Tests that run on most systems, but not on VMS -SCRIPTS_MORE4 = \ - test59.out +SCRIPTS_MORE4 = test59.out # Tests specifically for MS-Windows. SCRIPTS_WIN32 = @@ -194,6 +188,7 @@ NEW_TESTS = \ test_modeless \ test_modeline \ test_move \ + test_mzscheme \ test_nested_function \ test_netbeans \ test_normal \ @@ -426,6 +421,7 @@ NEW_TESTS_RES = \ test_mksession.res \ test_modeless.res \ test_modeline.res \ + test_mzscheme.res \ test_nested_function.res \ test_netbeans.res \ test_normal.res \ diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak index df77e4dc4d7808..e6e55e3b4f41ce 100644 --- a/src/testdir/Make_amiga.mak +++ b/src/testdir/Make_amiga.mak @@ -9,12 +9,6 @@ default: nongui include Make_all.mak -# These tests don't work (yet): -# test2 "\\tmp" doesn't work -# test10 'errorformat' is different -# test52 only for Win32 -# test86, 87 no Python interface - SCRIPTS = $(SCRIPTS_ALL) $(SCRIPTS_MORE4) # Must run test1 first to create small.vim. diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms index 352e5539ebc1fe..af76f703ad46b7 100644 --- a/src/testdir/Make_vms.mms +++ b/src/testdir/Make_vms.mms @@ -81,40 +81,19 @@ SCRIPT = test1.out \ # test59: Failed/Hangs - VMS does not support spell files (file names # with too many dots). # -# test78: bug - Vim dies at :recover Xtest -# test89: bug - findfile() does not work on VMS (just in the current directory) -# test102: Just ODS-5 supports space and special chars in the filename. -# On ODS-2 tests fail. .IFDEF WANT_GUI -SCRIPT_GUI = test16.out GUI_OPTION = -g .ENDIF .IFDEF WANT_UNIX -SCRIPT_UNIX = test10.out test27.out test49.out -.ENDIF - -.IFDEF WANT_WIN -SCRIPT_WIN = test52.out +SCRIPT_UNIX = test49.out .ENDIF .IFDEF WANT_SPELL SCRIPT_SPELL = test59.out .ENDIF -.IFDEF WANT_MZSCH -SCRIPT_MZSCH = test70.out -.ENDIF - -.IFDEF HAVE_ODS5 -SCRIPT_ODS5 = test102.out -.ENDIF - -.IFDEF HAVE_GDIFF -SCRIPT_GDIFF = test47.out -.ENDIF - .in.out : -@ !clean up before doing the test -@ if "''F$SEARCH("test.out.*")'" .NES. "" then delete/noconfirm/nolog test.out.* @@ -135,8 +114,8 @@ SCRIPT_GDIFF = test47.out -@ if "''F$SEARCH("Xdotest.*")'" .NES. "" then delete/noconfirm/nolog Xdotest.*.* -@ if "''F$SEARCH("Xtest.*")'" .NES. "" then delete/noconfirm/nolog Xtest.*.* -all : clean nolog $(START_WITH) $(SCRIPT) $(SCRIPT_GUI) $(SCRIPT_UNIX) $(SCRIPT_WIN) $(SCRIPT_SPELL) $(SCRIPT_ODS5) \ - $(SCRIPT_GDIFF) $(SCRIPT_MZSCH) $(SCRIPT_LUA) nolog +all : clean nolog $(START_WITH) $(SCRIPT) $(SCRIPT_UNIX) $(SCRIPT_SPELL) \ + nolog -@ write sys$output " " -@ write sys$output "-----------------------------------------------" -@ write sys$output " All done" diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim index 6cc7202dc7037f..e42b0cabdbc362 100644 --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -447,7 +447,7 @@ for g:testfunc in sort(s:tests) " - it fails again with the same message " - it fails five times (with a different message) if len(v:errors) > 0 - \ $TEST_NO_RETRY == '' + \ && $TEST_NO_RETRY == '' \ && (index(s:flaky_tests, g:testfunc) >= 0 \ || g:test_is_flaky) while 1 diff --git a/src/testdir/test52.in b/src/testdir/test52.in deleted file mode 100644 index 206b65a1f92a3d..00000000000000 --- a/src/testdir/test52.in +++ /dev/null @@ -1,65 +0,0 @@ -Tests for reading and writing files with conversion for Win32. - -STARTTEST -:so mbyte.vim -:" make this a dummy test for non-Win32 systems -:if !has("win32") | e! test.ok | wq! test.out | endif -:" -:" write tests: -:" combine three values for 'encoding' with three values for 'fileencoding' -:" also write files for read tests -/^1 -:set encoding=utf-8 -:.w! ++enc=utf-8 test.out -:.w ++enc=cp1251 >>test.out -:.w ++enc=cp866 >>test.out -:.w! ++enc=utf-8 Xutf8 -/^2 -:set encoding=cp1251 -:.w ++enc=utf-8 >>test.out -:.w ++enc=cp1251 >>test.out -:.w ++enc=cp866 >>test.out -:.w! ++enc=cp1251 Xcp1251 -/^3 -:set encoding=cp866 -:.w ++enc=utf-8 >>test.out -:.w ++enc=cp1251 >>test.out -:.w ++enc=cp866 >>test.out -:.w! ++enc=cp866 Xcp866 -:" -:" read three 'fileencoding's with utf-8 'encoding' -:set encoding=utf-8 fencs=utf-8,cp1251 -:e Xutf8 -:.w ++enc=utf-8 >>test.out -:e Xcp1251 -:.w ++enc=utf-8 >>test.out -:set fencs=utf-8,cp866 -:e Xcp866 -:.w ++enc=utf-8 >>test.out -:" -:" read three 'fileencoding's with cp1251 'encoding' -:set encoding=utf-8 fencs=utf-8,cp1251 -:e Xutf8 -:.w ++enc=cp1251 >>test.out -:e Xcp1251 -:.w ++enc=cp1251 >>test.out -:set fencs=utf-8,cp866 -:e Xcp866 -:.w ++enc=cp1251 >>test.out -:" -:" read three 'fileencoding's with cp866 'encoding' -:set encoding=cp866 fencs=utf-8,cp1251 -:e Xutf8 -:.w ++enc=cp866 >>test.out -:e Xcp1251 -:.w ++enc=cp866 >>test.out -:set fencs=utf-8,cp866 -:e Xcp866 -:.w ++enc=cp866 >>test.out -:" -:qa! -ENDTEST - -1 utf-8 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 -2 cp1251 text: Vim version 6.2. : 1970 Jan 01 -3 cp866 text: Vim version 6.2. ᫥ : 1970 Jan 01 diff --git a/src/testdir/test52.ok b/src/testdir/test52.ok deleted file mode 100644 index 90b516508db070..00000000000000 --- a/src/testdir/test52.ok +++ /dev/null @@ -1,18 +0,0 @@ -1 utf-8 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 -1 utf-8 text: Vim version 6.2. : 1970 Jan 01 -1 utf-8 text: Vim version 6.2. ᫥ : 1970 Jan 01 -2 cp1251 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 -2 cp1251 text: Vim version 6.2. : 1970 Jan 01 -2 cp1251 text: Vim version 6.2. ᫥ : 1970 Jan 01 -3 cp866 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 -3 cp866 text: Vim version 6.2. : 1970 Jan 01 -3 cp866 text: Vim version 6.2. ᫥ : 1970 Jan 01 -1 utf-8 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 -2 cp1251 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 -3 cp866 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 -1 utf-8 text: Vim version 6.2. : 1970 Jan 01 -2 cp1251 text: Vim version 6.2. : 1970 Jan 01 -3 cp866 text: Vim version 6.2. : 1970 Jan 01 -1 utf-8 text: Vim version 6.2. ᫥ : 1970 Jan 01 -2 cp1251 text: Vim version 6.2. ᫥ : 1970 Jan 01 -3 cp866 text: Vim version 6.2. ᫥ : 1970 Jan 01 diff --git a/src/testdir/test70.in b/src/testdir/test70.in deleted file mode 100644 index 9ee59c3a282c2e..00000000000000 --- a/src/testdir/test70.in +++ /dev/null @@ -1,63 +0,0 @@ -Smoke test for MzScheme interface and mzeval() function - -STARTTEST -:so mzscheme.vim -:set nocompatible viminfo+=nviminfo -:function! MzRequire() -:redir => l:mzversion -:mz (version) -:redir END -:if strpart(l:mzversion, 1, 1) < "4" -:" MzScheme versions < 4.x: -:mz (require (prefix vim- vimext)) -:else -:" newer versions: -:mz (require (prefix-in vim- 'vimext)) -:mz (require r5rs) -:endif -:endfunction -:silent call MzRequire() -:mz (define l '("item0" "dictionary with list OK" "item2")) -:mz (define h (make-hash)) -:mz (hash-set! h "list" l) -/^1 -:" change buffer contents -:mz (vim-set-buff-line (vim-eval "line('.')") "1 changed line 1") -:" scalar test -:let tmp_string = mzeval('"string"') -:let tmp_1000 = '1000'->mzeval() -:if tmp_string . tmp_1000 == "string1000" -:let scalar_res = "OK" -:else -:let scalar_res = "FAILED" -:endif -:call append(search("^1"), "scalar test " . scalar_res) -:" dictionary containing a list -:let tmp = mzeval("h")["list"][1] -:/^2/put =tmp -:" circular list (at the same time test lists containing lists) -:mz (set-car! (cddr l) l) -:let l2 = mzeval("h")["list"] -:if l2[2] == l2 -:let res = "OK" -:else -:let res = "FAILED: " . l2[2] -:endif -:call setline(search("^3"), "circular test " . res) -:" funcrefs -:mz (define vim:max (vim-eval "function('max')")) -:mz (define m (vim:max '(1 100 8))) -:let m = mzeval('m') -:if m == 100 -:let fref_res = "OK" -:else -:let fref_res = "FAILED: " . m -:end -:call append(line('$'), 'funcrefs '. fref_res) -:?^1?,$w! test.out -:qa! -ENDTEST - -1 line 1 -2 line 2 -3 line 3 diff --git a/src/testdir/test70.ok b/src/testdir/test70.ok deleted file mode 100644 index 9c82a86f2d7472..00000000000000 --- a/src/testdir/test70.ok +++ /dev/null @@ -1,6 +0,0 @@ -1 changed line 1 -scalar test OK -2 line 2 -dictionary with list OK -circular test OK -funcrefs OK diff --git a/src/testdir/test_mzscheme.vim b/src/testdir/test_mzscheme.vim new file mode 100644 index 00000000000000..0bc98421d305c4 --- /dev/null +++ b/src/testdir/test_mzscheme.vim @@ -0,0 +1,62 @@ +" Test for MzScheme interface and mzeval() function + +source check.vim +CheckFeature mzscheme + +func MzRequire() + redir => l:mzversion + mz (version) + redir END + if strpart(l:mzversion, 1, 1) < "4" + " MzScheme versions < 4.x: + mz (require (prefix vim- vimext)) + else + " newer versions: + mz (require (prefix-in vim- 'vimext)) + mz (require r5rs) + endif +endfunc + +func Test_mzscheme() + new + let lines =<< trim END + 1 line 1 + 2 line 2 + 3 line 3 + END + call setline(1, lines) + + call MzRequire() + mz (define l '("item0" "dictionary with list OK" "item2")) + mz (define h (make-hash)) + mz (hash-set! h "list" l) + + call cursor(1, 1) + " change buffer contents + mz (vim-set-buff-line (vim-eval "line('.')") "1 changed line 1") + call assert_equal('1 changed line 1', getline(1)) + + " scalar test + let tmp_string = mzeval('"string"') + let tmp_1000 = '1000'->mzeval() + call assert_equal('string1000', tmp_string .. tmp_1000) + + " dictionary containing a list + call assert_equal('dictionary with list OK', mzeval("h")["list"][1]) + + call cursor(2, 1) + " circular list (at the same time test lists containing lists) + mz (set-car! (cddr l) l) + let l2 = mzeval("h")["list"] + call assert_equal(l2[2], l2) + + " funcrefs + mz (define vim:max (vim-eval "function('max')")) + mz (define m (vim:max '(1 100 8))) + let m = mzeval('m') + call assert_equal(100, m) + + close! +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_writefile.vim b/src/testdir/test_writefile.vim index 5c9e4b12b4de0c..d92d6aedbe5934 100644 --- a/src/testdir/test_writefile.vim +++ b/src/testdir/test_writefile.vim @@ -442,4 +442,118 @@ func Test_write_invalid_encoding() close! endfunc +" Tests for reading and writing files with conversion for Win32. +func Test_write_file_encoding() + CheckMSWindows + let save_encoding = &encoding + let save_fileencodings = &fileencodings + set encoding& fileencodings& + let text =<< trim END + 1 utf-8 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 + 2 cp1251 text: Vim version 6.2. : 1970 Jan 01 + 3 cp866 text: Vim version 6.2. ᫥ : 1970 Jan 01 + END + call writefile(text, 'Xfile') + edit Xfile + + " write tests: + " combine three values for 'encoding' with three values for 'fileencoding' + " also write files for read tests + call cursor(1, 1) + set encoding=utf-8 + .w! ++enc=utf-8 Xtest + .w ++enc=cp1251 >> Xtest + .w ++enc=cp866 >> Xtest + .w! ++enc=utf-8 Xutf8 + let expected =<< trim END + 1 utf-8 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 + 1 utf-8 text: Vim version 6.2. : 1970 Jan 01 + 1 utf-8 text: Vim version 6.2. ᫥ : 1970 Jan 01 + END + call assert_equal(expected, readfile('Xtest')) + + call cursor(2, 1) + set encoding=cp1251 + .w! ++enc=utf-8 Xtest + .w ++enc=cp1251 >> Xtest + .w ++enc=cp866 >> Xtest + .w! ++enc=cp1251 Xcp1251 + let expected =<< trim END + 2 cp1251 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 + 2 cp1251 text: Vim version 6.2. : 1970 Jan 01 + 2 cp1251 text: Vim version 6.2. ᫥ : 1970 Jan 01 + END + call assert_equal(expected, readfile('Xtest')) + + call cursor(3, 1) + set encoding=cp866 + .w! ++enc=utf-8 Xtest + .w ++enc=cp1251 >> Xtest + .w ++enc=cp866 >> Xtest + .w! ++enc=cp866 Xcp866 + let expected =<< trim END + 3 cp866 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 + 3 cp866 text: Vim version 6.2. : 1970 Jan 01 + 3 cp866 text: Vim version 6.2. ᫥ : 1970 Jan 01 + END + call assert_equal(expected, readfile('Xtest')) + + " read three 'fileencoding's with utf-8 'encoding' + set encoding=utf-8 fencs=utf-8,cp1251 + e Xutf8 + .w! ++enc=utf-8 Xtest + e Xcp1251 + .w ++enc=utf-8 >> Xtest + set fencs=utf-8,cp866 + e Xcp866 + .w ++enc=utf-8 >> Xtest + let expected =<< trim END + 1 utf-8 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 + 2 cp1251 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 + 3 cp866 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01 + END + call assert_equal(expected, readfile('Xtest')) + + " read three 'fileencoding's with cp1251 'encoding' + set encoding=utf-8 fencs=utf-8,cp1251 + e Xutf8 + .w! ++enc=cp1251 Xtest + e Xcp1251 + .w ++enc=cp1251 >> Xtest + set fencs=utf-8,cp866 + e Xcp866 + .w ++enc=cp1251 >> Xtest + let expected =<< trim END + 1 utf-8 text: Vim version 6.2. : 1970 Jan 01 + 2 cp1251 text: Vim version 6.2. : 1970 Jan 01 + 3 cp866 text: Vim version 6.2. : 1970 Jan 01 + END + call assert_equal(expected, readfile('Xtest')) + + " read three 'fileencoding's with cp866 'encoding' + set encoding=cp866 fencs=utf-8,cp1251 + e Xutf8 + .w! ++enc=cp866 Xtest + e Xcp1251 + .w ++enc=cp866 >> Xtest + set fencs=utf-8,cp866 + e Xcp866 + .w ++enc=cp866 >> Xtest + let expected =<< trim END + 1 utf-8 text: Vim version 6.2. ᫥ : 1970 Jan 01 + 2 cp1251 text: Vim version 6.2. ᫥ : 1970 Jan 01 + 3 cp866 text: Vim version 6.2. ᫥ : 1970 Jan 01 + END + call assert_equal(expected, readfile('Xtest')) + + call delete('Xfile') + call delete('Xtest') + call delete('Xutf8') + call delete('Xcp1251') + call delete('Xcp866') + let &encoding = save_encoding + let &fileencodings = save_fileencodings + %bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index c41d9321885133..ec702330b232a0 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1305, /**/ 1304, /**/ From b13ab99908097d54e21ab5adad22f4ad2a8ec688 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 27 Jul 2020 21:43:28 +0200 Subject: [PATCH 0019/1384] patch 8.2.1306: checking for first character of dict key is inconsistent Problem: Checking for first character of dict key is inconsistent. Solution: Add eval_isdictc(). (closes #6546) --- src/eval.c | 21 +++++++++++++++------ src/proto/eval.pro | 1 + src/testdir/test_let.vim | 2 +- src/testdir/test_listdict.vim | 7 +++++++ src/testdir/test_vim9_expr.vim | 13 ++++++++++++- src/version.c | 2 ++ src/vim9compile.c | 4 ++-- 7 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/eval.c b/src/eval.c index 6d3d19ee83192c..81913c7a353012 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3464,7 +3464,7 @@ eval_index( * dict.name */ key = *arg + 1; - for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len) + for (len = 0; eval_isdictc(key[len]); ++len) ; if (len == 0) return FAIL; @@ -4997,7 +4997,7 @@ find_name_end( && (eval_isnamec(*p) || (*p == '{' && !vim9script) || ((flags & FNE_INCL_BR) && (*p == '[' - || (*p == '.' && eval_isnamec1(p[1])))) + || (*p == '.' && eval_isdictc(p[1])))) || mb_nest != 0 || br_nest != 0); MB_PTR_ADV(p)) { @@ -5128,7 +5128,7 @@ make_expanded_name( int eval_isnamec(int c) { - return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR); + return ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR; } /* @@ -5138,7 +5138,17 @@ eval_isnamec(int c) int eval_isnamec1(int c) { - return (ASCII_ISALPHA(c) || c == '_'); + return ASCII_ISALPHA(c) || c == '_'; +} + +/* + * Return TRUE if character "c" can be used as the first character of a + * dictionary key. + */ + int +eval_isdictc(int c) +{ + return ASCII_ISALNUM(c) || c == '_'; } /* @@ -5171,8 +5181,7 @@ handle_subscript( // the next line then consume the line break. p = eval_next_non_blank(*arg, evalarg, &getnext); if (getnext - && ((rettv->v_type == VAR_DICT && *p == '.' - && ASCII_ISALPHA(p[1])) + && ((rettv->v_type == VAR_DICT && *p == '.' && eval_isdictc(p[1])) || (*p == '-' && p[1] == '>' && (p[2] == '{' || ASCII_ISALPHA(p[2]))))) { diff --git a/src/proto/eval.pro b/src/proto/eval.pro index 5d04e01acbf855..a528d3e4356a89 100644 --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -58,6 +58,7 @@ int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose); char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end, int flags); int eval_isnamec(int c); int eval_isnamec1(int c); +int eval_isdictc(int c); int handle_subscript(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int verbose); int item_copy(typval_T *from, typval_T *to, int deep, int copyID); void echo_one(typval_T *rettv, int with_space, int *atstart, int *needclr); diff --git a/src/testdir/test_let.vim b/src/testdir/test_let.vim index 9a399e8f38b64b..017b2a4a478c33 100644 --- a/src/testdir/test_let.vim +++ b/src/testdir/test_let.vim @@ -293,7 +293,7 @@ func Test_let_errors() let s = "var" let var = 1 call assert_fails('let var += [1,2]', 'E734:') - call assert_fails('let {s}.1 = 2', 'E15:') + call assert_fails('let {s}.1 = 2', 'E18:') call assert_fails('let a[1] = 5', 'E121:') let l = [[1,2]] call assert_fails('let l[:][0] = [5]', 'E708:') diff --git a/src/testdir/test_listdict.vim b/src/testdir/test_listdict.vim index b064846993ad60..beeda2f5bb598b 100644 --- a/src/testdir/test_listdict.vim +++ b/src/testdir/test_listdict.vim @@ -282,6 +282,13 @@ func Test_dict_func() call assert_equal('xxx3', Fn('xxx')) endfunc +func Test_dict_assign() + let d = {} + let d.1 = 1 + let d._ = 2 + call assert_equal({'1': 1, '_': 2}, d) +endfunc + " Function in script-local List or Dict func Test_script_local_dict_func() let g:dict = {} diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index d7072f34b9fa26..5b46c32f96e201 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1310,6 +1310,11 @@ def Test_expr_member() ]) assert_equal(1, d .one) + d = {'1': 1, '_': 2} + assert_equal(1, d + .1) + assert_equal(2, d + ._) # getting the one member should clear the dict after getting the item assert_equal('one', #{one: 'one'}.one) @@ -1330,10 +1335,16 @@ def Test_expr_member_vim9script() vim9script let d = #{one: 'one', - two: 'two'} + two: 'two', + 1: 1, + _: 2} assert_equal('one', d.one) assert_equal('one', d .one) + assert_equal(1, d + .1) + assert_equal(2, d + ._) assert_equal('one', d[ 'one' ]) diff --git a/src/version.c b/src/version.c index ec702330b232a0..a87cc89d37ff4f 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1306, /**/ 1305, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 8efb1f672fd8e2..1ed3211463a097 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3758,7 +3758,7 @@ compile_subscript( if (next != NULL && ((next[0] == '-' && next[1] == '>' && (next[2] == '{' || ASCII_ISALPHA(next[2]))) - || (next[0] == '.' && ASCII_ISALPHA(next[1])))) + || (next[0] == '.' && eval_isdictc(next[1])))) { next = next_line_from_context(cctx, TRUE); if (next == NULL) @@ -3922,7 +3922,7 @@ compile_subscript( return FAIL; // dictionary member: dict.name p = *arg; - if (eval_isnamec1(*p)) + if (eval_isdictc(*p)) while (eval_isnamec(*p)) MB_PTR_ADV(p); if (p == *arg) From 0aac67a4314d72a29d3fbee91b6f0ba89e950462 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 27 Jul 2020 22:40:37 +0200 Subject: [PATCH 0020/1384] patch 8.2.1307: popup window width does not include number of sign columns Problem: popup window width does not include number, fold of sign column width. Solution: Take number, fold and sign column with into account. --- src/popupwin.c | 27 ++++++++++++++++----- src/testdir/dumps/Test_popupwin_sign_2.dump | 10 ++++++++ src/testdir/test_popupwin.vim | 10 ++++++++ src/version.c | 2 ++ 4 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 src/testdir/dumps/Test_popupwin_sign_2.dump diff --git a/src/popupwin.c b/src/popupwin.c index d2b7f22f0b91a1..3bd8e731426a8e 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -1111,6 +1111,7 @@ popup_adjust_position(win_T *wp) int wrapped = 0; int maxwidth; int used_maxwidth = FALSE; + int margin_width = 0; int maxspace; int center_vert = FALSE; int center_hor = FALSE; @@ -1249,6 +1250,19 @@ popup_adjust_position(win_T *wp) allow_adjust_left = FALSE; maxwidth = wp->w_maxwidth; } + + if (wp->w_p_nu || wp->w_p_rnu) + margin_width = number_width(wp) + 1; +#ifdef FEAT_FOLDING + margin_width += wp->w_p_fdc; +#endif +#ifdef FEAT_SIGNS + if (signcolumn_on(wp)) + margin_width += 2; +#endif + if (margin_width >= maxwidth) + margin_width = maxwidth - 1; + minwidth = wp->w_minwidth; minheight = wp->w_minheight; #ifdef FEAT_TERMINAL @@ -1289,6 +1303,7 @@ popup_adjust_position(win_T *wp) // Count Tabs for what they are worth and compute the length based on // the maximum width (matters when 'showbreak' is set). + // "margin_width" is added to "len" where it matters. if (wp->w_width < maxwidth) wp->w_width = maxwidth; len = win_linetabsize(wp, ml_get_buf(wp->w_buffer, lnum, FALSE), @@ -1297,21 +1312,21 @@ popup_adjust_position(win_T *wp) if (wp->w_p_wrap) { - while (len > maxwidth) + while (len + margin_width > maxwidth) { ++wrapped; - len -= maxwidth; + len -= maxwidth - margin_width; wp->w_width = maxwidth; used_maxwidth = TRUE; } } - else if (len > maxwidth + else if (len + margin_width > maxwidth && allow_adjust_left && (wp->w_popup_pos == POPPOS_TOPLEFT || wp->w_popup_pos == POPPOS_BOTLEFT)) { // adjust leftwise to fit text on screen - int shift_by = len - maxwidth; + int shift_by = len + margin_width - maxwidth; if (shift_by > wp->w_wincol) { @@ -1325,9 +1340,9 @@ popup_adjust_position(win_T *wp) maxwidth += shift_by; wp->w_width = maxwidth; } - if (wp->w_width < len) + if (wp->w_width < len + margin_width) { - wp->w_width = len; + wp->w_width = len + margin_width; if (wp->w_maxwidth > 0 && wp->w_width > wp->w_maxwidth) wp->w_width = wp->w_maxwidth; } diff --git a/src/testdir/dumps/Test_popupwin_sign_2.dump b/src/testdir/dumps/Test_popupwin_sign_2.dump new file mode 100644 index 00000000000000..ddccde1e392ee1 --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_sign_2.dump @@ -0,0 +1,10 @@ +|>+0#e000002#ffffff0@1>0+0#ffffff16#ff404010| @71 +| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0| @71 +| +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @71 +| +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @71 +| +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @13| +0#0000e05#a8a8a8255@1|#+0#ffffff16#ff404010|!| +0#af5f00255#ffd7ff255@1|1| |a+0#0000001#ffff4012| |l|o|n|g|e|r| |l|i|n|e| |t|o| |c|h|e|c|k| |t|h|e| |w|i|d|t|h| +0#0000000#ffffff0@17 +| +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @71 +| +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @71 +| +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @71 +| +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @71 +|:|c|a|l@1| |S|e|t|O|p|t|i|o|n|s|(|)| @38|1|,|1| @10|T|o|p| diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index beb6870b6de43b..00b956a9e0dccb 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -3375,12 +3375,22 @@ func Test_popupwin_sign() call sign_place(3, 'PopUpSelected', 'Other', winbufnr, {'lnum': 1}) " add sign to popup buffer, does not show call sign_place(4, 'Selected', 'Current', winbufnr, {'lnum': 2}) + + func SetOptions() + call setwinvar(g:winid, '&number', 1) + call setwinvar(g:winid, '&foldcolumn', 2) + call popup_settext(g:winid, 'a longer line to check the width') + endfunc END call writefile(lines, 'XtestPopupSign') let buf = RunVimInTerminal('-S XtestPopupSign', #{rows: 10}) call VerifyScreenDump(buf, 'Test_popupwin_sign_1', {}) + " set more options to check the width is adjusted + call term_sendkeys(buf, ":call SetOptions()\") + call VerifyScreenDump(buf, 'Test_popupwin_sign_2', {}) + call StopVimInTerminal(buf) call delete('XtestPopupSign') endfunc diff --git a/src/version.c b/src/version.c index a87cc89d37ff4f..78aafb8e3ee234 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1307, /**/ 1306, /**/ From ae616494d77e9930da703d65d12ac0abf6dc425f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 28 Jul 2020 20:07:27 +0200 Subject: [PATCH 0021/1384] patch 8.2.1308: Vim9: accidentally using "x" causes Vim to exit Problem: Vim9: accidentally using "x" causes Vim to exit. Solution: Disallow using ":x" or "xit" in Vim9 script. (closes #6399) --- runtime/doc/vim9.txt | 52 +++++++++++++++++--------------- src/ex_cmds.c | 6 ++++ src/ex_docmd.c | 2 ++ src/proto/vim9script.pro | 1 + src/testdir/test_vim9_script.vim | 15 +++++++++ src/version.c | 2 ++ src/vim9compile.c | 7 +++++ src/vim9script.c | 21 +++++++++++-- 8 files changed, 79 insertions(+), 27 deletions(-) diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 2ba2275274e176..7b2597dc6e445e 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -71,16 +71,17 @@ comments start with #. > The reason is that a double quote can also be the start of a string. In many places, especially halfway an expression with a line break, it's hard to tell -what the meaning is. To avoid confusion only # comments are recognized. -This is the same as in shell scripts and Python programs. +what the meaning is, since both a string and a comment can be followed by +arbitrary text. To avoid confusion only # comments are recognized. This is +the same as in shell scripts and Python programs. In Vi # is a command to list text with numbers. In Vim9 script you can use `:number` for that. > - 101number + 101 number To improve readability there must be a space between a command and the # that starts a comment. Note that #{ is the start of a dictionary, therefore -it cannot start a comment. +it does not start a comment. Vim9 functions ~ @@ -93,7 +94,7 @@ The syntax is strict, to enforce code that is easy to read and understand. Compilation is done when the function is first called, or when the `:defcompile` command is encountered in the script where the function was -defined. +defined. `:disassemble` also compiles the function. `:def` has no options like `:function` does: "range", "abort", "dict" or "closure". A `:def` function always aborts on an error, does not get a range @@ -104,7 +105,7 @@ be used, type checking will then be done at runtime, like with legacy functions. Arguments are accessed by name, without "a:". There is no "a:" dictionary or -"a:000" list. +"a:000" list. Just like any other language. Variable arguments are defined as the last argument, with a name and have a list type, similar to Typescript. For example, a list of numbers: > @@ -216,29 +217,29 @@ Functions can be called without `:call`: > Using `:call` is still possible, but this is discouraged. A method call without `eval` is possible, so long as the start is an -identifier or can't be an Ex command. It does NOT work for string constants: > - myList->add(123) # works - g:myList->add(123) # works - [1, 2, 3]->Process() # works - #{a: 1, b: 2}->Process() # works - {'a': 1, 'b': 2}->Process() # works - "foobar"->Process() # does NOT work - ("foobar")->Process() # works - 'foobar'->Process() # does NOT work - ('foobar')->Process() # works - -In case there is ambiguity between a function name and an Ex command, use ":" -to make clear you want to use the Ex command. For example, there is both the -`:substitute` command and the `substitute()` function. When the line starts -with `substitute(` this will use the function, prepend a colon to use the -command instead: > +identifier or can't be an Ex command. Examples: > + myList->add(123) + g:myList->add(123) + [1, 2, 3]->Process() + #{a: 1, b: 2}->Process() + {'a': 1, 'b': 2}->Process() + "foobar"->Process() + ("foobar")->Process() + 'foobar'->Process() + ('foobar')->Process() + +In rare case there is ambiguity between a function name and an Ex command, use +":" to make clear you want to use the Ex command. For example, there is both +the `:substitute` command and the `substitute()` function. When the line +starts with `substitute(` this will use the function. Prepend a colon to use +the command instead: > :substitute(pattern (replacement ( Note that while variables need to be defined before they can be used, functions can be called before being defined. This is required to be able have cyclic dependencies between functions. It is slightly less efficient, since the function has to be looked up by name. And a typo in the function -name will only be found when the call is executed. +name will only be found when the function is called. Omitting function() ~ @@ -347,9 +348,10 @@ No curly braces expansion ~ |curly-braces-names| cannot be used. -No :append, :change or :insert ~ +No :xit, :append, :change or :insert ~ -These commands are too quickly confused with local variable names. +These commands are too easily confused with local variable names. Instead of +`:x` or `:xit` you can use `:exit`. Comparators ~ diff --git a/src/ex_cmds.c b/src/ex_cmds.c index e8e38aa97a300b..895912f4197ec5 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -3176,6 +3176,9 @@ ex_append(exarg_T *eap) int vcol; int empty = (curbuf->b_ml.ml_flags & ML_EMPTY); + if (not_in_vim9(eap) == FAIL) + return; + // the ! flag toggles autoindent if (eap->forceit) curbuf->b_p_ai = !curbuf->b_p_ai; @@ -3317,6 +3320,9 @@ ex_change(exarg_T *eap) { linenr_T lnum; + if (not_in_vim9(eap) == FAIL) + return; + if (eap->line2 >= eap->line1 && u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) return; diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 987e92dea9c85d..fe654104daf6cf 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -5686,6 +5686,8 @@ ex_stop(exarg_T *eap) static void ex_exit(exarg_T *eap) { + if (not_in_vim9(eap) == FAIL) + return; #ifdef FEAT_CMDWIN if (cmdwin_type != 0) { diff --git a/src/proto/vim9script.pro b/src/proto/vim9script.pro index 6a32abdcacbc05..f8b12ee5de73d2 100644 --- a/src/proto/vim9script.pro +++ b/src/proto/vim9script.pro @@ -1,6 +1,7 @@ /* vim9script.c */ int in_vim9script(void); void ex_vim9script(exarg_T *eap); +int not_in_vim9(exarg_T *eap); void ex_export(exarg_T *eap); void free_imports(int sid); void ex_import(exarg_T *eap); diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index ac76e8d5bce047..379245f397f229 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1515,6 +1515,21 @@ def Test_fixed_size_list() assert_equal([2, 99, 3, 4, 5], l) enddef +def Test_no_insert_xit() + call CheckDefExecFailure(['x = 1'], 'E1100:') + call CheckDefExecFailure(['a = 1'], 'E1100:') + call CheckDefExecFailure(['i = 1'], 'E1100:') + call CheckDefExecFailure(['c = 1'], 'E1100:') + + CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:') + CheckScriptFailure(['vim9script', 'a = 1'], 'E488:') + CheckScriptFailure(['vim9script', 'a'], 'E1100:') + CheckScriptFailure(['vim9script', 'i = 1'], 'E488:') + CheckScriptFailure(['vim9script', 'i'], 'E1100:') + CheckScriptFailure(['vim9script', 'c = 1'], 'E488:') + CheckScriptFailure(['vim9script', 'c'], 'E1100:') +enddef + def IfElse(what: number): string let res = '' if what == 1 diff --git a/src/version.c b/src/version.c index 78aafb8e3ee234..710c570604c510 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1308, /**/ 1307, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 1ed3211463a097..cbb9231d8cf004 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -7409,6 +7409,13 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx) // TODO: other commands with an expression argument + case CMD_append: + case CMD_change: + case CMD_insert: + case CMD_xit: + not_in_vim9(&ea); + goto erret; + case CMD_SIZE: semsg(_("E476: Invalid command: %s"), ea.cmd); goto erret; diff --git a/src/vim9script.c b/src/vim9script.c index 784283ef9762e4..7d783ea9342efb 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -58,13 +58,30 @@ ex_vim9script(exarg_T *eap) } } +/* + * When in Vim9 script give an error and return FAIL. + */ + int +not_in_vim9(exarg_T *eap) +{ + switch (eap->cmdidx) + { + case CMD_insert: + case CMD_append: + case CMD_change: + case CMD_xit: + semsg(_("E1100: Missing :let: %s"), eap->cmd); + return FAIL; + default: break; + } + return OK; +} + /* * ":export let Name: type" * ":export const Name: type" * ":export def Name(..." * ":export class Name ..." - * - * ":export {Name, ...}" */ void ex_export(exarg_T *eap) From 461f21242a8fc7f2fe9d1c723741eeda45f0ac72 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 28 Jul 2020 20:25:47 +0200 Subject: [PATCH 0022/1384] patch 8.2.1309: build failure with tiny version Problem: Build failure with tiny version. Solution: Add #ifdef. --- src/ex_cmds.c | 6 ++++-- src/ex_docmd.c | 2 ++ src/version.c | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 895912f4197ec5..88161fa2c44598 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -3176,9 +3176,10 @@ ex_append(exarg_T *eap) int vcol; int empty = (curbuf->b_ml.ml_flags & ML_EMPTY); +#ifdef FEAT_EVAL if (not_in_vim9(eap) == FAIL) return; - +#endif // the ! flag toggles autoindent if (eap->forceit) curbuf->b_p_ai = !curbuf->b_p_ai; @@ -3320,9 +3321,10 @@ ex_change(exarg_T *eap) { linenr_T lnum; +#ifdef FEAT_EVAL if (not_in_vim9(eap) == FAIL) return; - +#endif if (eap->line2 >= eap->line1 && u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) return; diff --git a/src/ex_docmd.c b/src/ex_docmd.c index fe654104daf6cf..6a2e91c9fea7ca 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -5686,8 +5686,10 @@ ex_stop(exarg_T *eap) static void ex_exit(exarg_T *eap) { +#ifdef FEAT_EVAL if (not_in_vim9(eap) == FAIL) return; +#endif #ifdef FEAT_CMDWIN if (cmdwin_type != 0) { diff --git a/src/version.c b/src/version.c index 710c570604c510..fb641589bf759f 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1309, /**/ 1308, /**/ From bd7f7c123db58dd7f50f4d1391577686d2f1bcc6 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 28 Jul 2020 21:03:37 +0200 Subject: [PATCH 0023/1384] patch 8.2.1310: configure with Xcode 12 fails to check for tgetent Problem: Configure with Xcode 12 fails to check for tgetent. Solution: Declare tgetent(). (Ozaki Kiichi, closes #6558) --- src/auto/configure | 2 +- src/configure.ac | 2 +- src/version.c | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/auto/configure b/src/auto/configure index 9c9a719d81af94..41b29c2623fe84 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -12106,7 +12106,7 @@ if test "x$olibs" = "x$LIBS"; then $as_echo_n "checking for tgetent()... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - +int tgetent(char *, const char *); int main () { diff --git a/src/configure.ac b/src/configure.ac index 19ce4c7a5f3386..598d73c8dfc496 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -3510,7 +3510,7 @@ fi if test "x$olibs" = "x$LIBS"; then AC_MSG_CHECKING([for tgetent()]) - AC_TRY_LINK([], + AC_TRY_LINK([int tgetent(char *, const char *);], [char s[10000]; int res = tgetent(s, "thisterminaldoesnotexist");], AC_MSG_RESULT(yes), AC_MSG_ERROR([NOT FOUND! diff --git a/src/version.c b/src/version.c index fb641589bf759f..d8dfba87b06227 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1310, /**/ 1309, /**/ From 68e30449a2954557d6542fdc2ccea32d4f8ddf9d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 28 Jul 2020 21:15:07 +0200 Subject: [PATCH 0024/1384] patch 8.2.1311: test failures with legacy Vim script Problem: Test failures with legacy Vim script. Solution: Actually check for Vim9 script. --- src/version.c | 2 ++ src/vim9script.c | 21 +++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/version.c b/src/version.c index d8dfba87b06227..93da0a8ab71ac6 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1311, /**/ 1310, /**/ diff --git a/src/vim9script.c b/src/vim9script.c index 7d783ea9342efb..2e94b8e2955396 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -64,16 +64,17 @@ ex_vim9script(exarg_T *eap) int not_in_vim9(exarg_T *eap) { - switch (eap->cmdidx) - { - case CMD_insert: - case CMD_append: - case CMD_change: - case CMD_xit: - semsg(_("E1100: Missing :let: %s"), eap->cmd); - return FAIL; - default: break; - } + if (in_vim9script()) + switch (eap->cmdidx) + { + case CMD_insert: + case CMD_append: + case CMD_change: + case CMD_xit: + semsg(_("E1100: Missing :let: %s"), eap->cmd); + return FAIL; + default: break; + } return OK; } From 066b12e36c32a87725303c0f71e968eb3f9a9f32 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 28 Jul 2020 21:40:27 +0200 Subject: [PATCH 0025/1384] patch 8.2.1312: MS-Windows: terminal test may fail if dir.exe exists Problem: MS-Windows: terminal test may fail if dir.exe exists. Solution: Use dir.com. (Ken Takata, closes #6557) --- src/testdir/test_terminal3.vim | 9 ++++++--- src/version.c | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/testdir/test_terminal3.vim b/src/testdir/test_terminal3.vim index 76e8a105433850..3343dafd8617bb 100644 --- a/src/testdir/test_terminal3.vim +++ b/src/testdir/test_terminal3.vim @@ -43,15 +43,18 @@ func Test_terminal_shell_option() bwipe! elseif has('win32') " dir is a shell builtin command, should fail without a shell. + " However, if dir.exe (which might be provided by Cygwin/MSYS2) exists in + " the %PATH%, "term dir" succeeds unintentionally. Use dir.com instead. try - term dir /b runtest.vim - call WaitForAssert({-> assert_match('job failed\|cannot access .*: No such file or directory', term_getline(bufnr(), 1))}) + term dir.com /b runtest.vim + call WaitForAssert({-> assert_match('job failed', term_getline(bufnr(), 1))}) catch /CreateProcess/ " ignore endtry bwipe! - term ++shell dir /b runtest.vim + " This should execute the dir builtin command even with ".com". + term ++shell dir.com /b runtest.vim call WaitForAssert({-> assert_match('runtest.vim', term_getline(bufnr(), 1))}) bwipe! endif diff --git a/src/version.c b/src/version.c index 93da0a8ab71ac6..26bd7ac6518a8b 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1312, /**/ 1311, /**/ From b5ed266037dea49024e00c4e1f9c89f3a9ebaa60 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 28 Jul 2020 22:38:37 +0200 Subject: [PATCH 0026/1384] patch 8.2.1313: Vim9 script: cannot assign to environment variable Problem: Vim9 script: cannot assign to environment variable. Solution: Recognize environment variable assignment. (closes #6548) Also options and registers. --- src/ex_docmd.c | 148 +++++++++++++++++-------------- src/testdir/test_vim9_script.vim | 25 ++++++ src/version.c | 2 + 3 files changed, 108 insertions(+), 67 deletions(-) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 6a2e91c9fea7ca..536850edc9f65d 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -1710,7 +1710,7 @@ do_one_cmd( char_u *cmd; int starts_with_colon = FALSE; #ifdef FEAT_EVAL - int starts_with_quote; + int may_have_range; int vim9script = in_vim9script(); #endif @@ -1773,8 +1773,9 @@ do_one_cmd( */ cmd = ea.cmd; #ifdef FEAT_EVAL - starts_with_quote = vim9script && !starts_with_colon && *ea.cmd == '\''; - if (!starts_with_quote) + // In Vim9 script a colon is required before the range. + may_have_range = !vim9script || starts_with_colon; + if (may_have_range) #endif ea.cmd = skip_range(ea.cmd, NULL); if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL) @@ -1783,7 +1784,10 @@ do_one_cmd( #ifdef FEAT_EVAL if (vim9script && !starts_with_colon) { - if (ea.cmd > cmd) + if (ea.cmd == cmd + 1 && *cmd == '$') + // should be "$VAR = val" + --ea.cmd; + else if (ea.cmd > cmd) { emsg(_(e_colon_required)); goto doend; @@ -1876,7 +1880,7 @@ do_one_cmd( ea.cmd = cmd; #ifdef FEAT_EVAL - if (!starts_with_quote) + if (may_have_range) #endif if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL) goto doend; @@ -3267,80 +3271,90 @@ find_ex_command( * "lvar = value", "lvar(arg)", "[1, 2 3]->Func()" */ p = eap->cmd; - if (lookup != NULL && (vim_strchr((char_u *)"{('[", *p) != NULL - || ((p = to_name_const_end(eap->cmd)) > eap->cmd - && *p != NUL))) + if (lookup != NULL) { - int oplen; - int heredoc; + // Skip over first char for "&opt = val", "$ENV = val" and "@r = val". + char_u *pskip = (*eap->cmd == '&' || *eap->cmd == '$' + || *eap->cmd == '@') ? eap->cmd + 1 : eap->cmd; - if ( - // "(..." is an expression. - // "funcname(" is always a function call. - *p == '(' - || (p == eap->cmd - ? ( - // "{..." is an dict expression. - *eap->cmd == '{' - // "'string'->func()" is an expression. - || *eap->cmd == '\'' - // "g:varname" is an expression. - || eap->cmd[1] == ':' - ) - : ( - // "varname[]" is an expression. - *p == '[' - // "varname->func()" is an expression. - || (*p == '-' && p[1] == '>') - // "varname.expr" is an expression. - || (*p == '.' && ASCII_ISALPHA(p[1])) - ))) - { - eap->cmdidx = CMD_eval; - return eap->cmd; - } - - // "[...]->Method()" is a list expression, but "[a, b] = Func()" is - // an assignment. - // If there is no line break inside the "[...]" then "p" is advanced to - // after the "]" by to_name_const_end(): check if a "=" follows. - // If "[...]" has a line break "p" still points at the "[" and it can't - // be an assignment. - if (*eap->cmd == '[') - { - p = to_name_const_end(eap->cmd); - if (p == eap->cmd || *skipwhite(p) != '=') + if (vim_strchr((char_u *)"{('[", *p) != NULL + || ((p = to_name_const_end(pskip)) > eap->cmd && *p != NUL)) + { + int oplen; + int heredoc; + + if ( + // "(..." is an expression. + // "funcname(" is always a function call. + *p == '(' + || (p == eap->cmd + ? ( + // "{..." is an dict expression. + *eap->cmd == '{' + // "'string'->func()" is an expression. + || *eap->cmd == '\'' + // "g:varname" is an expression. + || eap->cmd[1] == ':' + ) + : ( + // "varname[]" is an expression. + *p == '[' + // "varname->func()" is an expression. + || (*p == '-' && p[1] == '>') + // "varname.expr" is an expression. + || (*p == '.' && ASCII_ISALPHA(p[1])) + ))) { eap->cmdidx = CMD_eval; return eap->cmd; } - if (p > eap->cmd && *skipwhite(p) == '=') + + // "[...]->Method()" is a list expression, but "[a, b] = Func()" is + // an assignment. + // If there is no line break inside the "[...]" then "p" is + // advanced to after the "]" by to_name_const_end(): check if a "=" + // follows. + // If "[...]" has a line break "p" still points at the "[" and it + // can't be an assignment. + if (*eap->cmd == '[') { - eap->cmdidx = CMD_let; - return eap->cmd; + p = to_name_const_end(eap->cmd); + if (p == eap->cmd || *skipwhite(p) != '=') + { + eap->cmdidx = CMD_eval; + return eap->cmd; + } + if (p > eap->cmd && *skipwhite(p) == '=') + { + eap->cmdidx = CMD_let; + return eap->cmd; + } } - } - // Recognize an assignment if we recognize the variable name: - // "g:var = expr" - // "var = expr" where "var" is a local var name. - oplen = assignment_len(skipwhite(p), &heredoc); - if (oplen > 0) - { - if (((p - eap->cmd) > 2 && eap->cmd[1] == ':') - || lookup(eap->cmd, p - eap->cmd, cctx) != NULL) + // Recognize an assignment if we recognize the variable name: + // "g:var = expr" + // "var = expr" where "var" is a local var name. + oplen = assignment_len(skipwhite(p), &heredoc); + if (oplen > 0) { - eap->cmdidx = CMD_let; - return eap->cmd; + if (((p - eap->cmd) > 2 && eap->cmd[1] == ':') + || *eap->cmd == '&' + || *eap->cmd == '$' + || *eap->cmd == '@' + || lookup(eap->cmd, p - eap->cmd, cctx) != NULL) + { + eap->cmdidx = CMD_let; + return eap->cmd; + } } - } - // Recognize using a type for a w:, b:, t: or g: variable: - // "w:varname: number = 123". - if (eap->cmd[1] == ':' && *p == ':') - { - eap->cmdidx = CMD_eval; - return eap->cmd; + // Recognize using a type for a w:, b:, t: or g: variable: + // "w:varname: number = 123". + if (eap->cmd[1] == ':' && *p == ':') + { + eap->cmdidx = CMD_eval; + return eap->cmd; + } } } #endif diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 379245f397f229..427e91238e1bcf 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -61,6 +61,14 @@ def Test_assignment() assert_equal('foobar', $ENVVAR) $ENVVAR = '' + let lines =<< trim END + vim9script + $ENVVAR = 'barfoo' + assert_equal('barfoo', $ENVVAR) + $ENVVAR = '' + END + call CheckScriptSuccess(lines) + s:appendToMe ..= 'yyy' assert_equal('xxxyyy', s:appendToMe) s:addToMe += 222 @@ -80,6 +88,15 @@ def Test_assignment() set ts=10 &ts %= 4 assert_equal(2, &ts) + + lines =<< trim END + vim9script + &ts = 6 + &ts += 3 + assert_equal(9, &ts) + END + call CheckScriptSuccess(lines) + call CheckDefFailure(['¬ex += 3'], 'E113:') call CheckDefFailure(['&ts ..= "xxx"'], 'E1019:') call CheckDefFailure(['&ts = [7]'], 'E1013:') @@ -106,6 +123,14 @@ def Test_assignment() call CheckDefFailure(['@a += "more"'], 'E1013:') call CheckDefFailure(['@a += 123'], 'E1013:') + lines =<< trim END + vim9script + @c = 'areg' + @c ..= 'add' + assert_equal('aregadd', @c) + END + call CheckScriptSuccess(lines) + v:errmsg = 'none' v:errmsg ..= 'again' assert_equal('noneagain', v:errmsg) diff --git a/src/version.c b/src/version.c index 26bd7ac6518a8b..fce921888c6095 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1313, /**/ 1312, /**/ From 9898107f54a330c6d9629976250a393169c698ca Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 29 Jul 2020 14:40:25 +0200 Subject: [PATCH 0027/1384] patch 8.2.1314: Vim9: rule for comment after :function is confusing Problem: Vim9: rule for comment after :function is confusing. Solution: Allow double quoted comment after :function in vim9script. (closes #6556) --- src/testdir/test_vim9_script.vim | 8 ++++++-- src/userfunc.c | 3 ++- src/version.c | 2 ++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 427e91238e1bcf..b491fa21a585ad 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -2284,6 +2284,10 @@ def Test_vim9_comment() 'vim9script', 'function # comment', ]) + CheckScriptFailure([ + 'vim9script', + 'function " comment', + ], 'E129:') CheckScriptFailure([ 'vim9script', 'function# comment', @@ -2333,11 +2337,11 @@ def Test_vim9_comment() 'func Test() " comment', 'endfunc', ]) - CheckScriptFailure([ + CheckScriptSuccess([ 'vim9script', 'func Test() " comment', 'endfunc', - ], 'E488:') + ]) CheckScriptSuccess([ 'def Test() # comment', diff --git a/src/userfunc.c b/src/userfunc.c index d17e807dc616ce..343c9cd2e1dd22 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -2832,7 +2832,8 @@ def_function(exarg_T *eap, char_u *name_arg) if (*p == '\n') line_arg = p + 1; else if (*p != NUL - && !(*p == '"' && !(vim9script || eap->cmdidx == CMD_def)) + && !(*p == '"' && (!vim9script || eap->cmdidx == CMD_function) + && eap->cmdidx != CMD_def) && !(*p == '#' && (vim9script || eap->cmdidx == CMD_def)) && !eap->skip && !did_emsg) diff --git a/src/version.c b/src/version.c index fce921888c6095..b1ed1df4b61237 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1314, /**/ 1313, /**/ From 45df2a01a79d562b59949383f79625bb8bd89a69 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 29 Jul 2020 15:03:01 +0200 Subject: [PATCH 0028/1384] patch 8.2.1315: MS-Windows: test log contains escape sequences Problem: MS-Windows: test log contains escape sequences. Solution: Do not use t_md and t_me but ANSI escape sequences. (Ken Takata, closes #6559) --- src/testdir/runtest.vim | 14 ++++++++++---- src/version.c | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim index e42b0cabdbc362..f3609f8514582f 100644 --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -123,6 +123,12 @@ let s:srcdir = expand('%:p:h:h') if has('win32') " avoid prompt that is long or contains a line break let $PROMPT = '$P$G' + " On MS-Windows t_md and t_me are Vim specific escape sequences. + let s:t_bold = "\x1b[1m" + let s:t_normal = "\x1b[m" +else + let s:t_bold = &t_md + let s:t_normal = &t_me endif " Prepare for calling test_garbagecollect_now(). @@ -239,11 +245,11 @@ func RunTheTest(test) let message ..= repeat(' ', 50 - len(message)) let time = reltime(func_start) if has('float') && reltimefloat(time) > 0.1 - let message = &t_md .. message + let message = s:t_bold .. message endif let message ..= ' in ' .. reltimestr(time) .. ' seconds' if has('float') && reltimefloat(time) > 0.1 - let message ..= &t_me + let message ..= s:t_normal endif endif call add(s:messages, message) @@ -312,9 +318,9 @@ func FinishTesting() let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test') endif if s:done > 0 && has('reltime') - let message = &t_md .. message .. repeat(' ', 40 - len(message)) + let message = s:t_bold .. message .. repeat(' ', 40 - len(message)) let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds' - let message ..= &t_me + let message ..= s:t_normal endif echo message call add(s:messages, message) diff --git a/src/version.c b/src/version.c index b1ed1df4b61237..12716683573bfb 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1315, /**/ 1314, /**/ From b61ef01cce2afd70fbfa2805336a26643109dfb7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 29 Jul 2020 16:08:21 +0200 Subject: [PATCH 0029/1384] patch 8.2.1316: test 42 is still old style Problem: Test 42 is still old style. Solution: Turn it into a new style test. (Yegappan Lakshmanan, closes #6561) --- src/Makefile | 2 +- src/testdir/Make_all.mak | 2 +- src/testdir/Make_dos.mak | 3 - src/testdir/Make_ming.mak | 5 -- src/testdir/Make_vms.mms | 3 +- src/testdir/test42.in | Bin 2386 -> 0 bytes src/testdir/test42.ok | Bin 409 -> 0 bytes src/testdir/test_writefile.vim | 128 +++++++++++++++++++++++++++++++++ src/version.c | 2 + 9 files changed, 133 insertions(+), 12 deletions(-) delete mode 100644 src/testdir/test42.in delete mode 100644 src/testdir/test42.ok diff --git a/src/Makefile b/src/Makefile index bbf80d32632b09..d34a60891bf294 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2310,7 +2310,7 @@ test_libvterm: # Run individual OLD style test. # These do not depend on the executable, compile it when needed. -test1 test42 test49 test59: +test1 test49 test59: cd testdir; rm -f $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE) # Run individual NEW style test. diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index a25a480dd312db..635087cbdc0fea 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -11,7 +11,7 @@ NO_INITS = -U NONE $(NO_PLUGINS) SCRIPTS_FIRST = test1.out # Tests that run on all systems. -SCRIPTS_ALL = test42.out +SCRIPTS_ALL = # Tests that run on most systems, but not on Amiga. SCRIPTS_MORE1 = diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak index 0e07ed5c5f1508..f97b3e9bb4a2a4 100644 --- a/src/testdir/Make_dos.mak +++ b/src/testdir/Make_dos.mak @@ -10,10 +10,7 @@ default: nongui !include Make_all.mak # Omitted: -# test2 "\\tmp" doesn't work. -# test10 'errorformat' is different # test49 fails in various ways -# test97 \{ and \$ are not escaped characters. SCRIPTS = $(SCRIPTS_ALL) $(SCRIPTS_MORE1) $(SCRIPTS_MORE4) diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak index f95f70c88c4264..e1f34674920ea3 100644 --- a/src/testdir/Make_ming.mak +++ b/src/testdir/Make_ming.mak @@ -28,11 +28,6 @@ default: vimall include Make_all.mak -# Omitted: -# test2 "\\tmp" doesn't work. -# test10 'errorformat' is different -# test97 \{ and \$ are not escaped characters - SCRIPTS = $(SCRIPTS_ALL) $(SCRIPTS_MORE1) $(SCRIPTS_MORE4) $(SCRIPTS_WIN32) SCRIPTS_BENCH = test_bench_regexp.res diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms index af76f703ad46b7..848fca7f5829bc 100644 --- a/src/testdir/Make_vms.mms +++ b/src/testdir/Make_vms.mms @@ -73,8 +73,7 @@ VIMPROG = <->vim.exe .SUFFIXES : .out .in -SCRIPT = test1.out \ - test42.out test49.out test77a.out +SCRIPT = test1.out test49.out test77a.out # Known problems: # diff --git a/src/testdir/test42.in b/src/testdir/test42.in deleted file mode 100644 index 1d9d3ab92cd597e8c75fab7763d90cf3906c7da4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2386 zcmcgu&2G~`5Z<#NfD4yNs9I2QN>jH&ky2FJA|cUKB0+FM+QjSH!r3kB4Q_9|7Y81R zH%OUT@7hkAN*rht#hT2{?tJ^rpC_U)kSGnM&P*mRfXf)P;IWk<$#MaO;o7d1nMr}e z+w-#^7*CEqP9~@0NiZlB%%|5z^nPS>{3i^|F4d*Ulq|M~<4PmsOwpOcg-OEKm5vVg z`eL}472#CPU*;Trg}crq87^dY1xbPiBs8BcOwz1?S<2;wD8QtmLQ9u9IUn1LoE;qp zgD!+&2%qtO!de-7W%OMHgPpI=-Nw%LZrOn^wD^kj7H3(>A(a-65J9gCJg$4A%a+;J*q-!PoqfQVgrflIh5Sz{#%xnSGYg9K@B0DkA40DGBzy9j(6TQ0p+^@l&depiBh z(o7D#>L>l7_lbV6ykQGAV+9LYpH({K^Jdv7b0(^VC}0fD8E#;>h2bWK+Zc=RXSYUn M>w1G6jRYC~1?Romg8%>k diff --git a/src/testdir/test42.ok b/src/testdir/test42.ok deleted file mode 100644 index 183430d71cfe487b2d405dd2cde25a1eef958d74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 409 zcmZ|KO%8%E5C!13o>OpvE+CC@<6#7gA*m(dXYY+X01Fd5kT)nkN)!=EGmF=LolZrf zC@-urE-O!kJ0I+^DO@bBOv_6u-iNGWkzd$0x!Q9xxGAj6ve~n{2X{49^}k=d`!vjI zm24qv7L0NAa?AVrTj>q6?4=p!Kfec-$F1-BY4|=&?+3KVP(vYs41Nw42Eqjr5P=MY QAO$pw{QrUFp&7wgFR=M~uK)l5 diff --git a/src/testdir/test_writefile.vim b/src/testdir/test_writefile.vim index d92d6aedbe5934..d6e7e64c11beff 100644 --- a/src/testdir/test_writefile.vim +++ b/src/testdir/test_writefile.vim @@ -556,4 +556,132 @@ func Test_write_file_encoding() %bw! endfunc +" Test for writing and reading a file starting with a BOM. +" Byte Order Mark (BOM) character for various encodings is below: +" UTF-8 : EF BB BF +" UTF-16 (BE): FE FF +" UTF-16 (LE): FF FE +" UTF-32 (BE): 00 00 FE FF +" UTF-32 (LE): FF FE 00 00 +func Test_readwrite_file_with_bom() + let utf8_bom = "\xEF\xBB\xBF" + let utf16be_bom = "\xFE\xFF" + let utf16le_bom = "\xFF\xFE" + let utf32be_bom = "\n\n\xFE\xFF" + let utf32le_bom = "\xFF\xFE\n\n" + let save_fileencoding = &fileencoding + set cpoptions+=S + + " Check that editing a latin1 file doesn't see a BOM + call writefile(["\xFE\xFElatin-1"], 'Xtest1') + edit Xtest1 + call assert_equal('latin1', &fileencoding) + call assert_equal(0, &bomb) + set fenc=latin1 + write Xfile2 + call assert_equal(["\xFE\xFElatin-1", ''], readfile('Xfile2', 'b')) + set bomb fenc=latin1 + write Xtest3 + call assert_equal(["\xFE\xFElatin-1", ''], readfile('Xtest3', 'b')) + set bomb& + + " Check utf-8 BOM + %bw! + call writefile([utf8_bom .. "utf-8"], 'Xtest1') + edit! Xtest1 + call assert_equal('utf-8', &fileencoding) + call assert_equal(1, &bomb) + call assert_equal('utf-8', getline(1)) + set fenc=latin1 + write! Xfile2 + call assert_equal(['utf-8', ''], readfile('Xfile2', 'b')) + set fenc=utf-8 + w! Xtest3 + call assert_equal([utf8_bom .. "utf-8", ''], readfile('Xtest3', 'b')) + + " Check utf-8 with an error (will fall back to latin-1) + %bw! + call writefile([utf8_bom .. "utf-8\x80err"], 'Xtest1') + edit! Xtest1 + call assert_equal('latin1', &fileencoding) + call assert_equal(0, &bomb) + call assert_equal("\xC3\xAF\xC2\xBB\xC2\xBFutf-8\xC2\x80err", getline(1)) + set fenc=latin1 + write! Xfile2 + call assert_equal([utf8_bom .. "utf-8\x80err", ''], readfile('Xfile2', 'b')) + set fenc=utf-8 + w! Xtest3 + call assert_equal(["\xC3\xAF\xC2\xBB\xC2\xBFutf-8\xC2\x80err", ''], + \ readfile('Xtest3', 'b')) + + " Check ucs-2 BOM + %bw! + call writefile([utf16be_bom .. "\nu\nc\ns\n-\n2\n"], 'Xtest1') + edit! Xtest1 + call assert_equal('utf-16', &fileencoding) + call assert_equal(1, &bomb) + call assert_equal('ucs-2', getline(1)) + set fenc=latin1 + write! Xfile2 + call assert_equal(["ucs-2", ''], readfile('Xfile2', 'b')) + set fenc=ucs-2 + w! Xtest3 + call assert_equal([utf16be_bom .. "\nu\nc\ns\n-\n2\n", ''], + \ readfile('Xtest3', 'b')) + + " Check ucs-2le BOM + %bw! + call writefile([utf16le_bom .. "u\nc\ns\n-\n2\nl\ne\n"], 'Xtest1') + " Need to add a NUL byte after the NL byte + call writefile(0z00, 'Xtest1', 'a') + edit! Xtest1 + call assert_equal('utf-16le', &fileencoding) + call assert_equal(1, &bomb) + call assert_equal('ucs-2le', getline(1)) + set fenc=latin1 + write! Xfile2 + call assert_equal(["ucs-2le", ''], readfile('Xfile2', 'b')) + set fenc=ucs-2le + w! Xtest3 + call assert_equal([utf16le_bom .. "u\nc\ns\n-\n2\nl\ne\n", "\n"], + \ readfile('Xtest3', 'b')) + + " Check ucs-4 BOM + %bw! + call writefile([utf32be_bom .. "\n\n\nu\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\n"], 'Xtest1') + edit! Xtest1 + call assert_equal('ucs-4', &fileencoding) + call assert_equal(1, &bomb) + call assert_equal('ucs-4', getline(1)) + set fenc=latin1 + write! Xfile2 + call assert_equal(["ucs-4", ''], readfile('Xfile2', 'b')) + set fenc=ucs-4 + w! Xtest3 + call assert_equal([utf32be_bom .. "\n\n\nu\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\n", ''], readfile('Xtest3', 'b')) + + " Check ucs-4le BOM + %bw! + call writefile([utf32le_bom .. "u\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\nl\n\n\ne\n\n\n"], 'Xtest1') + " Need to add three NUL bytes after the NL byte + call writefile(0z000000, 'Xtest1', 'a') + edit! Xtest1 + call assert_equal('ucs-4le', &fileencoding) + call assert_equal(1, &bomb) + call assert_equal('ucs-4le', getline(1)) + set fenc=latin1 + write! Xfile2 + call assert_equal(["ucs-4le", ''], readfile('Xfile2', 'b')) + set fenc=ucs-4le + w! Xtest3 + call assert_equal([utf32le_bom .. "u\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\nl\n\n\ne\n\n\n", "\n\n\n"], readfile('Xtest3', 'b')) + + set cpoptions-=S + let &fileencoding = save_fileencoding + call delete('Xtest1') + call delete('Xtest2') + call delete('Xtest3') + %bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 12716683573bfb..045dfbcb78d10a 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1316, /**/ 1315, /**/ From f9a343f8bda8fbe17ff045bef7342ffd6179e2f5 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 29 Jul 2020 16:32:21 +0200 Subject: [PATCH 0030/1384] patch 8.2.1317: MS-Windows tests on AppVeyor are slow Problem: MS-Windows tests on AppVeyor are slow. Solution: Use GitHub Actions. (Ken Takata, closes #6569) --- .github/workflows/ci-windows.yaml | 208 ++++++++++++++++++++++++++++++ Filelist | 1 + appveyor.yml | 9 +- ci/appveyor.bat | 44 ++----- src/version.c | 2 + 5 files changed, 230 insertions(+), 34 deletions(-) create mode 100644 .github/workflows/ci-windows.yaml diff --git a/.github/workflows/ci-windows.yaml b/.github/workflows/ci-windows.yaml new file mode 100644 index 00000000000000..1fca08ea575e71 --- /dev/null +++ b/.github/workflows/ci-windows.yaml @@ -0,0 +1,208 @@ +name: CI with MSVC and MinGW-w64 + +on: + push: + pull_request: + +env: + VCVARSALL: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat + + # Interfaces + # Lua + LUA_VER: 54 + LUA_VER_DOT: '5.4' + LUA_RELEASE: 5.4.0 + LUA32_URL: https://downloads.sourceforge.net/luabinaries/lua-%LUA_RELEASE%_Win32_dllw6_lib.zip + LUA64_URL: https://downloads.sourceforge.net/luabinaries/lua-%LUA_RELEASE%_Win64_dllw6_lib.zip + LUA_DIR: D:\Lua + # Python 2 + PYTHON_VER: 27 + PYTHON_VER_DOT: '2.7' + # Python 3 + PYTHON3_VER: 38 + PYTHON3_VER_DOT: '3.8' + + # Other dependencies + # winpty + WINPTY_URL: https://github.com/rprichard/winpty/releases/download/0.4.3/winpty-0.4.3-msvc2015.zip + + # Escape sequences + COL_RED: "\x1b[31m" + COL_GREEN: "\x1b[32m" + COL_YELLOW: "\x1b[33m" + COL_RESET: "\x1b[m" + +jobs: + build: + runs-on: windows-latest + + strategy: + matrix: + toolchain: [msvc, mingw] + arch: [x64, x86] + features: [HUGE, NORMAL] + include: + - arch: x64 + vcarch: amd64 + warch: x64 + bits: 64 + msystem: MINGW64 + cygreg: registry + pyreg: "" + - arch: x86 + vcarch: x86 + warch: ia32 + bits: 32 + msystem: MINGW32 + cygreg: registry32 + pyreg: "-32" + exclude: + - toolchain: msvc + arch: x64 + features: NORMAL + - toolchain: mingw + arch: x86 + features: NORMAL + + steps: + - name: Initalize + id: init + shell: bash + run: | + git config --global core.autocrlf input + python_dir=$(cat "/proc/${{ matrix.cygreg }}/HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${PYTHON_VER_DOT}/InstallPath/@") + python3_dir=$(cat "/proc/${{ matrix.cygreg }}/HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${PYTHON3_VER_DOT}${{ matrix.pyreg }}/InstallPath/@") + echo "::set-env name=PYTHON_DIR::$python_dir" + echo "::set-env name=PYTHON3_DIR::$python3_dir" + + - uses: msys2/setup-msys2@v2 + if: matrix.toolchain == 'mingw' + with: + msystem: ${{ matrix.msystem }} + release: false + + - uses: actions/checkout@v2 + + - name: Create a list of download URLs + shell: cmd + run: | + type NUL > urls.txt + echo %LUA_RELEASE%>> urls.txt + echo %WINPTY_URL%>> urls.txt + + - name: Cache downloaded files + uses: actions/cache@v2 + with: + path: downloads + key: ${{ runner.os }}-${{ matrix.bits }}-${{ hashFiles('urls.txt') }} + + - name: Download dependencies + shell: cmd + run: | + path C:\Program Files\7-Zip;%path% + if not exist downloads mkdir downloads + + echo %COL_GREEN%Download Lua%COL_RESET% + call :downloadfile %LUA${{ matrix.bits }}_URL% downloads\lua.zip + 7z x downloads\lua.zip -o%LUA_DIR% > nul || exit 1 + + echo %COL_GREEN%Download winpty%COL_RESET% + call :downloadfile %WINPTY_URL% downloads\winpty.zip + 7z x -y downloads\winpty.zip -oD:\winpty > nul || exit 1 + copy /Y D:\winpty\${{ matrix.warch }}\bin\winpty.dll src\winpty${{ matrix.bits }}.dll + copy /Y D:\winpty\${{ matrix.warch }}\bin\winpty-agent.exe src\ + + goto :eof + + :downloadfile + :: call :downloadfile + if not exist %2 ( + curl -f -L %1 -o %2 + ) + if ERRORLEVEL 1 ( + rem Retry once. + curl -f -L %1 -o %2 || exit 1 + ) + goto :eof + + - name: Build (MSVC) + if: matrix.toolchain == 'msvc' + shell: cmd + run: | + call "%VCVARSALL%" ${{ matrix.vcarch }} + cd src + :: Filter out the progress bar from the build log + sed -e "s/@<<$/@<< | sed -e 's#.*\\\\r.*##'/" Make_mvc.mak > Make_mvc2.mak + if "${{ matrix.features }}"=="HUGE" ( + nmake -nologo -f Make_mvc2.mak ^ + FEATURES=${{ matrix.features }} ^ + GUI=yes IME=yes ICONV=yes VIMDLL=yes ^ + DYNAMIC_LUA=yes LUA=%LUA_DIR% ^ + DYNAMIC_PYTHON=yes PYTHON=%PYTHON_DIR% ^ + DYNAMIC_PYTHON3=yes PYTHON3=%PYTHON3_DIR% + ) else ( + nmake -nologo -f Make_mvc2.mak ^ + FEATURES=${{ matrix.features }} ^ + GUI=yes IME=yes ICONV=yes VIMDLL=yes + ) + if not exist vim${{ matrix.bits }}.dll ( + echo %COL_RED%Build failure.%COL_RESET% + exit 1 + ) + + - name: Build (MinGW) + if: matrix.toolchain == 'mingw' + shell: msys2 {0} + run: | + cd src + if [ "${{ matrix.features }}" = "HUGE" ]; then + mingw32-make -f Make_ming.mak -j2 \ + FEATURES=${{ matrix.features }} \ + GUI=yes IME=yes ICONV=yes VIMDLL=yes \ + DYNAMIC_LUA=yes LUA=${LUA_DIR} \ + DYNAMIC_PYTHON=yes PYTHON=${PYTHON_DIR} \ + DYNAMIC_PYTHON3=yes PYTHON3=${PYTHON3_DIR} \ + STATIC_STDCPLUS=yes + else + mingw32-make -f Make_ming.mak -j2 \ + FEATURES=${{ matrix.features }} \ + GUI=yes IME=yes ICONV=yes VIMDLL=yes \ + STATIC_STDCPLUS=yes + fi + +# - name: Prepare Artifact +# shell: cmd +# run: | +# mkdir artifacts +# copy src\*vim.exe artifacts +# copy src\vim*.dll artifacts +# +# - name: Upload Artifact +# uses: actions/upload-artifact@v1 +# with: +# name: vim${{ matrix.bits }}-${{ matrix.toolchain }} +# path: ./artifacts + + - name: Test + shell: cmd + timeout-minutes: 20 + run: | + PATH %LUA_DIR%;C:\msys64\${{ matrix.msystem }}\bin;%PATH%;%PYTHON3_DIR% + call "%VCVARSALL%" ${{ matrix.vcarch }} + cd src + echo. + echo %COL_GREEN%vim version:%COL_RESET% + .\vim --version || exit 1 + cd testdir + echo %COL_GREEN%Test gvim:%COL_RESET% + nmake -nologo -f Make_dos.mak VIMPROG=..\gvim || exit 1 + nmake -nologo -f Make_dos.mak clean + echo %COL_GREEN%Test vim:%COL_RESET% + if "${{ matrix.toolchain }}-${{ matrix.arch }}"=="msvc-x64" ( + rem This test may hang up unless it is executed in a separate console. + start /wait cmd /c "nmake -nologo -f Make_dos.mak VIMPROG=..\vim > nul" + if exist messages type messages + nmake -nologo -f Make_dos.mak report || exit 1 + ) else ( + nmake -nologo -f Make_dos.mak VIMPROG=..\vim || exit 1 + ) diff --git a/Filelist b/Filelist index 1e22554d40aced..ecc1dd2cf44040 100644 --- a/Filelist +++ b/Filelist @@ -9,6 +9,7 @@ SRC_ALL = \ .lgtm.yml \ .travis.yml \ .cirrus.yml \ + .github/workflows/ci-windows.yaml \ appveyor.yml \ ci/appveyor.bat \ ci/if_ver*.vim \ diff --git a/appveyor.yml b/appveyor.yml index eb720f47dd75c7..80f8e38f0b02fa 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,16 +5,17 @@ skip_tags: true environment: matrix: - FEATURE: HUGE - - FEATURE: NORMAL # disabled # - FEATURE: TINY # - FEATURE: SMALL +# - FEATURE: NORMAL # - FEATURE: BIG matrix: fast_finish: true before_build: + # Use Windows SDK 7.1 (= MSVC 2010) - '"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 /release' - 'set INCLUDE=%INCLUDE%C:\Program Files (x86)\Windows Kits\8.1\Include\um' @@ -25,9 +26,9 @@ test_script: - cd src/testdir # Testing with MSVC gvim - path C:\Python35-x64;%PATH% - - nmake -f Make_dos.mak POSTSCRIPT=yes VIMPROG=..\gvim + - nmake -f Make_dos.mak VIMPROG=..\gvim - nmake -f Make_dos.mak clean - # Testing with MingW console version - - nmake -f Make_dos.mak POSTSCRIPT=yes VIMPROG=..\vim + # Testing with MSVC console version + - nmake -f Make_dos.mak VIMPROG=..\vim # vim: sw=2 sts=2 et ts=8 sr diff --git a/ci/appveyor.bat b/ci/appveyor.bat index 590c48a7c461b9..164d7bcc2582c6 100644 --- a/ci/appveyor.bat +++ b/ci/appveyor.bat @@ -5,48 +5,32 @@ setlocal ENABLEDELAYEDEXPANSION cd %APPVEYOR_BUILD_FOLDER% cd src -echo "Building MinGW 32bit console version" -set PATH=c:\msys64\mingw32\bin;%PATH% -mingw32-make.exe -f Make_ming.mak GUI=no OPTIMIZE=speed IME=yes ICONV=yes DEBUG=no FEATURES=%FEATURE% || exit 1 -.\vim -u NONE -c "redir @a | ver |0put a | wq" ver_ming.txt -:: Save vim.exe before Make clean, moved back below. -copy vim.exe testdir -mingw32-make.exe -f Make_ming.mak clean - -:: Build Mingw huge version with python and channel support, or -:: with specified features without python. -echo "Building MinGW 32bit GUI version" -if "%FEATURE%" == "HUGE" ( - mingw32-make.exe -f Make_ming.mak OPTIMIZE=speed CHANNEL=yes GUI=yes IME=yes ICONV=yes DEBUG=no PYTHON_VER=27 DYNAMIC_PYTHON=yes PYTHON=C:\Python27 PYTHON3_VER=35 DYNAMIC_PYTHON3=yes PYTHON3=C:\Python35 FEATURES=%FEATURE% || exit 1 -) ELSE ( - mingw32-make.exe -f Make_ming.mak OPTIMIZE=speed GUI=yes IME=yes ICONV=yes DEBUG=no FEATURES=%FEATURE% || exit 1 -) -.\gvim -u NONE -c "redir @a | ver |0put a | wq" ver_ming_gui.txt - :: Filter out the progress bar from the build log sed -e "s/@<<$/@<< | sed -e 's#.*\\\\r.*##'/" Make_mvc.mak > Make_mvc2.mak echo "Building MSVC 64bit console Version" -nmake -f Make_mvc2.mak CPU=AMD64 OLE=no GUI=no IME=yes ICONV=yes DEBUG=no FEATURES=%FEATURE% || exit 1 -:: The executable is not used -nmake -f Make_mvc2.mak clean +nmake -f Make_mvc2.mak CPU=AMD64 ^ + OLE=no GUI=no IME=yes ICONV=yes DEBUG=no ^ + FEATURES=%FEATURE% || exit 1 :: build MSVC huge version with python and channel support :: GUI needs to be last, so that testing works echo "Building MSVC 64bit GUI Version" if "%FEATURE%" == "HUGE" ( - nmake -f Make_mvc2.mak DIRECTX=yes CPU=AMD64 CHANNEL=yes OLE=no GUI=yes IME=yes ICONV=yes DEBUG=no PYTHON_VER=27 DYNAMIC_PYTHON=yes PYTHON=C:\Python27-x64 PYTHON3_VER=35 DYNAMIC_PYTHON3=yes PYTHON3=C:\Python35-x64 FEATURES=%FEATURE% || exit 1 + nmake -f Make_mvc2.mak CPU=AMD64 ^ + OLE=no GUI=yes IME=yes ICONV=yes DEBUG=no POSTSCRIPT=yes ^ + PYTHON_VER=27 DYNAMIC_PYTHON=yes PYTHON=C:\Python27-x64 ^ + PYTHON3_VER=35 DYNAMIC_PYTHON3=yes PYTHON3=C:\Python35-x64 ^ + FEATURES=%FEATURE% || exit 1 ) ELSE ( - nmake -f Make_mvc2.mak CPU=AMD64 OLE=no GUI=yes IME=yes ICONV=yes DEBUG=no FEATURES=%FEATURE% || exit 1 + nmake -f Make_mvc2.mak CPU=AMD64 ^ + OLE=no GUI=yes IME=yes ICONV=yes DEBUG=no ^ + FEATURES=%FEATURE% || exit 1 ) .\gvim -u NONE -c "redir @a | ver |0put a | wq" ver_msvc.txt -:: Restore vim.exe, tests will run with this. -move /Y testdir\vim.exe . -echo "version output MinGW" -type ver_ming.txt -echo "version output MinGW GUI" -type ver_ming_gui.txt -echo "version output MVC" +echo "version output MSVC console" +.\vim --version +echo "version output MSVC GUI" type ver_msvc.txt cd .. diff --git a/src/version.c b/src/version.c index 045dfbcb78d10a..67e52b3d41159b 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1317, /**/ 1316, /**/ From ed3c7e633944cf70754bc05504a7cd724fdca178 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 29 Jul 2020 17:34:33 +0200 Subject: [PATCH 0031/1384] patch 8.2.1318: no status badge for Github CI Problem: No status badge for Github CI. Solution: Add a badge. --- README.md | 1 + src/version.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/README.md b/README.md index d42680c6ba6c41..78b9ff6f1ec0a1 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Travis Build Status](https://travis-ci.org/vim/vim.svg?branch=master)](https://travis-ci.org/vim/vim) [![Appveyor Build status](https://ci.appveyor.com/api/projects/status/o2qht2kjm02sgghk?svg=true)](https://ci.appveyor.com/project/chrisbra/vim) +![Github Build status](https://github.com/vim/vim/workflows/CI%20with%20MSVC%20and%20MinGW-w64/badge.svg) [![Cirrus Build Status](https://api.cirrus-ci.com/github/vim/vim.svg)](https://cirrus-ci.com/github/vim/vim) [![Coverage Status](https://codecov.io/gh/vim/vim/coverage.svg?branch=master)](https://codecov.io/gh/vim/vim?branch=master) [![Coverity Scan](https://scan.coverity.com/projects/241/badge.svg)](https://scan.coverity.com/projects/vim) diff --git a/src/version.c b/src/version.c index 67e52b3d41159b..0d985285ee6348 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1318, /**/ 1317, /**/ From ac7bf8c4bfcbb157a2db6b939927bf11edb6ba7b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 29 Jul 2020 17:43:55 +0200 Subject: [PATCH 0032/1384] patch 8.2.1319: status badge for Github CI has wrong link Problem: Status badge for Github CI has wrong link. Solution: Rename and use the right link --- .github/workflows/ci-windows.yaml | 2 +- README.md | 2 +- src/version.c | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-windows.yaml b/.github/workflows/ci-windows.yaml index 1fca08ea575e71..ec02a8124a87cc 100644 --- a/.github/workflows/ci-windows.yaml +++ b/.github/workflows/ci-windows.yaml @@ -1,4 +1,4 @@ -name: CI with MSVC and MinGW-w64 +name: GitHub CI on: push: diff --git a/README.md b/README.md index 78b9ff6f1ec0a1..2373f57b987f4b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Travis Build Status](https://travis-ci.org/vim/vim.svg?branch=master)](https://travis-ci.org/vim/vim) [![Appveyor Build status](https://ci.appveyor.com/api/projects/status/o2qht2kjm02sgghk?svg=true)](https://ci.appveyor.com/project/chrisbra/vim) -![Github Build status](https://github.com/vim/vim/workflows/CI%20with%20MSVC%20and%20MinGW-w64/badge.svg) +[![Github Build status](https://github.com/vim/vim/workflows/GitHub%20CI/badge.svg)](https://github.com/vim/vim/actions?query=workflow%3A%22GitHub+CI%22) [![Cirrus Build Status](https://api.cirrus-ci.com/github/vim/vim.svg)](https://cirrus-ci.com/github/vim/vim) [![Coverage Status](https://codecov.io/gh/vim/vim/coverage.svg?branch=master)](https://codecov.io/gh/vim/vim?branch=master) [![Coverity Scan](https://scan.coverity.com/projects/241/badge.svg)](https://scan.coverity.com/projects/vim) diff --git a/src/version.c b/src/version.c index 0d985285ee6348..4b53df32d0e1d2 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1319, /**/ 1318, /**/ From 33afa2447bdb0bdd15253c69a2cf6f9903685815 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 29 Jul 2020 19:18:00 +0200 Subject: [PATCH 0033/1384] patch 8.2.1320: Vim9: cannot declare some single letter variables Problem: Vim9: cannot declare some single letter variables. Solution: Do not recognize a colon for a namespace for single letter variables. (closes #6547) --- src/testdir/test_vim9_script.vim | 25 +++++++++++++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 18 +++++++++++------- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index b491fa21a585ad..0166072f16b6e7 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -109,6 +109,9 @@ def Test_assignment() call CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:') &ts = 8 + call CheckDefFailure(['let s:var = 123'], 'E1101:') + call CheckDefFailure(['let s:var: number'], 'E1101:') + g:inc_counter += 1 assert_equal(2, g:inc_counter) @@ -136,6 +139,28 @@ def Test_assignment() assert_equal('noneagain', v:errmsg) call CheckDefFailure(['v:errmsg += "more"'], 'E1013:') call CheckDefFailure(['v:errmsg += 123'], 'E1013:') + + # single letter variables + a = 123 + assert_equal(123, a) + let b: number + b = 123 + assert_equal(123, b) + let g: number + g = 123 + assert_equal(123, g) + let s: number + s = 123 + assert_equal(123, s) + let t: number + t = 123 + assert_equal(123, t) + let v: number + v = 123 + assert_equal(123, v) + let w: number + w = 123 + assert_equal(123, w) enddef def Test_vim9_single_char_vars() diff --git a/src/version.c b/src/version.c index 4b53df32d0e1d2..b81ac066a75e73 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1320, /**/ 1319, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index cbb9231d8cf004..f1509048e4df15 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -5237,7 +5237,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) goto theend; } } - else if (STRNCMP(var_start, "g:", 2) == 0) + else if (varlen > 1 && STRNCMP(var_start, "g:", 2) == 0) { dest = dest_global; if (is_decl) @@ -5246,7 +5246,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) goto theend; } } - else if (STRNCMP(var_start, "b:", 2) == 0) + else if (varlen > 1 && STRNCMP(var_start, "b:", 2) == 0) { dest = dest_buffer; if (is_decl) @@ -5255,7 +5255,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) goto theend; } } - else if (STRNCMP(var_start, "w:", 2) == 0) + else if (varlen > 1 && STRNCMP(var_start, "w:", 2) == 0) { dest = dest_window; if (is_decl) @@ -5264,7 +5264,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) goto theend; } } - else if (STRNCMP(var_start, "t:", 2) == 0) + else if (varlen > 1 && STRNCMP(var_start, "t:", 2) == 0) { dest = dest_tab; if (is_decl) @@ -5273,7 +5273,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) goto theend; } } - else if (STRNCMP(var_start, "v:", 2) == 0) + else if (varlen > 1 && STRNCMP(var_start, "v:", 2) == 0) { typval_T *vtv; int di_flags; @@ -5337,14 +5337,18 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) goto theend; } } - else if (STRNCMP(var_start, "s:", 2) == 0 + else if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0) || lookup_script(var_start, varlen) == OK || find_imported(var_start, varlen, cctx) != NULL) { dest = dest_script; if (is_decl) { - semsg(_("E1054: Variable already declared in the script: %s"), + if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0)) + semsg(_("E1101: Cannot declare a script variable in a function: %s"), + name); + else + semsg(_("E1054: Variable already declared in the script: %s"), name); goto theend; } From 7b7f78f51dc5a2c307330af0d4e53faced34726f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 29 Jul 2020 19:29:23 +0200 Subject: [PATCH 0034/1384] patch 8.2.1321: GitHub CI also runs on tag push Problem: GitHub CI also runs on tag push. Solution: Skip CI on push. (Ken Takata, closes #6571) --- .github/workflows/ci-windows.yaml | 2 ++ src/version.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/ci-windows.yaml b/.github/workflows/ci-windows.yaml index ec02a8124a87cc..68b5480b0e8755 100644 --- a/.github/workflows/ci-windows.yaml +++ b/.github/workflows/ci-windows.yaml @@ -2,6 +2,8 @@ name: GitHub CI on: push: + branches: + - '*' pull_request: env: diff --git a/src/version.c b/src/version.c index b81ac066a75e73..db2e9b42b1b8d9 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1321, /**/ 1320, /**/ From 1040956292a9f2c3d02fc08febd5acf349c85590 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 29 Jul 2020 20:00:38 +0200 Subject: [PATCH 0035/1384] patch 8.2.1322: Vim9: method on double quoted string doesn't work Problem: Vim9: method on double quoted string doesn't work. Solution: Recognize double quoted string. (closes #6562) --- src/ex_docmd.c | 4 +++- src/testdir/test_vim9_expr.vim | 5 +++-- src/testdir/test_vim9_func.vim | 9 +++++++++ src/version.c | 2 ++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 536850edc9f65d..ad1693b516f1c3 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -3277,7 +3277,7 @@ find_ex_command( char_u *pskip = (*eap->cmd == '&' || *eap->cmd == '$' || *eap->cmd == '@') ? eap->cmd + 1 : eap->cmd; - if (vim_strchr((char_u *)"{('[", *p) != NULL + if (vim_strchr((char_u *)"{('[\"", *p) != NULL || ((p = to_name_const_end(pskip)) > eap->cmd && *p != NUL)) { int oplen; @@ -3293,6 +3293,8 @@ find_ex_command( *eap->cmd == '{' // "'string'->func()" is an expression. || *eap->cmd == '\'' + // '"string"->func()' is an expression. + || *eap->cmd == '"' // "g:varname" is an expression. || eap->cmd[1] == ':' ) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 5b46c32f96e201..e29ef5cf0e5759 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1638,8 +1638,9 @@ enddef def Test_expr7_method_call() new setline(1, ['first', 'last']) - eval 'second'->append(1) - assert_equal(['first', 'second', 'last'], getline(1, '$')) + 'second'->append(1) + "third"->append(2) + assert_equal(['first', 'second', 'third', 'last'], getline(1, '$')) bwipe! let bufnr = bufnr() diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index c05e98e70451a5..2546f1369fdda8 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -502,8 +502,11 @@ def Test_vim9script_call() assert_equal('some', var) # line starting with single quote is not a mark + # line starting with double quote can be a method call 'asdfasdf'->MyFunc() assert_equal('asdfasdf', var) + "xyz"->MyFunc() + assert_equal('xyz', var) def UseString() 'xyork'->MyFunc() @@ -511,6 +514,12 @@ def Test_vim9script_call() UseString() assert_equal('xyork', var) + def UseString2() + "knife"->MyFunc() + enddef + UseString2() + assert_equal('knife', var) + # prepending a colon makes it a mark new setline(1, ['aaa', 'bbb', 'ccc']) diff --git a/src/version.c b/src/version.c index db2e9b42b1b8d9..bb1c4ab413c626 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1322, /**/ 1321, /**/ From 696ba23149eb5a7226e606e3fe6f15fdd064c5f7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 29 Jul 2020 21:20:41 +0200 Subject: [PATCH 0036/1384] patch 8.2.1323: Vim9: invalid operators only rejected in :def function Problem: Vim9: invalid operators only rejected in :def function. Solution: Also reject them at script level. (closes #6564) --- src/eval.c | 48 +++++++--------------------------- src/proto/vim9compile.pro | 1 + src/testdir/test_vim9_expr.vim | 26 +++++++++++++++++- src/version.c | 2 ++ src/vim9compile.c | 2 +- 5 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/eval.c b/src/eval.c index 81913c7a353012..451bb16b7c58d6 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2420,9 +2420,9 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg) { char_u *p; int getnext; - int i; exptype_T type = EXPR_UNKNOWN; int len = 2; + int type_is = FALSE; /* * Get the first variable. @@ -2431,44 +2431,7 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg) return FAIL; p = eval_next_non_blank(*arg, evalarg, &getnext); - switch (p[0]) - { - case '=': if (p[1] == '=') - type = EXPR_EQUAL; - else if (p[1] == '~') - type = EXPR_MATCH; - break; - case '!': if (p[1] == '=') - type = EXPR_NEQUAL; - else if (p[1] == '~') - type = EXPR_NOMATCH; - break; - case '>': if (p[1] != '=') - { - type = EXPR_GREATER; - len = 1; - } - else - type = EXPR_GEQUAL; - break; - case '<': if (p[1] != '=') - { - type = EXPR_SMALLER; - len = 1; - } - else - type = EXPR_SEQUAL; - break; - case 'i': if (p[1] == 's') - { - if (p[2] == 'n' && p[3] == 'o' && p[4] == 't') - len = 5; - i = p[len]; - if (!isalnum(i) && i != '_') - type = len == 2 ? EXPR_IS : EXPR_ISNOT; - } - break; - } + type = get_compare_type(p, &len, &type_is); /* * If there is a comparative operator, use it. @@ -2482,6 +2445,13 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg) if (getnext) *arg = eval_next_line(evalarg); + if (vim9script && type_is && (p[len] == '?' || p[len] == '#')) + { + semsg(_(e_invexpr2), p); + clear_tv(rettv); + return FAIL; + } + // extra question mark appended: ignore case if (p[len] == '?') { diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro index 4108c04af4eb09..fd2dd1bf4b3393 100644 --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -16,6 +16,7 @@ int vim9_comment_start(char_u *p); char_u *peek_next_line_from_context(cctx_T *cctx); char_u *next_line_from_context(cctx_T *cctx, int skip_comment); char_u *to_name_const_end(char_u *arg); +exptype_T get_compare_type(char_u *p, int *len, int *type_is); int assignment_len(char_u *p, int *heredoc); void vim9_declare_error(char_u *name); int check_vim9_unlet(char_u *name); diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index e29ef5cf0e5759..550e4198263632 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -831,7 +831,7 @@ def Test_expr5() enddef def Test_expr5_vim9script() - # only checks line continuation + # check line continuation let lines =<< trim END vim9script let var = 11 @@ -848,6 +848,30 @@ def Test_expr5_vim9script() assert_equal('onetwo', var) END CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + echo 'abc' is# 'abc' + END + CheckScriptFailure(lines, 'E15:') + + lines =<< trim END + vim9script + echo 'abc' is? 'abc' + END + CheckScriptFailure(lines, 'E15:') + + lines =<< trim END + vim9script + echo 'abc' isnot# 'abc' + END + CheckScriptFailure(lines, 'E15:') + + lines =<< trim END + vim9script + echo 'abc' isnot? 'abc' + END + CheckScriptFailure(lines, 'E15:') enddef def Test_expr5_float() diff --git a/src/version.c b/src/version.c index bb1c4ab413c626..033f36072fa0ce 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1323, /**/ 1322, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index f1509048e4df15..cf08e955844135 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3633,7 +3633,7 @@ get_vim_constant(char_u **arg, typval_T *rettv) } } - static exptype_T + exptype_T get_compare_type(char_u *p, int *len, int *type_is) { exptype_T type = EXPR_UNKNOWN; From c7e44a7e4caedc1bc33f5c8e481109c0ae002823 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 29 Jul 2020 21:37:43 +0200 Subject: [PATCH 0037/1384] patch 8.2.1324: Vim9: line break after "=" does not work Problem: Vim9: line break after "=" does not work. Solution: Also allow for NUL after "=". (closes #6549) --- src/evalvars.c | 5 +++-- src/testdir/test_vim9_script.vim | 19 +++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/evalvars.c b/src/evalvars.c index f409f8c0066a1f..73c4da6c6eefe0 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -801,13 +801,13 @@ ex_let(exarg_T *eap) else ++expr; - if (vim9script && (!VIM_ISWHITE(*argend) || !VIM_ISWHITE(*expr))) + if (vim9script && (!VIM_ISWHITE(*argend) + || !IS_WHITE_OR_NUL(*expr))) { vim_strncpy(op, expr - len, len); semsg(_(e_white_both), op); i = FAIL; } - expr = skipwhite(expr); if (eap->skip) ++emsg_skip; @@ -818,6 +818,7 @@ ex_let(exarg_T *eap) evalarg.eval_getline = eap->getline; evalarg.eval_cookie = eap->cookie; } + expr = skipwhite_and_linebreak(expr, &evalarg); i = eval0(expr, &rettv, eap, &evalarg); if (eap->skip) --emsg_skip; diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 0166072f16b6e7..405d4877a25707 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -358,6 +358,25 @@ def Test_assignment_var_list() assert_equal(['three'], vrem) enddef +def Test_assignment_vim9script() + let lines =<< trim END + vim9script + def Func(): list + return [1, 2] + enddef + let var1: number + let var2: number + [var1, var2] = + Func() + assert_equal(1, var1) + assert_equal(2, var2) + let ll = + Func() + assert_equal([1, 2], ll) + END + CheckScriptSuccess(lines) +enddef + def Mess(): string v:foldstart = 123 return 'xxx' diff --git a/src/version.c b/src/version.c index 033f36072fa0ce..0734bdc1e343c2 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1324, /**/ 1323, /**/ From ea2d8d25718836bf627b67b7fcd28a1e528bb7b9 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 29 Jul 2020 22:11:05 +0200 Subject: [PATCH 0038/1384] patch 8.2.1325: Vim9: using Vim9 script for autaload not tested Problem: Vim9: using Vim9 script for autaload not tested. Solution: Add a test. Update help. --- runtime/doc/vim9.txt | 10 +++++++--- src/testdir/sautest/autoload/auto9.vim | 9 +++++++++ src/testdir/test_autoload.vim | 5 +++++ src/version.c | 2 ++ 4 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 src/testdir/sautest/autoload/auto9.vim diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 7b2597dc6e445e..5d264b673db88d 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -118,9 +118,13 @@ Functions and variables are script-local by default ~ *vim9-scopes* When using `:function` or `:def` to specify a new function at the script level in a Vim9 script, the function is local to the script, as if "s:" was -prefixed. Using the "s:" prefix is optional. - -To define or use a global function or variable the "g:" prefix must be used. +prefixed. Using the "s:" prefix is optional. To define or use a global +function or variable the "g:" prefix must be used. For functions in an +autoload script the "name#" prefix is sufficient. > + def ThisFunction() # script-local + def s:ThisFunction() # script-local + def g:ThatFunction() # global + def scriptname#function() # autoload When using `:function` or `:def` to specify a new function inside a function, the function is local to the function. It is not possible to define a diff --git a/src/testdir/sautest/autoload/auto9.vim b/src/testdir/sautest/autoload/auto9.vim new file mode 100644 index 00000000000000..c89ce3a33d5651 --- /dev/null +++ b/src/testdir/sautest/autoload/auto9.vim @@ -0,0 +1,9 @@ +vim9script + +func auto9#getsome() + return 'some' +endfunc + +def auto9#add42(count: number): number + return count + 42 +enddef diff --git a/src/testdir/test_autoload.vim b/src/testdir/test_autoload.vim index b8c4fa251f6734..57967bf64fb2cc 100644 --- a/src/testdir/test_autoload.vim +++ b/src/testdir/test_autoload.vim @@ -17,3 +17,8 @@ func Test_source_autoload() source sautest/autoload/sourced.vim call assert_equal(1, g:loaded_sourced_vim) endfunc + +func Test_autoload_vim9script() + call assert_equal('some', auto9#getsome()) + call assert_equal(49, auto9#add42(7)) +endfunc diff --git a/src/version.c b/src/version.c index 0734bdc1e343c2..02fa087806ef34 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1325, /**/ 1324, /**/ From 9d489566815d7913afc5dfc2a772bacede3970fb Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 30 Jul 2020 20:08:50 +0200 Subject: [PATCH 0039/1384] patch 8.2.1326: Vim9: skipping over white space after list Problem: Vim9: skipping over white space after list. Solution: Do not skip white space, a following [] would be misinterpreted. (closes #6552) Fix a few side effects. --- src/dict.c | 4 ++++ src/eval.c | 41 ++++++++++++++++++++++---------- src/list.c | 4 ++-- src/testdir/test_functions.vim | 2 +- src/testdir/test_gn.vim | 2 +- src/testdir/test_popupwin.vim | 2 +- src/testdir/test_tabpage.vim | 2 +- src/testdir/test_textobjects.vim | 34 +++++++++++++------------- src/testdir/test_textprop.vim | 2 +- src/userfunc.c | 4 ++++ src/version.c | 2 ++ 11 files changed, 62 insertions(+), 37 deletions(-) diff --git a/src/dict.c b/src/dict.c index eedaf42686ff22..019227f1054efb 100644 --- a/src/dict.c +++ b/src/dict.c @@ -838,6 +838,10 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal) : eval1(arg, &tvkey, evalarg)) == FAIL) // recursive! goto failret; + // The colon should come right after the key, but this wasn't checked + // previously, so only require it in Vim9 script. + if (!vim9script) + *arg = skipwhite(*arg); if (**arg != ':') { if (evaluate) diff --git a/src/eval.c b/src/eval.c index 451bb16b7c58d6..119b7cc189ac4c 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1913,27 +1913,28 @@ eval_func( char_u * eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext) { + char_u *p = skipwhite(arg); + *getnext = FALSE; if (in_vim9script() && evalarg != NULL && (evalarg->eval_cookie != NULL || evalarg->eval_cctx != NULL) - && (*arg == NUL || (VIM_ISWHITE(arg[-1]) - && vim9_comment_start(arg)))) + && (*p == NUL || (VIM_ISWHITE(p[-1]) && vim9_comment_start(p)))) { - char_u *p; + char_u *next; if (evalarg->eval_cookie != NULL) - p = getline_peek(evalarg->eval_getline, evalarg->eval_cookie); + next = getline_peek(evalarg->eval_getline, evalarg->eval_cookie); else - p = peek_next_line_from_context(evalarg->eval_cctx); + next = peek_next_line_from_context(evalarg->eval_cctx); - if (p != NULL) + if (next != NULL) { *getnext = TRUE; - return skipwhite(p); + return skipwhite(next); } } - return arg; + return p; } /* @@ -2039,6 +2040,7 @@ eval0( p = skipwhite(arg); ret = eval1(&p, rettv, evalarg); + p = skipwhite(p); if (ret == FAIL || !ends_excmd2(arg, p)) { @@ -2107,6 +2109,8 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) if (getnext) *arg = eval_next_line(evalarg_used); + else + *arg = p; result = FALSE; if (evaluate) @@ -2142,6 +2146,8 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) } if (getnext) *arg = eval_next_line(evalarg_used); + else + *arg = p; /* * Get the third variable. Recursive! @@ -2234,6 +2240,8 @@ eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg) { if (getnext) *arg = eval_next_line(evalarg_used); + else + *arg = p; /* * Get the second variable. @@ -2349,6 +2357,8 @@ eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg) { if (getnext) *arg = eval_next_line(evalarg_used); + else + *arg = p; /* * Get the second variable. @@ -2575,6 +2585,8 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg) if (getnext) *arg = eval_next_line(evalarg); + else + *arg = p; evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE); if ((op != '+' || (rettv->v_type != VAR_LIST && rettv->v_type != VAR_BLOB)) @@ -2756,6 +2768,7 @@ eval6( int evaluate; int getnext; typval_T var2; + char_u *p; int op; varnumber_T n1, n2; #ifdef FEAT_FLOAT @@ -2763,12 +2776,15 @@ eval6( #endif int error; - op = *eval_next_non_blank(*arg, evalarg, &getnext); + p = eval_next_non_blank(*arg, evalarg, &getnext); + op = *p; if (op != '*' && op != '/' && op != '%') break; if (getnext) *arg = eval_next_line(evalarg); + else + *arg = p; #ifdef FEAT_FLOAT f1 = 0; @@ -3115,8 +3131,6 @@ eval7( vim_free(alias); } - *arg = skipwhite(*arg); - // Handle following '[', '(' and '.' for expr[expr], expr.name, // expr(expr), expr->name(expr) if (ret == OK) @@ -5152,7 +5166,7 @@ handle_subscript( p = eval_next_non_blank(*arg, evalarg, &getnext); if (getnext && ((rettv->v_type == VAR_DICT && *p == '.' && eval_isdictc(p[1])) - || (*p == '-' && p[1] == '>' + || (p[0] == '-' && p[1] == '>' && (p[2] == '{' || ASCII_ISALPHA(p[2]))))) { *arg = eval_next_line(evalarg); @@ -5178,8 +5192,9 @@ handle_subscript( dict_unref(selfdict); selfdict = NULL; } - else if (**arg == '-' && (*arg)[1] == '>') + else if (p[0] == '-' && p[1] == '>') { + *arg = p; if (ret == OK) { if ((*arg)[2] == '{') diff --git a/src/list.c b/src/list.c index 9a334ae45bce72..5c2f60ef79981a 100644 --- a/src/list.c +++ b/src/list.c @@ -1199,7 +1199,7 @@ eval_list(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int do_error) had_comma = **arg == ','; if (had_comma) { - if (vim9script && (*arg)[1] != NUL && !VIM_ISWHITE((*arg)[1])) + if (vim9script && !IS_WHITE_OR_NUL((*arg)[1])) { semsg(_(e_white_after), ","); goto failret; @@ -1231,7 +1231,7 @@ eval_list(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int do_error) return FAIL; } - *arg = skipwhite(*arg + 1); + *arg += 1; if (evaluate) rettv_list_set(rettv, l); diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 9aa830b2f5bea4..7aaeeb7ae38954 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -1355,7 +1355,7 @@ func Test_input_func() func! Tcomplete(arglead, cmdline, pos) return "item1\nitem2\nitem3" endfunc - call feedkeys(":let c = input('Q? ', '' , 'custom,Tcomplete')\" + call feedkeys(":let c = input('Q? ', '', 'custom,Tcomplete')\" \ .. "\\", 'xt') delfunc Tcomplete call assert_equal('item1 item2 item3', c) diff --git a/src/testdir/test_gn.vim b/src/testdir/test_gn.vim index c72da925a3fde4..b90aa5f1d61753 100644 --- a/src/testdir/test_gn.vim +++ b/src/testdir/test_gn.vim @@ -120,7 +120,7 @@ func Test_gn_command() sil! %d_ " search using the \zs atom - call setline(1, [' nnoremap', '' , 'nnoremap']) + call setline(1, [' nnoremap', '', 'nnoremap']) set wrapscan&vim let @/ = '\_s\zsnnoremap' $ diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index 00b956a9e0dccb..30dfc6693acdc1 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -588,7 +588,7 @@ func Test_popup_drag_termwin() call setline(1, range(100)) for nr in range(7) call setline(nr * 12 + 1, "fold {{{") - call setline(nr * 12 + 11 , "end }}}") + call setline(nr * 12 + 11, "end }}}") endfor %foldclose set shell=/bin/sh noruler diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim index 33fdab47800379..bbcafa8eb6fd34 100644 --- a/src/testdir/test_tabpage.vim +++ b/src/testdir/test_tabpage.vim @@ -350,7 +350,7 @@ function Test_tabpage_with_tabprevious() call Check_tab_count(6, cmd . ' 3', 3) call Check_tab_count(6, cmd . ' 8', 4) for n in range(2) - for c in ['0', '.+3', '+', '+2' , '-', '-2' , '$', '+99', '-99'] + for c in ['0', '.+3', '+', '+2', '-', '-2', '$', '+99', '-99'] if n == 0 " pre count let entire_cmd = c . cmd let err_code = 'E16:' diff --git a/src/testdir/test_textobjects.vim b/src/testdir/test_textobjects.vim index 6eb6fbbf3ff8cb..54de3f89dce51c 100644 --- a/src/testdir/test_textobjects.vim +++ b/src/testdir/test_textobjects.vim @@ -201,28 +201,28 @@ func Test_match() call assert_equal("c", matchstr("abcd", ".", 2, 0)) call assert_equal("a", matchstr("abcd", ".", 0, -1)) call assert_equal(-1, match("abcd", ".", 0, 5)) - call assert_equal(0 , match("abcd", ".", 0, -1)) - call assert_equal(0 , match('abc', '.', 0, 1)) - call assert_equal(1 , match('abc', '.', 0, 2)) - call assert_equal(2 , match('abc', '.', 0, 3)) + call assert_equal(0, match("abcd", ".", 0, -1)) + call assert_equal(0, match('abc', '.', 0, 1)) + call assert_equal(1, match('abc', '.', 0, 2)) + call assert_equal(2, match('abc', '.', 0, 3)) call assert_equal(-1, match('abc', '.', 0, 4)) - call assert_equal(1 , match('abc', '.', 1, 1)) - call assert_equal(2 , match('abc', '.', 2, 1)) + call assert_equal(1, match('abc', '.', 1, 1)) + call assert_equal(2, match('abc', '.', 2, 1)) call assert_equal(-1, match('abc', '.', 3, 1)) - call assert_equal(3 , match('abc', '$', 0, 1)) + call assert_equal(3, match('abc', '$', 0, 1)) call assert_equal(-1, match('abc', '$', 0, 2)) - call assert_equal(3 , match('abc', '$', 1, 1)) - call assert_equal(3 , match('abc', '$', 2, 1)) - call assert_equal(3 , match('abc', '$', 3, 1)) + call assert_equal(3, match('abc', '$', 1, 1)) + call assert_equal(3, match('abc', '$', 2, 1)) + call assert_equal(3, match('abc', '$', 3, 1)) call assert_equal(-1, match('abc', '$', 4, 1)) - call assert_equal(0 , match('abc', '\zs', 0, 1)) - call assert_equal(1 , match('abc', '\zs', 0, 2)) - call assert_equal(2 , match('abc', '\zs', 0, 3)) - call assert_equal(3 , match('abc', '\zs', 0, 4)) + call assert_equal(0, match('abc', '\zs', 0, 1)) + call assert_equal(1, match('abc', '\zs', 0, 2)) + call assert_equal(2, match('abc', '\zs', 0, 3)) + call assert_equal(3, match('abc', '\zs', 0, 4)) call assert_equal(-1, match('abc', '\zs', 0, 5)) - call assert_equal(1 , match('abc', '\zs', 1, 1)) - call assert_equal(2 , match('abc', '\zs', 2, 1)) - call assert_equal(3 , match('abc', '\zs', 3, 1)) + call assert_equal(1, match('abc', '\zs', 1, 1)) + call assert_equal(2, match('abc', '\zs', 2, 1)) + call assert_equal(3, match('abc', '\zs', 3, 1)) call assert_equal(-1, match('abc', '\zs', 4, 1)) endfunc diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim index d5f67b49bea628..9db5275d5219d6 100644 --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -1219,7 +1219,7 @@ func Test_prop_func_invalid_args() call assert_fails('call prop_find({}, "x")', 'E474:') call assert_fails('call prop_find({"lnum" : -2})', 'E16:') call assert_fails('call prop_list(1, [])', 'E715:') - call assert_fails('call prop_list(-1 , {})', 'E16:') + call assert_fails('call prop_list(-1, {})', 'E16:') call assert_fails('call prop_remove([])', 'E474:') call assert_fails('call prop_remove({}, -2)', 'E16:') call assert_fails('call prop_remove({})', 'E968:') diff --git a/src/userfunc.c b/src/userfunc.c index 343c9cd2e1dd22..de0cdb7ea51c98 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -642,6 +642,10 @@ get_func_tv( break; } ++argcount; + // The comma should come right after the argument, but this wasn't + // checked previously, thus only enforce it in Vim9 script. + if (!in_vim9script()) + argp = skipwhite(argp); if (*argp != ',') break; } diff --git a/src/version.c b/src/version.c index 02fa087806ef34..c37fbe46fc281a 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1326, /**/ 1325, /**/ From f4ee528086dcff2b8744544c440853f177956261 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 30 Jul 2020 20:18:08 +0200 Subject: [PATCH 0040/1384] patch 8.2.1327: Mac: configure can't find Tcl libraries Problem: Mac: configure can't find Tcl libraries. Solution: Adjust configure check. (closes #6575) --- src/auto/configure | 5 +++-- src/configure.ac | 9 +++++++-- src/version.c | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/auto/configure b/src/auto/configure index 41b29c2623fe84..54ee35d87a5d4c 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -7417,7 +7417,7 @@ $as_echo_n "checking for location of Tcl include... " >&6; } if test "x$MACOS_X" != "xyes"; then tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/local/include/tcl$tclver /usr/include /usr/include/tcl$tclver" else - tclinc="/System/Library/Frameworks/Tcl.framework/Headers" + tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /System/Library/Frameworks/Tcl.framework/Headers `xcrun --show-sdk-path`/System/Library/Frameworks/Tcl.framework/Versions/Current/Headers" fi TCL_INC= for try in $tclinc; do @@ -7440,7 +7440,8 @@ $as_echo_n "checking for location of tclConfig.sh script... " >&6; } tclcnf=`echo $tclinc | sed s/include/lib/g` tclcnf="$tclcnf `echo $tclinc | sed s/include/lib64/g`" else - tclcnf="/System/Library/Frameworks/Tcl.framework" + tclcnf=`echo $tclinc | sed s/include/lib/g` + tclcnf="$tclcnf /System/Library/Frameworks/Tcl.framework `xcrun --show-sdk-path`/System/Library/Frameworks/Tcl.framework" fi for try in $tclcnf; do if test -f "$try/tclConfig.sh"; then diff --git a/src/configure.ac b/src/configure.ac index 598d73c8dfc496..054ea1dcb8d11f 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -1820,8 +1820,10 @@ if test "$enable_tclinterp" = "yes" -o "$enable_tclinterp" = "dynamic"; then if test "x$MACOS_X" != "xyes"; then tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/local/include/tcl$tclver /usr/include /usr/include/tcl$tclver" else + dnl For all macOS, use the value from TCL in case use of, say, homebrew dnl For Mac OS X 10.3, use the OS-provided framework location - tclinc="/System/Library/Frameworks/Tcl.framework/Headers" + dnl For Mac OS X 10.14, the OS-provided framework location doesn't contain the headers, so also check the Xcode SDK + tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /System/Library/Frameworks/Tcl.framework/Headers `xcrun --show-sdk-path`/System/Library/Frameworks/Tcl.framework/Versions/Current/Headers" fi TCL_INC= for try in $tclinc; do @@ -1841,8 +1843,11 @@ if test "$enable_tclinterp" = "yes" -o "$enable_tclinterp" = "dynamic"; then tclcnf=`echo $tclinc | sed s/include/lib/g` tclcnf="$tclcnf `echo $tclinc | sed s/include/lib64/g`" else + dnl For all macOS, use the value from TCL in case use of, say, homebrew dnl For Mac OS X 10.3, use the OS-provided framework location - tclcnf="/System/Library/Frameworks/Tcl.framework" + dnl For Mac OS X 10.14, the OS-provided framework location doesn't contain the headers, so also check the Xcode SDK + tclcnf=`echo $tclinc | sed s/include/lib/g` + tclcnf="$tclcnf /System/Library/Frameworks/Tcl.framework `xcrun --show-sdk-path`/System/Library/Frameworks/Tcl.framework" fi for try in $tclcnf; do if test -f "$try/tclConfig.sh"; then diff --git a/src/version.c b/src/version.c index c37fbe46fc281a..806e064f5740e3 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1327, /**/ 1326, /**/ From 4d4d1cd5c8b61ef0296bd6190ca2a0b2d6d96ba7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 30 Jul 2020 22:14:33 +0200 Subject: [PATCH 0041/1384] patch 8.2.1328: no space allowed before comma in list Problem: No space allowed before comma in list. Solution: Legacy Vim script allows it. (closes #6577) --- src/dict.c | 7 +++++-- src/list.c | 3 +++ src/testdir/test_listdict.vim | 7 +++++++ src/version.c | 2 ++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/dict.c b/src/dict.c index 019227f1054efb..af1e1e9c8bfbd6 100644 --- a/src/dict.c +++ b/src/dict.c @@ -838,7 +838,7 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal) : eval1(arg, &tvkey, evalarg)) == FAIL) // recursive! goto failret; - // The colon should come right after the key, but this wasn't checked + // the colon should come right after the key, but this wasn't checked // previously, so only require it in Vim9 script. if (!vim9script) *arg = skipwhite(*arg); @@ -895,7 +895,10 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal) } clear_tv(&tvkey); - // the comma must come after the value + // the comma should come right after the value, but this wasn't checked + // previously, so only require it in Vim9 script. + if (!vim9script) + *arg = skipwhite(*arg); had_comma = **arg == ','; if (had_comma) { diff --git a/src/list.c b/src/list.c index 5c2f60ef79981a..14a31bcfb71b43 100644 --- a/src/list.c +++ b/src/list.c @@ -1194,6 +1194,9 @@ eval_list(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int do_error) else clear_tv(&tv); } + // Legacy Vim script allowed a space before the comma. + if (!vim9script) + *arg = skipwhite(*arg); // the comma must come after the value had_comma = **arg == ','; diff --git a/src/testdir/test_listdict.vim b/src/testdir/test_listdict.vim index beeda2f5bb598b..563c79f0d38fea 100644 --- a/src/testdir/test_listdict.vim +++ b/src/testdir/test_listdict.vim @@ -23,6 +23,9 @@ func Test_list_create() call assert_equal(10, x) endfunc +" This was allowed in legacy Vim script +let s:list_with_spaces = [1 , 2 , 3] + " List slices func Test_list_slice() let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] @@ -202,6 +205,10 @@ func Test_dict() call assert_fails("let d={'k' : i}", 'E121:') endfunc +" This was allowed in legacy Vim script +let s:dict_with_spaces = {'one' : 1 , 'two' : 2 , 'three' : 3} +let s:dict_with_spaces_lit = #{one : 1 , two : 2 , three : 3} + " Dictionary identity func Test_dict_identity() let d = {001: 'asd', 'b': [1, 2, function('strlen')], -1: {'a': 1},} diff --git a/src/version.c b/src/version.c index 806e064f5740e3..6a939f4c9b24d7 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1328, /**/ 1327, /**/ From 38ddf333f6b2806b0ea2dd052ee1cd50dd7f4525 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 31 Jul 2020 22:05:04 +0200 Subject: [PATCH 0042/1384] patch 8.2.1329: Vim9: cannot define global function inside :def function Problem: Vim9: cannot define global function inside :def function. Solution: Assign to global variable instead of local. (closes #6584) --- src/misc2.c | 35 +++++++++++ src/proto/misc2.pro | 1 + src/proto/userfunc.pro | 1 + src/structs.h | 2 + src/testdir/test_vim9_disassemble.vim | 18 ++++++ src/testdir/test_vim9_func.vim | 22 +++++++ src/userfunc.c | 83 +++++++++++++++++++++++++-- src/version.c | 2 + src/vim9.h | 8 +++ src/vim9compile.c | 56 +++++++++++++++--- src/vim9execute.c | 21 +++++++ 11 files changed, 237 insertions(+), 12 deletions(-) diff --git a/src/misc2.c b/src/misc2.c index 7ef6cdf44d03f8..3e16c3633d941a 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -2027,6 +2027,41 @@ ga_clear_strings(garray_T *gap) ga_clear(gap); } +/* + * Copy a growing array that contains a list of strings. + */ + int +ga_copy_strings(garray_T *from, garray_T *to) +{ + int i; + + ga_init2(to, sizeof(char_u *), 1); + if (ga_grow(to, from->ga_len) == FAIL) + return FAIL; + + for (i = 0; i < from->ga_len; ++i) + { + char_u *orig = ((char_u **)from->ga_data)[i]; + char_u *copy; + + if (orig == NULL) + copy = NULL; + else + { + copy = vim_strsave(orig); + if (copy == NULL) + { + to->ga_len = i; + ga_clear_strings(to); + return FAIL; + } + } + ((char_u **)to->ga_data)[i] = copy; + } + to->ga_len = from->ga_len; + return OK; +} + /* * Initialize a growing array. Don't forget to set ga_itemsize and * ga_growsize! Or use ga_init2(). diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro index e1e20aaab17ce5..d55fc31c399577 100644 --- a/src/proto/misc2.pro +++ b/src/proto/misc2.pro @@ -56,6 +56,7 @@ char_u *vim_strrchr(char_u *string, int c); int vim_isspace(int x); void ga_clear(garray_T *gap); void ga_clear_strings(garray_T *gap); +int ga_copy_strings(garray_T *from, garray_T *to); void ga_init(garray_T *gap); void ga_init2(garray_T *gap, int itemsize, int growsize); int ga_grow(garray_T *gap, int n); diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro index 9c9eb2df7a832b..f30ac2f219c008 100644 --- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -5,6 +5,7 @@ int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, garray_T char_u *get_lambda_name(void); char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state); int get_lambda_tv(char_u **arg, typval_T *rettv, evalarg_T *evalarg); +void copy_func(char_u *lambda, char_u *global); char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload); void emsg_funcname(char *ermsg, char_u *name); int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, evalarg_T *evalarg, funcexe_T *funcexe); diff --git a/src/structs.h b/src/structs.h index ba9c98db0f5d0e..7e34d809981bde 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1546,6 +1546,7 @@ typedef enum { /* * Structure to hold info for a user function. + * When adding a field check copy_func(). */ typedef struct { @@ -1618,6 +1619,7 @@ typedef struct #define FC_NOARGS 0x200 // no a: variables in lambda #define FC_VIM9 0x400 // defined in vim9 script file #define FC_CFUNC 0x800 // defined as Lua C func +#define FC_COPY 0x1000 // copy of another function by copy_func() #define MAX_FUNC_ARGS 20 // maximum number of function arguments #define VAR_SHORT_LEN 20 // short variable name length diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 98a9e207e5a80d..ea012b744e9842 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -699,6 +699,24 @@ def Test_disassemble_lambda() instr) enddef +def NestedOuter() + def g:Inner() + echomsg "inner" + enddef +enddef + +def Test_nested_func() + let instr = execute('disassemble NestedOuter') + assert_match('NestedOuter\_s*' .. + 'def g:Inner()\_s*' .. + 'echomsg "inner"\_s*' .. + 'enddef\_s*' .. + '\d NEWFUNC \d\+ Inner\_s*' .. + '\d PUSHNR 0\_s*' .. + '\d RETURN', + instr) +enddef + def AndOr(arg: any): string if arg == 1 && arg != 2 || arg == 4 return 'yes' diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 2546f1369fdda8..dae64429d9b369 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -133,6 +133,28 @@ def Test_nested_function() CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:') enddef +def Test_nested_global_function() + let lines =<< trim END + vim9script + def Outer() + def g:Inner(): string + return 'inner' + enddef + enddef + disass Outer + Outer() + assert_equal('inner', g:Inner()) + delfunc g:Inner + Outer() + assert_equal('inner', g:Inner()) + delfunc g:Inner + Outer() + assert_equal('inner', g:Inner()) + delfunc g:Inner + END + CheckScriptSuccess(lines) +enddef + func Test_call_default_args_from_func() call assert_equal('string', MyDefaultArgs()) call assert_equal('one', MyDefaultArgs('one')) diff --git a/src/userfunc.c b/src/userfunc.c index de0cdb7ea51c98..de7034df821391 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -366,7 +366,7 @@ register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state) if (fp == NULL) return NULL; - fp->uf_dfunc_idx = UF_NOT_COMPILED; + fp->uf_def_status = UF_NOT_COMPILED; fp->uf_refcount = 1; fp->uf_varargs = TRUE; fp->uf_flags = FC_CFUNC; @@ -1069,7 +1069,8 @@ func_remove(ufunc_T *fp) { // When there is a def-function index do not actually remove the // function, so we can find the index when defining the function again. - if (fp->uf_def_status == UF_COMPILED) + // Do remove it when it's a copy. + if (fp->uf_def_status == UF_COMPILED && (fp->uf_flags & FC_COPY) == 0) fp->uf_flags |= FC_DEAD; else hash_remove(&func_hashtab, hi); @@ -1122,7 +1123,8 @@ func_clear(ufunc_T *fp, int force) // clear this function func_clear_items(fp); funccal_unref(fp->uf_scoped, fp, force); - clear_def_function(fp); + if ((fp->uf_flags & FC_COPY) == 0) + clear_def_function(fp); } /* @@ -1150,12 +1152,83 @@ func_free(ufunc_T *fp, int force) func_clear_free(ufunc_T *fp, int force) { func_clear(fp, force); - if (force || fp->uf_dfunc_idx == 0) + if (force || fp->uf_dfunc_idx == 0 || (fp->uf_flags & FC_COPY)) func_free(fp, force); else fp->uf_flags |= FC_DEAD; } +/* + * Copy already defined function "lambda" to a new function with name "global". + * This is for when a compiled function defines a global function. + */ + void +copy_func(char_u *lambda, char_u *global) +{ + ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL); + ufunc_T *fp; + + if (ufunc == NULL) + semsg(_("E1102: lambda function not found: %s"), lambda); + else + { + // TODO: handle ! to overwrite + fp = find_func(global, TRUE, NULL); + if (fp != NULL) + { + semsg(_(e_funcexts), global); + return; + } + + fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(global) + 1); + if (fp == NULL) + return; + + fp->uf_varargs = ufunc->uf_varargs; + fp->uf_flags = (ufunc->uf_flags & ~FC_VIM9) | FC_COPY; + fp->uf_def_status = ufunc->uf_def_status; + fp->uf_dfunc_idx = ufunc->uf_dfunc_idx; + if (ga_copy_strings(&fp->uf_args, &ufunc->uf_args) == FAIL + || ga_copy_strings(&fp->uf_def_args, &ufunc->uf_def_args) + == FAIL + || ga_copy_strings(&fp->uf_lines, &ufunc->uf_lines) == FAIL) + goto failed; + + fp->uf_name_exp = ufunc->uf_name_exp == NULL ? NULL + : vim_strsave(ufunc->uf_name_exp); + if (ufunc->uf_arg_types != NULL) + { + fp->uf_arg_types = ALLOC_MULT(type_T *, fp->uf_args.ga_len); + if (fp->uf_arg_types == NULL) + goto failed; + mch_memmove(fp->uf_arg_types, ufunc->uf_arg_types, + sizeof(type_T *) * fp->uf_args.ga_len); + } + if (ufunc->uf_def_arg_idx != NULL) + { + fp->uf_def_arg_idx = ALLOC_MULT(int, fp->uf_def_args.ga_len + 1); + if (fp->uf_def_arg_idx == NULL) + goto failed; + mch_memmove(fp->uf_def_arg_idx, ufunc->uf_def_arg_idx, + sizeof(int) * fp->uf_def_args.ga_len + 1); + } + if (ufunc->uf_va_name != NULL) + { + fp->uf_va_name = vim_strsave(ufunc->uf_va_name); + if (fp->uf_va_name == NULL) + goto failed; + } + + fp->uf_refcount = 1; + STRCPY(fp->uf_name, global); + hash_add(&func_hashtab, UF2HIKEY(fp)); + } + return; + +failed: + func_clear_free(fp, TRUE); +} + /* * Call a user function. @@ -2521,6 +2594,8 @@ list_functions(regmatch_T *regmatch) /* * ":function" also supporting nested ":def". + * When "name_arg" is not NULL this is a nested function, using "name_arg" for + * the function name. * Returns a pointer to the function or NULL if no function defined. */ ufunc_T * diff --git a/src/version.c b/src/version.c index 6a939f4c9b24d7..75232bf37c8383 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1329, /**/ 1328, /**/ diff --git a/src/vim9.h b/src/vim9.h index 0d51c98b5d35db..77f34271284ade 100644 --- a/src/vim9.h +++ b/src/vim9.h @@ -79,6 +79,7 @@ typedef enum { ISN_PCALL_END, // cleanup after ISN_PCALL with cpf_top set ISN_RETURN, // return, result is on top of stack ISN_FUNCREF, // push a function ref to dfunc isn_arg.funcref + ISN_NEWFUNC, // create a global function from a lambda function // expression operations ISN_JUMP, // jump if condition is matched isn_arg.jump @@ -237,6 +238,12 @@ typedef struct { int fr_var_idx; // variable to store partial } funcref_T; +// arguments to ISN_NEWFUNC +typedef struct { + char_u *nf_lambda; // name of the lambda already defined + char_u *nf_global; // name of the global function to be created +} newfunc_T; + // arguments to ISN_CHECKLEN typedef struct { int cl_min_len; // minimum length @@ -281,6 +288,7 @@ struct isn_S { script_T script; unlet_T unlet; funcref_T funcref; + newfunc_T newfunc; checklen_T checklen; shuffle_T shuffle; } isn_arg; diff --git a/src/vim9compile.c b/src/vim9compile.c index cf08e955844135..b9b2b6fa526cb3 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1522,6 +1522,27 @@ generate_FUNCREF(cctx_T *cctx, int dfunc_idx) return OK; } +/* + * Generate an ISN_NEWFUNC instruction. + */ + static int +generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name) +{ + isn_T *isn; + char_u *name; + + RETURN_OK_IF_SKIP(cctx); + name = vim_strsave(lambda_name); + if (name == NULL) + return FAIL; + if ((isn = generate_instr(cctx, ISN_NEWFUNC)) == NULL) + return FAIL; + isn->isn_arg.newfunc.nf_lambda = name; + isn->isn_arg.newfunc.nf_global = func_name; + + return OK; +} + /* * Generate an ISN_JUMP instruction. */ @@ -4875,11 +4896,13 @@ exarg_getline( static char_u * compile_nested_function(exarg_T *eap, cctx_T *cctx) { + int is_global = *eap->arg == 'g' && eap->arg[1] == ':'; char_u *name_start = eap->arg; - char_u *name_end = to_name_end(eap->arg, FALSE); + char_u *name_end = to_name_end(eap->arg, is_global); char_u *name = get_lambda_name(); lvar_T *lvar; ufunc_T *ufunc; + int r; eap->arg = name_end; eap->getline = exarg_getline; @@ -4894,16 +4917,28 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) && compile_def_function(ufunc, TRUE, cctx) == FAIL) return NULL; - // Define a local variable for the function reference. - lvar = reserve_local(cctx, name_start, name_end - name_start, - TRUE, ufunc->uf_func_type); + if (is_global) + { + char_u *func_name = vim_strnsave(name_start + 2, + name_end - name_start - 2); - if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL - || generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL) == FAIL) - return NULL; + if (func_name == NULL) + r = FAIL; + else + r = generate_NEWFUNC(cctx, name, func_name); + } + else + { + // Define a local variable for the function reference. + lvar = reserve_local(cctx, name_start, name_end - name_start, + TRUE, ufunc->uf_func_type); + if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL) + return NULL; + r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL); + } // TODO: warning for trailing text? - return (char_u *)""; + return r == FAIL ? NULL : (char_u *)""; } /* @@ -7641,6 +7676,11 @@ delete_instr(isn_T *isn) } break; + case ISN_NEWFUNC: + vim_free(isn->isn_arg.newfunc.nf_lambda); + vim_free(isn->isn_arg.newfunc.nf_global); + break; + case ISN_2BOOL: case ISN_2STRING: case ISN_ADDBLOB: diff --git a/src/vim9execute.c b/src/vim9execute.c index e52df61ac136d1..9bfec3af121375 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -723,7 +723,10 @@ call_def_function( dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; if (dfunc->df_instr == NULL) + { + iemsg("using call_def_function() on not compiled function"); return FAIL; + } } CLEAR_FIELD(ectx); @@ -1726,6 +1729,15 @@ call_def_function( } break; + // Create a global function from a lambda. + case ISN_NEWFUNC: + { + newfunc_T *newfunc = &iptr->isn_arg.newfunc; + + copy_func(newfunc->nf_lambda, newfunc->nf_global); + } + break; + // jump if a condition is met case ISN_JUMP: { @@ -2912,6 +2924,15 @@ ex_disassemble(exarg_T *eap) } break; + case ISN_NEWFUNC: + { + newfunc_T *newfunc = &iptr->isn_arg.newfunc; + + smsg("%4d NEWFUNC %s %s", current, + newfunc->nf_lambda, newfunc->nf_global); + } + break; + case ISN_JUMP: { char *when = "?"; From 3a53ec8bdddccf06a0e9db263277c50a6015294d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 31 Jul 2020 22:17:32 +0200 Subject: [PATCH 0043/1384] patch 8.2.1330: Github workflow takes longer than needed Problem: Github workflow takes longer than needed. Solution: Do two test runs in parallel instead of sequentially. (Ken Takata, closes #6579) --- .github/workflows/ci-windows.yaml | 33 +++++++++++++++++++++---------- src/version.c | 2 ++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci-windows.yaml b/.github/workflows/ci-windows.yaml index 68b5480b0e8755..dbc9007534d06f 100644 --- a/.github/workflows/ci-windows.yaml +++ b/.github/workflows/ci-windows.yaml @@ -195,16 +195,29 @@ jobs: echo. echo %COL_GREEN%vim version:%COL_RESET% .\vim --version || exit 1 - cd testdir + + mkdir ..\src2 + xcopy testdir ..\src2\testdir\ /E > nul || exit 1 + copy evalfunc.c ..\src2 > nul + + echo %COL_GREEN%Start testing vim in background.%COL_RESET% + start cmd /c "cd ..\src2\testdir & nmake -nologo -f Make_dos.mak VIMPROG=..\..\src\vim > nul & echo done>done.txt" + echo %COL_GREEN%Test gvim:%COL_RESET% + cd testdir nmake -nologo -f Make_dos.mak VIMPROG=..\gvim || exit 1 - nmake -nologo -f Make_dos.mak clean - echo %COL_GREEN%Test vim:%COL_RESET% - if "${{ matrix.toolchain }}-${{ matrix.arch }}"=="msvc-x64" ( - rem This test may hang up unless it is executed in a separate console. - start /wait cmd /c "nmake -nologo -f Make_dos.mak VIMPROG=..\vim > nul" - if exist messages type messages - nmake -nologo -f Make_dos.mak report || exit 1 - ) else ( - nmake -nologo -f Make_dos.mak VIMPROG=..\vim || exit 1 + cd .. + + echo %COL_GREEN%Wait for vim tests to finish.%COL_RESET% + cd ..\src2\testdir + :: Wait about 5 minutes. + for /L %%i in (1,1,300) do ( + if exist done.txt goto exitloop + ping -n 2 localhost > nul ) + echo %COL_RED%Timed out.%COL_RESET% + :exitloop + + echo %COL_GREEN%Test results of vim:%COL_RESET% + if exist messages type messages + nmake -nologo -f Make_dos.mak report VIMPROG=..\..\src\vim || exit 1 diff --git a/src/version.c b/src/version.c index 75232bf37c8383..b52bd2f5082e6f 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1330, /**/ 1329, /**/ From badd8486f7442bfcf55e0234ece80488958e7114 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 31 Jul 2020 22:38:17 +0200 Subject: [PATCH 0044/1384] patch 8.2.1331: Vim9: :echo with two lists doesn't work Problem: Vim9: :echo with two lists doesn't work. Solution: Do not skip white space before []. (closes #6552) --- src/testdir/test_vim9_expr.vim | 8 ++++++++ src/version.c | 2 ++ src/vim9compile.c | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 550e4198263632..226db83f8086b5 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1176,6 +1176,10 @@ def Test_expr7_list() assert_equal(g:list_mixed, [1, 'b', false,]) assert_equal('b', g:list_mixed[1]) + echo [1, + 2] [3, + 4] + call CheckDefExecFailure(["let x = g:anint[3]"], 'E714:') call CheckDefFailure(["let x = g:list_mixed[xxx]"], 'E1001:') call CheckDefFailure(["let x = [1,2,3]"], 'E1069:') @@ -1193,6 +1197,10 @@ def Test_expr7_list_vim9script() 22, ] assert_equal([11, 22], l) + + echo [1, + 2] [3, + 4] END CheckScriptSuccess(lines) diff --git a/src/version.c b/src/version.c index b52bd2f5082e6f..225674268c326b 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1331, /**/ 1330, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index b9b2b6fa526cb3..87a9fd1ce9dc91 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3855,7 +3855,7 @@ compile_subscript( return FAIL; } } - else if (*p == '[') + else if (**arg == '[') { garray_T *stack = &cctx->ctx_type_stack; type_T **typep; From ce6583568ff5b3e0e6438b37ede2c80bedffba10 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 31 Jul 2020 23:47:12 +0200 Subject: [PATCH 0045/1384] patch 8.2.1332: Vim9: memory leak when using nested global function Problem: Vim9: memory leak when using nested global function. Solution: Delete the function when deleting the instruction. Disable test that still causes a leak. --- src/proto/userfunc.pro | 3 ++- src/testdir/test_vim9_func.vim | 19 +++++++++---------- src/userfunc.c | 33 +++++++++++++++++++++------------ src/version.c | 2 ++ src/vim9compile.c | 17 +++++++++++++++-- 5 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro index f30ac2f219c008..2c4cbd5d364c56 100644 --- a/src/proto/userfunc.pro +++ b/src/proto/userfunc.pro @@ -5,12 +5,13 @@ int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, garray_T char_u *get_lambda_name(void); char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state); int get_lambda_tv(char_u **arg, typval_T *rettv, evalarg_T *evalarg); -void copy_func(char_u *lambda, char_u *global); char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload); void emsg_funcname(char *ermsg, char_u *name); int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, evalarg_T *evalarg, funcexe_T *funcexe); char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error); +ufunc_T *find_func_even_dead(char_u *name, int is_global, cctx_T *cctx); ufunc_T *find_func(char_u *name, int is_global, cctx_T *cctx); +void copy_func(char_u *lambda, char_u *global); int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict); void save_funccal(funccal_entry_T *entry); void restore_funccal(void); diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index dae64429d9b369..28937a1ddd8af9 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -141,16 +141,15 @@ def Test_nested_global_function() return 'inner' enddef enddef - disass Outer - Outer() - assert_equal('inner', g:Inner()) - delfunc g:Inner - Outer() - assert_equal('inner', g:Inner()) - delfunc g:Inner - Outer() - assert_equal('inner', g:Inner()) - delfunc g:Inner +# Outer() +# assert_equal('inner', g:Inner()) +# delfunc g:Inner +# Outer() +# assert_equal('inner', g:Inner()) +# delfunc g:Inner +# Outer() +# assert_equal('inner', g:Inner()) +# delfunc g:Inner END CheckScriptSuccess(lines) enddef diff --git a/src/userfunc.c b/src/userfunc.c index de7034df821391..cdce0056058e2d 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -780,7 +780,7 @@ find_func_with_sid(char_u *name, int sid) * When "is_global" is true don't find script-local or imported functions. * Return NULL for unknown function. */ - static ufunc_T * + ufunc_T * find_func_even_dead(char_u *name, int is_global, cctx_T *cctx) { hashitem_T *hi; @@ -1759,7 +1759,7 @@ delete_script_functions(int sid) { hashitem_T *hi; ufunc_T *fp; - long_u todo; + long_u todo = 1; char_u buf[30]; size_t len; @@ -1769,18 +1769,27 @@ delete_script_functions(int sid) sprintf((char *)buf + 3, "%d_", sid); len = STRLEN(buf); - todo = func_hashtab.ht_used; - for (hi = func_hashtab.ht_array; todo > 0; ++hi) - if (!HASHITEM_EMPTY(hi)) - { - fp = HI2UF(hi); - if (STRNCMP(fp->uf_name, buf, len) == 0) + while (todo > 0) + { + todo = func_hashtab.ht_used; + for (hi = func_hashtab.ht_array; todo > 0; ++hi) + if (!HASHITEM_EMPTY(hi)) { - fp->uf_flags |= FC_DEAD; - func_clear(fp, TRUE); + fp = HI2UF(hi); + if (STRNCMP(fp->uf_name, buf, len) == 0) + { + int changed = func_hashtab.ht_changed; + + fp->uf_flags |= FC_DEAD; + func_clear(fp, TRUE); + // When clearing a function another function can be cleared + // as a side effect. When that happens start over. + if (changed != func_hashtab.ht_changed) + break; + } + --todo; } - --todo; - } + } } #if defined(EXITFREE) || defined(PROTO) diff --git a/src/version.c b/src/version.c index 225674268c326b..dd7539e44b12f8 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1332, /**/ 1331, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 87a9fd1ce9dc91..688f42a9de109b 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -7677,8 +7677,21 @@ delete_instr(isn_T *isn) break; case ISN_NEWFUNC: - vim_free(isn->isn_arg.newfunc.nf_lambda); - vim_free(isn->isn_arg.newfunc.nf_global); + { + char_u *lambda = isn->isn_arg.newfunc.nf_lambda; + ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL); + + if (ufunc != NULL) + { + // Clear uf_dfunc_idx so that the function is deleted. + clear_def_function(ufunc); + ufunc->uf_dfunc_idx = 0; + func_ptr_unref(ufunc); + } + + vim_free(lambda); + vim_free(isn->isn_arg.newfunc.nf_global); + } break; case ISN_2BOOL: From af8edbb8dc551aaf2105a4d77b3d8495da239ef0 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 00:03:09 +0200 Subject: [PATCH 0046/1384] patch 8.2.1333: Vim9: memory leak when using nested global function Problem: Vim9: memory leak when using nested global function. Solution: Swap from and to when copying the lines. --- src/testdir/test_vim9_func.vim | 31 ++++++++++++++++--------------- src/userfunc.c | 6 +++--- src/version.c | 2 ++ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 28937a1ddd8af9..7298d9a7349160 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -133,6 +133,12 @@ def Test_nested_function() CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:') enddef +func Test_call_default_args_from_func() + call assert_equal('string', MyDefaultArgs()) + call assert_equal('one', MyDefaultArgs('one')) + call assert_fails('call MyDefaultArgs("one", "two")', 'E118:') +endfunc + def Test_nested_global_function() let lines =<< trim END vim9script @@ -141,25 +147,20 @@ def Test_nested_global_function() return 'inner' enddef enddef -# Outer() -# assert_equal('inner', g:Inner()) -# delfunc g:Inner -# Outer() -# assert_equal('inner', g:Inner()) -# delfunc g:Inner -# Outer() -# assert_equal('inner', g:Inner()) -# delfunc g:Inner + defcompile + Outer() + assert_equal('inner', g:Inner()) + delfunc g:Inner + Outer() + assert_equal('inner', g:Inner()) + delfunc g:Inner + Outer() + assert_equal('inner', g:Inner()) + delfunc g:Inner END CheckScriptSuccess(lines) enddef -func Test_call_default_args_from_func() - call assert_equal('string', MyDefaultArgs()) - call assert_equal('one', MyDefaultArgs('one')) - call assert_fails('call MyDefaultArgs("one", "two")', 'E118:') -endfunc - func TakesOneArg(arg) echo a:arg endfunc diff --git a/src/userfunc.c b/src/userfunc.c index cdce0056058e2d..4c1e2619522d0b 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -1188,10 +1188,10 @@ copy_func(char_u *lambda, char_u *global) fp->uf_flags = (ufunc->uf_flags & ~FC_VIM9) | FC_COPY; fp->uf_def_status = ufunc->uf_def_status; fp->uf_dfunc_idx = ufunc->uf_dfunc_idx; - if (ga_copy_strings(&fp->uf_args, &ufunc->uf_args) == FAIL - || ga_copy_strings(&fp->uf_def_args, &ufunc->uf_def_args) + if (ga_copy_strings(&ufunc->uf_args, &fp->uf_args) == FAIL + || ga_copy_strings(&ufunc->uf_def_args, &fp->uf_def_args) == FAIL - || ga_copy_strings(&fp->uf_lines, &ufunc->uf_lines) == FAIL) + || ga_copy_strings(&ufunc->uf_lines, &fp->uf_lines) == FAIL) goto failed; fp->uf_name_exp = ufunc->uf_name_exp == NULL ? NULL diff --git a/src/version.c b/src/version.c index dd7539e44b12f8..577a44bd6703fd 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1333, /**/ 1332, /**/ From b53da7918c643ef4de1256c37bc8b92413e6dcec Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 12:26:04 +0200 Subject: [PATCH 0047/1384] patch 8.2.1334: Github workflow timeout needs tuning Problem: Github workflow timeout needs tuning Solution: Use a 10 minute timeout. Fail when timing out. (Ken Takata, closes #6590) --- .github/workflows/ci-windows.yaml | 10 +++++++--- src/version.c | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-windows.yaml b/.github/workflows/ci-windows.yaml index dbc9007534d06f..d23beef4148b4b 100644 --- a/.github/workflows/ci-windows.yaml +++ b/.github/workflows/ci-windows.yaml @@ -210,14 +210,18 @@ jobs: echo %COL_GREEN%Wait for vim tests to finish.%COL_RESET% cd ..\src2\testdir - :: Wait about 5 minutes. - for /L %%i in (1,1,300) do ( + :: Wait about 10 minutes. + for /L %%i in (1,1,600) do ( if exist done.txt goto exitloop ping -n 2 localhost > nul ) - echo %COL_RED%Timed out.%COL_RESET% + set timeout=1 :exitloop echo %COL_GREEN%Test results of vim:%COL_RESET% if exist messages type messages nmake -nologo -f Make_dos.mak report VIMPROG=..\..\src\vim || exit 1 + if "%timeout%"=="1" ( + echo %COL_RED%Timed out.%COL_RESET% + exit 1 + ) diff --git a/src/version.c b/src/version.c index 577a44bd6703fd..f65d0fe6e38d49 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1334, /**/ 1333, /**/ From 4e1d8bd79b87b120bd40afe0eba54a419f8c3aee Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 13:10:14 +0200 Subject: [PATCH 0048/1384] patch 8.2.1335: CTRL-C in the GUI doesn't interrupt Problem: CTRL-C in the GUI doesn't interrupt. (Sergey Vlasov) Solution: Recognize "C" with CTRL modifier as CTRL-C. (issue #6565) --- src/gui.c | 21 +++++++++++++++++++++ src/gui_gtk_x11.c | 13 +++++++++---- src/gui_photon.c | 14 ++++++++++---- src/gui_x11.c | 16 +++++++++------- src/proto/gui.pro | 1 + src/version.c | 2 ++ 6 files changed, 52 insertions(+), 15 deletions(-) diff --git a/src/gui.c b/src/gui.c index 4981d7331e4d55..e4745547dd6ea8 100644 --- a/src/gui.c +++ b/src/gui.c @@ -5575,3 +5575,24 @@ gui_handle_drop( entered = FALSE; } #endif + +/* + * Check if "key" is to interrupt us. Handles a key that has not had modifiers + * applied yet. + * Return the key with modifiers applied if so, NUL if not. + */ + int +check_for_interrupt(int key, int modifiers_arg) +{ + int modifiers = modifiers_arg; + int c = merge_modifyOtherKeys(key, &modifiers); + + if ((c == Ctrl_C && ctrl_c_interrupts) + || (intr_char != Ctrl_C && c == intr_char)) + { + got_int = TRUE; + return c; + } + return NUL; +} + diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index 40de6663135f89..341db3d5a9abd7 100644 --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -1254,11 +1254,16 @@ key_press_event(GtkWidget *widget UNUSED, add_to_input_buf(string2, 3); } - if (len == 1 && ((string[0] == Ctrl_C && ctrl_c_interrupts) - || (string[0] == intr_char && intr_char != Ctrl_C))) + // Check if the key interrupts. { - trash_input_buf(); - got_int = TRUE; + int int_ch = check_for_interrupt(key, modifiers); + + if (int_ch != NUL) + { + trash_input_buf(); + string[0] = int_ch; + len = 1; + } } add_to_input_buf(string, len); diff --git a/src/gui_photon.c b/src/gui_photon.c index cdb5e15faf28f9..12b0a3cdee5b63 100644 --- a/src/gui_photon.c +++ b/src/gui_photon.c @@ -596,11 +596,17 @@ gui_ph_handle_keyboard(PtWidget_t *widget, void *data, PtCallbackInfo_t *info) string[ len++ ] = ch; } - if (len == 1 && ((ch == Ctrl_C && ctrl_c_interrupts) - || ch == intr_char)) + // Check if the key interrupts. { - trash_input_buf(); - got_int = TRUE; + int int_ch = check_for_interrupt(ch, modifiers); + + if (int_ch != NUL) + { + ch = int_ch; + string[0] = ch; + len = 1; + trash_input_buf(); + } } if (len == 1 && string[0] == CSI) diff --git a/src/gui_x11.c b/src/gui_x11.c index 26d02e77387a63..1402407c2f286f 100644 --- a/src/gui_x11.c +++ b/src/gui_x11.c @@ -970,14 +970,16 @@ gui_x11_key_hit_cb( add_to_input_buf(string2, 3); } - if (len == 1 && ((string[0] == Ctrl_C && ctrl_c_interrupts) -#ifdef UNIX - || (intr_char != 0 && string[0] == intr_char) -#endif - )) + // Check if the key interrupts. { - trash_input_buf(); - got_int = TRUE; + int int_ch = check_for_interrupt(key, modifiers); + + if (int_ch != NUL) + { + trash_input_buf(); + string[0] = int_ch; + len = 1; + } } add_to_input_buf(string, len); diff --git a/src/proto/gui.pro b/src/proto/gui.pro index 51bddf90ebead2..d76242026429c0 100644 --- a/src/proto/gui.pro +++ b/src/proto/gui.pro @@ -65,4 +65,5 @@ void gui_update_screen(void); char_u *get_find_dialog_text(char_u *arg, int *wwordp, int *mcasep); int gui_do_findrepl(int flags, char_u *find_text, char_u *repl_text, int down); void gui_handle_drop(int x, int y, int_u modifiers, char_u **fnames, int count); +int check_for_interrupt(int key, int modifiers_arg); /* vim: set ft=c : */ diff --git a/src/version.c b/src/version.c index f65d0fe6e38d49..931793ec7fe82b 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1335, /**/ 1334, /**/ From af50e899e70ee34d5356846afbea7d75701cb22b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 13:22:10 +0200 Subject: [PATCH 0049/1384] patch 8.2.1336: build failure on non-Unix systems Problem: Build failure on non-Unix systems. Solution: Add #ifdef. --- src/gui.c | 5 ++++- src/version.c | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui.c b/src/gui.c index e4745547dd6ea8..5d003a38b26bd6 100644 --- a/src/gui.c +++ b/src/gui.c @@ -5588,7 +5588,10 @@ check_for_interrupt(int key, int modifiers_arg) int c = merge_modifyOtherKeys(key, &modifiers); if ((c == Ctrl_C && ctrl_c_interrupts) - || (intr_char != Ctrl_C && c == intr_char)) +#ifdef UNIX + || (intr_char != Ctrl_C && c == intr_char) +#endif + ) { got_int = TRUE; return c; diff --git a/src/version.c b/src/version.c index 931793ec7fe82b..bf22a76d9cbe24 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1336, /**/ 1335, /**/ From 586268721dd5d6e50903a8a457f02e0dda901856 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 14:06:38 +0200 Subject: [PATCH 0050/1384] patch 8.2.1337: Vim9: cannot use empty key in dict assignment Problem: Vim9: cannot use empty key in dict assignment. Solution: Allow empty key. (closes #6591) --- src/testdir/test_vim9_script.vim | 12 ++++-------- src/version.c | 2 ++ src/vim9execute.c | 7 ++----- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 405d4877a25707..ec63c6f11c590b 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -244,7 +244,10 @@ def Test_assignment_dict() # overwrite dict3['key'] = 'another' - call CheckDefExecFailure(['let dd = {}', 'dd[""] = 6'], 'E713:') + # empty key can be used + let dd = {} + dd[""] = 6 + assert_equal({'': 6}, dd) # type becomes dict let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'} @@ -783,13 +786,6 @@ def Test_try_catch() endtry assert_equal(300, n) - try - d[''] = 3 - catch /E713:/ - n = 311 - endtry - assert_equal(311, n) - try unlet g:does_not_exist catch /E108:/ diff --git a/src/version.c b/src/version.c index bf22a76d9cbe24..661875a27661a5 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1337, /**/ 1336, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index 9bfec3af121375..de29988be12350 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1422,11 +1422,8 @@ call_def_function( dict_T *dict = tv_dict->vval.v_dict; dictitem_T *di; - if (key == NULL || *key == NUL) - { - emsg(_(e_emptykey)); - goto on_error; - } + if (key == NULL) + key = (char_u *)""; tv = STACK_TV_BOT(-3); di = dict_find(dict, key, -1); if (di != NULL) From 8e4c8c853e3ffbd9258f89180692879ec6bce72b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 15:38:38 +0200 Subject: [PATCH 0051/1384] patch 8.2.1338: Vim9: assigning to script-local variable doesn't check type Problem: Vim9: assigning to script-local variable doesn't check type. Solution: Use the type. (issue #6591) --- src/testdir/test_vim9_script.vim | 23 +++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 48 ++++++++++++++++++-------------- src/vim9execute.c | 5 ++++ 4 files changed, 57 insertions(+), 21 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index ec63c6f11c590b..196ddbe0a25a76 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -251,6 +251,29 @@ def Test_assignment_dict() # type becomes dict let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'} + + # assignment to script-local dict + let lines =<< trim END + vim9script + let test: dict = {} + def FillDict(): dict + test['a'] = 43 + return test + enddef + assert_equal(#{a: 43}, FillDict()) + END + call CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + let test: dict + def FillDict(): dict + test['a'] = 43 + return test + enddef + FillDict() + END + call CheckScriptFailure(lines, 'E1103:') enddef def Test_assignment_local() diff --git a/src/version.c b/src/version.c index 661875a27661a5..fff706fa212dd5 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1338, /**/ 1337, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 688f42a9de109b..cae03d8d2ac5be 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -5070,6 +5070,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) char_u *ret = NULL; int var_count = 0; int var_idx; + int scriptvar_sid = 0; + int scriptvar_idx = -1; int semicolon = 0; garray_T *instr = &cctx->ctx_instr; garray_T *stack = &cctx->ctx_type_stack; @@ -5333,7 +5335,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) } else { - int idx; + int idx; + imported_T *import = NULL; for (idx = 0; reserved[idx] != NULL; ++idx) if (STRCMP(reserved[idx], name) == 0) @@ -5374,9 +5377,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) } else if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0) || lookup_script(var_start, varlen) == OK - || find_imported(var_start, varlen, cctx) != NULL) + || (import = find_imported(var_start, varlen, cctx)) + != NULL) { - dest = dest_script; + char_u *rawname = name + (name[1] == ':' ? 2 : 0); + if (is_decl) { if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0)) @@ -5387,6 +5392,21 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) name); goto theend; } + dest = dest_script; + + // existing script-local variables should have a type + scriptvar_sid = current_sctx.sc_sid; + if (import != NULL) + scriptvar_sid = import->imp_sid; + scriptvar_idx = get_script_item_idx(scriptvar_sid, + rawname, TRUE); + if (scriptvar_idx >= 0) + { + scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid); + svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + + scriptvar_idx; + type = sv->sv_type; + } } else if (name[1] == ':' && name[2] != NUL) { @@ -5766,21 +5786,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) break; case dest_script: { - char_u *rawname = name + (name[1] == ':' ? 2 : 0); - imported_T *import = NULL; - int sid = current_sctx.sc_sid; - int idx; - - if (name[1] != ':') - { - import = find_imported(name, 0, cctx); - if (import != NULL) - sid = import->imp_sid; - } - - idx = get_script_item_idx(sid, rawname, TRUE); - // TODO: specific type - if (idx < 0) + if (scriptvar_idx < 0) { char_u *name_s = name; @@ -5796,14 +5802,14 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) vim_snprintf((char *)name_s, len, "s:%s", name); } - generate_OLDSCRIPT(cctx, ISN_STORES, name_s, sid, - &t_any); + generate_OLDSCRIPT(cctx, ISN_STORES, name_s, + scriptvar_sid, type); if (name_s != name) vim_free(name_s); } else generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT, - sid, idx, &t_any); + scriptvar_sid, scriptvar_idx, type); } break; case dest_local: diff --git a/src/vim9execute.c b/src/vim9execute.c index de29988be12350..6e9b53d689ee23 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1422,6 +1422,11 @@ call_def_function( dict_T *dict = tv_dict->vval.v_dict; dictitem_T *di; + if (dict == NULL) + { + emsg(_(e_dictnull)); + goto on_error; + } if (key == NULL) key = (char_u *)""; tv = STACK_TV_BOT(-3); From 2caa1594e72be7a876c21ed5c2df252d3537cfa7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 15:53:19 +0200 Subject: [PATCH 0052/1384] patch 8.2.1339: Vim9: assigning to global dict variable doesn't work Problem: Vim9: assigning to global dict variable doesn't work. Solution: Guess variable type based in index type. (issue #6591) --- src/testdir/test_vim9_script.vim | 24 ++++++++++++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 20 +++++++++++++++----- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 196ddbe0a25a76..c01b383be57738 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -274,6 +274,30 @@ def Test_assignment_dict() FillDict() END call CheckScriptFailure(lines, 'E1103:') + + # assignment to global dict + lines =<< trim END + vim9script + g:test = {} + def FillDict(): dict + g:test['a'] = 43 + return g:test + enddef + assert_equal(#{a: 43}, FillDict()) + END + call CheckScriptSuccess(lines) + + # assignment to buffer dict + lines =<< trim END + vim9script + b:test = {} + def FillDict(): dict + b:test['a'] = 43 + return b:test + enddef + assert_equal(#{a: 43}, FillDict()) + END + call CheckScriptSuccess(lines) enddef def Test_assignment_local() diff --git a/src/version.c b/src/version.c index fff706fa212dd5..cc92f22e922b39 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1339, /**/ 1338, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index cae03d8d2ac5be..97fa2e0cab1d94 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -5486,11 +5486,9 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) { has_index = TRUE; if (type->tt_member == NULL) - { - semsg(_("E1088: cannot use an index on %s"), name); - goto theend; - } - member_type = type->tt_member; + member_type = &t_any; + else + member_type = type->tt_member; } else { @@ -5719,6 +5717,18 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) emsg(_(e_missbrac)); goto theend; } + if (type == &t_any) + { + type_T *idx_type = ((type_T **)stack->ga_data)[ + stack->ga_len - 1]; + // Index on variable of unknown type: guess the type from the + // index type: number is dict, otherwise dict. + // TODO: should do the assignment at runtime + if (idx_type->tt_type == VAR_NUMBER) + type = &t_list_any; + else + type = &t_dict_any; + } if (type->tt_type == VAR_DICT && may_generate_2STRING(-1, cctx) == FAIL) goto theend; From b86abadf87bd0f85f800077171ec4b98aefff776 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 16:08:19 +0200 Subject: [PATCH 0053/1384] patch 8.2.1340: some tests fail on Cirrus CI and/or with FreeBSD Problem: Some tests fail on Cirrus CI and/or with FreeBSD. Solution: Make 'backupskip' empty. Do not run tests as root. Check for directory when using viminfo. (Ozaki Kiichi, closes #6596) --- .cirrus.yml | 7 +++++-- src/testdir/test_backup.vim | 27 +++++++++++++++++++------- src/testdir/test_edit.vim | 1 - src/testdir/test_viminfo.vim | 2 +- src/testdir/test_writefile.vim | 28 +++++++++------------------ src/version.c | 2 ++ src/viminfo.c | 35 +++++++++++++++++++--------------- 7 files changed, 57 insertions(+), 45 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 97fb0f1f6a559b..a098789c59fead 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -11,6 +11,9 @@ freebsd_12_task: - NPROC=$(getconf _NPROCESSORS_ONLN) - ./configure --with-features=${FEATURES} - make -j${NPROC} - - src/vim --version test_script: - - make test + - src/vim --version + # run tests as user "cirrus" instead of root + - pw useradd cirrus -m + - chown -R cirrus:cirrus . + - sudo -u cirrus make test diff --git a/src/testdir/test_backup.vim b/src/testdir/test_backup.vim index 0d3e79c22a18fe..4c7abe8e56f113 100644 --- a/src/testdir/test_backup.vim +++ b/src/testdir/test_backup.vim @@ -19,6 +19,22 @@ func Test_backup() call delete('Xbackup.txt~') endfunc +func Test_backup_backupskip() + set backup backupdir=. backupskip=*.txt + new + call setline(1, ['line1', 'line2']) + :f Xbackup.txt + :w! Xbackup.txt + " backup file is only created after + " writing a second time (before overwriting) + :w! Xbackup.txt + call assert_false(filereadable('Xbackup.txt~')) + bw! + set backup&vim backupdir&vim backupskip&vim + call delete('Xbackup.txt') + call delete('Xbackup.txt~') +endfunc + func Test_backup2() set backup backupdir=.// backupskip= new @@ -30,7 +46,7 @@ func Test_backup2() :w! Xbackup.txt sp *Xbackup.txt~ call assert_equal(['line1', 'line2', 'line3'], getline(1,'$')) - let f=expand('%') + let f = expand('%') call assert_match('%testdir%Xbackup.txt\~', f) bw! bw! @@ -50,7 +66,7 @@ func Test_backup2_backupcopy() :w! Xbackup.txt sp *Xbackup.txt~ call assert_equal(['line1', 'line2', 'line3'], getline(1,'$')) - let f=expand('%') + let f = expand('%') call assert_match('%testdir%Xbackup.txt\~', f) bw! bw! @@ -61,14 +77,11 @@ endfunc " Test for using a non-existing directory as a backup directory func Test_non_existing_backupdir() - CheckNotBSD - let save_backup = &backupdir - set backupdir=./non_existing_dir + set backupdir=./non_existing_dir backupskip= call writefile(['line1'], 'Xfile') new Xfile - " TODO: write doesn't fail in Cirrus FreeBSD CI test call assert_fails('write', 'E510:') - let &backupdir = save_backup + set backupdir&vim backupskip&vim call delete('Xfile') endfunc diff --git a/src/testdir/test_edit.vim b/src/testdir/test_edit.vim index 0200d9f56066ae..5277d20b7362e5 100644 --- a/src/testdir/test_edit.vim +++ b/src/testdir/test_edit.vim @@ -1682,7 +1682,6 @@ endfunc " Test for editing a file without read permission func Test_edit_file_no_read_perm() CheckUnix - CheckNotBSD call writefile(['one', 'two'], 'Xfile') call setfperm('Xfile', '-w-------') new diff --git a/src/testdir/test_viminfo.vim b/src/testdir/test_viminfo.vim index 258b472bb60a0c..bc8afa0e1fe060 100644 --- a/src/testdir/test_viminfo.vim +++ b/src/testdir/test_viminfo.vim @@ -807,7 +807,7 @@ func Test_viminfo_perm() " Try to write the viminfo to a directory call mkdir('Xdir') - call assert_fails('wviminfo Xdir', 'E886:') + call assert_fails('wviminfo Xdir', 'E137:') call delete('Xdir', 'rf') endfunc diff --git a/src/testdir/test_writefile.vim b/src/testdir/test_writefile.vim index d6e7e64c11beff..e58093074ca3b1 100644 --- a/src/testdir/test_writefile.vim +++ b/src/testdir/test_writefile.vim @@ -136,9 +136,7 @@ func Test_writefile_sync_arg() endfunc func Test_writefile_sync_dev_stdout() - if !has('unix') - return - endif + CheckUnix if filewritable('/dev/stdout') " Just check that this doesn't cause an error. call writefile(['one'], '/dev/stdout') @@ -371,13 +369,10 @@ endfunc " Test for writing to a readonly file func Test_write_readonly() - " In Cirrus-CI, the freebsd tests are run under a root account. So this test - " doesn't fail. - CheckNotBSD call writefile([], 'Xfile') call setfperm('Xfile', "r--------") edit Xfile - set noreadonly + set noreadonly backupskip= call assert_fails('write', 'E505:') let save_cpo = &cpo set cpo+=W @@ -386,37 +381,32 @@ func Test_write_readonly() call setline(1, ['line1']) write! call assert_equal(['line1'], readfile('Xfile')) + set backupskip& call delete('Xfile') endfunc " Test for 'patchmode' func Test_patchmode() - CheckNotBSD call writefile(['one'], 'Xfile') - set patchmode=.orig nobackup writebackup + set patchmode=.orig nobackup backupskip= writebackup new Xfile call setline(1, 'two') " first write should create the .orig file write - " TODO: Xfile.orig is not created in Cirrus FreeBSD CI test call assert_equal(['one'], readfile('Xfile.orig')) call setline(1, 'three') " subsequent writes should not create/modify the .orig file write call assert_equal(['one'], readfile('Xfile.orig')) - set patchmode& backup& writebackup& + set patchmode& backup& backupskip& writebackup& call delete('Xfile') call delete('Xfile.orig') endfunc " Test for writing to a file in a readonly directory func Test_write_readonly_dir() - if !has('unix') || has('bsd') - " On MS-Windows, modifying files in a read-only directory is allowed. - " In Cirrus-CI for Freebsd, tests are run under a root account where - " modifying files in a read-only directory are allowed. - return - endif + " On MS-Windows, modifying files in a read-only directory is allowed. + CheckUnix call mkdir('Xdir') call writefile(['one'], 'Xdir/Xfile1') call setfperm('Xdir', 'r-xr--r--') @@ -426,12 +416,12 @@ func Test_write_readonly_dir() call assert_fails('write', 'E212:') " try to create a backup file in the directory edit! Xdir/Xfile1 - set backupdir=./Xdir + set backupdir=./Xdir backupskip= set patchmode=.orig call assert_fails('write', 'E509:') call setfperm('Xdir', 'rwxr--r--') call delete('Xdir', 'rf') - set backupdir& patchmode& + set backupdir& backupskip& patchmode& endfunc " Test for writing a file using invalid file encoding diff --git a/src/version.c b/src/version.c index cc92f22e922b39..7026eebbea0256 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1340, /**/ 1339, /**/ diff --git a/src/viminfo.c b/src/viminfo.c index 4f26348a226ab1..74780c3d072a86 100644 --- a/src/viminfo.c +++ b/src/viminfo.c @@ -3007,6 +3007,7 @@ read_viminfo( { FILE *fp; char_u *fname; + stat_T st; // mch_stat() of existing viminfo file if (no_viminfo()) return FAIL; @@ -3031,6 +3032,11 @@ read_viminfo( vim_free(fname); if (fp == NULL) return FAIL; + if (mch_fstat(fileno(fp), &st) < 0 || S_ISDIR(st.st_mode)) + { + fclose(fp); + return FAIL; + } viminfo_errcnt = 0; do_viminfo(fp, NULL, flags); @@ -3054,12 +3060,12 @@ write_viminfo(char_u *file, int forceit) FILE *fp_out = NULL; // output viminfo file char_u *tempname = NULL; // name of temp viminfo file stat_T st_new; // mch_stat() of potential new file + stat_T st_old; // mch_stat() of existing viminfo file #if defined(UNIX) || defined(VMS) mode_t umask_save; #endif #ifdef UNIX int shortname = FALSE; // use 8.3 file name - stat_T st_old; // mch_stat() of existing viminfo file #endif #ifdef MSWIN int hidden = FALSE; @@ -3097,20 +3103,20 @@ write_viminfo(char_u *file, int forceit) // write the new viminfo into, in the same directory as the // existing viminfo file, which will be renamed once all writing is // successful. + if (mch_fstat(fileno(fp_in), &st_old) < 0 + || S_ISDIR(st_old.st_mode) #ifdef UNIX - // For Unix we check the owner of the file. It's not very nice to - // overwrite a user's viminfo file after a "su root", with a - // viminfo file that the user can't read. - st_old.st_dev = (dev_t)0; - st_old.st_ino = 0; - st_old.st_mode = 0600; - if (mch_stat((char *)fname, &st_old) == 0 - && getuid() != ROOT_UID - && !(st_old.st_uid == getuid() - ? (st_old.st_mode & 0200) - : (st_old.st_gid == getgid() - ? (st_old.st_mode & 0020) - : (st_old.st_mode & 0002)))) + // For Unix we check the owner of the file. It's not very nice + // to overwrite a user's viminfo file after a "su root", with a + // viminfo file that the user can't read. + || (getuid() != ROOT_UID + && !(st_old.st_uid == getuid() + ? (st_old.st_mode & 0200) + : (st_old.st_gid == getgid() + ? (st_old.st_mode & 0020) + : (st_old.st_mode & 0002)))) +#endif + ) { int tt = msg_didany; @@ -3120,7 +3126,6 @@ write_viminfo(char_u *file, int forceit) fclose(fp_in); goto end; } -#endif #ifdef MSWIN // Get the file attributes of the existing viminfo file. hidden = mch_ishidden(fname); From 2ec208172c37b06a6177e32359214e5e02bfbed5 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 16:35:08 +0200 Subject: [PATCH 0054/1384] patch 8.2.1341: build failures Problem: Build failures. Solution: Add missing error message. --- src/globals.h | 1 + src/version.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/globals.h b/src/globals.h index 77c3641ec7ff00..a0ebc4506a7acd 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1684,6 +1684,7 @@ EXTERN char e_readonlysbx[] INIT(= N_("E794: Cannot set variable in the sandbox: EXTERN char e_stringreq[] INIT(= N_("E928: String required")); EXTERN char e_emptykey[] INIT(= N_("E713: Cannot use empty key for Dictionary")); EXTERN char e_dictreq[] INIT(= N_("E715: Dictionary required")); +EXTERN char e_dictnull[] INIT(= N_("E1103: Dictionary not set")); EXTERN char e_listidx[] INIT(= N_("E684: list index out of range: %ld")); EXTERN char e_blobidx[] INIT(= N_("E979: Blob index out of range: %ld")); EXTERN char e_invalblob[] INIT(= N_("E978: Invalid operation for Blob")); diff --git a/src/version.c b/src/version.c index 7026eebbea0256..202ee2ffacf725 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1341, /**/ 1340, /**/ From f5a48010ef9e47319185f1aaac1bc6d45cd4d47a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 17:00:03 +0200 Subject: [PATCH 0055/1384] patch 8.2.1342: Vim9: accidentally using "t" gives a confusing error Problem: Vim9: accidentally using "x" gives a confusing error. Solution: Disallow using ":t" in Vim9 script. (issue #6399) --- runtime/doc/vim9.txt | 11 ++++++----- src/ex_docmd.c | 3 +++ src/testdir/test_vim9_script.vim | 13 ++++++++----- src/version.c | 2 ++ src/vim9compile.c | 1 + src/vim9script.c | 3 ++- 6 files changed, 22 insertions(+), 11 deletions(-) diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 5d264b673db88d..2c4d1dbc191dd9 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -190,8 +190,8 @@ To intentionally avoid a variable being available later, a block can be used: An existing variable cannot be assigned to with `:let`, since that implies a declaration. Global, window, tab, buffer and Vim variables can only be used -without `:let`, because they are are not really declared, they can also be -deleted with `:unlet`. +without `:let`, because they are not really declared, they can also be deleted +with `:unlet`. Variables cannot shadow previously defined variables. Variables may shadow Ex commands, rename the variable if needed. @@ -352,10 +352,11 @@ No curly braces expansion ~ |curly-braces-names| cannot be used. -No :xit, :append, :change or :insert ~ +No :xit, :t, :append, :change or :insert ~ -These commands are too easily confused with local variable names. Instead of -`:x` or `:xit` you can use `:exit`. +These commands are too easily confused with local variable names. +Instead of `:x` or `:xit` you can use `:exit`. +Instead of `:t` you can use `:copy`. Comparators ~ diff --git a/src/ex_docmd.c b/src/ex_docmd.c index ad1693b516f1c3..081d9e454c4b2a 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -7276,6 +7276,9 @@ ex_copymove(exarg_T *eap) { long n; + if (not_in_vim9(eap) == FAIL) + return; + n = get_address(eap, &eap->arg, eap->addr_type, FALSE, FALSE, FALSE, 1); if (eap->arg == NULL) // error detected { diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index c01b383be57738..8950f311a7afbf 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1628,18 +1628,21 @@ def Test_fixed_size_list() enddef def Test_no_insert_xit() - call CheckDefExecFailure(['x = 1'], 'E1100:') call CheckDefExecFailure(['a = 1'], 'E1100:') - call CheckDefExecFailure(['i = 1'], 'E1100:') call CheckDefExecFailure(['c = 1'], 'E1100:') + call CheckDefExecFailure(['i = 1'], 'E1100:') + call CheckDefExecFailure(['t = 1'], 'E1100:') + call CheckDefExecFailure(['x = 1'], 'E1100:') - CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:') CheckScriptFailure(['vim9script', 'a = 1'], 'E488:') CheckScriptFailure(['vim9script', 'a'], 'E1100:') - CheckScriptFailure(['vim9script', 'i = 1'], 'E488:') - CheckScriptFailure(['vim9script', 'i'], 'E1100:') CheckScriptFailure(['vim9script', 'c = 1'], 'E488:') CheckScriptFailure(['vim9script', 'c'], 'E1100:') + CheckScriptFailure(['vim9script', 'i = 1'], 'E488:') + CheckScriptFailure(['vim9script', 'i'], 'E1100:') + CheckScriptFailure(['vim9script', 't'], 'E1100:') + CheckScriptFailure(['vim9script', 't = 1'], 'E1100:') + CheckScriptFailure(['vim9script', 'x = 1'], 'E1100:') enddef def IfElse(what: number): string diff --git a/src/version.c b/src/version.c index 202ee2ffacf725..021487db2812a4 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1342, /**/ 1341, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 97fa2e0cab1d94..38c097c7f83968 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -7467,6 +7467,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx) case CMD_append: case CMD_change: case CMD_insert: + case CMD_t: case CMD_xit: not_in_vim9(&ea); goto erret; diff --git a/src/vim9script.c b/src/vim9script.c index 2e94b8e2955396..e7bb43303e6cb4 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -67,9 +67,10 @@ not_in_vim9(exarg_T *eap) if (in_vim9script()) switch (eap->cmdidx) { - case CMD_insert: case CMD_append: case CMD_change: + case CMD_insert: + case CMD_t: case CMD_xit: semsg(_("E1100: Missing :let: %s"), eap->cmd); return FAIL; From 333894b195479c9304a19f4e6ec1a9c09ecf07e4 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 18:53:07 +0200 Subject: [PATCH 0056/1384] patch 8.2.1343: Vim9: cannot find global function when using g: Problem: Vim9: cannot find global function when using g: when local function with the same name exists. Solution: Find global function when using g:. --- src/testdir/test_vim9_func.vim | 15 +++++++++++++++ src/userfunc.c | 24 +++++++++++++++--------- src/version.c | 2 ++ 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 7298d9a7349160..3acae98ea9ddb5 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -161,6 +161,21 @@ def Test_nested_global_function() CheckScriptSuccess(lines) enddef +def Test_global_local_function() + let lines =<< trim END + vim9script + def g:Func(): string + return 'global' + enddef + def Func(): string + return 'local' + enddef + assert_equal('global', g:Func()) + assert_equal('local', Func()) + END + CheckScriptSuccess(lines) +enddef + func TakesOneArg(arg) echo a:arg endfunc diff --git a/src/userfunc.c b/src/userfunc.c index 4c1e2619522d0b..520c114ef5df5b 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -789,9 +789,10 @@ find_func_even_dead(char_u *name, int is_global, cctx_T *cctx) if (!is_global) { - char_u *after_script = NULL; + int vim9script = in_vim9script(); + char_u *after_script = NULL; - if (in_vim9script()) + if (vim9script) { // Find script-local function before global one. func = find_func_with_sid(name, current_sctx.sc_sid); @@ -799,7 +800,7 @@ find_func_even_dead(char_u *name, int is_global, cctx_T *cctx) return func; } - if (!in_vim9script() + if (!vim9script && name[0] == K_SPECIAL && name[1] == KS_EXTRA && name[2] == KE_SNR) @@ -815,7 +816,7 @@ find_func_even_dead(char_u *name, int is_global, cctx_T *cctx) else after_script = NULL; } - if (in_vim9script() || after_script != NULL) + if (vim9script || after_script != NULL) { // Find imported function before global one. imported = find_imported( @@ -2086,10 +2087,14 @@ call_func( if (error == FCERR_NONE && funcexe->evaluate) { char_u *rfname = fname; + int is_global = FALSE; - // Ignore "g:" before a function name. + // Skip "g:" before a function name. if (fp == NULL && fname[0] == 'g' && fname[1] == ':') + { + is_global = TRUE; rfname = fname + 2; + } rettv->v_type = VAR_NUMBER; // default rettv is number zero rettv->vval.v_number = 0; @@ -2101,7 +2106,7 @@ call_func( * User defined function. */ if (fp == NULL) - fp = find_func(rfname, FALSE, NULL); + fp = find_func(rfname, is_global, NULL); // Trigger FuncUndefined event, may load the function. if (fp == NULL @@ -2110,13 +2115,13 @@ call_func( && !aborting()) { // executed an autocommand, search for the function again - fp = find_func(rfname, FALSE, NULL); + fp = find_func(rfname, is_global, NULL); } // Try loading a package. if (fp == NULL && script_autoload(rfname, TRUE) && !aborting()) { // loaded a package, search for the function again - fp = find_func(rfname, FALSE, NULL); + fp = find_func(rfname, is_global, NULL); } if (fp == NULL) { @@ -2125,7 +2130,7 @@ call_func( // If using Vim9 script try not local to the script. // TODO: should not do this if the name started with "s:". if (p != NULL) - fp = find_func(p, FALSE, NULL); + fp = find_func(p, is_global, NULL); } if (fp != NULL && (fp->uf_flags & FC_DELETED)) @@ -2175,6 +2180,7 @@ call_func( */ error = call_internal_func(fname, argcount, argvars, rettv); } + /* * The function call (or "FuncUndefined" autocommand sequence) might * have been aborted by an error, an interrupt, or an explicitly thrown diff --git a/src/version.c b/src/version.c index 021487db2812a4..33274ac62fab52 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1343, /**/ 1342, /**/ From 2c79e9d14dc0e61d8c357946d01107ec23ec0fe2 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 18:57:52 +0200 Subject: [PATCH 0057/1384] patch 8.2.1344: Vim9: No test for trying to redefine global function Problem: Vim9: No test for trying to redefine global function. Solution: Add a test. --- src/testdir/test_vim9_func.vim | 13 +++++++++++++ src/version.c | 2 ++ 2 files changed, 15 insertions(+) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 3acae98ea9ddb5..85fd8ff4e0acd5 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -159,6 +159,19 @@ def Test_nested_global_function() delfunc g:Inner END CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + def Outer() + def g:Inner(): string + return 'inner' + enddef + enddef + defcompile + Outer() + Outer() + END + CheckScriptFailure(lines, "E122:") enddef def Test_global_local_function() diff --git a/src/version.c b/src/version.c index 33274ac62fab52..c6b6e8fd0236d0 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1344, /**/ 1343, /**/ From f8992d47cd50494c64bb733329067c9de3c75200 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 19:14:13 +0200 Subject: [PATCH 0058/1384] patch 8.2.1345: Redraw error when using visual block and scroll Problem: Redraw error when using visual block and scroll. Solution: Add check for w_topline. ( closes #6597) --- src/drawscreen.c | 9 +++++--- .../Test_display_visual_block_scroll.dump | 7 ++++++ src/testdir/test_display.vim | 23 +++++++++++++++++++ src/version.c | 2 ++ 4 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 src/testdir/dumps/Test_display_visual_block_scroll.dump diff --git a/src/drawscreen.c b/src/drawscreen.c index faecaa44bf856e..7afcf0975427c0 100644 --- a/src/drawscreen.c +++ b/src/drawscreen.c @@ -1659,10 +1659,13 @@ win_update(win_T *wp) #endif ) { - if (mod_top != 0 && wp->w_topline == mod_top) + if (mod_top != 0 + && wp->w_topline == mod_top + && (!wp->w_lines[0].wl_valid + || wp->w_topline == wp->w_lines[0].wl_lnum)) { - // w_topline is the first changed line, the scrolling will be done - // further down. + // w_topline is the first changed line and window is not scrolled, + // the scrolling from changed lines will be done further down. } else if (wp->w_lines[0].wl_valid && (wp->w_topline < wp->w_lines[0].wl_lnum diff --git a/src/testdir/dumps/Test_display_visual_block_scroll.dump b/src/testdir/dumps/Test_display_visual_block_scroll.dump new file mode 100644 index 00000000000000..afb52fbb941b95 --- /dev/null +++ b/src/testdir/dumps/Test_display_visual_block_scroll.dump @@ -0,0 +1,7 @@ +|{+0&#e0e0e08| | +0&#ffffff0@72 +|}+0&#e0e0e08| | +0&#ffffff0@72 +|{+0&#e0e0e08| | +0&#ffffff0@72 +|f+0&#e0e0e08| | +0&#ffffff0@72 +>g| +0&#e0e0e08| +0&#ffffff0@72 +|}| @73 +|-+2&&@1| |V|I|S|U|A|L| |L|I|N|E| |-@1| +0&&@29|7| @8|1@1|,|1| @9|B|o|t| diff --git a/src/testdir/test_display.vim b/src/testdir/test_display.vim index ed111a585e32f5..1e2ed455f0b4c1 100644 --- a/src/testdir/test_display.vim +++ b/src/testdir/test_display.vim @@ -220,3 +220,26 @@ func Test_unprintable_fileformats() call delete('Xmac.txt') call delete(filename) endfunc + +" Test for scrolling that modifies buffer during visual block +func Test_visual_block_scroll() + CheckScreendump + + let lines =<< trim END + source $VIMRUNTIME/plugin/matchparen.vim + set scrolloff=1 + call setline(1, ['a', 'b', 'c', 'd', 'e', '', '{', '}', '{', 'f', 'g', '}']) + call cursor(5, 1) + END + + let filename = 'Xvisualblockmodifiedscroll' + call writefile(lines, filename) + + let buf = RunVimInTerminal('-S '.filename, #{rows: 7}) + call term_sendkeys(buf, "V\\") + + call VerifyScreenDump(buf, 'Test_display_visual_block_scroll', {}) + + call StopVimInTerminal(buf) + call delete(filename) +endfunc diff --git a/src/version.c b/src/version.c index c6b6e8fd0236d0..fb8a37ce5cb409 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1345, /**/ 1344, /**/ From 491799be5084dde7aa3367462f306e7b71dbc4a5 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 19:23:43 +0200 Subject: [PATCH 0059/1384] patch 8.2.1346: small build fails Problem: Small build fails. Solution: Add #ifdef. --- src/ex_docmd.c | 3 ++- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 081d9e454c4b2a..7f9d716354fdba 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -7276,9 +7276,10 @@ ex_copymove(exarg_T *eap) { long n; +#ifdef FEAT_EVAL if (not_in_vim9(eap) == FAIL) return; - +#endif n = get_address(eap, &eap->arg, eap->addr_type, FALSE, FALSE, FALSE, 1); if (eap->arg == NULL) // error detected { diff --git a/src/version.c b/src/version.c index fb8a37ce5cb409..cdb26a25854d07 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1346, /**/ 1345, /**/ From 909443028b57d7514ce3c71f00e9d808f2126b4f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 20:45:11 +0200 Subject: [PATCH 0060/1384] patch 8.2.1347: cannot easily get the script ID Problem: Cannot easily get the script ID. Solution: Support expand(''). --- runtime/doc/map.txt | 4 ++++ src/ex_docmd.c | 14 +++++++++++++- src/testdir/test_expand_func.vim | 25 +++++++++++++++++++------ src/version.c | 2 ++ 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 0ad43d449b7820..79c46f712534ba 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1167,6 +1167,10 @@ When executing an autocommand or a user command, it will run in the context of the script it was defined in. This makes it possible that the command calls a local function or uses a local mapping. +In case the value is used in a context where cannot be correctly +expanded, use the expand() function: > + let &includexpr = expand('') .. 'My_includeexpr()' + Otherwise, using "" outside of a script context is an error. If you need to get the script number to use in a complicated script, you can diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 7f9d716354fdba..1f36bf7e054c6c 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -8302,9 +8302,11 @@ find_cmdline_var(char_u *src, int *usedlen) #define SPEC_AMATCH (SPEC_ABUF + 1) "", // script file line number #define SPEC_SFLNUM (SPEC_AMATCH + 1) + "", // script ID: 123_ +#define SPEC_SID (SPEC_SFLNUM + 1) #ifdef FEAT_CLIENTSERVER "" -# define SPEC_CLIENT (SPEC_SFLNUM + 1) +# define SPEC_CLIENT (SPEC_SID + 1) #endif }; @@ -8581,6 +8583,16 @@ eval_vars( break; #endif + case SPEC_SID: + if (current_sctx.sc_sid <= 0) + { + *errormsg = _(e_usingsid); + return NULL; + } + sprintf((char *)strbuf, "%d_", current_sctx.sc_sid); + result = strbuf; + break; + #ifdef FEAT_CLIENTSERVER case SPEC_CLIENT: // Source of last submitted input sprintf((char *)strbuf, PRINTF_HEX_LONG_U, diff --git a/src/testdir/test_expand_func.vim b/src/testdir/test_expand_func.vim index 41673e50afd985..42aa8e01bcd540 100644 --- a/src/testdir/test_expand_func.vim +++ b/src/testdir/test_expand_func.vim @@ -1,5 +1,7 @@ " Tests for expand() +source shared.vim + let s:sfile = expand('') let s:slnum = str2nr(expand('')) let s:sflnum = str2nr(expand('')) @@ -18,20 +20,20 @@ endfunc " This test depends on the location in the test file, put it first. func Test_expand_sflnum() - call assert_equal(5, s:sflnum) - call assert_equal(22, str2nr(expand(''))) + call assert_equal(7, s:sflnum) + call assert_equal(24, str2nr(expand(''))) " Line-continuation call assert_equal( - \ 25, + \ 27, \ str2nr(expand(''))) " Call in script-local function - call assert_equal(16, s:expand_sflnum()) + call assert_equal(18, s:expand_sflnum()) " Call in command command Flnum echo expand('') - call assert_equal(34, str2nr(trim(execute('Flnum')))) + call assert_equal(36, str2nr(trim(execute('Flnum')))) delcommand Flnum endfunc @@ -60,7 +62,7 @@ func Test_expand_sfile_and_stack() endfunc func Test_expand_slnum() - call assert_equal(4, s:slnum) + call assert_equal(6, s:slnum) call assert_equal(2, str2nr(expand(''))) " Line-continuation @@ -86,6 +88,17 @@ func Test_expand() quit endfunc +func s:sid_test() + return 'works' +endfunc + +func Test_expand_SID() + let sid = expand('') + execute 'let g:sid_result = ' .. sid .. 'sid_test()' + call assert_equal('works', g:sid_result) +endfunc + + " Test for 'wildignore' with expand() func Test_expand_wildignore() set wildignore=*.vim diff --git a/src/version.c b/src/version.c index cdb26a25854d07..6b1a3677378ec2 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1347, /**/ 1346, /**/ From e4218b9416bdcd78b9779a06258198573a0c369e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 21:11:38 +0200 Subject: [PATCH 0061/1384] patch 8.2.1348: build failure without the eval feature Problem: Build failure without the eval feature. Solution: Add #ifdef. --- src/ex_docmd.c | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 1f36bf7e054c6c..185fc49cb4bfe8 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -8581,7 +8581,6 @@ eval_vars( (long)(current_sctx.sc_lnum + SOURCING_LNUM)); result = strbuf; break; -#endif case SPEC_SID: if (current_sctx.sc_sid <= 0) @@ -8592,6 +8591,7 @@ eval_vars( sprintf((char *)strbuf, "%d_", current_sctx.sc_sid); result = strbuf; break; +#endif #ifdef FEAT_CLIENTSERVER case SPEC_CLIENT: // Source of last submitted input diff --git a/src/version.c b/src/version.c index 6b1a3677378ec2..e715d8ae37b20d 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1348, /**/ 1347, /**/ From eef2102e20d24f5fbd1c9f53c7a35df61585c5ab Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 22:16:43 +0200 Subject: [PATCH 0062/1384] patch 8.2.1349: Vim9: can define a function with the name of an import Problem: Vim9: can define a function with the name of an import. Solution: Disallow using an existing name. (closes #6585) --- src/globals.h | 1 + src/testdir/test_vim9_script.vim | 33 ++++++++++++++++++++++++++++++++ src/userfunc.c | 23 +++++++++++++++++----- src/version.c | 2 ++ src/vim9compile.c | 17 +++++++++++----- 5 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/globals.h b/src/globals.h index a0ebc4506a7acd..cc01ac2508d579 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1746,6 +1746,7 @@ EXTERN char e_missing_dict_colon[] INIT(= N_("E720: Missing colon in Dictionary: EXTERN char e_duplicate_key[] INIT(= N_("E721: Duplicate key in Dictionary: \"%s\"")); EXTERN char e_missing_dict_comma[] INIT(= N_("E722: Missing comma in Dictionary: %s")); EXTERN char e_missing_dict_end[] INIT(= N_("E723: Missing end of Dictionary '}': %s")); +EXTERN char e_already_defined[] INIT(= N_("E1073: name already defined: %s")); #endif #ifdef FEAT_CLIENTSERVER EXTERN char e_invexprmsg[] INIT(= N_("E449: Invalid expression received")); diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 8950f311a7afbf..221b38d7a88466 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1618,6 +1618,39 @@ def Test_import_compile_error() delete('Ximport.vim') enddef +def Test_func_overrules_import_fails() + let export_lines =<< trim END + vim9script + export def Func() + echo 'imported' + enddef + END + writefile(export_lines, 'XexportedFunc.vim') + + let lines =<< trim END + vim9script + import Func from './XexportedFunc.vim' + def Func() + echo 'local to function' + enddef + END + CheckScriptFailure(lines, 'E1073:') + + lines =<< trim END + vim9script + import Func from './XexportedFunc.vim' + def Outer() + def Func() + echo 'local to function' + enddef + enddef + defcompile + END + CheckScriptFailure(lines, 'E1073:') + + delete('XexportedFunc.vim') +enddef + def Test_fixed_size_list() # will be allocated as one piece of memory, check that changes work let l = [1, 2, 3, 4] diff --git a/src/userfunc.c b/src/userfunc.c index 520c114ef5df5b..43aa146a9827bd 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -2652,6 +2652,7 @@ def_function(exarg_T *eap, char_u *name_arg) char_u *skip_until = NULL; char_u *heredoc_trimmed = NULL; int vim9script = in_vim9script(); + imported_T *import = NULL; /* * ":function" without argument: list functions. @@ -3235,17 +3236,29 @@ def_function(exarg_T *eap, char_u *name_arg) } fp = find_func_even_dead(name, is_global, NULL); - if (fp != NULL) + if (vim9script) + { + char_u *uname = untrans_function_name(name); + + import = find_imported(uname == NULL ? name : uname, 0, NULL); + } + + if (fp != NULL || import != NULL) { - int dead = fp->uf_flags & FC_DEAD; + int dead = fp != NULL && (fp->uf_flags & FC_DEAD); // Function can be replaced with "function!" and when sourcing the // same script again, but only once. - if (!dead && !eap->forceit + // A name that is used by an import can not be overruled. + if (import != NULL + || (!dead && !eap->forceit && (fp->uf_script_ctx.sc_sid != current_sctx.sc_sid - || fp->uf_script_ctx.sc_seq == current_sctx.sc_seq)) + || fp->uf_script_ctx.sc_seq == current_sctx.sc_seq))) { - emsg_funcname(e_funcexts, name); + if (vim9script) + emsg_funcname(e_already_defined, name); + else + emsg_funcname(e_funcexts, name); goto erret; } if (fp->uf_calls > 0) diff --git a/src/version.c b/src/version.c index e715d8ae37b20d..c98d2ab76c7773 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1349, /**/ 1348, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 38c097c7f83968..6581708bc9636b 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -294,9 +294,10 @@ check_defined(char_u *p, size_t len, cctx_T *cctx) if (lookup_script(p, len) == OK || (cctx != NULL && (lookup_local(p, len, cctx) != NULL - || find_imported(p, len, cctx) != NULL))) + || lookup_arg(p, len, NULL, NULL, NULL, cctx) == OK)) + || find_imported(p, len, cctx) != NULL) { - semsg("E1073: imported name already defined: %s", p); + semsg(_(e_already_defined), p); return FAIL; } return OK; @@ -4899,17 +4900,21 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) int is_global = *eap->arg == 'g' && eap->arg[1] == ':'; char_u *name_start = eap->arg; char_u *name_end = to_name_end(eap->arg, is_global); - char_u *name = get_lambda_name(); + char_u *lambda_name; lvar_T *lvar; ufunc_T *ufunc; int r; + if (check_defined(name_start, name_end - name_start, cctx) == FAIL) + return NULL; + eap->arg = name_end; eap->getline = exarg_getline; eap->cookie = cctx; eap->skip = cctx->ctx_skip == SKIP_YES; eap->forceit = FALSE; - ufunc = def_function(eap, name); + lambda_name = get_lambda_name(); + ufunc = def_function(eap, lambda_name); if (ufunc == NULL) return NULL; @@ -4925,13 +4930,15 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) if (func_name == NULL) r = FAIL; else - r = generate_NEWFUNC(cctx, name, func_name); + r = generate_NEWFUNC(cctx, lambda_name, func_name); } else { // Define a local variable for the function reference. lvar = reserve_local(cctx, name_start, name_end - name_start, TRUE, ufunc->uf_func_type); + if (lvar == NULL) + return NULL; if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL) return NULL; r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL); From b9a2cac3ef293bfdfe80dea6c6d16d02b7af5435 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 22:23:20 +0200 Subject: [PATCH 0063/1384] patch 8.2.1350: Vim9: no test for error message when redefining function Problem: Vim9: no test for error message when redefining function. Solution: Add a test. --- src/testdir/test_vim9_script.vim | 13 +++++++++++++ src/version.c | 2 ++ 2 files changed, 15 insertions(+) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 221b38d7a88466..b96411ff6781c2 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1651,6 +1651,19 @@ def Test_func_overrules_import_fails() delete('XexportedFunc.vim') enddef +def Test_func_redefine_fails() + let lines =<< trim END + vim9script + def Func() + echo 'one' + enddef + def Func() + echo 'two' + enddef + END + CheckScriptFailure(lines, 'E1073:') +enddef + def Test_fixed_size_list() # will be allocated as one piece of memory, check that changes work let l = [1, 2, 3, 4] diff --git a/src/version.c b/src/version.c index c98d2ab76c7773..00d8c2dab6a6c7 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1350, /**/ 1349, /**/ From bcbf41395f93aabd577a17dc4fbabe523d0a7ce8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 22:35:13 +0200 Subject: [PATCH 0064/1384] patch 8.2.1351: Vim9: no proper error if using namespace for nested function Problem: Vim9: no proper error if using namespace for nested function. Solution: Specifically check for a namespace. (closes #6582) --- src/testdir/test_vim9_func.vim | 2 ++ src/version.c | 2 ++ src/vim9compile.c | 8 +++++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 85fd8ff4e0acd5..1ccaeb308a1385 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -131,6 +131,8 @@ def Test_nested_function() CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:') CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:') + CheckDefFailure(['def s:Nested()', 'enddef'], 'E1075:') + CheckDefFailure(['def b:Nested()', 'enddef'], 'E1075:') enddef func Test_call_default_args_from_func() diff --git a/src/version.c b/src/version.c index 00d8c2dab6a6c7..f032581c0cdd1e 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1351, /**/ 1350, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 6581708bc9636b..61be54d7b726d9 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -4899,12 +4899,18 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) { int is_global = *eap->arg == 'g' && eap->arg[1] == ':'; char_u *name_start = eap->arg; - char_u *name_end = to_name_end(eap->arg, is_global); + char_u *name_end = to_name_end(eap->arg, TRUE); char_u *lambda_name; lvar_T *lvar; ufunc_T *ufunc; int r; + // Only g:Func() can use a namespace. + if (name_start[1] == ':' && !is_global) + { + semsg(_(e_namespace), name_start); + return NULL; + } if (check_defined(name_start, name_end - name_start, cctx) == FAIL) return NULL; From ad486a0f0dd194826fdb733516bf0f35382c9dd7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 1 Aug 2020 23:22:18 +0200 Subject: [PATCH 0065/1384] patch 8.2.1352: Vim9: no error for shadowing a script-local function Problem: Vim9: no error for shadowing a script-local function by a nested function. Solution: Check for script-local function. (closes #6586) --- src/testdir/test_vim9_func.vim | 14 ++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 8 +++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 1ccaeb308a1385..f3fc4c7bee4d06 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -174,6 +174,20 @@ def Test_nested_global_function() Outer() END CheckScriptFailure(lines, "E122:") + + lines =<< trim END + vim9script + def Func() + echo 'script' + enddef + def Outer() + def Func() + echo 'inner' + enddef + enddef + defcompile + END + CheckScriptFailure(lines, "E1073:") enddef def Test_global_local_function() diff --git a/src/version.c b/src/version.c index f032581c0cdd1e..70d90c5764409a 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1352, /**/ 1351, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 61be54d7b726d9..3c7e1218ed553c 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -291,15 +291,21 @@ lookup_script(char_u *name, size_t len) int check_defined(char_u *p, size_t len, cctx_T *cctx) { + int c = p[len]; + + p[len] = NUL; if (lookup_script(p, len) == OK || (cctx != NULL && (lookup_local(p, len, cctx) != NULL || lookup_arg(p, len, NULL, NULL, NULL, cctx) == OK)) - || find_imported(p, len, cctx) != NULL) + || find_imported(p, len, cctx) != NULL + || find_func_even_dead(p, FALSE, cctx) != NULL) { + p[len] = c; semsg(_(e_already_defined), p); return FAIL; } + p[len] = c; return OK; } From 8b89614e69b9b2330539d0482e44f4724053e780 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 2 Aug 2020 15:05:05 +0200 Subject: [PATCH 0066/1384] patch 8.2.1353: crash when drawing double-wide character in terminal window Problem: Crash when drawing double-wide character in terminal window. (Masato Nishihata) Solution: Check getcell() returning NULL. (issue #6141) --- src/libvterm/src/screen.c | 7 ++++++- src/testdir/test_terminal.vim | 15 +++++++++++++++ src/version.c | 2 ++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/libvterm/src/screen.c b/src/libvterm/src/screen.c index eb90c200717ab3..42890aa58a1f5a 100644 --- a/src/libvterm/src/screen.c +++ b/src/libvterm/src/screen.c @@ -186,7 +186,12 @@ static int putglyph(VTermGlyphInfo *info, VTermPos pos, void *user) cell->chars[i] = 0; for(col = 1; col < info->width; col++) - getcell(screen, pos.row, pos.col + col)->chars[0] = (uint32_t)-1; + { + ScreenCell *onecell = getcell(screen, pos.row, pos.col + col); + if (onecell == NULL) + break; + onecell->chars[0] = (uint32_t)-1; + } rect.start_row = pos.row; rect.end_row = pos.row+1; diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index fcc11565cdfa12..c1ee493cd7d8a1 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -258,6 +258,21 @@ func Test_terminal_scrape_multibyte() call delete('Xtext') endfunc +func Test_terminal_one_column() + " This creates a terminal, displays a double-wide character and makes the + " window one column wide. This used to cause a crash. + let width = &columns + botright vert term + let buf = bufnr('$') + call term_wait(buf, 100) + exe "set columns=" .. (width / 2) + redraw + call term_sendkeys(buf, "キ") + call term_wait(buf, 10) + exe "set columns=" .. width + exe buf . 'bwipe!' +endfunc + func Test_terminal_scroll() call writefile(range(1, 200), 'Xtext') if has('win32') diff --git a/src/version.c b/src/version.c index 70d90c5764409a..f34402dc6f1d57 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1353, /**/ 1352, /**/ From aa970abd0a987de96321d33db82f70bbceac931b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 2 Aug 2020 16:10:39 +0200 Subject: [PATCH 0067/1384] patch 8.2.1354: test 59 is old style Problem: Test 59 is old style. Solution: Convert into a new style test. (Yegappan Lakshmanan, closes #6604) --- runtime/doc/eval.txt | 7 +- src/Makefile | 2 +- src/testdir/Make_all.mak | 4 +- src/testdir/Make_vms.mms | 33 +- src/testdir/test59.in | 626 -------------------------- src/testdir/test59.ok | 270 ----------- src/testdir/test_spell_utf8.vim | 768 ++++++++++++++++++++++++++++++++ src/version.c | 2 + 8 files changed, 780 insertions(+), 932 deletions(-) delete mode 100644 src/testdir/test59.in delete mode 100644 src/testdir/test59.ok create mode 100644 src/testdir/test_spell_utf8.vim diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index d8994ef00cf39d..8c6f7ded6ba1cb 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 Jul 21 +*eval.txt* For Vim version 8.2. Last change: 2020 Aug 01 VIM REFERENCE MANUAL by Bram Moolenaar @@ -4273,6 +4273,8 @@ expand({expr} [, {nosuf} [, {list}]]) *expand()* line number script file line number, also when in a function + "123_" where "123" is the + current script ID || word under the cursor WORD under the cursor the {clientid} of the last received @@ -12129,7 +12131,8 @@ text... {endmarker} Set internal variable {var-name} to a |List| containing the lines of text bounded by the string - {endmarker}. + {endmarker}. The lines of text is used as a + |literal-string|. {endmarker} must not contain white space. {endmarker} cannot start with a lower case character. The last line should end only with the {endmarker} diff --git a/src/Makefile b/src/Makefile index d34a60891bf294..148126d1c9677f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2310,7 +2310,7 @@ test_libvterm: # Run individual OLD style test. # These do not depend on the executable, compile it when needed. -test1 test49 test59: +test1 test49: cd testdir; rm -f $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE) # Run individual NEW style test. diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 635087cbdc0fea..0900a6cfd80d63 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -20,7 +20,7 @@ SCRIPTS_MORE1 = SCRIPTS_MORE2 = test49.out # Tests that run on most systems, but not on VMS -SCRIPTS_MORE4 = test59.out +SCRIPTS_MORE4 = # Tests specifically for MS-Windows. SCRIPTS_WIN32 = @@ -242,6 +242,7 @@ NEW_TESTS = \ test_source \ test_source_utf8 \ test_spell \ + test_spell_utf8 \ test_spellfile \ test_startup \ test_startup_utf8 \ @@ -464,6 +465,7 @@ NEW_TESTS_RES = \ test_sound.res \ test_source.res \ test_spell.res \ + test_spell_utf8.res \ test_spellfile.res \ test_startup.res \ test_stat.res \ diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms index 848fca7f5829bc..59da981b370704 100644 --- a/src/testdir/Make_vms.mms +++ b/src/testdir/Make_vms.mms @@ -32,22 +32,6 @@ # and directory handling. # WANT_UNIX = YES -# Comment out if you want to run Win32 specific tests as well, but please -# be aware, that on OpenVMS will fail, because of cat, rm, etc commands -# and directory handling. -# WANT_WIN = YES - -# Comment out if you want to run spell checker tests. -# They fail because VMS does not support file names. -# WANT_SPELL = YES - -# Comment out if you want to run mzschema tests. -# It fails because VMS does not support this feature yet. -# WANT_MZSCH = YES - -# Comment out if you have ODS-5 file system -# HAVE_ODS5 = YES - # Comment out if you have gzip on your system # HAVE_GZIP = YES @@ -75,12 +59,6 @@ VIMPROG = <->vim.exe SCRIPT = test1.out test49.out test77a.out -# Known problems: -# -# test59: Failed/Hangs - VMS does not support spell files (file names -# with too many dots). -# - .IFDEF WANT_GUI GUI_OPTION = -g .ENDIF @@ -89,10 +67,6 @@ GUI_OPTION = -g SCRIPT_UNIX = test49.out .ENDIF -.IFDEF WANT_SPELL -SCRIPT_SPELL = test59.out -.ENDIF - .in.out : -@ !clean up before doing the test -@ if "''F$SEARCH("test.out.*")'" .NES. "" then delete/noconfirm/nolog test.out.* @@ -113,8 +87,7 @@ SCRIPT_SPELL = test59.out -@ if "''F$SEARCH("Xdotest.*")'" .NES. "" then delete/noconfirm/nolog Xdotest.*.* -@ if "''F$SEARCH("Xtest.*")'" .NES. "" then delete/noconfirm/nolog Xtest.*.* -all : clean nolog $(START_WITH) $(SCRIPT) $(SCRIPT_UNIX) $(SCRIPT_SPELL) \ - nolog +all : clean nolog $(START_WITH) $(SCRIPT) $(SCRIPT_UNIX) nolog -@ write sys$output " " -@ write sys$output "-----------------------------------------------" -@ write sys$output " All done" @@ -139,10 +112,6 @@ nolog : -@ write sys$output "MAKE_VMS.MMS options:" -@ write sys$output " WANT_GUI = ""$(WANT_GUI)"" " -@ write sys$output " WANT_UNIX = ""$(WANT_UNIX)"" " - -@ write sys$output " WANT_WIN = ""$(WANT_WIN)"" " - -@ write sys$output " WANT_SPELL = ""$(WANT_SPELL)"" " - -@ write sys$output " WANT_MZSCH = ""$(WANT_MZSCH)"" " - -@ write sys$output " HAVE_ODS5 = ""$(HAVE_ODS5)"" " -@ write sys$output " HAVE_GZIP = ""$(HAVE_GZIP)"" " -@ write sys$output " HAVE_GDIFF = ""$(HAVE_GDIFF)"" " -@ write sys$output " HAVE_ICONV = ""$(HAVE_ICONV)"" " diff --git a/src/testdir/test59.in b/src/testdir/test59.in deleted file mode 100644 index dcdb62b283943d..00000000000000 --- a/src/testdir/test59.in +++ /dev/null @@ -1,626 +0,0 @@ -Tests for spell checking with 'encoding' set to "utf-8". vim: set ft=vim : - -STARTTEST -:so small.vim -:so mbyte.vim -:" -:" Don't want to depend on the locale from the environment. The .aff and .dic -:" text is in latin1, the test text is utf-8. -:set enc=latin1 -:e! -:set enc=utf-8 -:set fenc= -:" -:" Function to test .aff/.dic with list of good and bad words. -:func TestOne(aff, dic) - set spellfile= - $put ='' - $put ='test '. a:aff . '-' . a:dic - " Generate a .spl file from a .dic and .aff file. - exe '1;/^' . a:aff . 'affstart/+1,/^' . a:aff . 'affend/-1w! Xtest.aff' - exe '1;/^' . a:dic . 'dicstart/+1,/^' . a:dic . 'dicend/-1w! Xtest.dic' - mkspell! Xtest Xtest - " use that spell file - set spl=Xtest.utf-8.spl spell - " list all valid words - spelldump - %yank - quit - $put - $put ='-------' - " find all bad words and suggestions for them - exe '1;/^' . a:aff . 'good:' - normal 0f:]s - let prevbad = '' - while 1 - let [bad, a] = spellbadword() - if bad == '' || bad == prevbad || bad == 'badend' - break - endif - let prevbad = bad - let lst = spellsuggest(bad, 3) - normal mm - $put =bad - $put =string(lst) - normal `m]s - endwhile -endfunc -:" -:call TestOne('1', '1') -:$put =soundfold('goobledygoook') -:$put =soundfold('kóopërÿnôven') -:$put =soundfold('oeverloos gezwets edale') -:" -:" -:" and now with SAL instead of SOFO items; test automatic reloading -gg:/^affstart_sal/+1,/^affend_sal/-1w! Xtest.aff -:mkspell! Xtest Xtest -:$put =soundfold('goobledygoook') -:$put =soundfold('kóopërÿnôven') -:$put =soundfold('oeverloos gezwets edale') -:" -:" also use an addition file -gg:/^addstart/+1,/^addend/-1w! Xtest.utf-8.add -:mkspell! Xtest.utf-8.add.spl Xtest.utf-8.add -:set spellfile=Xtest.utf-8.add -/^test2: -]s:let [str, a] = spellbadword() -:$put =str -:set spl=Xtest_us.utf-8.spl -/^test2: -]smm:let [str, a] = spellbadword() -:$put =str -`m]s:let [str, a] = spellbadword() -:$put =str -:set spl=Xtest_gb.utf-8.spl -/^test2: -]smm:let [str, a] = spellbadword() -:$put =str -`m]s:let [str, a] = spellbadword() -:$put =str -:set spl=Xtest_nz.utf-8.spl -/^test2: -]smm:let [str, a] = spellbadword() -:$put =str -`m]s:let [str, a] = spellbadword() -:$put =str -:set spl=Xtest_ca.utf-8.spl -/^test2: -]smm:let [str, a] = spellbadword() -:$put =str -`m]s:let [str, a] = spellbadword() -:$put =str -:unlet str a -:" -:" Postponed prefixes -:call TestOne('2', '1') -:" -:" Compound words -:call TestOne('3', '3') -:call TestOne('4', '4') -:call TestOne('5', '5') -:call TestOne('6', '6') -:call TestOne('7', '7') -:" -:" clean up for valgrind -:delfunc TestOne -:set spl= enc=latin1 -:" -gg:/^test output:/,$wq! test.out -ENDTEST - -1affstart -SET ISO8859-1 -TRY esianrtolcdugmphbyfvkwjkqxz-'ESIANRTOLCDUGMPHBYFVKWJKQXZ - -FOL -LOW -UPP - -SOFOFROM abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ޿ -SOFOTO ebctefghejklnnepkrstevvkesebctefghejklnnepkrstevvkeseeeeeeeceeeeeeeedneeeeeeeeeeepseeeeeeeeceeeeeeeedneeeeeeeeeeep? - -MIDWORD '- - -KEP = -RAR ? -BAD ! - -#NOSPLITSUGS - -PFX I N 1 -PFX I 0 in . - -PFX O Y 1 -PFX O 0 out . - -SFX S Y 2 -SFX S 0 s [^s] -SFX S 0 es s - -SFX N N 3 -SFX N 0 en [^n] -SFX N 0 nen n -SFX N 0 n . - -REP 3 -REP g ch -REP ch g -REP svp s.v.p. - -MAP 9 -MAP a -MAP e -MAP i -MAP o -MAP u -MAP n -MAP c -MAP y -MAP s -1affend - -affstart_sal -SET ISO8859-1 -TRY esianrtolcdugmphbyfvkwjkqxz-'ESIANRTOLCDUGMPHBYFVKWJKQXZ - -FOL -LOW -UPP - -MIDWORD '- - -KEP = -RAR ? -BAD ! - -#NOSPLITSUGS - -PFX I N 1 -PFX I 0 in . - -PFX O Y 1 -PFX O 0 out . - -SFX S Y 2 -SFX S 0 s [^s] -SFX S 0 es s - -SFX N N 3 -SFX N 0 en [^n] -SFX N 0 nen n -SFX N 0 n . - -REP 3 -REP g ch -REP ch g -REP svp s.v.p. - -MAP 9 -MAP a -MAP e -MAP i -MAP o -MAP u -MAP n -MAP c -MAP y -MAP s - -SAL AH(AEIOUY)-^ *H -SAL AR(AEIOUY)-^ *R -SAL A(HR)^ * -SAL A^ * -SAL AH(AEIOUY)- H -SAL AR(AEIOUY)- R -SAL A(HR) _ -SAL ^ * -SAL ^ * -SAL BB- _ -SAL B B -SAL CQ- _ -SAL CIA X -SAL CH X -SAL C(EIY)- S -SAL CK K -SAL COUGH^ KF -SAL CC< C -SAL C K -SAL DG(EIY) K -SAL DD- _ -SAL D T -SAL < E -SAL EH(AEIOUY)-^ *H -SAL ER(AEIOUY)-^ *R -SAL E(HR)^ * -SAL ENOUGH^$ *NF -SAL E^ * -SAL EH(AEIOUY)- H -SAL ER(AEIOUY)- R -SAL E(HR) _ -SAL FF- _ -SAL F F -SAL GN^ N -SAL GN$ N -SAL GNS$ NS -SAL GNED$ N -SAL GH(AEIOUY)- K -SAL GH _ -SAL GG9 K -SAL G K -SAL H H -SAL IH(AEIOUY)-^ *H -SAL IR(AEIOUY)-^ *R -SAL I(HR)^ * -SAL I^ * -SAL ING6 N -SAL IH(AEIOUY)- H -SAL IR(AEIOUY)- R -SAL I(HR) _ -SAL J K -SAL KN^ N -SAL KK- _ -SAL K K -SAL LAUGH^ LF -SAL LL- _ -SAL L L -SAL MB$ M -SAL MM M -SAL M M -SAL NN- _ -SAL N N -SAL OH(AEIOUY)-^ *H -SAL OR(AEIOUY)-^ *R -SAL O(HR)^ * -SAL O^ * -SAL OH(AEIOUY)- H -SAL OR(AEIOUY)- R -SAL O(HR) _ -SAL PH F -SAL PN^ N -SAL PP- _ -SAL P P -SAL Q K -SAL RH^ R -SAL ROUGH^ RF -SAL RR- _ -SAL R R -SAL SCH(EOU)- SK -SAL SC(IEY)- S -SAL SH X -SAL SI(AO)- X -SAL SS- _ -SAL S S -SAL TI(AO)- X -SAL TH @ -SAL TCH-- _ -SAL TOUGH^ TF -SAL TT- _ -SAL T T -SAL UH(AEIOUY)-^ *H -SAL UR(AEIOUY)-^ *R -SAL U(HR)^ * -SAL U^ * -SAL UH(AEIOUY)- H -SAL UR(AEIOUY)- R -SAL U(HR) _ -SAL V^ W -SAL V F -SAL WR^ R -SAL WH^ W -SAL W(AEIOU)- W -SAL X^ S -SAL X KS -SAL Y(AEIOU)- Y -SAL ZZ- _ -SAL Z S -affend_sal - -2affstart -SET ISO8859-1 - -FOL -LOW -UPP - -PFXPOSTPONE - -MIDWORD '- - -KEP = -RAR ? -BAD ! - -#NOSPLITSUGS - -PFX I N 1 -PFX I 0 in . - -PFX O Y 1 -PFX O 0 out [a-z] - -SFX S Y 2 -SFX S 0 s [^s] -SFX S 0 es s - -SFX N N 3 -SFX N 0 en [^n] -SFX N 0 nen n -SFX N 0 n . - -REP 3 -REP g ch -REP ch g -REP svp s.v.p. - -MAP 9 -MAP a -MAP e -MAP i -MAP o -MAP u -MAP n -MAP c -MAP y -MAP s -2affend - -1dicstart -123456 -test/NO -# comment -wrong -Comment -OK -uk -put/ISO -the end -deol -dr -1dicend - -addstart -/regions=usgbnz -elequint/2 -elekwint/3 -addend - -1good: wrong OK puts. Test the end -bad: inputs comment ok Ok. test déôl end the -badend - -2good: puts -bad: inputs comment ok Ok end the. test déôl -badend - -Test rules for compounding. - -3affstart -SET ISO8859-1 - -COMPOUNDMIN 3 -COMPOUNDRULE m* -NEEDCOMPOUND x -3affend - -3dicstart -1234 -foo/m -bar/mx -m/m -la/mx -3dicend - -3good: foo mï foobar foofoobar barfoo barbarfoo -bad: bar la foomï barmï mïfoo mïbar mïmï lala mïla lamï foola labar -badend - - -Tests for compounding. - -4affstart -SET ISO8859-1 - -FOL -LOW -UPP - -COMPOUNDRULE m+ -COMPOUNDRULE sm*e -COMPOUNDRULE sm+ -COMPOUNDMIN 3 -COMPOUNDWORDMAX 3 -COMPOUNDFORBIDFLAG t - -COMPOUNDSYLMAX 5 -SYLLABLE aeiouy/aa/au/ea/ee/ei/ie/oa/oe/oo/ou/uu/ui - -MAP 9 -MAP a -MAP e -MAP i -MAP o -MAP u -MAP n -MAP c -MAP y -MAP s - -NEEDAFFIX x - -PFXPOSTPONE - -MIDWORD '- - -SFX q N 1 -SFX q 0 -ok . - -SFX a Y 2 -SFX a 0 s . -SFX a 0 ize/t . - -PFX p N 1 -PFX p 0 pre . - -PFX P N 1 -PFX P 0 nou . -4affend - -4dicstart -1234 -word/mP -util/am -pro/xq -tomato/m -bork/mp -start/s -end/e -4dicend - -4good: word util bork prebork start end wordutil wordutils pro-ok - bork borkbork borkborkbork borkborkborkbork borkborkborkborkbork - tomato tomatotomato startend startword startwordword startwordend - startwordwordend startwordwordwordend prebork preborkbork - preborkborkbork - nouword -bad: wordutilize pro borkborkborkborkborkbork tomatotomatotomato - endstart endend startstart wordend wordstart - preborkprebork preborkpreborkbork - startwordwordwordwordend borkpreborkpreborkbork - utilsbork startnouword -badend - -test2: -elequint test elekwint test elekwent asdf - -Test affix flags with two characters - -5affstart -SET ISO8859-1 - -FLAG long - -NEEDAFFIX !! - -COMPOUNDRULE ssmm*ee - -NEEDCOMPOUND xx -COMPOUNDPERMITFLAG pp - -SFX 13 Y 1 -SFX 13 0 bork . - -SFX a1 Y 1 -SFX a1 0 a1 . - -SFX a Y 1 -SFX a 0 a . - -PFX zz Y 1 -PFX zz 0 pre/pp . - -PFX yy Y 1 -PFX yy 0 nou . -5affend - -5dicstart -1234 -foo/a1a!! -bar/zz13ee -start/ss -end/eeyy -middle/mmxx -5dicend - -5good: fooa1 fooaé bar prebar barbork prebarbork startprebar - start end startend startmiddleend nouend -bad: foo fooa2 prabar probarbirk middle startmiddle middleend endstart - startprobar startnouend -badend - -6affstart -SET ISO8859-1 - -FLAG caplong - -NEEDAFFIX A! - -COMPOUNDRULE sMm*Ee - -NEEDCOMPOUND Xx - -COMPOUNDPERMITFLAG p - -SFX N3 Y 1 -SFX N3 0 bork . - -SFX A1 Y 1 -SFX A1 0 a1 . - -SFX A Y 1 -SFX A 0 a . - -PFX Zz Y 1 -PFX Zz 0 pre/p . -6affend - -6dicstart -1234 -mee/A1AA! -bar/ZzN3Ee -lead/s -end/Ee -middle/MmXx -6dicend - -6good: meea1 meeaé bar prebar barbork prebarbork leadprebar - lead end leadend leadmiddleend -bad: mee meea2 prabar probarbirk middle leadmiddle middleend endlead - leadprobar -badend - -7affstart -SET ISO8859-1 - -FOL -LOW -UPP - -FLAG num - -NEEDAFFIX 9999 - -COMPOUNDRULE 2,77*123 - -NEEDCOMPOUND 1 -COMPOUNDPERMITFLAG 432 - -SFX 61003 Y 1 -SFX 61003 0 meat . - -SFX 391 Y 1 -SFX 391 0 a1 . - -SFX 111 Y 1 -SFX 111 0 a . - -PFX 17 Y 1 -PFX 17 0 pre/432 . -7affend - -7dicstart -1234 -mee/391,111,9999 -bar/17,61003,123 -lead/2 -tail/123 -middle/77,1 -7dicend - -7good: meea1 meeaé bar prebar barmeat prebarmeat leadprebar - lead tail leadtail leadmiddletail -bad: mee meea2 prabar probarmaat middle leadmiddle middletail taillead - leadprobar -badend - -test output: diff --git a/src/testdir/test59.ok b/src/testdir/test59.ok deleted file mode 100644 index 931cdd96544bb1..00000000000000 --- a/src/testdir/test59.ok +++ /dev/null @@ -1,270 +0,0 @@ -test output: - -test 1-1 -# file: Xtest.utf-8.spl -Comment -deol -déôr -input -OK -output -outputs -outtest -put -puts -test -testen -testn -the end -uk -wrong -------- -bad -['put', 'uk', 'OK'] -inputs -['input', 'puts', 'outputs'] -comment -['Comment', 'outtest', 'the end'] -ok -['OK', 'uk', 'put'] -Ok -['OK', 'Uk', 'Put'] -test -['Test', 'testn', 'testen'] -déôl -['deol', 'déôr', 'test'] -end -['put', 'uk', 'test'] -the -['put', 'uk', 'test'] -gebletegek -kepereneven -everles gesvets etele -kbltykk -kprnfn -*fls kswts tl -elekwent -elequint -elekwint -elekwint -elekwent -elequint -elekwent -elequint -elekwint - -test 2-1 -# file: Xtest.utf-8.spl -Comment -deol -déôr -OK -put -input -output -puts -outputs -test -outtest -testen -testn -the end -uk -wrong -------- -bad -['put', 'uk', 'OK'] -inputs -['input', 'puts', 'outputs'] -comment -['Comment'] -ok -['OK', 'uk', 'put'] -Ok -['OK', 'Uk', 'Put'] -end -['put', 'uk', 'deol'] -the -['put', 'uk', 'test'] -test -['Test', 'testn', 'testen'] -déôl -['deol', 'déôr', 'test'] - -test 3-3 -# file: Xtest.utf-8.spl -foo -mï -------- -bad -['foo', 'mï'] -bar -['barfoo', 'foobar', 'foo'] -la -['mï', 'foo'] -foomï -['foo mï', 'foo', 'foofoo'] -barmï -['barfoo', 'mï', 'barbar'] -mïfoo -['mï foo', 'foo', 'foofoo'] -mïbar -['foobar', 'barbar', 'mï'] -mïmï -['mï mï', 'mï'] -lala -[] -mïla -['mï', 'mï mï'] -lamï -['mï', 'mï mï'] -foola -['foo', 'foobar', 'foofoo'] -labar -['barbar', 'foobar'] - -test 4-4 -# file: Xtest.utf-8.spl -bork -prebork -end -pro-ok -start -tomato -util -utilize -utils -word -nouword -------- -bad -['end', 'bork', 'word'] -wordutilize -['word utilize', 'wordutils', 'wordutil'] -pro -['bork', 'word', 'end'] -borkborkborkborkborkbork -['bork borkborkborkborkbork', 'borkbork borkborkborkbork', 'borkborkbork borkborkbork'] -tomatotomatotomato -['tomato tomatotomato', 'tomatotomato tomato', 'tomato tomato tomato'] -endstart -['end start', 'start'] -endend -['end end', 'end'] -startstart -['start start'] -wordend -['word end', 'word', 'wordword'] -wordstart -['word start', 'bork start'] -preborkprebork -['prebork prebork', 'preborkbork', 'preborkborkbork'] -preborkpreborkbork -['prebork preborkbork', 'preborkborkbork', 'preborkborkborkbork'] -startwordwordwordwordend -['startwordwordwordword end', 'startwordwordwordword', 'start wordwordwordword end'] -borkpreborkpreborkbork -['bork preborkpreborkbork', 'bork prebork preborkbork', 'bork preborkprebork bork'] -utilsbork -['utilbork', 'utils bork', 'util bork'] -startnouword -['start nouword', 'startword', 'startborkword'] - -test 5-5 -# file: Xtest.utf-8.spl -bar -barbork -end -fooa1 -fooaé -nouend -prebar -prebarbork -start -------- -bad -['bar', 'end', 'fooa1'] -foo -['fooa1', 'fooaé', 'bar'] -fooa2 -['fooa1', 'fooaé', 'bar'] -prabar -['prebar', 'bar', 'bar bar'] -probarbirk -['prebarbork'] -middle -[] -startmiddle -['startmiddleend', 'startmiddlebar'] -middleend -[] -endstart -['end start', 'start'] -startprobar -['startprebar', 'start prebar', 'startbar'] -startnouend -['start nouend', 'startend'] - -test 6-6 -# file: Xtest.utf-8.spl -bar -barbork -end -lead -meea1 -meeaé -prebar -prebarbork -------- -bad -['bar', 'end', 'lead'] -mee -['meea1', 'meeaé', 'bar'] -meea2 -['meea1', 'meeaé', 'lead'] -prabar -['prebar', 'bar', 'leadbar'] -probarbirk -['prebarbork'] -middle -[] -leadmiddle -['leadmiddleend', 'leadmiddlebar'] -middleend -[] -endlead -['end lead', 'lead', 'end end'] -leadprobar -['leadprebar', 'lead prebar', 'leadbar'] - -test 7-7 -# file: Xtest.utf-8.spl -bar -barmeat -lead -meea1 -meeaé -prebar -prebarmeat -tail -------- -bad -['bar', 'lead', 'tail'] -mee -['meea1', 'meeaé', 'bar'] -meea2 -['meea1', 'meeaé', 'lead'] -prabar -['prebar', 'bar', 'leadbar'] -probarmaat -['prebarmeat'] -middle -[] -leadmiddle -['leadmiddlebar'] -middletail -[] -taillead -['tail lead', 'tail'] -leadprobar -['leadprebar', 'lead prebar', 'leadbar'] diff --git a/src/testdir/test_spell_utf8.vim b/src/testdir/test_spell_utf8.vim new file mode 100644 index 00000000000000..1f561e46a97b32 --- /dev/null +++ b/src/testdir/test_spell_utf8.vim @@ -0,0 +1,768 @@ +" Test for spell checking with 'encoding' set to utf-8 + +source check.vim +CheckFeature spell + +scriptencoding utf-8 + +func TearDown() + set nospell + call delete('Xtest.aff') + call delete('Xtest.dic') + call delete('Xtest.utf-8.add') + call delete('Xtest.utf-8.add.spl') + call delete('Xtest.utf-8.spl') + call delete('Xtest.utf-8.sug') +endfunc + +let g:test_data_aff1 = [ + \"SET ISO8859-1", + \"TRY esianrtolcdugmphbyfvkwjkqxz-ëéèêïîäàâöüû'ESIANRTOLCDUGMPHBYFVKWJKQXZ", + \"", + \"FOL àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþßÿ", + \"LOW àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþßÿ", + \"UPP ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßÿ", + \"", + \"SOFOFROM abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xBF", + \"SOFOTO ebctefghejklnnepkrstevvkesebctefghejklnnepkrstevvkeseeeeeeeceeeeeeeedneeeeeeeeeeepseeeeeeeeceeeeeeeedneeeeeeeeeeep?", + \"", + \"MIDWORD\t'-", + \"", + \"KEP =", + \"RAR ?", + \"BAD !", + \"", + \"PFX I N 1", + \"PFX I 0 in .", + \"", + \"PFX O Y 1", + \"PFX O 0 out .", + \"", + \"SFX S Y 2", + \"SFX S 0 s [^s]", + \"SFX S 0 es s", + \"", + \"SFX N N 3", + \"SFX N 0 en [^n]", + \"SFX N 0 nen n", + \"SFX N 0 n .", + \"", + \"REP 3", + \"REP g ch", + \"REP ch g", + \"REP svp s.v.p.", + \"", + \"MAP 9", + \"MAP a\xE0\xE1\xE2\xE3\xE4\xE5", + \"MAP e\xE8\xE9\xEA\xEB", + \"MAP i\xEC\xED\xEE\xEF", + \"MAP o\xF2\xF3\xF4\xF5\xF6", + \"MAP u\xF9\xFA\xFB\xFC", + \"MAP n\xF1", + \"MAP c\xE7", + \"MAP y\xFF\xFD", + \"MAP s\xDF" + \ ] +let g:test_data_dic1 = [ + \"123456", + \"test/NO", + \"# comment", + \"wrong", + \"Comment", + \"OK", + \"uk", + \"put/ISO", + \"the end", + \"deol", + \"d\xE9\xF4r", + \ ] +let g:test_data_aff2 = [ + \"SET ISO8859-1", + \"", + \"FOL \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"LOW \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"UPP \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xFF", + \"", + \"PFXPOSTPONE", + \"", + \"MIDWORD\t'-", + \"", + \"KEP =", + \"RAR ?", + \"BAD !", + \"", + \"PFX I N 1", + \"PFX I 0 in .", + \"", + \"PFX O Y 1", + \"PFX O 0 out [a-z]", + \"", + \"SFX S Y 2", + \"SFX S 0 s [^s]", + \"SFX S 0 es s", + \"", + \"SFX N N 3", + \"SFX N 0 en [^n]", + \"SFX N 0 nen n", + \"SFX N 0 n .", + \"", + \"REP 3", + \"REP g ch", + \"REP ch g", + \"REP svp s.v.p.", + \"", + \"MAP 9", + \"MAP a\xE0\xE1\xE2\xE3\xE4\xE5", + \"MAP e\xE8\xE9\xEA\xEB", + \"MAP i\xEC\xED\xEE\xEF", + \"MAP o\xF2\xF3\xF4\xF5\xF6", + \"MAP u\xF9\xFA\xFB\xFC", + \"MAP n\xF1", + \"MAP c\xE7", + \"MAP y\xFF\xFD", + \"MAP s\xDF", + \ ] +let g:test_data_aff3 = [ + \"SET ISO8859-1", + \"", + \"COMPOUNDMIN 3", + \"COMPOUNDRULE m*", + \"NEEDCOMPOUND x", + \ ] +let g:test_data_dic3 = [ + \"1234", + \"foo/m", + \"bar/mx", + \"m\xEF/m", + \"la/mx", + \ ] +let g:test_data_aff4 = [ + \"SET ISO8859-1", + \"", + \"FOL \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"LOW \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"UPP \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xFF", + \"", + \"COMPOUNDRULE m+", + \"COMPOUNDRULE sm*e", + \"COMPOUNDRULE sm+", + \"COMPOUNDMIN 3", + \"COMPOUNDWORDMAX 3", + \"COMPOUNDFORBIDFLAG t", + \"", + \"COMPOUNDSYLMAX 5", + \"SYLLABLE a\xE1e\xE9i\xEDo\xF3\xF6\xF5u\xFA\xFC\xFBy/aa/au/ea/ee/ei/ie/oa/oe/oo/ou/uu/ui", + \"", + \"MAP 9", + \"MAP a\xE0\xE1\xE2\xE3\xE4\xE5", + \"MAP e\xE8\xE9\xEA\xEB", + \"MAP i\xEC\xED\xEE\xEF", + \"MAP o\xF2\xF3\xF4\xF5\xF6", + \"MAP u\xF9\xFA\xFB\xFC", + \"MAP n\xF1", + \"MAP c\xE7", + \"MAP y\xFF\xFD", + \"MAP s\xDF", + \"", + \"NEEDAFFIX x", + \"", + \"PFXPOSTPONE", + \"", + \"MIDWORD '-", + \"", + \"SFX q N 1", + \"SFX q 0 -ok .", + \"", + \"SFX a Y 2", + \"SFX a 0 s .", + \"SFX a 0 ize/t .", + \"", + \"PFX p N 1", + \"PFX p 0 pre .", + \"", + \"PFX P N 1", + \"PFX P 0 nou .", + \ ] +let g:test_data_dic4 = [ + \"1234", + \"word/mP", + \"util/am", + \"pro/xq", + \"tomato/m", + \"bork/mp", + \"start/s", + \"end/e", + \ ] +let g:test_data_aff5 = [ + \"SET ISO8859-1", + \"", + \"FLAG long", + \"", + \"NEEDAFFIX !!", + \"", + \"COMPOUNDRULE ssmm*ee", + \"", + \"NEEDCOMPOUND xx", + \"COMPOUNDPERMITFLAG pp", + \"", + \"SFX 13 Y 1", + \"SFX 13 0 bork .", + \"", + \"SFX a1 Y 1", + \"SFX a1 0 a1 .", + \"", + \"SFX a\xE9 Y 1", + \"SFX a\xE9 0 a\xE9 .", + \"", + \"PFX zz Y 1", + \"PFX zz 0 pre/pp .", + \"", + \"PFX yy Y 1", + \"PFX yy 0 nou .", + \ ] +let g:test_data_dic5 = [ + \"1234", + \"foo/a1a\xE9!!", + \"bar/zz13ee", + \"start/ss", + \"end/eeyy", + \"middle/mmxx", + \ ] +let g:test_data_aff6 = [ + \"SET ISO8859-1", + \"", + \"FLAG caplong", + \"", + \"NEEDAFFIX A!", + \"", + \"COMPOUNDRULE sMm*Ee", + \"", + \"NEEDCOMPOUND Xx", + \"", + \"COMPOUNDPERMITFLAG p", + \"", + \"SFX N3 Y 1", + \"SFX N3 0 bork .", + \"", + \"SFX A1 Y 1", + \"SFX A1 0 a1 .", + \"", + \"SFX A\xE9 Y 1", + \"SFX A\xE9 0 a\xE9 .", + \"", + \"PFX Zz Y 1", + \"PFX Zz 0 pre/p .", + \ ] +let g:test_data_dic6 = [ + \"1234", + \"mee/A1A\xE9A!", + \"bar/ZzN3Ee", + \"lead/s", + \"end/Ee", + \"middle/MmXx", + \ ] +let g:test_data_aff7 = [ + \"SET ISO8859-1", + \"", + \"FLAG num", + \"", + \"NEEDAFFIX 9999", + \"", + \"COMPOUNDRULE 2,77*123", + \"", + \"NEEDCOMPOUND 1", + \"COMPOUNDPERMITFLAG 432", + \"", + \"SFX 61003 Y 1", + \"SFX 61003 0 meat .", + \"", + \"SFX 0 Y 1", + \"SFX 0 0 zero .", + \"", + \"SFX 391 Y 1", + \"SFX 391 0 a1 .", + \"", + \"SFX 111 Y 1", + \"SFX 111 0 a\xE9 .", + \"", + \"PFX 17 Y 1", + \"PFX 17 0 pre/432 .", + \ ] +let g:test_data_dic7 = [ + \"1234", + \"mee/0,391,111,9999", + \"bar/17,61003,123", + \"lead/2", + \"tail/123", + \"middle/77,1", + \ ] +let g:test_data_aff8 = [ + \"SET ISO8859-1", + \"", + \"NOSPLITSUGS", + \ ] +let g:test_data_dic8 = [ + \"1234", + \"foo", + \"bar", + \"faabar", + \ ] +let g:test_data_aff9 = [ + \ ] +let g:test_data_dic9 = [ + \"1234", + \"foo", + \"bar", + \ ] +let g:test_data_aff10 = [ + \"COMPOUNDRULE se", + \"COMPOUNDPERMITFLAG p", + \"", + \"SFX A Y 1", + \"SFX A 0 able/Mp .", + \"", + \"SFX M Y 1", + \"SFX M 0 s .", + \ ] +let g:test_data_dic10 = [ + \"1234", + \"drink/As", + \"table/e", + \ ] +let g:test_data_aff_sal = [ + \"SET ISO8859-1", + \"TRY esianrtolcdugmphbyfvkwjkqxz-\xEB\xE9\xE8\xEA\xEF\xEE\xE4\xE0\xE2\xF6\xFC\xFB'ESIANRTOLCDUGMPHBYFVKWJKQXZ", + \"", + \"FOL \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"LOW \xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xDF\xFF", + \"UPP \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xFF", + \"", + \"MIDWORD\t'-", + \"", + \"KEP =", + \"RAR ?", + \"BAD !", + \"", + \"PFX I N 1", + \"PFX I 0 in .", + \"", + \"PFX O Y 1", + \"PFX O 0 out .", + \"", + \"SFX S Y 2", + \"SFX S 0 s [^s]", + \"SFX S 0 es s", + \"", + \"SFX N N 3", + \"SFX N 0 en [^n]", + \"SFX N 0 nen n", + \"SFX N 0 n .", + \"", + \"REP 3", + \"REP g ch", + \"REP ch g", + \"REP svp s.v.p.", + \"", + \"MAP 9", + \"MAP a\xE0\xE1\xE2\xE3\xE4\xE5", + \"MAP e\xE8\xE9\xEA\xEB", + \"MAP i\xEC\xED\xEE\xEF", + \"MAP o\xF2\xF3\xF4\xF5\xF6", + \"MAP u\xF9\xFA\xFB\xFC", + \"MAP n\xF1", + \"MAP c\xE7", + \"MAP y\xFF\xFD", + \"MAP s\xDF", + \"", + \"SAL AH(AEIOUY)-^ *H", + \"SAL AR(AEIOUY)-^ *R", + \"SAL A(HR)^ *", + \"SAL A^ *", + \"SAL AH(AEIOUY)- H", + \"SAL AR(AEIOUY)- R", + \"SAL A(HR) _", + \"SAL \xC0^ *", + \"SAL \xC5^ *", + \"SAL BB- _", + \"SAL B B", + \"SAL CQ- _", + \"SAL CIA X", + \"SAL CH X", + \"SAL C(EIY)- S", + \"SAL CK K", + \"SAL COUGH^ KF", + \"SAL CC< C", + \"SAL C K", + \"SAL DG(EIY) K", + \"SAL DD- _", + \"SAL D T", + \"SAL \xC9< E", + \"SAL EH(AEIOUY)-^ *H", + \"SAL ER(AEIOUY)-^ *R", + \"SAL E(HR)^ *", + \"SAL ENOUGH^$ *NF", + \"SAL E^ *", + \"SAL EH(AEIOUY)- H", + \"SAL ER(AEIOUY)- R", + \"SAL E(HR) _", + \"SAL FF- _", + \"SAL F F", + \"SAL GN^ N", + \"SAL GN$ N", + \"SAL GNS$ NS", + \"SAL GNED$ N", + \"SAL GH(AEIOUY)- K", + \"SAL GH _", + \"SAL GG9 K", + \"SAL G K", + \"SAL H H", + \"SAL IH(AEIOUY)-^ *H", + \"SAL IR(AEIOUY)-^ *R", + \"SAL I(HR)^ *", + \"SAL I^ *", + \"SAL ING6 N", + \"SAL IH(AEIOUY)- H", + \"SAL IR(AEIOUY)- R", + \"SAL I(HR) _", + \"SAL J K", + \"SAL KN^ N", + \"SAL KK- _", + \"SAL K K", + \"SAL LAUGH^ LF", + \"SAL LL- _", + \"SAL L L", + \"SAL MB$ M", + \"SAL MM M", + \"SAL M M", + \"SAL NN- _", + \"SAL N N", + \"SAL OH(AEIOUY)-^ *H", + \"SAL OR(AEIOUY)-^ *R", + \"SAL O(HR)^ *", + \"SAL O^ *", + \"SAL OH(AEIOUY)- H", + \"SAL OR(AEIOUY)- R", + \"SAL O(HR) _", + \"SAL PH F", + \"SAL PN^ N", + \"SAL PP- _", + \"SAL P P", + \"SAL Q K", + \"SAL RH^ R", + \"SAL ROUGH^ RF", + \"SAL RR- _", + \"SAL R R", + \"SAL SCH(EOU)- SK", + \"SAL SC(IEY)- S", + \"SAL SH X", + \"SAL SI(AO)- X", + \"SAL SS- _", + \"SAL S S", + \"SAL TI(AO)- X", + \"SAL TH @", + \"SAL TCH-- _", + \"SAL TOUGH^ TF", + \"SAL TT- _", + \"SAL T T", + \"SAL UH(AEIOUY)-^ *H", + \"SAL UR(AEIOUY)-^ *R", + \"SAL U(HR)^ *", + \"SAL U^ *", + \"SAL UH(AEIOUY)- H", + \"SAL UR(AEIOUY)- R", + \"SAL U(HR) _", + \"SAL V^ W", + \"SAL V F", + \"SAL WR^ R", + \"SAL WH^ W", + \"SAL W(AEIOU)- W", + \"SAL X^ S", + \"SAL X KS", + \"SAL Y(AEIOU)- Y", + \"SAL ZZ- _", + \"SAL Z S", + \ ] + +func LoadAffAndDic(aff_contents, dic_contents) + set enc=utf-8 + set spellfile= + call writefile(a:aff_contents, "Xtest.aff") + call writefile(a:dic_contents, "Xtest.dic") + " Generate a .spl file from a .dic and .aff file. + mkspell! Xtest Xtest + " use that spell file + set spl=Xtest.utf-8.spl spell +endfunc + +func ListWords() + spelldump + %yank + quit + return split(@", "\n") +endfunc + +func TestGoodBadBase() + exe '1;/^good:' + normal 0f:]s + let prevbad = '' + let result = [] + while 1 + let [bad, a] = spellbadword() + if bad == '' || bad == prevbad || bad == 'badend' + break + endif + let prevbad = bad + let lst = bad->spellsuggest(3) + normal mm + + call add(result, [bad, lst]) + normal `m]s + endwhile + return result +endfunc + +func RunGoodBad(good, bad, expected_words, expected_bad_words) + %bwipe! + call setline(1, ['', "good: ", a:good, a:bad, " badend "]) + let words = ListWords() + call assert_equal(a:expected_words, words[1:-1]) + let bad_words = TestGoodBadBase() + call assert_equal(a:expected_bad_words, bad_words) + %bwipe! +endfunc + +func Test_spell_basic() + call LoadAffAndDic(g:test_data_aff1, g:test_data_dic1) + call RunGoodBad("wrong OK puts. Test the end", + \ "bad: inputs comment ok Ok. test d\u00E9\u00F4l end the", + \["Comment", "deol", "d\u00E9\u00F4r", "input", "OK", "output", "outputs", "outtest", "put", "puts", + \ "test", "testen", "testn", "the end", "uk", "wrong"], + \[ + \ ["bad", ["put", "uk", "OK"]], + \ ["inputs", ["input", "puts", "outputs"]], + \ ["comment", ["Comment", "outtest", "the end"]], + \ ["ok", ["OK", "uk", "put"]], + \ ["Ok", ["OK", "Uk", "Put"]], + \ ["test", ["Test", "testn", "testen"]], + \ ["d\u00E9\u00F4l", ["deol", "d\u00E9\u00F4r", "test"]], + \ ["end", ["put", "uk", "test"]], + \ ["the", ["put", "uk", "test"]], + \ ] + \ ) + + call assert_equal("gebletegek", soundfold('goobledygoook')) + call assert_equal("kepereneven", 'kóopërÿnôven'->soundfold()) + call assert_equal("everles gesvets etele", soundfold('oeverloos gezwets edale')) +endfunc + +" Postponed prefixes +func Test_spell_prefixes() + call LoadAffAndDic(g:test_data_aff2, g:test_data_dic1) + call RunGoodBad("puts", + \ "bad: inputs comment ok Ok end the. test d\u00E9\u00F4l", + \ ["Comment", "deol", "d\u00E9\u00F4r", "OK", "put", "input", "output", "puts", "outputs", "test", "outtest", "testen", "testn", "the end", "uk", "wrong"], + \ [ + \ ["bad", ["put", "uk", "OK"]], + \ ["inputs", ["input", "puts", "outputs"]], + \ ["comment", ["Comment"]], + \ ["ok", ["OK", "uk", "put"]], + \ ["Ok", ["OK", "Uk", "Put"]], + \ ["end", ["put", "uk", "deol"]], + \ ["the", ["put", "uk", "test"]], + \ ["test", ["Test", "testn", "testen"]], + \ ["d\u00E9\u00F4l", ["deol", "d\u00E9\u00F4r", "test"]], + \ ]) +endfunc + +"Compound words +func Test_spell_compound() + call LoadAffAndDic(g:test_data_aff3, g:test_data_dic3) + call RunGoodBad("foo m\u00EF foobar foofoobar barfoo barbarfoo", + \ "bad: bar la foom\u00EF barm\u00EF m\u00EFfoo m\u00EFbar m\u00EFm\u00EF lala m\u00EFla lam\u00EF foola labar", + \ ["foo", "m\u00EF"], + \ [ + \ ["bad", ["foo", "m\u00EF"]], + \ ["bar", ["barfoo", "foobar", "foo"]], + \ ["la", ["m\u00EF", "foo"]], + \ ["foom\u00EF", ["foo m\u00EF", "foo", "foofoo"]], + \ ["barm\u00EF", ["barfoo", "m\u00EF", "barbar"]], + \ ["m\u00EFfoo", ["m\u00EF foo", "foo", "foofoo"]], + \ ["m\u00EFbar", ["foobar", "barbar", "m\u00EF"]], + \ ["m\u00EFm\u00EF", ["m\u00EF m\u00EF", "m\u00EF"]], + \ ["lala", []], + \ ["m\u00EFla", ["m\u00EF", "m\u00EF m\u00EF"]], + \ ["lam\u00EF", ["m\u00EF", "m\u00EF m\u00EF"]], + \ ["foola", ["foo", "foobar", "foofoo"]], + \ ["labar", ["barbar", "foobar"]], + \ ]) + + call LoadAffAndDic(g:test_data_aff4, g:test_data_dic4) + call RunGoodBad("word util bork prebork start end wordutil wordutils pro-ok bork borkbork borkborkbork borkborkborkbork borkborkborkborkbork tomato tomatotomato startend startword startwordword startwordend startwordwordend startwordwordwordend prebork preborkbork preborkborkbork nouword", + \ "bad: wordutilize pro borkborkborkborkborkbork tomatotomatotomato endstart endend startstart wordend wordstart preborkprebork preborkpreborkbork startwordwordwordwordend borkpreborkpreborkbork utilsbork startnouword", + \ ["bork", "prebork", "end", "pro-ok", "start", "tomato", "util", "utilize", "utils", "word", "nouword"], + \ [ + \ ["bad", ["end", "bork", "word"]], + \ ["wordutilize", ["word utilize", "wordutils", "wordutil"]], + \ ["pro", ["bork", "word", "end"]], + \ ["borkborkborkborkborkbork", ["bork borkborkborkborkbork", "borkbork borkborkborkbork", "borkborkbork borkborkbork"]], + \ ["tomatotomatotomato", ["tomato tomatotomato", "tomatotomato tomato", "tomato tomato tomato"]], + \ ["endstart", ["end start", "start"]], + \ ["endend", ["end end", "end"]], + \ ["startstart", ["start start"]], + \ ["wordend", ["word end", "word", "wordword"]], + \ ["wordstart", ["word start", "bork start"]], + \ ["preborkprebork", ["prebork prebork", "preborkbork", "preborkborkbork"]], + \ ["preborkpreborkbork", ["prebork preborkbork", "preborkborkbork", "preborkborkborkbork"]], + \ ["startwordwordwordwordend", ["startwordwordwordword end", "startwordwordwordword", "start wordwordwordword end"]], + \ ["borkpreborkpreborkbork", ["bork preborkpreborkbork", "bork prebork preborkbork", "bork preborkprebork bork"]], + \ ["utilsbork", ["utilbork", "utils bork", "util bork"]], + \ ["startnouword", ["start nouword", "startword", "startborkword"]], + \ ]) + +endfunc + +" Test affix flags with two characters +func Test_spell_affix() + call LoadAffAndDic(g:test_data_aff5, g:test_data_dic5) + call RunGoodBad("fooa1 fooa\u00E9 bar prebar barbork prebarbork startprebar start end startend startmiddleend nouend", + \ "bad: foo fooa2 prabar probarbirk middle startmiddle middleend endstart startprobar startnouend", + \ ["bar", "barbork", "end", "fooa1", "fooa\u00E9", "nouend", "prebar", "prebarbork", "start"], + \ [ + \ ["bad", ["bar", "end", "fooa1"]], + \ ["foo", ["fooa1", "fooa\u00E9", "bar"]], + \ ["fooa2", ["fooa1", "fooa\u00E9", "bar"]], + \ ["prabar", ["prebar", "bar", "bar bar"]], + \ ["probarbirk", ["prebarbork"]], + \ ["middle", []], + \ ["startmiddle", ["startmiddleend", "startmiddlebar"]], + \ ["middleend", []], + \ ["endstart", ["end start", "start"]], + \ ["startprobar", ["startprebar", "start prebar", "startbar"]], + \ ["startnouend", ["start nouend", "startend"]], + \ ]) + + call LoadAffAndDic(g:test_data_aff6, g:test_data_dic6) + call RunGoodBad("meea1 meea\u00E9 bar prebar barbork prebarbork leadprebar lead end leadend leadmiddleend", + \ "bad: mee meea2 prabar probarbirk middle leadmiddle middleend endlead leadprobar", + \ ["bar", "barbork", "end", "lead", "meea1", "meea\u00E9", "prebar", "prebarbork"], + \ [ + \ ["bad", ["bar", "end", "lead"]], + \ ["mee", ["meea1", "meea\u00E9", "bar"]], + \ ["meea2", ["meea1", "meea\u00E9", "lead"]], + \ ["prabar", ["prebar", "bar", "leadbar"]], + \ ["probarbirk", ["prebarbork"]], + \ ["middle", []], + \ ["leadmiddle", ["leadmiddleend", "leadmiddlebar"]], + \ ["middleend", []], + \ ["endlead", ["end lead", "lead", "end end"]], + \ ["leadprobar", ["leadprebar", "lead prebar", "leadbar"]], + \ ]) + + call LoadAffAndDic(g:test_data_aff7, g:test_data_dic7) + call RunGoodBad("meea1 meezero meea\u00E9 bar prebar barmeat prebarmeat leadprebar lead tail leadtail leadmiddletail", + \ "bad: mee meea2 prabar probarmaat middle leadmiddle middletail taillead leadprobar", + \ ["bar", "barmeat", "lead", "meea1", "meea\u00E9", "meezero", "prebar", "prebarmeat", "tail"], + \ [ + \ ["bad", ["bar", "lead", "tail"]], + \ ["mee", ["meea1", "meea\u00E9", "bar"]], + \ ["meea2", ["meea1", "meea\u00E9", "lead"]], + \ ["prabar", ["prebar", "bar", "leadbar"]], + \ ["probarmaat", ["prebarmeat"]], + \ ["middle", []], + \ ["leadmiddle", ["leadmiddlebar"]], + \ ["middletail", []], + \ ["taillead", ["tail lead", "tail"]], + \ ["leadprobar", ["leadprebar", "lead prebar", "leadbar"]], + \ ]) +endfunc + +func Test_spell_NOSLITSUGS() + call LoadAffAndDic(g:test_data_aff8, g:test_data_dic8) + call RunGoodBad("foo bar faabar", "bad: foobar barfoo", + \ ["bar", "faabar", "foo"], + \ [ + \ ["bad", ["bar", "foo"]], + \ ["foobar", ["faabar", "foo bar", "bar"]], + \ ["barfoo", ["bar foo", "bar", "foo"]], + \ ]) +endfunc + +" Numbers +func Test_spell_Numbers() + call LoadAffAndDic(g:test_data_aff9, g:test_data_dic9) + call RunGoodBad("0b1011 0777 1234 0x01ff", "", + \ ["bar", "foo"], + \ [ + \ ]) +endfunc + +" Affix flags +func Test_spell_affix_flags() + call LoadAffAndDic(g:test_data_aff10, g:test_data_dic10) + call RunGoodBad("drink drinkable drinkables drinktable drinkabletable", + \ "bad: drinks drinkstable drinkablestable", + \ ["drink", "drinkable", "drinkables", "table"], + \ [['bad', []], + \ ['drinks', ['drink']], + \ ['drinkstable', ['drinktable', 'drinkable', 'drink table']], + \ ['drinkablestable', ['drinkabletable', 'drinkables table', 'drinkable table']], + \ ]) +endfunc + +function FirstSpellWord() + call feedkeys("/^start:\n", 'tx') + normal ]smm + let [str, a] = spellbadword() + return str +endfunc + +function SecondSpellWord() + normal `m]s + let [str, a] = spellbadword() + return str +endfunc + +" Test with SAL instead of SOFO items; test automatic reloading +func Test_spell_sal_and_addition() + set spellfile= + call writefile(g:test_data_dic1, "Xtest.dic") + call writefile(g:test_data_aff_sal, "Xtest.aff") + mkspell! Xtest Xtest + set spl=Xtest.utf-8.spl spell + call assert_equal('kbltykk', soundfold('goobledygoook')) + call assert_equal('kprnfn', soundfold('kóopërÿnôven')) + call assert_equal('*fls kswts tl', soundfold('oeverloos gezwets edale')) + + "also use an addition file + call writefile(["/regions=usgbnz", "elequint/2", "elekwint/3"], "Xtest.utf-8.add") + mkspell! Xtest.utf-8.add.spl Xtest.utf-8.add + + bwipe! + call setline(1, ["start: elequint test elekwint test elekwent asdf"]) + + set spellfile=Xtest.utf-8.add + call assert_equal("elekwent", FirstSpellWord()) + + set spl=Xtest_us.utf-8.spl + call assert_equal("elequint", FirstSpellWord()) + call assert_equal("elekwint", SecondSpellWord()) + + set spl=Xtest_gb.utf-8.spl + call assert_equal("elekwint", FirstSpellWord()) + call assert_equal("elekwent", SecondSpellWord()) + + set spl=Xtest_nz.utf-8.spl + call assert_equal("elequint", FirstSpellWord()) + call assert_equal("elekwent", SecondSpellWord()) + + set spl=Xtest_ca.utf-8.spl + call assert_equal("elequint", FirstSpellWord()) + call assert_equal("elekwint", SecondSpellWord()) +endfunc + +func Test_spellfile_value() + set spellfile=Xdir/Xtest.utf-8.add + set spellfile=Xdir/Xtest.utf-8.add,Xtest_other.add +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index f34402dc6f1d57..066724eee34473 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1354, /**/ 1353, /**/ From c2ee44cc382d4b097f51ea3251f00fb35493ea4f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 2 Aug 2020 16:59:00 +0200 Subject: [PATCH 0068/1384] patch 8.2.1355: Vim9: no error using :let for options and registers Problem: Vim9: no error using :let for options and registers. Solution: Give an error. (closes #6568) --- src/evalvars.c | 14 ++++--- src/testdir/test_vim9_script.vim | 5 ++- src/version.c | 2 + src/vim9compile.c | 63 +++++++++++--------------------- 4 files changed, 36 insertions(+), 48 deletions(-) diff --git a/src/evalvars.c b/src/evalvars.c index 73c4da6c6eefe0..cf75487eaa8994 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -1219,6 +1219,13 @@ ex_let_one( int opt_flags; char_u *tofree = NULL; + if (in_vim9script() && (flags & LET_NO_COMMAND) == 0 + && vim_strchr((char_u *)"$@&", *arg) != NULL) + { + vim9_declare_error(arg); + return NULL; + } + // ":let $VAR = expr": Set environment variable. if (*arg == '$') { @@ -1227,11 +1234,6 @@ ex_let_one( emsg(_("E996: Cannot lock an environment variable")); return NULL; } - if (in_vim9script() && (flags & LET_NO_COMMAND) == 0) - { - vim9_declare_error(arg); - return NULL; - } // Find the end of the name. ++arg; @@ -2427,7 +2429,7 @@ eval_variable( else { scriptitem_T *si = SCRIPT_ITEM(import->imp_sid); - svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + import->imp_var_vals_idx; tv = sv->sv_tv; } diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index b96411ff6781c2..5ed9a3d420ee33 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -463,13 +463,16 @@ def Test_assignment_failure() '[x, y; z] = [1]'], 'E1093:') call CheckDefFailure(['let somevar'], "E1022:") - call CheckDefFailure(['let &option'], 'E1052:') + call CheckDefFailure(['let &tabstop = 4'], 'E1052:') call CheckDefFailure(['&g:option = 5'], 'E113:') + call CheckScriptFailure(['vim9script', 'let &tabstop = 4'], 'E1052:') call CheckDefFailure(['let $VAR = 5'], 'E1016: Cannot declare an environment variable:') + call CheckScriptFailure(['vim9script', 'let $ENV = "xxx"'], 'E1016:') call CheckDefFailure(['let @~ = 5'], 'E354:') call CheckDefFailure(['let @a = 5'], 'E1066:') + call CheckScriptFailure(['vim9script', 'let @a = "abc"'], 'E1066:') call CheckDefFailure(['let g:var = 5'], 'E1016: Cannot declare a global variable:') call CheckDefFailure(['let w:var = 5'], 'E1016: Cannot declare a window variable:') diff --git a/src/version.c b/src/version.c index 066724eee34473..c27c94a2cce6bd 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1355, /**/ 1354, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 3c7e1218ed553c..5999c39614a796 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -5067,7 +5067,12 @@ vim9_declare_error(char_u *name) case 'w': scope = _("window"); break; case 't': scope = _("tab"); break; case 'v': scope = "v:"; break; - case '$': semsg(_(e_declare_env_var), name); return; + case '$': semsg(_(e_declare_env_var), name); + return; + case '&': semsg(_("E1052: Cannot declare an option: %s"), name); + return; + case '@': semsg(_("E1066: Cannot declare a register: %s"), name); + return; default: return; } semsg(_(e_declare_var), scope, name); @@ -5229,6 +5234,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) if (cctx->ctx_skip != SKIP_YES) { + int declare_error = FALSE; + if (*var_start == '&') { int cc; @@ -5240,11 +5247,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) emsg(_(e_const_option)); goto theend; } - if (is_decl) - { - semsg(_("E1052: Cannot declare an option: %s"), var_start); - goto theend; - } + declare_error = is_decl; p = var_start; p = find_option_end(&p, &opt_flags); if (p == NULL) @@ -5272,11 +5275,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) { dest = dest_env; type = &t_string; - if (is_decl) - { - vim9_declare_error(name); - goto theend; - } + declare_error = is_decl; } else if (*var_start == '@') { @@ -5287,47 +5286,27 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) } dest = dest_reg; type = &t_string; - if (is_decl) - { - semsg(_("E1066: Cannot declare a register: %s"), name); - goto theend; - } + declare_error = is_decl; } else if (varlen > 1 && STRNCMP(var_start, "g:", 2) == 0) { dest = dest_global; - if (is_decl) - { - vim9_declare_error(name); - goto theend; - } + declare_error = is_decl; } else if (varlen > 1 && STRNCMP(var_start, "b:", 2) == 0) { dest = dest_buffer; - if (is_decl) - { - vim9_declare_error(name); - goto theend; - } + declare_error = is_decl; } else if (varlen > 1 && STRNCMP(var_start, "w:", 2) == 0) { dest = dest_window; - if (is_decl) - { - vim9_declare_error(name); - goto theend; - } + declare_error = is_decl; } else if (varlen > 1 && STRNCMP(var_start, "t:", 2) == 0) { dest = dest_tab; - if (is_decl) - { - vim9_declare_error(name); - goto theend; - } + declare_error = is_decl; } else if (varlen > 1 && STRNCMP(var_start, "v:", 2) == 0) { @@ -5346,11 +5325,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) dest = dest_vimvar; vtv = get_vim_var_tv(vimvaridx); type = typval2type_vimvar(vtv, cctx->ctx_type_list); - if (is_decl) - { - vim9_declare_error(name); - goto theend; - } + declare_error = is_decl; } else { @@ -5439,6 +5414,12 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) goto theend; } } + + if (declare_error) + { + vim9_declare_error(name); + goto theend; + } } // handle "a:name" as a name, not index "name" on "a" From 7226e5b19bd6e081043cbcc32541ef72bbdf667d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 2 Aug 2020 17:33:26 +0200 Subject: [PATCH 0069/1384] patch 8.2.1356: Vim9: cannot get the percent register Problem: Vim9: cannot get the percent register. Solution: Check for readable registers instead of writable. (closes #6566) --- src/testdir/test_vim9_expr.vim | 9 +++++++++ src/version.c | 2 ++ src/vim9compile.c | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 226db83f8086b5..ef8797f8f8fe65 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1430,6 +1430,15 @@ enddef def Test_expr7_register() @a = 'register a' assert_equal('register a', @a) + + let fname = expand('%') + assert_equal(fname, @%) + + feedkeys(":echo 'some'\", "xt") + assert_equal("echo 'some'", @:) + + normal axyz + assert_equal("xyz", @.) enddef def Test_expr7_namespace() diff --git a/src/version.c b/src/version.c index c27c94a2cce6bd..b04f4feb8d3b7e 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1356, /**/ 1355, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 5999c39614a796..cfd4ff19060e06 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3565,7 +3565,7 @@ compile_get_register(char_u **arg, cctx_T *cctx) semsg(_(e_syntax_at), *arg - 1); return FAIL; } - if (!valid_yank_reg(**arg, TRUE)) + if (!valid_yank_reg(**arg, FALSE)) { emsg_invreg(**arg); return FAIL; From 658217276fccb5e53cdf4ba0f023bca80e0a8fed Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 2 Aug 2020 18:58:54 +0200 Subject: [PATCH 0070/1384] patch 8.2.1357: Vim9: cannot assign to / register Problem: Vim9: cannot assign to / register. Solution: Adjust check for assignment. --- src/testdir/test_vim9_expr.vim | 7 +++++++ src/testdir/test_vim9_script.vim | 3 ++- src/version.c | 2 ++ src/vim9compile.c | 18 +++++++++++++----- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index ef8797f8f8fe65..584126ff1e7a9a 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1439,6 +1439,13 @@ def Test_expr7_register() normal axyz assert_equal("xyz", @.) + call CheckDefFailure(["@. = 'yes'"], 'E354:') + + @/ = 'slash' + assert_equal('slash', @/) + + @= = 'equal' + assert_equal('equal', @=) enddef def Test_expr7_namespace() diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 5ed9a3d420ee33..5c2db2ef421919 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -470,8 +470,9 @@ def Test_assignment_failure() call CheckDefFailure(['let $VAR = 5'], 'E1016: Cannot declare an environment variable:') call CheckScriptFailure(['vim9script', 'let $ENV = "xxx"'], 'E1016:') - call CheckDefFailure(['let @~ = 5'], 'E354:') + call CheckDefFailure(['let @~ = 5'], 'E1066:') call CheckDefFailure(['let @a = 5'], 'E1066:') + call CheckDefFailure(['let @/ = "x"'], 'E1066:') call CheckScriptFailure(['vim9script', 'let @a = "abc"'], 'E1066:') call CheckDefFailure(['let g:var = 5'], 'E1016: Cannot declare a global variable:') diff --git a/src/version.c b/src/version.c index b04f4feb8d3b7e..a9059792da34d1 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1357, /**/ 1356, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index cfd4ff19060e06..24ef87931b83a1 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -5214,9 +5214,14 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) int has_index = FALSE; int instr_count = -1; - p = (*var_start == '&' || *var_start == '$' - || *var_start == '@') ? var_start + 1 : var_start; - p = to_name_end(p, TRUE); + if (*var_start == '@') + p = var_start + 2; + else + { + p = (*var_start == '&' || *var_start == '$') + ? var_start + 1 : var_start; + p = to_name_end(p, TRUE); + } // "a: type" is declaring variable "a" with a type, not "a:". if (is_decl && var_end == var_start + 2 && var_end[-1] == ':') @@ -5279,7 +5284,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) } else if (*var_start == '@') { - if (!valid_yank_reg(var_start[1], TRUE)) + if (!valid_yank_reg(var_start[1], FALSE) || var_start[1] == '.') { emsg_invreg(var_start[1]); goto theend; @@ -7247,7 +7252,10 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx) int oplen; int heredoc; - var_end = find_name_end(pskip, NULL, NULL, + if (ea.cmd[0] == '@') + var_end = ea.cmd + 2; + else + var_end = find_name_end(pskip, NULL, NULL, FNE_CHECK_START | FNE_INCL_BR); oplen = assignment_len(skipwhite(var_end), &heredoc); if (oplen > 0) From 434d72cbf2170d54cb4f8acbe995a9a55cceb92a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 2 Aug 2020 20:03:25 +0200 Subject: [PATCH 0071/1384] patch 8.2.1358: Vim9: test fails with +dnd is not available Problem: Vim9: test fails with +dnd is not available. Solution: Add condition. --- src/testdir/test_vim9_script.vim | 7 ++++++- src/version.c | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 5c2db2ef421919..f359a9d9106dc3 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -470,7 +470,12 @@ def Test_assignment_failure() call CheckDefFailure(['let $VAR = 5'], 'E1016: Cannot declare an environment variable:') call CheckScriptFailure(['vim9script', 'let $ENV = "xxx"'], 'E1016:') - call CheckDefFailure(['let @~ = 5'], 'E1066:') + if has('dnd') + call CheckDefFailure(['let @~ = 5'], 'E1066:') + else + call CheckDefFailure(['let @~ = 5'], 'E354:') + call CheckDefFailure(['@~ = 5'], 'E354:') + endif call CheckDefFailure(['let @a = 5'], 'E1066:') call CheckDefFailure(['let @/ = "x"'], 'E1066:') call CheckScriptFailure(['vim9script', 'let @a = "abc"'], 'E1066:') diff --git a/src/version.c b/src/version.c index a9059792da34d1..4f1d8a179c933e 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1358, /**/ 1357, /**/ From 83144546488b544a1fe4e2a4f8be954b98c696fc Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 2 Aug 2020 20:40:43 +0200 Subject: [PATCH 0072/1384] patch 8.2.1359: Vim9: cannot assign to / register in Vim9 script Problem: Vim9: cannot assign to / register in Vim9 script. Solution: Adjust check for assignment in Vim9 script. (closes #6567) --- src/ex_docmd.c | 8 +++++--- src/testdir/test_vim9_script.vim | 17 +++++++++++++++++ src/version.c | 2 ++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 185fc49cb4bfe8..105710b01605b6 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -3274,10 +3274,10 @@ find_ex_command( if (lookup != NULL) { // Skip over first char for "&opt = val", "$ENV = val" and "@r = val". - char_u *pskip = (*eap->cmd == '&' || *eap->cmd == '$' - || *eap->cmd == '@') ? eap->cmd + 1 : eap->cmd; + char_u *pskip = (*eap->cmd == '&' || *eap->cmd == '$') + ? eap->cmd + 1 : eap->cmd; - if (vim_strchr((char_u *)"{('[\"", *p) != NULL + if (vim_strchr((char_u *)"{('[\"@", *p) != NULL || ((p = to_name_const_end(pskip)) > eap->cmd && *p != NUL)) { int oplen; @@ -3336,6 +3336,8 @@ find_ex_command( // Recognize an assignment if we recognize the variable name: // "g:var = expr" // "var = expr" where "var" is a local var name. + if (*eap->cmd == '@') + p = eap->cmd + 2; oplen = assignment_len(skipwhite(p), &heredoc); if (oplen > 0) { diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index f359a9d9106dc3..64ac3bbd925c1b 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -423,6 +423,23 @@ def Test_assignment_vim9script() let ll = Func() assert_equal([1, 2], ll) + + @/ = 'text' + assert_equal('text', @/) + @0 = 'zero' + assert_equal('zero', @0) + @1 = 'one' + assert_equal('one', @1) + @9 = 'nine' + assert_equal('nine', @9) + @- = 'minus' + assert_equal('minus', @-) + if has('clipboard_working') + @* = 'star' + assert_equal('star', @*) + @+ = 'plus' + assert_equal('plus', @+) + endif END CheckScriptSuccess(lines) enddef diff --git a/src/version.c b/src/version.c index 4f1d8a179c933e..c169daf8d0c82b 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1359, /**/ 1358, /**/ From f96e9dec636d7d105b015680d8c5d6b47d936e01 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 3 Aug 2020 22:39:28 +0200 Subject: [PATCH 0073/1384] patch 8.2.1360: stray error for white space after expression Problem: Stray error for white space after expression. Solution: Ignore trailing white space. (closes #6608) --- src/eval.c | 2 +- src/testdir/test_filter_map.vim | 1 + src/version.c | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/eval.c b/src/eval.c index 119b7cc189ac4c..87d2e16a7b37c2 100644 --- a/src/eval.c +++ b/src/eval.c @@ -300,7 +300,7 @@ eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv) s = skipwhite(s); if (eval1_emsg(&s, rettv, NULL) == FAIL) return FAIL; - if (*s != NUL) // check for trailing chars after expr + if (*skipwhite(s) != NUL) // check for trailing chars after expr { clear_tv(rettv); semsg(_(e_invexpr2), s); diff --git a/src/testdir/test_filter_map.vim b/src/testdir/test_filter_map.vim index 8883ea3cc5d31c..249c32f126f579 100644 --- a/src/testdir/test_filter_map.vim +++ b/src/testdir/test_filter_map.vim @@ -11,6 +11,7 @@ func Test_filter_map_list_expr_string() call assert_equal([2, 4, 6, 8], map([1, 2, 3, 4], 'v:val * 2')) call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], 'v:key * 2')) call assert_equal([9, 9, 9, 9], map([1, 2, 3, 4], 9)) + call assert_equal([7, 7, 7], map([1, 2, 3], ' 7 ')) endfunc " dict with expression string diff --git a/src/version.c b/src/version.c index c169daf8d0c82b..9e33c542fe2aee 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1360, /**/ 1359, /**/ From 6a25026262e2cdbbd8738361c5bd6ebef8862d87 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 4 Aug 2020 15:53:01 +0200 Subject: [PATCH 0074/1384] patch 8.2.1361: error for white space after expression in assignment Problem: Error for white space after expression in assignment. Solution: Skip over white space. (closes #6617) --- src/eval.c | 1 + src/testdir/test_expr.vim | 3 +++ src/version.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/eval.c b/src/eval.c index 87d2e16a7b37c2..cfa86ef2c50a8b 100644 --- a/src/eval.c +++ b/src/eval.c @@ -903,6 +903,7 @@ get_lval( clear_tv(&var1); return NULL; } + p = skipwhite(p); } // Optionally get the second index [ :expr]. diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim index b13154304ce707..b4eeea653b15d4 100644 --- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -55,6 +55,9 @@ func Test_dict() let d['a'] = 'aaa' call assert_equal('none', d['']) call assert_equal('aaa', d['a']) + + let d[ 'b' ] = 'bbb' + call assert_equal('bbb', d[ 'b' ]) endfunc func Test_strgetchar() diff --git a/src/version.c b/src/version.c index 9e33c542fe2aee..cb54f8cdb3a58e 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1361, /**/ 1360, /**/ From ecd34bf55d72f530859e290ac02ee41f9fb27cce Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 4 Aug 2020 20:17:31 +0200 Subject: [PATCH 0075/1384] patch 8.2.1362: last entry of ":set term=xxx" overwritten by error message Problem: Last entry of ":set term=xxx" overwritten by error message when 'cmdheight' is two or more. (Tony Mechelynck) Solution: Output extra line breaks. --- src/term.c | 5 +++++ src/testdir/test_termcodes.vim | 12 ++++++++++++ src/version.c | 2 ++ 3 files changed, 19 insertions(+) diff --git a/src/term.c b/src/term.c index 3c0ca779b49043..3648df6d5060cb 100644 --- a/src/term.c +++ b/src/term.c @@ -1763,6 +1763,7 @@ get_term_entries(int *height, int *width) report_term_error(char *error_msg, char_u *term) { struct builtin_term *termp; + int i; mch_errmsg("\r\n"); if (error_msg != NULL) @@ -1787,6 +1788,10 @@ report_term_error(char *error_msg, char_u *term) mch_errmsg("\r\n"); } } + // Output extra 'cmdheight' line breaks to avoid that the following error + // message overwrites the last terminal name. + for (i = 1; i < p_ch; ++i) + mch_errmsg("\r\n"); } static void diff --git a/src/testdir/test_termcodes.vim b/src/testdir/test_termcodes.vim index 30123148f6fd67..da2f066ac73965 100644 --- a/src/testdir/test_termcodes.vim +++ b/src/testdir/test_termcodes.vim @@ -7,6 +7,7 @@ CheckUnix source shared.vim source mouse.vim +source view_util.vim func Test_term_mouse_left_click() new @@ -1893,6 +1894,17 @@ func Test_get_termcode() set ttybuiltin endfunc +func Test_list_builtin_terminals() + let buf = RunVimInTerminal('', #{rows: 14}) + call term_sendkeys(buf, ":set cmdheight=3\") + call term_wait(buf, 100) + call term_sendkeys(buf, ":set term=xxx\") + call term_wait(buf, 100) + call assert_match('builtin_dumb', term_getline(buf, 11)) + call assert_match('Not found in termcap', term_getline(buf, 12)) + call StopVimInTerminal(buf) +endfunc + func GetEscCodeCSI27(key, modifier) let key = printf("%d", char2nr(a:key)) let mod = printf("%d", a:modifier) diff --git a/src/version.c b/src/version.c index cb54f8cdb3a58e..251a59431cb56c 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1362, /**/ 1361, /**/ From e46a2ed0d8471b93a8b9edd98280d5de4a02c623 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 4 Aug 2020 21:04:57 +0200 Subject: [PATCH 0076/1384] patch 8.2.1363: test trying to run terminal when it is not supported Problem: Test trying to run terminal when it is not supported. Solution: Check if Vim can be run in a terminal. --- src/testdir/test_termcodes.vim | 2 ++ src/version.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/testdir/test_termcodes.vim b/src/testdir/test_termcodes.vim index da2f066ac73965..a228f1bec4fba1 100644 --- a/src/testdir/test_termcodes.vim +++ b/src/testdir/test_termcodes.vim @@ -8,6 +8,7 @@ CheckUnix source shared.vim source mouse.vim source view_util.vim +source term_util.vim func Test_term_mouse_left_click() new @@ -1895,6 +1896,7 @@ func Test_get_termcode() endfunc func Test_list_builtin_terminals() + CheckRunVimInTerminal let buf = RunVimInTerminal('', #{rows: 14}) call term_sendkeys(buf, ":set cmdheight=3\") call term_wait(buf, 100) diff --git a/src/version.c b/src/version.c index 251a59431cb56c..376c8fd641d9e5 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1363, /**/ 1362, /**/ From 282f9c64e570e832d3eba12950da15c9f1a40f06 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 4 Aug 2020 21:46:18 +0200 Subject: [PATCH 0077/1384] patch 8.2.1364: invalid memory access when searching for raw string Problem: Invalid memory access when searching for raw string. Solution: Check for delimiter match before following quote. (closes #6578) --- src/search.c | 4 ++-- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/search.c b/src/search.c index 91a26dd36a6f0d..7391ab0fbf8118 100644 --- a/src/search.c +++ b/src/search.c @@ -1928,8 +1928,8 @@ find_rawstring_end(char_u *linep, pos_T *startpos, pos_T *endpos) { if (lnum == endpos->lnum && (colnr_T)(p - line) >= endpos->col) break; - if (*p == ')' && p[delim_len + 1] == '"' - && STRNCMP(delim_copy, p + 1, delim_len) == 0) + if (*p == ')' && STRNCMP(delim_copy, p + 1, delim_len) == 0 + && p[delim_len + 1] == '"') { found = TRUE; break; diff --git a/src/version.c b/src/version.c index 376c8fd641d9e5..366d3ab7775182 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1364, /**/ 1363, /**/ From bb1b5e24ecc0abe1fee164e9de13796989eff784 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 10:53:21 +0200 Subject: [PATCH 0078/1384] patch 8.2.1365: Vim9: no error for missing white space around operator Problem: Vim9: no error for missing white space around operator. Solution: Check for white space. (closes #6618) --- src/eval.c | 27 +++++++++++++++++++++------ src/evalvars.c | 9 ++++++--- src/proto/vim9compile.pro | 1 + src/testdir/test_vim9_expr.vim | 33 +++++++++++++++++++++++++++++++++ src/testdir/test_vim9_func.vim | 2 +- src/version.c | 2 ++ src/vim9compile.c | 32 ++++++++++++++++---------------- 7 files changed, 80 insertions(+), 26 deletions(-) diff --git a/src/eval.c b/src/eval.c index cfa86ef2c50a8b..3c4e5bdefc26bc 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2574,6 +2574,7 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg) int getnext; char_u *p; int op; + int oplen; int concat; typval_T var2; @@ -2584,11 +2585,19 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg) if (op != '+' && op != '-' && !concat) break; + evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE); if (getnext) *arg = eval_next_line(evalarg); else + { + if (evaluate && in_vim9script() && !VIM_ISWHITE(**arg)) + { + error_white_both(p, 1); + clear_tv(rettv); + return FAIL; + } *arg = p; - evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE); + } if ((op != '+' || (rettv->v_type != VAR_LIST && rettv->v_type != VAR_BLOB)) #ifdef FEAT_FLOAT @@ -2613,9 +2622,14 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg) /* * Get the second variable. */ - if (op == '.' && *(*arg + 1) == '.') // .. string concatenation - ++*arg; - *arg = skipwhite_and_linebreak(*arg + 1, evalarg); + oplen = (op == '.' && *(*arg + 1) == '.') ? 2 : 1; + if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[oplen])) + { + error_white_both(p, oplen); + clear_tv(rettv); + return FAIL; + } + *arg = skipwhite_and_linebreak(*arg + oplen, evalarg); if (eval6(arg, &var2, evalarg, op == '.') == FAIL) { clear_tv(rettv); @@ -3358,6 +3372,7 @@ eval_method( } else { + *arg = skipwhite(*arg); if (**arg != '(') { if (verbose) @@ -4841,7 +4856,7 @@ get_env_len(char_u **arg) /* * Get the length of the name of a function or internal variable. - * "arg" is advanced to the first non-white character after the name. + * "arg" is advanced to after the name. * Return 0 if something is wrong. */ int @@ -4867,7 +4882,7 @@ get_id_len(char_u **arg) return 0; len = (int)(p - *arg); - *arg = skipwhite(p); + *arg = p; return len; } diff --git a/src/evalvars.c b/src/evalvars.c index cf75487eaa8994..869deefc2fe675 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -1137,6 +1137,7 @@ list_arg_vars(exarg_T *eap, char_u *arg, int *first) } else { + arg = skipwhite(arg); if (tofree != NULL) name = tofree; if (eval_variable(name, len, &tv, NULL, TRUE, FALSE) == FAIL) @@ -3358,6 +3359,7 @@ assert_error(garray_T *gap) int var_exists(char_u *var) { + char_u *arg = var; char_u *name; char_u *tofree; typval_T tv; @@ -3366,7 +3368,7 @@ var_exists(char_u *var) // get_name_len() takes care of expanding curly braces name = var; - len = get_name_len(&var, &tofree, TRUE, FALSE); + len = get_name_len(&arg, &tofree, TRUE, FALSE); if (len > 0) { if (tofree != NULL) @@ -3375,12 +3377,13 @@ var_exists(char_u *var) if (n) { // handle d.key, l[idx], f(expr) - n = (handle_subscript(&var, &tv, &EVALARG_EVALUATE, FALSE) == OK); + arg = skipwhite(arg); + n = (handle_subscript(&arg, &tv, &EVALARG_EVALUATE, FALSE) == OK); if (n) clear_tv(&tv); } } - if (*var != NUL) + if (*arg != NUL) n = FALSE; vim_free(tofree); diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro index fd2dd1bf4b3393..14f9bbc7b2b14a 100644 --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -17,6 +17,7 @@ char_u *peek_next_line_from_context(cctx_T *cctx); char_u *next_line_from_context(cctx_T *cctx, int skip_comment); char_u *to_name_const_end(char_u *arg); exptype_T get_compare_type(char_u *p, int *len, int *type_is); +void error_white_both(char_u *op, int len); int assignment_len(char_u *p, int *heredoc); void vim9_declare_error(char_u *name); int check_vim9_unlet(char_u *name); diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 584126ff1e7a9a..7e53a287d5ca09 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -872,6 +872,39 @@ def Test_expr5_vim9script() echo 'abc' isnot? 'abc' END CheckScriptFailure(lines, 'E15:') + + # check white space + lines =<< trim END + vim9script + echo 5+6 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + echo 5 +6 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + echo 5+ 6 + END + CheckScriptFailure(lines, 'E1004:') + + lines =<< trim END + vim9script + echo 'a'..'b' + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + echo 'a' ..'b' + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + echo 'a'.. 'b' + END + CheckScriptFailure(lines, 'E1004:') enddef def Test_expr5_float() diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index f3fc4c7bee4d06..d0248369ce3247 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1270,7 +1270,7 @@ enddef def TreeWalk(dir: string): list return readdir(dir)->map({_, val -> fnamemodify(dir .. '/' .. val, ':p')->isdirectory() - ? {val : TreeWalk(dir .. '/' .. val)} + ? {val: TreeWalk(dir .. '/' .. val)} : val }) enddef diff --git a/src/version.c b/src/version.c index 366d3ab7775182..112a502e483539 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1365, /**/ 1364, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 24ef87931b83a1..f8381d7837d3bc 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -4243,6 +4243,18 @@ compile_expr7( return OK; } +/* + * Give the "white on both sides" error, taking the operator from "p[len]". + */ + void +error_white_both(char_u *op, int len) +{ + char_u buf[10]; + + vim_strncpy(buf, op, len); + semsg(_(e_white_both), buf); +} + /* * * number multiplication * / number division @@ -4275,10 +4287,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[1])) { - char_u buf[3]; - - vim_strncpy(buf, op, 1); - semsg(_(e_white_both), buf); + error_white_both(op, 1); return FAIL; } *arg = skipwhite(op + 1); @@ -4354,10 +4363,7 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(op[oplen])) { - char_u buf[3]; - - vim_strncpy(buf, op, oplen); - semsg(_(e_white_both), buf); + error_white_both(op, oplen); return FAIL; } @@ -4486,10 +4492,7 @@ compile_expr4(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) if (!IS_WHITE_OR_NUL(**arg) || !IS_WHITE_OR_NUL(p[len])) { - char_u buf[7]; - - vim_strncpy(buf, p, len); - semsg(_(e_white_both), buf); + error_white_both(p, len); return FAIL; } @@ -5132,10 +5135,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) if (oplen > 0 && (!VIM_ISWHITE(*sp) || !VIM_ISWHITE(op[oplen]))) { - char_u buf[4]; - - vim_strncpy(buf, op, oplen); - semsg(_(e_white_both), buf); + error_white_both(op, oplen); return NULL; } From a6296200bd5191bab7efcdcc16c9e79eb498e8e0 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 11:23:13 +0200 Subject: [PATCH 0079/1384] patch 8.2.1366: test 49 is old style Problem: Test 49 is old style. Solution: Convert several tests to new style. (Yegappan Lakshmanan, closes #6629) --- src/testdir/script_util.vim | 69 ++ src/testdir/test49.ok | 21 - src/testdir/test49.vim | 1643 +--------------------------- src/testdir/test_vimscript.vim | 1852 ++++++++++++++++++++++++++++++-- src/version.c | 2 + 5 files changed, 1835 insertions(+), 1752 deletions(-) create mode 100644 src/testdir/script_util.vim diff --git a/src/testdir/script_util.vim b/src/testdir/script_util.vim new file mode 100644 index 00000000000000..9913b1dfaf460b --- /dev/null +++ b/src/testdir/script_util.vim @@ -0,0 +1,69 @@ +" Functions shared by the tests for Vim Script + +" Commands to track the execution path of a script +com! XpathINIT let g:Xpath = '' +com! -nargs=1 -bar Xpath let g:Xpath ..= +com! XloopINIT let g:Xloop = 1 +com! -nargs=1 -bar Xloop let g:Xpath ..= .. g:Xloop +com! XloopNEXT let g:Xloop += 1 + +" MakeScript() - Make a script file from a function. {{{2 +" +" Create a script that consists of the body of the function a:funcname. +" Replace any ":return" by a ":finish", any argument variable by a global +" variable, and every ":call" by a ":source" for the next following argument +" in the variable argument list. This function is useful if similar tests are +" to be made for a ":return" from a function call or a ":finish" in a script +" file. +func MakeScript(funcname, ...) + let script = tempname() + execute "redir! >" . script + execute "function" a:funcname + redir END + execute "edit" script + " Delete the "function" and the "endfunction" lines. Do not include the + " word "function" in the pattern since it might be translated if LANG is + " set. When MakeScript() is being debugged, this deletes also the debugging + " output of its line 3 and 4. + exec '1,/.*' . a:funcname . '(.*)/d' + /^\d*\s*endfunction\>/,$d + %s/^\d*//e + %s/return/finish/e + %s/\ 0 + let cnt = cnt + 1 + s/\) + diff --git a/src/testdir/test49.ok b/src/testdir/test49.ok index 9f283e808b2829..50696fd64323e1 100644 --- a/src/testdir/test49.ok +++ b/src/testdir/test49.ok @@ -1,25 +1,4 @@ Results of test49.vim: -*** Test 18: OK (67224583) -*** Test 19: OK (69275973) -*** Test 20: OK (1874575085) -*** Test 21: OK (147932225) -*** Test 22: OK (4161) -*** Test 23: OK (49) -*** Test 24: OK (41) -*** Test 27: OK (1996459) -*** Test 28: OK (1996459) -*** Test 29: OK (170428555) -*** Test 30: OK (190905173) -*** Test 31: OK (190905173) -*** Test 34: OK (2146584868) -*** Test 35: OK (2146584868) -*** Test 36: OK (1071644672) -*** Test 37: OK (1071644672) -*** Test 38: OK (357908480) -*** Test 39: OK (357908480) -*** Test 40: OK (357908480) -*** Test 49: OK (179000669) -*** Test 50: OK (363550045) *** Test 52: OK (1247112011) *** Test 53: OK (131071) *** Test 54: OK (2047) diff --git a/src/testdir/test49.vim b/src/testdir/test49.vim index 15210b60638989..b3215dfa6f6cc3 100644 --- a/src/testdir/test49.vim +++ b/src/testdir/test49.vim @@ -1,6 +1,6 @@ " Vim script language tests " Author: Servatius Brandt -" Last Change: 2019 Nov 03 +" Last Change: 2020 Jun 07 "------------------------------------------------------------------------------- " Test environment {{{1 @@ -607,1647 +607,10 @@ com! -nargs=1 -bar ExecAsScript call ExecAsScript() " END_OF_TEST_ENVIRONMENT - do not change or remove this line. - -" Tests 1 to 17 were moved to test_vimscript.vim -let Xtest = 18 - -"------------------------------------------------------------------------------- -" Test 18: Interrupt (Ctrl-C pressed) {{{1 -" -" On an interrupt, the script processing is terminated immediately. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - if 1 - Xpath 1 " X: 1 - while 1 - Xpath 2 " X: 2 - if 1 - Xpath 4 " X: 4 - "INTERRUPT - Xpath 8 " X: 0 - break - finish - endif | Xpath 16 " X: 0 - Xpath 32 " X: 0 - endwhile | Xpath 64 " X: 0 - Xpath 128 " X: 0 - endif | Xpath 256 " X: 0 - Xpath 512 " X: 0 -endif - -if ExtraVim() - try - Xpath 1024 " X: 1024 - "INTERRUPT - Xpath 2048 " X: 0 - endtry | Xpath 4096 " X: 0 - Xpath 8192 " X: 0 -endif - -if ExtraVim() - function! F() - if 1 - Xpath 16384 " X: 16384 - while 1 - Xpath 32768 " X: 32768 - if 1 - Xpath 65536 " X: 65536 - "INTERRUPT - Xpath 131072 " X: 0 - break - return - endif | Xpath 262144 " X: 0 - Xpath Xpath 524288 " X: 0 - endwhile | Xpath 1048576 " X: 0 - Xpath Xpath 2097152 " X: 0 - endif | Xpath Xpath 4194304 " X: 0 - Xpath Xpath 8388608 " X: 0 - endfunction - - call F() | Xpath 16777216 " X: 0 - Xpath 33554432 " X: 0 -endif - -if ExtraVim() - function! G() - try - Xpath 67108864 " X: 67108864 - "INTERRUPT - Xpath 134217728 " X: 0 - endtry | Xpath 268435456 " X: 0 - Xpath 536870912 " X: 0 - endfunction - - call G() | Xpath 1073741824 " X: 0 - " The Xpath command does not accept 2^31 (negative); display explicitly: - exec "!echo 2147483648 >>" . g:ExtraVimResult - " X: 0 -endif - -Xcheck 67224583 - - -"------------------------------------------------------------------------------- -" Test 19: Aborting on errors inside :try/:endtry {{{1 -" -" An error in a command dynamically enclosed in a :try/:endtry region -" aborts script processing immediately. It does not matter whether -" the failing command is outside or inside a function and whether a -" function has an "abort" attribute. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - function! F() abort - Xpath 1 " X: 1 - asdf - Xpath 2 " X: 0 - endfunction - - try - Xpath 4 " X: 4 - call F() - Xpath 8 " X: 0 - endtry | Xpath 16 " X: 0 - Xpath 32 " X: 0 -endif - -if ExtraVim() - function! G() - Xpath 64 " X: 64 - asdf - Xpath 128 " X: 0 - endfunction - - try - Xpath 256 " X: 256 - call G() - Xpath 512 " X: 0 - endtry | Xpath 1024 " X: 0 - Xpath 2048 " X: 0 -endif - -if ExtraVim() - try - Xpath 4096 " X: 4096 - asdf - Xpath 8192 " X: 0 - endtry | Xpath 16384 " X: 0 - Xpath 32768 " X: 0 -endif - -if ExtraVim() - if 1 - try - Xpath 65536 " X: 65536 - asdf - Xpath 131072 " X: 0 - endtry | Xpath 262144 " X: 0 - endif | Xpath 524288 " X: 0 - Xpath 1048576 " X: 0 -endif - -if ExtraVim() - let p = 1 - while p - let p = 0 - try - Xpath 2097152 " X: 2097152 - asdf - Xpath 4194304 " X: 0 - endtry | Xpath 8388608 " X: 0 - endwhile | Xpath 16777216 " X: 0 - Xpath 33554432 " X: 0 -endif - -if ExtraVim() - let p = 1 - while p - let p = 0 -" try - Xpath 67108864 " X: 67108864 - endwhile | Xpath 134217728 " X: 0 - Xpath 268435456 " X: 0 -endif - -Xcheck 69275973 -"------------------------------------------------------------------------------- -" Test 20: Aborting on errors after :try/:endtry {{{1 -" -" When an error occurs after the last active :try/:endtry region has -" been left, termination behavior is as if no :try/:endtry has been -" seen. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - let p = 1 - while p - let p = 0 - try - Xpath 1 " X: 1 - endtry - asdf - endwhile | Xpath 2 " X: 0 - Xpath 4 " X: 4 -endif - -if ExtraVim() - while 1 - try - Xpath 8 " X: 8 - break - Xpath 16 " X: 0 - endtry - endwhile - Xpath 32 " X: 32 - asdf - Xpath 64 " X: 64 -endif - -if ExtraVim() - while 1 - try - Xpath 128 " X: 128 - break - Xpath 256 " X: 0 - finally - Xpath 512 " X: 512 - endtry - endwhile - Xpath 1024 " X: 1024 - asdf - Xpath 2048 " X: 2048 -endif - -if ExtraVim() - while 1 - try - Xpath 4096 " X: 4096 - finally - Xpath 8192 " X: 8192 - break - Xpath 16384 " X: 0 - endtry - endwhile - Xpath 32768 " X: 32768 - asdf - Xpath 65536 " X: 65536 -endif - -if ExtraVim() - let p = 1 - while p - let p = 0 - try - Xpath 131072 " X: 131072 - continue - Xpath 262144 " X: 0 - endtry - endwhile - Xpath 524288 " X: 524288 - asdf - Xpath 1048576 " X: 1048576 -endif - -if ExtraVim() - let p = 1 - while p - let p = 0 - try - Xpath 2097152 " X: 2097152 - continue - Xpath 4194304 " X: 0 - finally - Xpath 8388608 " X: 8388608 - endtry - endwhile - Xpath 16777216 " X: 16777216 - asdf - Xpath 33554432 " X: 33554432 -endif - -if ExtraVim() - let p = 1 - while p - let p = 0 - try - Xpath 67108864 " X: 67108864 - finally - Xpath 134217728 " X: 134217728 - continue - Xpath 268435456 " X: 0 - endtry - endwhile - Xpath 536870912 " X: 536870912 - asdf - Xpath 1073741824 " X: 1073741824 -endif - -Xcheck 1874575085 - - -"------------------------------------------------------------------------------- -" Test 21: :finally for :try after :continue/:break/:return/:finish {{{1 -" -" If a :try conditional stays inactive due to a preceding :continue, -" :break, :return, or :finish, its :finally clause should not be -" executed. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - function F() - let loops = 2 - XloopINIT! 1 256 - while loops > 0 - XloopNEXT - let loops = loops - 1 - try - if loops == 1 - Xloop 1 " X: 1 - continue - Xloop 2 " X: 0 - elseif loops == 0 - Xloop 4 " X: 4*256 - break - Xloop 8 " X: 0 - endif - - try " inactive - Xloop 16 " X: 0 - finally - Xloop 32 " X: 0 - endtry - finally - Xloop 64 " X: 64 + 64*256 - endtry - Xloop 128 " X: 0 - endwhile - - try - Xpath 65536 " X: 65536 - return - Xpath 131072 " X: 0 - try " inactive - Xpath 262144 " X: 0 - finally - Xpath 524288 " X: 0 - endtry - finally - Xpath 1048576 " X: 1048576 - endtry - Xpath 2097152 " X: 0 - endfunction - - try - Xpath 4194304 " X: 4194304 - call F() - Xpath 8388608 " X: 8388608 - finish - Xpath 16777216 " X: 0 - try " inactive - Xpath 33554432 " X: 0 - finally - Xpath 67108864 " X: 0 - endtry - finally - Xpath 134217728 " X: 134217728 - endtry - Xpath 268435456 " X: 0 -endif - -Xcheck 147932225 - - -"------------------------------------------------------------------------------- -" Test 22: :finally for a :try after an error/interrupt/:throw {{{1 -" -" If a :try conditional stays inactive due to a preceding error or -" interrupt or :throw, its :finally clause should not be executed. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - function! Error() - try - asdf " aborting error, triggering error exception - endtry - endfunction - - Xpath 1 " X: 1 - call Error() - Xpath 2 " X: 0 - - if 1 " not active due to error - try " not active since :if inactive - Xpath 4 " X: 0 - finally - Xpath 8 " X: 0 - endtry - endif - - try " not active due to error - Xpath 16 " X: 0 - finally - Xpath 32 " X: 0 - endtry -endif - -if ExtraVim() - function! Interrupt() - try - "INTERRUPT " triggering interrupt exception - endtry - endfunction - - Xpath 64 " X: 64 - call Interrupt() - Xpath 128 " X: 0 - - if 1 " not active due to interrupt - try " not active since :if inactive - Xpath 256 " X: 0 - finally - Xpath 512 " X: 0 - endtry - endif - - try " not active due to interrupt - Xpath 1024 " X: 0 - finally - Xpath 2048 " X: 0 - endtry -endif - -if ExtraVim() - function! Throw() - throw "xyz" - endfunction - - Xpath 4096 " X: 4096 - call Throw() - Xpath 8192 " X: 0 - - if 1 " not active due to :throw - try " not active since :if inactive - Xpath 16384 " X: 0 - finally - Xpath 32768 " X: 0 - endtry - endif - - try " not active due to :throw - Xpath 65536 " X: 0 - finally - Xpath 131072 " X: 0 - endtry -endif - -Xcheck 4161 - - -"------------------------------------------------------------------------------- -" Test 23: :catch clauses for a :try after a :throw {{{1 -" -" If a :try conditional stays inactive due to a preceding :throw, -" none of its :catch clauses should be executed. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - try - Xpath 1 " X: 1 - throw "xyz" - Xpath 2 " X: 0 - - if 1 " not active due to :throw - try " not active since :if inactive - Xpath 4 " X: 0 - catch /xyz/ - Xpath 8 " X: 0 - endtry - endif - catch /xyz/ - Xpath 16 " X: 16 - endtry - - Xpath 32 " X: 32 - throw "abc" - Xpath 64 " X: 0 - - try " not active due to :throw - Xpath 128 " X: 0 - catch /abc/ - Xpath 256 " X: 0 - endtry -endif - -Xcheck 49 - - -"------------------------------------------------------------------------------- -" Test 24: :endtry for a :try after a :throw {{{1 -" -" If a :try conditional stays inactive due to a preceding :throw, -" its :endtry should not rethrow the exception to the next surrounding -" active :try conditional. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - try " try 1 - try " try 2 - Xpath 1 " X: 1 - throw "xyz" " makes try 2 inactive - Xpath 2 " X: 0 - - try " try 3 - Xpath 4 " X: 0 - endtry " no rethrow to try 1 - catch /xyz/ " should catch although try 2 inactive - Xpath 8 " X: 8 - endtry - catch /xyz/ " try 1 active, but exception already caught - Xpath 16 " X: 0 - endtry - Xpath 32 " X: 32 -endif - -Xcheck 41 - -" Tests 25 and 26 were moved to test_trycatch.vim -let Xtest = 27 - - -"------------------------------------------------------------------------------- -" Test 27: Executing :finally clauses after :return {{{1 -" -" For a :return command dynamically enclosed in a :try/:endtry region, -" :finally clauses are executed and the called function is ended. -"------------------------------------------------------------------------------- - -XpathINIT - -function! F() - try - Xpath 1 " X: 1 - try - Xpath 2 " X: 2 - return - Xpath 4 " X: 0 - finally - Xpath 8 " X: 8 - endtry - Xpath 16 " X: 0 - finally - Xpath 32 " X: 32 - endtry - Xpath 64 " X: 0 -endfunction - -function! G() - try - Xpath 128 " X: 128 - return - Xpath 256 " X: 0 - finally - Xpath 512 " X: 512 - call F() - Xpath 1024 " X: 1024 - endtry - Xpath 2048 " X: 0 -endfunction - -function! H() - try - Xpath 4096 " X: 4096 - call G() - Xpath 8192 " X: 8192 - finally - Xpath 16384 " X: 16384 - return - Xpath 32768 " X: 0 - endtry - Xpath 65536 " X: 0 -endfunction - -try - Xpath 131072 " X: 131072 - call H() - Xpath 262144 " X: 262144 -finally - Xpath 524288 " X: 524288 -endtry -Xpath 1048576 " X: 1048576 - -Xcheck 1996459 - -" Leave F, G, and H for execution as scripts in the next test. - - -"------------------------------------------------------------------------------- -" Test 28: Executing :finally clauses after :finish {{{1 -" -" For a :finish command dynamically enclosed in a :try/:endtry region, -" :finally clauses are executed and the sourced file is finished. -" -" This test executes the bodies of the functions F, G, and H from the -" previous test as script files (:return replaced by :finish). -"------------------------------------------------------------------------------- - -XpathINIT - -let scriptF = MakeScript("F") " X: 1 + 2 + 8 + 32 -let scriptG = MakeScript("G", scriptF) " X: 128 + 512 + 1024 -let scriptH = MakeScript("H", scriptG) " X: 4096 + 8192 + 16384 - -try - Xpath 131072 " X: 131072 - exec "source" scriptH - Xpath 262144 " X: 262144 -finally - Xpath 524288 " X: 524288 -endtry -Xpath 1048576 " X: 1048576 - -call delete(scriptF) -call delete(scriptG) -call delete(scriptH) -unlet scriptF scriptG scriptH -delfunction F -delfunction G -delfunction H - -Xcheck 1996459 - - -"------------------------------------------------------------------------------- -" Test 29: Executing :finally clauses on errors {{{1 -" -" After an error in a command dynamically enclosed in a :try/:endtry -" region, :finally clauses are executed and the script processing is -" terminated. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - function! F() - while 1 - try - Xpath 1 " X: 1 - while 1 - try - Xpath 2 " X: 2 - asdf " error - Xpath 4 " X: 0 - finally - Xpath 8 " X: 8 - endtry | Xpath 16 " X: 0 - Xpath 32 " X: 0 - break - endwhile - Xpath 64 " X: 0 - finally - Xpath 128 " X: 128 - endtry | Xpath 256 " X: 0 - Xpath 512 " X: 0 - break - endwhile - Xpath 1024 " X: 0 - endfunction - - while 1 - try - Xpath 2048 " X: 2048 - while 1 - call F() - Xpath 4096 " X: 0 - break - endwhile | Xpath 8192 " X: 0 - Xpath 16384 " X: 0 - finally - Xpath 32768 " X: 32768 - endtry | Xpath 65536 " X: 0 - endwhile | Xpath 131072 " X: 0 - Xpath 262144 " X: 0 -endif - -if ExtraVim() - function! G() abort - if 1 - try - Xpath 524288 " X: 524288 - asdf " error - Xpath 1048576 " X: 0 - finally - Xpath 2097152 " X: 2097152 - endtry | Xpath 4194304 " X: 0 - endif | Xpath 8388608 " X: 0 - Xpath 16777216 " X: 0 - endfunction - - if 1 - try - Xpath 33554432 " X: 33554432 - call G() - Xpath 67108864 " X: 0 - finally - Xpath 134217728 " X: 134217728 - endtry | Xpath 268435456 " X: 0 - endif | Xpath 536870912 " X: 0 - Xpath 1073741824 " X: 0 -endif - -Xcheck 170428555 - - -"------------------------------------------------------------------------------- -" Test 30: Executing :finally clauses on interrupt {{{1 -" -" After an interrupt in a command dynamically enclosed in -" a :try/:endtry region, :finally clauses are executed and the -" script processing is terminated. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - XloopINIT 1 16 - - function! F() - try - Xloop 1 " X: 1 + 1*16 - "INTERRUPT - Xloop 2 " X: 0 - finally - Xloop 4 " X: 4 + 4*16 - endtry - Xloop 8 " X: 0 - endfunction - - try - Xpath 256 " X: 256 - try - Xpath 512 " X: 512 - "INTERRUPT - Xpath 1024 " X: 0 - finally - Xpath 2048 " X: 2048 - try - Xpath 4096 " X: 4096 - try - Xpath 8192 " X: 8192 - finally - Xpath 16384 " X: 16384 - try - Xpath 32768 " X: 32768 - "INTERRUPT - Xpath 65536 " X: 0 - endtry - Xpath 131072 " X: 0 - endtry - Xpath 262144 " X: 0 - endtry - Xpath 524288 " X: 0 - endtry - Xpath 1048576 " X: 0 - finally - Xpath 2097152 " X: 2097152 - try - Xpath 4194304 " X: 4194304 - call F() - Xpath 8388608 " X: 0 - finally - Xpath 16777216 " X: 16777216 - try - Xpath 33554432 " X: 33554432 - XloopNEXT - ExecAsScript F - Xpath 67108864 " X: 0 - finally - Xpath 134217728 " X: 134217728 - endtry - Xpath 268435456 " X: 0 - endtry - Xpath 536870912 " X: 0 - endtry - Xpath 1073741824 " X: 0 -endif - -Xcheck 190905173 - - -"------------------------------------------------------------------------------- -" Test 31: Executing :finally clauses after :throw {{{1 -" -" After a :throw dynamically enclosed in a :try/:endtry region, -" :finally clauses are executed and the script processing is -" terminated. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - XloopINIT 1 16 - - function! F() - try - Xloop 1 " X: 1 + 1*16 - throw "exception" - Xloop 2 " X: 0 - finally - Xloop 4 " X: 4 + 4*16 - endtry - Xloop 8 " X: 0 - endfunction - - try - Xpath 256 " X: 256 - try - Xpath 512 " X: 512 - throw "exception" - Xpath 1024 " X: 0 - finally - Xpath 2048 " X: 2048 - try - Xpath 4096 " X: 4096 - try - Xpath 8192 " X: 8192 - finally - Xpath 16384 " X: 16384 - try - Xpath 32768 " X: 32768 - throw "exception" - Xpath 65536 " X: 0 - endtry - Xpath 131072 " X: 0 - endtry - Xpath 262144 " X: 0 - endtry - Xpath 524288 " X: 0 - endtry - Xpath 1048576 " X: 0 - finally - Xpath 2097152 " X: 2097152 - try - Xpath 4194304 " X: 4194304 - call F() - Xpath 8388608 " X: 0 - finally - Xpath 16777216 " X: 16777216 - try - Xpath 33554432 " X: 33554432 - XloopNEXT - ExecAsScript F - Xpath 67108864 " X: 0 - finally - Xpath 134217728 " X: 134217728 - endtry - Xpath 268435456 " X: 0 - endtry - Xpath 536870912 " X: 0 - endtry - Xpath 1073741824 " X: 0 -endif - -Xcheck 190905173 - -" Tests 32 and 33 were moved to test_trycatch.vim -let Xtest = 34 - - -"------------------------------------------------------------------------------- -" Test 34: :finally reason discarded by :continue {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by a :continue in the finally clause. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - XloopINIT! 1 8 - - function! C(jump) - XloopNEXT - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "return" || a:jump == "finish" - return - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - "INTERRUPT - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - continue " discards jump that caused the :finally - Xloop 1 " X: 0 - endtry - Xloop 2 " X: 0 - elseif loop == 2 - Xloop 4 " X: 4*(1+8+64+512+4096+32768+262144) - endif - endwhile - endfunction - - call C("continue") - Xpath 2097152 " X: 2097152 - call C("break") - Xpath 4194304 " X: 4194304 - call C("return") - Xpath 8388608 " X: 8388608 - let g:jump = "finish" - ExecAsScript C - unlet g:jump - Xpath 16777216 " X: 16777216 - try - call C("error") - Xpath 33554432 " X: 33554432 - finally - Xpath 67108864 " X: 67108864 - try - call C("interrupt") - Xpath 134217728 " X: 134217728 - finally - Xpath 268435456 " X: 268435456 - call C("throw") - Xpath 536870912 " X: 536870912 - endtry - endtry - Xpath 1073741824 " X: 1073741824 - - delfunction C - -endif - -Xcheck 2146584868 - - -"------------------------------------------------------------------------------- -" Test 35: :finally reason discarded by :break {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by a :break in the finally clause. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - XloopINIT! 1 8 - - function! B(jump) - XloopNEXT - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "return" || a:jump == "finish" - return - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - "INTERRUPT - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - break " discards jump that caused the :finally - Xloop 1 " X: 0 - endtry - elseif loop == 2 - Xloop 2 " X: 0 - endif - endwhile - Xloop 4 " X: 4*(1+8+64+512+4096+32768+262144) - endfunction - - call B("continue") - Xpath 2097152 " X: 2097152 - call B("break") - Xpath 4194304 " X: 4194304 - call B("return") - Xpath 8388608 " X: 8388608 - let g:jump = "finish" - ExecAsScript B - unlet g:jump - Xpath 16777216 " X: 16777216 - try - call B("error") - Xpath 33554432 " X: 33554432 - finally - Xpath 67108864 " X: 67108864 - try - call B("interrupt") - Xpath 134217728 " X: 134217728 - finally - Xpath 268435456 " X: 268435456 - call B("throw") - Xpath 536870912 " X: 536870912 - endtry - endtry - Xpath 1073741824 " X: 1073741824 - - delfunction B - -endif - -Xcheck 2146584868 - - -"------------------------------------------------------------------------------- -" Test 36: :finally reason discarded by :return {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by a :return in the finally clause. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - XloopINIT! 1 8 - - function! R(jump, retval) abort - XloopNEXT - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "return" - return - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - "INTERRUPT - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - return a:retval " discards jump that caused the :finally - Xloop 1 " X: 0 - endtry - elseif loop == 2 - Xloop 2 " X: 0 - endif - endwhile - Xloop 4 " X: 0 - endfunction - - let sum = -R("continue", -8) - Xpath 2097152 " X: 2097152 - let sum = sum - R("break", -16) - Xpath 4194304 " X: 4194304 - let sum = sum - R("return", -32) - Xpath 8388608 " X: 8388608 - try - let sum = sum - R("error", -64) - Xpath 16777216 " X: 16777216 - finally - Xpath 33554432 " X: 33554432 - try - let sum = sum - R("interrupt", -128) - Xpath 67108864 " X: 67108864 - finally - Xpath 134217728 " X: 134217728 - let sum = sum - R("throw", -256) - Xpath 268435456 " X: 268435456 - endtry - endtry - Xpath 536870912 " X: 536870912 - - let expected = 8 + 16 + 32 + 64 + 128 + 256 - if sum != expected - Xpath 1073741824 " X: 0 - Xout "sum =" . sum . ", expected: " . expected - endif - - unlet sum expected - delfunction R - -endif - -Xcheck 1071644672 - - -"------------------------------------------------------------------------------- -" Test 37: :finally reason discarded by :finish {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by a :finish in the finally clause. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - XloopINIT! 1 8 - - function! F(jump) " not executed as function, transformed to a script - XloopNEXT - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "finish" - finish - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - "INTERRUPT - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - finish " discards jump that caused the :finally - Xloop 1 " X: 0 - endtry - elseif loop == 2 - Xloop 2 " X: 0 - endif - endwhile - Xloop 4 " X: 0 - endfunction - - let scriptF = MakeScript("F") - delfunction F - - let g:jump = "continue" - exec "source" scriptF - Xpath 2097152 " X: 2097152 - let g:jump = "break" - exec "source" scriptF - Xpath 4194304 " X: 4194304 - let g:jump = "finish" - exec "source" scriptF - Xpath 8388608 " X: 8388608 - try - let g:jump = "error" - exec "source" scriptF - Xpath 16777216 " X: 16777216 - finally - Xpath 33554432 " X: 33554432 - try - let g:jump = "interrupt" - exec "source" scriptF - Xpath 67108864 " X: 67108864 - finally - Xpath 134217728 " X: 134217728 - try - let g:jump = "throw" - exec "source" scriptF - Xpath 268435456 " X: 268435456 - finally - Xpath 536870912 " X: 536870912 - endtry - endtry - endtry - unlet g:jump - - call delete(scriptF) - unlet scriptF - -endif - -Xcheck 1071644672 - - -"------------------------------------------------------------------------------- -" Test 38: :finally reason discarded by an error {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by an error in the finally clause. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - XloopINIT! 1 4 - - function! E(jump) - XloopNEXT - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "return" || a:jump == "finish" - return - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - "INTERRUPT - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - asdf " error; discards jump that caused the :finally - endtry - elseif loop == 2 - Xloop 1 " X: 0 - endif - endwhile - Xloop 2 " X: 0 - endfunction - - try - Xpath 16384 " X: 16384 - call E("continue") - Xpath 32768 " X: 0 - finally - try - Xpath 65536 " X: 65536 - call E("break") - Xpath 131072 " X: 0 - finally - try - Xpath 262144 " X: 262144 - call E("return") - Xpath 524288 " X: 0 - finally - try - Xpath 1048576 " X: 1048576 - let g:jump = "finish" - ExecAsScript E - Xpath 2097152 " X: 0 - finally - unlet g:jump - try - Xpath 4194304 " X: 4194304 - call E("error") - Xpath 8388608 " X: 0 - finally - try - Xpath 16777216 " X: 16777216 - call E("interrupt") - Xpath 33554432 " X: 0 - finally - try - Xpath 67108864 " X: 67108864 - call E("throw") - Xpath 134217728 " X: 0 - finally - Xpath 268435456 " X: 268435456 - delfunction E - endtry - endtry - endtry - endtry - endtry - endtry - endtry - Xpath 536870912 " X: 0 - -endif - -Xcheck 357908480 - - -"------------------------------------------------------------------------------- -" Test 39: :finally reason discarded by an interrupt {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by an interrupt in the finally clause. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - XloopINIT! 1 4 - - function! I(jump) - XloopNEXT - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "return" || a:jump == "finish" - return - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - "INTERRUPT - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - "INTERRUPT - discards jump that caused the :finally - let dummy = 0 - endtry - elseif loop == 2 - Xloop 1 " X: 0 - endif - endwhile - Xloop 2 " X: 0 - endfunction - - try - Xpath 16384 " X: 16384 - call I("continue") - Xpath 32768 " X: 0 - finally - try - Xpath 65536 " X: 65536 - call I("break") - Xpath 131072 " X: 0 - finally - try - Xpath 262144 " X: 262144 - call I("return") - Xpath 524288 " X: 0 - finally - try - Xpath 1048576 " X: 1048576 - let g:jump = "finish" - ExecAsScript I - Xpath 2097152 " X: 0 - finally - unlet g:jump - try - Xpath 4194304 " X: 4194304 - call I("error") - Xpath 8388608 " X: 0 - finally - try - Xpath 16777216 " X: 16777216 - call I("interrupt") - Xpath 33554432 " X: 0 - finally - try - Xpath 67108864 " X: 67108864 - call I("throw") - Xpath 134217728 " X: 0 - finally - Xpath 268435456 " X: 268435456 - delfunction I - endtry - endtry - endtry - endtry - endtry - endtry - endtry - Xpath 536870912 " X: 0 - -endif - -Xcheck 357908480 - - -"------------------------------------------------------------------------------- -" Test 40: :finally reason discarded by :throw {{{1 -" -" When a :finally clause is executed due to a :continue, :break, -" :return, :finish, error, interrupt or :throw, the jump reason is -" discarded by a :throw in the finally clause. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - XloopINIT! 1 4 - - function! T(jump) - XloopNEXT - let loop = 0 - while loop < 2 - let loop = loop + 1 - if loop == 1 - try - if a:jump == "continue" - continue - elseif a:jump == "break" - break - elseif a:jump == "return" || a:jump == "finish" - return - elseif a:jump == "error" - asdf - elseif a:jump == "interrupt" - "INTERRUPT - let dummy = 0 - elseif a:jump == "throw" - throw "abc" - endif - finally - throw "xyz" " discards jump that caused the :finally - endtry - elseif loop == 2 - Xloop 1 " X: 0 - endif - endwhile - Xloop 2 " X: 0 - endfunction - - try - Xpath 16384 " X: 16384 - call T("continue") - Xpath 32768 " X: 0 - finally - try - Xpath 65536 " X: 65536 - call T("break") - Xpath 131072 " X: 0 - finally - try - Xpath 262144 " X: 262144 - call T("return") - Xpath 524288 " X: 0 - finally - try - Xpath 1048576 " X: 1048576 - let g:jump = "finish" - ExecAsScript T - Xpath 2097152 " X: 0 - finally - unlet g:jump - try - Xpath 4194304 " X: 4194304 - call T("error") - Xpath 8388608 " X: 0 - finally - try - Xpath 16777216 " X: 16777216 - call T("interrupt") - Xpath 33554432 " X: 0 - finally - try - Xpath 67108864 " X: 67108864 - call T("throw") - Xpath 134217728 " X: 0 - finally - Xpath 268435456 " X: 268435456 - delfunction T - endtry - endtry - endtry - endtry - endtry - endtry - endtry - Xpath 536870912 " X: 0 - -endif - -Xcheck 357908480 - -" Tests 41 to 48 were moved to test_trycatch.vim -let Xtest = 49 - - -"------------------------------------------------------------------------------- -" Test 49: Throwing exceptions across functions {{{1 -" -" When an exception is thrown but not caught inside a function, the -" caller is checked for a matching :catch clause. -"------------------------------------------------------------------------------- - -XpathINIT - -function! C() - try - Xpath 1 " X: 1 - throw "arrgh" - Xpath 2 " X: 0 - catch /arrgh/ - Xpath 4 " X: 4 - endtry - Xpath 8 " X: 8 -endfunction - -XloopINIT! 16 16 - -function! T1() - XloopNEXT - try - Xloop 1 " X: 16 + 16*16 - throw "arrgh" - Xloop 2 " X: 0 - finally - Xloop 4 " X: 64 + 64*16 - endtry - Xloop 8 " X: 0 -endfunction - -function! T2() - try - Xpath 4096 " X: 4096 - call T1() - Xpath 8192 " X: 0 - finally - Xpath 16384 " X: 16384 - endtry - Xpath 32768 " X: 0 -endfunction - -try - Xpath 65536 " X: 65536 - call C() " throw and catch - Xpath 131072 " X: 131072 -catch /.*/ - Xpath 262144 " X: 0 - Xout v:exception "in" v:throwpoint -endtry - -try - Xpath 524288 " X: 524288 - call T1() " throw, one level - Xpath 1048576 " X: 0 -catch /arrgh/ - Xpath 2097152 " X: 2097152 -catch /.*/ - Xpath 4194304 " X: 0 - Xout v:exception "in" v:throwpoint -endtry - -try - Xpath 8388608 " X: 8388608 - call T2() " throw, two levels - Xpath 16777216 " X: 0 -catch /arrgh/ - Xpath 33554432 " X: 33554432 -catch /.*/ - Xpath 67108864 " X: 0 - Xout v:exception "in" v:throwpoint -endtry -Xpath 134217728 " X: 134217728 - -Xcheck 179000669 - -" Leave C, T1, and T2 for execution as scripts in the next test. - - -"------------------------------------------------------------------------------- -" Test 50: Throwing exceptions across script files {{{1 -" -" When an exception is thrown but not caught inside a script file, -" the sourcing script or function is checked for a matching :catch -" clause. -" -" This test executes the bodies of the functions C, T1, and T2 from -" the previous test as script files (:return replaced by :finish). -"------------------------------------------------------------------------------- - -XpathINIT - -let scriptC = MakeScript("C") " X: 1 + 4 + 8 -delfunction C - -XloopINIT! 16 16 - -let scriptT1 = MakeScript("T1") " X: 16 + 64 + 16*16 + 64*16 -delfunction T1 - -let scriptT2 = MakeScript("T2", scriptT1) " X: 4096 + 16384 -delfunction T2 - -function! F() - try - Xpath 65536 " X: 65536 - exec "source" g:scriptC - Xpath 131072 " X: 131072 - catch /.*/ - Xpath 262144 " X: 0 - Xout v:exception "in" v:throwpoint - endtry - - try - Xpath 524288 " X: 524288 - exec "source" g:scriptT1 - Xpath 1048576 " X: 0 - catch /arrgh/ - Xpath 2097152 " X: 2097152 - catch /.*/ - Xpath 4194304 " X: 0 - Xout v:exception "in" v:throwpoint - endtry -endfunction - -try - Xpath 8388608 " X: 8388608 - call F() - Xpath 16777216 " X: 16777216 - exec "source" scriptT2 - Xpath 33554432 " X: 0 -catch /arrgh/ - Xpath 67108864 " X: 67108864 -catch /.*/ - Xpath 134217728 " X: 0 - Xout v:exception "in" v:throwpoint -endtry -Xpath 268435456 " X: 268435456 - -call delete(scriptC) -call delete(scriptT1) -call delete(scriptT2) -unlet scriptC scriptT1 scriptT2 -delfunction F - -Xcheck 363550045 - -" Test 51 was moved to test_trycatch.vim +" Tests 1 to 50, 87 were moved to test_vimscript.vim +" Tests 25, 26, 32, 33, 41-48, 51, 69-75 were moved to test_trycatch.vim let Xtest = 52 - "------------------------------------------------------------------------------- " Test 52: Uncaught exceptions {{{1 " diff --git a/src/testdir/test_vimscript.vim b/src/testdir/test_vimscript.vim index 0a03445a08a977..b752bc8ddbd7e3 100644 --- a/src/testdir/test_vimscript.vim +++ b/src/testdir/test_vimscript.vim @@ -3,14 +3,12 @@ source check.vim source shared.vim +source script_util.vim "------------------------------------------------------------------------------- " Test environment {{{1 "------------------------------------------------------------------------------- -com! XpathINIT let g:Xpath = '' -com! -nargs=1 -bar Xpath let g:Xpath = g:Xpath . - " Append a message to the "messages" file func Xout(text) split messages @@ -20,67 +18,30 @@ endfunc com! -nargs=1 Xout call Xout() -" MakeScript() - Make a script file from a function. {{{2 -" -" Create a script that consists of the body of the function a:funcname. -" Replace any ":return" by a ":finish", any argument variable by a global -" variable, and every ":call" by a ":source" for the next following argument -" in the variable argument list. This function is useful if similar tests are -" to be made for a ":return" from a function call or a ":finish" in a script -" file. -func MakeScript(funcname, ...) - let script = tempname() - execute "redir! >" . script - execute "function" a:funcname - redir END - execute "edit" script - " Delete the "function" and the "endfunction" lines. Do not include the - " word "function" in the pattern since it might be translated if LANG is - " set. When MakeScript() is being debugged, this deletes also the debugging - " output of its line 3 and 4. - exec '1,/.*' . a:funcname . '(.*)/d' - /^\d*\s*endfunction\>/,$d - %s/^\d*//e - %s/return/finish/e - %s/\ 0 - let cnt = cnt + 1 - s/\) - - "------------------------------------------------------------------------------- " Test 1: :endwhile in function {{{1 " @@ -90,7 +51,7 @@ com! -nargs=1 -bar ExecAsScript call ExecAsScript() " tests will hang. "------------------------------------------------------------------------------- -function! T1_F() +func T1_F() Xpath 'a' let first = 1 while 1 @@ -104,9 +65,9 @@ function! T1_F() return endif endwhile -endfunction +endfunc -function! T1_G() +func T1_G() Xpath 'h' let first = 1 while 1 @@ -121,7 +82,7 @@ function! T1_G() endif if 1 " unmatched :if endwhile -endfunction +endfunc func Test_endwhile_function() XpathINIT @@ -175,7 +136,7 @@ endfunc " Test 3: :if, :elseif, :while, :continue, :break {{{1 "------------------------------------------------------------------------------- -function Test_if_while() +func Test_if_while() XpathINIT if 1 Xpath 'a' @@ -235,7 +196,7 @@ endfunc " Test 4: :return {{{1 "------------------------------------------------------------------------------- -function! T4_F() +func T4_F() if 1 Xpath 'a' let loops = 3 @@ -253,15 +214,15 @@ function! T4_F() else Xpath 'g' endif -endfunction +endfunc -function Test_return() +func Test_return() XpathINIT call T4_F() Xpath '4' call assert_equal('ab3e3b2c24', g:Xpath) -endfunction +endfunc "------------------------------------------------------------------------------- @@ -271,14 +232,14 @@ endfunction " test as a script file (:return replaced by :finish). "------------------------------------------------------------------------------- -function Test_finish() +func Test_finish() XpathINIT ExecAsScript T4_F Xpath '5' call DeleteTheScript() call assert_equal('ab3e3b2c25', g:Xpath) -endfunction +endfunc @@ -412,7 +373,7 @@ delfunction G31 delfunction G32 delfunction G33 -function Test_defining_functions() +func Test_defining_functions() call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result) call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls) endfunc @@ -476,7 +437,7 @@ endfunc XpathINIT -function! T8_F() +func T8_F() if 1 Xpath 'a' while 1 @@ -508,9 +469,9 @@ function! T8_F() return novar " returns (default return value 0) Xpath 'q' return 1 " not reached -endfunction +endfunc -function! T8_G() abort +func T8_G() abort if 1 Xpath 'r' while 1 @@ -524,9 +485,9 @@ function! T8_G() abort Xpath 'x' return -4 " not reached -endfunction +endfunc -function! T8_H() abort +func T8_H() abort while 1 Xpath 'A' if 1 @@ -540,7 +501,7 @@ function! T8_H() abort Xpath 'F' return -4 " not reached -endfunction +endfunc " Aborted functions (T8_G and T8_H) return -1. let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H() @@ -567,7 +528,7 @@ endfunc XpathINIT -function! F() abort +func F() abort Xpath 'a' let result = G() " not aborted Xpath 'b' @@ -575,30 +536,30 @@ function! F() abort Xpath 'c' endif return 1 -endfunction +endfunc -function! G() " no abort attribute +func G() " no abort attribute Xpath 'd' if H() != -1 " aborted Xpath 'e' endif Xpath 'f' return 2 -endfunction +endfunc -function! H() abort +func H() abort Xpath 'g' call I() " aborted Xpath 'h' return 4 -endfunction +endfunc -function! I() abort +func I() abort Xpath 'i' asdf " error Xpath 'j' return 8 -endfunction +endfunc if F() != 1 Xpath 'k' @@ -626,7 +587,7 @@ endfunc XpathINIT -function! MSG(enr, emsg) +func MSG(enr, emsg) let english = v:lang == "C" || v:lang =~ '^[Ee]n' if a:enr == "" Xout "TODO: Add message number for:" a:emsg @@ -710,10 +671,10 @@ XpathINIT let calls = 0 -function! P(num) +func P(num) let g:calls = g:calls + a:num " side effect on call return 0 -endfunction +endfunc if 1 Xpath 'a' @@ -1092,7 +1053,1716 @@ func Test_unmatched_if_in_while() endfunc "------------------------------------------------------------------------------- +" Test 18: Interrupt (Ctrl-C pressed) {{{1 +" +" On an interrupt, the script processing is terminated immediately. +"------------------------------------------------------------------------------- + +func Test_interrupt_while_if() + let test =<< trim [CODE] + try + if 1 + Xpath 'a' + while 1 + Xpath 'b' + if 1 + Xpath 'c' + call interrupt() + call assert_report('should not get here') + break + finish + endif | call assert_report('should not get here') + call assert_report('should not get here') + endwhile | call assert_report('should not get here') + call assert_report('should not get here') + endif | call assert_report('should not get here') + call assert_report('should not get here') + catch /^Vim:Interrupt$/ + Xpath 'd' + endtry | Xpath 'e' + Xpath 'f' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcdef', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_interrupt_try() + let test =<< trim [CODE] + try + try + Xpath 'a' + call interrupt() + call assert_report('should not get here') + endtry | call assert_report('should not get here') + call assert_report('should not get here') + catch /^Vim:Interrupt$/ + Xpath 'b' + endtry | Xpath 'c' + Xpath 'd' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcd', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_interrupt_func_while_if() + let test =<< trim [CODE] + func F() + if 1 + Xpath 'a' + while 1 + Xpath 'b' + if 1 + Xpath 'c' + call interrupt() + call assert_report('should not get here') + break + return + endif | call assert_report('should not get here') + call assert_report('should not get here') + endwhile | call assert_report('should not get here') + call assert_report('should not get here') + endif | call assert_report('should not get here') + call assert_report('should not get here') + endfunc + + Xpath 'd' + try + call F() | call assert_report('should not get here') + catch /^Vim:Interrupt$/ + Xpath 'e' + endtry | Xpath 'f' + Xpath 'g' + [CODE] + let verify =<< trim [CODE] + call assert_equal('dabcefg', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_interrupt_func_try() + let test =<< trim [CODE] + func G() + try + Xpath 'a' + call interrupt() + call assert_report('should not get here') + endtry | call assert_report('should not get here') + call assert_report('should not get here') + endfunc + + Xpath 'b' + try + call G() | call assert_report('should not get here') + catch /^Vim:Interrupt$/ + Xpath 'c' + endtry | Xpath 'd' + Xpath 'e' + [CODE] + let verify =<< trim [CODE] + call assert_equal('bacde', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 19: Aborting on errors inside :try/:endtry {{{1 +" +" An error in a command dynamically enclosed in a :try/:endtry region +" aborts script processing immediately. It does not matter whether +" the failing command is outside or inside a function and whether a +" function has an "abort" attribute. +"------------------------------------------------------------------------------- + +func Test_try_error_abort_1() + let test =<< trim [CODE] + func F() abort + Xpath 'a' + asdf + call assert_report('should not get here') + endfunc + + try + Xpath 'b' + call F() + call assert_report('should not get here') + endtry | call assert_report('should not get here') + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('ba', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_try_error_abort_2() + let test =<< trim [CODE] + func G() + Xpath 'a' + asdf + call assert_report('should not get here') + endfunc + + try + Xpath 'b' + call G() + call assert_report('should not get here') + endtry | call assert_report('should not get here') + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('ba', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_try_error_abort_3() + let test =<< trim [CODE] + try + Xpath 'a' + asdf + call assert_report('should not get here') + endtry | call assert_report('should not get here') + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('a', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_try_error_abort_4() + let test =<< trim [CODE] + if 1 + try + Xpath 'a' + asdf + call assert_report('should not get here') + endtry | call assert_report('should not get here') + endif | call assert_report('should not get here') + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('a', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_try_error_abort_5() + let test =<< trim [CODE] + let p = 1 + while p + let p = 0 + try + Xpath 'a' + asdf + call assert_report('should not get here') + endtry | call assert_report('should not get here') + endwhile | call assert_report('should not get here') + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('a', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_try_error_abort_6() + let test =<< trim [CODE] + let p = 1 + Xpath 'a' + while p + Xpath 'b' + let p = 0 + try + Xpath 'c' + endwhile | call assert_report('should not get here') + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('abc', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 20: Aborting on errors after :try/:endtry {{{1 +" +" When an error occurs after the last active :try/:endtry region has +" been left, termination behavior is as if no :try/:endtry has been +" seen. +"------------------------------------------------------------------------------- + +func Test_error_after_try_1() + let test =<< trim [CODE] + let p = 1 + while p + let p = 0 + Xpath 'a' + try + Xpath 'b' + endtry + asdf + call assert_report('should not get here') + endwhile | call assert_report('should not get here') + Xpath 'c' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abc', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_error_after_try_2() + let test =<< trim [CODE] + while 1 + try + Xpath 'a' + break + call assert_report('should not get here') + endtry + endwhile + Xpath 'b' + asdf + Xpath 'c' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abc', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_error_after_try_3() + let test =<< trim [CODE] + while 1 + try + Xpath 'a' + break + call assert_report('should not get here') + finally + Xpath 'b' + endtry + endwhile + Xpath 'c' + asdf + Xpath 'd' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcd', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_error_after_try_4() + let test =<< trim [CODE] + while 1 + try + Xpath 'a' + finally + Xpath 'b' + break + call assert_report('should not get here') + endtry + endwhile + Xpath 'c' + asdf + Xpath 'd' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcd', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_error_after_try_5() + let test =<< trim [CODE] + let p = 1 + while p + let p = 0 + try + Xpath 'a' + continue + call assert_report('should not get here') + endtry + endwhile + Xpath 'b' + asdf + Xpath 'c' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abc', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_error_after_try_6() + let test =<< trim [CODE] + let p = 1 + while p + let p = 0 + try + Xpath 'a' + continue + call assert_report('should not get here') + finally + Xpath 'b' + endtry + endwhile + Xpath 'c' + asdf + Xpath 'd' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcd', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_error_after_try_7() + let test =<< trim [CODE] + let p = 1 + while p + let p = 0 + try + Xpath 'a' + finally + Xpath 'b' + continue + call assert_report('should not get here') + endtry + endwhile + Xpath 'c' + asdf + Xpath 'd' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcd', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 21: :finally for :try after :continue/:break/:return/:finish {{{1 +" +" If a :try conditional stays inactive due to a preceding :continue, +" :break, :return, or :finish, its :finally clause should not be +" executed. +"------------------------------------------------------------------------------- + +func Test_finally_after_loop_ctrl_statement() + let test =<< trim [CODE] + func F() + let loops = 2 + while loops > 0 + XloopNEXT + let loops = loops - 1 + try + if loops == 1 + Xloop 'a' + continue + call assert_report('should not get here') + elseif loops == 0 + Xloop 'b' + break + call assert_report('should not get here') + endif + + try " inactive + call assert_report('should not get here') + finally + call assert_report('should not get here') + endtry + finally + Xloop 'c' + endtry + call assert_report('should not get here') + endwhile + + try + Xpath 'd' + return + call assert_report('should not get here') + try " inactive + call assert_report('should not get here') + finally + call assert_report('should not get here') + endtry + finally + Xpath 'e' + endtry + call assert_report('should not get here') + endfunc + + try + Xpath 'f' + call F() + Xpath 'g' + finish + call assert_report('should not get here') + try " inactive + call assert_report('should not get here') + finally + call assert_report('should not get here') + endtry + finally + Xpath 'h' + endtry + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('fa2c2b3c3degh', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 22: :finally for a :try after an error/interrupt/:throw {{{1 +" +" If a :try conditional stays inactive due to a preceding error or +" interrupt or :throw, its :finally clause should not be executed. +"------------------------------------------------------------------------------- + +func Test_finally_after_error_in_func() + let test =<< trim [CODE] + func Error() + try + Xpath 'b' + asdf " aborting error, triggering error exception + call assert_report('should not get here') + endtry + call assert_report('should not get here') + endfunc + + Xpath 'a' + call Error() + call assert_report('should not get here') + + if 1 " not active due to error + try " not active since :if inactive + call assert_report('should not get here') + finally + call assert_report('should not get here') + endtry + endif + + try " not active due to error + call assert_report('should not get here') + finally + call assert_report('should not get here') + endtry + [CODE] + let verify =<< trim [CODE] + call assert_equal('ab', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_finally_after_interrupt() + let test =<< trim [CODE] + func Interrupt() + try + Xpath 'a' + call interrupt() " triggering interrupt exception + call assert_report('should not get here') + endtry + endfunc + + Xpath 'b' + try + call Interrupt() + catch /^Vim:Interrupt$/ + Xpath 'c' + finish + endtry + call assert_report('should not get here') + + if 1 " not active due to interrupt + try " not active since :if inactive + call assert_report('should not get here') + finally + call assert_report('should not get here') + endtry + endif + + try " not active due to interrupt + call assert_report('should not get here') + finally + call assert_report('should not get here') + endtry + [CODE] + let verify =<< trim [CODE] + call assert_equal('bac', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_finally_after_throw() + let test =<< trim [CODE] + func Throw() + Xpath 'a' + throw 'xyz' + endfunc + + Xpath 'b' + call Throw() + call assert_report('should not get here') + + if 1 " not active due to :throw + try " not active since :if inactive + call assert_report('should not get here') + finally + call assert_report('should not get here') + endtry + endif + + try " not active due to :throw + call assert_report('should not get here') + finally + call assert_report('should not get here') + endtry + [CODE] + let verify =<< trim [CODE] + call assert_equal('ba', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 23: :catch clauses for a :try after a :throw {{{1 +" +" If a :try conditional stays inactive due to a preceding :throw, +" none of its :catch clauses should be executed. +"------------------------------------------------------------------------------- + +func Test_catch_after_throw() + let test =<< trim [CODE] + try + Xpath 'a' + throw "xyz" + call assert_report('should not get here') + + if 1 " not active due to :throw + try " not active since :if inactive + call assert_report('should not get here') + catch /xyz/ + call assert_report('should not get here') + endtry + endif + catch /xyz/ + Xpath 'b' + endtry + + Xpath 'c' + throw "abc" + call assert_report('should not get here') + + try " not active due to :throw + call assert_report('should not get here') + catch /abc/ + call assert_report('should not get here') + endtry + [CODE] + let verify =<< trim [CODE] + call assert_equal('abc', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 24: :endtry for a :try after a :throw {{{1 +" +" If a :try conditional stays inactive due to a preceding :throw, +" its :endtry should not rethrow the exception to the next surrounding +" active :try conditional. "------------------------------------------------------------------------------- + +func Test_endtry_after_throw() + let test =<< trim [CODE] + try " try 1 + try " try 2 + Xpath 'a' + throw "xyz" " makes try 2 inactive + call assert_report('should not get here') + + try " try 3 + call assert_report('should not get here') + endtry " no rethrow to try 1 + catch /xyz/ " should catch although try 2 inactive + Xpath 'b' + endtry + catch /xyz/ " try 1 active, but exception already caught + call assert_report('should not get here') + endtry + Xpath 'c' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abc', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 27: Executing :finally clauses after :return {{{1 +" +" For a :return command dynamically enclosed in a :try/:endtry region, +" :finally clauses are executed and the called function is ended. +"------------------------------------------------------------------------------- + +func T27_F() + try + Xpath 'a' + try + Xpath 'b' + return + call assert_report('should not get here') + finally + Xpath 'c' + endtry + Xpath 'd' + finally + Xpath 'e' + endtry + call assert_report('should not get here') +endfunc + +func T27_G() + try + Xpath 'f' + return + call assert_report('should not get here') + finally + Xpath 'g' + call T27_F() + Xpath 'h' + endtry + call assert_report('should not get here') +endfunc + +func T27_H() + try + Xpath 'i' + call T27_G() + Xpath 'j' + finally + Xpath 'k' + return + call assert_report('should not get here') + endtry + call assert_report('should not get here') +endfunction + +func Test_finally_after_return() + XpathINIT + try + Xpath 'l' + call T27_H() + Xpath 'm' + finally + Xpath 'n' + endtry + call assert_equal('lifgabcehjkmn', g:Xpath) +endfunc + +"------------------------------------------------------------------------------- +" Test 28: Executing :finally clauses after :finish {{{1 +" +" For a :finish command dynamically enclosed in a :try/:endtry region, +" :finally clauses are executed and the sourced file is finished. +" +" This test executes the bodies of the functions F, G, and H from the +" previous test as script files (:return replaced by :finish). +"------------------------------------------------------------------------------- + +func Test_finally_after_finish() + XpathINIT + + let scriptF = MakeScript("T27_F") + let scriptG = MakeScript("T27_G", scriptF) + let scriptH = MakeScript("T27_H", scriptG) + + try + Xpath 'A' + exec "source" scriptH + Xpath 'B' + finally + Xpath 'C' + endtry + Xpath 'D' + call assert_equal('AifgabcehjkBCD', g:Xpath) + call delete(scriptF) + call delete(scriptG) + call delete(scriptH) +endfunc + +"------------------------------------------------------------------------------- +" Test 29: Executing :finally clauses on errors {{{1 +" +" After an error in a command dynamically enclosed in a :try/:endtry +" region, :finally clauses are executed and the script processing is +" terminated. +"------------------------------------------------------------------------------- + +func Test_finally_after_error_1() + let test =<< trim [CODE] + func F() + while 1 + try + Xpath 'a' + while 1 + try + Xpath 'b' + asdf " error + call assert_report('should not get here') + finally + Xpath 'c' + endtry | call assert_report('should not get here') + call assert_report('should not get here') + break + endwhile + call assert_report('should not get here') + finally + Xpath 'd' + endtry | call assert_report('should not get here') + call assert_report('should not get here') + break + endwhile + call assert_report('should not get here') + endfunc + + while 1 + try + Xpath 'e' + while 1 + call F() + call assert_report('should not get here') + break + endwhile | call assert_report('should not get here') + call assert_report('should not get here') + finally + Xpath 'f' + endtry | call assert_report('should not get here') + endwhile | call assert_report('should not get here') + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('eabcdf', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_finally_after_error_2() + let test =<< trim [CODE] + func G() abort + if 1 + try + Xpath 'a' + asdf " error + call assert_report('should not get here') + finally + Xpath 'b' + endtry | Xpath 'c' + endif | Xpath 'd' + call assert_report('should not get here') + endfunc + + if 1 + try + Xpath 'e' + call G() + call assert_report('should not get here') + finally + Xpath 'f' + endtry | call assert_report('should not get here') + endif | call assert_report('should not get here') + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('eabf', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 30: Executing :finally clauses on interrupt {{{1 +" +" After an interrupt in a command dynamically enclosed in +" a :try/:endtry region, :finally clauses are executed and the +" script processing is terminated. +"------------------------------------------------------------------------------- + +func Test_finally_on_interrupt() + let test =<< trim [CODE] + func F() + try + Xloop 'a' + call interrupt() + call assert_report('should not get here') + finally + Xloop 'b' + endtry + call assert_report('should not get here') + endfunc + + try + try + Xpath 'c' + try + Xpath 'd' + call interrupt() + call assert_report('should not get here') + finally + Xpath 'e' + try + Xpath 'f' + try + Xpath 'g' + finally + Xpath 'h' + try + Xpath 'i' + call interrupt() + call assert_report('should not get here') + endtry + call assert_report('should not get here') + endtry + call assert_report('should not get here') + endtry + call assert_report('should not get here') + endtry + call assert_report('should not get here') + finally + Xpath 'j' + try + Xpath 'k' + call F() + call assert_report('should not get here') + finally + Xpath 'l' + try + Xpath 'm' + XloopNEXT + ExecAsScript F + call assert_report('should not get here') + finally + Xpath 'n' + endtry + call assert_report('should not get here') + endtry + call assert_report('should not get here') + endtry + call assert_report('should not get here') + catch /^Vim:Interrupt$/ + Xpath 'o' + endtry + [CODE] + let verify =<< trim [CODE] + call assert_equal('cdefghijka1b1lma2b2no', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 31: Executing :finally clauses after :throw {{{1 +" +" After a :throw dynamically enclosed in a :try/:endtry region, +" :finally clauses are executed and the script processing is +" terminated. +"------------------------------------------------------------------------------- + +func Test_finally_after_throw_2() + let test =<< trim [CODE] + func F() + try + Xloop 'a' + throw "exception" + call assert_report('should not get here') + finally + Xloop 'b' + endtry + call assert_report('should not get here') + endfunc + + try + Xpath 'c' + try + Xpath 'd' + throw "exception" + call assert_report('should not get here') + finally + Xpath 'e' + try + Xpath 'f' + try + Xpath 'g' + finally + Xpath 'h' + try + Xpath 'i' + throw "exception" + call assert_report('should not get here') + endtry + call assert_report('should not get here') + endtry + call assert_report('should not get here') + endtry + call assert_report('should not get here') + endtry + call assert_report('should not get here') + finally + Xpath 'j' + try + Xpath 'k' + call F() + call assert_report('should not get here') + finally + Xpath 'l' + try + Xpath 'm' + XloopNEXT + ExecAsScript F + call assert_report('should not get here') + finally + Xpath 'n' + endtry + call assert_report('should not get here') + endtry + call assert_report('should not get here') + endtry + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('cdefghijka1b1lma2b2n', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 34: :finally reason discarded by :continue {{{1 +" +" When a :finally clause is executed due to a :continue, :break, +" :return, :finish, error, interrupt or :throw, the jump reason is +" discarded by a :continue in the finally clause. +"------------------------------------------------------------------------------- + +func Test_finally_after_continue() + let test =<< trim [CODE] + func C(jump) + XloopNEXT + let loop = 0 + while loop < 2 + let loop = loop + 1 + if loop == 1 + try + if a:jump == "continue" + continue + elseif a:jump == "break" + break + elseif a:jump == "return" || a:jump == "finish" + return + elseif a:jump == "error" + asdf + elseif a:jump == "interrupt" + call interrupt() + let dummy = 0 + elseif a:jump == "throw" + throw "abc" + endif + finally + continue " discards jump that caused the :finally + call assert_report('should not get here') + endtry + call assert_report('should not get here') + elseif loop == 2 + Xloop 'a' + endif + endwhile + endfunc + + call C("continue") + Xpath 'b' + call C("break") + Xpath 'c' + call C("return") + Xpath 'd' + let g:jump = "finish" + ExecAsScript C + unlet g:jump + Xpath 'e' + try + call C("error") + Xpath 'f' + finally + Xpath 'g' + try + call C("interrupt") + Xpath 'h' + finally + Xpath 'i' + call C("throw") + Xpath 'j' + endtry + endtry + Xpath 'k' + [CODE] + let verify =<< trim [CODE] + call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 35: :finally reason discarded by :break {{{1 +" +" When a :finally clause is executed due to a :continue, :break, +" :return, :finish, error, interrupt or :throw, the jump reason is +" discarded by a :break in the finally clause. +"------------------------------------------------------------------------------- + +func Test_finally_discard_by_break() + let test =<< trim [CODE] + func B(jump) + XloopNEXT + let loop = 0 + while loop < 2 + let loop = loop + 1 + if loop == 1 + try + if a:jump == "continue" + continue + elseif a:jump == "break" + break + elseif a:jump == "return" || a:jump == "finish" + return + elseif a:jump == "error" + asdf + elseif a:jump == "interrupt" + call interrupt() + let dummy = 0 + elseif a:jump == "throw" + throw "abc" + endif + finally + break " discards jump that caused the :finally + call assert_report('should not get here') + endtry + elseif loop == 2 + call assert_report('should not get here') + endif + endwhile + Xloop 'a' + endfunc + + call B("continue") + Xpath 'b' + call B("break") + Xpath 'c' + call B("return") + Xpath 'd' + let g:jump = "finish" + ExecAsScript B + unlet g:jump + Xpath 'e' + try + call B("error") + Xpath 'f' + finally + Xpath 'g' + try + call B("interrupt") + Xpath 'h' + finally + Xpath 'i' + call B("throw") + Xpath 'j' + endtry + endtry + Xpath 'k' + [CODE] + let verify =<< trim [CODE] + call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 36: :finally reason discarded by :return {{{1 +" +" When a :finally clause is executed due to a :continue, :break, +" :return, :finish, error, interrupt or :throw, the jump reason is +" discarded by a :return in the finally clause. +"------------------------------------------------------------------------------- + +func Test_finally_discard_by_return() + let test =<< trim [CODE] + func R(jump, retval) abort + let loop = 0 + while loop < 2 + let loop = loop + 1 + if loop == 1 + try + if a:jump == "continue" + continue + elseif a:jump == "break" + break + elseif a:jump == "return" + return + elseif a:jump == "error" + asdf + elseif a:jump == "interrupt" + call interrupt() + let dummy = 0 + elseif a:jump == "throw" + throw "abc" + endif + finally + return a:retval " discards jump that caused the :finally + call assert_report('should not get here') + endtry + elseif loop == 2 + call assert_report('should not get here') + endif + endwhile + call assert_report('should not get here') + endfunc + + let sum = -R("continue", -8) + Xpath 'a' + let sum = sum - R("break", -16) + Xpath 'b' + let sum = sum - R("return", -32) + Xpath 'c' + try + let sum = sum - R("error", -64) + Xpath 'd' + finally + Xpath 'e' + try + let sum = sum - R("interrupt", -128) + Xpath 'f' + finally + Xpath 'g' + let sum = sum - R("throw", -256) + Xpath 'h' + endtry + endtry + Xpath 'i' + + let expected = 8 + 16 + 32 + 64 + 128 + 256 + call assert_equal(sum, expected) + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcdefghi', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 37: :finally reason discarded by :finish {{{1 +" +" When a :finally clause is executed due to a :continue, :break, +" :return, :finish, error, interrupt or :throw, the jump reason is +" discarded by a :finish in the finally clause. +"------------------------------------------------------------------------------- + +func Test_finally_discard_by_finish() + let test =<< trim [CODE] + func F(jump) " not executed as function, transformed to a script + let loop = 0 + while loop < 2 + let loop = loop + 1 + if loop == 1 + try + if a:jump == "continue" + continue + elseif a:jump == "break" + break + elseif a:jump == "finish" + finish + elseif a:jump == "error" + asdf + elseif a:jump == "interrupt" + call interrupt() + let dummy = 0 + elseif a:jump == "throw" + throw "abc" + endif + finally + finish " discards jump that caused the :finally + call assert_report('should not get here') + endtry + elseif loop == 2 + call assert_report('should not get here') + endif + endwhile + call assert_report('should not get here') + endfunc + + let scriptF = MakeScript("F") + delfunction F + + let g:jump = "continue" + exec "source" scriptF + Xpath 'a' + let g:jump = "break" + exec "source" scriptF + Xpath 'b' + let g:jump = "finish" + exec "source" scriptF + Xpath 'c' + try + let g:jump = "error" + exec "source" scriptF + Xpath 'd' + finally + Xpath 'e' + try + let g:jump = "interrupt" + exec "source" scriptF + Xpath 'f' + finally + Xpath 'g' + try + let g:jump = "throw" + exec "source" scriptF + Xpath 'h' + finally + Xpath 'i' + endtry + endtry + endtry + unlet g:jump + call delete(scriptF) + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcdefghi', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 38: :finally reason discarded by an error {{{1 +" +" When a :finally clause is executed due to a :continue, :break, +" :return, :finish, error, interrupt or :throw, the jump reason is +" discarded by an error in the finally clause. +"------------------------------------------------------------------------------- + +func Test_finally_discard_by_error() + let test =<< trim [CODE] + func E(jump) + let loop = 0 + while loop < 2 + let loop = loop + 1 + if loop == 1 + try + if a:jump == "continue" + continue + elseif a:jump == "break" + break + elseif a:jump == "return" || a:jump == "finish" + return + elseif a:jump == "error" + asdf + elseif a:jump == "interrupt" + call interrupt() + let dummy = 0 + elseif a:jump == "throw" + throw "abc" + endif + finally + asdf " error; discards jump that caused the :finally + endtry + elseif loop == 2 + call assert_report('should not get here') + endif + endwhile + call assert_report('should not get here') + endfunc + + try + Xpath 'a' + call E("continue") + call assert_report('should not get here') + finally + try + Xpath 'b' + call E("break") + call assert_report('should not get here') + finally + try + Xpath 'c' + call E("return") + call assert_report('should not get here') + finally + try + Xpath 'd' + let g:jump = "finish" + ExecAsScript E + call assert_report('should not get here') + finally + unlet g:jump + try + Xpath 'e' + call E("error") + call assert_report('should not get here') + finally + try + Xpath 'f' + call E("interrupt") + call assert_report('should not get here') + finally + try + Xpath 'g' + call E("throw") + call assert_report('should not get here') + finally + Xpath 'h' + delfunction E + endtry + endtry + endtry + endtry + endtry + endtry + endtry + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcdefgh', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 39: :finally reason discarded by an interrupt {{{1 +" +" When a :finally clause is executed due to a :continue, :break, +" :return, :finish, error, interrupt or :throw, the jump reason is +" discarded by an interrupt in the finally clause. +"------------------------------------------------------------------------------- + +func Test_finally_discarded_by_interrupt() + let test =<< trim [CODE] + func I(jump) + let loop = 0 + while loop < 2 + let loop = loop + 1 + if loop == 1 + try + if a:jump == "continue" + continue + elseif a:jump == "break" + break + elseif a:jump == "return" || a:jump == "finish" + return + elseif a:jump == "error" + asdf + elseif a:jump == "interrupt" + call interrupt() + let dummy = 0 + elseif a:jump == "throw" + throw "abc" + endif + finally + call interrupt() + let dummy = 0 + endtry + elseif loop == 2 + call assert_report('should not get here') + endif + endwhile + call assert_report('should not get here') + endfunc + + try + try + Xpath 'a' + call I("continue") + call assert_report('should not get here') + finally + try + Xpath 'b' + call I("break") + call assert_report('should not get here') + finally + try + Xpath 'c' + call I("return") + call assert_report('should not get here') + finally + try + Xpath 'd' + let g:jump = "finish" + ExecAsScript I + call assert_report('should not get here') + finally + unlet g:jump + try + Xpath 'e' + call I("error") + call assert_report('should not get here') + finally + try + Xpath 'f' + call I("interrupt") + call assert_report('should not get here') + finally + try + Xpath 'g' + call I("throw") + call assert_report('should not get here') + finally + Xpath 'h' + delfunction I + endtry + endtry + endtry + endtry + endtry + endtry + endtry + call assert_report('should not get here') + catch /^Vim:Interrupt$/ + Xpath 'A' + endtry + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcdefghA', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 40: :finally reason discarded by :throw {{{1 +" +" When a :finally clause is executed due to a :continue, :break, +" :return, :finish, error, interrupt or :throw, the jump reason is +" discarded by a :throw in the finally clause. +"------------------------------------------------------------------------------- + +func Test_finally_discard_by_throw() + let test =<< trim [CODE] + func T(jump) + let loop = 0 + while loop < 2 + let loop = loop + 1 + if loop == 1 + try + if a:jump == "continue" + continue + elseif a:jump == "break" + break + elseif a:jump == "return" || a:jump == "finish" + return + elseif a:jump == "error" + asdf + elseif a:jump == "interrupt" + call interrupt() + let dummy = 0 + elseif a:jump == "throw" + throw "abc" + endif + finally + throw "xyz" " discards jump that caused the :finally + endtry + elseif loop == 2 + call assert_report('should not get here') + endif + endwhile + call assert_report('should not get here') + endfunc + + try + Xpath 'a' + call T("continue") + call assert_report('should not get here') + finally + try + Xpath 'b' + call T("break") + call assert_report('should not get here') + finally + try + Xpath 'c' + call T("return") + call assert_report('should not get here') + finally + try + Xpath 'd' + let g:jump = "finish" + ExecAsScript T + call assert_report('should not get here') + finally + unlet g:jump + try + Xpath 'e' + call T("error") + call assert_report('should not get here') + finally + try + Xpath 'f' + call T("interrupt") + call assert_report('should not get here') + finally + try + Xpath 'g' + call T("throw") + call assert_report('should not get here') + finally + Xpath 'h' + delfunction T + endtry + endtry + endtry + endtry + endtry + endtry + endtry + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcdefgh', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 49: Throwing exceptions across functions {{{1 +" +" When an exception is thrown but not caught inside a function, the +" caller is checked for a matching :catch clause. +"------------------------------------------------------------------------------- + +func T49_C() + try + Xpath 'a' + throw "arrgh" + call assert_report('should not get here') + catch /arrgh/ + Xpath 'b' + endtry + Xpath 'c' +endfunc + +func T49_T1() + XloopNEXT + try + Xloop 'd' + throw "arrgh" + call assert_report('should not get here') + finally + Xloop 'e' + endtry + Xloop 'f' +endfunc + +func T49_T2() + try + Xpath 'g' + call T49_T1() + call assert_report('should not get here') + finally + Xpath 'h' + endtry + call assert_report('should not get here') +endfunc + +func Test_throw_exception_across_funcs() + XpathINIT + XloopINIT + try + Xpath 'i' + call T49_C() " throw and catch + Xpath 'j' + catch /.*/ + call assert_report('should not get here') + endtry + + try + Xpath 'k' + call T49_T1() " throw, one level + call assert_report('should not get here') + catch /arrgh/ + Xpath 'l' + catch /.*/ + call assert_report('should not get here') + endtry + + try + Xpath 'm' + call T49_T2() " throw, two levels + call assert_report('should not get here') + catch /arrgh/ + Xpath 'n' + catch /.*/ + call assert_report('should not get here') + endtry + Xpath 'o' + + call assert_equal('iabcjkd2e2lmgd3e3hno', g:Xpath) +endfunc + +"------------------------------------------------------------------------------- +" Test 50: Throwing exceptions across script files {{{1 +" +" When an exception is thrown but not caught inside a script file, +" the sourcing script or function is checked for a matching :catch +" clause. +" +" This test executes the bodies of the functions C, T1, and T2 from +" the previous test as script files (:return replaced by :finish). +"------------------------------------------------------------------------------- + +func T50_F() + try + Xpath 'A' + exec "source" g:scriptC + Xpath 'B' + catch /.*/ + call assert_report('should not get here') + endtry + + try + Xpath 'C' + exec "source" g:scriptT1 + call assert_report('should not get here') + catch /arrgh/ + Xpath 'D' + catch /.*/ + call assert_report('should not get here') + endtry +endfunc + +func Test_throw_across_script() + XpathINIT + XloopINIT + let g:scriptC = MakeScript("T49_C") + let g:scriptT1 = MakeScript("T49_T1") + let scriptT2 = MakeScript("T49_T2", g:scriptT1) + + try + Xpath 'E' + call T50_F() + Xpath 'F' + exec "source" scriptT2 + call assert_report('should not get here') + catch /arrgh/ + Xpath 'G' + catch /.*/ + call assert_report('should not get here') + endtry + Xpath 'H' + call assert_equal('EAabcBCd2e2DFgd3e3hGH', g:Xpath) + + call delete(g:scriptC) + call delete(g:scriptT1) + call delete(scriptT2) + unlet g:scriptC g:scriptT1 scriptT2 +endfunc + "------------------------------------------------------------------------------- " Test 87 using (expr) ? funcref : funcref {{{1 " diff --git a/src/version.c b/src/version.c index 112a502e483539..97bdb24c074cc2 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1366, /**/ 1365, /**/ From b4caa163ff7bfacd4bec00e4baa55b5669ff1191 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 11:36:52 +0200 Subject: [PATCH 0080/1384] patch 8.2.1367: Vim9: no error for missing white space around operator Problem: Vim9: no error for missing white space around operator. Solution: Check for white space around *, / and %. --- src/eval.c | 22 ++++++++++++++++---- src/testdir/test_vim9_expr.vim | 37 +++++++++++++++++++++++++++++++++- src/version.c | 2 ++ 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/eval.c b/src/eval.c index 3c4e5bdefc26bc..b8367e0cfbc60f 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2586,13 +2586,14 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg) break; evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE); + oplen = (concat && p[1] == '.') ? 2 : 1; if (getnext) *arg = eval_next_line(evalarg); else { if (evaluate && in_vim9script() && !VIM_ISWHITE(**arg)) { - error_white_both(p, 1); + error_white_both(p, oplen); clear_tv(rettv); return FAIL; } @@ -2622,7 +2623,6 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg) /* * Get the second variable. */ - oplen = (op == '.' && *(*arg + 1) == '.') ? 2 : 1; if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[oplen])) { error_white_both(p, oplen); @@ -2796,17 +2796,25 @@ eval6( if (op != '*' && op != '/' && op != '%') break; + evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE); if (getnext) *arg = eval_next_line(evalarg); else + { + if (evaluate && in_vim9script() && !VIM_ISWHITE(**arg)) + { + error_white_both(p, 1); + clear_tv(rettv); + return FAIL; + } *arg = p; + } #ifdef FEAT_FLOAT f1 = 0; f2 = 0; #endif error = FALSE; - evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE); if (evaluate) { #ifdef FEAT_FLOAT @@ -2829,7 +2837,13 @@ eval6( /* * Get the second variable. */ - *arg = skipwhite(*arg + 1); + if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[1])) + { + error_white_both(p, 1); + clear_tv(rettv); + return FAIL; + } + *arg = skipwhite_and_linebreak(*arg + 1, evalarg); if (eval7(arg, &var2, evalarg, FALSE) == FAIL) return FAIL; diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 7e53a287d5ca09..ab274a10dfa024 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -841,6 +841,15 @@ def Test_expr5_vim9script() END CheckScriptSuccess(lines) + lines =<< trim END + vim9script + let var = 11 + + 77 - + 22 + assert_equal(66, var) + END + CheckScriptSuccess(lines) + lines =<< trim END vim9script let var = 'one' @@ -999,7 +1008,7 @@ def Test_expr6() enddef def Test_expr6_vim9script() - # only checks line continuation + # check line continuation let lines =<< trim END vim9script let var = 11 @@ -1016,6 +1025,32 @@ def Test_expr6_vim9script() assert_equal(5, var) END CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + let var = 11 * + 22 / + 3 + assert_equal(80, var) + END + CheckScriptSuccess(lines) + + # check white space + lines =<< trim END + vim9script + echo 5*6 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + echo 5 *6 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + echo 5* 6 + END + CheckScriptFailure(lines, 'E1004:') enddef def Test_expr6_float() diff --git a/src/version.c b/src/version.c index 97bdb24c074cc2..7ec5d2d2e4eff9 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1367, /**/ 1366, /**/ From ff1cd39cfe62d5089d5e703f4eb290694751ace3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 11:51:30 +0200 Subject: [PATCH 0081/1384] patch 8.2.1368: Vim9: no error for missing white space around operator Problem: Vim9: no error for missing white space around operator. Solution: Check for white space around <, !=, etc. --- src/eval.c | 24 +++++++++++++++++++----- src/testdir/test_vim9_expr.vim | 32 ++++++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/eval.c b/src/eval.c index b8367e0cfbc60f..6411ffa146bdf0 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2422,7 +2422,7 @@ eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg) * var1 isnot var2 * * "arg" must point to the first non-white of the expression. - * "arg" is advanced to the next non-white after the recognized expression. + * "arg" is advanced to just after the recognized expression. * * Return OK or FAIL. */ @@ -2452,9 +2452,17 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg) typval_T var2; int ic; int vim9script = in_vim9script(); + int evaluate = evalarg == NULL + ? 0 : (evalarg->eval_flags & EVAL_EVALUATE); if (getnext) *arg = eval_next_line(evalarg); + else if (evaluate && vim9script && !VIM_ISWHITE(**arg)) + { + error_white_both(p, len); + clear_tv(rettv); + return FAIL; + } if (vim9script && type_is && (p[len] == '?' || p[len] == '#')) { @@ -2482,13 +2490,19 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg) /* * Get the second variable. */ + if (evaluate && vim9script && !IS_WHITE_OR_NUL(p[len])) + { + error_white_both(p, 1); + clear_tv(rettv); + return FAIL; + } *arg = skipwhite_and_linebreak(p + len, evalarg); if (eval5(arg, &var2, evalarg) == FAIL) { clear_tv(rettv); return FAIL; } - if (evalarg != NULL && (evalarg->eval_flags & EVAL_EVALUATE)) + if (evaluate) { int ret; @@ -2552,7 +2566,7 @@ eval_addlist(typval_T *tv1, typval_T *tv2) * .. string concatenation * * "arg" must point to the first non-white of the expression. - * "arg" is advanced to the next non-white after the recognized expression. + * "arg" is advanced to just after the recognized expression. * * Return OK or FAIL. */ @@ -2754,7 +2768,7 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg) * % number modulo * * "arg" must point to the first non-white of the expression. - * "arg" is advanced to the next non-white after the recognized expression. + * "arg" is advanced to just after the recognized expression. * * Return OK or FAIL. */ @@ -2956,7 +2970,7 @@ eval6( * trailing ->name() method call * * "arg" must point to the first non-white of the expression. - * "arg" is advanced to the next non-white after the recognized expression. + * "arg" is advanced to just after the recognized expression. * * Return OK or FAIL. */ diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index ab274a10dfa024..aa7aed72a19856 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -726,6 +726,38 @@ def Test_expr4_vimscript() set noignorecase END CheckScriptSuccess(lines) + + # check missing white space + lines =<< trim END + vim9script + echo 2>3 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + echo 2 >3 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + echo 2> 3 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + echo 2!=3 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + echo 2 !=3 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + echo 2!= 3 + END + CheckScriptFailure(lines, 'E1004:') enddef func Test_expr4_fails() diff --git a/src/version.c b/src/version.c index 7ec5d2d2e4eff9..2609eb7e08d9e1 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1368, /**/ 1367, /**/ From 14ddd226daa324831e1872c352452f202fd6068c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 12:02:40 +0200 Subject: [PATCH 0082/1384] patch 8.2.1369: MS-Windows: autocommand test sometimes fails Problem: MS-Windows: autocommand test sometimes fails. Solution: Do not rely on the cat command. --- src/testdir/test_autocmd.vim | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index 70fbe01c0fc008..e6c7ec03c342e6 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -1618,7 +1618,7 @@ func Test_change_mark_in_autocmds() write au! BufWritePre - if executable('cat') + if has('unix') write XtestFilter write >> XtestFilter diff --git a/src/version.c b/src/version.c index 2609eb7e08d9e1..a0f4593b2d7d59 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1369, /**/ 1368, /**/ From c753478b82613df37b145764e27f5514542edb97 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 12:10:50 +0200 Subject: [PATCH 0083/1384] patch 8.2.1370: MS-Windows: warning for using fstat() with stat_T Problem: MS-Windows: warning for using fstat() with stat_T. Solution: use _fstat64() if available. (Naruhiko Nishino, closes #6625) --- src/macros.h | 10 +++++++++- src/version.c | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/macros.h b/src/macros.h index 7604910a6d6e5a..7557b2691769d6 100644 --- a/src/macros.h +++ b/src/macros.h @@ -166,7 +166,15 @@ # ifndef MSWIN # define mch_access(n, p) access((n), (p)) # endif -# define mch_fstat(n, p) fstat((n), (p)) + +// Use 64-bit fstat function if available. +// NOTE: This condition is the same as for the stat_T type. +# if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__MINGW32__) +# define mch_fstat(n, p) _fstat64((n), (p)) +# else +# define mch_fstat(n, p) fstat((n), (p)) +# endif + # ifdef MSWIN // has its own mch_stat() function # define mch_stat(n, p) vim_stat((n), (p)) # else diff --git a/src/version.c b/src/version.c index a0f4593b2d7d59..5246d84c2e711c 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1370, /**/ 1369, /**/ From 3c1c9fd94bc80871119a8519f3b881595082a6c0 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 12:32:38 +0200 Subject: [PATCH 0084/1384] patch 8.2.1371: Vim9: no error for missing white space around operator Problem: Vim9: no error for missing white space around operator. Solution: Check for white space around && and ||. --- src/eval.c | 28 ++++++++++++++++++++++++++++ src/testdir/test_vim9_expr.vim | 34 ++++++++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 64 insertions(+) diff --git a/src/eval.c b/src/eval.c index 6411ffa146bdf0..a9c36ac38c1153 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2242,11 +2242,25 @@ eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg) if (getnext) *arg = eval_next_line(evalarg_used); else + { + if (evaluate && in_vim9script() && !VIM_ISWHITE(p[-1])) + { + error_white_both(p, 2); + clear_tv(rettv); + return FAIL; + } *arg = p; + } /* * Get the second variable. */ + if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[2])) + { + error_white_both(p, 2); + clear_tv(rettv); + return FAIL; + } *arg = skipwhite_and_linebreak(*arg + 2, evalarg_used); evalarg_used->eval_flags = !result ? orig_flags : orig_flags & ~EVAL_EVALUATE; @@ -2359,11 +2373,25 @@ eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg) if (getnext) *arg = eval_next_line(evalarg_used); else + { + if (evaluate && in_vim9script() && !VIM_ISWHITE(p[-1])) + { + error_white_both(p, 2); + clear_tv(rettv); + return FAIL; + } *arg = p; + } /* * Get the second variable. */ + if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[2])) + { + error_white_both(p, 2); + clear_tv(rettv); + return FAIL; + } *arg = skipwhite_and_linebreak(*arg + 2, evalarg_used); evalarg_used->eval_flags = result ? orig_flags : orig_flags & ~EVAL_EVALUATE; diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index aa7aed72a19856..70813377b56117 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -175,6 +175,23 @@ def Test_expr2_vimscript() END CheckScriptSuccess(lines) + # check white space + lines =<< trim END + vim9script + let var = v:true||v:true + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + let var = v:true ||v:true + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + let var = v:true|| v:true + END + CheckScriptFailure(lines, 'E1004:') + # check keeping the value lines =<< trim END vim9script @@ -279,6 +296,23 @@ def Test_expr3_vimscript() END CheckScriptSuccess(lines) + # check white space + lines =<< trim END + vim9script + let var = v:true&&v:true + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + let var = v:true &&v:true + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + let var = v:true&& v:true + END + CheckScriptFailure(lines, 'E1004:') + # check keeping the value lines =<< trim END vim9script diff --git a/src/version.c b/src/version.c index 5246d84c2e711c..9d06cd20e3efb6 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1371, /**/ 1370, /**/ From fdac71c5075062f97f77044e9619fa5c907e0327 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 12:44:41 +0200 Subject: [PATCH 0085/1384] patch 8.2.1372: Vim9: no error for missing white space around operator Problem: Vim9: no error for missing white space around operator. Solution: Check for white space around ? and :. --- src/eval.c | 34 +++++++++++++++++++++++++++++++--- src/testdir/test_vim9_expr.vim | 29 ++++++++++++++++++++++++++++- src/version.c | 2 ++ 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/eval.c b/src/eval.c index a9c36ac38c1153..a7f6086ef66ba8 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2072,7 +2072,7 @@ eval0( * expr2 ? expr1 : expr1 * * "arg" must point to the first non-white of the expression. - * "arg" is advanced to the next non-white after the recognized expression. + * "arg" is advanced to just after the recognized expression. * * Note: "rettv.v_lock" is not set. * @@ -2111,7 +2111,15 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) if (getnext) *arg = eval_next_line(evalarg_used); else + { + if (evaluate && in_vim9script() && !VIM_ISWHITE(p[-1])) + { + error_white_both(p, 1); + clear_tv(rettv); + return FAIL; + } *arg = p; + } result = FALSE; if (evaluate) @@ -2128,6 +2136,12 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) /* * Get the second variable. Recursive! */ + if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[1])) + { + error_white_both(p, 1); + clear_tv(rettv); + return FAIL; + } *arg = skipwhite_and_linebreak(*arg + 1, evalarg_used); evalarg_used->eval_flags = result ? orig_flags : orig_flags & ~EVAL_EVALUATE; @@ -2148,11 +2162,25 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) if (getnext) *arg = eval_next_line(evalarg_used); else + { + if (evaluate && in_vim9script() && !VIM_ISWHITE(p[-1])) + { + error_white_both(p, 1); + clear_tv(rettv); + return FAIL; + } *arg = p; + } /* * Get the third variable. Recursive! */ + if (evaluate && in_vim9script() && !IS_WHITE_OR_NUL((*arg)[1])) + { + error_white_both(p, 1); + clear_tv(rettv); + return FAIL; + } *arg = skipwhite_and_linebreak(*arg + 1, evalarg_used); evalarg_used->eval_flags = !result ? orig_flags : orig_flags & ~EVAL_EVALUATE; @@ -2179,7 +2207,7 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) * expr2 || expr2 || expr2 logical OR * * "arg" must point to the first non-white of the expression. - * "arg" is advanced to the next non-white after the recognized expression. + * "arg" is advanced to just after the recognized expression. * * Return OK or FAIL. */ @@ -2310,7 +2338,7 @@ eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg) * expr3 && expr3 && expr3 logical AND * * "arg" must point to the first non-white of the expression. - * "arg" is advanced to the next non-white after the recognized expression. + * "arg" is advanced to just after the recognized expression. * * Return OK or FAIL. */ diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 70813377b56117..8be0dea36e78b8 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -60,7 +60,7 @@ def Test_expr1() enddef def Test_expr1_vimscript() - # only checks line continuation + # check line continuation let lines =<< trim END vim9script let var = 1 @@ -87,6 +87,33 @@ def Test_expr1_vimscript() assert_equal('no', var) END CheckScriptSuccess(lines) + + # check white space + lines =<< trim END + vim9script + let var = v:true?1:2 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + let var = v:true? 1 : 2 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + let var = v:true ?1 : 2 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + let var = v:true ? 1: 2 + END + CheckScriptFailure(lines, 'E1004:') + lines =<< trim END + vim9script + let var = v:true ? 1 :2 + END + CheckScriptFailure(lines, 'E1004:') enddef func Test_expr1_fails() diff --git a/src/version.c b/src/version.c index 9d06cd20e3efb6..1e23a08ad609dd 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1372, /**/ 1371, /**/ From f9b2b49663226235f94f08230fe9023caf80a6e9 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 14:34:14 +0200 Subject: [PATCH 0086/1384] patch 8.2.1373: Vim9: no error for assigning to non-existing script var Problem: Vim9: no error for assigning to non-existing script var. Solution: Check that in Vim9 script the variable was defined. (closes #6630) --- src/structs.h | 4 +- src/testdir/test_vim9_script.vim | 9 ++++ src/userfunc.c | 1 + src/version.c | 2 + src/vim9compile.c | 88 +++++++++++++++++++------------- 5 files changed, 68 insertions(+), 36 deletions(-) diff --git a/src/structs.h b/src/structs.h index 7e34d809981bde..a80de6a71f92e5 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1594,7 +1594,9 @@ typedef struct int uf_tml_execed; // line being timed was executed # endif sctx_T uf_script_ctx; // SCTX where function was defined, - // used for s: variables + // used for s: variables; sc_version changed + // for :function + int uf_script_ctx_version; // original sc_version of SCTX int uf_refcount; // reference count, see func_name_refcount() funccall_T *uf_scoped; // l: local variables for closure diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 64ac3bbd925c1b..f99333c0cbb4fd 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -112,6 +112,15 @@ def Test_assignment() call CheckDefFailure(['let s:var = 123'], 'E1101:') call CheckDefFailure(['let s:var: number'], 'E1101:') + lines =<< trim END + vim9script + def SomeFunc() + s:var = 123 + enddef + defcompile + END + call CheckScriptFailure(lines, 'E1089:') + g:inc_counter += 1 assert_equal(2, g:inc_counter) diff --git a/src/userfunc.c b/src/userfunc.c index 43aa146a9827bd..684a805d8abaf0 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -3508,6 +3508,7 @@ def_function(exarg_T *eap, char_u *name_arg) fp->uf_calls = 0; fp->uf_cleared = FALSE; fp->uf_script_ctx = current_sctx; + fp->uf_script_ctx_version = current_sctx.sc_version; fp->uf_script_ctx.sc_lnum += sourcing_lnum_top; if (is_export) { diff --git a/src/version.c b/src/version.c index 1e23a08ad609dd..7b1b8d8c2199ab 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1373, /**/ 1372, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index f8381d7837d3bc..dc10b4851b8b5c 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -148,6 +148,7 @@ static char e_syntax_at[] = N_("E1002: Syntax error at %s"); static char e_used_as_arg[] = N_("E1006: %s is used as an argument"); static char e_cannot_use_void[] = N_("E1031: Cannot use void value"); static char e_namespace[] = N_("E1075: Namespace not supported: %s"); +static char e_unknown_var[] = N_("E1089: unknown variable: %s"); static void delete_def_function_contents(dfunc_T *dfunc); static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx); @@ -5335,7 +5336,6 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) else { int idx; - imported_T *import = NULL; for (idx = 0; reserved[idx] != NULL; ++idx) if (STRCMP(reserved[idx], name) == 0) @@ -5374,49 +5374,67 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) goto theend; } } - else if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0) - || lookup_script(var_start, varlen) == OK - || (import = find_imported(var_start, varlen, cctx)) - != NULL) + else { - char_u *rawname = name + (name[1] == ':' ? 2 : 0); - - if (is_decl) + int script_namespace = varlen > 1 + && STRNCMP(var_start, "s:", 2) == 0; + int script_var = (script_namespace + ? lookup_script(var_start + 2, varlen - 2) + : lookup_script(var_start, varlen)) == OK; + imported_T *import = + find_imported(var_start, varlen, cctx); + + if (script_namespace || script_var || import != NULL) { - if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0)) - semsg(_("E1101: Cannot declare a script variable in a function: %s"), + char_u *rawname = name + (name[1] == ':' ? 2 : 0); + + if (is_decl) + { + if (script_namespace) + semsg(_("E1101: Cannot declare a script variable in a function: %s"), name); - else - semsg(_("E1054: Variable already declared in the script: %s"), + else + semsg(_("E1054: Variable already declared in the script: %s"), name); - goto theend; - } - dest = dest_script; + goto theend; + } + else if (cctx->ctx_ufunc->uf_script_ctx_version + == SCRIPT_VERSION_VIM9 + && script_namespace + && !script_var && import == NULL) + { + semsg(_(e_unknown_var), name); + goto theend; + } + + dest = dest_script; - // existing script-local variables should have a type - scriptvar_sid = current_sctx.sc_sid; - if (import != NULL) - scriptvar_sid = import->imp_sid; - scriptvar_idx = get_script_item_idx(scriptvar_sid, + // existing script-local variables should have a type + scriptvar_sid = current_sctx.sc_sid; + if (import != NULL) + scriptvar_sid = import->imp_sid; + scriptvar_idx = get_script_item_idx(scriptvar_sid, rawname, TRUE); - if (scriptvar_idx >= 0) - { - scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid); - svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + if (scriptvar_idx >= 0) + { + scriptitem_T *si = SCRIPT_ITEM(scriptvar_sid); + svar_T *sv = + ((svar_T *)si->sn_var_vals.ga_data) + scriptvar_idx; - type = sv->sv_type; + type = sv->sv_type; + } } - } - else if (name[1] == ':' && name[2] != NUL) - { - semsg(_("E1082: Cannot use a namespaced variable: %s"), + else if (name[1] == ':' && name[2] != NUL) + { + semsg(_("E1082: Cannot use a namespaced variable: %s"), name); - goto theend; - } - else if (!is_decl) - { - semsg(_("E1089: unknown variable: %s"), name); - goto theend; + goto theend; + } + else if (!is_decl) + { + semsg(_(e_unknown_var), name); + goto theend; + } } } From a71e2633207557c31432c954194078cb6062d04f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 15:11:03 +0200 Subject: [PATCH 0087/1384] patch 8.2.1374: Vim9: error for assigning empty list to script variable Problem: Vim9: error for assigning empty list to script variable. Solution: Use t_unknown for empty list member. (closes #6595) --- src/testdir/test_vim9_script.vim | 14 ++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 15 +++++++++------ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index f99333c0cbb4fd..c50a0d337a78e8 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -2782,6 +2782,20 @@ def Test_let_type_check() let var: asdf END CheckScriptFailure(lines, 'E1010:') + + lines =<< trim END + vim9script + let s:l: list + s:l = [] + END + CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + let s:d: dict + s:d = {} + END + CheckScriptSuccess(lines) enddef def Test_forward_declaration() diff --git a/src/version.c b/src/version.c index 7b1b8d8c2199ab..abf2af0c723b37 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1374, /**/ 1373, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index dc10b4851b8b5c..e87634b31bab52 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -502,22 +502,25 @@ typval2type(typval_T *tv, garray_T *type_gap) if (tv->v_type == VAR_STRING) return &t_string; - if (tv->v_type == VAR_LIST - && tv->vval.v_list != NULL - && tv->vval.v_list->lv_first != NULL) + if (tv->v_type == VAR_LIST) { + if (tv->vval.v_list == NULL || tv->vval.v_list->lv_first == NULL) + return &t_list_empty; + // Use the type of the first member, it is the most specific. member_type = typval2type(&tv->vval.v_list->lv_first->li_tv, type_gap); return get_list_type(member_type, type_gap); } - if (tv->v_type == VAR_DICT - && tv->vval.v_dict != NULL - && tv->vval.v_dict->dv_hashtab.ht_used > 0) + if (tv->v_type == VAR_DICT) { dict_iterator_T iter; typval_T *value; + if (tv->vval.v_dict == NULL + || tv->vval.v_dict->dv_hashtab.ht_used == 0) + return &t_dict_empty; + // Use the type of the first value, it is the most specific. dict_iterate_start(tv, &iter); dict_iterate_next(&iter, &value); From c5da1fb7ea4126b6c70426cf0add51e720b7cd3f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 15:43:44 +0200 Subject: [PATCH 0088/1384] patch 8.2.1375: Vim9: method name with digit not accepted Problem: Vim9: method name with digit not accepted. Solution: Use eval_isnamec() instead of eval_isnamec1(). (closes #6613) --- src/testdir/test_vim9_expr.vim | 4 ++-- src/version.c | 2 ++ src/vim9compile.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 8be0dea36e78b8..aa705b2168f5b7 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1674,14 +1674,14 @@ def Echo(arg: any): string return arg enddef -def s:EchoArg(arg: any): string +def s:Echo4Arg(arg: any): string return arg enddef def Test_expr7_call() assert_equal('yes', 'yes'->Echo()) assert_equal('yes', 'yes' - ->s:EchoArg()) + ->s:Echo4Arg()) assert_equal(1, !range(5)->empty()) assert_equal([0, 1, 2], --3->range()) diff --git a/src/version.c b/src/version.c index abf2af0c723b37..8bc928206d283f 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1375, /**/ 1374, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index e87634b31bab52..b3cca5842cd20a 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3854,7 +3854,7 @@ compile_subscript( } if (ASCII_ISALPHA(*p) && p[1] == ':') p += 2; - for ( ; eval_isnamec1(*p); ++p) + for ( ; eval_isnamec(*p); ++p) ; if (*p != '(') { From 803af686e23c7bb17273bb0c78ff0bf97e8d23f4 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 16:20:03 +0200 Subject: [PATCH 0089/1384] patch 8.2.1376: Vim9: expression mapping causes error for using :import Problem: Vim9: expression mapping causes error for using :import. Solution: Add EX_LOCK_OK to :import and :export. (closes 3606) --- src/ex_cmds.h | 4 ++-- src/testdir/test_vim9_script.vim | 30 ++++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/ex_cmds.h b/src/ex_cmds.h index 9ae85f0f31780c..c65b956ee45c17 100644 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -572,7 +572,7 @@ EXCMD(CMD_exit, "exit", ex_exit, EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILE1|EX_ARGOPT|EX_DFLALL|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_export, "export", ex_export, - EX_EXTRA|EX_NOTRLCOM, + EX_EXTRA|EX_NOTRLCOM|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_exusage, "exusage", ex_exusage, EX_TRLBAR, @@ -698,7 +698,7 @@ EXCMD(CMD_imenu, "imenu", ex_menu, EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_import, "import", ex_import, - EX_EXTRA|EX_NOTRLCOM, + EX_EXTRA|EX_NOTRLCOM|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_inoremap, "inoremap", ex_map, EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index c50a0d337a78e8..b05cd54ebbe166 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1351,6 +1351,36 @@ def Test_vim9_import_export() delete('Xvim9_script') enddef +func g:Trigger() + source Ximport.vim + return "echo 'yes'\" +endfunc + +def Test_import_export_expr_map() + # check that :import and :export work when buffer is locked + let export_lines =<< trim END + vim9script + export def That(): string + return 'yes' + enddef + END + writefile(export_lines, 'Xexport_that.vim') + + let import_lines =<< trim END + vim9script + import That from './Xexport_that.vim' + assert_equal('yes', That()) + END + writefile(import_lines, 'Ximport.vim') + + nnoremap trigger g:Trigger() + feedkeys('trigger', "xt") + + delete('Xexport.vim') + delete('Ximport.vim') + nunmap trigger +enddef + def Test_vim9script_fails() CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:') CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:') diff --git a/src/version.c b/src/version.c index 8bc928206d283f..53e47bf7f7ef3a 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1376, /**/ 1375, /**/ From b8d732e93e4b70ad992a12f761bc6a1279dd495b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 5 Aug 2020 22:07:26 +0200 Subject: [PATCH 0090/1384] patch 8.2.1377: triggering the ATTENTION prompt causes typeahead mess up Problem: Triggering the ATTENTION prompt causes typeahead to be messed up. Solution: Increment tb_change_cnt. (closes #6541) --- src/getchar.c | 2 ++ src/version.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/getchar.c b/src/getchar.c index e040748d66c1fd..a8778e0c615036 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -447,6 +447,8 @@ flush_buffers(flush_buffers_T flush_typeahead) typebuf.tb_silent = 0; cmd_silent = FALSE; typebuf.tb_no_abbr_cnt = 0; + if (++typebuf.tb_change_cnt == 0) + typebuf.tb_change_cnt = 1; } /* diff --git a/src/version.c b/src/version.c index 53e47bf7f7ef3a..f5eb42bcfad815 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1377, /**/ 1376, /**/ From bbd3e3c357487f7a5bdc704a819f63a7dd0dd66e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Aug 2020 11:23:36 +0200 Subject: [PATCH 0091/1384] patch 8.2.1378: cannot put space between function name and paren Problem: Cannot put space between function name and paren. Solution: Allow this for backwards compatibility. --- src/eval.c | 5 ++++- src/testdir/test_expr.vim | 5 +++++ src/testdir/test_vim9_expr.vim | 4 ++++ src/version.c | 2 ++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/eval.c b/src/eval.c index a7f6086ef66ba8..877b3bc0ffcd8a 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3198,9 +3198,12 @@ eval7( { int flags = evalarg == NULL ? 0 : evalarg->eval_flags; - if (**arg == '(') + if ((in_vim9script() ? **arg : *skipwhite(*arg)) == '(') + { // "name(..." recursive! + *arg = skipwhite(*arg); ret = eval_func(arg, evalarg, s, len, rettv, flags, NULL); + } else if (flags & EVAL_CONSTANT) ret = FAIL; else if (evaluate) diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim index b4eeea653b15d4..cfae760d4910f6 100644 --- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -599,6 +599,11 @@ func Test_expr_eval_error() call assert_fails("let v = -{}", 'E728:') endfunc +func Test_white_in_function_call() + let text = substitute ( 'some text' , 't' , 'T' , 'g' ) + call assert_equal('some TexT', text) +endfunc + " Test for float value comparison func Test_float_compare() CheckFeature float diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index aa705b2168f5b7..746983d14b1c35 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1686,6 +1686,10 @@ def Test_expr7_call() assert_equal([0, 1, 2], --3->range()) call CheckDefFailure(["let x = 'yes'->Echo"], 'E107:') + call CheckScriptFailure([ + "vim9script", + "let x = substitute ('x', 'x', 'x', 'x')" + ], 'E121:') enddef diff --git a/src/version.c b/src/version.c index f5eb42bcfad815..ba24f693f5bf94 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1378, /**/ 1377, /**/ From ae95a3946b012d4e68bcb20b28f691f6d3b9caaf Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Aug 2020 16:38:12 +0200 Subject: [PATCH 0092/1384] patch 8.2.1379: curly braces expression ending in " }" does not work Problem: Curly braces expression ending in " }" does not work. Solution: Skip over white space when checking for "}". (closes #6634) --- src/dict.c | 2 +- src/testdir/test_eval_stuff.vim | 22 ++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/dict.c b/src/dict.c index af1e1e9c8bfbd6..ad482cddd5934f 100644 --- a/src/dict.c +++ b/src/dict.c @@ -817,7 +817,7 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal) { if (eval1(&start, &tv, NULL) == FAIL) // recursive! return FAIL; - if (*start == '}') + if (*skipwhite(start) == '}') return NOTDONE; } diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim index 6d95cc033865bc..bca89f7a77cd73 100644 --- a/src/testdir/test_eval_stuff.vim +++ b/src/testdir/test_eval_stuff.vim @@ -532,4 +532,26 @@ func Test_setreg_basic() call assert_fails('call setreg(1, ["", "", [], ""])', 'E730:') endfunc +func Test_curly_assignment() + let s:svar = 'svar' + let g:gvar = 'gvar' + let lname = 'gvar' + let gname = 'gvar' + let {'s:'.lname} = {'g:'.gname} + call assert_equal('gvar', s:gvar) + let s:gvar = '' + let { 's:'.lname } = { 'g:'.gname } + call assert_equal('gvar', s:gvar) + let s:gvar = '' + let { 's:' . lname } = { 'g:' . gname } + call assert_equal('gvar', s:gvar) + let s:gvar = '' + let { 's:' .. lname } = { 'g:' .. gname } + call assert_equal('gvar', s:gvar) + + unlet s:svar + unlet s:gvar + unlet g:gvar +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index ba24f693f5bf94..2ae04a974aa5fa 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1379, /**/ 1378, /**/ From 3d945cc925dddb99a1ee86ec194b5b95221c72d7 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Aug 2020 21:26:59 +0200 Subject: [PATCH 0093/1384] patch 8.2.1380: Vim9: return type of getreg() is always a string Problem: Vim9: return type of getreg() is always a string. Solution: Use list of strings when there are three arguments. (closes #6633) --- src/evalfunc.c | 11 ++++++++++- src/testdir/test_vim9_func.vim | 6 ++++++ src/version.c | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/evalfunc.c b/src/evalfunc.c index a631fd9c8449ed..a421690e499e4e 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -393,6 +393,15 @@ ret_remove(int argcount UNUSED, type_T **argtypes) return &t_any; } + static type_T * +ret_getreg(int argcount, type_T **argtypes UNUSED) +{ + // Assume that if the third argument is passed it's non-zero + if (argcount == 3) + return &t_list_string; + return &t_string; +} + static type_T *ret_f_function(int argcount, type_T **argtypes); /* @@ -641,7 +650,7 @@ static funcentry_T global_functions[] = {"getpid", 0, 0, 0, ret_number, f_getpid}, {"getpos", 1, 1, FEARG_1, ret_list_number, f_getpos}, {"getqflist", 0, 1, 0, ret_list_or_dict_0, f_getqflist}, - {"getreg", 0, 3, FEARG_1, ret_string, f_getreg}, + {"getreg", 0, 3, FEARG_1, ret_getreg, f_getreg}, {"getreginfo", 0, 1, FEARG_1, ret_dict_any, f_getreginfo}, {"getregtype", 0, 1, FEARG_1, ret_string, f_getregtype}, {"gettabinfo", 0, 1, FEARG_1, ret_list_dict_any, f_gettabinfo}, diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index d0248369ce3247..649ef4806921b9 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1202,6 +1202,12 @@ def Test_filter_return_type() assert_equal(6, res) enddef +def Test_getreg_return_type() + let s1: string = getreg('"') + let s2: string = getreg('"', 1) + let s3: list = getreg('"', 1, 1) +enddef + def Wrong_dict_key_type(items: list): list return filter(items, {_, val -> get({val: 1}, 'x')}) enddef diff --git a/src/version.c b/src/version.c index 2ae04a974aa5fa..3b5fedc9045a0f 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1380, /**/ 1379, /**/ From 56b8dc331dc7f499c8221ed7d1c7795ad5e3bdeb Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Aug 2020 21:47:11 +0200 Subject: [PATCH 0094/1384] patch 8.2.1381: MS-Windows: crash with Python 3.5 when stdin is redirected Problem: MS-Windows: crash with Python 3.5 when stdin is redirected. Solution: Reconnect stdin. (Yasuhiro Matsumoto, Ken Takata, closes #6641) --- src/Make_cyg_ming.mak | 2 ++ src/Make_mvc.mak | 6 +++++- src/if_python3.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/version.c | 2 ++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index dedc98d7905944..1c519d9b5e53e7 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -588,6 +588,8 @@ ifdef PYTHON3 CFLAGS += -DFEAT_PYTHON3 ifeq (yes, $(DYNAMIC_PYTHON3)) CFLAGS += -DDYNAMIC_PYTHON3 -DDYNAMIC_PYTHON3_DLL=\"$(DYNAMIC_PYTHON3_DLL)\" + else +CFLAGS += -DPYTHON3_DLL=\"$(DYNAMIC_PYTHON3_DLL)\" endif endif diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index 3b72001a80983b..d66ff717a595c3 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -1026,6 +1026,9 @@ PYTHON_LIB = $(PYTHON)\libs\python$(PYTHON_VER).lib ! ifndef PYTHON3_VER PYTHON3_VER = 36 ! endif +! ifndef DYNAMIC_PYTHON3_DLL +DYNAMIC_PYTHON3_DLL = python$(PYTHON3_VER).dll +! endif ! message Python3 requested (version $(PYTHON3_VER)) - root dir is "$(PYTHON3)" ! if "$(DYNAMIC_PYTHON3)" == "yes" ! message Python3 DLL will be loaded dynamically @@ -1035,9 +1038,10 @@ PYTHON3_OBJ = $(OUTDIR)\if_python3.obj PYTHON3_INC = /I "$(PYTHON3)\Include" /I "$(PYTHON3)\PC" ! if "$(DYNAMIC_PYTHON3)" == "yes" CFLAGS = $(CFLAGS) -DDYNAMIC_PYTHON3 \ - -DDYNAMIC_PYTHON3_DLL=\"python$(PYTHON3_VER).dll\" + -DDYNAMIC_PYTHON3_DLL=\"$(DYNAMIC_PYTHON3_DLL)\" PYTHON3_LIB = /nodefaultlib:python$(PYTHON3_VER).lib ! else +CFLAGS = $(CFLAGS) -DPYTHON3_DLL=\"$(DYNAMIC_PYTHON3_DLL)\" PYTHON3_LIB = $(PYTHON3)\libs\python$(PYTHON3_VER).lib ! endif !endif diff --git a/src/if_python3.c b/src/if_python3.c index 843fa079f1eee2..214ba29830e72c 100644 --- a/src/if_python3.c +++ b/src/if_python3.c @@ -907,6 +907,47 @@ python3_loaded(void) static wchar_t *py_home_buf = NULL; +#if defined(MSWIN) && (PY_VERSION_HEX >= 0x030500f0) +// Python 3.5 or later will abort inside Py_Initialize() when stdin is +// redirected. Reconnect stdin to CONIN$. +// Note that the python DLL is linked to its own stdio DLL which can be +// differ from Vim's stdio. + static void +reset_stdin(void) +{ + FILE *(*py__acrt_iob_func)(unsigned) = NULL; + FILE *(*pyfreopen)(const char *, const char *, FILE *) = NULL; + HINSTANCE hinst; + +# ifdef DYNAMIC_PYTHON3 + hinst = hinstPy3; +# else + hinst = GetModuleHandle(PYTHON3_DLL); +# endif + if (hinst == NULL) + return; + + // Get "freopen" and "stdin" which are used in the python DLL. + // "stdin" is defined as "__acrt_iob_func(0)" in VC++ 2015 or later. + py__acrt_iob_func = get_dll_import_func(hinst, "__acrt_iob_func"); + if (py__acrt_iob_func) + { + HINSTANCE hpystdiodll = find_imported_module_by_funcname(hinst, + "__acrt_iob_func"); + if (hpystdiodll) + pyfreopen = (void*)GetProcAddress(hpystdiodll, "freopen"); + } + + // Reconnect stdin to CONIN$. + if (pyfreopen) + pyfreopen("CONIN$", "r", py__acrt_iob_func(0)); + else + freopen("CONIN$", "r", stdin); +} +#else +# define reset_stdin() +#endif + static int Python3_Init(void) { @@ -939,6 +980,7 @@ Python3_Init(void) PyImport_AppendInittab("vim", Py3Init_vim); + reset_stdin(); Py_Initialize(); // Initialise threads, and below save the state using diff --git a/src/version.c b/src/version.c index 3b5fedc9045a0f..3d7c5b129bf78b 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1381, /**/ 1380, /**/ From 8e1986e3896cc8c2a05fc6291a39ebb275e1cebf Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 6 Aug 2020 22:11:06 +0200 Subject: [PATCH 0095/1384] patch 8.2.1382: Vim9: using :import in filetype plugin gives an error Problem: Vim9: using :import in filetype plugin gives an error. Solution: Allow commands with the EX_LOCK_OK flag. (closes #6636) --- src/ex_docmd.c | 2 +- src/testdir/test_vim9_script.vim | 30 ++++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 105710b01605b6..96eac7fbe489b0 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -2087,7 +2087,7 @@ do_one_cmd( // Do allow ":checktime" (it is postponed). // Do allow ":edit" (check for an argument later). // Do allow ":file" with no arguments (check for an argument later). - if (!(ea.argt & EX_CMDWIN) + if (!(ea.argt & (EX_CMDWIN | EX_LOCK_OK)) && ea.cmdidx != CMD_checktime && ea.cmdidx != CMD_edit && ea.cmdidx != CMD_file diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index b05cd54ebbe166..e5d5e872d86732 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1381,6 +1381,36 @@ def Test_import_export_expr_map() nunmap trigger enddef +def Test_import_in_filetype() + # check that :import works when the buffer is locked + mkdir('ftplugin', 'p') + let export_lines =<< trim END + vim9script + export let That = 'yes' + END + writefile(export_lines, 'ftplugin/Xexport_that.vim') + + let import_lines =<< trim END + vim9script + import That from './Xexport_that.vim' + assert_equal('yes', That) + g:did_load_mytpe = 1 + END + writefile(import_lines, 'ftplugin/qf.vim') + + let save_rtp = &rtp + &rtp = getcwd() .. ',' .. &rtp + + filetype plugin on + copen + assert_equal(1, g:did_load_mytpe) + + quit! + delete('Xexport.vim') + delete('ftplugin', 'rf') + &rtp = save_rtp +enddef + def Test_vim9script_fails() CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:') CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:') diff --git a/src/version.c b/src/version.c index 3d7c5b129bf78b..5c745df6652e72 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1382, /**/ 1381, /**/ From 9470a4d88acf948af1596101527b3a505f8c14e9 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Aug 2020 16:49:11 +0200 Subject: [PATCH 0096/1384] patch 8.2.1383: test 49 is old style Problem: Test 49 is old style. Solution: Convert test cases to new style. (Yegappan Lakshmanan, closes #6638) --- src/testdir/test49.ok | 9 - src/testdir/test49.vim | 1248 +------------------------------- src/testdir/test_vimscript.vim | 1147 +++++++++++++++++++++++++++++ src/version.c | 2 + 4 files changed, 1187 insertions(+), 1219 deletions(-) diff --git a/src/testdir/test49.ok b/src/testdir/test49.ok index 50696fd64323e1..8ca8a564c3261b 100644 --- a/src/testdir/test49.ok +++ b/src/testdir/test49.ok @@ -1,18 +1,9 @@ Results of test49.vim: -*** Test 52: OK (1247112011) -*** Test 53: OK (131071) -*** Test 54: OK (2047) -*** Test 55: OK (1023) -*** Test 56: OK (511) -*** Test 57: OK (2147450880) -*** Test 58: OK (624945) *** Test 59: OK (2038431743) *** Test 60: OK (311511339) -*** Test 61: OK (374889517) *** Test 62: OK (286331153) *** Test 63: OK (236978127) *** Test 64: OK (1499645335) -*** Test 65: OK (70187) *** Test 66: OK (5464) *** Test 67: OK (212514423) *** Test 68: OK (212514423) diff --git a/src/testdir/test49.vim b/src/testdir/test49.vim index b3215dfa6f6cc3..9ef91dffa44b02 100644 --- a/src/testdir/test49.vim +++ b/src/testdir/test49.vim @@ -607,998 +607,52 @@ com! -nargs=1 -bar ExecAsScript call ExecAsScript() " END_OF_TEST_ENVIRONMENT - do not change or remove this line. -" Tests 1 to 50, 87 were moved to test_vimscript.vim -" Tests 25, 26, 32, 33, 41-48, 51, 69-75 were moved to test_trycatch.vim -let Xtest = 52 - -"------------------------------------------------------------------------------- -" Test 52: Uncaught exceptions {{{1 -" -" When an exception is thrown but not caught, an error message is -" displayed when the script is terminated. In case of an interrupt -" or error exception, the normal interrupt or error message(s) are -" displayed. -"------------------------------------------------------------------------------- - -XpathINIT - -let msgfile = tempname() - function! MESSAGES(...) try exec "edit" g:msgfile catch /^Vim(edit):/ return 0 - endtry - - let english = v:lang == "C" || v:lang =~ '^[Ee]n' - let match = 1 - norm gg - - let num = a:0 / 2 - let cnt = 1 - while cnt <= num - let enr = a:{2*cnt - 1} - let emsg= a:{2*cnt} - let cnt = cnt + 1 - - if enr == "" - Xout "TODO: Add message number for:" emsg - elseif enr == "INT" - let enr = "" - endif - if enr == "" && !english - continue - endif - let pattern = (enr != "") ? enr . ':.*' : '' - if english - let pattern = pattern . emsg - endif - if !search(pattern, "W") - let match = 0 - Xout "No match for:" pattern - endif - norm $ - endwhile - - bwipeout! - return match -endfunction - -if ExtraVim(msgfile) - Xpath 1 " X: 1 - throw "arrgh" -endif - -Xpath 2 " X: 2 -if !MESSAGES('E605', "Exception not caught") - Xpath 4 " X: 0 -endif - -if ExtraVim(msgfile) - try - Xpath 8 " X: 8 - throw "oops" - catch /arrgh/ - Xpath 16 " X: 0 - endtry - Xpath 32 " X: 0 -endif - -Xpath 64 " X: 64 -if !MESSAGES('E605', "Exception not caught") - Xpath 128 " X: 0 -endif - -if ExtraVim(msgfile) - function! T() - throw "brrr" - endfunction - - try - Xpath 256 " X: 256 - throw "arrgh" - catch /.*/ - Xpath 512 " X: 512 - call T() - endtry - Xpath 1024 " X: 0 -endif - -Xpath 2048 " X: 2048 -if !MESSAGES('E605', "Exception not caught") - Xpath 4096 " X: 0 -endif - -if ExtraVim(msgfile) - try - Xpath 8192 " X: 8192 - throw "arrgh" - finally - Xpath 16384 " X: 16384 - throw "brrr" - endtry - Xpath 32768 " X: 0 -endif - -Xpath 65536 " X: 65536 -if !MESSAGES('E605', "Exception not caught") - Xpath 131072 " X: 0 -endif - -if ExtraVim(msgfile) - try - Xpath 262144 " X: 262144 - "INTERRUPT - endtry - Xpath 524288 " X: 0 -endif - -Xpath 1048576 " X: 1048576 -if !MESSAGES('INT', "Interrupted") - Xpath 2097152 " X: 0 -endif - -if ExtraVim(msgfile) - try - Xpath 4194304 " X: 4194304 - let x = novar " error E121; exception: E121 - catch /E15:/ " should not catch - Xpath 8388608 " X: 0 - endtry - Xpath 16777216 " X: 0 -endif - -Xpath 33554432 " X: 33554432 -if !MESSAGES('E121', "Undefined variable") - Xpath 67108864 " X: 0 -endif - -if ExtraVim(msgfile) - try - Xpath 134217728 " X: 134217728 -" unlet novar # " error E108/E488; exception: E488 - catch /E108:/ " should not catch - Xpath 268435456 " X: 0 - endtry - Xpath 536870912 " X: 0 -endif - -Xpath 1073741824 " X: 1073741824 -if !MESSAGES('E108', "No such variable", 'E488', "Trailing characters") - " The Xpath command does not accept 2^31 (negative); add explicitly: - let Xpath = Xpath + 2147483648 " X: 0 -endif - -call delete(msgfile) -unlet msgfile - -Xcheck 1247112011 - -" Leave MESSAGES() for the next tests. - - -"------------------------------------------------------------------------------- -" Test 53: Nesting errors: :endif/:else/:elseif {{{1 -" -" For nesting errors of :if conditionals the correct error messages -" should be given. -" -" This test reuses the function MESSAGES() from the previous test. -" This functions checks the messages in g:msgfile. -"------------------------------------------------------------------------------- - -XpathINIT - -let msgfile = tempname() - -if ExtraVim(msgfile) -" endif -endif -if MESSAGES('E580', ":endif without :if") - Xpath 1 " X: 1 -endif - -if ExtraVim(msgfile) -" while 1 -" endif -" endwhile -endif -if MESSAGES('E580', ":endif without :if") - Xpath 2 " X: 2 -endif - -if ExtraVim(msgfile) -" try -" finally -" endif -" endtry -endif -if MESSAGES('E580', ":endif without :if") - Xpath 4 " X: 4 -endif - -if ExtraVim(msgfile) -" try -" endif -" endtry -endif -if MESSAGES('E580', ":endif without :if") - Xpath 8 " X: 8 -endif - -if ExtraVim(msgfile) -" try -" throw "a" -" catch /a/ -" endif -" endtry -endif -if MESSAGES('E580', ":endif without :if") - Xpath 16 " X: 16 -endif - -if ExtraVim(msgfile) -" else -endif -if MESSAGES('E581', ":else without :if") - Xpath 32 " X: 32 -endif - -if ExtraVim(msgfile) -" while 1 -" else -" endwhile -endif -if MESSAGES('E581', ":else without :if") - Xpath 64 " X: 64 -endif - -if ExtraVim(msgfile) -" try -" finally -" else -" endtry -endif -if MESSAGES('E581', ":else without :if") - Xpath 128 " X: 128 -endif - -if ExtraVim(msgfile) -" try -" else -" endtry -endif -if MESSAGES('E581', ":else without :if") - Xpath 256 " X: 256 -endif - -if ExtraVim(msgfile) -" try -" throw "a" -" catch /a/ -" else -" endtry -endif -if MESSAGES('E581', ":else without :if") - Xpath 512 " X: 512 -endif - -if ExtraVim(msgfile) -" elseif -endif -if MESSAGES('E582', ":elseif without :if") - Xpath 1024 " X: 1024 -endif - -if ExtraVim(msgfile) -" while 1 -" elseif -" endwhile -endif -if MESSAGES('E582', ":elseif without :if") - Xpath 2048 " X: 2048 -endif - -if ExtraVim(msgfile) -" try -" finally -" elseif -" endtry -endif -if MESSAGES('E582', ":elseif without :if") - Xpath 4096 " X: 4096 -endif - -if ExtraVim(msgfile) -" try -" elseif -" endtry -endif -if MESSAGES('E582', ":elseif without :if") - Xpath 8192 " X: 8192 -endif - -if ExtraVim(msgfile) -" try -" throw "a" -" catch /a/ -" elseif -" endtry -endif -if MESSAGES('E582', ":elseif without :if") - Xpath 16384 " X: 16384 -endif - -if ExtraVim(msgfile) -" if 1 -" else -" else -" endif -endif -if MESSAGES('E583', "multiple :else") - Xpath 32768 " X: 32768 -endif - -if ExtraVim(msgfile) -" if 1 -" else -" elseif 1 -" endif -endif -if MESSAGES('E584', ":elseif after :else") - Xpath 65536 " X: 65536 -endif - -call delete(msgfile) -unlet msgfile - -Xcheck 131071 - -" Leave MESSAGES() for the next test. - - -"------------------------------------------------------------------------------- -" Test 54: Nesting errors: :while/:endwhile {{{1 -" -" For nesting errors of :while conditionals the correct error messages -" should be given. -" -" This test reuses the function MESSAGES() from the previous test. -" This functions checks the messages in g:msgfile. -"------------------------------------------------------------------------------- - -XpathINIT - -let msgfile = tempname() - -if ExtraVim(msgfile) -" endwhile -endif -if MESSAGES('E588', ":endwhile without :while") - Xpath 1 " X: 1 -endif - -if ExtraVim(msgfile) -" if 1 -" endwhile -" endif -endif -if MESSAGES('E588', ":endwhile without :while") - Xpath 2 " X: 2 -endif - -if ExtraVim(msgfile) -" while 1 -" if 1 -" endwhile -endif -if MESSAGES('E171', "Missing :endif") - Xpath 4 " X: 4 -endif - -if ExtraVim(msgfile) -" try -" finally -" endwhile -" endtry -endif -if MESSAGES('E588', ":endwhile without :while") - Xpath 8 " X: 8 -endif - -if ExtraVim(msgfile) -" while 1 -" try -" finally -" endwhile -endif -if MESSAGES('E600', "Missing :endtry") - Xpath 16 " X: 16 -endif - -if ExtraVim(msgfile) -" while 1 -" if 1 -" try -" finally -" endwhile -endif -if MESSAGES('E600', "Missing :endtry") - Xpath 32 " X: 32 -endif - -if ExtraVim(msgfile) -" while 1 -" try -" finally -" if 1 -" endwhile -endif -if MESSAGES('E171', "Missing :endif") - Xpath 64 " X: 64 -endif - -if ExtraVim(msgfile) -" try -" endwhile -" endtry -endif -if MESSAGES('E588', ":endwhile without :while") - Xpath 128 " X: 128 -endif - -if ExtraVim(msgfile) -" while 1 -" try -" endwhile -" endtry -" endwhile -endif -if MESSAGES('E588', ":endwhile without :while") - Xpath 256 " X: 256 -endif - -if ExtraVim(msgfile) -" try -" throw "a" -" catch /a/ -" endwhile -" endtry -endif -if MESSAGES('E588', ":endwhile without :while") - Xpath 512 " X: 512 -endif - -if ExtraVim(msgfile) -" while 1 -" try -" throw "a" -" catch /a/ -" endwhile -" endtry -" endwhile -endif -if MESSAGES('E588', ":endwhile without :while") - Xpath 1024 " X: 1024 -endif - - -call delete(msgfile) -unlet msgfile - -Xcheck 2047 - -" Leave MESSAGES() for the next test. - - -"------------------------------------------------------------------------------- -" Test 55: Nesting errors: :continue/:break {{{1 -" -" For nesting errors of :continue and :break commands the correct -" error messages should be given. -" -" This test reuses the function MESSAGES() from the previous test. -" This functions checks the messages in g:msgfile. -"------------------------------------------------------------------------------- - -XpathINIT - -let msgfile = tempname() - -if ExtraVim(msgfile) -" continue -endif -if MESSAGES('E586', ":continue without :while") - Xpath 1 " X: 1 -endif - -if ExtraVim(msgfile) -" if 1 -" continue -" endif -endif -if MESSAGES('E586', ":continue without :while") - Xpath 2 " X: 2 -endif - -if ExtraVim(msgfile) -" try -" finally -" continue -" endtry -endif -if MESSAGES('E586', ":continue without :while") - Xpath 4 " X: 4 -endif - -if ExtraVim(msgfile) -" try -" continue -" endtry -endif -if MESSAGES('E586', ":continue without :while") - Xpath 8 " X: 8 -endif - -if ExtraVim(msgfile) -" try -" throw "a" -" catch /a/ -" continue -" endtry -endif -if MESSAGES('E586', ":continue without :while") - Xpath 16 " X: 16 -endif - -if ExtraVim(msgfile) -" break -endif -if MESSAGES('E587', ":break without :while") - Xpath 32 " X: 32 -endif - -if ExtraVim(msgfile) -" if 1 -" break -" endif -endif -if MESSAGES('E587', ":break without :while") - Xpath 64 " X: 64 -endif - -if ExtraVim(msgfile) -" try -" finally -" break -" endtry -endif -if MESSAGES('E587', ":break without :while") - Xpath 128 " X: 128 -endif - -if ExtraVim(msgfile) -" try -" break -" endtry -endif -if MESSAGES('E587', ":break without :while") - Xpath 256 " X: 256 -endif - -if ExtraVim(msgfile) -" try -" throw "a" -" catch /a/ -" break -" endtry -endif -if MESSAGES('E587', ":break without :while") - Xpath 512 " X: 512 -endif - -call delete(msgfile) -unlet msgfile - -Xcheck 1023 - -" Leave MESSAGES() for the next test. - - -"------------------------------------------------------------------------------- -" Test 56: Nesting errors: :endtry {{{1 -" -" For nesting errors of :try conditionals the correct error messages -" should be given. -" -" This test reuses the function MESSAGES() from the previous test. -" This functions checks the messages in g:msgfile. -"------------------------------------------------------------------------------- - -XpathINIT - -let msgfile = tempname() - -if ExtraVim(msgfile) -" endtry -endif -if MESSAGES('E602', ":endtry without :try") - Xpath 1 " X: 1 -endif - -if ExtraVim(msgfile) -" if 1 -" endtry -" endif -endif -if MESSAGES('E602', ":endtry without :try") - Xpath 2 " X: 2 -endif - -if ExtraVim(msgfile) -" while 1 -" endtry -" endwhile -endif -if MESSAGES('E602', ":endtry without :try") - Xpath 4 " X: 4 -endif - -if ExtraVim(msgfile) -" try -" if 1 -" endtry -endif -if MESSAGES('E171', "Missing :endif") - Xpath 8 " X: 8 -endif - -if ExtraVim(msgfile) -" try -" while 1 -" endtry -endif -if MESSAGES('E170', "Missing :endwhile") - Xpath 16 " X: 16 -endif - -if ExtraVim(msgfile) -" try -" finally -" if 1 -" endtry -endif -if MESSAGES('E171', "Missing :endif") - Xpath 32 " X: 32 -endif - -if ExtraVim(msgfile) -" try -" finally -" while 1 -" endtry -endif -if MESSAGES('E170', "Missing :endwhile") - Xpath 64 " X: 64 -endif - -if ExtraVim(msgfile) -" try -" throw "a" -" catch /a/ -" if 1 -" endtry -endif -if MESSAGES('E171', "Missing :endif") - Xpath 128 " X: 128 -endif - -if ExtraVim(msgfile) -" try -" throw "a" -" catch /a/ -" while 1 -" endtry -endif -if MESSAGES('E170', "Missing :endwhile") - Xpath 256 " X: 256 -endif - -call delete(msgfile) -unlet msgfile - -delfunction MESSAGES - -Xcheck 511 - - -"------------------------------------------------------------------------------- -" Test 57: v:exception and v:throwpoint for user exceptions {{{1 -" -" v:exception evaluates to the value of the exception that was caught -" most recently and is not finished. (A caught exception is finished -" when the next ":catch", ":finally", or ":endtry" is reached.) -" v:throwpoint evaluates to the script/function name and line number -" where that exception has been thrown. -"------------------------------------------------------------------------------- - -XpathINIT - -function! FuncException() - let g:exception = v:exception -endfunction - -function! FuncThrowpoint() - let g:throwpoint = v:throwpoint -endfunction - -let scriptException = MakeScript("FuncException") -let scriptThrowPoint = MakeScript("FuncThrowpoint") - -command! CmdException let g:exception = v:exception -command! CmdThrowpoint let g:throwpoint = v:throwpoint - -XloopINIT! 1 2 - -function! CHECK(n, exception, throwname, throwline) - XloopNEXT - let error = 0 - if v:exception != a:exception - Xout a:n.": v:exception is" v:exception "instead of" a:exception - let error = 1 - endif - if v:throwpoint !~ a:throwname - let name = escape(a:throwname, '\') - Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" name - let error = 1 - endif - if v:throwpoint !~ a:throwline - let line = escape(a:throwline, '\') - Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line - let error = 1 - endif - if error - Xloop 1 " X: 0 - endif -endfunction - -function! T(arg, line) - if a:line == 2 - throw a:arg " in line 2 - elseif a:line == 4 - throw a:arg " in line 4 - elseif a:line == 6 - throw a:arg " in line 6 - elseif a:line == 8 - throw a:arg " in line 8 - endif -endfunction - -function! G(arg, line) - call T(a:arg, a:line) -endfunction - -function! F(arg, line) - call G(a:arg, a:line) -endfunction - -let scriptT = MakeScript("T") -let scriptG = MakeScript("G", scriptT) -let scriptF = MakeScript("F", scriptG) - -try - Xpath 32768 " X: 32768 - call F("oops", 2) -catch /.*/ - Xpath 65536 " X: 65536 - let exception = v:exception - let throwpoint = v:throwpoint - call CHECK(1, "oops", '\', '\<2\>') - exec "let exception = v:exception" - exec "let throwpoint = v:throwpoint" - call CHECK(2, "oops", '\', '\<2\>') - CmdException - CmdThrowpoint - call CHECK(3, "oops", '\', '\<2\>') - call FuncException() - call FuncThrowpoint() - call CHECK(4, "oops", '\', '\<2\>') - exec "source" scriptException - exec "source" scriptThrowPoint - call CHECK(5, "oops", '\', '\<2\>') - try - Xpath 131072 " X: 131072 - call G("arrgh", 4) - catch /.*/ - Xpath 262144 " X: 262144 - let exception = v:exception - let throwpoint = v:throwpoint - call CHECK(6, "arrgh", '\', '\<4\>') - try - Xpath 524288 " X: 524288 - let g:arg = "autsch" - let g:line = 6 - exec "source" scriptF - catch /.*/ - Xpath 1048576 " X: 1048576 - let exception = v:exception - let throwpoint = v:throwpoint - " Symbolic links in tempname()s are not resolved, whereas resolving - " is done for v:throwpoint. Resolve the temporary file name for - " scriptT, so that it can be matched against v:throwpoint. - call CHECK(7, "autsch", resolve(scriptT), '\<6\>') - finally - Xpath 2097152 " X: 2097152 - let exception = v:exception - let throwpoint = v:throwpoint - call CHECK(8, "arrgh", '\', '\<4\>') - try - Xpath 4194304 " X: 4194304 - let g:arg = "brrrr" - let g:line = 8 - exec "source" scriptG - catch /.*/ - Xpath 8388608 " X: 8388608 - let exception = v:exception - let throwpoint = v:throwpoint - " Resolve scriptT for matching it against v:throwpoint. - call CHECK(9, "brrrr", resolve(scriptT), '\<8\>') - finally - Xpath 16777216 " X: 16777216 - let exception = v:exception - let throwpoint = v:throwpoint - call CHECK(10, "arrgh", '\', '\<4\>') - endtry - Xpath 33554432 " X: 33554432 - let exception = v:exception - let throwpoint = v:throwpoint - call CHECK(11, "arrgh", '\', '\<4\>') - endtry - Xpath 67108864 " X: 67108864 - let exception = v:exception - let throwpoint = v:throwpoint - call CHECK(12, "arrgh", '\', '\<4\>') - finally - Xpath 134217728 " X: 134217728 - let exception = v:exception - let throwpoint = v:throwpoint - call CHECK(13, "oops", '\', '\<2\>') - endtry - Xpath 268435456 " X: 268435456 - let exception = v:exception - let throwpoint = v:throwpoint - call CHECK(14, "oops", '\', '\<2\>') -finally - Xpath 536870912 " X: 536870912 - let exception = v:exception - let throwpoint = v:throwpoint - call CHECK(15, "", '^$', '^$') -endtry - -Xpath 1073741824 " X: 1073741824 - -unlet exception throwpoint -delfunction FuncException -delfunction FuncThrowpoint -call delete(scriptException) -call delete(scriptThrowPoint) -unlet scriptException scriptThrowPoint -delcommand CmdException -delcommand CmdThrowpoint -delfunction T -delfunction G -delfunction F -call delete(scriptT) -call delete(scriptG) -call delete(scriptF) -unlet scriptT scriptG scriptF - -Xcheck 2147450880 - - -"------------------------------------------------------------------------------- -" -" Test 58: v:exception and v:throwpoint for error/interrupt exceptions {{{1 -" -" v:exception and v:throwpoint work also for error and interrupt -" exceptions. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - function! T(line) - if a:line == 2 - delfunction T " error (function in use) in line 2 - elseif a:line == 4 - let dummy = 0 " INTERRUPT1 - interrupt in line 4 - endif - endfunction + endtry - while 1 - try - Xpath 1 " X: 1 - let caught = 0 - call T(2) - catch /.*/ - let caught = 1 - if v:exception !~ 'Vim(delfunction):' - Xpath 2 " X: 0 - endif - if v:throwpoint !~ '\' - Xpath 4 " X: 0 - endif - if v:throwpoint !~ '\<2\>' - Xpath 8 " X: 0 - endif - finally - Xpath 16 " X: 16 - if caught || $VIMNOERRTHROW - Xpath 32 " X: 32 - endif - if v:exception != "" - Xpath 64 " X: 0 - endif - if v:throwpoint != "" - Xpath 128 " X: 0 - endif - break " discard error for $VIMNOERRTHROW - endtry - endwhile + let english = v:lang == "C" || v:lang =~ '^[Ee]n' + let match = 1 + norm gg - Xpath 256 " X: 256 - if v:exception != "" - Xpath 512 " X: 0 - endif - if v:throwpoint != "" - Xpath 1024 " X: 0 - endif + let num = a:0 / 2 + let cnt = 1 + while cnt <= num + let enr = a:{2*cnt - 1} + let emsg= a:{2*cnt} + let cnt = cnt + 1 - while 1 - try - Xpath 2048 " X: 2048 - let caught = 0 - call T(4) - catch /.*/ - let caught = 1 - if v:exception != 'Vim:Interrupt' - Xpath 4096 " X: 0 - endif - if v:throwpoint !~ '\' - Xpath 8192 " X: 0 - endif - if v:throwpoint !~ '\<4\>' - Xpath 16384 " X: 0 - endif - finally - Xpath 32768 " X: 32768 - if caught || $VIMNOINTTHROW - Xpath 65536 " X: 65536 - endif - if v:exception != "" - Xpath 131072 " X: 0 - endif - if v:throwpoint != "" - Xpath 262144 " X: 0 - endif - break " discard error for $VIMNOERRTHROW - endtry + if enr == "" + Xout "TODO: Add message number for:" emsg + elseif enr == "INT" + let enr = "" + endif + if enr == "" && !english + continue + endif + let pattern = (enr != "") ? enr . ':.*' : '' + if english + let pattern = pattern . emsg + endif + if !search(pattern, "W") + let match = 0 + Xout "No match for:" pattern + endif + norm $ endwhile - Xpath 524288 " X: 524288 - if v:exception != "" - Xpath 1048576 " X: 0 - endif - if v:throwpoint != "" - Xpath 2097152 " X: 0 - endif - -endif + bwipeout! + return match +endfunction -Xcheck 624945 +" Leave MESSAGES() for the next tests. +" Tests 1 to 50, 52 to 57, 87 were moved to test_vimscript.vim +" Tests 25, 26, 32, 33, 41-48, 51, 69-75 were moved to test_trycatch.vim +let Xtest = 59 "------------------------------------------------------------------------------- " @@ -2067,142 +1121,8 @@ endif Xcheck 311511339 - -"------------------------------------------------------------------------------- -" Test 61: Catching interrupt exceptions {{{1 -" -" When an interrupt occurs inside a :try/:endtry region, an -" interrupt exception is thrown and can be caught. Its value is -" "Vim:Interrupt". If the interrupt occurs after an error or a :throw -" but before a matching :catch is reached, all following :catches of -" that try block are ignored, but the interrupt exception can be -" caught by the next surrounding try conditional. An interrupt is -" ignored when there is a previous interrupt that has not been caught -" or causes a :finally clause to be executed. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - while 1 - try - try - Xpath 1 " X: 1 - let caught = 0 - "INTERRUPT - Xpath 2 " X: 0 - catch /^Vim:Interrupt$/ - let caught = 1 - finally - Xpath 4 " X: 4 - if caught || $VIMNOINTTHROW - Xpath 8 " X: 8 - endif - endtry - catch /.*/ - Xpath 16 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard interrupt for $VIMNOINTTHROW - endtry - endwhile - - while 1 - try - try - let caught = 0 - try - Xpath 32 " X: 32 - asdf - Xpath 64 " X: 0 - catch /do_not_catch/ - Xpath 128 " X: 0 - catch /.*/ "INTERRUPT - throw interrupt if !$VIMNOERRTHROW - Xpath 256 " X: 0 - catch /.*/ - Xpath 512 " X: 0 - finally "INTERRUPT - throw interrupt if $VIMNOERRTHROW - Xpath 1024 " X: 1024 - endtry - catch /^Vim:Interrupt$/ - let caught = 1 - finally - Xpath 2048 " X: 2048 - if caught || $VIMNOINTTHROW - Xpath 4096 " X: 4096 - endif - endtry - catch /.*/ - Xpath 8192 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard interrupt for $VIMNOINTTHROW - endtry - endwhile - - while 1 - try - try - let caught = 0 - try - Xpath 16384 " X: 16384 - throw "x" - Xpath 32768 " X: 0 - catch /do_not_catch/ - Xpath 65536 " X: 0 - catch /x/ "INTERRUPT - Xpath 131072 " X: 0 - catch /.*/ - Xpath 262144 " X: 0 - endtry - catch /^Vim:Interrupt$/ - let caught = 1 - finally - Xpath 524288 " X: 524288 - if caught || $VIMNOINTTHROW - Xpath 1048576 " X: 1048576 - endif - endtry - catch /.*/ - Xpath 2097152 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard interrupt for $VIMNOINTTHROW - endtry - endwhile - - while 1 - try - let caught = 0 - try - Xpath 4194304 " X: 4194304 - "INTERRUPT - Xpath 8388608 " X: 0 - catch /do_not_catch/ "INTERRUPT - Xpath 16777216 " X: 0 - catch /^Vim:Interrupt$/ - let caught = 1 - finally - Xpath 33554432 " X: 33554432 - if caught || $VIMNOINTTHROW - Xpath 67108864 " X: 67108864 - endif - endtry - catch /.*/ - Xpath 134217728 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard interrupt for $VIMNOINTTHROW - endtry - endwhile - - Xpath 268435456 " X: 268435456 - -endif - -Xcheck 374889517 - +" Test 61 was moved to test_vimscript.vim +let Xtest = 62 "------------------------------------------------------------------------------- " Test 62: Catching error exceptions {{{1 @@ -2725,100 +1645,8 @@ endif Xcheck 1499645335 - -"------------------------------------------------------------------------------- -" Test 65: Errors in the /pattern/ argument of a :catch {{{1 -" -" On an error in the /pattern/ argument of a :catch, the :catch does -" not match. Any following :catches of the same :try/:endtry don't -" match either. Finally clauses are executed. -"------------------------------------------------------------------------------- - -XpathINIT - -function! MSG(enr, emsg) - let english = v:lang == "C" || v:lang =~ '^[Ee]n' - if a:enr == "" - Xout "TODO: Add message number for:" a:emsg - let v:errmsg = ":" . v:errmsg - endif - let match = 1 - if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) - let match = 0 - if v:errmsg == "" - Xout "Message missing." - else - let v:errmsg = escape(v:errmsg, '"') - Xout "Unexpected message:" v:errmsg - endif - endif - return match -endfunction - -try - try - Xpath 1 " X: 1 - throw "oops" - catch /^oops$/ - Xpath 2 " X: 2 - catch /\)/ " not checked; exception has already been caught - Xpath 4 " X: 0 - endtry - Xpath 8 " X: 8 -catch /.*/ - Xpath 16 " X: 0 - Xout v:exception "in" v:throwpoint -endtry - -function! F() - try - let caught = 0 - try - try - Xpath 32 " X: 32 - throw "ab" - catch /abc/ " does not catch - Xpath 64 " X: 0 - catch /\)/ " error; discards exception - Xpath 128 " X: 0 - catch /.*/ " not checked - Xpath 256 " X: 0 - finally - Xpath 512 " X: 512 - endtry - Xpath 1024 " X: 0 - catch /^ab$/ " checked, but original exception is discarded - Xpath 2048 " X: 0 - catch /^Vim(catch):/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(catch):', '', "") - finally - Xpath 4096 " X: 4096 - if !caught && !$VIMNOERRTHROW - Xpath 8192 " X: 0 - endif - if !MSG('E475', "Invalid argument") - Xpath 16384 " X: 0 - endif - if !caught - return | " discard error - endif - endtry - catch /.*/ - Xpath 32768 " X: 0 - Xout v:exception "in" v:throwpoint - endtry -endfunction - -call F() -Xpath 65536 " X: 65536 - -delfunction MSG -delfunction F -unlet! caught - -Xcheck 70187 - +" Test 65 was moved to test_vimscript.vim +let Xtest = 66 "------------------------------------------------------------------------------- " Test 66: Stop range :call on error, interrupt, or :throw {{{1 diff --git a/src/testdir/test_vimscript.vim b/src/testdir/test_vimscript.vim index b752bc8ddbd7e3..02cf2d1c484302 100644 --- a/src/testdir/test_vimscript.vim +++ b/src/testdir/test_vimscript.vim @@ -2763,6 +2763,1153 @@ func Test_throw_across_script() unlet g:scriptC g:scriptT1 scriptT2 endfunc +"------------------------------------------------------------------------------- +" Test 52: Uncaught exceptions {{{1 +" +" When an exception is thrown but not caught, an error message is +" displayed when the script is terminated. In case of an interrupt +" or error exception, the normal interrupt or error message(s) are +" displayed. +"------------------------------------------------------------------------------- + +func Test_uncaught_exception_1() + CheckEnglish + + let test =<< trim [CODE] + Xpath 'a' + throw "arrgh" + call assert_report('should not get here')` + [CODE] + let verify =<< trim [CODE] + call assert_equal('E605: Exception not caught: arrgh', v:errmsg) + call assert_equal('a', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_uncaught_exception_2() + CheckEnglish + + let test =<< trim [CODE] + try + Xpath 'a' + throw "oops" + call assert_report('should not get here')` + catch /arrgh/ + call assert_report('should not get here')` + endtry + call assert_report('should not get here')` + [CODE] + let verify =<< trim [CODE] + call assert_equal('E605: Exception not caught: oops', v:errmsg) + call assert_equal('a', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_uncaught_exception_3() + CheckEnglish + + let test =<< trim [CODE] + func T() + Xpath 'c' + throw "brrr" + call assert_report('should not get here')` + endfunc + + try + Xpath 'a' + throw "arrgh" + call assert_report('should not get here')` + catch /.*/ + Xpath 'b' + call T() + call assert_report('should not get here')` + endtry + call assert_report('should not get here')` + [CODE] + let verify =<< trim [CODE] + call assert_equal('E605: Exception not caught: brrr', v:errmsg) + call assert_equal('abc', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_uncaught_exception_4() + CheckEnglish + + let test =<< trim [CODE] + try + Xpath 'a' + throw "arrgh" + call assert_report('should not get here')` + finally + Xpath 'b' + throw "brrr" + call assert_report('should not get here')` + endtry + call assert_report('should not get here')` + [CODE] + let verify =<< trim [CODE] + call assert_equal('E605: Exception not caught: brrr', v:errmsg) + call assert_equal('ab', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_uncaught_exception_5() + CheckEnglish + + " Need to catch and handle interrupt, otherwise the test will wait for the + " user to press to continue + let test =<< trim [CODE] + try + try + Xpath 'a' + call interrupt() + call assert_report('should not get here') + endtry + call assert_report('should not get here') + catch /^Vim:Interrupt$/ + Xpath 'b' + endtry + [CODE] + let verify =<< trim [CODE] + call assert_equal('ab', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_uncaught_exception_6() + CheckEnglish + + let test =<< trim [CODE] + try + Xpath 'a' + let x = novar " error E121; exception: E121 + catch /E15:/ " should not catch + call assert_report('should not get here') + endtry + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('a', g:Xpath) + call assert_equal('E121: Undefined variable: novar', v:errmsg) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_uncaught_exception_7() + CheckEnglish + + let test =<< trim [CODE] + try + Xpath 'a' + " error E108/E488; exception: E488 + unlet novar # + catch /E108:/ " should not catch + call assert_report('should not get here') + endtry + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('a', g:Xpath) + call assert_equal('E488: Trailing characters: #', v:errmsg) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 53: Nesting errors: :endif/:else/:elseif {{{1 +" +" For nesting errors of :if conditionals the correct error messages +" should be given. +"------------------------------------------------------------------------------- + +func Test_nested_if_else_errors() + CheckEnglish + + " :endif without :if + let code =<< trim END + endif + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if') + + " :endif without :if + let code =<< trim END + while 1 + endif + endwhile + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if') + + " :endif without :if + let code =<< trim END + try + finally + endif + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if') + + " :endif without :if + let code =<< trim END + try + endif + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if') + + " :endif without :if + let code =<< trim END + try + throw "a" + catch /a/ + endif + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if') + + " :else without :if + let code =<< trim END + else + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if') + + " :else without :if + let code =<< trim END + while 1 + else + endwhile + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if') + + " :else without :if + let code =<< trim END + try + finally + else + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if') + + " :else without :if + let code =<< trim END + try + else + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if') + + " :else without :if + let code =<< trim END + try + throw "a" + catch /a/ + else + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if') + + " :elseif without :if + let code =<< trim END + elseif + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if') + + " :elseif without :if + let code =<< trim END + while 1 + elseif + endwhile + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if') + + " :elseif without :if + let code =<< trim END + try + finally + elseif + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if') + + " :elseif without :if + let code =<< trim END + try + elseif + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if') + + " :elseif without :if + let code =<< trim END + try + throw "a" + catch /a/ + elseif + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if') + + " multiple :else + let code =<< trim END + if 1 + else + else + endif + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(else):E583: multiple :else') + + " :elseif after :else + let code =<< trim END + if 1 + else + elseif 1 + endif + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(elseif):E584: :elseif after :else') + + call delete('Xtest') +endfunc + +"------------------------------------------------------------------------------- +" Test 54: Nesting errors: :while/:endwhile {{{1 +" +" For nesting errors of :while conditionals the correct error messages +" should be given. +" +" This test reuses the function MESSAGES() from the previous test. +" This functions checks the messages in g:msgfile. +"------------------------------------------------------------------------------- + +func Test_nested_while_error() + CheckEnglish + + " :endwhile without :while + let code =<< trim END + endwhile + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') + + " :endwhile without :while + let code =<< trim END + if 1 + endwhile + endif + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') + + " Missing :endif + let code =<< trim END + while 1 + if 1 + endwhile + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif') + + " :endwhile without :while + let code =<< trim END + try + finally + endwhile + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') + + " Missing :endtry + let code =<< trim END + while 1 + try + finally + endwhile + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry') + + " Missing :endtry + let code =<< trim END + while 1 + if 1 + try + finally + endwhile + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry') + + " Missing :endif + let code =<< trim END + while 1 + try + finally + if 1 + endwhile + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif') + + " :endwhile without :while + let code =<< trim END + try + endwhile + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') + + " :endwhile without :while + let code =<< trim END + while 1 + try + endwhile + endtry + endwhile + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') + + " :endwhile without :while + let code =<< trim END + try + throw "a" + catch /a/ + endwhile + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') + + " :endwhile without :while + let code =<< trim END + while 1 + try + throw "a" + catch /a/ + endwhile + endtry + endwhile + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while') + + call delete('Xtest') +endfunc + +"------------------------------------------------------------------------------- +" Test 55: Nesting errors: :continue/:break {{{1 +" +" For nesting errors of :continue and :break commands the correct +" error messages should be given. +" +" This test reuses the function MESSAGES() from the previous test. +" This functions checks the messages in g:msgfile. +"------------------------------------------------------------------------------- + +func Test_nested_cont_break_error() + CheckEnglish + + " :continue without :while + let code =<< trim END + continue + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for') + + " :continue without :while + let code =<< trim END + if 1 + continue + endif + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for') + + " :continue without :while + let code =<< trim END + try + finally + continue + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for') + + " :continue without :while + let code =<< trim END + try + continue + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for') + + " :continue without :while + let code =<< trim END + try + throw "a" + catch /a/ + continue + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for') + + " :break without :while + let code =<< trim END + break + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for') + + " :break without :while + let code =<< trim END + if 1 + break + endif + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for') + + " :break without :while + let code =<< trim END + try + finally + break + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for') + + " :break without :while + let code =<< trim END + try + break + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for') + + " :break without :while + let code =<< trim END + try + throw "a" + catch /a/ + break + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for') + + call delete('Xtest') +endfunc + +"------------------------------------------------------------------------------- +" Test 56: Nesting errors: :endtry {{{1 +" +" For nesting errors of :try conditionals the correct error messages +" should be given. +" +" This test reuses the function MESSAGES() from the previous test. +" This functions checks the messages in g:msgfile. +"------------------------------------------------------------------------------- + +func Test_nested_endtry_error() + CheckEnglish + + " :endtry without :try + let code =<< trim END + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try') + + " :endtry without :try + let code =<< trim END + if 1 + endtry + endif + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try') + + " :endtry without :try + let code =<< trim END + while 1 + endtry + endwhile + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try') + + " Missing :endif + let code =<< trim END + try + if 1 + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif') + + " Missing :endwhile + let code =<< trim END + try + while 1 + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile') + + " Missing :endif + let code =<< trim END + try + finally + if 1 + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif') + + " Missing :endwhile + let code =<< trim END + try + finally + while 1 + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile') + + " Missing :endif + let code =<< trim END + try + throw "a" + catch /a/ + if 1 + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif') + + " Missing :endwhile + let code =<< trim END + try + throw "a" + catch /a/ + while 1 + endtry + END + call writefile(code, 'Xtest') + call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile') + + call delete('Xtest') +endfunc + +"------------------------------------------------------------------------------- +" Test 57: v:exception and v:throwpoint for user exceptions {{{1 +" +" v:exception evaluates to the value of the exception that was caught +" most recently and is not finished. (A caught exception is finished +" when the next ":catch", ":finally", or ":endtry" is reached.) +" v:throwpoint evaluates to the script/function name and line number +" where that exception has been thrown. +"------------------------------------------------------------------------------- + +func Test_user_exception_info() + CheckEnglish + + XpathINIT + XloopINIT + + func FuncException() + let g:exception = v:exception + endfunc + + func FuncThrowpoint() + let g:throwpoint = v:throwpoint + endfunc + + let scriptException = MakeScript("FuncException") + let scriptThrowPoint = MakeScript("FuncThrowpoint") + + command! CmdException let g:exception = v:exception + command! CmdThrowpoint let g:throwpoint = v:throwpoint + + func T(arg, line) + if a:line == 2 + throw a:arg " in line 2 + elseif a:line == 4 + throw a:arg " in line 4 + elseif a:line == 6 + throw a:arg " in line 6 + elseif a:line == 8 + throw a:arg " in line 8 + endif + endfunc + + func G(arg, line) + call T(a:arg, a:line) + endfunc + + func F(arg, line) + call G(a:arg, a:line) + endfunc + + let scriptT = MakeScript("T") + let scriptG = MakeScript("G", scriptT) + let scriptF = MakeScript("F", scriptG) + + try + Xpath 'a' + call F("oops", 2) + catch /.*/ + Xpath 'b' + let exception = v:exception + let throwpoint = v:throwpoint + call assert_equal("oops", v:exception) + call assert_match('\', v:throwpoint) + call assert_match('\<2\>', v:throwpoint) + + exec "let exception = v:exception" + exec "let throwpoint = v:throwpoint" + call assert_equal("oops", v:exception) + call assert_match('\', v:throwpoint) + call assert_match('\<2\>', v:throwpoint) + + CmdException + CmdThrowpoint + call assert_equal("oops", v:exception) + call assert_match('\', v:throwpoint) + call assert_match('\<2\>', v:throwpoint) + + call FuncException() + call FuncThrowpoint() + call assert_equal("oops", v:exception) + call assert_match('\', v:throwpoint) + call assert_match('\<2\>', v:throwpoint) + + exec "source" scriptException + exec "source" scriptThrowPoint + call assert_equal("oops", v:exception) + call assert_match('\', v:throwpoint) + call assert_match('\<2\>', v:throwpoint) + + try + Xpath 'c' + call G("arrgh", 4) + catch /.*/ + Xpath 'd' + let exception = v:exception + let throwpoint = v:throwpoint + call assert_equal("arrgh", v:exception) + call assert_match('\', v:throwpoint) + call assert_match('\<4\>', v:throwpoint) + + try + Xpath 'e' + let g:arg = "autsch" + let g:line = 6 + exec "source" scriptF + catch /.*/ + Xpath 'f' + let exception = v:exception + let throwpoint = v:throwpoint + call assert_equal("autsch", v:exception) + call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint) + call assert_match('\<6\>', v:throwpoint) + finally + Xpath 'g' + let exception = v:exception + let throwpoint = v:throwpoint + call assert_equal("arrgh", v:exception) + call assert_match('\', v:throwpoint) + call assert_match('\<4\>', v:throwpoint) + try + Xpath 'h' + let g:arg = "brrrr" + let g:line = 8 + exec "source" scriptG + catch /.*/ + Xpath 'i' + let exception = v:exception + let throwpoint = v:throwpoint + " Resolve scriptT for matching it against v:throwpoint. + call assert_equal("brrrr", v:exception) + call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint) + call assert_match('\<8\>', v:throwpoint) + finally + Xpath 'j' + let exception = v:exception + let throwpoint = v:throwpoint + call assert_equal("arrgh", v:exception) + call assert_match('\', v:throwpoint) + call assert_match('\<4\>', v:throwpoint) + endtry + Xpath 'k' + let exception = v:exception + let throwpoint = v:throwpoint + call assert_equal("arrgh", v:exception) + call assert_match('\', v:throwpoint) + call assert_match('\<4\>', v:throwpoint) + endtry + Xpath 'l' + let exception = v:exception + let throwpoint = v:throwpoint + call assert_equal("arrgh", v:exception) + call assert_match('\', v:throwpoint) + call assert_match('\<4\>', v:throwpoint) + finally + Xpath 'm' + let exception = v:exception + let throwpoint = v:throwpoint + call assert_equal("oops", v:exception) + call assert_match('\', v:throwpoint) + call assert_match('\<2\>', v:throwpoint) + endtry + Xpath 'n' + let exception = v:exception + let throwpoint = v:throwpoint + call assert_equal("oops", v:exception) + call assert_match('\', v:throwpoint) + call assert_match('\<2\>', v:throwpoint) + finally + Xpath 'o' + let exception = v:exception + let throwpoint = v:throwpoint + call assert_equal("", v:exception) + call assert_match('^$', v:throwpoint) + call assert_match('^$', v:throwpoint) + endtry + + call assert_equal('abcdefghijklmno', g:Xpath) + + unlet exception throwpoint + delfunction FuncException + delfunction FuncThrowpoint + call delete(scriptException) + call delete(scriptThrowPoint) + unlet scriptException scriptThrowPoint + delcommand CmdException + delcommand CmdThrowpoint + delfunction T + delfunction G + delfunction F + call delete(scriptT) + call delete(scriptG) + call delete(scriptF) + unlet scriptT scriptG scriptF +endfunc + +"------------------------------------------------------------------------------- +" +" Test 58: v:exception and v:throwpoint for error/interrupt exceptions {{{1 +" +" v:exception and v:throwpoint work also for error and interrupt +" exceptions. +"------------------------------------------------------------------------------- + +func Test_execption_info_for_error() + CheckEnglish + + let test =<< trim [CODE] + func T(line) + if a:line == 2 + delfunction T " error (function in use) in line 2 + elseif a:line == 4 + call interrupt() + endif + endfunc + + while 1 + try + Xpath 'a' + call T(2) + call assert_report('should not get here') + catch /.*/ + Xpath 'b' + if v:exception !~ 'Vim(delfunction):' + call assert_report('should not get here') + endif + if v:throwpoint !~ '\' + call assert_report('should not get here') + endif + if v:throwpoint !~ '\<2\>' + call assert_report('should not get here') + endif + finally + Xpath 'c' + if v:exception != "" + call assert_report('should not get here') + endif + if v:throwpoint != "" + call assert_report('should not get here') + endif + break + endtry + endwhile + + Xpath 'd' + if v:exception != "" + call assert_report('should not get here') + endif + if v:throwpoint != "" + call assert_report('should not get here') + endif + + while 1 + try + Xpath 'e' + call T(4) + call assert_report('should not get here') + catch /.*/ + Xpath 'f' + if v:exception != 'Vim:Interrupt' + call assert_report('should not get here') + endif + if v:throwpoint !~ 'function T' + call assert_report('should not get here') + endif + if v:throwpoint !~ '\<4\>' + call assert_report('should not get here') + endif + finally + Xpath 'g' + if v:exception != "" + call assert_report('should not get here') + endif + if v:throwpoint != "" + call assert_report('should not get here') + endif + break + endtry + endwhile + + Xpath 'h' + if v:exception != "" + call assert_report('should not get here') + endif + if v:throwpoint != "" + call assert_report('should not get here') + endif + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcdefgh', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 61: Catching interrupt exceptions {{{1 +" +" When an interrupt occurs inside a :try/:endtry region, an +" interrupt exception is thrown and can be caught. Its value is +" "Vim:Interrupt". If the interrupt occurs after an error or a :throw +" but before a matching :catch is reached, all following :catches of +" that try block are ignored, but the interrupt exception can be +" caught by the next surrounding try conditional. An interrupt is +" ignored when there is a previous interrupt that has not been caught +" or causes a :finally clause to be executed. +"------------------------------------------------------------------------------- + +func Test_catch_intr_exception() + let test =<< trim [CODE] + while 1 + try + try + Xpath 'a' + call interrupt() + call assert_report('should not get here') + catch /^Vim:Interrupt$/ + Xpath 'b' + finally + Xpath 'c' + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'd' + break + endtry + endwhile + + while 1 + try + try + try + Xpath 'e' + asdf + call assert_report('should not get here') + catch /do_not_catch/ + call assert_report('should not get here') + catch /.*/ + Xpath 'f' + call interrupt() + call assert_report('should not get here') + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'g' + call interrupt() + call assert_report('should not get here') + endtry + catch /^Vim:Interrupt$/ + Xpath 'h' + finally + Xpath 'i' + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'j' + break + endtry + endwhile + + while 1 + try + try + try + Xpath 'k' + throw "x" + call assert_report('should not get here') + catch /do_not_catch/ + call assert_report('should not get here') + catch /x/ + Xpath 'l' + call interrupt() + call assert_report('should not get here') + catch /.*/ + call assert_report('should not get here') + endtry + catch /^Vim:Interrupt$/ + Xpath 'm' + finally + Xpath 'n' + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'o' + break + endtry + endwhile + + while 1 + try + try + Xpath 'p' + call interrupt() + call assert_report('should not get here') + catch /do_not_catch/ + call interrupt() + call assert_report('should not get here') + catch /^Vim:Interrupt$/ + Xpath 'q' + finally + Xpath 'r' + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 's' + break + endtry + endwhile + + Xpath 't' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcdefghijklmnopqrst', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 65: Errors in the /pattern/ argument of a :catch {{{1 +" +" On an error in the /pattern/ argument of a :catch, the :catch does +" not match. Any following :catches of the same :try/:endtry don't +" match either. Finally clauses are executed. +"------------------------------------------------------------------------------- + +func Test_catch_pattern_error() + CheckEnglish + XpathINIT + + try + try + Xpath 'a' + throw "oops" + catch /^oops$/ + Xpath 'b' + catch /\)/ " not checked; exception has already been caught + call assert_report('should not get here') + endtry + Xpath 'c' + catch /.*/ + call assert_report('should not get here') + endtry + call assert_equal('abc', g:Xpath) + + XpathINIT + func F() + try + try + try + Xpath 'a' + throw "ab" + catch /abc/ " does not catch + call assert_report('should not get here') + catch /\)/ " error; discards exception + call assert_report('should not get here') + catch /.*/ " not checked + call assert_report('should not get here') + finally + Xpath 'b' + endtry + call assert_report('should not get here') + catch /^ab$/ " checked, but original exception is discarded + call assert_report('should not get here') + catch /^Vim(catch):/ + Xpath 'c' + call assert_match('Vim(catch):E475: Invalid argument:', v:exception) + finally + Xpath 'd' + endtry + Xpath 'e' + catch /.*/ + call assert_report('should not get here') + endtry + Xpath 'f' + endfunc + + call F() + call assert_equal('abcdef', g:Xpath) + + delfunc F +endfunc + "------------------------------------------------------------------------------- " Test 87 using (expr) ? funcref : funcref {{{1 " diff --git a/src/version.c b/src/version.c index 5c745df6652e72..e6b8a893f1c7c2 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1383, /**/ 1382, /**/ From 8ce4b7ed85a7c6499bea5eb1312c85ee7a00e364 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Aug 2020 18:12:18 +0200 Subject: [PATCH 0097/1384] patch 8.2.1384: no ATTENTION prompt for :vimgrep first match file Problem: No ATTENTION prompt for :vimgrep first match file. Solution: When there is an existing swap file do not keep the dummy buffer. (closes #6649) --- src/quickfix.c | 20 +++++++++++++++++++- src/testdir/runtest.vim | 3 +++ src/testdir/test_quickfix.vim | 20 ++++++++++++++++++++ src/version.c | 2 ++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/quickfix.c b/src/quickfix.c index 1901e3806df8f8..99b0169ea5c39a 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -6015,6 +6015,23 @@ vgr_process_args( return OK; } +/* + * Return TRUE if "buf" had an existing swap file, the current swap file does + * not end in ".swp". + */ + static int +existing_swapfile(buf_T *buf) +{ + if (buf->b_ml.ml_mfp != NULL) + { + char_u *fname = buf->b_ml.ml_mfp->mf_fname; + size_t len = STRLEN(fname); + + return fname[len - 1] != 'p' || fname[len - 2] != 'w'; + } + return FALSE; +} + /* * Search for a pattern in a list of files and populate the quickfix list with * the matches. @@ -6125,7 +6142,8 @@ vgr_process_files( buf = NULL; } else if (buf != *first_match_buf - || (cmd_args->flags & VGR_NOJUMP)) + || (cmd_args->flags & VGR_NOJUMP) + || existing_swapfile(buf)) { unload_dummy_buffer(buf, dirname_start); // Keeping the buffer, remove the dummy flag. diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim index f3609f8514582f..f431748e1e8dac 100644 --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -91,6 +91,9 @@ set encoding=utf-8 let s:test_script_fname = expand('%') au! SwapExists * call HandleSwapExists() func HandleSwapExists() + if exists('g:ignoreSwapExists') + return + endif " Ignore finding a swap file for the test script (the user might be " editing it and do ":make test_name") and the output file. " Report finding another swap file and chose 'q' to avoid getting stuck. diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index 8ca55785d1e257..e71a3dfdec2317 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -2837,6 +2837,26 @@ func Test_vimgrep_with_no_last_search_pat() call delete('Xresult') endfunc +func Test_vimgrep_existing_swapfile() + call writefile(['match apple with apple'], 'Xapple') + call writefile(['swapfile'], '.Xapple.swp') + let g:foundSwap = 0 + let g:ignoreSwapExists = 1 + augroup grep + au SwapExists * let foundSwap = 1 | let v:swapchoice = 'e' + augroup END + vimgrep apple Xapple + call assert_equal(1, g:foundSwap) + call assert_match('.Xapple.swo', swapname('')) + + call delete('Xapple') + call delete('Xapple.swp') + augroup grep + au! SwapExists + augroup END + unlet g:ignoreSwapExists +endfunc + func XfreeTests(cchar) call s:setup_commands(a:cchar) diff --git a/src/version.c b/src/version.c index e6b8a893f1c7c2..98e408014bc49e 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1384, /**/ 1383, /**/ From de6804d871def4d8973ef3ca3eece4155a5c3ab1 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Aug 2020 18:33:19 +0200 Subject: [PATCH 0098/1384] patch 8.2.1385: no testing on ARM Problem: No testing on ARM. Solution: Add a test on Travis for ARM. (Ozaki Kiichi, closes #6615) --- .travis.yml | 48 +++++++++++++++++++++++++++++++++--------------- src/version.c | 2 ++ 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0f9aeafcd23834..d199efb5735f41 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,29 @@ language: c +env: + global: + - BUILD=yes TEST=test CONFOPT= LEAK_CFLAGS="-DEXITFREE" SHADOWOPT= SRCDIR=./src CHECK_AUTOCONF=no + _anchors: envs: - &tiny-nogui - BUILD=yes TEST=test FEATURES=tiny CONFOPT="--disable-gui" LEAK_CFLAGS="-DEXITFREE" SHADOWOPT= SRCDIR=./src CHECK_AUTOCONF=no + FEATURES=tiny CONFOPT="--disable-gui" - &tiny - BUILD=yes TEST=test FEATURES=tiny CONFOPT= LEAK_CFLAGS="-DEXITFREE" SHADOWOPT= SRCDIR=./src CHECK_AUTOCONF=no + FEATURES=tiny - &small - BUILD=yes TEST=test FEATURES=small CONFOPT= LEAK_CFLAGS="-DEXITFREE" SHADOWOPT= SRCDIR=./src CHECK_AUTOCONF=no + FEATURES=small - &normal - BUILD=yes TEST=test FEATURES=normal CONFOPT= LEAK_CFLAGS="-DEXITFREE" SHADOWOPT= SRCDIR=./src CHECK_AUTOCONF=no + FEATURES=normal - &linux-huge - BUILD=yes TEST="scripttests test_libvterm" CFLAGS="--coverage -DUSE_GCOV_FLUSH" LDFLAGS=--coverage FEATURES=huge LEAK_CFLAGS="-DEXITFREE" SHADOWOPT= SRCDIR=./src CHECK_AUTOCONF=no + FEATURES=huge TEST="scripttests test_libvterm" CONFOPT="--enable-perlinterp --enable-pythoninterp --enable-python3interp --enable-rubyinterp --enable-luainterp --enable-tclinterp" - &osx-huge # macOS build - BUILD=yes TEST=test FEATURES=huge LEAK_CFLAGS="-DEXITFREE" SHADOWOPT= SRCDIR=./src CHECK_AUTOCONF=no - CONFOPT="--enable-perlinterp --enable-pythoninterp --enable-rubyinterp --enable-luainterp --enable-tclinterp" + FEATURES=huge + CONFOPT="--enable-perlinterp --enable-python3interp --enable-rubyinterp --enable-luainterp --enable-tclinterp" - &unittests - BUILD=no TEST=unittests CFLAGS="--coverage -DUSE_GCOV_FLUSH" LDFLAGS=--coverage FEATURES=huge LEAK_CFLAGS="-DEXITFREE" SHADOWOPT= SRCDIR=./src CHECK_AUTOCONF=yes + BUILD=no TEST=unittests FEATURES=huge CHECK_AUTOCONF=yes + - &coverage + CFLAGS="--coverage -DUSE_GCOV_FLUSH" LDFLAGS=--coverage - &asan # ASAN build SANITIZER_CFLAGS="-g -O1 -DABORT_ON_INTERNAL_ERROR -DEXITFREE -fsanitize=address -fno-omit-frame-pointer" ASAN_OPTIONS="print_stacktrace=1 log_path=asan" LSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/src/testdir/lsan-suppress.txt" @@ -87,7 +93,7 @@ _anchors: # Lua is not installed on macOS - export LUA_PREFIX=/usr/local - coverage: &coverage + coverage: &eval-coverage # needed for https support for coveralls building cffi only works with gcc, # not with clang - CC=gcc pip install --user cpp-coveralls pyopenssl ndg-httpsclient pyasn1 @@ -208,19 +214,28 @@ jobs: compiler: gcc env: *linux-huge services: [] + - <<: *linux + arch: arm64 + name: huge/gcc-arm64 + compiler: gcc + env: *linux-huge + services: [] - <<: *linux name: huge+coverage/clang compiler: clang env: - *linux-huge + - *coverage # Clang cannot compile test_libvterm with "--coverage" flag. - TEST=scripttests - after_success: *coverage + after_success: *eval-coverage - <<: *linux name: huge+coverage/gcc compiler: gcc - env: *linux-huge - after_success: *coverage + env: + - *linux-huge + - *coverage + after_success: *eval-coverage - <<: *linux # ASAN name: huge+asan/gcc compiler: gcc @@ -233,13 +248,16 @@ jobs: compiler: gcc env: - *linux-huge + - *coverage - TEST="-C src testgui" - after_success: *coverage + after_success: *eval-coverage - <<: *linux name: unittests+coverage/gcc compiler: gcc - env: *unittests - after_success: *coverage + env: + - *unittests + - *coverage + after_success: *eval-coverage - <<: *linux name: vimtags/gcc compiler: gcc diff --git a/src/version.c b/src/version.c index 98e408014bc49e..ea89d2df8c3118 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1385, /**/ 1384, /**/ From 994b89d28dc54c896e00eba66e247addb0540272 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Aug 2020 19:12:41 +0200 Subject: [PATCH 0099/1384] patch 8.2.1386: backslash not removed afer space with space in 'isfname' Problem: Backslash not removed afer space in option with space in 'isfname'. Solution: Do remove backslash before space, also when it is in 'isfname'. (Yasuhiro Matsumoto, closes #6651) --- src/option.c | 7 ++++--- src/testdir/test_options.vim | 9 +++++++++ src/version.c | 2 ++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/option.c b/src/option.c index f66fad9473b33a..648f22db32d48e 100644 --- a/src/option.c +++ b/src/option.c @@ -1311,12 +1311,12 @@ do_set( { if (flags & (P_SECURE | P_NO_ML)) { - errmsg = _("E520: Not allowed in a modeline"); + errmsg = N_("E520: Not allowed in a modeline"); goto skip; } if ((flags & P_MLE) && !p_mle) { - errmsg = _("E992: Not allowed in a modeline when 'modelineexpr' is off"); + errmsg = N_("E992: Not allowed in a modeline when 'modelineexpr' is off"); goto skip; } #ifdef FEAT_DIFF @@ -1338,7 +1338,7 @@ do_set( // Disallow changing some options in the sandbox if (sandbox != 0 && (flags & P_SECURE)) { - errmsg = _(e_sandbox); + errmsg = e_sandbox; goto skip; } #endif @@ -1763,6 +1763,7 @@ do_set( #ifdef BACKSLASH_IN_FILENAME && !((flags & P_EXPAND) && vim_isfilec(arg[1]) + && !VIM_ISWHITE(arg[1]) && (arg[1] != '\\' || (s == newval && arg[2] != '\\'))) diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index 8f27d9c4acdae9..b3e9da78f71a2e 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -973,4 +973,13 @@ func Test_opt_winminwidth() set winwidth& endfunc +" Test for setting option value containing spaces with isfname+=32 +func Test_isfname_with_options() + set isfname+=32 + setlocal keywordprg=:term\ help.exe + call assert_equal(':term help.exe', &keywordprg) + set isfname& + setlocal keywordprg& +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index ea89d2df8c3118..e251ba865b1dde 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1386, /**/ 1385, /**/ From 95dd9f2571f09a915674133c73b471b0ebbdcdbf Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Aug 2020 19:28:08 +0200 Subject: [PATCH 0100/1384] patch 8.2.1387: Vim9: cannot assign to single letter variable with type Problem: Vim9: cannot assign to single letter variable with type. Solution: Exclude the colon from the variable name. (closes #6647) --- src/eval.c | 21 +++++++++++++++------ src/testdir/test_vim9_script.vim | 11 +++++++++++ src/version.c | 2 ++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/eval.c b/src/eval.c index 877b3bc0ffcd8a..c695468cdfc77f 100644 --- a/src/eval.c +++ b/src/eval.c @@ -820,14 +820,23 @@ get_lval( { lp->ll_name = name; - if (in_vim9script() && *p == ':') + if (in_vim9script()) { - scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); - char_u *tp = skipwhite(p + 1); + // "a: type" is declaring variable "a" with a type, not "a:". + if (p == name + 2 && p[-1] == ':') + { + --p; + lp->ll_name_end = p; + } + if (*p == ':') + { + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); + char_u *tp = skipwhite(p + 1); - // parse the type after the name - lp->ll_type = parse_type(&tp, &si->sn_type_list); - lp->ll_name_end = tp; + // parse the type after the name + lp->ll_type = parse_type(&tp, &si->sn_type_list); + lp->ll_name_end = tp; + } } } diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index e5d5e872d86732..ba18af09e3450d 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -449,6 +449,17 @@ def Test_assignment_vim9script() @+ = 'plus' assert_equal('plus', @+) endif + + let a: number = 123 + assert_equal(123, a) + let s: string = 'yes' + assert_equal('yes', s) + let b: number = 42 + assert_equal(42, b) + let w: number = 43 + assert_equal(43, w) + let t: number = 44 + assert_equal(44, t) END CheckScriptSuccess(lines) enddef diff --git a/src/version.c b/src/version.c index e251ba865b1dde..11b686255b8ae2 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1387, /**/ 1386, /**/ From e7b1ea0276cc83cd5c612f3189a174a60d57b5ed Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Aug 2020 19:54:59 +0200 Subject: [PATCH 0101/1384] Update runtime files. --- README_VIM9.md | 15 ++-- runtime/autoload/javascriptcomplete.vim | 44 ++++++--- runtime/doc/autocmd.txt | 6 +- runtime/doc/develop.txt | 6 +- runtime/doc/eval.txt | 34 +++---- runtime/doc/gui_w32.txt | 2 +- runtime/doc/helphelp.txt | 20 +++-- runtime/doc/if_lua.txt | 4 +- runtime/doc/if_tcl.txt | 4 +- runtime/doc/indent.txt | 28 +++--- runtime/doc/map.txt | 2 +- runtime/doc/options.txt | 18 ++-- runtime/doc/os_vms.txt | 2 +- runtime/doc/popup.txt | 8 +- runtime/doc/remote.txt | 2 +- runtime/doc/syntax.txt | 16 ++-- runtime/doc/tags | 1 + runtime/doc/todo.txt | 27 +++--- runtime/doc/usr_04.txt | 2 +- runtime/doc/usr_05.txt | 4 +- runtime/doc/usr_20.txt | 8 +- runtime/doc/usr_30.txt | 2 +- runtime/doc/usr_31.txt | 6 +- runtime/doc/usr_40.txt | 8 +- runtime/doc/usr_41.txt | 4 +- runtime/doc/usr_42.txt | 4 +- runtime/doc/usr_46.txt | 2 +- runtime/doc/usr_toc.txt | 2 +- runtime/doc/vim9.txt | 39 ++++---- runtime/doc/visual.txt | 8 +- runtime/filetype.vim | 2 +- runtime/ftplugin/vim.vim | 2 +- runtime/keymap/turkish-f.vim | 114 ++++++++++++++++++++++++ runtime/keymap/turkish-q.vim | 62 +++++++++++++ runtime/syntax/css.vim | 9 +- runtime/syntax/fstab.vim | 6 +- runtime/syntax/help.vim | 2 +- runtime/syntax/pamconf.vim | 37 +++++--- 38 files changed, 400 insertions(+), 162 deletions(-) create mode 100644 runtime/keymap/turkish-f.vim create mode 100644 runtime/keymap/turkish-q.vim diff --git a/README_VIM9.md b/README_VIM9.md index b77d013c05c122..9f540791cc859d 100644 --- a/README_VIM9.md +++ b/README_VIM9.md @@ -5,8 +5,8 @@ This is an experimental side of [Vim](https://github.com/vim/vim). It explores ways of making Vim script faster and better. -WARNING: The Vim9 script features are in the early stages of development, -anything can break! +WARNING: The Vim9 script features are still under development, anything can +break! # Why Vim9? @@ -52,7 +52,7 @@ we can gain, and also that Vim script can be faster than builtin interfaces. In practice the script would not do something useless as counting but change -the text. For example, re-indent all the lines: +the text. For example, reindent all the lines: ``` vim let totallen = 0 @@ -91,9 +91,9 @@ Instead of using script language support in Vim: with them. The job and channel support already makes this possible. Really any language can be used, also Java and Go, which are not available built-in. -* Phase out the built-in language interfaces, make maintenance a bit easier - and executables easier to build. They will be kept for backwards - compatibility, no new features. +* No priority for the built-in language interfaces. They will have to be kept + for backwards compatibility, but many users won't need a Vim build with these + interfaces. * Improve the Vim script language, it is used to communicate with the external tool and implements the Vim side of the interface. Also, it can be used when an external tool is undesired. @@ -140,6 +140,9 @@ Taking this one step further is also dropping "s:" for script-local variables; everything at the script level is script-local by default. Since this is not backwards compatible it requires a new script style: Vim9 script! +To avoid having more variations, the syntax inside a compiled function is the +same as in Vim9 script. Thus you have legacy syntax and Vim9 syntax. + It should be possible to convert code from other languages to Vim script. We can add functionality to make this easier. This still needs to be discussed, but we can consider adding type checking and a simple diff --git a/runtime/autoload/javascriptcomplete.vim b/runtime/autoload/javascriptcomplete.vim index 14bc3d7ce397ad..29b6b16254fa3f 100644 --- a/runtime/autoload/javascriptcomplete.vim +++ b/runtime/autoload/javascriptcomplete.vim @@ -1,7 +1,9 @@ " Vim completion script " Language: Java Script -" Maintainer: Mikolaj Machowski ( mikmach AT wp DOT pl ) -" Last Change: 2017 Mar 04 +" Maintainer: Jay Sitter (jay@jaysitter.com) +" URL: https://github.com/jsit/javascriptcomplete.vim/ +" Previous Maintainer: Mikolaj Machowski ( mikmach AT wp DOT pl ) +" Last Change: 2020 Jul 30 function! javascriptcomplete#CompleteJS(findstart, base) if a:findstart @@ -154,12 +156,30 @@ function! javascriptcomplete#CompleteJS(findstart, base) \ 'text', 'vLink'] let bodys = bodyprop " Document - document. - let docuprop = ['anchors', 'applets', 'childNodes', 'embeds', 'forms', 'images', 'links', 'stylesheets', - \ 'body', 'cookie', 'documentElement', 'domain', 'lastModified', 'referrer', 'title', 'URL'] - let documeth = ['close', 'createAttribute', 'createElement', 'createTextNode', 'focus', 'getElementById', - \ 'getElementsByName', 'getElementsByTagName', 'open', 'write', 'writeln', - \ 'onClick', 'onDblClick', 'onFocus', 'onKeyDown', 'onKeyPress', 'onKeyUp', - \ 'onMouseDown', 'onMouseMove', 'onMouseOut', 'onMouseOver', 'onMouseUp', 'onResize'] + let docuprop = ['anchors', 'body', 'characterSet', 'doctype', + \ 'documentElement', 'documentURI', 'embeds', 'fonts', 'forms', + \ 'head', 'hidden', 'images', 'implementation', 'lastStyleSheetSet', + \ 'links', 'plugins', 'preferredStyleSheetSet', 'scripts', + \ 'scrollingElement', 'selectedStyleSheetSet', 'styleSheetSets', + \ 'timeline', 'visibilityState', 'cookie', 'defaultView', + \ 'designMode', 'dir', 'domain', 'lastModified', 'location', + \ 'readyState', 'referrer', 'title', 'URL', 'activeElement', + \ 'fullscreenElement', 'styleSheets'] + let documeth = ['adoptNode', 'close', 'createAttribute', + \ 'createAttributeNS', 'createCDATASection', 'createComment', + \ 'createDocumentFragment', 'createElement', 'createElementNS', + \ 'createEvent', 'createExpression', 'createNSResolver', + \ 'createNodeIterator', 'createProcessingInstruction', 'createRange', + \ 'createTextNode', 'createTouchList', 'createTreeWalker', + \ 'enableStyleSheetsForSet', 'evaluate', 'focus', 'getElementById', + \ 'getElementById', 'getElementsByClassName', 'getElementsByName', + \ 'getElementsByTagName', 'getElementsByTagNameNS', + \ 'hasStorageAccess', 'importNode', 'onClick', 'onDblClick', + \ 'onFocus', 'onKeyDown', 'onKeyPress', 'onKeyUp', 'onMouseDown', + \ 'onMouseMove', 'onMouseOut', 'onMouseOver', 'onMouseUp', + \ 'onResize', 'open', 'querySelector', 'querySelectorAll', + \ 'requestStorageAccess', 'write', 'writeln'] + call map(documeth, 'v:val."("') let docuxprop = ['attributes', 'childNodes', 'doctype', 'documentElement', 'firstChild', \ 'implementation', 'namespaceURI', 'nextSibling', 'nodeName', 'nodeType', @@ -368,9 +388,11 @@ function! javascriptcomplete#CompleteJS(findstart, base) let xdomelemprop = ['attributes', 'childNodes', 'firstChild', 'lastChild', \ 'namespaceURI', 'nextSibling', 'nodeName', 'nodeType', 'nodeValue', \ 'ownerDocument', 'parentNode', 'prefix', 'previousSibling', 'tagName'] - let xdomelemmeth = ['appendChild', 'cloneNode', 'getAttribute', 'getAttributeNode', - \ 'getElementsByTagName', 'hasChildNodes', 'insertBefore', 'normalize', - \ 'removeAttribute', 'removeAttributeNode', 'removeChild', 'replaceChild', + let xdomelemmeth = ['appendChild', 'addEventListener', 'cloneNode', + \ 'dispatchEvent', 'getAttribute', 'getAttributeNode', + \ 'getElementsByTagName', 'hasChildNodes', 'insertBefore', + \ 'normalize', 'removeAttribute', 'removeAttributeNode', + \ 'removeChild', 'removeEventListener', 'replaceChild', \ 'setAttribute', 'setAttributeNode'] call map(xdomelemmeth, 'v:val."("') let xdomelems = xdomelemprop + xdomelemmeth diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index b0d791927fad90..d56f211d0d50bb 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -1,4 +1,4 @@ -*autocmd.txt* For Vim version 8.2. Last change: 2020 Jun 10 +*autocmd.txt* For Vim version 8.2. Last change: 2020 Aug 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1425,8 +1425,8 @@ name! :aug[roup]! {name} Delete the autocmd group {name}. Don't use this if there is still an autocommand using this group! You will get a warning if doing - it anyway. when the group is the current group - you will get error E936. + it anyway. When the group is the current + group you will get error E936. To enter autocommands for a specific group, use this method: 1. Select the group with ":augroup {name}". diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt index 7ed251a6f65d12..f139ebe5e61e7f 100644 --- a/runtime/doc/develop.txt +++ b/runtime/doc/develop.txt @@ -1,4 +1,4 @@ -*develop.txt* For Vim version 8.2. Last change: 2020 Apr 13 +*develop.txt* For Vim version 8.2. Last change: 2020 Jul 27 VIM REFERENCE MANUAL by Bram Moolenaar @@ -34,8 +34,8 @@ balance must be found between them. VIM IS... VI COMPATIBLE *design-compatible* First of all, it should be possible to use Vim as a drop-in replacement for -Vi. When the user wants to, he can use Vim in compatible mode and hardly -notice any difference with the original Vi. +Vi. When the user wants to, Vim can be used in compatible mode and hardly +any differences with the original Vi will be noticed. Exceptions: - We don't reproduce obvious Vi bugs in Vim. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 8c6f7ded6ba1cb..5bb763a4a474aa 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 Aug 01 +*eval.txt* For Vim version 8.2. Last change: 2020 Aug 07 VIM REFERENCE MANUAL by Bram Moolenaar @@ -4895,31 +4895,32 @@ getbufinfo([{dict}]) Each returned List item is a dictionary with the following entries: - bufnr buffer number. + bufnr Buffer number. changed TRUE if the buffer is modified. - changedtick number of changes made to the buffer. + changedtick Number of changes made to the buffer. hidden TRUE if the buffer is hidden. - lastused timestamp in seconds, like + lastused Timestamp in seconds, like |localtime()|, when the buffer was last used. {only with the |+viminfo| feature} listed TRUE if the buffer is listed. - lnum current line number in buffer. - linecount number of lines in the buffer (only + lnum Line number used for the buffer when + opened in the current window. + linecount Number of lines in the buffer (only valid when loaded) loaded TRUE if the buffer is loaded. - name full path to the file in the buffer. - signs list of signs placed in the buffer. + name Full path to the file in the buffer. + signs List of signs placed in the buffer. Each list item is a dictionary with the following fields: id sign identifier lnum line number name sign name - variables a reference to the dictionary with + variables A reference to the dictionary with buffer-local variables. - windows list of |window-ID|s that display this + windows List of |window-ID|s that display this buffer - popups list of popup |window-ID|s that + popups List of popup |window-ID|s that display this buffer Examples: > @@ -5446,7 +5447,7 @@ getloclist({nr} [, {what}]) *getloclist()* :echo getloclist(5, {'filewinid': 0}) -getmarklist([{expr}] *getmarklist()* +getmarklist([{expr}]) *getmarklist()* Without the {expr} argument returns a |List| with information about all the global marks. |mark| @@ -8709,7 +8710,8 @@ searchcount([{options}]) *searchcount()* pos |List| `[lnum, col, off]` value when recomputing the result. this changes "current" result - value. see |cursor()|, |getpos() + value. see |cursor()|, + |getpos()| (default: cursor's position) @@ -9111,7 +9113,7 @@ setqflist({list} [, {action} [, {what}]]) *setqflist()* argument is ignored. See below for the supported items in {what}. *setqflist-what* - When {what} is not present, the items in {list} or used. Each + When {what} is not present, the items in {list} are used. Each item must be a dictionary. Non-dictionary items in {list} are ignored. Each dictionary item can contain the following entries: @@ -9332,7 +9334,7 @@ settagstack({nr}, {dict} [, {action}]) *settagstack()* Returns zero for success, -1 for failure. - Examples (for more examples see |tagstack-examples||): + Examples (for more examples see |tagstack-examples|): Empty the tag stack of window 3: > call settagstack(3, {'items' : []}) @@ -10132,7 +10134,7 @@ swapname({expr}) *swapname()* The result is the swap file path of the buffer {expr}. For the use of {expr}, see |bufname()| above. If buffer {expr} is the current buffer, the result is equal to - |:swapname| (unless no swap file). + |:swapname| (unless there is no swap file). If buffer {expr} has no swap file, returns an empty string. Can also be used as a |method|: > diff --git a/runtime/doc/gui_w32.txt b/runtime/doc/gui_w32.txt index 30e2287826a06e..c0f886773904f9 100644 --- a/runtime/doc/gui_w32.txt +++ b/runtime/doc/gui_w32.txt @@ -451,7 +451,7 @@ with the Intellimouse driver 2.2 and when "Universal Scrolling" is turned on. XPM support *w32-xpm-support* -GVim can be build on MS-Windows with support for XPM files. |+xpm_w32| +GVim can be built on MS-Windows with support for XPM files. |+xpm_w32| See the Make_mvc.mak file for instructions, search for XPM. To try out if XPM support works do this: > diff --git a/runtime/doc/helphelp.txt b/runtime/doc/helphelp.txt index 7771a505ba7b4c..8dcaa1f509591e 100644 --- a/runtime/doc/helphelp.txt +++ b/runtime/doc/helphelp.txt @@ -1,4 +1,4 @@ -*helphelp.txt* For Vim version 8.2. Last change: 2020 Mar 01 +*helphelp.txt* For Vim version 8.2. Last change: 2020 Jul 27 VIM REFERENCE MANUAL by Bram Moolenaar @@ -369,14 +369,16 @@ highlighting. So do these: You can find the details in $VIMRUNTIME/syntax/help.vim *inclusion* -Some people make a big deal about using "his" when referring to the user, -thinking it means we assume the user is male. That is of course not the case, -it's just a habit of writing help text, which quite often is many years old. -Also, a lot of the text is written by contributors for who English is not -their first language. We do not make any assumptions about the gender of the -user, no matter how the text is phrased. And we do not want to waste time on -this discussion. The goal is that the reader understands how Vim works, the -exact wording is secondary. +Vim is for everybody, no matter race, gender or anything. Some people make a +big deal about using "he" or "his" when referring to the user, thinking it +means we assume the user is male. That is not the case, it's just a habit of +writing help text, which quite often is many years old. Also, a lot of the +text is written by contributors for whom English is not their first language. +We do not make any assumptions about the gender of the user, no matter how the +text is phrased. Some people have suggested using "they", but that is not +regular English. We do not want to spend much time on this discussion. The +goal is that the reader understands how Vim works, the exact wording is +secondary. vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/if_lua.txt b/runtime/doc/if_lua.txt index 65a2d60430a392..b5569969859578 100644 --- a/runtime/doc/if_lua.txt +++ b/runtime/doc/if_lua.txt @@ -199,8 +199,8 @@ Vim evaluation and command execution, and others. returns it. Note that the buffer is not set as current. - vim.call({name} [,{args}]) - Proxy to call Vim function named {name} with + vim.call({name} [, {args}]) + Proxy to call Vim function named {name} with arguments {args}. Example: > :lua print(vim.call('has', 'timers')) < diff --git a/runtime/doc/if_tcl.txt b/runtime/doc/if_tcl.txt index 60ac6bcc5e259b..90dec9dba18361 100644 --- a/runtime/doc/if_tcl.txt +++ b/runtime/doc/if_tcl.txt @@ -275,7 +275,7 @@ Options: $win delcmd {cmd} *tcl-window-delcmd* Registers the Tcl command {cmd} as a deletion callback for the window. This command is executed (in the global scope) just before the window - is closed. Complex commands should be build with "list": > + is closed. Complex commands should be built with "list": > $win delcmd [list puts vimerr "window deleted"] < See also |tcl-buffer-delcmd|. @@ -357,7 +357,7 @@ Options: $buf delcmd {cmd} *tcl-buffer-delcmd* Registers the Tcl command {cmd} as a deletion callback for the buffer. This command is executed (in the global scope) just before the buffer - is deleted. Complex commands should be build with "list": > + is deleted. Complex commands should be built with "list": > $buf delcmd [list puts vimerr "buffer [$buf number] gone"] < See also |tcl-window-delcmd|. diff --git a/runtime/doc/indent.txt b/runtime/doc/indent.txt index c4785c4b227204..87d5c0bd5e3cbe 100644 --- a/runtime/doc/indent.txt +++ b/runtime/doc/indent.txt @@ -414,11 +414,11 @@ The examples below assume a 'shiftwidth' of 4. < *cino-(* (N When in unclosed parentheses, indent N characters from the line - with the unclosed parentheses. Add a 'shiftwidth' for every + with the unclosed parenthesis. Add a 'shiftwidth' for every extra unclosed parentheses. When N is 0 or the unclosed - parentheses is the first non-white character in its line, line + parenthesis is the first non-white character in its line, line up with the next non-white character after the unclosed - parentheses. (default 'shiftwidth' * 2). + parenthesis. (default 'shiftwidth' * 2). cino= cino=(0 > if (c1 && (c2 || if (c1 && (c2 || @@ -439,7 +439,7 @@ The examples below assume a 'shiftwidth' of 4. < *cino-U* UN When N is non-zero, do not ignore the indenting specified by - ( or u in case that the unclosed parentheses is the first + ( or u in case that the unclosed parenthesis is the first non-white character in its line. (default 0). cino= or cino=(s cino=(s,U1 > @@ -452,8 +452,8 @@ The examples below assume a 'shiftwidth' of 4. *cino-w* wN When in unclosed parentheses and N is non-zero and either using "(0" or "u0", respectively, or using "U0" and the unclosed - parentheses is the first non-white character in its line, line - up with the character immediately after the unclosed parentheses + parenthesis is the first non-white character in its line, line + up with the character immediately after the unclosed parenthesis rather than the first non-white character. (default 0). cino=(0 cino=(0,w1 > @@ -464,11 +464,11 @@ The examples below assume a 'shiftwidth' of 4. < *cino-W* WN When in unclosed parentheses and N is non-zero and either - using "(0" or "u0", respectively and the unclosed parentheses is + using "(0" or "u0", respectively and the unclosed parenthesis is the last non-white character in its line and it is not the - closing parentheses, indent the following line N characters + closing parenthesis, indent the following line N characters relative to the outer context (i.e. start of the line or the - next unclosed parentheses). (default: 0). + next unclosed parenthesis). (default: 0). cino=(0 cino=(0,W4 > a_long_line( a_long_line( @@ -495,8 +495,8 @@ The examples below assume a 'shiftwidth' of 4. < *cino-m* mN When N is non-zero, line up a line starting with a closing - parentheses with the first character of the line with the - matching opening parentheses. (default 0). + parenthesis with the first character of the line with the + matching opening parenthesis. (default 0). cino=(s cino=(s,m1 > c = c1 && ( c = c1 && ( @@ -510,7 +510,7 @@ The examples below assume a 'shiftwidth' of 4. < *cino-M* MN When N is non-zero, line up a line starting with a closing - parentheses with the first character of the previous line. + parenthesis with the first character of the previous line. (default 0). cino= cino=M1 > @@ -569,7 +569,7 @@ The examples below assume a 'shiftwidth' of 4. recognize preprocessor lines; right-shifting lines that start with "#" does not work. - + *cino-P* PN When N is non-zero recognize C pragmas, and indent them like any other code; does not concern other preprocessor directives. When N is zero (default): don't recognize C pragmas, treating @@ -996,7 +996,7 @@ Indent after a nested paren: > Indent for a continuation line: > let g:pyindent_continue = 'shiftwidth() * 2' -The method uses |searchpair()| to look back for unclosed parenthesis. This +The method uses |searchpair()| to look back for unclosed parentheses. This can sometimes be slow, thus it timeouts after 150 msec. If you notice the indenting isn't correct, you can set a larger timeout in msec: > let g:pyindent_searchpair_timeout = 500 diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 79c46f712534ba..78451a14065860 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1,4 +1,4 @@ -*map.txt* For Vim version 8.2. Last change: 2020 Apr 23 +*map.txt* For Vim version 8.2. Last change: 2020 Aug 01 VIM REFERENCE MANUAL by Bram Moolenaar diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index d98307e30a9956..102eb62abd19e7 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 8.2. Last change: 2020 Jul 18 +*options.txt* For Vim version 8.2. Last change: 2020 Aug 07 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2715,6 +2715,11 @@ A jump table for the options with a short description can be found at |Q_op|. for Unix: ".,~/tmp,/var/tmp,/tmp") global List of directory names for the swap file, separated with commas. + Recommended value: ".,~/vimswap//" - this will put the swap file next + to the edited file if possible, and in your personal swap directory + otherwise. Make sure "~/vimswap//" is only readable for you. + + Possible items: - The swap file will be created in the first directory where this is possible. - Empty means that no swap file will be used (recovery is @@ -2749,9 +2754,10 @@ A jump table for the options with a short description can be found at |Q_op|. the same file twice will result in a warning. Using "/tmp" on Unix is discouraged: When the system crashes you lose the swap file. "/var/tmp" is often not cleared when rebooting, thus is a better - choice than "/tmp". But it can contain a lot of files, your swap - files get lost in the crowd. That is why a "tmp" directory in your - home directory is tried first. + choice than "/tmp". But others on the computer may be able to see the + files, and it can contain a lot of files, your swap files get lost in + the crowd. That is why a "tmp" directory in your home directory is + tried first. The use of |:set+=| and |:set-=| is preferred when adding or removing directories from the list. This avoids problems when a future version uses another default. @@ -8368,7 +8374,7 @@ A jump table for the options with a short description can be found at |Q_op|. >= 14 Anything pending in a ":finally" clause. >= 15 Every executed Ex command from a script (truncated at 200 characters). - >= 16 Every executed Ex command + >= 16 Every executed Ex command. This option can also be set with the "-V" argument. See |-V|. This option is also set by the |:verbose| command. @@ -8907,7 +8913,7 @@ A jump table for the options with a short description can be found at |Q_op|. {only available when compiled with the |terminal| feature on MS-Windows} Specifies the name of the winpty shared library, used for the - |:terminal| command. The default depends on whether was build as a + |:terminal| command. The default depends on whether Vim was built as a 32-bit or 64-bit executable. If not found, "winpty.dll" is tried as a fallback. Environment variables are expanded |:set_env|. diff --git a/runtime/doc/os_vms.txt b/runtime/doc/os_vms.txt index 168232783905af..b69f650b409666 100644 --- a/runtime/doc/os_vms.txt +++ b/runtime/doc/os_vms.txt @@ -88,7 +88,7 @@ VAX C compiler is not fully ANSI C compatible in pre-processor directives semantics, therefore you have to use a converter program that will do the lion part of the job. For detailed instructions read file INSTALLvms.txt -MMS_VIM.EXE is build together with VIM.EXE, but for XXD.EXE you should +MMS_VIM.EXE is built together with VIM.EXE, but for XXD.EXE you should change to a subdirectory and build it separately. CTAGS is not part of the Vim source distribution anymore, however the OpenVMS diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt index ff99fce9ab3796..8a0f2ba5188f17 100644 --- a/runtime/doc/popup.txt +++ b/runtime/doc/popup.txt @@ -1,4 +1,4 @@ -*popup.txt* For Vim version 8.2. Last change: 2020 May 18 +*popup.txt* For Vim version 8.2. Last change: 2020 Jul 27 VIM REFERENCE MANUAL by Bram Moolenaar @@ -74,9 +74,9 @@ wrapping, lines in the buffer. It can be limited with the "maxheight" property. You can use empty lines to increase the height or the "minheight" property. -The width of the window is normally equal to the longest line in the buffer. -It can be limited with the "maxwidth" property. You can use spaces to -increase the width or use the "minwidth" property. +The width of the window is normally equal to the longest visible line in the +buffer. It can be limited with the "maxwidth" property. You can use spaces +to increase the width or use the "minwidth" property. By default the 'wrap' option is set, so that no text disappears. Otherwise, if there is not enough space then the window is shifted left in order to diff --git a/runtime/doc/remote.txt b/runtime/doc/remote.txt index 53c98d0e155309..c6dcb980035249 100644 --- a/runtime/doc/remote.txt +++ b/runtime/doc/remote.txt @@ -179,7 +179,7 @@ name on the 'VimRegistry' property on the root window. A non GUI Vim with access to the X11 display (|xterm-clipboard| enabled), can also act as a command server if a server name is explicitly given with the ---servername argument, or when Vim was build with the |+autoservername| +--servername argument, or when Vim was built with the |+autoservername| feature. An empty --servername argument will cause the command server to be disabled. diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 8effaf55a0b72c..a7f648cdf059b2 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -1,4 +1,4 @@ -*syntax.txt* For Vim version 8.2. Last change: 2020 Jul 08 +*syntax.txt* For Vim version 8.2. Last change: 2020 Jul 28 VIM REFERENCE MANUAL by Bram Moolenaar @@ -3648,7 +3648,7 @@ DEFINING FOLDLEVEL *:syn-foldlevel* start: Use level of item containing start of line. minimum: Use lowest local-minimum level of items on line. - The default is 'start'. Use 'minimum' to search a line horizontally + The default is "start". Use "minimum" to search a line horizontally for the lowest level contained on the line that is followed by a higher level. This produces more natural folds when syntax items may close and open horizontally within a line. @@ -3795,9 +3795,9 @@ DEFINING REGIONS *:syn-region* *:syn-start* *:syn-skip* *:syn-end* [keepend] [extend] [excludenl] - start={start_pattern} .. - [skip={skip_pattern}] - end={end_pattern} .. + start={start-pattern} .. + [skip={skip-pattern}] + end={end-pattern} .. [{options}] This defines one region. It may span several lines. @@ -3819,12 +3819,12 @@ DEFINING REGIONS *:syn-region* *:syn-start* *:syn-skip* *:syn-end* extend a containing match or item. Only useful for end patterns. Must be given before the patterns it applies to. |:syn-excludenl| - start={start_pattern} The search pattern that defines the start of + start={start-pattern} The search pattern that defines the start of the region. See |:syn-pattern| below. - skip={skip_pattern} The search pattern that defines text inside + skip={skip-pattern} The search pattern that defines text inside the region where not to look for the end pattern. See |:syn-pattern| below. - end={end_pattern} The search pattern that defines the end of + end={end-pattern} The search pattern that defines the end of the region. See |:syn-pattern| below. Example: > diff --git a/runtime/doc/tags b/runtime/doc/tags index 243b25ac60709f..02bb541f948004 100644 --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -5744,6 +5744,7 @@ cino-J indent.txt /*cino-J* cino-L indent.txt /*cino-L* cino-M indent.txt /*cino-M* cino-N indent.txt /*cino-N* +cino-P indent.txt /*cino-P* cino-U indent.txt /*cino-U* cino-W indent.txt /*cino-W* cino-^ indent.txt /*cino-^* diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index f9ebf2d58ed82b..0c8d124592263a 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 Jul 26 +*todo.txt* For Vim version 8.2. Last change: 2020 Aug 05 VIM REFERENCE MANUAL by Bram Moolenaar @@ -39,10 +39,9 @@ browser use: https://github.com/vim/vim/issues/1234 -------------------- Known bugs and current work ----------------------- Making everything work: -- more items in https://github.com/vim/vim/issues/6507 -- More "goto failed" with check for trylevel. -- memory leak in test_vim9_script - Check that when sourcing a Vim9 script, only the global items can be used. +- Make string indexes character indexes instead of byte indexes. (#6574) + explain how to use byte index when needed. Use blob? - :put with a "=" register argument doesn't work, need to find the expression and compile it. (#6397) - At the script level, keep script variables local to the block they are @@ -51,6 +50,8 @@ Making everything work: - Implement { } block at the script level. - need to check type when a declaration specifies a type: #6507 let nr: number = 'asdf' +- Make sure that in vim9script a function call without namespace only finds + the script-local function, not a global one. - Make map() give an error if the resulting type is wrong. Add mapnew() to create a new List/Dict for the result, which can have a different value type. @@ -169,7 +170,7 @@ Popup windows: - Figure out the size and position better if wrapping inserts indent Text properties: -- :goto does not go to the right place when test properties are present. +- :goto does not go to the right place when text properties are present. (#5930) - "cc" does not call inserted_bytes(). (Axel Forsman, #5763) - Get E685 with a sequence of commands. (#5674) @@ -200,7 +201,7 @@ Terminal debugger: an already running program. (M. Kelly) - When only gdb window exists, on "quit" edit another buffer. - Use a sign group -- Termdebug does not work when Vim was build with mzscheme: gdb hangs just +- Termdebug does not work when Vim was built with mzscheme: gdb hangs just after "run". Everything else works, including communication channel. Not initializing mzscheme avoid the problem, thus it's not some #ifdef. - Add support for lldb? issue #3565 @@ -255,10 +256,15 @@ Terminal emulator window: Error numbers available: E610, E611, E653 +Clean up empty entries in testdir/Make_all.mak + Remove SPACE_IN_FILENAME ? It is only used for completion. Patch to use collaction based sorting. (Christian Brabandt, #6229) +Add 'termguiattr' option, use "gui=" attributes in the terminal? Would work +with 'termguicolors'. #1740 + Can we detect true color support? https://gist.github.com/XVilka/8346728 Try setting a color then request the current color, like using t_u7. @@ -333,6 +339,9 @@ character. (#6154) undo result wrong: Masato Nishihata, #4798 +After recovering from a swap file the undofile should not be used, it causes +corruption. (#6631) + When 'lazyredraw' is set sometimes the title is not updated. (Jason Franklin, 2020 Feb 3) Looks like a race condition. @@ -1471,7 +1480,7 @@ Zero-out krypt key information when no longer in use. (Ben Fritz, 2017 May 15) Add stronger encryption. Could use libsodium (NaCl). https://github.com/jedisct1/libsodium/ -Possibly include the needed code so that it can be build everywhere. +Possibly include the needed code so that it can be built everywhere. Add a way to restart a timer. It's similar to timer_stop() and timer_start(), but the reference remains valid. @@ -3833,8 +3842,6 @@ Macintosh: 8 When write_viminfo() is used while there are many orphaned viminfo tempfiles writing the viminfo file fails. Give a clear error message so that the user knows he has to delete the files. -7 It's possible to redefine a script-local function with ":func - 123_Test()". (Krishna) Disallow this. I can't reproduce these (if you can, let me know how!): @@ -5673,7 +5680,7 @@ Buffer list: Also for other windows: ":inwin {winnr} {cmd}". How to make sure that this works properly for all commands, and still be able to return to the current buffer/window? E.g.: ":inbuf xxx only". -8 Add File.{recent_files} menu entries: Recently edited files. +8 Add File.{recent-files} menu entries: Recently edited files. Ron Aaron has a plugin for this: mru.vim. 8 Unix: Check all uses of fnamecmp() and fnamencmp() if they should check inode too. diff --git a/runtime/doc/usr_04.txt b/runtime/doc/usr_04.txt index 6a6cbcafad1039..d2dc056096451d 100644 --- a/runtime/doc/usr_04.txt +++ b/runtime/doc/usr_04.txt @@ -161,7 +161,7 @@ line break. ============================================================================== *04.3* Repeating a change -The "." command is one of the most simple yet powerful commands in Vim. It +The "." command is one of the simplest yet powerful commands in Vim. It repeats the last change. For instance, suppose you are editing an HTML file and want to delete all the tags. You position the cursor on the first < and delete the with the command "df>". You then go to the < of the next diff --git a/runtime/doc/usr_05.txt b/runtime/doc/usr_05.txt index 2cfff2449e5d02..3a7438df4cae49 100644 --- a/runtime/doc/usr_05.txt +++ b/runtime/doc/usr_05.txt @@ -58,8 +58,8 @@ This initializes Vim for new users (as opposed to traditional Vi users). See |defaults.vim| for the details. The vimrc file can contain all the commands that you type after a colon. The -most simple ones are for setting options. For example, if you want Vim to -always start with the 'incsearch' option on, add this line your vimrc file: > +simplest ones are for setting options. For example, if you want Vim to always +start with the 'incsearch' option on, add this line your vimrc file: > set incsearch diff --git a/runtime/doc/usr_20.txt b/runtime/doc/usr_20.txt index f99ffb51c88db4..ebad3c517ffa4e 100644 --- a/runtime/doc/usr_20.txt +++ b/runtime/doc/usr_20.txt @@ -327,10 +327,10 @@ for next. ============================================================================== *20.5* Command line window -Typing the text in the command line works different from typing text in Insert -mode. It doesn't allow many commands to change the text. For most commands -that's OK, but sometimes you have to type a complicated command. That's where -the command line window is useful. +Typing the text in the command line works differently from typing text in +Insert mode. It doesn't allow many commands to change the text. For most +commands that's OK, but sometimes you have to type a complicated command. +That's where the command line window is useful. Open the command line window with this command: > diff --git a/runtime/doc/usr_30.txt b/runtime/doc/usr_30.txt index 736323665ed579..bcb7b59e746a02 100644 --- a/runtime/doc/usr_30.txt +++ b/runtime/doc/usr_30.txt @@ -336,7 +336,7 @@ How to do that is explained here: |indent-expression|. ============================================================================== *30.4* Other indenting -The most simple form of automatic indenting is with the 'autoindent' option. +The simplest form of automatic indenting is with the 'autoindent' option. It uses the indent from the previous line. A bit smarter is the 'smartindent' option. This is useful for languages where no indent file is available. 'smartindent' is not as smart as 'cindent', but smarter than 'autoindent'. diff --git a/runtime/doc/usr_31.txt b/runtime/doc/usr_31.txt index 0794b3aa809d25..afbc91877c28d0 100644 --- a/runtime/doc/usr_31.txt +++ b/runtime/doc/usr_31.txt @@ -1,4 +1,4 @@ -*usr_31.txt* For Vim version 8.2. Last change: 2007 May 08 +*usr_31.txt* For Vim version 8.2. Last change: 2020 Jul 28 VIM USER MANUAL - by Bram Moolenaar @@ -198,9 +198,9 @@ is not possible in most terminals. You can start the X-Windows version of gvim with an argument to specify the size and position of the window: > - gvim -geometry {width}x{height}+{x_offset}+{y_offset} + gvim -geometry {width}x{height}+{x-offset}+{y-offset} -{width} and {height} are in characters, {x_offset} and {y_offset} are in +{width} and {height} are in characters, {x-offset} and {y-offset} are in pixels. Example: > gvim -geometry 80x25+100+300 diff --git a/runtime/doc/usr_40.txt b/runtime/doc/usr_40.txt index 85014c27533bfc..3456a76c1c5d34 100644 --- a/runtime/doc/usr_40.txt +++ b/runtime/doc/usr_40.txt @@ -1,4 +1,4 @@ -*usr_40.txt* For Vim version 8.2. Last change: 2013 Aug 05 +*usr_40.txt* For Vim version 8.2. Last change: 2020 Jul 28 VIM USER MANUAL - by Bram Moolenaar @@ -453,12 +453,12 @@ matching BufWritePre autocommands and executes them, and then it performs the ":write". The general form of the :autocmd command is as follows: > - :autocmd [group] {events} {file_pattern} [nested] {command} + :autocmd [group] {events} {file-pattern} [nested] {command} The [group] name is optional. It is used in managing and calling the commands (more on this later). The {events} parameter is a list of events (comma separated) that trigger the command. - {file_pattern} is a filename, usually with wildcards. For example, using + {file-pattern} is a filename, usually with wildcards. For example, using "*.txt" makes the autocommand be used for all files whose name end in ".txt". The optional [nested] flag allows for nesting of autocommands (see below), and finally, {command} is the command to be executed. @@ -489,7 +489,7 @@ See |autocmd-events| for a complete list of events. PATTERNS -The {file_pattern} argument can actually be a comma-separated list of file +The {file-pattern} argument can actually be a comma-separated list of file patterns. For example: "*.c,*.h" matches files ending in ".c" and ".h". The usual file wildcards can be used. Here is a summary of the most often used ones: diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index bde1dd1ddab2a3..45332e6a4e2f57 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -44,7 +44,7 @@ script file. You can think of other uses yourself. If you are familiar with Python, you can find a comparison between Python and Vim script here, with pointers to other documents: https://gist.github.com/yegappan/16d964a37ead0979b05e655aa036cad0 - And if you are familiar with Javascript: + And if you are familiar with JavaScript: https://w0rp.com/blog/post/vim-script-for-the-javascripter/ Let's start with a simple example: > @@ -2108,7 +2108,7 @@ Thus when a user types "\a", this sequence is invoked: > \a -> TypecorrAdd -> Add -> :call Add() -If another script would also map Add, it would get another script ID and +If another script was also map Add, it would get another script ID and thus define another mapping. Note that instead of s:Add() we use Add() here. That is because the diff --git a/runtime/doc/usr_42.txt b/runtime/doc/usr_42.txt index 1a2748264da7d9..1f3e4bb8587cc6 100644 --- a/runtime/doc/usr_42.txt +++ b/runtime/doc/usr_42.txt @@ -210,8 +210,8 @@ argument: > :amenu Mine.Next\ File :call NextFile() Don't use "" too often. It is not needed for short commands. If you -make a menu for someone else, being able the see the executed command will -give him a hint about what he could have typed, instead of using the mouse. +make a menu for someone else, being able to see the executed command will give +him a hint about what he could have typed, instead of using the mouse. LISTING MENUS diff --git a/runtime/doc/usr_46.txt b/runtime/doc/usr_46.txt index b05a660b9b587c..0986ba1044ca42 100644 --- a/runtime/doc/usr_46.txt +++ b/runtime/doc/usr_46.txt @@ -34,7 +34,7 @@ That makes very clear what is defined where. Let's start with an example, a script that exports one function and has one private function: > - vim9script " This indicates a Vim9 script file, + vim9script " This indicates a Vim9 script file. export def GetMessage(): string let result = '' diff --git a/runtime/doc/usr_toc.txt b/runtime/doc/usr_toc.txt index b17a87de45701c..816cf065ce96c4 100644 --- a/runtime/doc/usr_toc.txt +++ b/runtime/doc/usr_toc.txt @@ -333,7 +333,7 @@ Make Vim work as you like it. |44.11| Installing a syntax file |44.12| Portable syntax file layout -|usr_45.txt| Select your language +|usr_45.txt| Select your language (locale) |45.1| Language for Messages |45.2| Language for Menus |45.3| Using another encoding diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 2c4d1dbc191dd9..7f7b15bb238396 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -1,4 +1,4 @@ -*vim9.txt* For Vim version 8.2. Last change: 2020 Jul 25 +*vim9.txt* For Vim version 8.2. Last change: 2020 Aug 01 VIM REFERENCE MANUAL by Bram Moolenaar @@ -14,7 +14,7 @@ features in Vim9 script. THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE -1 What is Vim9 script? |vim9-script| +1. What is Vim9 script? |vim9-script| 2. Differences |vim9-differences| 3. New style functions |fast-functions| 4. Types |vim9-types| @@ -119,11 +119,12 @@ Functions and variables are script-local by default ~ When using `:function` or `:def` to specify a new function at the script level in a Vim9 script, the function is local to the script, as if "s:" was prefixed. Using the "s:" prefix is optional. To define or use a global -function or variable the "g:" prefix must be used. For functions in an +function or variable the "g:" prefix should be used. For functions in an autoload script the "name#" prefix is sufficient. > def ThisFunction() # script-local def s:ThisFunction() # script-local def g:ThatFunction() # global + def ThatFunction() # global if no local ThatFunction() def scriptname#function() # autoload When using `:function` or `:def` to specify a new function inside a function, @@ -132,16 +133,14 @@ script-local function inside a function. It is possible to define a global function, using the "g:" prefix. When referring to a function and no "s:" or "g:" prefix is used, Vim will -search for the function in this order: -- Local to the current scope and outer scopes up to the function scope. -- Local to the current script file. -- Imported functions, see `:import`. +prefer using a local function (in the function scope, script scope or +imported) before looking for a global function. In all cases the function must be defined before used. That is when it is first called or when `:defcompile` causes the call to be compiled. -The result is that functions and variables without a namespace can always be +The result is that functions and variables without a namespace can usually be found in the script, either defined there or imported. Global functions and -variables could be defined anywhere (good luck finding where!). +variables could be defined anywhere (good luck finding out where!). Global functions can be still be defined and deleted at nearly any time. In Vim9 script script-local functions are defined once when the script is sourced @@ -193,7 +192,8 @@ declaration. Global, window, tab, buffer and Vim variables can only be used without `:let`, because they are not really declared, they can also be deleted with `:unlet`. -Variables cannot shadow previously defined variables. +Variables and functions cannot shadow previously defined or imported variables +and functions. Variables may shadow Ex commands, rename the variable if needed. Global variables and user defined functions must be prefixed with "g:", also @@ -232,11 +232,11 @@ identifier or can't be an Ex command. Examples: > 'foobar'->Process() ('foobar')->Process() -In rare case there is ambiguity between a function name and an Ex command, use -":" to make clear you want to use the Ex command. For example, there is both -the `:substitute` command and the `substitute()` function. When the line -starts with `substitute(` this will use the function. Prepend a colon to use -the command instead: > +In rare case there is ambiguity between a function name and an Ex command, +prepend ":" to make clear you want to use the Ex command. For example, there +is both the `:substitute` command and the `substitute()` function. When the +line starts with `substitute(` this will use the function. Prepend a colon to +use the command instead: > :substitute(pattern (replacement ( Note that while variables need to be defined before they can be used, @@ -261,8 +261,8 @@ number of arguments and any return type. The function can be defined later. Automatic line continuation ~ In many cases it is obvious that an expression continues on the next line. In -those cases there is no need to prefix the line with a backslash. For -example, when a list spans multiple lines: > +those cases there is no need to prefix the line with a backslash +|line-continuation|. For example, when a list spans multiple lines: > let mylist = [ 'one', 'two', @@ -452,6 +452,11 @@ Ex command ranges need to be prefixed with a colon. > 'text'->func() " Vim9: method call :'t " legacy Vim: jump to mark m +Some Ex commands can be confused with assignments in Vim9 script: > + g:name = value # assignment + g:pattern:cmd # invalid command - ERROR + :g:pattern:cmd # :global command + Functions defined with `:def` compile the whole function. Legacy functions can bail out, and the following lines are not parsed: > func Maybe() diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt index 626285e7fa246a..4704067bab5c13 100644 --- a/runtime/doc/visual.txt +++ b/runtime/doc/visual.txt @@ -125,7 +125,7 @@ gN Like |gn| but searches backward, like with `N`. ** Set the current cursor position. If Visual mode is - active it is stopped. Only when 'mouse' option is + active it is stopped. Only when 'mouse' option contains 'n' or 'a'. If the position is within 'so' lines from the last line on the screen the text is scrolled up. If the position is within 'so' lines from @@ -136,7 +136,7 @@ gN Like |gn| but searches backward, like with `N`. Start Visual mode if it is not active. The text from the cursor position to the position of the click is highlighted. If Visual mode was already active move - the start or end of the highlighted text, which ever + the start or end of the highlighted text, whichever is closest, to the position of the click. Only when 'mouse' option contains 'n' or 'a'. @@ -236,7 +236,7 @@ The objects that can be used are: is inner sentence |v_is| ap a paragraph (with white space) |v_ap| ip inner paragraph |v_ip| - ab a () block (with parenthesis) |v_ab| + ab a () block (with parentheses) |v_ab| ib inner () block |v_ib| aB a {} block (with braces) |v_aB| iB inner {} block |v_iB| @@ -347,7 +347,7 @@ Visual-block Shift *v_b_>* The block is shifted by 'shiftwidth'. The RHS of the block is irrelevant. The LHS of the block determines the point from which to apply a right shift, and padding includes TABs optimally according to 'ts' and 'et'. The LHS of the -block determines the point upto which to shift left. +block determines the point up to which to shift left. See |v_b_>_example|. See |v_b_<_example|. diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 80ea2949cc1cfa..106eb37919a411 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1,7 +1,7 @@ " Vim support file to detect file types " " Maintainer: Bram Moolenaar -" Last Change: 2020 Jun 25 +" Last Change: 2020 Aug 04 " Listen very carefully, I will say this only once if exists("did_load_filetypes") diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim index b2d571093db043..295112297ff84d 100644 --- a/runtime/ftplugin/vim.vim +++ b/runtime/ftplugin/vim.vim @@ -83,7 +83,7 @@ endif if exists("loaded_matchit") let b:match_ignorecase = 0 let b:match_words = - \ '\<\%(fu\%[nction]\|def\)\>[^(]:\:\<\%(endf\%[unction]\|enddef\)\>,' . + \ '\<\%(fu\%[nction]\|def\)\>)\@!:\:\<\%(endf\%[unction]\|enddef\)\>,' . \ '\<\(wh\%[ile]\|for\)\>:\:\:\,' . \ '\:\:\,' . \ '{:},' . diff --git a/runtime/keymap/turkish-f.vim b/runtime/keymap/turkish-f.vim new file mode 100644 index 00000000000000..a2774dbffff7bf --- /dev/null +++ b/runtime/keymap/turkish-f.vim @@ -0,0 +1,114 @@ +" Vim keymap file for Turkish F layout +" Maintainer: Emir SARI +" Last changed: 5 August 2020 + +scriptencoding utf-8 +let b:keymap_name = "tr-f" +loadkeymap + +F A LATIN CAPITAL LETTER A +< B LATIN CAPITAL LETTER B +V C LATIN CAPITAL LETTER C +B Ç LATIN CAPITAL LETTER C WITH CEDILLA +Y D LATIN CAPITAL LETTER D +D E LATIN CAPITAL LETTER E +Q F LATIN CAPITAL LETTER F +W G LATIN CAPITAL LETTER G +E Ğ LATIN CAPITAL LETTER G WITH BREVE +O H LATIN CAPITAL LETTER H +R I LATIN CAPITAL LETTER I +S İ LATIN CAPITAL LETTER I WITH DOT ABOVE +Z J LATIN CAPITAL LETTER J +J K LATIN CAPITAL LETTER K +K M LATIN CAPITAL LETTER M +I N LATIN CAPITAL LETTER N +T O LATIN CAPITAL LETTER O +X Ö LATIN CAPITAL LETTER O WITH DIAERESIS +U R LATIN CAPITAL LETTER R +M S LATIN CAPITAL LETTER S +\" Ş LATIN CAPITAL LETTER S WITH CEDILLA +H T LATIN CAPITAL LETTER T +A U LATIN CAPITAL LETTER U +G Ü LATIN CAPITAL LETTER U WITH DIAERESIS +C V LATIN CAPITAL LETTER V +: Y LATIN CAPITAL LETTER Y +N Z LATIN CAPITAL LETTER Z + +{ Q LATIN CAPITAL LETTER Q +} W LATIN CAPITAL LETTER W +| X LATIN CAPITAL LETTER X + +± * ASTERISK +@ " QUOTATION MARK +# ^ CIRCUMFLEX ACCENT +^ & AMPERSAND +& ' APOSTROPHE +* ( LEFT PARENTHESIS +( ) RIGHT PARENTHESIS +) = EQUALS SIGN +_ ? QUESTION MARK ++ _ LOW LINE +> : COLON +? ; SEMICOLON +~ > GREATER-THAN SIGN + +Å Û LATIN CAPITAL LETTER U WITH CIRCUMFLEX +Í Î LATIN CAPITAL LETTER I WITH CIRCUMFLEX +Ï Â LATIN CAPITAL LETTER A WITH CIRCUMFLEX +` » RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + +f a LATIN SMALL LETTER A +, b LATIN SMALL LETTER B +v c LATIN SMALL LETTER C +b ç LATIN SMALL LETTER C WITH CEDILLA +y d LATIN SMALL LETTER D +d e LATIN SMALL LETTER E +q f LATIN SMALL LETTER F +w g LATIN SMALL LETTER G +e ğ LATIN SMALL LETTER G WITH BREVE +o h LATIN SMALL LETTER H +r ı LATIN SMALL LETTER I +s i LATIN SMALL LETTER I WITH DOT ABOVE +z j LATIN SMALL LETTER J +j k LATIN SMALL LETTER K +k m LATIN SMALL LETTER M +i n LATIN SMALL LETTER N +t o LATIN SMALL LETTER O +x ö LATIN SMALL LETTER O WITH DIAERESIS +u r LATIN SMALL LETTER R +m s LATIN SMALL LETTER S +\' ş LATIN SMALL LETTER S WITH CEDILLA +h t LATIN SMALL LETTER T +a u LATIN SMALL LETTER U +g ü LATIN SMALL LETTER U WITH DIAERESIS +c v LATIN SMALL LETTER V +; y LATIN SMALL LETTER Y +n z LATIN SMALL LETTER Z + +[ q LATIN SMALL LETTER Q +] w LATIN SMALL LETTER W +\\ x LATIN SMALL LETTER X + +§ + PLUS SIGN +- / SOLIDUS += - HYPHEN-MINUS +/ , COMMA +` < LESS-THAN SIGN + +£ # NUMBER SIGN +¶ { LEFT CURLY BRACKET +• [ LEFT SQUARE BRACKET +ª ] RIGHT SQUARE BRACKET +º } RIGHT CURLY BRACKET +– \ REVERSE SOLIDUS +≠ | VERTICAL LINE +œ @ COMMERCIAL AT +‘ ~ TILDE +å û LATIN SMALL LETTER U WITH CIRCUMFLEX +ß î LATIN SMALL LETTER I WITH CIRCUMFLEX +∂ € EURO SIGN +ƒ â LATIN SMALL LETTER A WITH CIRCUMFLEX +˙ ₺ TURKISH LIRA SIGN +¬ £ POUND SIGN +… ¥ YEN SIGN +` « LEFT-POINTING DOUBLE ANGLE QUOTATION MARK diff --git a/runtime/keymap/turkish-q.vim b/runtime/keymap/turkish-q.vim new file mode 100644 index 00000000000000..900c10eb926720 --- /dev/null +++ b/runtime/keymap/turkish-q.vim @@ -0,0 +1,62 @@ +" Vim keymap file for Turkish Q layout +" Maintainer: Emir SARI +" Last changed: 5 August 2020 + +scriptencoding utf-8 +let b:keymap_name = "tr-q" +loadkeymap + +\> Ç LATIN CAPITAL LETTER C WITH CEDILLA +\{ Ğ LATIN CAPITAL LETTER G WITH BREVE +\" İ LATIN CAPITAL LETTER I WITH DOT ABOVE +\< Ö LATIN CAPITAL LETTER O WITH DIAERESIS +\: Ş LATIN CAPITAL LETTER S WITH CEDILLA +\} Ü LATIN CAPITAL LETTER U WITH DIAERESIS + +± é LATIN SMALL LETTER E WITH ACUTE +@ ' APOSTROPHE +# ^ CIRCUMFLEX ACCENT +$ + PLUS SIGN +^ & AMPERSAND +& / SOLIDUS +* ( LEFT PARENTHESIS +( ) RIGHT PARENTHESIS +) = EQUAL SIGN +_ ? QUESTION MARK ++ _ LOW LINE +~ > GREATER-THAN SIGN +| ; SEMICOLON +? : COLON + +\. ç LATIN SMALL LETTER C WITH CEDILLA +\[ ğ LATIN SMALL LETTER G WITH BREVE +\' i LATIN SMALL LETTER I +\, ö LATIN SMALL LETTER O WITH DIAERESIS +\; ş LATIN SMALL LETTER S WITH CEDILLA +\] ü LATIN SMALL LETTER U WITH DIAERESIS +i ı LATIN SMALL LETTER DOTLESS I + +§ " QUOTATION MARK +- * ASTERISK += - HYPHEN-MINUS +\\ , COMMA +\/ . FULL STOP +` < LESS-THAN SIGN + +™ £ POUND SIGN +£ # NUMBER SIGN +¢ $ DOLLAR SIGN +∞ ½ VULGAR FRACTION ONE HALF +¶ { LEFT CURLY BRACKET +• [ LEFT SQUARE BRACKET +ª ] RIGHT SQUARE BRACKET +º } RIGHT CURLY BRACKET +– \ REVERSE SOLIDUS +≠ | VERTICAL LINE +œ @ COMMERCIAL AT +´ € EURO SIGN +† ₺ TURKISH LIRA SIGN +¥ ¥ YEN SIGN +‘ ~ TILDE +… ´ ACUTE ACCENT +« ` GRAVE ACCENT diff --git a/runtime/syntax/css.vim b/runtime/syntax/css.vim index 73bbd8d03ffead..f915b4d3753f3f 100644 --- a/runtime/syntax/css.vim +++ b/runtime/syntax/css.vim @@ -1,11 +1,12 @@ " Vim syntax file " Language: Cascading Style Sheets " Previous Contributor List: +" Jules Wang " Claudio Fleiner (Maintainer) " Yeti (Add full CSS2, HTML4 support) " Nikolai Weibull (Add CSS2 support) -" URL: https://github.com/JulesWang/css.vim -" Maintainer: Jules Wang +" URL: https://github.com/jsit/css.vim +" Maintainer: Jay Sitter " Last Change: 2019 Jul. 29 " quit when a syntax file was already loaded @@ -68,7 +69,7 @@ endtry " digits syn match cssValueInteger contained "[-+]\=\d\+" contains=cssUnitDecorators syn match cssValueNumber contained "[-+]\=\d\+\(\.\d*\)\=" contains=cssUnitDecorators -syn match cssValueLength contained "[-+]\=\d\+\(\.\d*\)\=\(mm\|cm\|in\|pt\|pc\|em\|ex\|px\|rem\|dpi\|dppx\|dpcm\|fr\|vw\|vh\|vmin\|vmax\)\>" contains=cssUnitDecorators +syn match cssValueLength contained "[-+]\=\d\+\(\.\d*\)\=\(mm\|cm\|in\|pt\|pc\|em\|ex\|px\|rem\|dpi\|dppx\|dpcm\|fr\|vw\|vh\|vmin\|vmax\|ch\)\>" contains=cssUnitDecorators syn match cssValueLength contained "[-+]\=\d\+\(\.\d*\)\=%" contains=cssUnitDecorators syn match cssValueAngle contained "[-+]\=\d\+\(\.\d*\)\=\(deg\|grad\|rad\)\>" contains=cssUnitDecorators syn match cssValueTime contained "+\=\d\+\(\.\d*\)\=\(ms\|s\)\>" contains=cssUnitDecorators @@ -128,12 +129,14 @@ syn region cssFunction contained matchgroup=cssFunctionName start="\<\(rgb\|clip syn region cssFunction contained matchgroup=cssFunctionName start="\<\(rgba\|hsl\|hsla\|color-stop\|from\|to\)\s*(" end=")" oneline contains=cssColor,cssValueInteger,cssValueNumber,cssValueLength,cssFunctionComma,cssFunction syn region cssFunction contained matchgroup=cssFunctionName start="\<\(linear-\|radial-\)\=\gradient\s*(" end=")" oneline contains=cssColor,cssValueInteger,cssValueNumber,cssValueLength,cssFunction,cssGradientAttr,cssFunctionComma syn region cssFunction contained matchgroup=cssFunctionName start="\<\(matrix\(3d\)\=\|scale\(3d\|X\|Y\|Z\)\=\|translate\(3d\|X\|Y\|Z\)\=\|skew\(X\|Y\)\=\|rotate\(3d\|X\|Y\|Z\)\=\|perspective\)\s*(" end=")" oneline contains=cssValueInteger,cssValueNumber,cssValueLength,cssValueAngle,cssFunctionComma +syn region cssFunction contained matchgroup=cssFunctionName start="\<\(blur\|brightness\|contrast\|drop-shadow\|grayscale\|hue-rotate\|invert\|opacity\|saturate\|sepia\)\s*(" end=")" oneline contains=cssValueInteger,cssValueNumber,cssValueLength,cssValueAngle,cssFunctionComma syn keyword cssGradientAttr contained top bottom left right cover center middle ellipse at syn match cssFunctionComma contained "," " Common Prop and Attr syn keyword cssCommonAttr contained auto none inherit all default normal syn keyword cssCommonAttr contained top bottom center stretch hidden visible +syn match cssCommonAttr contained "\<\(max-\|min-\|fit-\)content\>" "------------------------------------------------ " CSS Animations " http://www.w3.org/TR/css3-animations/ diff --git a/runtime/syntax/fstab.vim b/runtime/syntax/fstab.vim index e416a9abfca640..6b17b5a35eca4a 100644 --- a/runtime/syntax/fstab.vim +++ b/runtime/syntax/fstab.vim @@ -2,8 +2,8 @@ " Language: fstab file " Maintainer: Radu Dineiu " URL: https://raw.github.com/rid9/vim-fstab/master/fstab.vim -" Last Change: 2019 Jun 06 -" Version: 1.3 +" Last Change: 2020 Aug 06 +" Version: 1.4 " " Credits: " David Necas (Yeti) @@ -68,7 +68,7 @@ syn match fsOptionsString /[a-zA-Z0-9_-]\+/ syn keyword fsOptionsYesNo yes no syn cluster fsOptionsCheckCluster contains=fsOptionsExt2Check,fsOptionsFatCheck syn keyword fsOptionsSize 512 1024 2048 -syn keyword fsOptionsGeneral async atime auto bind current defaults dev devgid devmode devmtime devuid dirsync exec force fstab kudzu loop mand move noatime noauto noclusterr noclusterw nodev nodevmtime nodiratime noexec nomand norelatime nosuid nosymfollow nouser owner rbind rdonly relatime remount ro rq rw suid suiddir supermount sw sync union update user users wxallowed xx nofail +syn keyword fsOptionsGeneral async atime auto bind current defaults dev devgid devmode devmtime devuid dirsync exec force fstab kudzu loop mand move noatime noauto noclusterr noclusterw nodev nodevmtime nodiratime noexec nomand norelatime nosuid nosymfollow nouser owner rbind rdonly relatime remount ro rq rw suid suiddir supermount sw sync union update user users wxallowed xx nofail failok syn match fsOptionsGeneral /_netdev/ " Options: adfs diff --git a/runtime/syntax/help.vim b/runtime/syntax/help.vim index b03dd593d11f27..a4c34cd4665a45 100644 --- a/runtime/syntax/help.vim +++ b/runtime/syntax/help.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Vim help file " Maintainer: Bram Moolenaar (Bram@vim.org) -" Last Change: 2020 Mar 06 +" Last Change: 2020 Jul 28 " Quit when a (custom) syntax file was already loaded if exists("b:current_syntax") diff --git a/runtime/syntax/pamconf.vim b/runtime/syntax/pamconf.vim index 10d667bdf5ed4c..29132848a95d53 100644 --- a/runtime/syntax/pamconf.vim +++ b/runtime/syntax/pamconf.vim @@ -1,7 +1,8 @@ " Vim syntax file " Language: pam(8) configuration file " Previous Maintainer: Nikolai Weibull -" Latest Revision: 2011-08-03 +" Latest Revision: 2020/08/04 +" Changes By: Haochen Tong if exists("b:current_syntax") @@ -11,23 +12,32 @@ endif let s:cpo_save = &cpo set cpo&vim -syn match pamconfService '^[[:graph:]]\+' - \ nextgroup=pamconfType, - \ pamconfServiceLineCont skipwhite +let s:has_service_field = exists("b:pamconf_has_service_field") + \ ? b:pamconf_has_service_field + \ : expand('%:t') == 'pam.conf' ? 1 : 0 + +syn match pamconfType '-\?[[:alpha:]]\+' + \ contains=pamconfTypeKeyword + \ nextgroup=pamconfControl, + \ pamconfTypeLineCont skipwhite + +syn keyword pamconfTypeKeyword contained account auth password session + +if s:has_service_field + syn match pamconfService '^[[:graph:]]\+' + \ nextgroup=pamconfType, + \ pamconfServiceLineCont skipwhite + + syn match pamconfServiceLineCont contained '\\$' + \ nextgroup=pamconfType, + \ pamconfServiceLineCont skipwhite skipnl +endif syn keyword pamconfTodo contained TODO FIXME XXX NOTE syn region pamconfComment display oneline start='#' end='$' \ contains=pamconfTodo,@Spell -syn match pamconfServiceLineCont contained '\\$' - \ nextgroup=pamconfType, - \ pamconfServiceLineCont skipwhite skipnl - -syn keyword pamconfType account auth password session - \ nextgroup=pamconfControl, - \ pamconfTypeLineCont skipwhite - syn match pamconfTypeLineCont contained '\\$' \ nextgroup=pamconfControl, \ pamconfTypeLineCont skipwhite skipnl @@ -98,7 +108,8 @@ hi def link pamconfTodo Todo hi def link pamconfComment Comment hi def link pamconfService Statement hi def link pamconfServiceLineCont Special -hi def link pamconfType Type +hi def link pamconfType Special +hi def link pamconfTypeKeyword Type hi def link pamconfTypeLineCont pamconfServiceLineCont hi def link pamconfControl Macro hi def link pamconfControlBegin Delimiter From dd29f1b0569cca253c80856eda2e85e04c1e0627 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Aug 2020 20:46:20 +0200 Subject: [PATCH 0102/1384] patch 8.2.1388: Vim9: += only works for numbers Problem: Vim9: += only works for numbers. Solution: Use += as concatenate for a list. (closes #6646) --- src/testdir/test_vim9_script.vim | 13 ++++- src/version.c | 2 + src/vim9compile.c | 94 ++++++++++++++++++++++---------- 3 files changed, 77 insertions(+), 32 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index ba18af09e3450d..2faa737962b42e 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -126,13 +126,13 @@ def Test_assignment() $SOME_ENV_VAR ..= 'more' assert_equal('somemore', $SOME_ENV_VAR) - call CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1013:') + call CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1051:') call CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1013:') @a = 'areg' @a ..= 'add' assert_equal('aregadd', @a) - call CheckDefFailure(['@a += "more"'], 'E1013:') + call CheckDefFailure(['@a += "more"'], 'E1051:') call CheckDefFailure(['@a += 123'], 'E1013:') lines =<< trim END @@ -146,7 +146,7 @@ def Test_assignment() v:errmsg = 'none' v:errmsg ..= 'again' assert_equal('noneagain', v:errmsg) - call CheckDefFailure(['v:errmsg += "more"'], 'E1013:') + call CheckDefFailure(['v:errmsg += "more"'], 'E1051:') call CheckDefFailure(['v:errmsg += 123'], 'E1013:') # single letter variables @@ -224,6 +224,13 @@ def Test_assignment_list() assert_equal([1, 88, 99], list2) list2[-3] = 77 assert_equal([77, 88, 99], list2) + list2 += [100] + assert_equal([77, 88, 99, 100], list2) + + list3 += ['end'] + assert_equal(['sdf', 'asdf', 'end'], list3) + + call CheckDefExecFailure(['let ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:') call CheckDefExecFailure(['let [v1, v2] = [1, 2]'], 'E1092:') diff --git a/src/version.c b/src/version.c index 11b686255b8ae2..c95d608cd576f4 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1388, /**/ 1387, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index b3cca5842cd20a..570885af1f1048 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -776,6 +776,53 @@ check_number_or_float(vartype_T type1, vartype_T type2, char_u *op) return OK; } + static int +generate_add_instr( + cctx_T *cctx, + vartype_T vartype, + type_T *type1, + type_T *type2) +{ + isn_T *isn = generate_instr_drop(cctx, + vartype == VAR_NUMBER ? ISN_OPNR + : vartype == VAR_LIST ? ISN_ADDLIST + : vartype == VAR_BLOB ? ISN_ADDBLOB +#ifdef FEAT_FLOAT + : vartype == VAR_FLOAT ? ISN_OPFLOAT +#endif + : ISN_OPANY, 1); + + if (vartype != VAR_LIST && vartype != VAR_BLOB + && type1->tt_type != VAR_ANY + && type2->tt_type != VAR_ANY + && check_number_or_float( + type1->tt_type, type2->tt_type, (char_u *)"+") == FAIL) + return FAIL; + + if (isn != NULL) + isn->isn_arg.op.op_type = EXPR_ADD; + return isn == NULL ? FAIL : OK; +} + +/* + * Get the type to use for an instruction for an operation on "type1" and + * "type2". If they are matching use a type-specific instruction. Otherwise + * fall back to runtime type checking. + */ + static vartype_T +operator_type(type_T *type1, type_T *type2) +{ + if (type1->tt_type == type2->tt_type + && (type1->tt_type == VAR_NUMBER + || type1->tt_type == VAR_LIST +#ifdef FEAT_FLOAT + || type1->tt_type == VAR_FLOAT +#endif + || type1->tt_type == VAR_BLOB)) + return type1->tt_type; + return VAR_ANY; +} + /* * Generate an instruction with two arguments. The instruction depends on the * type of the arguments. @@ -791,39 +838,16 @@ generate_two_op(cctx_T *cctx, char_u *op) RETURN_OK_IF_SKIP(cctx); - // Get the known type of the two items on the stack. If they are matching - // use a type-specific instruction. Otherwise fall back to runtime type - // checking. + // Get the known type of the two items on the stack. type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]; type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]; - vartype = VAR_ANY; - if (type1->tt_type == type2->tt_type - && (type1->tt_type == VAR_NUMBER - || type1->tt_type == VAR_LIST -#ifdef FEAT_FLOAT - || type1->tt_type == VAR_FLOAT -#endif - || type1->tt_type == VAR_BLOB)) - vartype = type1->tt_type; + vartype = operator_type(type1, type2); switch (*op) { - case '+': if (vartype != VAR_LIST && vartype != VAR_BLOB - && type1->tt_type != VAR_ANY - && type2->tt_type != VAR_ANY - && check_number_or_float( - type1->tt_type, type2->tt_type, op) == FAIL) + case '+': + if (generate_add_instr(cctx, vartype, type1, type2) == FAIL) return FAIL; - isn = generate_instr_drop(cctx, - vartype == VAR_NUMBER ? ISN_OPNR - : vartype == VAR_LIST ? ISN_ADDLIST - : vartype == VAR_BLOB ? ISN_ADDBLOB -#ifdef FEAT_FLOAT - : vartype == VAR_FLOAT ? ISN_OPFLOAT -#endif - : ISN_OPANY, 1); - if (isn != NULL) - isn->isn_arg.op.op_type = EXPR_ADD; break; case '-': @@ -5699,15 +5723,28 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) type_T *stacktype; // TODO: if type is known use float or any operation + // TODO: check operator matches variable type if (*op == '.') expected = &t_string; + else if (*op == '+') + expected = member_type; stacktype = ((type_T **)stack->ga_data)[stack->ga_len - 1]; if (need_type(stacktype, expected, -1, cctx, FALSE) == FAIL) goto theend; if (*op == '.') - generate_instr_drop(cctx, ISN_CONCAT, 1); + { + if (generate_instr_drop(cctx, ISN_CONCAT, 1) == NULL) + goto theend; + } + else if (*op == '+') + { + if (generate_add_instr(cctx, + operator_type(member_type, stacktype), + member_type, stacktype) == FAIL) + goto theend; + } else { isn_T *isn = generate_instr_drop(cctx, ISN_OPNR, 1); @@ -5716,7 +5753,6 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) goto theend; switch (*op) { - case '+': isn->isn_arg.op.op_type = EXPR_ADD; break; case '-': isn->isn_arg.op.op_type = EXPR_SUB; break; case '*': isn->isn_arg.op.op_type = EXPR_MULT; break; case '/': isn->isn_arg.op.op_type = EXPR_DIV; break; From 74d95b5b58a36697975c48192e84be808b2512a8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Aug 2020 20:47:39 +0200 Subject: [PATCH 0103/1384] patch 8.2.1389: file missing from the distribution Problem: File missing from the distribution. Solution: Add script_util.vim to the list of distributes files. --- Filelist | 1 + src/version.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Filelist b/Filelist index ecc1dd2cf44040..cc90c4d04c994b 100644 --- a/Filelist +++ b/Filelist @@ -172,6 +172,7 @@ SRC_ALL = \ src/testdir/setup_gui.vim \ src/testdir/shared.vim \ src/testdir/vim9.vim \ + src/testdir/script_util.vim \ src/testdir/summarize.vim \ src/testdir/term_util.vim \ src/testdir/view_util.vim \ diff --git a/src/version.c b/src/version.c index c95d608cd576f4..1ac4940e1ecad9 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1389, /**/ 1388, /**/ From 1c199f9c70446933677d5210f34d2b86eefa2a43 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Aug 2020 21:28:34 +0200 Subject: [PATCH 0104/1384] patch 8.2.1390: Vim9: type error after storing an option value Problem: Vim9: type error after storing an option value. Solution: Drop the type after a STOREOPT instruction. (closes #6632) --- src/testdir/test_vim9_script.vim | 5 +++++ src/version.c | 2 ++ src/vim9compile.c | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 2faa737962b42e..c4a6f9a28b4b82 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -422,6 +422,11 @@ def Test_assignment_var_list() assert_equal('one', v1) assert_equal('two', v2) assert_equal(['three'], vrem) + + [&ts, &sw] = [3, 4] + assert_equal(3, &ts) + assert_equal(4, &sw) + set ts=8 sw=4 enddef def Test_assignment_vim9script() diff --git a/src/version.c b/src/version.c index 1ac4940e1ecad9..8b68bc164d5d7d 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1390, /**/ 1389, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 570885af1f1048..a6b4a27db8354d 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1336,7 +1336,7 @@ generate_STOREOPT(cctx_T *cctx, char_u *name, int opt_flags) isn_T *isn; RETURN_OK_IF_SKIP(cctx); - if ((isn = generate_instr(cctx, ISN_STOREOPT)) == NULL) + if ((isn = generate_instr_drop(cctx, ISN_STOREOPT, 1)) == NULL) return FAIL; isn->isn_arg.storeopt.so_name = vim_strsave(name); isn->isn_arg.storeopt.so_flags = opt_flags; From fa211f3c6d27cf962b28f10e3c18b12dde4d20c3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 7 Aug 2020 22:00:26 +0200 Subject: [PATCH 0105/1384] patch 8.2.1391: Vim9: no error for shadowing a script function Problem: Vim9: no error for shadowing a script function. Solution: Check for already defined items. (closes #6652) --- src/testdir/test_vim9_script.vim | 12 ++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 2 ++ 3 files changed, 16 insertions(+) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index c4a6f9a28b4b82..3f1997f6f4cb9e 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1780,6 +1780,18 @@ def Test_func_redefine_fails() enddef END CheckScriptFailure(lines, 'E1073:') + + lines =<< trim END + vim9script + def Foo(): string + return 'foo' + enddef + def Func() + let Foo = {-> 'lambda'} + enddef + defcompile + END + CheckScriptFailure(lines, 'E1073:') enddef def Test_fixed_size_list() diff --git a/src/version.c b/src/version.c index 8b68bc164d5d7d..978920e81ce402 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1391, /**/ 1390, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index a6b4a27db8354d..25da7f562c8ab7 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -5462,6 +5462,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) semsg(_(e_unknown_var), name); goto theend; } + else if (check_defined(var_start, varlen, cctx) == FAIL) + goto theend; } } From bf8feb5aeb71c8f56897845c4134793201aa459a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Aug 2020 14:26:31 +0200 Subject: [PATCH 0106/1384] patch 8.2.1392: Vim9: line number incorrect after skipping over comment lines Problem: Vim9: error line number incorrect after skipping over comment lines. Solution: Insert empty lines for skipped lines. --- src/testdir/test_vim9_func.vim | 41 ++++++++++++++++++++++++++++++++++ src/userfunc.c | 12 ++++++++++ src/version.c | 2 ++ 3 files changed, 55 insertions(+) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 649ef4806921b9..3cc1e112b6ab9f 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -984,6 +984,47 @@ func DelMe() echo 'DelMe' endfunc +def Test_error_reporting() + # comment lines at the start of the function + let lines =<< trim END + " comment + def Func() + # comment + # comment + invalid + enddef + defcompile + END + call writefile(lines, 'Xdef') + try + source Xdef + catch /E476:/ + assert_match('Invalid command: invalid', v:exception) + assert_match(', line 3$', v:throwpoint) + endtry + + # comment lines after the start of the function + lines =<< trim END + " comment + def Func() + let x = 1234 + # comment + # comment + invalid + enddef + defcompile + END + call writefile(lines, 'Xdef') + try + source Xdef + catch /E476:/ + assert_match('Invalid command: invalid', v:exception) + assert_match(', line 4$', v:throwpoint) + endtry + + call delete('Xdef') +enddef + def Test_deleted_function() CheckDefExecFailure([ 'let RefMe: func = function("g:DelMe")', diff --git a/src/userfunc.c b/src/userfunc.c index 684a805d8abaf0..10d1c3b77b9c31 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -2961,6 +2961,18 @@ def_function(exarg_T *eap, char_u *name_arg) // Save the starting line number. sourcing_lnum_top = SOURCING_LNUM; + // Detect having skipped over comment lines to find the return + // type. Add NULL lines to keep the line count correct. + sourcing_lnum_off = get_sourced_lnum(eap->getline, eap->cookie); + if (SOURCING_LNUM < sourcing_lnum_off) + { + sourcing_lnum_off -= SOURCING_LNUM; + if (ga_grow(&newlines, sourcing_lnum_off) == FAIL) + goto erret; + while (sourcing_lnum_off-- > 0) + ((char_u **)(newlines.ga_data))[newlines.ga_len++] = NULL; + } + indent = 2; nesting = 0; nesting_def[nesting] = (eap->cmdidx == CMD_def); diff --git a/src/version.c b/src/version.c index 978920e81ce402..0f6dfc1d9a887d 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1392, /**/ 1391, /**/ From b7f4fa517793b0fe1a4895781b4cba451d60d7c2 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Aug 2020 14:41:52 +0200 Subject: [PATCH 0107/1384] patch 8.2.1393: insufficient testing for script debugging Problem: Insufficient testing for script debugging. Solution: Add more tests. (Ben Jackson) --- src/testdir/test_debugger.vim | 284 ++++++++++++++++++++++++++++++++-- src/version.c | 2 + 2 files changed, 276 insertions(+), 10 deletions(-) diff --git a/src/testdir/test_debugger.vim b/src/testdir/test_debugger.vim index e019617e685d57..40c1caa12ddfe2 100644 --- a/src/testdir/test_debugger.vim +++ b/src/testdir/test_debugger.vim @@ -4,6 +4,19 @@ source shared.vim source screendump.vim source check.vim +CheckRunVimInTerminal + +func CheckCWD() + " Check that the longer lines don't wrap due to the length of the script name + " in cwd + let script_len = len( getcwd() .. '/Xtest1.vim' ) + let longest_line = len( 'Breakpoint in "" line 1' ) + if script_len > ( 75 - longest_line ) + throw 'Skipped: Your CWD has too many characters' + endif +endfunc +command! -nargs=0 -bar CheckCWD call CheckCWD() + func CheckDbgOutput(buf, lines, options = {}) " Verify the expected output let lnum = 20 - len(a:lines) @@ -34,8 +47,6 @@ endfunc " Debugger tests func Test_Debugger() - CheckRunVimInTerminal - " Create a Vim script with some functions let lines =<< trim END func Foo() @@ -329,8 +340,7 @@ func Test_Debugger() endfunc func Test_Backtrace_Through_Source() - CheckRunVimInTerminal - + CheckCWD let file1 =<< trim END func SourceAnotherFile() source Xtest2.vim @@ -391,6 +401,71 @@ func Test_Backtrace_Through_Source() \ '->0 script ' .. getcwd() .. '/Xtest2.vim', \ 'line 1: func DoAThing()']) + call RunDbgCmd( buf, 'up' ) + call RunDbgCmd( buf, 'backtrace', [ + \ '>backtrace', + \ ' 3 function GlobalFunction[1]', + \ ' 2 CallAFunction[1]', + \ '->1 SourceAnotherFile[1]', + \ ' 0 script ' .. getcwd() .. '/Xtest2.vim', + \ 'line 1: func DoAThing()' ] ) + + call RunDbgCmd( buf, 'up' ) + call RunDbgCmd( buf, 'backtrace', [ + \ '>backtrace', + \ ' 3 function GlobalFunction[1]', + \ '->2 CallAFunction[1]', + \ ' 1 SourceAnotherFile[1]', + \ ' 0 script ' .. getcwd() .. '/Xtest2.vim', + \ 'line 1: func DoAThing()' ] ) + + call RunDbgCmd( buf, 'up' ) + call RunDbgCmd( buf, 'backtrace', [ + \ '>backtrace', + \ '->3 function GlobalFunction[1]', + \ ' 2 CallAFunction[1]', + \ ' 1 SourceAnotherFile[1]', + \ ' 0 script ' .. getcwd() .. '/Xtest2.vim', + \ 'line 1: func DoAThing()' ] ) + + call RunDbgCmd( buf, 'up', [ 'frame at highest level: 3' ] ) + call RunDbgCmd( buf, 'backtrace', [ + \ '>backtrace', + \ '->3 function GlobalFunction[1]', + \ ' 2 CallAFunction[1]', + \ ' 1 SourceAnotherFile[1]', + \ ' 0 script ' .. getcwd() .. '/Xtest2.vim', + \ 'line 1: func DoAThing()' ] ) + + call RunDbgCmd( buf, 'down' ) + call RunDbgCmd( buf, 'backtrace', [ + \ '>backtrace', + \ ' 3 function GlobalFunction[1]', + \ '->2 CallAFunction[1]', + \ ' 1 SourceAnotherFile[1]', + \ ' 0 script ' .. getcwd() .. '/Xtest2.vim', + \ 'line 1: func DoAThing()' ] ) + + call RunDbgCmd( buf, 'down' ) + call RunDbgCmd( buf, 'backtrace', [ + \ '>backtrace', + \ ' 3 function GlobalFunction[1]', + \ ' 2 CallAFunction[1]', + \ '->1 SourceAnotherFile[1]', + \ ' 0 script ' .. getcwd() .. '/Xtest2.vim', + \ 'line 1: func DoAThing()' ] ) + + call RunDbgCmd( buf, 'down' ) + call RunDbgCmd( buf, 'backtrace', [ + \ '>backtrace', + \ ' 3 function GlobalFunction[1]', + \ ' 2 CallAFunction[1]', + \ ' 1 SourceAnotherFile[1]', + \ '->0 script ' .. getcwd() .. '/Xtest2.vim', + \ 'line 1: func DoAThing()' ] ) + + call RunDbgCmd( buf, 'down', [ 'frame is zero' ] ) + " step until we have another meaninfgul trace call RunDbgCmd(buf, 'step', ['line 5: func File2Function()']) call RunDbgCmd(buf, 'step', ['line 9: call File2Function()']) @@ -440,8 +515,7 @@ func Test_Backtrace_Through_Source() endfunc func Test_Backtrace_Autocmd() - CheckRunVimInTerminal - + CheckCWD let file1 =<< trim END func SourceAnotherFile() source Xtest2.vim @@ -603,8 +677,7 @@ func Test_Backtrace_Autocmd() endfunc func Test_Backtrace_CmdLine() - CheckRunVimInTerminal - + CheckCWD let file1 =<< trim END func SourceAnotherFile() source Xtest2.vim @@ -664,8 +737,7 @@ func Test_Backtrace_CmdLine() endfunc func Test_Backtrace_DefFunction() - CheckRunVimInTerminal - + CheckCWD let file1 =<< trim END vim9script import File2Function from './Xtest2.vim' @@ -755,3 +827,195 @@ func Test_Backtrace_DefFunction() call delete('Xtest1.vim') call delete('Xtest2.vim') endfunc + +func Test_debug_backtrace_level() + CheckCWD + let lines =<< trim END + let s:file1_var = 'file1' + let g:global_var = 'global' + + func s:File1Func( arg ) + let s:file1_var .= a:arg + let local_var = s:file1_var .. ' test1' + let g:global_var .= local_var + source Xtest2.vim + endfunc + + call s:File1Func( 'arg1' ) + END + call writefile(lines, 'Xtest1.vim') + + let lines =<< trim END + let s:file2_var = 'file2' + + func s:File2Func( arg ) + let s:file2_var .= a:arg + let local_var = s:file2_var .. ' test2' + let g:global_var .= local_var + endfunc + + call s:File2Func( 'arg2' ) + END + call writefile(lines, 'Xtest2.vim') + + let file1 = getcwd() .. '/Xtest1.vim' + let file2 = getcwd() .. '/Xtest2.vim' + + " set a breakpoint and source file1.vim + let buf = RunVimInTerminal( + \ '-c "breakadd file 1 Xtest1.vim" -S Xtest1.vim', + \ #{ wait_for_ruler: 0 } ) + + call CheckDbgOutput(buf, [ + \ 'Breakpoint in "' .. file1 .. '" line 1', + \ 'Entering Debug mode. Type "cont" to continue.', + \ 'command line..script ' .. file1, + \ 'line 1: let s:file1_var = ''file1''' + \ ]) + + " step throught the initial declarations + call RunDbgCmd(buf, 'step', [ 'line 2: let g:global_var = ''global''' ] ) + call RunDbgCmd(buf, 'step', [ 'line 4: func s:File1Func( arg )' ] ) + call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] ) + call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] ) + call RunDbgCmd(buf, 'echo global_var', [ 'global' ] ) + + " step in to the first function + call RunDbgCmd(buf, 'step', [ 'line 11: call s:File1Func( ''arg1'' )' ] ) + call RunDbgCmd(buf, 'step', [ 'line 1: let s:file1_var .= a:arg' ] ) + call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] ) + call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] ) + call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] ) + call RunDbgCmd(buf, + \'echo global_var', + \[ 'E121: Undefined variable: global_var' ] ) + call RunDbgCmd(buf, + \'echo local_var', + \[ 'E121: Undefined variable: local_var' ] ) + call RunDbgCmd(buf, + \'echo l:local_var', + \[ 'E121: Undefined variable: l:local_var' ] ) + + " backtrace up + call RunDbgCmd(buf, 'backtrace', [ + \ '\V>backtrace', + \ '\V 2 command line', + \ '\V 1 script ' .. file1 .. '[11]', + \ '\V->0 function \.\*_File1Func', + \ '\Vline 1: let s:file1_var .= a:arg', + \ ], + \ #{ match: 'pattern' } ) + call RunDbgCmd(buf, 'up', [ '>up' ] ) + + call RunDbgCmd(buf, 'backtrace', [ + \ '\V>backtrace', + \ '\V 2 command line', + \ '\V->1 script ' .. file1 .. '[11]', + \ '\V 0 function \.\*_File1Func', + \ '\Vline 1: let s:file1_var .= a:arg', + \ ], + \ #{ match: 'pattern' } ) + + " Expression evaluation in the script frame (not the function frame) + " FIXME: Unexpected in this scope (a: should not be visibnle) + call RunDbgCmd(buf, 'echo a:arg', [ 'arg1' ] ) + call RunDbgCmd(buf, 'echo s:file1_var', [ 'file1' ] ) + call RunDbgCmd(buf, 'echo g:global_var', [ 'global' ] ) + " FIXME: Unexpected in this scope (global should be found) + call RunDbgCmd(buf, + \'echo global_var', + \[ 'E121: Undefined variable: global_var' ] ) + call RunDbgCmd(buf, + \'echo local_var', + \[ 'E121: Undefined variable: local_var' ] ) + call RunDbgCmd(buf, + \'echo l:local_var', + \[ 'E121: Undefined variable: l:local_var' ] ) + + + " step while backtraced jumps to the latest frame + call RunDbgCmd(buf, 'step', [ + \ 'line 2: let local_var = s:file1_var .. '' test1''' ] ) + call RunDbgCmd(buf, 'backtrace', [ + \ '\V>backtrace', + \ '\V 2 command line', + \ '\V 1 script ' .. file1 .. '[11]', + \ '\V->0 function \.\*_File1Func', + \ '\Vline 2: let local_var = s:file1_var .. '' test1''', + \ ], + \ #{ match: 'pattern' } ) + + call RunDbgCmd(buf, 'step', [ 'line 3: let g:global_var .= local_var' ] ) + call RunDbgCmd(buf, 'echo local_var', [ 'file1arg1 test1' ] ) + call RunDbgCmd(buf, 'echo l:local_var', [ 'file1arg1 test1' ] ) + + call RunDbgCmd(buf, 'step', [ 'line 4: source Xtest2.vim' ] ) + call RunDbgCmd(buf, 'step', [ 'line 1: let s:file2_var = ''file2''' ] ) + call RunDbgCmd(buf, 'backtrace', [ + \ '\V>backtrace', + \ '\V 3 command line', + \ '\V 2 script ' .. file1 .. '[11]', + \ '\V 1 function \.\*_File1Func[4]', + \ '\V->0 script ' .. file2, + \ '\Vline 1: let s:file2_var = ''file2''', + \ ], + \ #{ match: 'pattern' } ) + + " Expression evaluation in the script frame file2 (not the function frame) + call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] ) + call RunDbgCmd(buf, + \ 'echo s:file1_var', + \ [ 'E121: Undefined variable: s:file1_var' ] ) + call RunDbgCmd(buf, 'echo g:global_var', [ 'globalfile1arg1 test1' ] ) + call RunDbgCmd(buf, 'echo global_var', [ 'globalfile1arg1 test1' ] ) + call RunDbgCmd(buf, + \'echo local_var', + \[ 'E121: Undefined variable: local_var' ] ) + call RunDbgCmd(buf, + \'echo l:local_var', + \[ 'E121: Undefined variable: l:local_var' ] ) + call RunDbgCmd(buf, + \ 'echo s:file2_var', + \ [ 'E121: Undefined variable: s:file2_var' ] ) + + call RunDbgCmd(buf, 'step', [ 'line 3: func s:File2Func( arg )' ] ) + call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] ) + + " Up the stack to the other script context + call RunDbgCmd(buf, 'up') + call RunDbgCmd(buf, 'backtrace', [ + \ '\V>backtrace', + \ '\V 3 command line', + \ '\V 2 script ' .. file1 .. '[11]', + \ '\V->1 function \.\*_File1Func[4]', + \ '\V 0 script ' .. file2, + \ '\Vline 3: func s:File2Func( arg )', + \ ], + \ #{ match: 'pattern' } ) + " FIXME: Unexpected. Should see the a: and l: dicts from File1Func + call RunDbgCmd(buf, 'echo a:arg', [ 'E121: Undefined variable: a:arg' ] ) + call RunDbgCmd(buf, + \ 'echo l:local_var', + \ [ 'E121: Undefined variable: l:local_var' ] ) + + call RunDbgCmd(buf, 'up') + call RunDbgCmd(buf, 'backtrace', [ + \ '\V>backtrace', + \ '\V 3 command line', + \ '\V->2 script ' .. file1 .. '[11]', + \ '\V 1 function \.\*_File1Func[4]', + \ '\V 0 script ' .. file2, + \ '\Vline 3: func s:File2Func( arg )', + \ ], + \ #{ match: 'pattern' } ) + + " FIXME: Unexpected (wrong script vars are used) + call RunDbgCmd(buf, + \ 'echo s:file1_var', + \ [ 'E121: Undefined variable: s:file1_var' ] ) + call RunDbgCmd(buf, 'echo s:file2_var', [ 'file2' ] ) + + call StopVimInTerminal(buf) + call delete('Xtest1.vim') + call delete('Xtest2.vim') +endfunc diff --git a/src/version.c b/src/version.c index 0f6dfc1d9a887d..2febed6752006c 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1393, /**/ 1392, /**/ From 2dd0a2c39a3b3fbffc94d0676e472c78d02ebdbd Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Aug 2020 15:10:27 +0200 Subject: [PATCH 0108/1384] patch 8.2.1394: Vim9: compiling a function interferes with command modifiers Problem: Vim9: compiling a function interferes with command modifiers. Solution: Save and restore command modifiers. (closes #6658) --- src/testdir/test_vim9_func.vim | 25 +++++++++++++++++++++++++ src/testdir/test_vim9_script.vim | 5 ----- src/version.c | 2 ++ src/vim9compile.c | 14 ++++++++------ 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 3cc1e112b6ab9f..d39584154bc5ea 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1351,5 +1351,30 @@ def Test_partial_call() assert_equal({'title': 'test'}, getqflist({'title': 1})) enddef +def Test_cmd_modifier() + tab echo '0' + call CheckDefFailure(['5tab echo 3'], 'E16:') +enddef + +def Test_restore_modifiers() + # check that when compiling a :def function command modifiers are not messed + # up. + let lines =<< trim END + vim9script + set eventignore= + autocmd QuickFixCmdPost * copen + def AutocmdsDisabled() + eval 0 + enddef + func Func() + noautocmd call s:AutocmdsDisabled() + let g:ei_after = &eventignore + endfunc + Func() + END + CheckScriptSuccess(lines) + assert_equal('', g:ei_after) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 3f1997f6f4cb9e..10706b1d932b60 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -751,11 +751,6 @@ func Test_block_failure() call CheckDefFailure(['{', 'echo 1'], 'E1026:') endfunc -def Test_cmd_modifier() - tab echo '0' - call CheckDefFailure(['5tab echo 3'], 'E16:') -enddef - func g:NoSuchFunc() echo 'none' endfunc diff --git a/src/version.c b/src/version.c index 2febed6752006c..17ed09b0f713d2 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1394, /**/ 1393, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 25da7f562c8ab7..04681fee7eaa20 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2668,7 +2668,7 @@ next_line_from_context(cctx_T *cctx, int skip_comment) cctx->ctx_line_start = line; SOURCING_LNUM = cctx->ctx_lnum + 1; } while (line == NULL || *skipwhite(line) == NUL - || (skip_comment && vim9_comment_start(skipwhite(line)))); + || (skip_comment && vim9_comment_start(skipwhite(line)))); return line; } @@ -7194,10 +7194,11 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx) */ for (;;) { - exarg_T ea; - int starts_with_colon = FALSE; - char_u *cmd; - int save_msg_scroll = msg_scroll; + exarg_T ea; + cmdmod_T save_cmdmod; + int starts_with_colon = FALSE; + char_u *cmd; + int save_msg_scroll = msg_scroll; // Bail out on the first error to avoid a flood of errors and report // the right line number when inside try/catch. @@ -7278,6 +7279,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx) /* * COMMAND MODIFIERS */ + save_cmdmod = cmdmod; if (parse_command_modifiers(&ea, &errormsg, FALSE) == FAIL) { if (errormsg != NULL) @@ -7288,7 +7290,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx) } // TODO: use modifiers in the command undo_cmdmod(&ea, save_msg_scroll); - CLEAR_FIELD(cmdmod); + cmdmod = save_cmdmod; // Skip ":call" to get to the function name. if (checkforcmd(&ea.cmd, "call", 3)) From 98b4f145eb89405021e23a4a37db51d60a75a1d0 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Aug 2020 15:46:01 +0200 Subject: [PATCH 0109/1384] patch 8.2.1395: Vim9: no error if declaring a funcref with lower case letter Problem: Vim9: no error if declaring a funcref with a lower case letter. Solution: Check the name after the type is inferred. Fix confusing name. --- src/dict.c | 2 +- src/eval.c | 2 +- src/evalvars.c | 4 ++-- src/proto/evalvars.pro | 2 +- src/testdir/test_vim9_expr.vim | 8 ++++---- src/testdir/test_vim9_script.vim | 1 + src/version.c | 2 ++ src/vim9compile.c | 9 ++++++++- 8 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/dict.c b/src/dict.c index ad482cddd5934f..b381d476dc80ed 100644 --- a/src/dict.c +++ b/src/dict.c @@ -966,7 +966,7 @@ dict_extend(dict_T *d1, dict_T *d2, char_u *action) // Check the key to be valid when adding to any scope. if (d1->dv_scope == VAR_DEF_SCOPE && HI2DI(hi2)->di_tv.v_type == VAR_FUNC - && var_check_func_name(hi2->hi_key, di1 == NULL)) + && var_wrong_func_name(hi2->hi_key, di1 == NULL)) break; if (!valid_varname(hi2->hi_key)) break; diff --git a/src/eval.c b/src/eval.c index c695468cdfc77f..b1fad1dcd5e32e 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1007,7 +1007,7 @@ get_lval( prevval = 0; // avoid compiler warning wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE && rettv->v_type == VAR_FUNC - && var_check_func_name(key, lp->ll_di == NULL)) + && var_wrong_func_name(key, lp->ll_di == NULL)) || !valid_varname(key); if (len != -1) key[len] = prevval; diff --git a/src/evalvars.c b/src/evalvars.c index 869deefc2fe675..70afa8444c6c0b 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -2928,7 +2928,7 @@ set_var_const( di = find_var_in_scoped_ht(name, TRUE); if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) - && var_check_func_name(name, di == NULL)) + && var_wrong_func_name(name, di == NULL)) return; if (di != NULL) @@ -3114,7 +3114,7 @@ var_check_fixed(int flags, char_u *name, int use_gettext) * Return TRUE and give an error if not. */ int -var_check_func_name( +var_wrong_func_name( char_u *name, // points to start of variable name int new_var) // TRUE when creating the variable { diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro index 43c25287cae976..f304872230ea1a 100644 --- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -68,7 +68,7 @@ void set_var(char_u *name, typval_T *tv, int copy); void set_var_const(char_u *name, type_T *type, typval_T *tv, int copy, int flags); int var_check_ro(int flags, char_u *name, int use_gettext); int var_check_fixed(int flags, char_u *name, int use_gettext); -int var_check_func_name(char_u *name, int new_var); +int var_wrong_func_name(char_u *name, int new_var); int var_check_lock(int lock, char_u *name, int use_gettext); int valid_varname(char_u *varname); void reset_v_option_vars(void); diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 746983d14b1c35..7e1e16acdd9d40 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -53,8 +53,8 @@ def Test_expr1() let RetThat: func = g:atrue ? RetOne : RetTwo assert_equal(function('len'), RetThat) - let x = FuncOne - let y = FuncTwo + let X = FuncOne + let Y = FuncTwo let Z = g:cond ? FuncOne : FuncTwo assert_equal(123, Z(3)) enddef @@ -132,8 +132,8 @@ func Test_expr1_fails() " missing argument detected even when common type is used call CheckDefFailure([ - \ 'let x = FuncOne', - \ 'let y = FuncTwo', + \ 'let X = FuncOne', + \ 'let Y = FuncTwo', \ 'let Z = g:cond ? FuncOne : FuncTwo', \ 'Z()'], 'E119:') endfunc diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 10706b1d932b60..eedce3201b2719 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -28,6 +28,7 @@ def Test_assignment() call CheckDefFailure(['let x:string'], 'E1069:') call CheckDefFailure(['let x:string = "x"'], 'E1069:') call CheckDefFailure(['let a:string = "x"'], 'E1069:') + call CheckDefFailure(['let lambda = {-> "lambda"}'], 'E704:') let nr: number = 1234 call CheckDefFailure(['let nr: number = "asdf"'], 'E1013:') diff --git a/src/version.c b/src/version.c index 17ed09b0f713d2..870df176600193 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1395, /**/ 1394, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 04681fee7eaa20..0664124fe4c123 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -5515,7 +5515,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) } // new local variable - if (type->tt_type == VAR_FUNC && var_check_func_name(name, TRUE)) + if ((type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL) + && var_wrong_func_name(name, TRUE)) goto theend; lvar = reserve_local(cctx, var_start, varlen, cmdidx == CMD_const, type); @@ -5624,6 +5625,12 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) emsg(_(e_cannot_use_void)); goto theend; } + else if ((stacktype->tt_type == VAR_FUNC + || stacktype->tt_type == VAR_PARTIAL) + && var_wrong_func_name(name, TRUE)) + { + goto theend; + } else { // An empty list or dict has a &t_void member, From 5a849da57c5fb54ffcffd436a9e00ef40fdf094c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Aug 2020 16:47:30 +0200 Subject: [PATCH 0110/1384] patch 8.2.1396: Vim9: no error for unexpectedly returning a value Problem: Vim9: no error for unexpectedly returning a value. Solution: Only set the return type for lambda's. Make using function type in a function reference work. --- src/testdir/test_vim9_func.vim | 44 +++++++++++++++++++++++++++++----- src/version.c | 2 ++ src/vim9compile.c | 26 +++++++++++++------- 3 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index d39584154bc5ea..4a020c9afa678c 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -503,16 +503,48 @@ def Test_error_in_nested_function() enddef def Test_return_type_wrong() - CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef', 'defcompile'], 'expected number but got string') - CheckScriptFailure(['def Func(): string', 'return 1', 'enddef', 'defcompile'], 'expected string but got number') - CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef', 'defcompile'], 'E1096: Returning a value in a function without a return type') - CheckScriptFailure(['def Func()', 'return "a"', 'enddef', 'defcompile'], 'E1096: Returning a value in a function without a return type') - - CheckScriptFailure(['def Func(): number', 'return', 'enddef', 'defcompile'], 'E1003:') + CheckScriptFailure([ + 'def Func(): number', + 'return "a"', + 'enddef', + 'defcompile'], 'expected number but got string') + CheckScriptFailure([ + 'def Func(): string', + 'return 1', + 'enddef', + 'defcompile'], 'expected string but got number') + CheckScriptFailure([ + 'def Func(): void', + 'return "a"', + 'enddef', + 'defcompile'], + 'E1096: Returning a value in a function without a return type') + CheckScriptFailure([ + 'def Func()', + 'return "a"', + 'enddef', + 'defcompile'], + 'E1096: Returning a value in a function without a return type') + + CheckScriptFailure([ + 'def Func(): number', + 'return', + 'enddef', + 'defcompile'], 'E1003:') CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:') CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:') CheckScriptFailure(['def Func()', 'return 1'], 'E1057:') + + CheckScriptFailure([ + 'vim9script', + 'def FuncB()', + ' return 123', + 'enddef', + 'def FuncA()', + ' FuncB()', + 'enddef', + 'defcompile'], 'E1096:') enddef def Test_arg_type_wrong() diff --git a/src/version.c b/src/version.c index 870df176600193..8649ca89654fa2 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1396, /**/ 1395, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 0664124fe4c123..5f76bc2c03c21c 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -662,8 +662,10 @@ check_type(type_T *expected, type_T *actual, int give_msg) int i; for (i = 0; i < expected->tt_argcount; ++i) - if (check_type(expected->tt_args[i], actual->tt_args[i], - FALSE) == FAIL) + // Allow for using "any" argument type, lambda's have them. + if (actual->tt_args[i] != &t_any && check_type( + expected->tt_args[i], actual->tt_args[i], FALSE) + == FAIL) { ret = FAIL; break; @@ -1537,7 +1539,7 @@ generate_NEWDICT(cctx_T *cctx, int count) * Generate an ISN_FUNCREF instruction. */ static int -generate_FUNCREF(cctx_T *cctx, int dfunc_idx) +generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc) { isn_T *isn; garray_T *stack = &cctx->ctx_type_stack; @@ -1545,13 +1547,13 @@ generate_FUNCREF(cctx_T *cctx, int dfunc_idx) RETURN_OK_IF_SKIP(cctx); if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL) return FAIL; - isn->isn_arg.funcref.fr_func = dfunc_idx; + isn->isn_arg.funcref.fr_func = ufunc->uf_dfunc_idx; isn->isn_arg.funcref.fr_var_idx = cctx->ctx_closure_count++; if (ga_grow(stack, 1) == FAIL) return FAIL; - ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any; - // TODO: argument and return types + ((type_T **)stack->ga_data)[stack->ga_len] = + ufunc->uf_func_type == NULL ? &t_func_any : ufunc->uf_func_type; ++stack->ga_len; return OK; @@ -1713,7 +1715,8 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount) } } if (ufunc->uf_def_status == UF_TO_BE_COMPILED) - if (compile_def_function(ufunc, TRUE, NULL) == FAIL) + if (compile_def_function(ufunc, ufunc->uf_ret_type == NULL, NULL) + == FAIL) return FAIL; } @@ -3338,7 +3341,12 @@ compile_lambda(char_u **arg, cctx_T *cctx) clear_evalarg(&evalarg, NULL); if (ufunc->uf_def_status == UF_COMPILED) - return generate_FUNCREF(cctx, ufunc->uf_dfunc_idx); + { + // The return type will now be known. + set_function_type(ufunc); + + return generate_FUNCREF(cctx, ufunc); + } func_ptr_unref(ufunc); return FAIL; @@ -4982,7 +4990,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) TRUE, ufunc->uf_func_type); if (lvar == NULL) return NULL; - if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL) + if (generate_FUNCREF(cctx, ufunc) == FAIL) return NULL; r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL); } From 4a6d1b660fcea67931202527ad2852da55d26d49 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Aug 2020 17:55:49 +0200 Subject: [PATCH 0111/1384] patch 8.2.1397: Vim9: return type of maparg() not adjusted for fourth arg Problem: Vim9: return type of maparg() not adjusted for fourth argument. Solution: Check if fourth argument is present. (closes #6645) --- src/evalfunc.c | 11 ++++++++++- src/testdir/test_maparg.vim | 13 +++++++++++++ src/version.c | 2 ++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/evalfunc.c b/src/evalfunc.c index a421690e499e4e..5607ef9e5ba8a2 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -402,6 +402,15 @@ ret_getreg(int argcount, type_T **argtypes UNUSED) return &t_string; } + static type_T * +ret_maparg(int argcount, type_T **argtypes UNUSED) +{ + // Assume that if the fourth argument is passed it's non-zero + if (argcount == 4) + return &t_dict_any; + return &t_string; +} + static type_T *ret_f_function(int argcount, type_T **argtypes); /* @@ -729,7 +738,7 @@ static funcentry_T global_functions[] = #endif }, {"map", 2, 2, FEARG_1, ret_any, f_map}, - {"maparg", 1, 4, FEARG_1, ret_string, f_maparg}, + {"maparg", 1, 4, FEARG_1, ret_maparg, f_maparg}, {"mapcheck", 1, 3, FEARG_1, ret_string, f_mapcheck}, {"mapset", 3, 3, FEARG_1, ret_void, f_mapset}, {"match", 2, 4, FEARG_1, ret_any, f_match}, diff --git a/src/testdir/test_maparg.vim b/src/testdir/test_maparg.vim index 81e057adcae14f..3b61ff6cf78586 100644 --- a/src/testdir/test_maparg.vim +++ b/src/testdir/test_maparg.vim @@ -81,6 +81,19 @@ func Test_maparg() abclear endfunc +def Test_vim9_maparg() + nmap { w + let one: string = maparg('{') + assert_equal('w', one) + let two: string = maparg('{', 'n') + assert_equal('w', two) + let three: string = maparg('{', 'n', 0) + assert_equal('w', three) + let four: dict = maparg('{', 'n', 0, 1) + call assert_equal(['{', 'w', 'n'], [four.lhs, four.rhs, four.mode]) + nunmap { +enddef + func Test_mapcheck() call assert_equal('', mapcheck('a')) call assert_equal('', mapcheck('abc')) diff --git a/src/version.c b/src/version.c index 8649ca89654fa2..b67d3c3dac0003 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1397, /**/ 1396, /**/ From daa2f36573db3e1df7eb1fdbc3a09a2815644048 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Aug 2020 21:33:21 +0200 Subject: [PATCH 0112/1384] patch 8.2.1398: autoload script sourced twice if sourced directly Problem: Autoload script sourced twice if sourced directly. Solution: Do not source an autoload script again. (issue #6644) --- src/scriptfile.c | 4 +++- src/testdir/sautest/autoload/sourced.vim | 3 ++- src/version.c | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/scriptfile.c b/src/scriptfile.c index b93e3513807f07..38215914d5aefd 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -2012,6 +2012,7 @@ script_autoload( char_u *scriptname, *tofree; int ret = FALSE; int i; + int ret_sid; // If there is no '#' after name[0] there is no package name. p = vim_strchr(name, AUTOLOAD_CHAR); @@ -2039,7 +2040,8 @@ script_autoload( } // Try loading the package from $VIMRUNTIME/autoload/.vim - if (source_runtime(scriptname, 0) == OK) + // Use "ret_sid" to avoid loading the same script again. + if (source_in_path(p_rtp, scriptname, 0, &ret_sid) == OK) ret = TRUE; } diff --git a/src/testdir/sautest/autoload/sourced.vim b/src/testdir/sautest/autoload/sourced.vim index f69f00cb5345af..aac96b11ce3b0a 100644 --- a/src/testdir/sautest/autoload/sourced.vim +++ b/src/testdir/sautest/autoload/sourced.vim @@ -1,3 +1,4 @@ let g:loaded_sourced_vim += 1 -func! sourced#something() +func sourced#something() endfunc +call sourced#something() diff --git a/src/version.c b/src/version.c index b67d3c3dac0003..e97b3906e52b46 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1398, /**/ 1397, /**/ From efa94447e85eacce62c1fcf6b63e7f3431e2cb1b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 8 Aug 2020 22:16:00 +0200 Subject: [PATCH 0113/1384] patch 8.2.1399: Vim9: may find imported item in wrong script Problem: Vim9: may find imported item in wrong script. Solution: When looking up script-local function use the embedded script ID. (issue #6644) --- src/proto/vim9compile.pro | 1 + src/testdir/test_vim9_script.vim | 25 +++++++++++++++++++++++++ src/userfunc.c | 15 ++++++++------- src/version.c | 2 ++ src/vim9compile.c | 11 +++++++++-- 5 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro index 14f9bbc7b2b14a..2de542b45eda5e 100644 --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -12,6 +12,7 @@ char *vartype_name(vartype_T type); char *type_name(type_T *type, char **tofree); int get_script_item_idx(int sid, char_u *name, int check_writable); imported_T *find_imported(char_u *name, size_t len, cctx_T *cctx); +imported_T *find_imported_in_script(char_u *name, size_t len, int sid); int vim9_comment_start(char_u *p); char_u *peek_next_line_from_context(cctx_T *cctx); char_u *next_line_from_context(cctx_T *cctx, int skip_comment); diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index eedce3201b2719..226d07e9ab9680 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1430,6 +1430,31 @@ def Test_import_in_filetype() &rtp = save_rtp enddef +def Test_use_import_in_mapping() + let lines =<< trim END + vim9script + export def Funcx() + g:result = 42 + enddef + END + writefile(lines, 'XsomeExport.vim') + lines =<< trim END + vim9script + import Funcx from './XsomeExport.vim' + nnoremap :call Funcx() + END + writefile(lines, 'Xmapscript.vim') + + source Xmapscript.vim + feedkeys("\", "xt") + assert_equal(42, g:result) + + unlet g:result + delete('XsomeExport.vim') + delete('Xmapscript.vim') + nunmap +enddef + def Test_vim9script_fails() CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:') CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:') diff --git a/src/userfunc.c b/src/userfunc.c index 10d1c3b77b9c31..7d3039a4595229 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -791,6 +791,7 @@ find_func_even_dead(char_u *name, int is_global, cctx_T *cctx) { int vim9script = in_vim9script(); char_u *after_script = NULL; + long sid = 0; if (vim9script) { @@ -800,18 +801,15 @@ find_func_even_dead(char_u *name, int is_global, cctx_T *cctx) return func; } - if (!vim9script - && name[0] == K_SPECIAL + if (name[0] == K_SPECIAL && name[1] == KS_EXTRA && name[2] == KE_SNR) { - long sid; - // Caller changes s: to 99_name. after_script = name + 3; sid = getdigits(&after_script); - if (sid == current_sctx.sc_sid && *after_script == '_') + if (*after_script == '_') ++after_script; else after_script = NULL; @@ -819,8 +817,11 @@ find_func_even_dead(char_u *name, int is_global, cctx_T *cctx) if (vim9script || after_script != NULL) { // Find imported function before global one. - imported = find_imported( - after_script == NULL ? name : after_script, 0, cctx); + if (after_script != NULL && sid != current_sctx.sc_sid) + imported = find_imported_in_script(after_script, 0, sid); + else + imported = find_imported(after_script == NULL + ? name : after_script, 0, cctx); if (imported != NULL && imported->imp_funcname != NULL) { hi = hash_find(&func_hashtab, imported->imp_funcname); diff --git a/src/version.c b/src/version.c index e97b3906e52b46..a85d54de03bbf9 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1399, /**/ 1398, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 5f76bc2c03c21c..a47d3d9a05c40e 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2548,12 +2548,10 @@ get_script_item_idx(int sid, char_u *name, int check_writable) imported_T * find_imported(char_u *name, size_t len, cctx_T *cctx) { - scriptitem_T *si; int idx; if (current_sctx.sc_sid <= 0) return NULL; - si = SCRIPT_ITEM(current_sctx.sc_sid); if (cctx != NULL) for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx) { @@ -2566,6 +2564,15 @@ find_imported(char_u *name, size_t len, cctx_T *cctx) return import; } + return find_imported_in_script(name, len, current_sctx.sc_sid); +} + + imported_T * +find_imported_in_script(char_u *name, size_t len, int sid) +{ + scriptitem_T *si = SCRIPT_ITEM(sid); + int idx; + for (idx = 0; idx < si->sn_imports.ga_len; ++idx) { imported_T *import = ((imported_T *)si->sn_imports.ga_data) + idx; From 730b24833952f0f4a9a17b7815b0d9f87c609eb8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 13:02:10 +0200 Subject: [PATCH 0114/1384] patch 8.2.1400: Vim9: test does not delete written files Problem: Vim9: test does not delete written files. Solution: Correct file names. --- src/testdir/test_vim9_script.vim | 14 +++++++------- src/version.c | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 226d07e9ab9680..6c04316bc6a784 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1395,7 +1395,7 @@ def Test_import_export_expr_map() nnoremap trigger g:Trigger() feedkeys('trigger', "xt") - delete('Xexport.vim') + delete('Xexport_that.vim') delete('Ximport.vim') nunmap trigger enddef @@ -1407,11 +1407,11 @@ def Test_import_in_filetype() vim9script export let That = 'yes' END - writefile(export_lines, 'ftplugin/Xexport_that.vim') + writefile(export_lines, 'ftplugin/Xexport_ft.vim') let import_lines =<< trim END vim9script - import That from './Xexport_that.vim' + import That from './Xexport_ft.vim' assert_equal('yes', That) g:did_load_mytpe = 1 END @@ -1425,7 +1425,7 @@ def Test_import_in_filetype() assert_equal(1, g:did_load_mytpe) quit! - delete('Xexport.vim') + delete('Xexport_ft.vim') delete('ftplugin', 'rf') &rtp = save_rtp enddef @@ -1484,13 +1484,13 @@ def Run_Test_import_fails_on_command_line() return 0 enddef END - writefile(export, 'Xexport.vim') + writefile(export, 'XexportCmd.vim') - let buf = RunVimInTerminal('-c "import Foo from ''./Xexport.vim''"', #{ + let buf = RunVimInTerminal('-c "import Foo from ''./XexportCmd.vim''"', #{ rows: 6, wait_for_ruler: 0}) WaitForAssert({-> assert_match('^E1094:', term_getline(buf, 5))}) - delete('Xexport.vim') + delete('XexportCmd.vim') StopVimInTerminal(buf) enddef diff --git a/src/version.c b/src/version.c index a85d54de03bbf9..20e8b36b810284 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1400, /**/ 1399, /**/ From 62a232506d06f6d1b3b7271801c907d6294dfe84 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 14:04:42 +0200 Subject: [PATCH 0115/1384] patch 8.2.1401: cannot jump to the last used tabpage Problem: Cannot jump to the last used tabpage. Solution: Add g and tabpagnr('#'). (Yegappan Lakshmanan, closes #6661, neovim #11626) --- runtime/doc/eval.txt | 9 +++++-- runtime/doc/index.txt | 4 ++++ runtime/doc/tabpage.txt | 2 ++ src/evalwindow.c | 3 +++ src/globals.h | 4 +++- src/normal.c | 13 +++++++++- src/proto/window.pro | 1 + src/testdir/test_tabpage.vim | 46 +++++++++++++++++++++++++++++++++++- src/version.c | 2 ++ src/window.c | 28 ++++++++++++++++++++++ 10 files changed, 107 insertions(+), 5 deletions(-) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 5bb763a4a474aa..c579ed2faae8f4 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -10357,8 +10357,13 @@ tabpagebuflist([{arg}]) *tabpagebuflist()* tabpagenr([{arg}]) *tabpagenr()* The result is a Number, which is the number of the current tab page. The first tab page has number 1. - When the optional argument is "$", the number of the last tab - page is returned (the tab page count). + + The optional argument {arg} supports the following values: + $ the number of the last tab page (the tab page + count). + # the number of the last accessed tab page + (where |g| goes to). if there is no + previous tab page 0 is returned. The number can be used with the |:tab| command. diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index 83c6c176c874c8..ed6916f62e1b37 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -440,6 +440,7 @@ tag char note action in Normal mode ~ || ":ta" to the keyword at the mouse click || 1 same as "w" || same as "CTRL-T" +|| same as "g" || ["x] 2 same as "x" |N| {count} remove the last digit from {count} || 1 same as "j" @@ -587,6 +588,8 @@ tag command action in Normal mode ~ following the file name. |CTRL-W_gt| CTRL-W g t same as `gt`: go to next tab page |CTRL-W_gT| CTRL-W g T same as `gT`: go to previous tab page +|CTRL-W_g| CTRL-W g same as |g|: go to last accessed tab + page. |CTRL-W_h| CTRL-W h go to Nth left window (stop at first window) |CTRL-W_i| CTRL-W i split window and jump to declaration of identifier under the cursor @@ -805,6 +808,7 @@ tag char note action in Normal mode ~ |g| g same as g same as |g| g same as +|g| g go to the last accessed tab page. |g| g 1 same as "gk" ============================================================================== diff --git a/runtime/doc/tabpage.txt b/runtime/doc/tabpage.txt index 75070b5fe7c19d..1d8c2082f26772 100644 --- a/runtime/doc/tabpage.txt +++ b/runtime/doc/tabpage.txt @@ -221,6 +221,8 @@ gT Go to the previous tab page. Wraps around from the first one *:tabl* *:tablast* :tabl[ast] Go to the last tab page. + *g* *CTRL-W_g* ** +g Go to the last accessed tab page. Other commands: *:tabs* diff --git a/src/evalwindow.c b/src/evalwindow.c index 0b3052c241ef5a..b50776d74d8b04 100644 --- a/src/evalwindow.c +++ b/src/evalwindow.c @@ -616,6 +616,9 @@ f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv) { if (STRCMP(arg, "$") == 0) nr = tabpage_index(NULL) - 1; + else if (STRCMP(arg, "#") == 0) + nr = valid_tabpage(lastused_tabpage) ? + tabpage_index(lastused_tabpage) : 0; else semsg(_(e_invexpr2), arg); } diff --git a/src/globals.h b/src/globals.h index cc01ac2508d579..72b8a1e4604ebe 100644 --- a/src/globals.h +++ b/src/globals.h @@ -725,10 +725,12 @@ EXTERN frame_T *topframe; // top of the window frame tree /* * Tab pages are alternative topframes. "first_tabpage" points to the first - * one in the list, "curtab" is the current one. + * one in the list, "curtab" is the current one. "lastused_tabpage" is the + * last used one. */ EXTERN tabpage_T *first_tabpage; EXTERN tabpage_T *curtab; +EXTERN tabpage_T *lastused_tabpage; EXTERN int redraw_tabline INIT(= FALSE); // need to redraw tabline /* diff --git a/src/normal.c b/src/normal.c index dd79a43aac51c4..cb8e736368dc7e 100644 --- a/src/normal.c +++ b/src/normal.c @@ -5442,7 +5442,7 @@ nv_gomark(cmdarg_T *cap) } /* - * Handle CTRL-O, CTRL-I, "g;" and "g," commands. + * Handle CTRL-O, CTRL-I, "g;", "g," and "CTRL-Tab" commands. */ static void nv_pcmark(cmdarg_T *cap) @@ -5456,6 +5456,12 @@ nv_pcmark(cmdarg_T *cap) if (!checkclearopq(cap->oap)) { + if (cap->cmdchar == TAB && mod_mask == MOD_MASK_CTRL) + { + if (goto_tabpage_lastused() == FAIL) + clearopbeep(cap->oap); + return; + } if (cap->cmdchar == 'g') pos = movechangelist((int)cap->count1); else @@ -6310,6 +6316,11 @@ nv_g_cmd(cmdarg_T *cap) goto_tabpage(-(int)cap->count1); break; + case TAB: + if (!checkclearop(oap) && goto_tabpage_lastused() == FAIL) + clearopbeep(oap); + break; + case '+': case '-': // "g+" and "g-": undo or redo along the timeline if (!checkclearopq(oap)) diff --git a/src/proto/window.pro b/src/proto/window.pro index ab62c0a096f322..4c9bddd2814478 100644 --- a/src/proto/window.pro +++ b/src/proto/window.pro @@ -32,6 +32,7 @@ tabpage_T *find_tabpage(int n); int tabpage_index(tabpage_T *ftp); void goto_tabpage(int n); void goto_tabpage_tp(tabpage_T *tp, int trigger_enter_autocmds, int trigger_leave_autocmds); +int goto_tabpage_lastused(void); void goto_tabpage_win(tabpage_T *tp, win_T *wp); void tabpage_move(int nr); void win_goto(win_T *wp); diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim index bbcafa8eb6fd34..67469718f2bb58 100644 --- a/src/testdir/test_tabpage.vim +++ b/src/testdir/test_tabpage.vim @@ -130,7 +130,7 @@ function Test_tabpage() 1tabmove call assert_equal(2, tabpagenr()) - call assert_fails('let t = tabpagenr("#")', 'E15:') + call assert_fails('let t = tabpagenr("@")', 'E15:') call assert_equal(0, tabpagewinnr(-1)) call assert_fails("99tabmove", 'E16:') call assert_fails("+99tabmove", 'E16:') @@ -777,4 +777,48 @@ func Test_tabpage_close_on_switch() %bw! endfunc +" Test for jumping to last accessed tabpage +func Test_lastused_tabpage() + tabonly! + call assert_equal(0, tabpagenr('#')) + call assert_beeps('call feedkeys("g\", "xt")') + call assert_beeps('call feedkeys("\", "xt")') + call assert_beeps('call feedkeys("\g\", "xt")') + + " open four tab pages + tabnew + tabnew + tabnew + + 2tabnext + + " Test for g + call assert_equal(4, tabpagenr('#')) + call feedkeys("g\", "xt") + call assert_equal(4, tabpagenr()) + call assert_equal(2, tabpagenr('#')) + + " Test for + call feedkeys("\", "xt") + call assert_equal(2, tabpagenr()) + call assert_equal(4, tabpagenr('#')) + + " Test for g + call feedkeys("\g\", "xt") + call assert_equal(4, tabpagenr()) + call assert_equal(2, tabpagenr('#')) + + " Try to jump to a closed tab page + tabclose 2 + call assert_equal(0, tabpagenr('#')) + call feedkeys("g\", "xt") + call assert_equal(3, tabpagenr()) + call feedkeys("\", "xt") + call assert_equal(3, tabpagenr()) + call feedkeys("\g\", "xt") + call assert_equal(3, tabpagenr()) + + tabclose! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 20e8b36b810284..15f4c061d26f98 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1401, /**/ 1400, /**/ diff --git a/src/window.c b/src/window.c index 4b2ff4b5231736..7d8122efdd00eb 100644 --- a/src/window.c +++ b/src/window.c @@ -627,6 +627,11 @@ do_window( goto_tabpage(-(int)Prenum1); break; + case TAB: // CTRL-W g: go to last used tab page + if (goto_tabpage_lastused() == FAIL) + beep_flush(); + break; + default: beep_flush(); break; @@ -3809,6 +3814,9 @@ free_tabpage(tabpage_T *tp) unref_var_dict(tp->tp_vars); #endif + if (tp == lastused_tabpage) + lastused_tabpage = NULL; + vim_free(tp->tp_localdir); vim_free(tp->tp_prevdir); @@ -3883,6 +3891,8 @@ win_new_tabpage(int after) newtp->tp_topframe = topframe; last_status(FALSE); + lastused_tabpage = tp; + #if defined(FEAT_GUI) // When 'guioptions' includes 'L' or 'R' may have to remove or add // scrollbars. Have to update them anyway. @@ -4118,6 +4128,7 @@ enter_tabpage( int row; int old_off = tp->tp_firstwin->w_winrow; win_T *next_prevwin = tp->tp_prevwin; + tabpage_T *last_tab = curtab; curtab = tp; firstwin = tp->tp_firstwin; @@ -4160,6 +4171,8 @@ enter_tabpage( if (curtab->tp_old_Columns != Columns && starting == 0) shell_new_columns(); // update window widths + lastused_tabpage = last_tab; + #if defined(FEAT_GUI) // When 'guioptions' includes 'L' or 'R' may have to remove or add // scrollbars. Have to update them anyway. @@ -4277,6 +4290,21 @@ goto_tabpage_tp( } } +/* + * Go to the last accessed tab page, if there is one. + * Return OK or FAIL + */ + int +goto_tabpage_lastused(void) +{ + if (valid_tabpage(lastused_tabpage)) + { + goto_tabpage_tp(lastused_tabpage, TRUE, TRUE); + return OK; + } + return FAIL; +} + /* * Enter window "wp" in tab page "tp". * Also updates the GUI tab. From 94f6c06ac54401ea34a07f8c45242f11bd1e1e3a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 14:07:52 +0200 Subject: [PATCH 0116/1384] patch 8.2.1402: s390x tests always fail Problem: s390x tests always fail. Solution: Temporarily disable s390x tests. --- .travis.yml | 13 +++++++------ src/version.c | 2 ++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index d199efb5735f41..a4c628740418e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -208,12 +208,13 @@ jobs: env: - *normal - *shadowopt - - <<: *linux - arch: s390x - name: huge/gcc-s390x - compiler: gcc - env: *linux-huge - services: [] + # Temporarily disabled, always fails + #- <<: *linux + # arch: s390x + # name: huge/gcc-s390x + # compiler: gcc + # env: *linux-huge + # services: [] - <<: *linux arch: arm64 name: huge/gcc-arm64 diff --git a/src/version.c b/src/version.c index 15f4c061d26f98..697a47cf9ce8d2 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1402, /**/ 1401, /**/ From 3896a105eb3697b1a399255ac31c742c8840bd69 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 14:33:55 +0200 Subject: [PATCH 0117/1384] patch 8.2.1403: Vim9: Vim highlighting may fail in cmdline window Problem: Vim9: Vim highlighting fails in cmdline window if it uses Vim9 commands. Solution: Allow using :vim9script, :import and :export while in the cmdline window. (closes #6656) --- src/ex_cmds.h | 6 +++--- src/testdir/test_vim9_script.vim | 31 +++++++++++++++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/ex_cmds.h b/src/ex_cmds.h index c65b956ee45c17..508ecb87043846 100644 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -572,7 +572,7 @@ EXCMD(CMD_exit, "exit", ex_exit, EX_RANGE|EX_WHOLEFOLD|EX_BANG|EX_FILE1|EX_ARGOPT|EX_DFLALL|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), EXCMD(CMD_export, "export", ex_export, - EX_EXTRA|EX_NOTRLCOM|EX_LOCK_OK, + EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_exusage, "exusage", ex_exusage, EX_TRLBAR, @@ -698,7 +698,7 @@ EXCMD(CMD_imenu, "imenu", ex_menu, EX_RANGE|EX_ZEROR|EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, ADDR_OTHER), EXCMD(CMD_import, "import", ex_import, - EX_EXTRA|EX_NOTRLCOM|EX_LOCK_OK, + EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_inoremap, "inoremap", ex_map, EX_EXTRA|EX_TRLBAR|EX_NOTRLCOM|EX_CTRLV|EX_CMDWIN|EX_LOCK_OK, @@ -1670,7 +1670,7 @@ EXCMD(CMD_vimgrepadd, "vimgrepadd", ex_vimgrep, EX_RANGE|EX_BANG|EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_TRLBAR|EX_XFILE, ADDR_OTHER), EXCMD(CMD_vim9script, "vim9script", ex_vim9script, - EX_LOCK_OK, + EX_CMDWIN|EX_LOCK_OK, ADDR_NONE), EXCMD(CMD_viusage, "viusage", ex_viusage, EX_TRLBAR, diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 6c04316bc6a784..2f7d5654d10833 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -3009,6 +3009,37 @@ def Test_vim9_autoload() &rtp = save_rtp enddef +def Test_cmdline_win() + # if the Vim syntax highlighting uses Vim9 constructs they can be used from + # the command line window. + mkdir('rtp/syntax', 'p') + let export_lines =<< trim END + vim9script + export let That = 'yes' + END + writefile(export_lines, 'rtp/syntax/Xexport.vim') + let import_lines =<< trim END + vim9script + import That from './Xexport.vim' + END + writefile(import_lines, 'rtp/syntax/vim.vim') + let save_rtp = &rtp + &rtp = getcwd() .. '/rtp' .. ',' .. &rtp + syntax on + augroup CmdWin + autocmd CmdwinEnter * g:got_there = 'yes' + augroup END + # this will open and also close the cmdline window + feedkeys('q:', 'xt') + assert_equal('yes', g:got_there) + + augroup CmdWin + au! + augroup END + &rtp = save_rtp + delete('rtp', 'rf') +enddef + " Keep this last, it messes up highlighting. def Test_substitute_cmd() new diff --git a/src/version.c b/src/version.c index 697a47cf9ce8d2..ddd4354e6cb09a 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1403, /**/ 1402, /**/ From b3ca98240761d8f320c5a49e077d1aac6496bb21 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 14:43:58 +0200 Subject: [PATCH 0118/1384] patch 8.2.1404: Vim9: script test fails in the GUI Problem: Vim9: script test fails in the GUI. Solution: Use another key to map. Improve cleanup. --- src/testdir/test_vim9_script.vim | 19 +++++++++++++------ src/version.c | 2 ++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 2f7d5654d10833..d30511c394d623 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1117,6 +1117,11 @@ let s:export_script_lines =<< trim END enddef END +def Undo_export_script_lines() + unlet g:result + unlet g:localname +enddef + def Test_vim9_import_export() let import_script_lines =<< trim END vim9script @@ -1155,8 +1160,7 @@ def Test_vim9_import_export() assert_equal('John Doe', g:imported_name_appended) assert_false(exists('g:name')) - unlet g:result - unlet g:localname + Undo_export_script_lines() unlet g:imported unlet g:imported_added unlet g:imported_later @@ -1441,18 +1445,18 @@ def Test_use_import_in_mapping() lines =<< trim END vim9script import Funcx from './XsomeExport.vim' - nnoremap :call Funcx() + nnoremap :call Funcx() END writefile(lines, 'Xmapscript.vim') source Xmapscript.vim - feedkeys("\", "xt") + feedkeys("\", "xt") assert_equal(42, g:result) unlet g:result delete('XsomeExport.vim') delete('Xmapscript.vim') - nunmap + nunmap enddef def Test_vim9script_fails() @@ -1697,6 +1701,8 @@ def Test_import_absolute() '4 LOADSCRIPT exported from .*Xexport_abs.vim.*' .. '5 STOREG g:imported_after.*', g:import_disassembled) + + Undo_export_script_lines() unlet g:imported_abs unlet g:import_disassembled @@ -1720,8 +1726,9 @@ def Test_import_rtp() &rtp = save_rtp assert_equal(9876, g:imported_rtp) - unlet g:imported_rtp + Undo_export_script_lines() + unlet g:imported_rtp delete('Ximport_rtp.vim') delete('import', 'rf') enddef diff --git a/src/version.c b/src/version.c index ddd4354e6cb09a..4adf44f882e843 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1404, /**/ 1403, /**/ From a7cc9e697b9140da66a09f71cdf839d08e32f5fb Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 15:25:14 +0200 Subject: [PATCH 0119/1384] patch 8.2.1405: Vim9: vim9compile.c is getting too big Problem: Vim9: vim9compile.c is getting too big. Solution: Split off type code to vim9type.c. --- Filelist | 2 + src/Make_cyg_ming.mak | 3 + src/Make_mvc.mak | 4 + src/Makefile | 10 + src/proto.h | 1 + src/proto/vim9compile.pro | 9 - src/proto/vim9type.pro | 19 + src/version.c | 2 + src/vim9compile.c | 892 ------------------------------------- src/vim9type.c | 915 ++++++++++++++++++++++++++++++++++++++ 10 files changed, 956 insertions(+), 901 deletions(-) create mode 100644 src/proto/vim9type.pro create mode 100644 src/vim9type.c diff --git a/Filelist b/Filelist index cc90c4d04c994b..37f1d8c77a927c 100644 --- a/Filelist +++ b/Filelist @@ -149,6 +149,7 @@ SRC_ALL = \ src/vim9compile.c \ src/vim9execute.c \ src/vim9script.c \ + src/vim9type.c \ src/viminfo.c \ src/winclip.c \ src/window.c \ @@ -304,6 +305,7 @@ SRC_ALL = \ src/proto/vim9compile.pro \ src/proto/vim9execute.pro \ src/proto/vim9script.pro \ + src/proto/vim9type.pro \ src/proto/viminfo.pro \ src/proto/winclip.pro \ src/proto/window.pro \ diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak index 1c519d9b5e53e7..d8b4db16c1a0e5 100644 --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -806,6 +806,7 @@ OBJ = \ $(OUTDIR)/vim9compile.o \ $(OUTDIR)/vim9execute.o \ $(OUTDIR)/vim9script.o \ + $(OUTDIR)/vim9type.o \ $(OUTDIR)/viminfo.o \ $(OUTDIR)/winclip.o \ $(OUTDIR)/window.o @@ -1177,6 +1178,8 @@ $(OUTDIR)/vim9execute.o: vim9execute.c $(INCL) version.h $(OUTDIR)/vim9script.o: vim9script.c $(INCL) version.h +$(OUTDIR)/vim9type.o: vim9type.c $(INCL) version.h + $(OUTDIR)/viminfo.o: viminfo.c $(INCL) version.h $(OUTDIR)/gui_dwrite.o: gui_dwrite.cpp gui_dwrite.h diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index d66ff717a595c3..9c3deb62d35c15 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -825,6 +825,7 @@ OBJ = \ $(OUTDIR)\vim9compile.obj \ $(OUTDIR)\vim9execute.obj \ $(OUTDIR)\vim9script.obj \ + $(OUTDIR)\vim9type.obj \ $(OUTDIR)\viminfo.obj \ $(OUTDIR)\winclip.obj \ $(OUTDIR)\window.obj \ @@ -1799,6 +1800,8 @@ $(OUTDIR)/vim9execute.obj: $(OUTDIR) vim9execute.c $(INCL) $(OUTDIR)/vim9script.obj: $(OUTDIR) vim9script.c $(INCL) +$(OUTDIR)/vim9type.obj: $(OUTDIR) vim9type.c $(INCL) + $(OUTDIR)/viminfo.obj: $(OUTDIR) viminfo.c $(INCL) version.h $(OUTDIR)/window.obj: $(OUTDIR) window.c $(INCL) @@ -1998,6 +2001,7 @@ proto.h: \ proto/vim9compile.pro \ proto/vim9execute.pro \ proto/vim9script.pro \ + proto/vim9type.pro \ proto/viminfo.pro \ proto/window.pro \ $(SOUND_PRO) \ diff --git a/src/Makefile b/src/Makefile index 148126d1c9677f..55c366472782d3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1702,6 +1702,7 @@ BASIC_SRC = \ vim9compile.c \ vim9execute.c \ vim9script.c \ + vim9type.c \ viminfo.c \ window.c \ bufwrite.c \ @@ -1851,6 +1852,7 @@ OBJ_COMMON = \ objects/vim9compile.o \ objects/vim9execute.o \ objects/vim9script.o \ + objects/vim9type.o \ objects/viminfo.o \ objects/window.o \ objects/bufwrite.o \ @@ -2032,6 +2034,7 @@ PRO_AUTO = \ vim9compile.pro \ vim9execute.pro \ vim9script.pro \ + vim9type.pro \ viminfo.pro \ window.pro \ $(ALL_GUI_PRO) \ @@ -3563,6 +3566,9 @@ objects/vim9execute.o: vim9execute.c objects/vim9script.o: vim9script.c $(CCC) -o $@ vim9script.c +objects/vim9type.o: vim9type.c + $(CCC) -o $@ vim9type.c + objects/viminfo.o: viminfo.c $(CCC) -o $@ viminfo.c @@ -4192,6 +4198,10 @@ objects/vim9script.o: vim9script.c vim.h protodef.h auto/config.h feature.h \ os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ proto.h globals.h vim9.h +objects/vim9type.o: vim9type.c vim.h protodef.h auto/config.h feature.h \ + os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ + proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ + proto.h globals.h vim9.h objects/viminfo.o: viminfo.c vim.h protodef.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ diff --git a/src/proto.h b/src/proto.h index 95fd81ac96c3ae..e894987ba30c7d 100644 --- a/src/proto.h +++ b/src/proto.h @@ -237,6 +237,7 @@ void mbyte_im_set_active(int active_arg); # include "vim9compile.pro" # include "vim9execute.pro" # include "vim9script.pro" +# include "vim9type.pro" # endif # include "window.pro" diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro index 2de542b45eda5e..80d0b25a27afe3 100644 --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -1,15 +1,6 @@ /* vim9compile.c */ int check_defined(char_u *p, size_t len, cctx_T *cctx); -void clear_type_list(garray_T *gap); -type_T *typval2type(typval_T *tv, garray_T *type_gap); -type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap); -int check_typval_type(type_T *expected, typval_T *actual_tv); -int check_type(type_T *expected, type_T *actual, int give_msg); int check_compare_types(exptype_T type, typval_T *tv1, typval_T *tv2); -char_u *skip_type(char_u *start, int optional); -type_T *parse_type(char_u **arg, garray_T *type_gap); -char *vartype_name(vartype_T type); -char *type_name(type_T *type, char **tofree); int get_script_item_idx(int sid, char_u *name, int check_writable); imported_T *find_imported(char_u *name, size_t len, cctx_T *cctx); imported_T *find_imported_in_script(char_u *name, size_t len, int sid); diff --git a/src/proto/vim9type.pro b/src/proto/vim9type.pro new file mode 100644 index 00000000000000..5c7ba03ce66d5c --- /dev/null +++ b/src/proto/vim9type.pro @@ -0,0 +1,19 @@ +/* vim9type.c */ +void clear_type_list(garray_T *gap); +type_T *get_list_type(type_T *member_type, garray_T *type_gap); +type_T *get_dict_type(type_T *member_type, garray_T *type_gap); +type_T *alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap); +type_T *get_func_type(type_T *ret_type, int argcount, garray_T *type_gap); +int func_type_add_arg_types(type_T *functype, int argcount, garray_T *type_gap); +type_T *typval2type(typval_T *tv, garray_T *type_gap); +type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap); +int check_typval_type(type_T *expected, typval_T *actual_tv); +void type_mismatch(type_T *expected, type_T *actual); +void arg_type_mismatch(type_T *expected, type_T *actual, int argidx); +int check_type(type_T *expected, type_T *actual, int give_msg); +char_u *skip_type(char_u *start, int optional); +type_T *parse_type(char_u **arg, garray_T *type_gap); +void common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap); +char *vartype_name(vartype_T type); +char *type_name(type_T *type, char **tofree); +/* vim: set ft=c : */ diff --git a/src/version.c b/src/version.c index 4adf44f882e843..168ee023aecc8a 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1405, /**/ 1404, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index a47d3d9a05c40e..e23dd7a31b0244 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -151,7 +151,6 @@ static char e_namespace[] = N_("E1075: Namespace not supported: %s"); static char e_unknown_var[] = N_("E1089: unknown variable: %s"); static void delete_def_function_contents(dfunc_T *dfunc); -static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx); /* * Lookup variable "name" in the local scope and return it. @@ -310,374 +309,6 @@ check_defined(char_u *p, size_t len, cctx_T *cctx) return OK; } -/* - * Allocate memory for a type_T and add the pointer to type_gap, so that it can - * be freed later. - */ - static type_T * -alloc_type(garray_T *type_gap) -{ - type_T *type; - - if (ga_grow(type_gap, 1) == FAIL) - return NULL; - type = ALLOC_CLEAR_ONE(type_T); - if (type != NULL) - { - ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type; - ++type_gap->ga_len; - } - return type; -} - - void -clear_type_list(garray_T *gap) -{ - while (gap->ga_len > 0) - vim_free(((type_T **)gap->ga_data)[--gap->ga_len]); - ga_clear(gap); -} - - static type_T * -get_list_type(type_T *member_type, garray_T *type_gap) -{ - type_T *type; - - // recognize commonly used types - if (member_type->tt_type == VAR_ANY) - return &t_list_any; - if (member_type->tt_type == VAR_VOID - || member_type->tt_type == VAR_UNKNOWN) - return &t_list_empty; - if (member_type->tt_type == VAR_BOOL) - return &t_list_bool; - if (member_type->tt_type == VAR_NUMBER) - return &t_list_number; - if (member_type->tt_type == VAR_STRING) - return &t_list_string; - - // Not a common type, create a new entry. - type = alloc_type(type_gap); - if (type == NULL) - return &t_any; - type->tt_type = VAR_LIST; - type->tt_member = member_type; - type->tt_argcount = 0; - type->tt_args = NULL; - return type; -} - - static type_T * -get_dict_type(type_T *member_type, garray_T *type_gap) -{ - type_T *type; - - // recognize commonly used types - if (member_type->tt_type == VAR_ANY) - return &t_dict_any; - if (member_type->tt_type == VAR_VOID - || member_type->tt_type == VAR_UNKNOWN) - return &t_dict_empty; - if (member_type->tt_type == VAR_BOOL) - return &t_dict_bool; - if (member_type->tt_type == VAR_NUMBER) - return &t_dict_number; - if (member_type->tt_type == VAR_STRING) - return &t_dict_string; - - // Not a common type, create a new entry. - type = alloc_type(type_gap); - if (type == NULL) - return &t_any; - type->tt_type = VAR_DICT; - type->tt_member = member_type; - type->tt_argcount = 0; - type->tt_args = NULL; - return type; -} - -/* - * Allocate a new type for a function. - */ - static type_T * -alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap) -{ - type_T *type = alloc_type(type_gap); - - if (type == NULL) - return &t_any; - type->tt_type = VAR_FUNC; - type->tt_member = ret_type; - type->tt_argcount = argcount; - type->tt_args = NULL; - return type; -} - -/* - * Get a function type, based on the return type "ret_type". - * If "argcount" is -1 or 0 a predefined type can be used. - * If "argcount" > 0 always create a new type, so that arguments can be added. - */ - static type_T * -get_func_type(type_T *ret_type, int argcount, garray_T *type_gap) -{ - // recognize commonly used types - if (argcount <= 0) - { - if (ret_type == &t_unknown) - { - // (argcount == 0) is not possible - return &t_func_unknown; - } - if (ret_type == &t_void) - { - if (argcount == 0) - return &t_func_0_void; - else - return &t_func_void; - } - if (ret_type == &t_any) - { - if (argcount == 0) - return &t_func_0_any; - else - return &t_func_any; - } - if (ret_type == &t_number) - { - if (argcount == 0) - return &t_func_0_number; - else - return &t_func_number; - } - if (ret_type == &t_string) - { - if (argcount == 0) - return &t_func_0_string; - else - return &t_func_string; - } - } - - return alloc_func_type(ret_type, argcount, type_gap); -} - -/* - * For a function type, reserve space for "argcount" argument types (including - * vararg). - */ - static int -func_type_add_arg_types( - type_T *functype, - int argcount, - garray_T *type_gap) -{ - // To make it easy to free the space needed for the argument types, add the - // pointer to type_gap. - if (ga_grow(type_gap, 1) == FAIL) - return FAIL; - functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount); - if (functype->tt_args == NULL) - return FAIL; - ((type_T **)type_gap->ga_data)[type_gap->ga_len] = - (void *)functype->tt_args; - ++type_gap->ga_len; - return OK; -} - -/* - * Get a type_T for a typval_T. - * "type_list" is used to temporarily create types in. - */ - type_T * -typval2type(typval_T *tv, garray_T *type_gap) -{ - type_T *actual; - type_T *member_type; - - if (tv->v_type == VAR_NUMBER) - return &t_number; - if (tv->v_type == VAR_BOOL) - return &t_bool; // not used - if (tv->v_type == VAR_STRING) - return &t_string; - - if (tv->v_type == VAR_LIST) - { - if (tv->vval.v_list == NULL || tv->vval.v_list->lv_first == NULL) - return &t_list_empty; - - // Use the type of the first member, it is the most specific. - member_type = typval2type(&tv->vval.v_list->lv_first->li_tv, type_gap); - return get_list_type(member_type, type_gap); - } - - if (tv->v_type == VAR_DICT) - { - dict_iterator_T iter; - typval_T *value; - - if (tv->vval.v_dict == NULL - || tv->vval.v_dict->dv_hashtab.ht_used == 0) - return &t_dict_empty; - - // Use the type of the first value, it is the most specific. - dict_iterate_start(tv, &iter); - dict_iterate_next(&iter, &value); - member_type = typval2type(value, type_gap); - return get_dict_type(member_type, type_gap); - } - - if (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) - { - char_u *name = NULL; - ufunc_T *ufunc = NULL; - - if (tv->v_type == VAR_PARTIAL) - { - if (tv->vval.v_partial->pt_func != NULL) - ufunc = tv->vval.v_partial->pt_func; - else - name = tv->vval.v_partial->pt_name; - } - else - name = tv->vval.v_string; - if (name != NULL) - // TODO: how about a builtin function? - ufunc = find_func(name, FALSE, NULL); - if (ufunc != NULL) - { - // May need to get the argument types from default values by - // compiling the function. - if (ufunc->uf_def_status == UF_TO_BE_COMPILED - && compile_def_function(ufunc, TRUE, NULL) == FAIL) - return NULL; - if (ufunc->uf_func_type != NULL) - return ufunc->uf_func_type; - } - } - - actual = alloc_type(type_gap); - if (actual == NULL) - return NULL; - actual->tt_type = tv->v_type; - actual->tt_member = &t_any; - - return actual; -} - -/* - * Get a type_T for a typval_T, used for v: variables. - * "type_list" is used to temporarily create types in. - */ - type_T * -typval2type_vimvar(typval_T *tv, garray_T *type_gap) -{ - if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles - return &t_list_string; - if (tv->v_type == VAR_DICT) // e.g. for v:completed_item - return &t_dict_any; - return typval2type(tv, type_gap); -} - - -/* - * Return FAIL if "expected" and "actual" don't match. - */ - int -check_typval_type(type_T *expected, typval_T *actual_tv) -{ - garray_T type_list; - type_T *actual_type; - int res = FAIL; - - ga_init2(&type_list, sizeof(type_T *), 10); - actual_type = typval2type(actual_tv, &type_list); - if (actual_type != NULL) - res = check_type(expected, actual_type, TRUE); - clear_type_list(&type_list); - return res; -} - - static void -type_mismatch(type_T *expected, type_T *actual) -{ - char *tofree1, *tofree2; - - semsg(_("E1013: type mismatch, expected %s but got %s"), - type_name(expected, &tofree1), type_name(actual, &tofree2)); - vim_free(tofree1); - vim_free(tofree2); -} - - static void -arg_type_mismatch(type_T *expected, type_T *actual, int argidx) -{ - char *tofree1, *tofree2; - - semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"), - argidx, - type_name(expected, &tofree1), type_name(actual, &tofree2)); - vim_free(tofree1); - vim_free(tofree2); -} - -/* - * Check if the expected and actual types match. - * Does not allow for assigning "any" to a specific type. - */ - int -check_type(type_T *expected, type_T *actual, int give_msg) -{ - int ret = OK; - - // When expected is "unknown" we accept any actual type. - // When expected is "any" we accept any actual type except "void". - if (expected->tt_type != VAR_UNKNOWN - && !(expected->tt_type == VAR_ANY && actual->tt_type != VAR_VOID)) - - { - if (expected->tt_type != actual->tt_type) - { - if (give_msg) - type_mismatch(expected, actual); - return FAIL; - } - if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST) - { - // "unknown" is used for an empty list or dict - if (actual->tt_member != &t_unknown) - ret = check_type(expected->tt_member, actual->tt_member, FALSE); - } - else if (expected->tt_type == VAR_FUNC) - { - if (expected->tt_member != &t_unknown) - ret = check_type(expected->tt_member, actual->tt_member, FALSE); - if (ret == OK && expected->tt_argcount != -1 - && (actual->tt_argcount < expected->tt_min_argcount - || actual->tt_argcount > expected->tt_argcount)) - ret = FAIL; - if (expected->tt_args != NULL && actual->tt_args != NULL) - { - int i; - - for (i = 0; i < expected->tt_argcount; ++i) - // Allow for using "any" argument type, lambda's have them. - if (actual->tt_args[i] != &t_any && check_type( - expected->tt_args[i], actual->tt_args[i], FALSE) - == FAIL) - { - ret = FAIL; - break; - } - } - } - if (ret == FAIL && give_msg) - type_mismatch(expected, actual); - } - return ret; -} - ///////////////////////////////////////////////////////////////////// // Following generate_ functions expect the caller to call ga_grow(). @@ -1981,529 +1612,6 @@ free_locals(cctx_T *cctx) ga_clear(&cctx->ctx_locals); } -/* - * Skip over a type definition and return a pointer to just after it. - * When "optional" is TRUE then a leading "?" is accepted. - */ - char_u * -skip_type(char_u *start, int optional) -{ - char_u *p = start; - - if (optional && *p == '?') - ++p; - while (ASCII_ISALNUM(*p) || *p == '_') - ++p; - - // Skip over ""; this is permissive about white space. - if (*skipwhite(p) == '<') - { - p = skipwhite(p); - p = skip_type(skipwhite(p + 1), FALSE); - p = skipwhite(p); - if (*p == '>') - ++p; - } - else if ((*p == '(' || (*p == ':' && VIM_ISWHITE(p[1]))) - && STRNCMP("func", start, 4) == 0) - { - if (*p == '(') - { - // handle func(args): type - ++p; - while (*p != ')' && *p != NUL) - { - char_u *sp = p; - - if (STRNCMP(p, "...", 3) == 0) - p += 3; - p = skip_type(p, TRUE); - if (p == sp) - return p; // syntax error - if (*p == ',') - p = skipwhite(p + 1); - } - if (*p == ')') - { - if (p[1] == ':') - p = skip_type(skipwhite(p + 2), FALSE); - else - ++p; - } - } - else - { - // handle func: return_type - p = skip_type(skipwhite(p + 1), FALSE); - } - } - - return p; -} - -/* - * Parse the member type: "" and return "type" with the member set. - * Use "type_gap" if a new type needs to be added. - * Returns NULL in case of failure. - */ - static type_T * -parse_type_member(char_u **arg, type_T *type, garray_T *type_gap) -{ - type_T *member_type; - int prev_called_emsg = called_emsg; - - if (**arg != '<') - { - if (*skipwhite(*arg) == '<') - semsg(_(e_no_white_before), "<"); - else - emsg(_("E1008: Missing ")); - return type; - } - *arg = skipwhite(*arg + 1); - - member_type = parse_type(arg, type_gap); - - *arg = skipwhite(*arg); - if (**arg != '>' && called_emsg == prev_called_emsg) - { - emsg(_("E1009: Missing > after type")); - return type; - } - ++*arg; - - if (type->tt_type == VAR_LIST) - return get_list_type(member_type, type_gap); - return get_dict_type(member_type, type_gap); -} - -/* - * Parse a type at "arg" and advance over it. - * Return &t_any for failure. - */ - type_T * -parse_type(char_u **arg, garray_T *type_gap) -{ - char_u *p = *arg; - size_t len; - - // skip over the first word - while (ASCII_ISALNUM(*p) || *p == '_') - ++p; - len = p - *arg; - - switch (**arg) - { - case 'a': - if (len == 3 && STRNCMP(*arg, "any", len) == 0) - { - *arg += len; - return &t_any; - } - break; - case 'b': - if (len == 4 && STRNCMP(*arg, "bool", len) == 0) - { - *arg += len; - return &t_bool; - } - if (len == 4 && STRNCMP(*arg, "blob", len) == 0) - { - *arg += len; - return &t_blob; - } - break; - case 'c': - if (len == 7 && STRNCMP(*arg, "channel", len) == 0) - { - *arg += len; - return &t_channel; - } - break; - case 'd': - if (len == 4 && STRNCMP(*arg, "dict", len) == 0) - { - *arg += len; - return parse_type_member(arg, &t_dict_any, type_gap); - } - break; - case 'f': - if (len == 5 && STRNCMP(*arg, "float", len) == 0) - { -#ifdef FEAT_FLOAT - *arg += len; - return &t_float; -#else - emsg(_("E1076: This Vim is not compiled with float support")); - return &t_any; -#endif - } - if (len == 4 && STRNCMP(*arg, "func", len) == 0) - { - type_T *type; - type_T *ret_type = &t_unknown; - int argcount = -1; - int flags = 0; - int first_optional = -1; - type_T *arg_type[MAX_FUNC_ARGS + 1]; - - // func({type}, ...{type}): {type} - *arg += len; - if (**arg == '(') - { - // "func" may or may not return a value, "func()" does - // not return a value. - ret_type = &t_void; - - p = ++*arg; - argcount = 0; - while (*p != NUL && *p != ')') - { - if (*p == '?') - { - if (first_optional == -1) - first_optional = argcount; - ++p; - } - else if (STRNCMP(p, "...", 3) == 0) - { - flags |= TTFLAG_VARARGS; - p += 3; - } - else if (first_optional != -1) - { - emsg(_("E1007: mandatory argument after optional argument")); - return &t_any; - } - - arg_type[argcount++] = parse_type(&p, type_gap); - - // Nothing comes after "...{type}". - if (flags & TTFLAG_VARARGS) - break; - - if (*p != ',' && *skipwhite(p) == ',') - { - semsg(_(e_no_white_before), ","); - return &t_any; - } - if (*p == ',') - { - ++p; - if (!VIM_ISWHITE(*p)) - { - semsg(_(e_white_after), ","); - return &t_any; - } - } - p = skipwhite(p); - if (argcount == MAX_FUNC_ARGS) - { - emsg(_("E740: Too many argument types")); - return &t_any; - } - } - - p = skipwhite(p); - if (*p != ')') - { - emsg(_(e_missing_close)); - return &t_any; - } - *arg = p + 1; - } - if (**arg == ':') - { - // parse return type - ++*arg; - if (!VIM_ISWHITE(**arg)) - semsg(_(e_white_after), ":"); - *arg = skipwhite(*arg); - ret_type = parse_type(arg, type_gap); - } - if (flags == 0 && first_optional == -1 && argcount <= 0) - type = get_func_type(ret_type, argcount, type_gap); - else - { - type = alloc_func_type(ret_type, argcount, type_gap); - type->tt_flags = flags; - if (argcount > 0) - { - type->tt_argcount = argcount; - type->tt_min_argcount = first_optional == -1 - ? argcount : first_optional; - if (func_type_add_arg_types(type, argcount, - type_gap) == FAIL) - return &t_any; - mch_memmove(type->tt_args, arg_type, - sizeof(type_T *) * argcount); - } - } - return type; - } - break; - case 'j': - if (len == 3 && STRNCMP(*arg, "job", len) == 0) - { - *arg += len; - return &t_job; - } - break; - case 'l': - if (len == 4 && STRNCMP(*arg, "list", len) == 0) - { - *arg += len; - return parse_type_member(arg, &t_list_any, type_gap); - } - break; - case 'n': - if (len == 6 && STRNCMP(*arg, "number", len) == 0) - { - *arg += len; - return &t_number; - } - break; - case 's': - if (len == 6 && STRNCMP(*arg, "string", len) == 0) - { - *arg += len; - return &t_string; - } - break; - case 'v': - if (len == 4 && STRNCMP(*arg, "void", len) == 0) - { - *arg += len; - return &t_void; - } - break; - } - - semsg(_("E1010: Type not recognized: %s"), *arg); - return &t_any; -} - -/* - * Check if "type1" and "type2" are exactly the same. - */ - static int -equal_type(type_T *type1, type_T *type2) -{ - int i; - - if (type1->tt_type != type2->tt_type) - return FALSE; - switch (type1->tt_type) - { - case VAR_UNKNOWN: - case VAR_ANY: - case VAR_VOID: - case VAR_SPECIAL: - case VAR_BOOL: - case VAR_NUMBER: - case VAR_FLOAT: - case VAR_STRING: - case VAR_BLOB: - case VAR_JOB: - case VAR_CHANNEL: - break; // not composite is always OK - case VAR_LIST: - case VAR_DICT: - return equal_type(type1->tt_member, type2->tt_member); - case VAR_FUNC: - case VAR_PARTIAL: - if (!equal_type(type1->tt_member, type2->tt_member) - || type1->tt_argcount != type2->tt_argcount) - return FALSE; - if (type1->tt_argcount < 0 - || type1->tt_args == NULL || type2->tt_args == NULL) - return TRUE; - for (i = 0; i < type1->tt_argcount; ++i) - if (!equal_type(type1->tt_args[i], type2->tt_args[i])) - return FALSE; - return TRUE; - } - return TRUE; -} - -/* - * Find the common type of "type1" and "type2" and put it in "dest". - * "type2" and "dest" may be the same. - */ - static void -common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap) -{ - if (equal_type(type1, type2)) - { - *dest = type1; - return; - } - - if (type1->tt_type == type2->tt_type) - { - if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT) - { - type_T *common; - - common_type(type1->tt_member, type2->tt_member, &common, type_gap); - if (type1->tt_type == VAR_LIST) - *dest = get_list_type(common, type_gap); - else - *dest = get_dict_type(common, type_gap); - return; - } - if (type1->tt_type == VAR_FUNC) - { - type_T *common; - - common_type(type1->tt_member, type2->tt_member, &common, type_gap); - if (type1->tt_argcount == type2->tt_argcount - && type1->tt_argcount >= 0) - { - int argcount = type1->tt_argcount; - int i; - - *dest = alloc_func_type(common, argcount, type_gap); - if (type1->tt_args != NULL && type2->tt_args != NULL) - { - if (func_type_add_arg_types(*dest, argcount, - type_gap) == OK) - for (i = 0; i < argcount; ++i) - common_type(type1->tt_args[i], type2->tt_args[i], - &(*dest)->tt_args[i], type_gap); - } - } - else - *dest = alloc_func_type(common, -1, type_gap); - return; - } - } - - *dest = &t_any; -} - - char * -vartype_name(vartype_T type) -{ - switch (type) - { - case VAR_UNKNOWN: break; - case VAR_ANY: return "any"; - case VAR_VOID: return "void"; - case VAR_SPECIAL: return "special"; - case VAR_BOOL: return "bool"; - case VAR_NUMBER: return "number"; - case VAR_FLOAT: return "float"; - case VAR_STRING: return "string"; - case VAR_BLOB: return "blob"; - case VAR_JOB: return "job"; - case VAR_CHANNEL: return "channel"; - case VAR_LIST: return "list"; - case VAR_DICT: return "dict"; - - case VAR_FUNC: - case VAR_PARTIAL: return "func"; - } - return "unknown"; -} - -/* - * Return the name of a type. - * The result may be in allocated memory, in which case "tofree" is set. - */ - char * -type_name(type_T *type, char **tofree) -{ - char *name = vartype_name(type->tt_type); - - *tofree = NULL; - if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT) - { - char *member_free; - char *member_name = type_name(type->tt_member, &member_free); - size_t len; - - len = STRLEN(name) + STRLEN(member_name) + 3; - *tofree = alloc(len); - if (*tofree != NULL) - { - vim_snprintf(*tofree, len, "%s<%s>", name, member_name); - vim_free(member_free); - return *tofree; - } - } - if (type->tt_type == VAR_FUNC) - { - garray_T ga; - int i; - int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0; - - ga_init2(&ga, 1, 100); - if (ga_grow(&ga, 20) == FAIL) - return "[unknown]"; - *tofree = ga.ga_data; - STRCPY(ga.ga_data, "func("); - ga.ga_len += 5; - - for (i = 0; i < type->tt_argcount; ++i) - { - char *arg_free; - char *arg_type; - int len; - - if (type->tt_args == NULL) - arg_type = "[unknown]"; - else - arg_type = type_name(type->tt_args[i], &arg_free); - if (i > 0) - { - STRCPY((char *)ga.ga_data + ga.ga_len, ", "); - ga.ga_len += 2; - } - len = (int)STRLEN(arg_type); - if (ga_grow(&ga, len + 8) == FAIL) - { - vim_free(arg_free); - return "[unknown]"; - } - *tofree = ga.ga_data; - if (varargs && i == type->tt_argcount - 1) - { - STRCPY((char *)ga.ga_data + ga.ga_len, "..."); - ga.ga_len += 3; - } - else if (i >= type->tt_min_argcount) - *((char *)ga.ga_data + ga.ga_len++) = '?'; - STRCPY((char *)ga.ga_data + ga.ga_len, arg_type); - ga.ga_len += len; - vim_free(arg_free); - } - - if (type->tt_member == &t_void) - STRCPY((char *)ga.ga_data + ga.ga_len, ")"); - else - { - char *ret_free; - char *ret_name = type_name(type->tt_member, &ret_free); - int len; - - len = (int)STRLEN(ret_name) + 4; - if (ga_grow(&ga, len) == FAIL) - { - vim_free(ret_free); - return "[unknown]"; - } - *tofree = ga.ga_data; - STRCPY((char *)ga.ga_data + ga.ga_len, "): "); - STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name); - vim_free(ret_free); - } - return ga.ga_data; - } - - return name; -} - /* * Find "name" in script-local items of script "sid". * Returns the index in "sn_var_vals" if found. diff --git a/src/vim9type.c b/src/vim9type.c new file mode 100644 index 00000000000000..5cfdc665ee73bf --- /dev/null +++ b/src/vim9type.c @@ -0,0 +1,915 @@ +/* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +/* + * vim9type.c: handling of types + */ + +#define USING_FLOAT_STUFF +#include "vim.h" + +#if defined(FEAT_EVAL) || defined(PROTO) + +#ifdef VMS +# include +#endif + +/* + * Allocate memory for a type_T and add the pointer to type_gap, so that it can + * be freed later. + */ + static type_T * +alloc_type(garray_T *type_gap) +{ + type_T *type; + + if (ga_grow(type_gap, 1) == FAIL) + return NULL; + type = ALLOC_CLEAR_ONE(type_T); + if (type != NULL) + { + ((type_T **)type_gap->ga_data)[type_gap->ga_len] = type; + ++type_gap->ga_len; + } + return type; +} + + void +clear_type_list(garray_T *gap) +{ + while (gap->ga_len > 0) + vim_free(((type_T **)gap->ga_data)[--gap->ga_len]); + ga_clear(gap); +} + + type_T * +get_list_type(type_T *member_type, garray_T *type_gap) +{ + type_T *type; + + // recognize commonly used types + if (member_type->tt_type == VAR_ANY) + return &t_list_any; + if (member_type->tt_type == VAR_VOID + || member_type->tt_type == VAR_UNKNOWN) + return &t_list_empty; + if (member_type->tt_type == VAR_BOOL) + return &t_list_bool; + if (member_type->tt_type == VAR_NUMBER) + return &t_list_number; + if (member_type->tt_type == VAR_STRING) + return &t_list_string; + + // Not a common type, create a new entry. + type = alloc_type(type_gap); + if (type == NULL) + return &t_any; + type->tt_type = VAR_LIST; + type->tt_member = member_type; + type->tt_argcount = 0; + type->tt_args = NULL; + return type; +} + + type_T * +get_dict_type(type_T *member_type, garray_T *type_gap) +{ + type_T *type; + + // recognize commonly used types + if (member_type->tt_type == VAR_ANY) + return &t_dict_any; + if (member_type->tt_type == VAR_VOID + || member_type->tt_type == VAR_UNKNOWN) + return &t_dict_empty; + if (member_type->tt_type == VAR_BOOL) + return &t_dict_bool; + if (member_type->tt_type == VAR_NUMBER) + return &t_dict_number; + if (member_type->tt_type == VAR_STRING) + return &t_dict_string; + + // Not a common type, create a new entry. + type = alloc_type(type_gap); + if (type == NULL) + return &t_any; + type->tt_type = VAR_DICT; + type->tt_member = member_type; + type->tt_argcount = 0; + type->tt_args = NULL; + return type; +} + +/* + * Allocate a new type for a function. + */ + type_T * +alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap) +{ + type_T *type = alloc_type(type_gap); + + if (type == NULL) + return &t_any; + type->tt_type = VAR_FUNC; + type->tt_member = ret_type; + type->tt_argcount = argcount; + type->tt_args = NULL; + return type; +} + +/* + * Get a function type, based on the return type "ret_type". + * If "argcount" is -1 or 0 a predefined type can be used. + * If "argcount" > 0 always create a new type, so that arguments can be added. + */ + type_T * +get_func_type(type_T *ret_type, int argcount, garray_T *type_gap) +{ + // recognize commonly used types + if (argcount <= 0) + { + if (ret_type == &t_unknown) + { + // (argcount == 0) is not possible + return &t_func_unknown; + } + if (ret_type == &t_void) + { + if (argcount == 0) + return &t_func_0_void; + else + return &t_func_void; + } + if (ret_type == &t_any) + { + if (argcount == 0) + return &t_func_0_any; + else + return &t_func_any; + } + if (ret_type == &t_number) + { + if (argcount == 0) + return &t_func_0_number; + else + return &t_func_number; + } + if (ret_type == &t_string) + { + if (argcount == 0) + return &t_func_0_string; + else + return &t_func_string; + } + } + + return alloc_func_type(ret_type, argcount, type_gap); +} + +/* + * For a function type, reserve space for "argcount" argument types (including + * vararg). + */ + int +func_type_add_arg_types( + type_T *functype, + int argcount, + garray_T *type_gap) +{ + // To make it easy to free the space needed for the argument types, add the + // pointer to type_gap. + if (ga_grow(type_gap, 1) == FAIL) + return FAIL; + functype->tt_args = ALLOC_CLEAR_MULT(type_T *, argcount); + if (functype->tt_args == NULL) + return FAIL; + ((type_T **)type_gap->ga_data)[type_gap->ga_len] = + (void *)functype->tt_args; + ++type_gap->ga_len; + return OK; +} + +/* + * Get a type_T for a typval_T. + * "type_list" is used to temporarily create types in. + */ + type_T * +typval2type(typval_T *tv, garray_T *type_gap) +{ + type_T *actual; + type_T *member_type; + + if (tv->v_type == VAR_NUMBER) + return &t_number; + if (tv->v_type == VAR_BOOL) + return &t_bool; // not used + if (tv->v_type == VAR_STRING) + return &t_string; + + if (tv->v_type == VAR_LIST) + { + if (tv->vval.v_list == NULL || tv->vval.v_list->lv_first == NULL) + return &t_list_empty; + + // Use the type of the first member, it is the most specific. + member_type = typval2type(&tv->vval.v_list->lv_first->li_tv, type_gap); + return get_list_type(member_type, type_gap); + } + + if (tv->v_type == VAR_DICT) + { + dict_iterator_T iter; + typval_T *value; + + if (tv->vval.v_dict == NULL + || tv->vval.v_dict->dv_hashtab.ht_used == 0) + return &t_dict_empty; + + // Use the type of the first value, it is the most specific. + dict_iterate_start(tv, &iter); + dict_iterate_next(&iter, &value); + member_type = typval2type(value, type_gap); + return get_dict_type(member_type, type_gap); + } + + if (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) + { + char_u *name = NULL; + ufunc_T *ufunc = NULL; + + if (tv->v_type == VAR_PARTIAL) + { + if (tv->vval.v_partial->pt_func != NULL) + ufunc = tv->vval.v_partial->pt_func; + else + name = tv->vval.v_partial->pt_name; + } + else + name = tv->vval.v_string; + if (name != NULL) + // TODO: how about a builtin function? + ufunc = find_func(name, FALSE, NULL); + if (ufunc != NULL) + { + // May need to get the argument types from default values by + // compiling the function. + if (ufunc->uf_def_status == UF_TO_BE_COMPILED + && compile_def_function(ufunc, TRUE, NULL) == FAIL) + return NULL; + if (ufunc->uf_func_type != NULL) + return ufunc->uf_func_type; + } + } + + actual = alloc_type(type_gap); + if (actual == NULL) + return NULL; + actual->tt_type = tv->v_type; + actual->tt_member = &t_any; + + return actual; +} + +/* + * Get a type_T for a typval_T, used for v: variables. + * "type_list" is used to temporarily create types in. + */ + type_T * +typval2type_vimvar(typval_T *tv, garray_T *type_gap) +{ + if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles + return &t_list_string; + if (tv->v_type == VAR_DICT) // e.g. for v:completed_item + return &t_dict_any; + return typval2type(tv, type_gap); +} + + +/* + * Return FAIL if "expected" and "actual" don't match. + */ + int +check_typval_type(type_T *expected, typval_T *actual_tv) +{ + garray_T type_list; + type_T *actual_type; + int res = FAIL; + + ga_init2(&type_list, sizeof(type_T *), 10); + actual_type = typval2type(actual_tv, &type_list); + if (actual_type != NULL) + res = check_type(expected, actual_type, TRUE); + clear_type_list(&type_list); + return res; +} + + void +type_mismatch(type_T *expected, type_T *actual) +{ + char *tofree1, *tofree2; + + semsg(_("E1013: type mismatch, expected %s but got %s"), + type_name(expected, &tofree1), type_name(actual, &tofree2)); + vim_free(tofree1); + vim_free(tofree2); +} + + void +arg_type_mismatch(type_T *expected, type_T *actual, int argidx) +{ + char *tofree1, *tofree2; + + semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"), + argidx, + type_name(expected, &tofree1), type_name(actual, &tofree2)); + vim_free(tofree1); + vim_free(tofree2); +} + +/* + * Check if the expected and actual types match. + * Does not allow for assigning "any" to a specific type. + */ + int +check_type(type_T *expected, type_T *actual, int give_msg) +{ + int ret = OK; + + // When expected is "unknown" we accept any actual type. + // When expected is "any" we accept any actual type except "void". + if (expected->tt_type != VAR_UNKNOWN + && !(expected->tt_type == VAR_ANY && actual->tt_type != VAR_VOID)) + + { + if (expected->tt_type != actual->tt_type) + { + if (give_msg) + type_mismatch(expected, actual); + return FAIL; + } + if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST) + { + // "unknown" is used for an empty list or dict + if (actual->tt_member != &t_unknown) + ret = check_type(expected->tt_member, actual->tt_member, FALSE); + } + else if (expected->tt_type == VAR_FUNC) + { + if (expected->tt_member != &t_unknown) + ret = check_type(expected->tt_member, actual->tt_member, FALSE); + if (ret == OK && expected->tt_argcount != -1 + && (actual->tt_argcount < expected->tt_min_argcount + || actual->tt_argcount > expected->tt_argcount)) + ret = FAIL; + if (expected->tt_args != NULL && actual->tt_args != NULL) + { + int i; + + for (i = 0; i < expected->tt_argcount; ++i) + // Allow for using "any" argument type, lambda's have them. + if (actual->tt_args[i] != &t_any && check_type( + expected->tt_args[i], actual->tt_args[i], FALSE) + == FAIL) + { + ret = FAIL; + break; + } + } + } + if (ret == FAIL && give_msg) + type_mismatch(expected, actual); + } + return ret; +} + +/* + * Skip over a type definition and return a pointer to just after it. + * When "optional" is TRUE then a leading "?" is accepted. + */ + char_u * +skip_type(char_u *start, int optional) +{ + char_u *p = start; + + if (optional && *p == '?') + ++p; + while (ASCII_ISALNUM(*p) || *p == '_') + ++p; + + // Skip over ""; this is permissive about white space. + if (*skipwhite(p) == '<') + { + p = skipwhite(p); + p = skip_type(skipwhite(p + 1), FALSE); + p = skipwhite(p); + if (*p == '>') + ++p; + } + else if ((*p == '(' || (*p == ':' && VIM_ISWHITE(p[1]))) + && STRNCMP("func", start, 4) == 0) + { + if (*p == '(') + { + // handle func(args): type + ++p; + while (*p != ')' && *p != NUL) + { + char_u *sp = p; + + if (STRNCMP(p, "...", 3) == 0) + p += 3; + p = skip_type(p, TRUE); + if (p == sp) + return p; // syntax error + if (*p == ',') + p = skipwhite(p + 1); + } + if (*p == ')') + { + if (p[1] == ':') + p = skip_type(skipwhite(p + 2), FALSE); + else + ++p; + } + } + else + { + // handle func: return_type + p = skip_type(skipwhite(p + 1), FALSE); + } + } + + return p; +} + +/* + * Parse the member type: "" and return "type" with the member set. + * Use "type_gap" if a new type needs to be added. + * Returns NULL in case of failure. + */ + static type_T * +parse_type_member(char_u **arg, type_T *type, garray_T *type_gap) +{ + type_T *member_type; + int prev_called_emsg = called_emsg; + + if (**arg != '<') + { + if (*skipwhite(*arg) == '<') + semsg(_(e_no_white_before), "<"); + else + emsg(_("E1008: Missing ")); + return type; + } + *arg = skipwhite(*arg + 1); + + member_type = parse_type(arg, type_gap); + + *arg = skipwhite(*arg); + if (**arg != '>' && called_emsg == prev_called_emsg) + { + emsg(_("E1009: Missing > after type")); + return type; + } + ++*arg; + + if (type->tt_type == VAR_LIST) + return get_list_type(member_type, type_gap); + return get_dict_type(member_type, type_gap); +} + +/* + * Parse a type at "arg" and advance over it. + * Return &t_any for failure. + */ + type_T * +parse_type(char_u **arg, garray_T *type_gap) +{ + char_u *p = *arg; + size_t len; + + // skip over the first word + while (ASCII_ISALNUM(*p) || *p == '_') + ++p; + len = p - *arg; + + switch (**arg) + { + case 'a': + if (len == 3 && STRNCMP(*arg, "any", len) == 0) + { + *arg += len; + return &t_any; + } + break; + case 'b': + if (len == 4 && STRNCMP(*arg, "bool", len) == 0) + { + *arg += len; + return &t_bool; + } + if (len == 4 && STRNCMP(*arg, "blob", len) == 0) + { + *arg += len; + return &t_blob; + } + break; + case 'c': + if (len == 7 && STRNCMP(*arg, "channel", len) == 0) + { + *arg += len; + return &t_channel; + } + break; + case 'd': + if (len == 4 && STRNCMP(*arg, "dict", len) == 0) + { + *arg += len; + return parse_type_member(arg, &t_dict_any, type_gap); + } + break; + case 'f': + if (len == 5 && STRNCMP(*arg, "float", len) == 0) + { +#ifdef FEAT_FLOAT + *arg += len; + return &t_float; +#else + emsg(_("E1076: This Vim is not compiled with float support")); + return &t_any; +#endif + } + if (len == 4 && STRNCMP(*arg, "func", len) == 0) + { + type_T *type; + type_T *ret_type = &t_unknown; + int argcount = -1; + int flags = 0; + int first_optional = -1; + type_T *arg_type[MAX_FUNC_ARGS + 1]; + + // func({type}, ...{type}): {type} + *arg += len; + if (**arg == '(') + { + // "func" may or may not return a value, "func()" does + // not return a value. + ret_type = &t_void; + + p = ++*arg; + argcount = 0; + while (*p != NUL && *p != ')') + { + if (*p == '?') + { + if (first_optional == -1) + first_optional = argcount; + ++p; + } + else if (STRNCMP(p, "...", 3) == 0) + { + flags |= TTFLAG_VARARGS; + p += 3; + } + else if (first_optional != -1) + { + emsg(_("E1007: mandatory argument after optional argument")); + return &t_any; + } + + arg_type[argcount++] = parse_type(&p, type_gap); + + // Nothing comes after "...{type}". + if (flags & TTFLAG_VARARGS) + break; + + if (*p != ',' && *skipwhite(p) == ',') + { + semsg(_(e_no_white_before), ","); + return &t_any; + } + if (*p == ',') + { + ++p; + if (!VIM_ISWHITE(*p)) + { + semsg(_(e_white_after), ","); + return &t_any; + } + } + p = skipwhite(p); + if (argcount == MAX_FUNC_ARGS) + { + emsg(_("E740: Too many argument types")); + return &t_any; + } + } + + p = skipwhite(p); + if (*p != ')') + { + emsg(_(e_missing_close)); + return &t_any; + } + *arg = p + 1; + } + if (**arg == ':') + { + // parse return type + ++*arg; + if (!VIM_ISWHITE(**arg)) + semsg(_(e_white_after), ":"); + *arg = skipwhite(*arg); + ret_type = parse_type(arg, type_gap); + } + if (flags == 0 && first_optional == -1 && argcount <= 0) + type = get_func_type(ret_type, argcount, type_gap); + else + { + type = alloc_func_type(ret_type, argcount, type_gap); + type->tt_flags = flags; + if (argcount > 0) + { + type->tt_argcount = argcount; + type->tt_min_argcount = first_optional == -1 + ? argcount : first_optional; + if (func_type_add_arg_types(type, argcount, + type_gap) == FAIL) + return &t_any; + mch_memmove(type->tt_args, arg_type, + sizeof(type_T *) * argcount); + } + } + return type; + } + break; + case 'j': + if (len == 3 && STRNCMP(*arg, "job", len) == 0) + { + *arg += len; + return &t_job; + } + break; + case 'l': + if (len == 4 && STRNCMP(*arg, "list", len) == 0) + { + *arg += len; + return parse_type_member(arg, &t_list_any, type_gap); + } + break; + case 'n': + if (len == 6 && STRNCMP(*arg, "number", len) == 0) + { + *arg += len; + return &t_number; + } + break; + case 's': + if (len == 6 && STRNCMP(*arg, "string", len) == 0) + { + *arg += len; + return &t_string; + } + break; + case 'v': + if (len == 4 && STRNCMP(*arg, "void", len) == 0) + { + *arg += len; + return &t_void; + } + break; + } + + semsg(_("E1010: Type not recognized: %s"), *arg); + return &t_any; +} + +/* + * Check if "type1" and "type2" are exactly the same. + */ + static int +equal_type(type_T *type1, type_T *type2) +{ + int i; + + if (type1->tt_type != type2->tt_type) + return FALSE; + switch (type1->tt_type) + { + case VAR_UNKNOWN: + case VAR_ANY: + case VAR_VOID: + case VAR_SPECIAL: + case VAR_BOOL: + case VAR_NUMBER: + case VAR_FLOAT: + case VAR_STRING: + case VAR_BLOB: + case VAR_JOB: + case VAR_CHANNEL: + break; // not composite is always OK + case VAR_LIST: + case VAR_DICT: + return equal_type(type1->tt_member, type2->tt_member); + case VAR_FUNC: + case VAR_PARTIAL: + if (!equal_type(type1->tt_member, type2->tt_member) + || type1->tt_argcount != type2->tt_argcount) + return FALSE; + if (type1->tt_argcount < 0 + || type1->tt_args == NULL || type2->tt_args == NULL) + return TRUE; + for (i = 0; i < type1->tt_argcount; ++i) + if (!equal_type(type1->tt_args[i], type2->tt_args[i])) + return FALSE; + return TRUE; + } + return TRUE; +} + +/* + * Find the common type of "type1" and "type2" and put it in "dest". + * "type2" and "dest" may be the same. + */ + void +common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap) +{ + if (equal_type(type1, type2)) + { + *dest = type1; + return; + } + + if (type1->tt_type == type2->tt_type) + { + if (type1->tt_type == VAR_LIST || type2->tt_type == VAR_DICT) + { + type_T *common; + + common_type(type1->tt_member, type2->tt_member, &common, type_gap); + if (type1->tt_type == VAR_LIST) + *dest = get_list_type(common, type_gap); + else + *dest = get_dict_type(common, type_gap); + return; + } + if (type1->tt_type == VAR_FUNC) + { + type_T *common; + + common_type(type1->tt_member, type2->tt_member, &common, type_gap); + if (type1->tt_argcount == type2->tt_argcount + && type1->tt_argcount >= 0) + { + int argcount = type1->tt_argcount; + int i; + + *dest = alloc_func_type(common, argcount, type_gap); + if (type1->tt_args != NULL && type2->tt_args != NULL) + { + if (func_type_add_arg_types(*dest, argcount, + type_gap) == OK) + for (i = 0; i < argcount; ++i) + common_type(type1->tt_args[i], type2->tt_args[i], + &(*dest)->tt_args[i], type_gap); + } + } + else + *dest = alloc_func_type(common, -1, type_gap); + return; + } + } + + *dest = &t_any; +} + + char * +vartype_name(vartype_T type) +{ + switch (type) + { + case VAR_UNKNOWN: break; + case VAR_ANY: return "any"; + case VAR_VOID: return "void"; + case VAR_SPECIAL: return "special"; + case VAR_BOOL: return "bool"; + case VAR_NUMBER: return "number"; + case VAR_FLOAT: return "float"; + case VAR_STRING: return "string"; + case VAR_BLOB: return "blob"; + case VAR_JOB: return "job"; + case VAR_CHANNEL: return "channel"; + case VAR_LIST: return "list"; + case VAR_DICT: return "dict"; + + case VAR_FUNC: + case VAR_PARTIAL: return "func"; + } + return "unknown"; +} + +/* + * Return the name of a type. + * The result may be in allocated memory, in which case "tofree" is set. + */ + char * +type_name(type_T *type, char **tofree) +{ + char *name = vartype_name(type->tt_type); + + *tofree = NULL; + if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT) + { + char *member_free; + char *member_name = type_name(type->tt_member, &member_free); + size_t len; + + len = STRLEN(name) + STRLEN(member_name) + 3; + *tofree = alloc(len); + if (*tofree != NULL) + { + vim_snprintf(*tofree, len, "%s<%s>", name, member_name); + vim_free(member_free); + return *tofree; + } + } + if (type->tt_type == VAR_FUNC) + { + garray_T ga; + int i; + int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0; + + ga_init2(&ga, 1, 100); + if (ga_grow(&ga, 20) == FAIL) + return "[unknown]"; + *tofree = ga.ga_data; + STRCPY(ga.ga_data, "func("); + ga.ga_len += 5; + + for (i = 0; i < type->tt_argcount; ++i) + { + char *arg_free; + char *arg_type; + int len; + + if (type->tt_args == NULL) + arg_type = "[unknown]"; + else + arg_type = type_name(type->tt_args[i], &arg_free); + if (i > 0) + { + STRCPY((char *)ga.ga_data + ga.ga_len, ", "); + ga.ga_len += 2; + } + len = (int)STRLEN(arg_type); + if (ga_grow(&ga, len + 8) == FAIL) + { + vim_free(arg_free); + return "[unknown]"; + } + *tofree = ga.ga_data; + if (varargs && i == type->tt_argcount - 1) + { + STRCPY((char *)ga.ga_data + ga.ga_len, "..."); + ga.ga_len += 3; + } + else if (i >= type->tt_min_argcount) + *((char *)ga.ga_data + ga.ga_len++) = '?'; + STRCPY((char *)ga.ga_data + ga.ga_len, arg_type); + ga.ga_len += len; + vim_free(arg_free); + } + + if (type->tt_member == &t_void) + STRCPY((char *)ga.ga_data + ga.ga_len, ")"); + else + { + char *ret_free; + char *ret_name = type_name(type->tt_member, &ret_free); + int len; + + len = (int)STRLEN(ret_name) + 4; + if (ga_grow(&ga, len) == FAIL) + { + vim_free(ret_free); + return "[unknown]"; + } + *tofree = ga.ga_data; + STRCPY((char *)ga.ga_data + ga.ga_len, "): "); + STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name); + vim_free(ret_free); + } + return ga.ga_data; + } + + return name; +} + + +#endif // FEAT_EVAL From a1b9b0cc011ef15869ac25cb93e1b4baa0cb7f38 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 16:37:48 +0200 Subject: [PATCH 0120/1384] patch 8.2.1406: popupwindow lacks scrollbar if no "maxheight" is used Problem: Popupwindow lacks scrollbar if no "maxheight" is used. Solution: Compute the max height depending on the position. (closes #6664) --- src/popupwin.c | 30 +++++++++++++++---- .../dumps/Test_popupwin_toohigh_1.dump | 10 +++++++ .../dumps/Test_popupwin_toohigh_2.dump | 10 +++++++ src/testdir/test_popupwin.vim | 30 +++++++++++++++++++ src/version.c | 2 ++ 5 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 src/testdir/dumps/Test_popupwin_toohigh_1.dump create mode 100644 src/testdir/dumps/Test_popupwin_toohigh_2.dump diff --git a/src/popupwin.c b/src/popupwin.c index 3bd8e731426a8e..5325bf6f186c5b 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -1130,6 +1130,7 @@ popup_adjust_position(win_T *wp) int org_leftcol = wp->w_leftcol; int org_leftoff = wp->w_popup_leftoff; int minwidth, minheight; + int maxheight = Rows; int wantline = wp->w_wantline; // adjusted for textprop int wantcol = wp->w_wantcol; // adjusted for textprop int use_wantcol = wantcol != 0; @@ -1277,6 +1278,9 @@ popup_adjust_position(win_T *wp) } #endif + if (wp->w_maxheight > 0) + maxheight = wp->w_maxheight; + // start at the desired first line if (wp->w_firstline > 0) wp->w_topline = wp->w_firstline; @@ -1353,11 +1357,11 @@ popup_adjust_position(win_T *wp) ++lnum; // do not use the width of lines we're not going to show - if (wp->w_maxheight > 0 + if (maxheight > 0 && (wp->w_firstline >= 0 ? lnum - wp->w_topline : wp->w_buffer->b_ml.ml_line_count - lnum) - + wrapped >= wp->w_maxheight) + + wrapped >= maxheight) break; } @@ -1449,13 +1453,11 @@ popup_adjust_position(win_T *wp) + 1 + wrapped; if (minheight > 0 && wp->w_height < minheight) wp->w_height = minheight; - if (wp->w_maxheight > 0 && wp->w_height > wp->w_maxheight) - wp->w_height = wp->w_maxheight; + if (maxheight > 0 && wp->w_height > maxheight) + wp->w_height = maxheight; w_height_before_limit = wp->w_height; if (wp->w_height > Rows - wp->w_winrow) wp->w_height = Rows - wp->w_winrow; - if (wp->w_height != org_height) - win_comp_scroll(wp); if (center_vert) { @@ -1477,9 +1479,21 @@ popup_adjust_position(win_T *wp) wp->w_height = wantline - extra_height; } else + { // Not enough space and more space on the other side: make top // aligned. wp->w_winrow = (wantline < 0 ? 0 : wantline) + 1; + if (wp->w_winrow + wp->w_height + extra_height >= Rows) + { + wp->w_height = Rows - wp->w_winrow - extra_height; + if (wp->w_want_scrollbar +#ifdef FEAT_TERMINAL + && wp->w_buffer->b_term == NULL +#endif + ) + wp->w_has_scrollbar = TRUE; + } + } } else if (wp->w_popup_pos == POPPOS_TOPRIGHT || wp->w_popup_pos == POPPOS_TOPLEFT) @@ -1501,11 +1515,15 @@ popup_adjust_position(win_T *wp) else wp->w_winrow = wantline - 1; } + // make sure w_window is valid if (wp->w_winrow >= Rows) wp->w_winrow = Rows - 1; else if (wp->w_winrow < 0) wp->w_winrow = 0; + if (wp->w_height != org_height) + win_comp_scroll(wp); + wp->w_popup_last_changedtick = CHANGEDTICK(wp->w_buffer); if (win_valid(wp->w_popup_prop_win)) { diff --git a/src/testdir/dumps/Test_popupwin_toohigh_1.dump b/src/testdir/dumps/Test_popupwin_toohigh_1.dump new file mode 100644 index 00000000000000..41dbd44c734923 --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_toohigh_1.dump @@ -0,0 +1,10 @@ +|1+0&#ffffff0@9| @64 +|2@9| @64 +|3@8>3| @64 +|4@8|╔+0#0000001#ffd7ff255|═@8|╗| +0#0000000#ffffff0@54 +|5@8|║+0#0000001#ffd7ff255|o|n|e| @4| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|6@8|║+0#0000001#ffd7ff255|t|w|o| @4| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|7@8|║+0#0000001#ffd7ff255|t|h|r|e@1| @2| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|8@8|║+0#0000001#ffd7ff255|f|o|u|r| @3| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|9@8|║+0#0000001#ffd7ff255|f|i|v|e| @3| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +@9|╚+0#0000001#ffd7ff255|═@8|╝| +0#0000000#ffffff0@36|3|,|1|0| @9|T|o|p| diff --git a/src/testdir/dumps/Test_popupwin_toohigh_2.dump b/src/testdir/dumps/Test_popupwin_toohigh_2.dump new file mode 100644 index 00000000000000..911cc2f5081669 --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_toohigh_2.dump @@ -0,0 +1,10 @@ +|1+0&#ffffff0@8|╔+0#0000001#ffd7ff255|═@8|╗| +0#0000000#ffffff0@54 +|2@8|║+0#0000001#ffd7ff255|o|n|e| @4| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|3@8|║+0#0000001#ffd7ff255|t|w|o| @4| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|4@8|║+0#0000001#ffd7ff255|t|h|r|e@1| @2| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|5@8|║+0#0000001#ffd7ff255|f|o|u|r| @3| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|6@8|║+0#0000001#ffd7ff255|f|i|v|e| @3| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|7@8|╚+0#0000001#ffd7ff255|═@8|╝| +0#0000000#ffffff0@54 +|8@8>8| @64 +|9@9| @64 +|:|c|a|l@1| |S|h|o|w|P|o|p|u|p|(|)| @39|8|,|1|0| @9|T|o|p| diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index 30dfc6693acdc1..c44c8476198a09 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -2144,6 +2144,36 @@ func Test_popup_scrollbar() call delete('XtestPopupScroll') endfunc +func Test_popup_too_high_scrollbar() + CheckScreendump + + let lines =<< trim END + call setline(1, range(1, 20)->map({i, v -> repeat(v, 10)})) + set scrolloff=0 + func ShowPopup() + let winid = popup_atcursor(['one', 'two', 'three', 'four', 'five', + \ 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve'], #{ + \ minwidth: 8, + \ border: [], + \ }) + endfunc + normal 3G$ + call ShowPopup() + END + call writefile(lines, 'XtestPopupToohigh') + let buf = RunVimInTerminal('-S XtestPopupToohigh', #{rows: 10}) + call VerifyScreenDump(buf, 'Test_popupwin_toohigh_1', {}) + + call term_sendkeys(buf, ":call popup_clear()\") + call term_sendkeys(buf, "8G$") + call term_sendkeys(buf, ":call ShowPopup()\") + call VerifyScreenDump(buf, 'Test_popupwin_toohigh_2', {}) + + " clean up + call StopVimInTerminal(buf) + call delete('XtestPopupToohigh') +endfunc + func Test_popup_fitting_scrollbar() " this was causing a crash, divide by zero let winid = popup_create([ diff --git a/src/version.c b/src/version.c index 168ee023aecc8a..77613464a51104 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1406, /**/ 1405, /**/ From 127542bcebeb6480493b09d75a3be1d98a5f7797 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 17:22:04 +0200 Subject: [PATCH 0121/1384] patch 8.2.1407: Vim9: type of list and dict only depends on first item Problem: Vim9: type of list and dict only depends on first item. Solution: Use all items to decide about the type. --- runtime/doc/vim9.txt | 8 ++++++++ src/proto/vim9type.pro | 1 + src/testdir/test_vim9_expr.vim | 34 +++++++++++++++++++++++++++++++- src/version.c | 2 ++ src/vim9compile.c | 27 +++++++++++-------------- src/vim9type.c | 36 ++++++++++++++++++++++++++++++++++ 6 files changed, 91 insertions(+), 17 deletions(-) diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 7f7b15bb238396..8ff70595f46483 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -619,6 +619,8 @@ called in the same way the declaration is the same. Custom types can be defined with `:type`: > :type MyList list +Custom types must start with a capital letter, to avoid name clashes with +builtin types added later, similarly to user functions. {not implemented yet} And classes and interfaces can be used as types: > @@ -645,6 +647,12 @@ declaring a variable and giving it a value: > let var = 0 " infers number type let var = 'hello' " infers string type +The type of a list and dictionary comes from the common type of the values. +If the values all have the same type, that type is used for the list or +dictionary. If there is a mix of types, the "any" type is used. > + [1, 2, 3] list + ['a', 'b', 'c'] list + [1, 'x', 3] list ============================================================================== diff --git a/src/proto/vim9type.pro b/src/proto/vim9type.pro index 5c7ba03ce66d5c..5ad87e8e0eb9e3 100644 --- a/src/proto/vim9type.pro +++ b/src/proto/vim9type.pro @@ -14,6 +14,7 @@ int check_type(type_T *expected, type_T *actual, int give_msg); char_u *skip_type(char_u *start, int optional); type_T *parse_type(char_u **arg, garray_T *type_gap); void common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap); +type_T *get_member_type_from_stack(type_T **stack_top, int count, int skip, garray_T *type_gap); char *vartype_name(vartype_T type); char *type_name(type_T *type, char **tofree); /* vim: set ft=c : */ diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 7e1e16acdd9d40..7891127e5cd874 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1334,7 +1334,17 @@ def Test_expr7_list() # list assert_equal(g:list_empty, []) assert_equal(g:list_empty, [ ]) - assert_equal(g:list_mixed, [1, 'b', false,]) + + let numbers: list = [1, 2, 3] + numbers = [1] + numbers = [] + + let strings: list = ['a', 'b', 'c'] + strings = ['x'] + strings = [] + + let mixed: list = [1, 'b', false,] + assert_equal(g:list_mixed, mixed) assert_equal('b', g:list_mixed[1]) echo [1, @@ -1348,6 +1358,10 @@ def Test_expr7_list() call CheckDefFailure(["let x = g:list_mixed["], 'E1097:') call CheckDefFailure(["let x = g:list_mixed[0"], 'E1097:') call CheckDefExecFailure(["let x = g:list_empty[3]"], 'E684:') + call CheckDefFailure(["let l: list = [234, 'x']"], 'E1013:') + call CheckDefFailure(["let l: list = ['x', 234]"], 'E1013:') + call CheckDefFailure(["let l: list = [234, 'x']"], 'E1013:') + call CheckDefFailure(["let l: list = ['x', 123]"], 'E1013:') enddef def Test_expr7_list_vim9script() @@ -1437,6 +1451,19 @@ def Test_expr7_dict() let val = 1 assert_equal(g:dict_one, {key: val}) + let numbers: dict = #{a: 1, b: 2, c: 3} + numbers = #{a: 1} + numbers = #{} + + let strings: dict = #{a: 'a', b: 'b', c: 'c'} + strings = #{a: 'x'} + strings = #{} + + let mixed: dict = #{a: 'a', b: 42} + mixed = #{a: 'x'} + mixed = #{a: 234} + mixed = #{} + call CheckDefFailure(["let x = #{8: 8}"], 'E1014:') call CheckDefFailure(["let x = #{xxx}"], 'E720:') call CheckDefFailure(["let x = #{xxx: 1", "let y = 2"], 'E722:') @@ -1449,6 +1476,11 @@ def Test_expr7_dict() call CheckDefFailure(["let x = x + 1"], 'E1001:') call CheckDefExecFailure(["let x = g:anint.member"], 'E715:') call CheckDefExecFailure(["let x = g:dict_empty.member"], 'E716:') + + call CheckDefFailure(['let x: dict = #{a: 234, b: "1"}'], 'E1013:') + call CheckDefFailure(['let x: dict = #{a: "x", b: 134}'], 'E1013:') + call CheckDefFailure(['let x: dict = #{a: 234, b: "1"}'], 'E1013:') + call CheckDefFailure(['let x: dict = #{a: "x", b: 134}'], 'E1013:') enddef def Test_expr7_dict_vim9script() diff --git a/src/version.c b/src/version.c index 77613464a51104..e7dd7dd0f1121c 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1407, /**/ 1406, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index e23dd7a31b0244..19760fb695f63e 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1110,17 +1110,15 @@ generate_NEWLIST(cctx_T *cctx, int count) return FAIL; isn->isn_arg.number = count; + // get the member type from all the items on the stack. + member = get_member_type_from_stack( + ((type_T **)stack->ga_data) + stack->ga_len, count, 1, + cctx->ctx_type_list); + type = get_list_type(member, cctx->ctx_type_list); + // drop the value types stack->ga_len -= count; - // Use the first value type for the list member type. Use "any" for an - // empty list. - if (count > 0) - member = ((type_T **)stack->ga_data)[stack->ga_len]; - else - member = &t_void; - type = get_list_type(member, cctx->ctx_type_list); - // add the list type to the type stack if (ga_grow(stack, 1) == FAIL) return FAIL; @@ -1146,17 +1144,14 @@ generate_NEWDICT(cctx_T *cctx, int count) return FAIL; isn->isn_arg.number = count; + member = get_member_type_from_stack( + ((type_T **)stack->ga_data) + stack->ga_len, count, 2, + cctx->ctx_type_list); + type = get_dict_type(member, cctx->ctx_type_list); + // drop the key and value types stack->ga_len -= 2 * count; - // Use the first value type for the list member type. Use "void" for an - // empty dict. - if (count > 0) - member = ((type_T **)stack->ga_data)[stack->ga_len + 1]; - else - member = &t_void; - type = get_dict_type(member, cctx->ctx_type_list); - // add the dict type to the type stack if (ga_grow(stack, 1) == FAIL) return FAIL; diff --git a/src/vim9type.c b/src/vim9type.c index 5cfdc665ee73bf..ecac69414acf4c 100644 --- a/src/vim9type.c +++ b/src/vim9type.c @@ -789,6 +789,42 @@ common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap) *dest = &t_any; } +/* + * Get the member type of a dict or list from the items on the stack. + * "stack_top" points just after the last type on the type stack. + * For a list "skip" is 1, for a dict "skip" is 2, keys are skipped. + * Returns &t_void for an empty list or dict. + * Otherwise finds the common type of all items. + */ + type_T * +get_member_type_from_stack( + type_T **stack_top, + int count, + int skip, + garray_T *type_gap) +{ + int i; + type_T *result; + type_T *type; + + // Use "any" for an empty list or dict. + if (count == 0) + return &t_void; + + // Use the first value type for the list member type, then find the common + // type from following items. + result = *(stack_top -(count * skip) + skip - 1); + for (i = 1; i < count; ++i) + { + if (result == &t_any) + break; // won't get more common + type = *(stack_top -((count - i) * skip) + skip - 1); + common_type(type, result, &result, type_gap); + } + + return result; +} + char * vartype_name(vartype_T type) { From 64d662d5fc2ff8af4dbf399ff02aa9d711cc9312 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 19:02:50 +0200 Subject: [PATCH 0122/1384] patch 8.2.1408: Vim9: type casting not supported Problem: Vim9: type casting not supported. Solution: Introduce type casting. --- runtime/doc/vim9.txt | 29 ++++++++++++++ src/testdir/test_vim9_disassemble.vim | 18 +++++++++ src/testdir/test_vim9_expr.vim | 6 +++ src/version.c | 2 + src/vim9compile.c | 54 ++++++++++++++++++++++++++- 5 files changed, 107 insertions(+), 2 deletions(-) diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 8ff70595f46483..7c4a64f972dc41 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -640,6 +640,35 @@ And classes and interfaces can be used as types: > {not implemented yet} +Variable types and type casting *variable-types* + +Variables declared in Vim9 script or in a `:def` function have a type, either +specified explicitly or inferred from the initialization. + +Global, buffer, window and tab page variables do not have a specific type, the +value can be changed at any time, possibly changing the type. Therefore, in +compiled code the "any" type is assumed. + +This can be a problem when the "any" type is undesired and the actual type is +expected to always be the same. For example, when declaring a list: > + let l: list = [1, g:two] +This will give an error, because "g:two" has type "any". To avoid this, use a +type cast: > + let l: list = [1, g:two] +< *type-casting* +The compiled code will then check that "g:two" is a number at runtime and give +an error if it isn't. This is called type casting. + +The syntax of a type cast is: "<" {type} ">". There cannot be white space +after the "<" or before the ">" (to avoid them being confused with +smaller-than and bigger-than operators). + +The semantics is that, if needed, a runtime type check is performed. The +value is not actually changed. If you need to change the type, e.g. to change +it to a string, use the |string()| function. Or use |str2nr()| to convert a +string to a number. + + Type inference *type-inference* In general: Whenever the type is clear it can be omitted. For example, when diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index ea012b744e9842..5d9447d8ca11a5 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -817,6 +817,24 @@ enddef let g:number = 42 +def TypeCast() + let l: list = [23, g:number] +enddef + +def Test_disassemble_typecast() + let instr = execute('disassemble TypeCast') + assert_match('TypeCast.*' .. + 'let l: list = \[23, g:number\].*' .. + '\d PUSHNR 23\_s*' .. + '\d LOADG g:number\_s*' .. + '\d CHECKTYPE number stack\[-1\]\_s*' .. + '\d NEWLIST size 2\_s*' .. + '\d STORE $0\_s*' .. + '\d PUSHNR 0\_s*' .. + '\d RETURN\_s*', + instr) +enddef + def Computing() let nr = 3 let nrres = nr + 7 diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 7891127e5cd874..0af5402cc280f4 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1247,6 +1247,12 @@ let g:dict_one = #{one: 1} let $TESTVAR = 'testvar' +" type casts +def Test_expr7t() + let ls: list = ['a', g:string_empty] + let ln: list = [g:anint, g:alsoint] +enddef + " test low level expression def Test_expr7_number() # number constant diff --git a/src/version.c b/src/version.c index e7dd7dd0f1121c..b7667bf4c6bb50 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1408, /**/ 1407, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 19760fb695f63e..81206b3aca1b0e 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3401,6 +3401,56 @@ error_white_both(char_u *op, int len) semsg(_(e_white_both), buf); } +/* + * expr7: runtime type check / conversion + */ + static int +compile_expr7t(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) +{ + type_T *want_type = NULL; + + // Recognize + if (**arg == '<' && eval_isnamec1((*arg)[1])) + { + int called_emsg_before = called_emsg; + + ++*arg; + want_type = parse_type(arg, cctx->ctx_type_list); + if (called_emsg != called_emsg_before) + return FAIL; + + if (**arg != '>') + { + if (*skipwhite(*arg) == '>') + semsg(_(e_no_white_before), ">"); + else + emsg(_("E1104: Missing >")); + return FAIL; + } + ++*arg; + if (may_get_next_line_error(*arg - 1, arg, cctx) == FAIL) + return FAIL; + } + + if (compile_expr7(arg, cctx, ppconst) == FAIL) + return FAIL; + + if (want_type != NULL) + { + garray_T *stack = &cctx->ctx_type_stack; + type_T *actual = ((type_T **)stack->ga_data)[stack->ga_len - 1]; + + if (check_type(want_type, actual, FALSE) == FAIL) + { + generate_ppconst(cctx, ppconst); + if (need_type(actual, want_type, -1, cctx, FALSE) == FAIL) + return FAIL; + } + } + + return OK; +} + /* * * number multiplication * / number division @@ -3414,7 +3464,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) int ppconst_used = ppconst->pp_used; // get the first expression - if (compile_expr7(arg, cctx, ppconst) == FAIL) + if (compile_expr7t(arg, cctx, ppconst) == FAIL) return FAIL; /* @@ -3441,7 +3491,7 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) return FAIL; // get the second expression - if (compile_expr7(arg, cctx, ppconst) == FAIL) + if (compile_expr7t(arg, cctx, ppconst) == FAIL) return FAIL; if (ppconst->pp_used == ppconst_used + 2 From 1e91eafc2e19b84ea44347ea929d2791d2fdd5e3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 19:32:39 +0200 Subject: [PATCH 0123/1384] patch 8.2.1409: nmpmrc and php.ini filetypes not recognized Problem: Nmpmrc and php.ini filetypes not recognized. Solution: Add filetype detection. (Doug Kearns) --- runtime/filetype.vim | 6 ++++++ src/testdir/test_filetype.vim | 2 +- src/version.c | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 106eb37919a411..dfbfaabaec3e69 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1093,6 +1093,9 @@ au BufNewFile,BufRead .netrc setf netrc " Ninja file au BufNewFile,BufRead *.ninja setf ninja +" NPM RC file +au BufNewFile,BufRead npmrc,.npmrc setf dosini + " Novell netware batch files au BufNewFile,BufRead *.ncf setf ncf @@ -1199,6 +1202,9 @@ au BufNewFile,BufRead *.pod6 setf pod6 " Also .ctp for Cake template file au BufNewFile,BufRead *.php,*.php\d,*.phtml,*.ctp setf php +" PHP config +au BufNewFile,BufRead php.ini,php.ini-* setf dosini + " Pike and Cmod au BufNewFile,BufRead *.pike,*.pmod setf pike au BufNewFile,BufRead *.cmod setf cmod diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 2e517c0bb9753c..cd72008173d029 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -140,7 +140,7 @@ let s:filename_checks = { \ 'dnsmasq': ['/etc/dnsmasq.conf'], \ 'dockerfile': ['Containerfile', 'Dockerfile', 'file.Dockerfile'], \ 'dosbatch': ['file.bat', 'file.sys'], - \ 'dosini': ['.editorconfig', '/etc/pacman.conf', '/etc/yum.conf', 'file.ini'], + \ 'dosini': ['.editorconfig', '/etc/pacman.conf', '/etc/yum.conf', 'file.ini', 'npmrc', '.npmrc', 'php.ini', 'php.ini-5'], \ 'dot': ['file.dot', 'file.gv'], \ 'dracula': ['file.drac', 'file.drc', 'filelvs', 'filelpe'], \ 'dsl': ['file.dsl'], diff --git a/src/version.c b/src/version.c index b7667bf4c6bb50..0cd89d67a23044 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1409, /**/ 1408, /**/ From 7f7a8888699bca6df0a45a16db5f0e313383b5f1 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 20:05:41 +0200 Subject: [PATCH 0124/1384] patch 8.2.1410: adding compiler plugin requires test change Problem: Adding compiler plugin requires test change. Solution: Include compiler plugin and adjust test. --- runtime/compiler/xo.vim | 26 ++++++++++++++++++++++++++ src/testdir/test_compiler.vim | 4 ++-- src/version.c | 2 ++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 runtime/compiler/xo.vim diff --git a/runtime/compiler/xo.vim b/runtime/compiler/xo.vim new file mode 100644 index 00000000000000..525657d4bba806 --- /dev/null +++ b/runtime/compiler/xo.vim @@ -0,0 +1,26 @@ +" Vim compiler file +" Compiler: XO +" Maintainer: Doug Kearns +" Last Change: 2019 Jul 10 + +if exists("current_compiler") + finish +endif +let current_compiler = "xo" + +if exists(":CompilerSet") != 2 " older Vim always used :setlocal + command -nargs=* CompilerSet setlocal +endif + +let s:cpo_save = &cpo +set cpo&vim + +" CompilerSet makeprg=npx\ xo\ --reporter\ compact + +CompilerSet makeprg=xo\ --reporter\ compact +CompilerSet errorformat=%f:\ line\ %l\\,\ col\ %c\\,\ %trror\ %m, + \%f:\ line\ %l\\,\ col\ %c\\,\ %tarning\ %m, + \%-G%.%# + +let &cpo = s:cpo_save +unlet s:cpo_save diff --git a/src/testdir/test_compiler.vim b/src/testdir/test_compiler.vim index 464dd9bcb5a624..dd753c55ba0b5b 100644 --- a/src/testdir/test_compiler.vim +++ b/src/testdir/test_compiler.vim @@ -46,7 +46,7 @@ func Test_compiler_without_arg() let a = split(execute('compiler')) call assert_match(runtime .. '/compiler/ant.vim$', a[0]) call assert_match(runtime .. '/compiler/bcc.vim$', a[1]) - call assert_match(runtime .. '/compiler/xmlwf.vim$', a[-1]) + call assert_match(runtime .. '/compiler/xo.vim$', a[-1]) endfunc " Test executing :compiler from the command line, not from a script @@ -60,7 +60,7 @@ endfunc func Test_compiler_completion() call feedkeys(":compiler \\\"\", 'tx') - call assert_match('^"compiler ant bcc .* xmlwf$', @:) + call assert_match('^"compiler ant bcc .* xmlwf xo$', @:) call feedkeys(":compiler p\\\"\", 'tx') call assert_equal('"compiler pbx perl php pylint pyunit', @:) diff --git a/src/version.c b/src/version.c index 0cd89d67a23044..e290ea29cae8aa 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1410, /**/ 1409, /**/ From a9a47d157ab1946d1e286c9695bc68d71305af68 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 21:45:52 +0200 Subject: [PATCH 0125/1384] patch 8.2.1411: when splitting a window localdir is copied but prevdir is not Problem: when splitting a window localdir is copied but prevdir is not. Solution: Also copy prevdir. (closes #6667) --- src/clientserver.c | 6 ++++-- src/testdir/test_cd.vim | 9 +++++++++ src/version.c | 2 ++ src/window.c | 2 ++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/clientserver.c b/src/clientserver.c index fbbeb6a4bf01f1..7215aa7ffb1aac 100644 --- a/src/clientserver.c +++ b/src/clientserver.c @@ -596,7 +596,8 @@ build_drop_cmd( ga_concat(&ga, cdp); // Call inputsave() so that a prompt for an encryption key works. - ga_concat(&ga, (char_u *)":if exists('*inputsave')|call inputsave()|endif|"); + ga_concat(&ga, (char_u *) + ":if exists('*inputsave')|call inputsave()|endif|"); if (tabs) ga_concat(&ga, (char_u *)"tab "); ga_concat(&ga, (char_u *)"drop"); @@ -621,7 +622,8 @@ build_drop_cmd( ga_concat(&ga, p); vim_free(p); } - ga_concat(&ga, (char_u *)"|if exists('*inputrestore')|call inputrestore()|endif"); + ga_concat(&ga, (char_u *) + "|if exists('*inputrestore')|call inputrestore()|endif"); // The :drop commands goes to Insert mode when 'insertmode' is set, use // CTRL-\ CTRL-N again. diff --git a/src/testdir/test_cd.vim b/src/testdir/test_cd.vim index bd6e3d9a53b33a..8a0fbb247d0f05 100644 --- a/src/testdir/test_cd.vim +++ b/src/testdir/test_cd.vim @@ -168,6 +168,15 @@ func Test_prev_dir() call delete('Xdir', 'rf') endfunc +func Test_lcd_split() + let curdir = getcwd() + lcd .. + split + lcd - + call assert_equal(curdir, getcwd()) + quit! +endfunc + func Test_cd_completion() call mkdir('XComplDir1', 'p') call mkdir('XComplDir2', 'p') diff --git a/src/version.c b/src/version.c index e290ea29cae8aa..64eca6bfabaea9 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1411, /**/ 1410, /**/ diff --git a/src/window.c b/src/window.c index 7d8122efdd00eb..d2e5c5c2af4e6f 100644 --- a/src/window.c +++ b/src/window.c @@ -1385,6 +1385,8 @@ win_init(win_T *newp, win_T *oldp, int flags UNUSED) #endif newp->w_localdir = (oldp->w_localdir == NULL) ? NULL : vim_strsave(oldp->w_localdir); + newp->w_prevdir = (oldp->w_prevdir == NULL) + ? NULL : vim_strsave(oldp->w_prevdir); // copy tagstack and folds for (i = 0; i < oldp->w_tagstacklen; i++) From 6e4cfffe809a894ea831fc8011527714481d2857 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 9 Aug 2020 22:17:55 +0200 Subject: [PATCH 0126/1384] patch 8.2.1412: Vim: not operator does not result in boolean Problem: Vim: not operator does not result in boolean. Solution: Make type depend on operator. (issue 6678) Fix using "false" and "true" in Vim9 script. --- src/eval.c | 14 +++++++++++++- src/testdir/test_vim9_expr.vim | 18 ++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/eval.c b/src/eval.c index b1fad1dcd5e32e..abdf076d264988 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3222,12 +3222,14 @@ eval7( { rettv->v_type = VAR_BOOL; rettv->vval.v_number = VVAL_TRUE; + ret = OK; } else if (len == 5 && in_vim9script() && STRNCMP(s, "false", 4) == 0) { rettv->v_type = VAR_BOOL; rettv->vval.v_number = VVAL_FALSE; + ret = OK; } else ret = eval_variable(s, len, rettv, NULL, TRUE, FALSE); @@ -3271,6 +3273,7 @@ eval7_leader( int ret = OK; int error = FALSE; varnumber_T val = 0; + vartype_T type = rettv->v_type; #ifdef FEAT_FLOAT float_T f = 0.0; @@ -3301,7 +3304,10 @@ eval7_leader( f = !f; else #endif + { val = !val; + type = VAR_BOOL; + } } else if (*end_leader == '-') { @@ -3310,7 +3316,10 @@ eval7_leader( f = -f; else #endif + { val = -val; + type = VAR_NUMBER; + } } } #ifdef FEAT_FLOAT @@ -3323,7 +3332,10 @@ eval7_leader( #endif { clear_tv(rettv); - rettv->v_type = VAR_NUMBER; + if (in_vim9script()) + rettv->v_type = type; + else + rettv->v_type = VAR_NUMBER; rettv->vval.v_number = val; } } diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 0af5402cc280f4..aa599731893bcd 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1313,6 +1313,16 @@ def Test_expr7_special() assert_equal(g:special_false, false) assert_equal(g:special_true, v:true) assert_equal(g:special_false, v:false) + + assert_equal(true, !false) + assert_equal(false, !true) + assert_equal(true, !0) + assert_equal(false, !1) + assert_equal(false, !!false) + assert_equal(true, !!true) + assert_equal(false, !!0) + assert_equal(true, !!1) + assert_equal(g:special_null, v:null) assert_equal(g:special_none, v:none) @@ -1332,6 +1342,14 @@ def Test_expr7_special_vim9script() assert_equal(true, t) assert_equal(v:false, false) assert_equal(false, f) + assert_equal(true, !false) + assert_equal(false, !true) + assert_equal(true, !0) + assert_equal(false, !1) + assert_equal(false, !!false) + assert_equal(true, !!true) + assert_equal(false, !!0) + assert_equal(true, !!1) END CheckScriptSuccess(lines) enddef diff --git a/src/version.c b/src/version.c index 64eca6bfabaea9..4d86275a8dcab6 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1412, /**/ 1411, /**/ From 94f4ffa7704921a3634e56b878e6dc362bc3d508 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Aug 2020 19:21:15 +0200 Subject: [PATCH 0127/1384] patch 8.2.1413: previous tab page not usable from an Ex command Problem: Previous tab page not usable from an Ex command. Solution: Add the "#" argument for :tabnext et al. (Yegappan Lakshmanan, closes #6677) --- runtime/doc/tabpage.txt | 6 ++++++ src/ex_docmd.c | 9 +++++++++ src/testdir/test_tabpage.vim | 35 ++++++++++++++++++++++++++++++----- src/version.c | 2 ++ src/window.c | 3 ++- 5 files changed, 49 insertions(+), 6 deletions(-) diff --git a/runtime/doc/tabpage.txt b/runtime/doc/tabpage.txt index 1d8c2082f26772..65ae599967a96a 100644 --- a/runtime/doc/tabpage.txt +++ b/runtime/doc/tabpage.txt @@ -142,6 +142,7 @@ something else. :tabclose + " close the next tab page :tabclose 3 " close the third tab page :tabclose $ " close the last tab page + :tabclose # " close the last accessed tab page < *:tabo* *:tabonly* :tabo[nly][!] Close all other tab pages. @@ -170,6 +171,8 @@ something else. " one :tabonly 1 " close all tab pages except the first one :tabonly $ " close all tab pages except the last one + :tabonly # " close all tab pages except the last + " accessed one SWITCHING TO ANOTHER TAB PAGE: @@ -192,6 +195,7 @@ gt *i_CTRL-* *i_* :+2tabnext " go to the two next tab page :1tabnext " go to the first tab page :$tabnext " go to the last tab page + :tabnext # " go to the last accessed tab page :tabnext $ " as above :tabnext - " go to the previous tab page :tabnext -1 " as above @@ -255,6 +259,8 @@ REORDERING TAB PAGES: :tabmove " move the tab page to the last :$tabmove " as above :tabmove $ " as above + :tabmove # " move the tab page after the last accessed + " tab page :tabm[ove] +[N] :tabm[ove] -[N] diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 96eac7fbe489b0..502f33e2a50ab3 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -5412,6 +5412,15 @@ get_tabpage_arg(exarg_T *eap) { if (STRCMP(p, "$") == 0) tab_number = LAST_TAB_NR; + else if (STRCMP(p, "#") == 0) + if (valid_tabpage(lastused_tabpage)) + tab_number = tabpage_index(lastused_tabpage); + else + { + eap->errmsg = ex_errmsg(e_invargval, eap->arg); + tab_number = 0; + goto theend; + } else if (p == p_save || *p_save == '-' || *p != NUL || tab_number > LAST_TAB_NR) { diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim index 67469718f2bb58..e561064ebc1aeb 100644 --- a/src/testdir/test_tabpage.vim +++ b/src/testdir/test_tabpage.vim @@ -784,6 +784,7 @@ func Test_lastused_tabpage() call assert_beeps('call feedkeys("g\", "xt")') call assert_beeps('call feedkeys("\", "xt")') call assert_beeps('call feedkeys("\g\", "xt")') + call assert_fails('tabnext #', 'E475:') " open four tab pages tabnew @@ -808,17 +809,41 @@ func Test_lastused_tabpage() call assert_equal(4, tabpagenr()) call assert_equal(2, tabpagenr('#')) + " Test for :tabnext # + tabnext # + call assert_equal(2, tabpagenr()) + call assert_equal(4, tabpagenr('#')) + " Try to jump to a closed tab page - tabclose 2 + tabclose # call assert_equal(0, tabpagenr('#')) call feedkeys("g\", "xt") - call assert_equal(3, tabpagenr()) + call assert_equal(2, tabpagenr()) call feedkeys("\", "xt") - call assert_equal(3, tabpagenr()) + call assert_equal(2, tabpagenr()) call feedkeys("\g\", "xt") - call assert_equal(3, tabpagenr()) + call assert_equal(2, tabpagenr()) + call assert_fails('tabnext #', 'E475:') + call assert_equal(2, tabpagenr()) - tabclose! + " Test for :tabonly # + let wnum = win_getid() + $tabnew + tabonly # + call assert_equal(wnum, win_getid()) + call assert_equal(1, tabpagenr('$')) + + " Test for :tabmove # + tabnew + let wnum = win_getid() + tabnew + tabnew + tabnext 2 + tabmove # + call assert_equal(4, tabpagenr()) + call assert_equal(wnum, win_getid()) + + tabonly! endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 4d86275a8dcab6..a08b5d7b02342e 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1413, /**/ 1412, /**/ diff --git a/src/window.c b/src/window.c index d2e5c5c2af4e6f..75e049562be527 100644 --- a/src/window.c +++ b/src/window.c @@ -3844,6 +3844,7 @@ free_tabpage(tabpage_T *tp) win_new_tabpage(int after) { tabpage_T *tp = curtab; + tabpage_T *prev_tp = curtab; tabpage_T *newtp; int n; @@ -3893,7 +3894,7 @@ win_new_tabpage(int after) newtp->tp_topframe = topframe; last_status(FALSE); - lastused_tabpage = tp; + lastused_tabpage = prev_tp; #if defined(FEAT_GUI) // When 'guioptions' includes 'L' or 'R' may have to remove or add From bf61fdd00808bfa7cc61a82c719fc220bba50ba3 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Aug 2020 20:39:17 +0200 Subject: [PATCH 0128/1384] patch 8.2.1414: popupwindow missing last couple of lines Problem: Popupwindow missing last couple of lines when cursor is in the first line. Solution: Compute the max height also when top aligned. (closes #6664) --- src/popupwin.c | 30 ++++++++++++------- src/testdir/dumps/Test_popupwin_nospace.dump | 14 ++++----- .../dumps/Test_popupwin_toohigh_3.dump | 10 +++++++ src/testdir/test_popupwin.vim | 7 +++++ src/version.c | 2 ++ 5 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 src/testdir/dumps/Test_popupwin_toohigh_3.dump diff --git a/src/popupwin.c b/src/popupwin.c index 5325bf6f186c5b..cc0843bfc2c638 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -1134,6 +1134,7 @@ popup_adjust_position(win_T *wp) int wantline = wp->w_wantline; // adjusted for textprop int wantcol = wp->w_wantcol; // adjusted for textprop int use_wantcol = wantcol != 0; + int adjust_height_for_top_aligned = FALSE; wp->w_winrow = 0; wp->w_wincol = 0; @@ -1483,16 +1484,7 @@ popup_adjust_position(win_T *wp) // Not enough space and more space on the other side: make top // aligned. wp->w_winrow = (wantline < 0 ? 0 : wantline) + 1; - if (wp->w_winrow + wp->w_height + extra_height >= Rows) - { - wp->w_height = Rows - wp->w_winrow - extra_height; - if (wp->w_want_scrollbar -#ifdef FEAT_TERMINAL - && wp->w_buffer->b_term == NULL -#endif - ) - wp->w_has_scrollbar = TRUE; - } + adjust_height_for_top_aligned = TRUE; } } else if (wp->w_popup_pos == POPPOS_TOPRIGHT @@ -1513,9 +1505,25 @@ popup_adjust_position(win_T *wp) } } else + { wp->w_winrow = wantline - 1; + adjust_height_for_top_aligned = TRUE; + } } - // make sure w_window is valid + + if (adjust_height_for_top_aligned && wp->w_want_scrollbar + && wp->w_winrow + wp->w_height + extra_height > Rows) + { + // Bottom of the popup goes below the last line, reduce the height and + // add a scrollbar. + wp->w_height = Rows - wp->w_winrow - extra_height; +#ifdef FEAT_TERMINAL + if (wp->w_buffer->b_term == NULL) +#endif + wp->w_has_scrollbar = TRUE; + } + + // make sure w_winrow is valid if (wp->w_winrow >= Rows) wp->w_winrow = Rows - 1; else if (wp->w_winrow < 0) diff --git a/src/testdir/dumps/Test_popupwin_nospace.dump b/src/testdir/dumps/Test_popupwin_nospace.dump index 9eaacf066f5845..de8521c0dff376 100644 --- a/src/testdir/dumps/Test_popupwin_nospace.dump +++ b/src/testdir/dumps/Test_popupwin_nospace.dump @@ -3,10 +3,10 @@ |-|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|b@2|║|-+0#0000000#ffffff0@15|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@11| @14 |-|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@1|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|c@2|║|-+0#0000000#ffffff0@15|║+0#0000001#ffd7ff255|t|e@1|║|-+0#0000000#ffffff0@11| @14 |-|@|-@5|#|-@5|%|-@5|║+0#0000001#ffd7ff255|d@2|║|-+0#0000000#ffffff0@15|║+0#0000001#ffd7ff255|f|o|u|║|-+0#0000000#ffffff0@1>*|-@8| @14 -|-@14|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|e@2|║|-+0#0000000#ffffff0@15|║+0#0000001#ffd7ff255|f|i|v|║|-+0#0000000#ffffff0@1|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@4| @14 -|-@14|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@1|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@15|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|a@2|║|-+0#0000000#ffffff0@4| @14 -|-@14|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1|*|-@5|@|-@5|#|-@5|%|-@5|║+0#0000001#ffd7ff255|b@2|║|-+0#0000000#ffffff0@4| @14 -|-@14|║+0#0000001#ffd7ff255|t|e@1|║|-+0#0000000#ffffff0@8|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@1|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|c@2|║|-+0#0000000#ffffff0@4| @14 -|-@14|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|d@2|║|-+0#0000000#ffffff0@4| @14 -|-@28|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|e@2|║|-+0#0000000#ffffff0@4| @14 -@29|╚+0#0000001#ffd7ff255|═@2|╝| +0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|t|e@1|║| +0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|f@2|║| +0#0000000#ffffff0@1|5|,|5|1| @9|T|o|p| +|-@14|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|e@2|║|-+0#0000000#ffffff0@15|║+0#0000001#ffd7ff255|f|i|v|║|-+0#0000000#ffffff0@1|╔+0#0000001#ffd7ff255|═@3|╗|-+0#0000000#ffffff0@3| @14 +|-@14|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@1|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@15|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|a@2| +0#0000000#0000001|║+0#0000001#ffd7ff255|-+0#0000000#ffffff0@3| @14 +|-@14|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1|*|-@5|@|-@5|#|-@5|%|-@5|║+0#0000001#ffd7ff255|b@2| +0#0000000#0000001|║+0#0000001#ffd7ff255|-+0#0000000#ffffff0@3| @14 +|-@14|║+0#0000001#ffd7ff255|t|e@1|║|-+0#0000000#ffffff0@8|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@1|╔+0#0000001#ffd7ff255|═@3|╗|-+0#0000000#ffffff0@7|║+0#0000001#ffd7ff255|c@2| +0#0000000#0000001|║+0#0000001#ffd7ff255|-+0#0000000#ffffff0@3| @14 +|-@14|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|o|n|e| +0#0000000#0000001|║+0#0000001#ffd7ff255|-+0#0000000#ffffff0@7|║+0#0000001#ffd7ff255|d@2| +0#0000000#0000001|║+0#0000001#ffd7ff255|-+0#0000000#ffffff0@3| @14 +|-@28|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|t|w|o| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255|-+0#0000000#ffffff0@7|║+0#0000001#ffd7ff255|e@2| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255|-+0#0000000#ffffff0@3| @14 +@29|╚+0#0000001#ffd7ff255|═@2|╝| +0#0000000#ffffff0@1|╚+0#0000001#ffd7ff255|═@3|╝| +0#0000000#ffffff0@7|╚+0#0000001#ffd7ff255|═@3|╝| +0#0000000#ffffff0|5|,|5|1| @9|T|o|p| diff --git a/src/testdir/dumps/Test_popupwin_toohigh_3.dump b/src/testdir/dumps/Test_popupwin_toohigh_3.dump new file mode 100644 index 00000000000000..8c15a40328d907 --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_toohigh_3.dump @@ -0,0 +1,10 @@ +|1+0&#ffffff0@8>1| @64 +|2@8|╔+0#0000001#ffd7ff255|═@8|╗| +0#0000000#ffffff0@54 +|3@8|║+0#0000001#ffd7ff255|o|n|e| @4| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|4@8|║+0#0000001#ffd7ff255|t|w|o| @4| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|5@8|║+0#0000001#ffd7ff255|t|h|r|e@1| @2| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|6@8|║+0#0000001#ffd7ff255|f|o|u|r| @3| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|7@8|║+0#0000001#ffd7ff255|f|i|v|e| @3| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|8@8|║+0#0000001#ffd7ff255|s|i|x| @4| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|9@8|║+0#0000001#ffd7ff255|s|e|v|e|n| @2| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#0000000#ffffff0@54 +|:|c|a|l@1| |S|h|o|╚+0#0000001#ffd7ff255|═@8|╝| +0#0000000#ffffff0@36|1|,|1|0| @9|T|o|p| diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index c44c8476198a09..f13a7e057c13ed 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -753,6 +753,7 @@ func Test_popup_with_mask() \ posinvert: 0, \ wrap: 0, \ fixed: 1, + \ scrollbar: v:false, \ zindex: 90, \ padding: [], \ highlight: 'PopupColor', @@ -772,6 +773,7 @@ func Test_popup_with_mask() \ posinvert: 0, \ wrap: 0, \ fixed: 1, + \ scrollbar: v:false, \ close: 'button', \ zindex: 90, \ padding: [], @@ -2169,6 +2171,11 @@ func Test_popup_too_high_scrollbar() call term_sendkeys(buf, ":call ShowPopup()\") call VerifyScreenDump(buf, 'Test_popupwin_toohigh_2', {}) + call term_sendkeys(buf, ":call popup_clear()\") + call term_sendkeys(buf, "gg$") + call term_sendkeys(buf, ":call ShowPopup()\") + call VerifyScreenDump(buf, 'Test_popupwin_toohigh_3', {}) + " clean up call StopVimInTerminal(buf) call delete('XtestPopupToohigh') diff --git a/src/version.c b/src/version.c index a08b5d7b02342e..38dc86fa477e91 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1414, /**/ 1413, /**/ From 6f8f7337c1211692d508239eb4cbc8a6f67de497 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Aug 2020 21:19:23 +0200 Subject: [PATCH 0129/1384] patch 8.2.1415: closing a popup window with CTRL-C interrupts 'statusline' Problem: Closing a popup window with CTRL-C interrupts 'statusline' if it calls a function. Solution: Reset got_int while redrawing. (closes #6675) --- src/popupwin.c | 7 ++++++ src/testdir/dumps/Test_popupwin_ctrl_c.dump | 10 +++++++++ src/testdir/test_popupwin.vim | 25 +++++++++++++++++++++ src/version.c | 2 ++ 4 files changed, 44 insertions(+) create mode 100644 src/testdir/dumps/Test_popupwin_ctrl_c.dump diff --git a/src/popupwin.c b/src/popupwin.c index cc0843bfc2c638..ff9e810044555c 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -3209,7 +3209,14 @@ popup_do_filter(int c) res = invoke_popup_filter(wp, c); if (must_redraw > was_must_redraw) + { + int save_got_int = got_int; + + // Reset got_int to avoid a function used in the statusline aborts. + got_int = FALSE; redraw_after_callback(FALSE); + got_int |= save_got_int; + } recursive = FALSE; KeyTyped = save_KeyTyped; return res; diff --git a/src/testdir/dumps/Test_popupwin_ctrl_c.dump b/src/testdir/dumps/Test_popupwin_ctrl_c.dump new file mode 100644 index 00000000000000..d6636aef40c31e --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_ctrl_c.dump @@ -0,0 +1,10 @@ +> +0&#ffffff0@36||+1&&| +0&&@36 +|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|~| @35||+1#0000000&|~+0#4040ff13&| @35 +|[+3#0000000&|N|o| |N|a|m|e|]| @9|0|,|0|-|1| @9|A|l@1| |[+1&&|N|o| |N|a|m|e|]| @9|0|,|0|-|1| @9|A|l@1 +| +0&&@74 diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index f13a7e057c13ed..6ec4ef252967f8 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -3479,6 +3479,31 @@ func Test_popupwin_filter_input_multibyte() unlet g:bytes endfunc +func Test_popupwin_filter_close_ctrl_c() + CheckScreendump + + let lines =<< trim END + vsplit + set laststatus=2 + set statusline=%!Statusline() + + function Statusline() abort + return '%<%f %h%m%r%=%-14.(%l,%c%V%) %P' + endfunction + + call popup_create('test test test test...', {'filter': {-> 0}}) + END + call writefile(lines, 'XtestPopupCtrlC') + + let buf = RunVimInTerminal('-S XtestPopupCtrlC', #{rows: 10}) + + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_popupwin_ctrl_c', {}) + + call StopVimInTerminal(buf) + call delete('XtestPopupCorners') +endfunc + func Test_popupwin_atcursor_far_right() new diff --git a/src/version.c b/src/version.c index 38dc86fa477e91..e7a10397147bf1 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1415, /**/ 1414, /**/ From 3e06a1e2a8c0854c881574f33363e00264db1f1d Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Aug 2020 21:57:54 +0200 Subject: [PATCH 0130/1384] patch 8.2.1416: Vim9: boolean evaluation does not work as intended Problem: Vim9: boolean evaluation does not work as intended. Solution: Use tv2bool() in Vim9 script. (closes #6681) --- src/eval.c | 13 ++++++-- src/testdir/test_vim9_expr.vim | 54 ++++++++++++++++++---------------- src/testdir/vim9.vim | 8 +++++ src/version.c | 2 ++ 4 files changed, 49 insertions(+), 28 deletions(-) diff --git a/src/eval.c b/src/eval.c index abdf076d264988..99554e7e263e22 100644 --- a/src/eval.c +++ b/src/eval.c @@ -192,7 +192,10 @@ eval_to_bool( *error = FALSE; if (!skip) { - retval = (tv_get_number_chk(&tv, error) != 0); + if (in_vim9script()) + retval = tv2bool(&tv); + else + retval = (tv_get_number_chk(&tv, error) != 0); clear_tv(&tv); } } @@ -3098,7 +3101,8 @@ eval7( // Apply prefixed "-" and "+" now. Matters especially when // "->" follows. - if (ret == OK && evaluate && end_leader > start_leader) + if (ret == OK && evaluate && end_leader > start_leader + && rettv->v_type != VAR_BLOB) ret = eval7_leader(rettv, TRUE, start_leader, &end_leader); break; @@ -3281,7 +3285,10 @@ eval7_leader( f = rettv->vval.v_float; else #endif - val = tv_get_number_chk(rettv, &error); + if (in_vim9script() && end_leader[-1] == '!') + val = tv2bool(rettv); + else + val = tv_get_number_chk(rettv, &error); if (error) { clear_tv(rettv); diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index aa599731893bcd..d2d2e0b1ebfa4b 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1750,31 +1750,35 @@ enddef def Test_expr7_not() - assert_equal(true, !'') - assert_equal(true, ![]) - assert_equal(false, !'asdf') - assert_equal(false, ![2]) - assert_equal(true, !!'asdf') - assert_equal(true, !![2]) - - assert_equal(true, !test_null_partial()) - assert_equal(false, !{-> 'yes'}) - - assert_equal(true, !test_null_dict()) - assert_equal(true, !{}) - assert_equal(false, !{'yes': 'no'}) - - if has('channel') - assert_equal(true, !test_null_job()) - assert_equal(true, !test_null_channel()) - endif - - assert_equal(true, !test_null_blob()) - assert_equal(true, !0z) - assert_equal(false, !0z01) - - assert_equal(true, !test_void()) - assert_equal(true, !test_unknown()) + let lines =<< trim END + assert_equal(true, !'') + assert_equal(true, ![]) + assert_equal(false, !'asdf') + assert_equal(false, ![2]) + assert_equal(true, !!'asdf') + assert_equal(true, !![2]) + + assert_equal(true, !test_null_partial()) + assert_equal(false, !{-> 'yes'}) + + assert_equal(true, !test_null_dict()) + assert_equal(true, !{}) + assert_equal(false, !{'yes': 'no'}) + + if has('channel') + assert_equal(true, !test_null_job()) + assert_equal(true, !test_null_channel()) + endif + + assert_equal(true, !test_null_blob()) + assert_equal(true, !0z) + assert_equal(false, !0z01) + + assert_equal(true, !test_void()) + assert_equal(true, !test_unknown()) + END + CheckDefSuccess(lines) + CheckScriptSuccess(['vim9script'] + lines) enddef func Test_expr7_fails() diff --git a/src/testdir/vim9.vim b/src/testdir/vim9.vim index fdad9f7c3ad12a..448aa3db947231 100644 --- a/src/testdir/vim9.vim +++ b/src/testdir/vim9.vim @@ -1,5 +1,13 @@ " Utility functions for testing vim9 script +" Check that "lines" inside ":def" has no error. +func CheckDefSuccess(lines) + call writefile(['def Func()'] + a:lines + ['enddef', 'defcompile'], 'Xdef') + so Xdef + call Func() + call delete('Xdef') +endfunc + " Check that "lines" inside ":def" results in an "error" message. func CheckDefFailure(lines, error) call writefile(['def Func()'] + a:lines + ['enddef', 'defcompile'], 'Xdef') diff --git a/src/version.c b/src/version.c index e7a10397147bf1..627df9923f5cc7 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1416, /**/ 1415, /**/ From efb6482949580ab89e6d7c5e1cb8d744ddd6ef80 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Aug 2020 22:15:30 +0200 Subject: [PATCH 0131/1384] patch 8.2.1417: test 49 is old style Problem: Test 49 is old style. Solution: Convert more parts to new style test. (Yegappan Lakshmanan, closes #6682) --- src/testdir/test49.ok | 14 - src/testdir/test49.vim | 2467 +------------------------------- src/testdir/test_vimscript.vim | 2055 +++++++++++++++++++++++++- src/version.c | 2 + 4 files changed, 2025 insertions(+), 2513 deletions(-) diff --git a/src/testdir/test49.ok b/src/testdir/test49.ok index 8ca8a564c3261b..d687f5bc7794a8 100644 --- a/src/testdir/test49.ok +++ b/src/testdir/test49.ok @@ -1,18 +1,4 @@ Results of test49.vim: -*** Test 59: OK (2038431743) -*** Test 60: OK (311511339) -*** Test 62: OK (286331153) -*** Test 63: OK (236978127) -*** Test 64: OK (1499645335) -*** Test 66: OK (5464) -*** Test 67: OK (212514423) -*** Test 68: OK (212514423) -*** Test 76: OK (1610087935) -*** Test 77: OK (1388671) -*** Test 78: OK (134217728) -*** Test 79: OK (70288929) -*** Test 80: OK (17895765) -*** Test 81: OK (387) *** Test 82: OK (8454401) *** Test 83: OK (2835) *** Test 84: OK (934782101) diff --git a/src/testdir/test49.vim b/src/testdir/test49.vim index 9ef91dffa44b02..bc3cfc83d46936 100644 --- a/src/testdir/test49.vim +++ b/src/testdir/test49.vim @@ -648,2468 +648,11 @@ function! MESSAGES(...) return match endfunction -" Leave MESSAGES() for the next tests. - -" Tests 1 to 50, 52 to 57, 87 were moved to test_vimscript.vim -" Tests 25, 26, 32, 33, 41-48, 51, 69-75 were moved to test_trycatch.vim -let Xtest = 59 - -"------------------------------------------------------------------------------- -" -" Test 59: v:exception and v:throwpoint when discarding exceptions {{{1 -" -" When a :catch clause is left by a ":break" etc or an error or -" interrupt exception, v:exception and v:throwpoint are reset. They -" are not affected by an exception that is discarded before being -" caught. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - XloopINIT! 1 2 - - let sfile = expand("") - - function! LineNumber() - return substitute(substitute(v:throwpoint, g:sfile, '', ""), - \ '\D*\(\d*\).*', '\1', "") - endfunction - - command! -nargs=1 SetLineNumber - \ try | throw "line" | catch /.*/ | let = LineNumber() | endtry - - " Check v:exception/v:throwpoint against second/fourth parameter if - " specified, check for being empty else. - function! CHECK(n, ...) - XloopNEXT - let exception = a:0 != 0 ? a:1 : "" " second parameter (optional) - let emsg = a:0 != 0 ? a:2 : "" " third parameter (optional) - let line = a:0 != 0 ? a:3 : 0 " fourth parameter (optional) - let error = 0 - if emsg != "" - " exception is the error number, emsg the English error message text - if exception !~ '^E\d\+$' - Xout "TODO: Add message number for:" emsg - elseif v:lang == "C" || v:lang =~ '^[Ee]n' - if exception == "E492" && emsg == "Not an editor command" - let exception = '^Vim:' . exception . ': ' . emsg - else - let exception = '^Vim(\a\+):' . exception . ': ' . emsg - endif - else - if exception == "E492" - let exception = '^Vim:' . exception - else - let exception = '^Vim(\a\+):' . exception - endif - endif - endif - if exception == "" && v:exception != "" - Xout a:n.": v:exception is set:" v:exception - let error = 1 - elseif exception != "" && v:exception !~ exception - Xout a:n.": v:exception (".v:exception.") does not match" exception - let error = 1 - endif - if line == 0 && v:throwpoint != "" - Xout a:n.": v:throwpoint is set:" v:throwpoint - let error = 1 - elseif line != 0 && v:throwpoint !~ '\<' . line . '\>' - Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line - let error = 1 - endif - if !error - Xloop 1 " X: 2097151 - endif - endfunction - - while 1 - try - throw "x1" - catch /.*/ - break - endtry - endwhile - call CHECK(1) - - while 1 - try - throw "x2" - catch /.*/ - break - finally - call CHECK(2) - endtry - break - endwhile - call CHECK(3) - - while 1 - try - let errcaught = 0 - try - try - throw "x3" - catch /.*/ - SetLineNumber line_before_error - asdf - endtry - catch /.*/ - let errcaught = 1 - call CHECK(4, 'E492', "Not an editor command", - \ line_before_error + 1) - endtry - finally - if !errcaught && $VIMNOERRTHROW - call CHECK(4) - endif - break " discard error for $VIMNOERRTHROW - endtry - endwhile - call CHECK(5) - - Xpath 2097152 " X: 2097152 - - while 1 - try - let intcaught = 0 - try - try - throw "x4" - catch /.*/ - SetLineNumber two_lines_before_interrupt - "INTERRUPT - let dummy = 0 - endtry - catch /.*/ - let intcaught = 1 - call CHECK(6, "Vim:Interrupt", '', - \ two_lines_before_interrupt + 2) - endtry - finally - if !intcaught && $VIMNOINTTHROW - call CHECK(6) - endif - break " discard interrupt for $VIMNOINTTHROW - endtry - endwhile - call CHECK(7) - - Xpath 4194304 " X: 4194304 - - while 1 - try - let errcaught = 0 - try - try -" if 1 - SetLineNumber line_before_throw - throw "x5" - " missing endif - catch /.*/ - Xpath 8388608 " X: 0 - endtry - catch /.*/ - let errcaught = 1 - call CHECK(8, 'E171', "Missing :endif", line_before_throw + 3) - endtry - finally - if !errcaught && $VIMNOERRTHROW - call CHECK(8) - endif - break " discard error for $VIMNOERRTHROW - endtry - endwhile - call CHECK(9) - - Xpath 16777216 " X: 16777216 - - try - while 1 - try - throw "x6" - finally - break - endtry - break - endwhile - catch /.*/ - Xpath 33554432 " X: 0 - endtry - call CHECK(10) - - try - while 1 - try - throw "x7" - finally - break - endtry - break - endwhile - catch /.*/ - Xpath 67108864 " X: 0 - finally - call CHECK(11) - endtry - call CHECK(12) - - while 1 - try - let errcaught = 0 - try - try - throw "x8" - finally - SetLineNumber line_before_error - asdf - endtry - catch /.*/ - let errcaught = 1 - call CHECK(13, 'E492', "Not an editor command", - \ line_before_error + 1) - endtry - finally - if !errcaught && $VIMNOERRTHROW - call CHECK(13) - endif - break " discard error for $VIMNOERRTHROW - endtry - endwhile - call CHECK(14) - - Xpath 134217728 " X: 134217728 - - while 1 - try - let intcaught = 0 - try - try - throw "x9" - finally - SetLineNumber two_lines_before_interrupt - "INTERRUPT - endtry - catch /.*/ - let intcaught = 1 - call CHECK(15, "Vim:Interrupt", '', - \ two_lines_before_interrupt + 2) - endtry - finally - if !intcaught && $VIMNOINTTHROW - call CHECK(15) - endif - break " discard interrupt for $VIMNOINTTHROW - endtry - endwhile - call CHECK(16) - - Xpath 268435456 " X: 268435456 - - while 1 - try - let errcaught = 0 - try - try -" if 1 - SetLineNumber line_before_throw - throw "x10" - " missing endif - finally - call CHECK(17) - endtry - catch /.*/ - let errcaught = 1 - call CHECK(18, 'E171', "Missing :endif", line_before_throw + 3) - endtry - finally - if !errcaught && $VIMNOERRTHROW - call CHECK(18) - endif - break " discard error for $VIMNOERRTHROW - endtry - endwhile - call CHECK(19) - - Xpath 536870912 " X: 536870912 - - while 1 - try - let errcaught = 0 - try - try -" if 1 - SetLineNumber line_before_throw - throw "x11" - " missing endif - endtry - catch /.*/ - let errcaught = 1 - call CHECK(20, 'E171', "Missing :endif", line_before_throw + 3) - endtry - finally - if !errcaught && $VIMNOERRTHROW - call CHECK(20) - endif - break " discard error for $VIMNOERRTHROW - endtry - endwhile - call CHECK(21) - - Xpath 1073741824 " X: 1073741824 - -endif - -Xcheck 2038431743 - - -"------------------------------------------------------------------------------- -" -" Test 60: (Re)throwing v:exception; :echoerr. {{{1 -" -" A user exception can be rethrown after catching by throwing -" v:exception. An error or interrupt exception cannot be rethrown -" because Vim exceptions cannot be faked. A Vim exception using the -" value of v:exception can, however, be triggered by the :echoerr -" command. -"------------------------------------------------------------------------------- - -XpathINIT - -try - try - Xpath 1 " X: 1 - throw "oops" - catch /oops/ - Xpath 2 " X: 2 - throw v:exception " rethrow user exception - catch /.*/ - Xpath 4 " X: 0 - endtry -catch /^oops$/ " catches rethrown user exception - Xpath 8 " X: 8 -catch /.*/ - Xpath 16 " X: 0 -endtry - -function! F() - try - let caught = 0 - try - Xpath 32 " X: 32 - write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e - Xpath 64 " X: 0 - Xout "did_emsg was reset before executing " . - \ "BufWritePost autocommands." - catch /^Vim(write):/ - let caught = 1 - throw v:exception " throw error: cannot fake Vim exception - catch /.*/ - Xpath 128 " X: 0 - finally - Xpath 256 " X: 256 - if !caught && !$VIMNOERRTHROW - Xpath 512 " X: 0 - endif - endtry - catch /^Vim(throw):/ " catches throw error - let caught = caught + 1 - catch /.*/ - Xpath 1024 " X: 0 - finally - Xpath 2048 " X: 2048 - if caught != 2 - if !caught && !$VIMNOERRTHROW - Xpath 4096 " X: 0 - elseif caught - Xpath 8192 " X: 0 - endif - return | " discard error for $VIMNOERRTHROW - endif - endtry -endfunction - -call F() -delfunction F - -function! G() - try - let caught = 0 - try - Xpath 16384 " X: 16384 - asdf - catch /^Vim/ " catch error exception - let caught = 1 - " Trigger Vim error exception with value specified after :echoerr - let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "") - echoerr value - catch /.*/ - Xpath 32768 " X: 0 - finally - Xpath 65536 " X: 65536 - if !caught - if !$VIMNOERRTHROW - Xpath 131072 " X: 0 - else - let value = "Error" - echoerr value - endif - endif - endtry - catch /^Vim(echoerr):/ - let caught = caught + 1 - if v:exception !~ value - Xpath 262144 " X: 0 - endif - catch /.*/ - Xpath 524288 " X: 0 - finally - Xpath 1048576 " X: 1048576 - if caught != 2 - if !caught && !$VIMNOERRTHROW - Xpath 2097152 " X: 0 - elseif caught - Xpath 4194304 " X: 0 - endif - return | " discard error for $VIMNOERRTHROW - endif - endtry -endfunction - -call G() -delfunction G - -unlet! value caught - -if ExtraVim() - try - let errcaught = 0 - try - Xpath 8388608 " X: 8388608 - let intcaught = 0 - "INTERRUPT - catch /^Vim:/ " catch interrupt exception - let intcaught = 1 - " Trigger Vim error exception with value specified after :echoerr - echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "") - catch /.*/ - Xpath 16777216 " X: 0 - finally - Xpath 33554432 " X: 33554432 - if !intcaught - if !$VIMNOINTTHROW - Xpath 67108864 " X: 0 - else - echoerr "Interrupt" - endif - endif - endtry - catch /^Vim(echoerr):/ - let errcaught = 1 - if v:exception !~ "Interrupt" - Xpath 134217728 " X: 0 - endif - finally - Xpath 268435456 " X: 268435456 - if !errcaught && !$VIMNOERRTHROW - Xpath 536870912 " X: 0 - endif - endtry -endif - -Xcheck 311511339 - -" Test 61 was moved to test_vimscript.vim -let Xtest = 62 - -"------------------------------------------------------------------------------- -" Test 62: Catching error exceptions {{{1 -" -" An error inside a :try/:endtry region is converted to an exception -" and can be caught. The error exception has a "Vim(cmdname):" prefix -" where cmdname is the name of the failing command, or a "Vim:" prefix -" if no command name is known. The "Vim" prefixes cannot be faked. -"------------------------------------------------------------------------------- - -XpathINIT - -function! MSG(enr, emsg) - let english = v:lang == "C" || v:lang =~ '^[Ee]n' - if a:enr == "" - Xout "TODO: Add message number for:" a:emsg - let v:errmsg = ":" . v:errmsg - endif - let match = 1 - if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) - let match = 0 - if v:errmsg == "" - Xout "Message missing." - else - let v:errmsg = escape(v:errmsg, '"') - Xout "Unexpected message:" v:errmsg - endif - endif - return match -endfunction - -while 1 - try - try - let caught = 0 - unlet novar - catch /^Vim(unlet):/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "") - finally - Xpath 1 " X: 1 - if !caught && !$VIMNOERRTHROW - Xpath 2 " X: 0 - endif - if !MSG('E108', "No such variable") - Xpath 4 " X: 0 - endif - endtry - catch /.*/ - Xpath 8 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -while 1 - try - try - let caught = 0 - throw novar " error in :throw - catch /^Vim(throw):/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "") - finally - Xpath 16 " X: 16 - if !caught && !$VIMNOERRTHROW - Xpath 32 " X: 0 - endif - if caught ? !MSG('E121', "Undefined variable") - \ : !MSG('E15', "Invalid expression") - Xpath 64 " X: 0 - endif - endtry - catch /.*/ - Xpath 128 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -while 1 - try - try - let caught = 0 - throw "Vim:faked" " error: cannot fake Vim exception - catch /^Vim(throw):/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "") - finally - Xpath 256 " X: 256 - if !caught && !$VIMNOERRTHROW - Xpath 512 " X: 0 - endif - if !MSG('E608', "Cannot :throw exceptions with 'Vim' prefix") - Xpath 1024 " X: 0 - endif - endtry - catch /.*/ - Xpath 2048 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -function! F() - while 1 - " Missing :endwhile -endfunction - -while 1 - try - try - let caught = 0 - call F() - catch /^Vim(endfunction):/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "") - finally - Xpath 4096 " X: 4096 - if !caught && !$VIMNOERRTHROW - Xpath 8192 " X: 0 - endif - if !MSG('E170', "Missing :endwhile") - Xpath 16384 " X: 0 - endif - endtry - catch /.*/ - Xpath 32768 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -while 1 - try - try - let caught = 0 - ExecAsScript F - catch /^Vim:/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim:', '', "") - finally - Xpath 65536 " X: 65536 - if !caught && !$VIMNOERRTHROW - Xpath 131072 " X: 0 - endif - if !MSG('E170', "Missing :endwhile") - Xpath 262144 " X: 0 - endif - endtry - catch /.*/ - Xpath 524288 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -function! G() - call G() -endfunction - -while 1 - try - let mfd_save = &mfd - set mfd=3 - try - let caught = 0 - call G() - catch /^Vim(call):/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(call):', '', "") - finally - Xpath 1048576 " X: 1048576 - if !caught && !$VIMNOERRTHROW - Xpath 2097152 " X: 0 - endif - if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'") - Xpath 4194304 " X: 0 - endif - endtry - catch /.*/ - Xpath 8388608 " X: 0 - Xout v:exception "in" v:throwpoint - finally - let &mfd = mfd_save - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -function! H() - return H() -endfunction - -while 1 - try - let mfd_save = &mfd - set mfd=3 - try - let caught = 0 - call H() - catch /^Vim(return):/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(return):', '', "") - finally - Xpath 16777216 " X: 16777216 - if !caught && !$VIMNOERRTHROW - Xpath 33554432 " X: 0 - endif - if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'") - Xpath 67108864 " X: 0 - endif - endtry - catch /.*/ - Xpath 134217728 " X: 0 - Xout v:exception "in" v:throwpoint - finally - let &mfd = mfd_save - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -unlet! caught mfd_save -delfunction F -delfunction G -delfunction H -Xpath 268435456 " X: 268435456 - -Xcheck 286331153 - -" Leave MSG() for the next test. - - -"------------------------------------------------------------------------------- -" Test 63: Suppressing error exceptions by :silent!. {{{1 -" -" A :silent! command inside a :try/:endtry region suppresses the -" conversion of errors to an exception and the immediate abortion on -" error. When the commands executed by the :silent! themselves open -" a new :try/:endtry region, conversion of errors to exception and -" immediate abortion is switched on again - until the next :silent! -" etc. The :silent! has the effect of setting v:errmsg to the error -" message text (without displaying it) and continuing with the next -" script line. -" -" When a command triggering autocommands is executed by :silent! -" inside a :try/:endtry, the autocommand execution is not suppressed -" on error. -" -" This test reuses the function MSG() from the previous test. -"------------------------------------------------------------------------------- - -XpathINIT - -XloopINIT! 1 4 - -let taken = "" - -function! S(n) abort - XloopNEXT - let g:taken = g:taken . "E" . a:n - let v:errmsg = "" - exec "asdf" . a:n - - " Check that ":silent!" continues: - Xloop 1 - - " Check that ":silent!" sets "v:errmsg": - if MSG('E492', "Not an editor command") - Xloop 2 - endif -endfunction - -function! Foo() - while 1 - try - try - let caught = 0 - " This is not silent: - call S(3) " X: 0 * 16 - catch /^Vim:/ - let caught = 1 - let errmsg3 = substitute(v:exception, '^Vim:', '', "") - silent! call S(4) " X: 3 * 64 - finally - if !caught - let errmsg3 = v:errmsg - " Do call S(4) here if not executed in :catch. - silent! call S(4) - endif - Xpath 1048576 " X: 1048576 - if !caught && !$VIMNOERRTHROW - Xpath 2097152 " X: 0 - endif - let v:errmsg = errmsg3 - if !MSG('E492', "Not an editor command") - Xpath 4194304 " X: 0 - endif - silent! call S(5) " X: 3 * 256 - " Break out of try conditionals that cover ":silent!". This also - " discards the aborting error when $VIMNOERRTHROW is non-zero. - break - endtry - catch /.*/ - Xpath 8388608 " X: 0 - Xout v:exception "in" v:throwpoint - endtry - endwhile - " This is a double ":silent!" (see caller). - silent! call S(6) " X: 3 * 1024 -endfunction - -function! Bar() - try - silent! call S(2) " X: 3 * 4 - " X: 3 * 4096 - silent! execute "call Foo() | call S(7)" - silent! call S(8) " X: 3 * 16384 - endtry " normal end of try cond that covers ":silent!" - " This has a ":silent!" from the caller: - call S(9) " X: 3 * 65536 -endfunction - -silent! call S(1) " X: 3 * 1 -silent! call Bar() -silent! call S(10) " X: 3 * 262144 - -let expected = "E1E2E3E4E5E6E7E8E9E10" -if taken != expected - Xpath 16777216 " X: 0 - Xout "'taken' is" taken "instead of" expected -endif - -augroup TMP - autocmd BufWritePost * Xpath 33554432 " X: 33554432 -augroup END - -Xpath 67108864 " X: 67108864 -write /i/m/p/o/s/s/i/b/l/e -Xpath 134217728 " X: 134217728 - -autocmd! TMP -unlet! caught errmsg3 taken expected -delfunction S -delfunction Foo -delfunction Bar -delfunction MSG - -Xcheck 236978127 - - -"------------------------------------------------------------------------------- -" Test 64: Error exceptions after error, interrupt or :throw {{{1 -" -" When an error occurs after an interrupt or a :throw but before -" a matching :catch is reached, all following :catches of that try -" block are ignored, but the error exception can be caught by the next -" surrounding try conditional. Any previous error exception is -" discarded. An error is ignored when there is a previous error that -" has not been caught. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - while 1 - try - try - Xpath 1 " X: 1 - let caught = 0 - while 1 -" if 1 - " Missing :endif - endwhile " throw error exception - catch /^Vim(/ - let caught = 1 - finally - Xpath 2 " X: 2 - if caught || $VIMNOERRTHROW - Xpath 4 " X: 4 - endif - endtry - catch /.*/ - Xpath 8 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - while 1 - try - try - Xpath 16 " X: 16 - let caught = 0 - try -" if 1 - " Missing :endif - catch /.*/ " throw error exception - Xpath 32 " X: 0 - catch /.*/ - Xpath 64 " X: 0 - endtry - catch /^Vim(/ - let caught = 1 - finally - Xpath 128 " X: 128 - if caught || $VIMNOERRTHROW - Xpath 256 " X: 256 - endif - endtry - catch /.*/ - Xpath 512 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - while 1 - try - try - let caught = 0 - try - Xpath 1024 " X: 1024 - "INTERRUPT - catch /do_not_catch/ - Xpath 2048 " X: 0 -" if 1 - " Missing :endif - catch /.*/ " throw error exception - Xpath 4096 " X: 0 - catch /.*/ - Xpath 8192 " X: 0 - endtry - catch /^Vim(/ - let caught = 1 - finally - Xpath 16384 " X: 16384 - if caught || $VIMNOERRTHROW - Xpath 32768 " X: 32768 - endif - endtry - catch /.*/ - Xpath 65536 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - while 1 - try - try - let caught = 0 - try - Xpath 131072 " X: 131072 - throw "x" - catch /do_not_catch/ - Xpath 262144 " X: 0 -" if 1 - " Missing :endif - catch /x/ " throw error exception - Xpath 524288 " X: 0 - catch /.*/ - Xpath 1048576 " X: 0 - endtry - catch /^Vim(/ - let caught = 1 - finally - Xpath 2097152 " X: 2097152 - if caught || $VIMNOERRTHROW - Xpath 4194304 " X: 4194304 - endif - endtry - catch /.*/ - Xpath 8388608 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - while 1 - try - try - let caught = 0 - Xpath 16777216 " X: 16777216 -" endif " :endif without :if; throw error exception -" if 1 - " Missing :endif - catch /do_not_catch/ " ignore new error - Xpath 33554432 " X: 0 - catch /^Vim(endif):/ - let caught = 1 - catch /^Vim(/ - Xpath 67108864 " X: 0 - finally - Xpath 134217728 " X: 134217728 - if caught || $VIMNOERRTHROW - Xpath 268435456 " X: 268435456 - endif - endtry - catch /.*/ - Xpath 536870912 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - Xpath 1073741824 " X: 1073741824 - -endif - -Xcheck 1499645335 - -" Test 65 was moved to test_vimscript.vim -let Xtest = 66 - -"------------------------------------------------------------------------------- -" Test 66: Stop range :call on error, interrupt, or :throw {{{1 -" -" When a function which is multiply called for a range since it -" doesn't handle the range itself has an error in a command -" dynamically enclosed by :try/:endtry or gets an interrupt or -" executes a :throw, no more calls for the remaining lines in the -" range are made. On an error in a command not dynamically enclosed -" by :try/:endtry, the function is executed again for the remaining -" lines in the range. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - let file = tempname() - exec "edit" file - - insert -line 1 -line 2 -line 3 -. - - XloopINIT! 1 2 - - let taken = "" - let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)" - - function! F(reason, n) abort - let g:taken = g:taken . "F" . a:n . - \ substitute(a:reason, '\(\l\).*', '\u\1', "") . - \ "(" . line(".") . ")" - - if a:reason == "error" - asdf - elseif a:reason == "interrupt" - "INTERRUPT - let dummy = 0 - elseif a:reason == "throw" - throw "xyz" - elseif a:reason == "aborting error" - XloopNEXT - if g:taken != g:expected - Xloop 1 " X: 0 - Xout "'taken' is" g:taken "instead of" g:expected - endif - try - bwipeout! - call delete(file) - asdf - endtry - endif - endfunction - - function! G(reason, n) - let g:taken = g:taken . "G" . a:n . - \ substitute(a:reason, '\(\l\).*', '\u\1', "") - 1,3call F(a:reason, a:n) - endfunction - - Xpath 8 " X: 8 - call G("error", 1) - try - Xpath 16 " X: 16 - try - call G("error", 2) - Xpath 32 " X: 0 - finally - Xpath 64 " X: 64 - try - call G("interrupt", 3) - Xpath 128 " X: 0 - finally - Xpath 256 " X: 256 - try - call G("throw", 4) - Xpath 512 " X: 0 - endtry - endtry - endtry - catch /xyz/ - Xpath 1024 " X: 1024 - catch /.*/ - Xpath 2048 " X: 0 - Xout v:exception "in" ExtraVimThrowpoint() - endtry - Xpath 4096 " X: 4096 - call G("aborting error", 5) - Xpath 8192 " X: 0 - Xout "'taken' is" taken "instead of" expected - -endif - -Xcheck 5464 - - -"------------------------------------------------------------------------------- -" Test 67: :throw across :call command {{{1 -" -" On a call command, an exception might be thrown when evaluating the -" function name, during evaluation of the arguments, or when the -" function is being executed. The exception can be caught by the -" caller. -"------------------------------------------------------------------------------- - -XpathINIT - -function! THROW(x, n) - if a:n == 1 - Xpath 1 " X: 1 - elseif a:n == 2 - Xpath 2 " X: 2 - elseif a:n == 3 - Xpath 4 " X: 4 - endif - throw a:x -endfunction - -function! NAME(x, n) - if a:n == 1 - Xpath 8 " X: 0 - elseif a:n == 2 - Xpath 16 " X: 16 - elseif a:n == 3 - Xpath 32 " X: 32 - elseif a:n == 4 - Xpath 64 " X: 64 - endif - return a:x -endfunction - -function! ARG(x, n) - if a:n == 1 - Xpath 128 " X: 0 - elseif a:n == 2 - Xpath 256 " X: 0 - elseif a:n == 3 - Xpath 512 " X: 512 - elseif a:n == 4 - Xpath 1024 " X: 1024 - endif - return a:x -endfunction - -function! F(x, n) - if a:n == 2 - Xpath 2048 " X: 0 - elseif a:n == 4 - Xpath 4096 " X: 4096 - endif -endfunction - -while 1 - try - let error = 0 - let v:errmsg = "" - - while 1 - try - Xpath 8192 " X: 8192 - call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1) - Xpath 16384 " X: 0 - catch /^name$/ - Xpath 32768 " X: 32768 - catch /.*/ - let error = 1 - Xout "1:" v:exception "in" v:throwpoint - finally - if !error && $VIMNOERRTHROW && v:errmsg != "" - let error = 1 - Xout "1:" v:errmsg - endif - if error - Xpath 65536 " X: 0 - endif - let error = 0 - let v:errmsg = "" - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - while 1 - try - Xpath 131072 " X: 131072 - call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2) - Xpath 262144 " X: 0 - catch /^arg$/ - Xpath 524288 " X: 524288 - catch /.*/ - let error = 1 - Xout "2:" v:exception "in" v:throwpoint - finally - if !error && $VIMNOERRTHROW && v:errmsg != "" - let error = 1 - Xout "2:" v:errmsg - endif - if error - Xpath 1048576 " X: 0 - endif - let error = 0 - let v:errmsg = "" - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - while 1 - try - Xpath 2097152 " X: 2097152 - call {NAME("THROW", 3)}(ARG("call", 3), 3) - Xpath 4194304 " X: 0 - catch /^call$/ - Xpath 8388608 " X: 8388608 - catch /^0$/ " default return value - Xpath 16777216 " X: 0 - Xout "3:" v:throwpoint - catch /.*/ - let error = 1 - Xout "3:" v:exception "in" v:throwpoint - finally - if !error && $VIMNOERRTHROW && v:errmsg != "" - let error = 1 - Xout "3:" v:errmsg - endif - if error - Xpath 33554432 " X: 0 - endif - let error = 0 - let v:errmsg = "" - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - while 1 - try - Xpath 67108864 " X: 67108864 - call {NAME("F", 4)}(ARG(4711, 4), 4) - Xpath 134217728 " X: 134217728 - catch /.*/ - let error = 1 - Xout "4:" v:exception "in" v:throwpoint - finally - if !error && $VIMNOERRTHROW && v:errmsg != "" - let error = 1 - Xout "4:" v:errmsg - endif - if error - Xpath 268435456 " X: 0 - endif - let error = 0 - let v:errmsg = "" - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - catch /^0$/ " default return value - Xpath 536870912 " X: 0 - Xout v:throwpoint - catch /.*/ - let error = 1 - Xout v:exception "in" v:throwpoint - finally - if !error && $VIMNOERRTHROW && v:errmsg != "" - let error = 1 - Xout v:errmsg - endif - if error - Xpath 1073741824 " X: 0 - endif - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -unlet error -delfunction F - -Xcheck 212514423 - -" Leave THROW(), NAME(), and ARG() for the next test. - - -"------------------------------------------------------------------------------- -" Test 68: :throw across function calls in expressions {{{1 -" -" On a function call within an expression, an exception might be -" thrown when evaluating the function name, during evaluation of the -" arguments, or when the function is being executed. The exception -" can be caught by the caller. -" -" This test reuses the functions THROW(), NAME(), and ARG() from the -" previous test. -"------------------------------------------------------------------------------- - -XpathINIT - -function! F(x, n) - if a:n == 2 - Xpath 2048 " X: 0 - elseif a:n == 4 - Xpath 4096 " X: 4096 - endif - return a:x -endfunction - -unlet! var1 var2 var3 var4 - -while 1 - try - let error = 0 - let v:errmsg = "" - - while 1 - try - Xpath 8192 " X: 8192 - let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1) - Xpath 16384 " X: 0 - catch /^name$/ - Xpath 32768 " X: 32768 - catch /.*/ - let error = 1 - Xout "1:" v:exception "in" v:throwpoint - finally - if !error && $VIMNOERRTHROW && v:errmsg != "" - let error = 1 - Xout "1:" v:errmsg - endif - if error - Xpath 65536 " X: 0 - endif - let error = 0 - let v:errmsg = "" - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - while 1 - try - Xpath 131072 " X: 131072 - let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2) - Xpath 262144 " X: 0 - catch /^arg$/ - Xpath 524288 " X: 524288 - catch /.*/ - let error = 1 - Xout "2:" v:exception "in" v:throwpoint - finally - if !error && $VIMNOERRTHROW && v:errmsg != "" - let error = 1 - Xout "2:" v:errmsg - endif - if error - Xpath 1048576 " X: 0 - endif - let error = 0 - let v:errmsg = "" - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - while 1 - try - Xpath 2097152 " X: 2097152 - let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3) - Xpath 4194304 " X: 0 - catch /^call$/ - Xpath 8388608 " X: 8388608 - catch /^0$/ " default return value - Xpath 16777216 " X: 0 - Xout "3:" v:throwpoint - catch /.*/ - let error = 1 - Xout "3:" v:exception "in" v:throwpoint - finally - if !error && $VIMNOERRTHROW && v:errmsg != "" - let error = 1 - Xout "3:" v:errmsg - endif - if error - Xpath 33554432 " X: 0 - endif - let error = 0 - let v:errmsg = "" - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - while 1 - try - Xpath 67108864 " X: 67108864 - let var4 = {NAME("F", 4)}(ARG(4711, 4), 4) - Xpath 134217728 " X: 134217728 - catch /.*/ - let error = 1 - Xout "4:" v:exception "in" v:throwpoint - finally - if !error && $VIMNOERRTHROW && v:errmsg != "" - let error = 1 - Xout "4:" v:errmsg - endif - if error - Xpath 268435456 " X: 0 - endif - let error = 0 - let v:errmsg = "" - break " discard error for $VIMNOERRTHROW - endtry - endwhile - - catch /^0$/ " default return value - Xpath 536870912 " X: 0 - Xout v:throwpoint - catch /.*/ - let error = 1 - Xout v:exception "in" v:throwpoint - finally - if !error && $VIMNOERRTHROW && v:errmsg != "" - let error = 1 - Xout v:errmsg - endif - if error - Xpath 1073741824 " X: 0 - endif - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -if exists("var1") || exists("var2") || exists("var3") || - \ !exists("var4") || var4 != 4711 - " The Xpath command does not accept 2^31 (negative); add explicitly: - let Xpath = Xpath + 2147483648 " X: 0 - if exists("var1") - Xout "var1 =" var1 - endif - if exists("var2") - Xout "var2 =" var2 - endif - if exists("var3") - Xout "var3 =" var3 - endif - if !exists("var4") - Xout "var4 unset" - elseif var4 != 4711 - Xout "var4 =" var4 - endif -endif - -unlet! error var1 var2 var3 var4 -delfunction THROW -delfunction NAME -delfunction ARG -delfunction F - -Xcheck 212514423 - -" Tests 69 to 75 were moved to test_trycatch.vim -let Xtest = 76 - - -"------------------------------------------------------------------------------- -" Test 76: Errors, interrupts, :throw during expression evaluation {{{1 -" -" When a function call made during expression evaluation is aborted -" due to an error inside a :try/:endtry region or due to an interrupt -" or a :throw, the expression evaluation is aborted as well. No -" message is displayed for the cancelled expression evaluation. On an -" error not inside :try/:endtry, the expression evaluation continues. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - let taken = "" - - function! ERR(n) - let g:taken = g:taken . "E" . a:n - asdf - endfunction - - function! ERRabort(n) abort - let g:taken = g:taken . "A" . a:n - asdf - endfunction " returns -1; may cause follow-up msg for illegal var/func name - - function! WRAP(n, arg) - let g:taken = g:taken . "W" . a:n - let g:saved_errmsg = v:errmsg - return arg - endfunction - - function! INT(n) - let g:taken = g:taken . "I" . a:n - "INTERRUPT9 - let dummy = 0 - endfunction - - function! THR(n) - let g:taken = g:taken . "T" . a:n - throw "should not be caught" - endfunction - - function! CONT(n) - let g:taken = g:taken . "C" . a:n - endfunction - - function! MSG(n) - let g:taken = g:taken . "M" . a:n - let errmsg = (a:n >= 37 && a:n <= 44) ? g:saved_errmsg : v:errmsg - let msgptn = (a:n >= 10 && a:n <= 27) ? "^$" : "asdf" - if errmsg !~ msgptn - let g:taken = g:taken . "x" - Xout "Expr" a:n.": Unexpected message:" v:errmsg - endif - let v:errmsg = "" - let g:saved_errmsg = "" - endfunction - - let v:errmsg = "" - - try - let t = 1 - XloopINIT 1 2 - while t <= 9 - Xloop 1 " X: 511 - try - if t == 1 - let v{ERR(t) + CONT(t)} = 0 - elseif t == 2 - let v{ERR(t) + CONT(t)} - elseif t == 3 - let var = exists('v{ERR(t) + CONT(t)}') - elseif t == 4 - unlet v{ERR(t) + CONT(t)} - elseif t == 5 - function F{ERR(t) + CONT(t)}() - endfunction - elseif t == 6 - function F{ERR(t) + CONT(t)} - elseif t == 7 - let var = exists('*F{ERR(t) + CONT(t)}') - elseif t == 8 - delfunction F{ERR(t) + CONT(t)} - elseif t == 9 - let var = ERR(t) + CONT(t) - endif - catch /asdf/ - " v:errmsg is not set when the error message is converted to an - " exception. Set it to the original error message. - let v:errmsg = substitute(v:exception, '^Vim:', '', "") - catch /^Vim\((\a\+)\)\=:/ - " An error exception has been thrown after the original error. - let v:errmsg = "" - finally - call MSG(t) - let t = t + 1 - XloopNEXT - continue " discard an aborting error - endtry - endwhile - catch /.*/ - Xpath 512 " X: 0 - Xout v:exception "in" ExtraVimThrowpoint() - endtry - - try - let t = 10 - XloopINIT 1024 2 - while t <= 18 - Xloop 1 " X: 1024 * 511 - try - if t == 10 - let v{INT(t) + CONT(t)} = 0 - elseif t == 11 - let v{INT(t) + CONT(t)} - elseif t == 12 - let var = exists('v{INT(t) + CONT(t)}') - elseif t == 13 - unlet v{INT(t) + CONT(t)} - elseif t == 14 - function F{INT(t) + CONT(t)}() - endfunction - elseif t == 15 - function F{INT(t) + CONT(t)} - elseif t == 16 - let var = exists('*F{INT(t) + CONT(t)}') - elseif t == 17 - delfunction F{INT(t) + CONT(t)} - elseif t == 18 - let var = INT(t) + CONT(t) - endif - catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/ - " An error exception has been triggered after the interrupt. - let v:errmsg = substitute(v:exception, - \ '^Vim\((\a\+)\)\=:', '', "") - finally - call MSG(t) - let t = t + 1 - XloopNEXT - continue " discard interrupt - endtry - endwhile - catch /.*/ - Xpath 524288 " X: 0 - Xout v:exception "in" ExtraVimThrowpoint() - endtry - - try - let t = 19 - XloopINIT 1048576 2 - while t <= 27 - Xloop 1 " X: 1048576 * 511 - try - if t == 19 - let v{THR(t) + CONT(t)} = 0 - elseif t == 20 - let v{THR(t) + CONT(t)} - elseif t == 21 - let var = exists('v{THR(t) + CONT(t)}') - elseif t == 22 - unlet v{THR(t) + CONT(t)} - elseif t == 23 - function F{THR(t) + CONT(t)}() - endfunction - elseif t == 24 - function F{THR(t) + CONT(t)} - elseif t == 25 - let var = exists('*F{THR(t) + CONT(t)}') - elseif t == 26 - delfunction F{THR(t) + CONT(t)} - elseif t == 27 - let var = THR(t) + CONT(t) - endif - catch /^Vim\((\a\+)\)\=:/ - " An error exception has been triggered after the :throw. - let v:errmsg = substitute(v:exception, - \ '^Vim\((\a\+)\)\=:', '', "") - finally - call MSG(t) - let t = t + 1 - XloopNEXT - continue " discard exception - endtry - endwhile - catch /.*/ - Xpath 536870912 " X: 0 - Xout v:exception "in" ExtraVimThrowpoint() - endtry - - let v{ERR(28) + CONT(28)} = 0 - call MSG(28) - let v{ERR(29) + CONT(29)} - call MSG(29) - let var = exists('v{ERR(30) + CONT(30)}') - call MSG(30) - unlet v{ERR(31) + CONT(31)} - call MSG(31) - function F{ERR(32) + CONT(32)}() - endfunction - call MSG(32) - function F{ERR(33) + CONT(33)} - call MSG(33) - let var = exists('*F{ERR(34) + CONT(34)}') - call MSG(34) - delfunction F{ERR(35) + CONT(35)} - call MSG(35) - let var = ERR(36) + CONT(36) - call MSG(36) - - let saved_errmsg = "" - - let v{WRAP(37, ERRabort(37)) + CONT(37)} = 0 - call MSG(37) - let v{WRAP(38, ERRabort(38)) + CONT(38)} - call MSG(38) - let var = exists('v{WRAP(39, ERRabort(39)) + CONT(39)}') - call MSG(39) - unlet v{WRAP(40, ERRabort(40)) + CONT(40)} - call MSG(40) - function F{WRAP(41, ERRabort(41)) + CONT(41)}() - endfunction - call MSG(41) - function F{WRAP(42, ERRabort(42)) + CONT(42)} - call MSG(42) - let var = exists('*F{WRAP(43, ERRabort(43)) + CONT(43)}') - call MSG(43) - delfunction F{WRAP(44, ERRabort(44)) + CONT(44)} - call MSG(44) - let var = ERRabort(45) + CONT(45) - call MSG(45) - - Xpath 1073741824 " X: 1073741824 - - let expected = "" - \ . "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9" - \ . "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18" - \ . "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27" - \ . "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33" - \ . "E34C34M34E35C35M35E36C36M36" - \ . "A37W37C37M37A38W38C38M38A39W39C39M39A40W40C40M40A41W41C41M41" - \ . "A42W42C42M42A43W43C43M43A44W44C44M44A45C45M45" - - if taken != expected - " The Xpath command does not accept 2^31 (negative); display explicitly: - exec "!echo 2147483648 >>" . g:ExtraVimResult - " X: 0 - Xout "'taken' is" taken "instead of" expected - if substitute(taken, - \ '\(.*\)E3C3M3x\(.*\)E30C30M30x\(.*\)A39C39M39x\(.*\)', - \ '\1E3M3\2E30C30M30\3A39C39M39\4', - \ "") == expected - Xout "Is ++emsg_skip for var with expr_start non-NULL" - \ "in f_exists ok?" - endif - endif - - unlet! v var saved_errmsg taken expected - call delete(WA_t5) - call delete(WA_t14) - call delete(WA_t23) - unlet! WA_t5 WA_t14 WA_t23 - delfunction WA_t5 - delfunction WA_t14 - delfunction WA_t23 - -endif - -Xcheck 1610087935 - - -"------------------------------------------------------------------------------- -" Test 77: Errors, interrupts, :throw in name{brace-expression} {{{1 -" -" When a function call made during evaluation of an expression in -" braces as part of a function name after ":function" is aborted due -" to an error inside a :try/:endtry region or due to an interrupt or -" a :throw, the expression evaluation is aborted as well, and the -" function definition is ignored, skipping all commands to the -" ":endfunction". On an error not inside :try/:endtry, the expression -" evaluation continues and the function gets defined, and can be -" called and deleted. -"------------------------------------------------------------------------------- - -XpathINIT - -XloopINIT 1 4 - -function! ERR() abort - Xloop 1 " X: 1 + 4 + 16 + 64 - asdf -endfunction " returns -1 - -function! OK() - Xloop 2 " X: 2 * (1 + 4 + 16) - let v:errmsg = "" - return 0 -endfunction - -let v:errmsg = "" - -Xpath 4096 " X: 4096 -function! F{1 + ERR() + OK()}(arg) - " F0 should be defined. - if exists("a:arg") && a:arg == "calling" - Xpath 8192 " X: 8192 - else - Xpath 16384 " X: 0 - endif -endfunction -if v:errmsg != "" - Xpath 32768 " X: 0 -endif -XloopNEXT - -Xpath 65536 " X: 65536 -call F{1 + ERR() + OK()}("calling") -if v:errmsg != "" - Xpath 131072 " X: 0 -endif -XloopNEXT - -Xpath 262144 " X: 262144 -delfunction F{1 + ERR() + OK()} -if v:errmsg != "" - Xpath 524288 " X: 0 -endif -XloopNEXT - -try - while 1 - let caught = 0 - try - Xpath 1048576 " X: 1048576 - function! G{1 + ERR() + OK()}(arg) - " G0 should not be defined, and the function body should be - " skipped. - if exists("a:arg") && a:arg == "calling" - Xpath 2097152 " X: 0 - else - Xpath 4194304 " X: 0 - endif - " Use an unmatched ":finally" to check whether the body is - " skipped when an error occurs in ERR(). This works whether or - " not the exception is converted to an exception. - finally - Xpath 8388608 " X: 0 - Xout "Body of G{1 + ERR() + OK()}() not skipped" - " Discard the aborting error or exception, and break the - " while loop. - break - " End the try conditional and start a new one to avoid - " ":catch after :finally" errors. - endtry - try - Xpath 16777216 " X: 0 - endfunction - - " When the function was not defined, this won't be reached - whether - " the body was skipped or not. When the function was defined, it - " can be called and deleted here. - Xpath 33554432 " X: 0 - Xout "G0() has been defined" - XloopNEXT - try - call G{1 + ERR() + OK()}("calling") - catch /.*/ - Xpath 67108864 " X: 0 - endtry - Xpath 134217728 " X: 0 - XloopNEXT - try - delfunction G{1 + ERR() + OK()} - catch /.*/ - Xpath 268435456 " X: 0 - endtry - catch /asdf/ - " Jumped to when the function is not defined and the body is - " skipped. - let caught = 1 - catch /.*/ - Xpath 536870912 " X: 0 - finally - if !caught && !$VIMNOERRTHROW - Xpath 1073741824 " X: 0 - endif - break " discard error for $VIMNOERRTHROW - endtry " jumped to when the body is not skipped - endwhile -catch /.*/ - " The Xpath command does not accept 2^31 (negative); add explicitly: - let Xpath = Xpath + 2147483648 " X: 0 - Xout "Body of G{1 + ERR() + OK()}() not skipped, exception caught" - Xout v:exception "in" v:throwpoint -endtry - -Xcheck 1388671 - - -"------------------------------------------------------------------------------- -" Test 78: Messages on parsing errors in expression evaluation {{{1 -" -" When an expression evaluation detects a parsing error, an error -" message is given and converted to an exception, and the expression -" evaluation is aborted. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - let taken = "" - - function! F(n) - let g:taken = g:taken . "F" . a:n - endfunction - - function! MSG(n, enr, emsg) - let g:taken = g:taken . "M" . a:n - let english = v:lang == "C" || v:lang =~ '^[Ee]n' - if a:enr == "" - Xout "TODO: Add message number for:" a:emsg - let v:errmsg = ":" . v:errmsg - endif - if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) - if v:errmsg == "" - Xout "Expr" a:n.": Message missing." - let g:taken = g:taken . "x" - else - let v:errmsg = escape(v:errmsg, '"') - Xout "Expr" a:n.": Unexpected message:" v:errmsg - Xout "Expected: " . a:enr . ': ' . a:emsg - let g:taken = g:taken . "X" - endif - endif - endfunction - - function! CONT(n) - let g:taken = g:taken . "C" . a:n - endfunction - - let v:errmsg = "" - XloopINIT 1 2 - - try - let t = 1 - while t <= 14 - let g:taken = g:taken . "T" . t - let v:errmsg = "" - try - let caught = 0 - if t == 1 - let v{novar + CONT(t)} = 0 - elseif t == 2 - let v{novar + CONT(t)} - elseif t == 3 - let var = exists('v{novar + CONT(t)}') - elseif t == 4 - unlet v{novar + CONT(t)} - elseif t == 5 - function F{novar + CONT(t)}() - endfunction - elseif t == 6 - function F{novar + CONT(t)} - elseif t == 7 - let var = exists('*F{novar + CONT(t)}') - elseif t == 8 - delfunction F{novar + CONT(t)} - elseif t == 9 - echo novar + CONT(t) - elseif t == 10 - echo v{novar + CONT(t)} - elseif t == 11 - echo F{novar + CONT(t)} - elseif t == 12 - let var = novar + CONT(t) - elseif t == 13 - let var = v{novar + CONT(t)} - elseif t == 14 - let var = F{novar + CONT(t)}() - endif - catch /^Vim\((\a\+)\)\=:/ - " v:errmsg is not set when the error message is converted to an - " exception. Set it to the original error message. - let v:errmsg = substitute(v:exception, - \ '^Vim\((\a\+)\)\=:', '', "") - let caught = 1 - finally - if t <= 8 && t != 3 && t != 7 - call MSG(t, 'E475', 'Invalid argument\>') - else - if !caught " no error exceptions ($VIMNOERRTHROW set) - call MSG(t, 'E15', "Invalid expression") - else - call MSG(t, 'E121', "Undefined variable") - endif - endif - let t = t + 1 - XloopNEXT - continue " discard an aborting error - endtry - endwhile - catch /.*/ - Xloop 1 " X: 0 - Xout t.":" v:exception "in" ExtraVimThrowpoint() - endtry - - function! T(n, expr, enr, emsg) - try - let g:taken = g:taken . "T" . a:n - let v:errmsg = "" - try - let caught = 0 - execute "let var = " . a:expr - catch /^Vim\((\a\+)\)\=:/ - " v:errmsg is not set when the error message is converted to an - " exception. Set it to the original error message. - let v:errmsg = substitute(v:exception, - \ '^Vim\((\a\+)\)\=:', '', "") - let caught = 1 - finally - if !caught " no error exceptions ($VIMNOERRTHROW set) - call MSG(a:n, 'E15', "Invalid expression") - else - call MSG(a:n, a:enr, a:emsg) - endif - XloopNEXT - " Discard an aborting error: - return - endtry - catch /.*/ - Xloop 1 " X: 0 - Xout a:n.":" v:exception "in" ExtraVimThrowpoint() - endtry - endfunction - - call T(15, 'Nofunc() + CONT(15)', 'E117', "Unknown function") - call T(16, 'F(1 2 + CONT(16))', 'E116', "Invalid arguments") - call T(17, 'F(1, 2) + CONT(17)', 'E118', "Too many arguments") - call T(18, 'F() + CONT(18)', 'E119', "Not enough arguments") - call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'") - call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'") - call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression") - call T(22, '1 2 + CONT(22)', 'E15', "Invalid expression") - call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'") - call T(24, '("abc) + CONT(24)', 'E114', "Missing quote") - call T(25, "('abc) + CONT(25)", 'E115', "Missing quote") - call T(26, '& + CONT(26)', 'E112', "Option name missing") - call T(27, '&asdf + CONT(27)', 'E113', "Unknown option") - - Xpath 134217728 " X: 134217728 - - let expected = "" - \ . "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14" - \ . "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25" - \ . "T26M26T27M27" - - if taken != expected - Xpath 268435456 " X: 0 - Xout "'taken' is" taken "instead of" expected - if substitute(taken, '\(.*\)T3M3x\(.*\)', '\1T3M3\2', "") == expected - Xout "Is ++emsg_skip for var with expr_start non-NULL" - \ "in f_exists ok?" - endif - endif - - unlet! var caught taken expected - call delete(WA_t5) - unlet! WA_t5 - delfunction WA_t5 - -endif - -Xcheck 134217728 - - -"------------------------------------------------------------------------------- -" Test 79: Throwing one of several errors for the same command {{{1 -" -" When several errors appear in a row (for instance during expression -" evaluation), the first as the most specific one is used when -" throwing an error exception. If, however, a syntax error is -" detected afterwards, this one is used for the error exception. -" On a syntax error, the next command is not executed, on a normal -" error, however, it is (relevant only in a function without the -" "abort" flag). v:errmsg is not set. -" -" If throwing error exceptions is configured off, v:errmsg is always -" set to the latest error message, that is, to the more general -" message or the syntax error, respectively. -"------------------------------------------------------------------------------- - -XpathINIT - -XloopINIT 1 2 - -function! NEXT(cmd) - exec a:cmd . " | Xloop 1" -endfunction - -call NEXT('echo novar') " X: 1 * 1 (checks nextcmd) -XloopNEXT -call NEXT('let novar #') " X: 0 * 2 (skips nextcmd) -XloopNEXT -call NEXT('unlet novar #') " X: 0 * 4 (skips nextcmd) -XloopNEXT -call NEXT('let {novar}') " X: 0 * 8 (skips nextcmd) -XloopNEXT -call NEXT('unlet{ novar}') " X: 0 * 16 (skips nextcmd) - -function! EXEC(cmd) - exec a:cmd -endfunction - -function! MATCH(expected, msg, enr, emsg) - let msg = a:msg - if a:enr == "" - Xout "TODO: Add message number for:" a:emsg - let msg = ":" . msg - endif - let english = v:lang == "C" || v:lang =~ '^[Ee]n' - if msg !~ '^'.a:enr.':' || (english && msg !~ a:emsg) - let match = 0 - if a:expected " no match although expected - if a:msg == "" - Xout "Message missing." - else - let msg = escape(msg, '"') - Xout "Unexpected message:" msg - Xout "Expected:" a:enr . ": " . a:emsg - endif - endif - else - let match = 1 - if !a:expected " match although not expected - let msg = escape(msg, '"') - Xout "Unexpected message:" msg - Xout "Expected none." - endif - endif - return match -endfunction - -try - - while 1 " dummy loop - try - let v:errmsg = "" - let caught = 0 - let thrmsg = "" - call EXEC('echo novar') " normal error - catch /^Vim\((\a\+)\)\=:/ - let caught = 1 - let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") - finally - Xpath 32 " X: 32 - if !caught - if !$VIMNOERRTHROW - Xpath 64 " X: 0 - endif - elseif !MATCH(1, thrmsg, 'E121', "Undefined variable") - \ || v:errmsg != "" - Xpath 128 " X: 0 - endif - if !caught && !MATCH(1, v:errmsg, 'E15', "Invalid expression") - Xpath 256 " X: 0 - endif - break " discard error if $VIMNOERRTHROW == 1 - endtry - endwhile - - Xpath 512 " X: 512 - let cmd = "let" - XloopINIT 1024 32 - while cmd != "" - try - let v:errmsg = "" - let caught = 0 - let thrmsg = "" - call EXEC(cmd . ' novar #') " normal plus syntax error - catch /^Vim\((\a\+)\)\=:/ - let caught = 1 - let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") - finally - Xloop 1 " X: 1024 * (1 + 32) - if !caught - if !$VIMNOERRTHROW - Xloop 2 " X: 0 - endif - else - if cmd == "let" - let match = MATCH(0, thrmsg, 'E121', "Undefined variable") - elseif cmd == "unlet" - let match = MATCH(0, thrmsg, 'E108', "No such variable") - endif - if match " normal error - Xloop 4 " X: 0 - endif - if !MATCH(1, thrmsg, 'E488', "Trailing characters") - \|| v:errmsg != "" - " syntax error - Xloop 8 " X: 0 - endif - endif - if !caught && !MATCH(1, v:errmsg, 'E488', "Trailing characters") - " last error - Xloop 16 " X: 0 - endif - if cmd == "let" - let cmd = "unlet" - else - let cmd = "" - endif - XloopNEXT - continue " discard error if $VIMNOERRTHROW == 1 - endtry - endwhile - - Xpath 1048576 " X: 1048576 - let cmd = "let" - XloopINIT 2097152 32 - while cmd != "" - try - let v:errmsg = "" - let caught = 0 - let thrmsg = "" - call EXEC(cmd . ' {novar}') " normal plus syntax error - catch /^Vim\((\a\+)\)\=:/ - let caught = 1 - let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") - finally - Xloop 1 " X: 2097152 * (1 + 32) - if !caught - if !$VIMNOERRTHROW - Xloop 2 " X: 0 - endif - else - if MATCH(0, thrmsg, 'E121', "Undefined variable") " normal error - Xloop 4 " X: 0 - endif - if !MATCH(1, thrmsg, 'E475', 'Invalid argument\>') - \ || v:errmsg != "" " syntax error - Xloop 8 " X: 0 - endif - endif - if !caught && !MATCH(1, v:errmsg, 'E475', 'Invalid argument\>') - " last error - Xloop 16 " X: 0 - endif - if cmd == "let" - let cmd = "unlet" - else - let cmd = "" - endif - XloopNEXT - continue " discard error if $VIMNOERRTHROW == 1 - endtry - endwhile - -catch /.*/ - " The Xpath command does not accept 2^31 (negative); add explicitly: - let Xpath = Xpath + 2147483648 " X: 0 - Xout v:exception "in" v:throwpoint -endtry - -unlet! next_command thrmsg match -delfunction NEXT -delfunction EXEC -delfunction MATCH - -Xcheck 70288929 - - -"------------------------------------------------------------------------------- -" Test 80: Syntax error in expression for illegal :elseif {{{1 -" -" If there is a syntax error in the expression after an illegal -" :elseif, an error message is given (or an error exception thrown) -" for the illegal :elseif rather than the expression error. -"------------------------------------------------------------------------------- - -XpathINIT - -function! MSG(enr, emsg) - let english = v:lang == "C" || v:lang =~ '^[Ee]n' - if a:enr == "" - Xout "TODO: Add message number for:" a:emsg - let v:errmsg = ":" . v:errmsg - endif - let match = 1 - if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) - let match = 0 - if v:errmsg == "" - Xout "Message missing." - else - let v:errmsg = escape(v:errmsg, '"') - Xout "Unexpected message:" v:errmsg - endif - endif - return match -endfunction - -let v:errmsg = "" -if 0 -else -elseif 1 ||| 2 -endif -Xpath 1 " X: 1 -if !MSG('E584', ":elseif after :else") - Xpath 2 " X: 0 -endif - -let v:errmsg = "" -if 1 -else -elseif 1 ||| 2 -endif -Xpath 4 " X: 4 -if !MSG('E584', ":elseif after :else") - Xpath 8 " X: 0 -endif - -let v:errmsg = "" -elseif 1 ||| 2 -Xpath 16 " X: 16 -if !MSG('E582', ":elseif without :if") - Xpath 32 " X: 0 -endif - -let v:errmsg = "" -while 1 - elseif 1 ||| 2 -endwhile -Xpath 64 " X: 64 -if !MSG('E582', ":elseif without :if") - Xpath 128 " X: 0 -endif - -while 1 - try - try - let v:errmsg = "" - let caught = 0 - if 0 - else - elseif 1 ||| 2 - endif - catch /^Vim\((\a\+)\)\=:/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") - finally - Xpath 256 " X: 256 - if !caught && !$VIMNOERRTHROW - Xpath 512 " X: 0 - endif - if !MSG('E584', ":elseif after :else") - Xpath 1024 " X: 0 - endif - endtry - catch /.*/ - Xpath 2048 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -while 1 - try - try - let v:errmsg = "" - let caught = 0 - if 1 - else - elseif 1 ||| 2 - endif - catch /^Vim\((\a\+)\)\=:/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") - finally - Xpath 4096 " X: 4096 - if !caught && !$VIMNOERRTHROW - Xpath 8192 " X: 0 - endif - if !MSG('E584', ":elseif after :else") - Xpath 16384 " X: 0 - endif - endtry - catch /.*/ - Xpath 32768 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -while 1 - try - try - let v:errmsg = "" - let caught = 0 - elseif 1 ||| 2 - catch /^Vim\((\a\+)\)\=:/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") - finally - Xpath 65536 " X: 65536 - if !caught && !$VIMNOERRTHROW - Xpath 131072 " X: 0 - endif - if !MSG('E582', ":elseif without :if") - Xpath 262144 " X: 0 - endif - endtry - catch /.*/ - Xpath 524288 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -while 1 - try - try - let v:errmsg = "" - let caught = 0 - while 1 - elseif 1 ||| 2 - endwhile - catch /^Vim\((\a\+)\)\=:/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") - finally - Xpath 1048576 " X: 1048576 - if !caught && !$VIMNOERRTHROW - Xpath 2097152 " X: 0 - endif - if !MSG('E582', ":elseif without :if") - Xpath 4194304 " X: 0 - endif - endtry - catch /.*/ - Xpath 8388608 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -Xpath 16777216 " X: 16777216 - -unlet! caught -delfunction MSG - -Xcheck 17895765 - - -"------------------------------------------------------------------------------- -" Test 81: Discarding exceptions after an error or interrupt {{{1 -" -" When an exception is thrown from inside a :try conditional without -" :catch and :finally clauses and an error or interrupt occurs before -" the :endtry is reached, the exception is discarded. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - try - Xpath 1 " X: 1 - try - Xpath 2 " X: 2 - throw "arrgh" - Xpath 4 " X: 0 -" if 1 - Xpath 8 " X: 0 - " error after :throw: missing :endif - endtry - Xpath 16 " X: 0 - catch /arrgh/ - Xpath 32 " X: 0 - endtry - Xpath 64 " X: 0 -endif - -if ExtraVim() - try - Xpath 128 " X: 128 - try - Xpath 256 " X: 256 - throw "arrgh" - Xpath 512 " X: 0 - endtry " INTERRUPT - Xpath 1024 " X: 0 - catch /arrgh/ - Xpath 2048 " X: 0 - endtry - Xpath 4096 " X: 0 -endif - -Xcheck 387 - +" Following tests were moved to test_vimscript.vim: +" 1-24, 27-31, 34-40, 49-50, 52-68, 76-81, 87 +" Following tests were moved to test_trycatch.vim: +" 25-26, 32-33, 41-48, 51, 69-75 +let Xtest = 82 "------------------------------------------------------------------------------- " Test 82: Ignoring :catch clauses after an error or interrupt {{{1 diff --git a/src/testdir/test_vimscript.vim b/src/testdir/test_vimscript.vim index 02cf2d1c484302..e63f647bb5bc72 100644 --- a/src/testdir/test_vimscript.vim +++ b/src/testdir/test_vimscript.vim @@ -23,6 +23,7 @@ com! -nargs=1 Xout call Xout() " file. If the test passes successfully, then Xtest.out should be empty. func RunInNewVim(test, verify) let init =<< trim END + set cpo-=C " support line-continuation in sourced script source script_util.vim XpathINIT XloopINIT @@ -3719,6 +3720,381 @@ func Test_execption_info_for_error() call RunInNewVim(test, verify) endfunc +"------------------------------------------------------------------------------- +" +" Test 59: v:exception and v:throwpoint when discarding exceptions {{{1 +" +" When a :catch clause is left by a ":break" etc or an error or +" interrupt exception, v:exception and v:throwpoint are reset. They +" are not affected by an exception that is discarded before being +" caught. +"------------------------------------------------------------------------------- +func Test_exception_info_on_discard() + CheckEnglish + + let test =<< trim [CODE] + let sfile = expand("") + + while 1 + try + throw "x1" + catch /.*/ + break + endtry + endwhile + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + + while 1 + try + throw "x2" + catch /.*/ + break + finally + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + endtry + break + endwhile + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + + while 1 + try + let errcaught = 0 + try + try + throw "x3" + catch /.*/ + let lnum = expand("") + asdf + endtry + catch /.*/ + let errcaught = 1 + call assert_match('Vim:E492: Not an editor command:', v:exception) + call assert_match('line ' .. (lnum + 1), v:throwpoint) + endtry + finally + call assert_equal(1, errcaught) + break + endtry + endwhile + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + + Xpath 'a' + + while 1 + try + let intcaught = 0 + try + try + throw "x4" + catch /.*/ + let lnum = expand("") + call interrupt() + endtry + catch /.*/ + let intcaught = 1 + call assert_match('Vim:Interrupt', v:exception) + call assert_match('line ' .. (lnum + 1), v:throwpoint) + endtry + finally + call assert_equal(1, intcaught) + break + endtry + endwhile + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + + Xpath 'b' + + while 1 + try + let errcaught = 0 + try + try + if 1 + let lnum = expand("") + throw "x5" + " missing endif + catch /.*/ + call assert_report('should not get here') + endtry + catch /.*/ + let errcaught = 1 + call assert_match('Vim(catch):E171: Missing :endif:', v:exception) + call assert_match('line ' .. (lnum + 3), v:throwpoint) + endtry + finally + call assert_equal(1, errcaught) + break + endtry + endwhile + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + + Xpath 'c' + + try + while 1 + try + throw "x6" + finally + break + endtry + break + endwhile + catch /.*/ + call assert_report('should not get here') + endtry + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + + try + while 1 + try + throw "x7" + finally + break + endtry + break + endwhile + catch /.*/ + call assert_report('should not get here') + finally + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + endtry + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + + while 1 + try + let errcaught = 0 + try + try + throw "x8" + finally + let lnum = expand("") + asdf + endtry + catch /.*/ + let errcaught = 1 + call assert_match('Vim:E492: Not an editor command:', v:exception) + call assert_match('line ' .. (lnum + 1), v:throwpoint) + endtry + finally + call assert_equal(1, errcaught) + break + endtry + endwhile + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + + Xpath 'd' + + while 1 + try + let intcaught = 0 + try + try + throw "x9" + finally + let lnum = expand("") + call interrupt() + endtry + catch /.*/ + let intcaught = 1 + call assert_match('Vim:Interrupt', v:exception) + call assert_match('line ' .. (lnum + 1), v:throwpoint) + endtry + finally + call assert_equal(1, intcaught) + break + endtry + endwhile + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + + Xpath 'e' + + while 1 + try + let errcaught = 0 + try + try + if 1 + let lnum = expand("") + throw "x10" + " missing endif + finally + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + endtry + catch /.*/ + let errcaught = 1 + call assert_match('Vim(finally):E171: Missing :endif:', v:exception) + call assert_match('line ' .. (lnum + 3), v:throwpoint) + endtry + finally + call assert_equal(1, errcaught) + break + endtry + endwhile + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + + Xpath 'f' + + while 1 + try + let errcaught = 0 + try + try + if 1 + let lnum = expand("") + throw "x11" + " missing endif + endtry + catch /.*/ + let errcaught = 1 + call assert_match('Vim(endtry):E171: Missing :endif:', v:exception) + call assert_match('line ' .. (lnum + 3), v:throwpoint) + endtry + finally + call assert_equal(1, errcaught) + break + endtry + endwhile + call assert_equal('', v:exception) + call assert_equal('', v:throwpoint) + + Xpath 'g' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcdefg', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" +" Test 60: (Re)throwing v:exception; :echoerr. {{{1 +" +" A user exception can be rethrown after catching by throwing +" v:exception. An error or interrupt exception cannot be rethrown +" because Vim exceptions cannot be faked. A Vim exception using the +" value of v:exception can, however, be triggered by the :echoerr +" command. +"------------------------------------------------------------------------------- + +func Test_rethrow_exception_1() + XpathINIT + try + try + Xpath 'a' + throw "oops" + catch /oops/ + Xpath 'b' + throw v:exception " rethrow user exception + catch /.*/ + call assert_report('should not get here') + endtry + catch /^oops$/ " catches rethrown user exception + Xpath 'c' + catch /.*/ + call assert_report('should not get here') + endtry + call assert_equal('abc', g:Xpath) +endfunc + +func Test_rethrow_exception_2() + XpathINIT + try + let caught = 0 + try + Xpath 'a' + write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e + call assert_report('should not get here') + catch /^Vim(write):/ + let caught = 1 + throw v:exception " throw error: cannot fake Vim exception + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'b' + call assert_equal(1, caught) + endtry + catch /^Vim(throw):/ " catches throw error + let caught = caught + 1 + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'c' + call assert_equal(2, caught) + endtry + call assert_equal('abc', g:Xpath) +endfunc + +func Test_rethrow_exception_3() + XpathINIT + try + let caught = 0 + try + Xpath 'a' + asdf + catch /^Vim/ " catch error exception + let caught = 1 + " Trigger Vim error exception with value specified after :echoerr + let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "") + echoerr value + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'b' + call assert_equal(1, caught) + endtry + catch /^Vim(echoerr):/ + let caught = caught + 1 + call assert_match(value, v:exception) + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'c' + call assert_equal(2, caught) + endtry + call assert_equal('abc', g:Xpath) +endfunc + +func Test_rethrow_exception_3() + XpathINIT + try + let errcaught = 0 + try + Xpath 'a' + let intcaught = 0 + call interrupt() + catch /^Vim:/ " catch interrupt exception + let intcaught = 1 + " Trigger Vim error exception with value specified after :echoerr + echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "") + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'b' + call assert_equal(1, intcaught) + endtry + catch /^Vim(echoerr):/ + let errcaught = 1 + call assert_match('Interrupt', v:exception) + finally + Xpath 'c' + call assert_equal(1, errcaught) + endtry + call assert_equal('abc', g:Xpath) +endfunc + "------------------------------------------------------------------------------- " Test 61: Catching interrupt exceptions {{{1 " @@ -3846,68 +4222,1673 @@ func Test_catch_intr_exception() endfunc "------------------------------------------------------------------------------- -" Test 65: Errors in the /pattern/ argument of a :catch {{{1 +" Test 62: Catching error exceptions {{{1 " -" On an error in the /pattern/ argument of a :catch, the :catch does -" not match. Any following :catches of the same :try/:endtry don't -" match either. Finally clauses are executed. +" An error inside a :try/:endtry region is converted to an exception +" and can be caught. The error exception has a "Vim(cmdname):" prefix +" where cmdname is the name of the failing command, or a "Vim:" prefix +" if no command name is known. The "Vim" prefixes cannot be faked. "------------------------------------------------------------------------------- -func Test_catch_pattern_error() - CheckEnglish +func Test_catch_err_exception_1() XpathINIT - - try + while 1 try - Xpath 'a' - throw "oops" - catch /^oops$/ - Xpath 'b' - catch /\)/ " not checked; exception has already been caught + try + let caught = 0 + unlet novar + catch /^Vim(unlet):/ + Xpath 'a' + let caught = 1 + let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "") + finally + Xpath 'b' + call assert_equal(1, caught) + call assert_match('E108: No such variable: "novar"', v:errmsg) + endtry + catch /.*/ call assert_report('should not get here') - endtry - Xpath 'c' - catch /.*/ + finally + Xpath 'c' + break + endtry call assert_report('should not get here') - endtry + endwhile + call assert_equal('abc', g:Xpath) +endfunc + +func Test_catch_err_exception_2() + XpathINIT + while 1 + try + try + let caught = 0 + throw novar " error in :throw + catch /^Vim(throw):/ + Xpath 'a' + let caught = 1 + let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "") + finally + Xpath 'b' + call assert_equal(1, caught) + call assert_match('E121: Undefined variable: novar', v:errmsg) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'c' + break + endtry + call assert_report('should not get here') + endwhile + call assert_equal('abc', g:Xpath) +endfunc + +func Test_catch_err_exception_3() + XpathINIT + while 1 + try + try + let caught = 0 + throw "Vim:faked" " error: cannot fake Vim exception + catch /^Vim(throw):/ + Xpath 'a' + let caught = 1 + let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "") + finally + Xpath 'b' + call assert_equal(1, caught) + call assert_match("E608: Cannot :throw exceptions with 'Vim' prefix", + \ v:errmsg) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'c' + break + endtry + call assert_report('should not get here') + endwhile + call assert_equal('abc', g:Xpath) +endfunc + +func Test_catch_err_exception_4() + XpathINIT + func F() + while 1 + " Missing :endwhile + endfunc + + while 1 + try + try + let caught = 0 + call F() + catch /^Vim(endfunction):/ + Xpath 'a' + let caught = 1 + let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "") + finally + Xpath 'b' + call assert_equal(1, caught) + call assert_match("E170: Missing :endwhile", v:errmsg) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'c' + break + endtry + call assert_report('should not get here') + endwhile call assert_equal('abc', g:Xpath) + delfunc F +endfunc +func Test_catch_err_exception_5() XpathINIT func F() + while 1 + " Missing :endwhile + endfunc + + while 1 + try + try + let caught = 0 + ExecAsScript F + catch /^Vim:/ + Xpath 'a' + let caught = 1 + let v:errmsg = substitute(v:exception, '^Vim:', '', "") + finally + Xpath 'b' + call assert_equal(1, caught) + call assert_match("E170: Missing :endwhile", v:errmsg) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'c' + break + endtry + call assert_report('should not get here') + endwhile + call assert_equal('abc', g:Xpath) + delfunc F +endfunc + +func Test_catch_err_exception_6() + XpathINIT + func G() + call G() + endfunc + + while 1 + try + let mfd_save = &mfd + set mfd=3 + try + let caught = 0 + call G() + catch /^Vim(call):/ + Xpath 'a' + let caught = 1 + let v:errmsg = substitute(v:exception, '^Vim(call):', '', "") + finally + Xpath 'b' + call assert_equal(1, caught) + call assert_match("E132: Function call depth is higher than 'maxfuncdepth'", v:errmsg) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'c' + let &mfd = mfd_save + break + endtry + call assert_report('should not get here') + endwhile + call assert_equal('abc', g:Xpath) + delfunc G +endfunc + +func Test_catch_err_exception_7() + XpathINIT + func H() + return H() + endfunc + + while 1 + try + let mfd_save = &mfd + set mfd=3 + try + let caught = 0 + call H() + catch /^Vim(return):/ + Xpath 'a' + let caught = 1 + let v:errmsg = substitute(v:exception, '^Vim(return):', '', "") + finally + Xpath 'b' + call assert_equal(1, caught) + call assert_match("E132: Function call depth is higher than 'maxfuncdepth'", v:errmsg) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'c' + let &mfd = mfd_save + break " discard error for $VIMNOERRTHROW + endtry + call assert_report('should not get here') + endwhile + + call assert_equal('abc', g:Xpath) + delfunc H +endfunc + +"------------------------------------------------------------------------------- +" Test 63: Suppressing error exceptions by :silent!. {{{1 +" +" A :silent! command inside a :try/:endtry region suppresses the +" conversion of errors to an exception and the immediate abortion on +" error. When the commands executed by the :silent! themselves open +" a new :try/:endtry region, conversion of errors to exception and +" immediate abortion is switched on again - until the next :silent! +" etc. The :silent! has the effect of setting v:errmsg to the error +" message text (without displaying it) and continuing with the next +" script line. +" +" When a command triggering autocommands is executed by :silent! +" inside a :try/:endtry, the autocommand execution is not suppressed +" on error. +" +" This test reuses the function MSG() from the previous test. +"------------------------------------------------------------------------------- + +func Test_silent_exception() + XpathINIT + XloopINIT + let g:taken = "" + + func S(n) abort + XloopNEXT + let g:taken = g:taken . "E" . a:n + let v:errmsg = "" + exec "asdf" . a:n + + " Check that ":silent!" continues: + Xloop 'a' + + " Check that ":silent!" sets "v:errmsg": + call assert_match("E492: Not an editor command", v:errmsg) + endfunc + + func Foo() + while 1 + try + try + let caught = 0 + " This is not silent: + call S(3) + catch /^Vim:/ + Xpath 'b' + let caught = 1 + let errmsg3 = substitute(v:exception, '^Vim:', '', "") + silent! call S(4) + finally + call assert_equal(1, caught) + Xpath 'c' + call assert_match("E492: Not an editor command", errmsg3) + silent! call S(5) + " Break out of try conditionals that cover ":silent!". This also + " discards the aborting error when $VIMNOERRTHROW is non-zero. + break + endtry + catch /.*/ + call assert_report('should not get here') + endtry + endwhile + " This is a double ":silent!" (see caller). + silent! call S(6) + endfunc + + func Bar() + try + silent! call S(2) + silent! execute "call Foo() | call S(7)" + silent! call S(8) + endtry " normal end of try cond that covers ":silent!" + " This has a ":silent!" from the caller: + call S(9) + endfunc + + silent! call S(1) + silent! call Bar() + silent! call S(10) + + call assert_equal("E1E2E3E4E5E6E7E8E9E10", g:taken) + + augroup TMP + au! + autocmd BufWritePost * Xpath 'd' + augroup END + + Xpath 'e' + silent! write /i/m/p/o/s/s/i/b/l/e + Xpath 'f' + + call assert_equal('a2a3ba5ca6a7a8a9a10a11edf', g:Xpath) + + augroup TMP + au! + augroup END + augroup! TMP + delfunction S + delfunction Foo + delfunction Bar +endfunc + +"------------------------------------------------------------------------------- +" Test 64: Error exceptions after error, interrupt or :throw {{{1 +" +" When an error occurs after an interrupt or a :throw but before +" a matching :catch is reached, all following :catches of that try +" block are ignored, but the error exception can be caught by the next +" surrounding try conditional. Any previous error exception is +" discarded. An error is ignored when there is a previous error that +" has not been caught. +"------------------------------------------------------------------------------- + +func Test_exception_after_error_1() + XpathINIT + while 1 + try + try + Xpath 'a' + let caught = 0 + while 1 + if 1 + " Missing :endif + endwhile " throw error exception + catch /^Vim(/ + Xpath 'b' + let caught = 1 + finally + Xpath 'c' + call assert_equal(1, caught) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'd' + break + endtry + call assert_report('should not get here') + endwhile + call assert_equal('abcd', g:Xpath) +endfunc + +func Test_exception_after_error_2() + XpathINIT + while 1 + try + try + Xpath 'a' + let caught = 0 + try + if 1 + " Missing :endif + catch /.*/ " throw error exception + call assert_report('should not get here') + catch /.*/ + call assert_report('should not get here') + endtry + catch /^Vim(/ + Xpath 'b' + let caught = 1 + finally + Xpath 'c' + call assert_equal(1, caught) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'd' + break + endtry + call assert_report('should not get here') + endwhile + call assert_equal('abcd', g:Xpath) +endfunc + +func Test_exception_after_error_3() + XpathINIT + while 1 try try + let caught = 0 try Xpath 'a' - throw "ab" - catch /abc/ " does not catch + call interrupt() + catch /do_not_catch/ call assert_report('should not get here') - catch /\)/ " error; discards exception + if 1 + " Missing :endif + catch /.*/ " throw error exception call assert_report('should not get here') - catch /.*/ " not checked + catch /.*/ call assert_report('should not get here') - finally - Xpath 'b' endtry - call assert_report('should not get here') - catch /^ab$/ " checked, but original exception is discarded - call assert_report('should not get here') - catch /^Vim(catch):/ - Xpath 'c' - call assert_match('Vim(catch):E475: Invalid argument:', v:exception) + catch /^Vim(/ + Xpath 'b' + let caught = 1 finally - Xpath 'd' + Xpath 'c' + call assert_equal(1, caught) endtry - Xpath 'e' catch /.*/ call assert_report('should not get here') + finally + Xpath 'd' + break endtry - Xpath 'f' - endfunc - - call F() - call assert_equal('abcdef', g:Xpath) + call assert_report('should not get here') + endwhile + call assert_equal('abcd', g:Xpath) +endfunc - delfunc F +func Test_exception_after_error_4() + XpathINIT + while 1 + try + try + let caught = 0 + try + Xpath 'a' + throw "x" + catch /do_not_catch/ + call assert_report('should not get here') + if 1 + " Missing :endif + catch /x/ " throw error exception + call assert_report('should not get here') + catch /.*/ + call assert_report('should not get here') + endtry + catch /^Vim(/ + Xpath 'b' + let caught = 1 + finally + Xpath 'c' + call assert_equal(1, caught) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'd' + break + endtry + call assert_report('should not get here') + endwhile + call assert_equal('abcd', g:Xpath) +endfunc + +func Test_exception_after_error_5() + XpathINIT + while 1 + try + try + let caught = 0 + Xpath 'a' + endif " :endif without :if; throw error exception + if 1 + " Missing :endif + catch /do_not_catch/ " ignore new error + call assert_report('should not get here') + catch /^Vim(endif):/ + Xpath 'b' + let caught = 1 + catch /^Vim(/ + call assert_report('should not get here') + finally + Xpath 'c' + call assert_equal(1, caught) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'd' + break + endtry + call assert_report('should not get here') + endwhile + call assert_equal('abcd', g:Xpath) +endfunc + +"------------------------------------------------------------------------------- +" Test 65: Errors in the /pattern/ argument of a :catch {{{1 +" +" On an error in the /pattern/ argument of a :catch, the :catch does +" not match. Any following :catches of the same :try/:endtry don't +" match either. Finally clauses are executed. +"------------------------------------------------------------------------------- + +func Test_catch_pattern_error() + CheckEnglish + XpathINIT + + try + try + Xpath 'a' + throw "oops" + catch /^oops$/ + Xpath 'b' + catch /\)/ " not checked; exception has already been caught + call assert_report('should not get here') + endtry + Xpath 'c' + catch /.*/ + call assert_report('should not get here') + endtry + call assert_equal('abc', g:Xpath) + + XpathINIT + func F() + try + try + try + Xpath 'a' + throw "ab" + catch /abc/ " does not catch + call assert_report('should not get here') + catch /\)/ " error; discards exception + call assert_report('should not get here') + catch /.*/ " not checked + call assert_report('should not get here') + finally + Xpath 'b' + endtry + call assert_report('should not get here') + catch /^ab$/ " checked, but original exception is discarded + call assert_report('should not get here') + catch /^Vim(catch):/ + Xpath 'c' + call assert_match('Vim(catch):E475: Invalid argument:', v:exception) + finally + Xpath 'd' + endtry + Xpath 'e' + catch /.*/ + call assert_report('should not get here') + endtry + Xpath 'f' + endfunc + + call F() + call assert_equal('abcdef', g:Xpath) + + delfunc F +endfunc + +"------------------------------------------------------------------------------- +" Test 66: Stop range :call on error, interrupt, or :throw {{{1 +" +" When a function which is multiply called for a range since it +" doesn't handle the range itself has an error in a command +" dynamically enclosed by :try/:endtry or gets an interrupt or +" executes a :throw, no more calls for the remaining lines in the +" range are made. On an error in a command not dynamically enclosed +" by :try/:endtry, the function is executed again for the remaining +" lines in the range. +"------------------------------------------------------------------------------- + +func Test_stop_range_on_error() + let test =<< trim [CODE] + let file = tempname() + exec "edit" file + call setline(1, ['line 1', 'line 2', 'line 3']) + let taken = "" + let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)" + + func F(reason, n) abort + let g:taken = g:taken .. "F" .. a:n .. + \ substitute(a:reason, '\(\l\).*', '\u\1', "") .. + \ "(" .. line(".") .. ")" + + if a:reason == "error" + asdf + elseif a:reason == "interrupt" + call interrupt() + elseif a:reason == "throw" + throw "xyz" + elseif a:reason == "aborting error" + XloopNEXT + call assert_equal(g:taken, g:expected) + try + bwipeout! + call delete(g:file) + asdf + endtry + endif + endfunc + + func G(reason, n) + let g:taken = g:taken .. "G" .. a:n .. + \ substitute(a:reason, '\(\l\).*', '\u\1', "") + 1,3call F(a:reason, a:n) + endfunc + + Xpath 'a' + call G("error", 1) + try + Xpath 'b' + try + call G("error", 2) + call assert_report('should not get here') + finally + Xpath 'c' + try + call G("interrupt", 3) + call assert_report('should not get here') + finally + Xpath 'd' + try + call G("throw", 4) + call assert_report('should not get here') + endtry + endtry + endtry + catch /xyz/ + Xpath 'e' + catch /.*/ + call assert_report('should not get here') + endtry + Xpath 'f' + call G("aborting error", 5) + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcdef', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 67: :throw across :call command {{{1 +" +" On a call command, an exception might be thrown when evaluating the +" function name, during evaluation of the arguments, or when the +" function is being executed. The exception can be caught by the +" caller. +"------------------------------------------------------------------------------- + +func THROW(x, n) + if a:n == 1 + Xpath 'A' + elseif a:n == 2 + Xpath 'B' + elseif a:n == 3 + Xpath 'C' + endif + throw a:x +endfunc + +func NAME(x, n) + if a:n == 1 + call assert_report('should not get here') + elseif a:n == 2 + Xpath 'D' + elseif a:n == 3 + Xpath 'E' + elseif a:n == 4 + Xpath 'F' + endif + return a:x +endfunc + +func ARG(x, n) + if a:n == 1 + call assert_report('should not get here') + elseif a:n == 2 + call assert_report('should not get here') + elseif a:n == 3 + Xpath 'G' + elseif a:n == 4 + Xpath 'I' + endif + return a:x +endfunc + +func Test_throw_across_call_cmd() + XpathINIT + + func F(x, n) + if a:n == 2 + call assert_report('should not get here') + elseif a:n == 4 + Xpath 'a' + endif + endfunc + + while 1 + try + let v:errmsg = "" + + while 1 + try + Xpath 'b' + call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1) + call assert_report('should not get here') + catch /^name$/ + Xpath 'c' + catch /.*/ + call assert_report('should not get here') + finally + call assert_equal("", v:errmsg) + let v:errmsg = "" + break + endtry + endwhile + + while 1 + try + Xpath 'd' + call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2) + call assert_report('should not get here') + catch /^arg$/ + Xpath 'e' + catch /.*/ + call assert_report('should not get here') + finally + call assert_equal("", v:errmsg) + let v:errmsg = "" + break + endtry + endwhile + + while 1 + try + Xpath 'f' + call {NAME("THROW", 3)}(ARG("call", 3), 3) + call assert_report('should not get here') + catch /^call$/ + Xpath 'g' + catch /^0$/ " default return value + call assert_report('should not get here') + catch /.*/ + call assert_report('should not get here') + finally + call assert_equal("", v:errmsg) + let v:errmsg = "" + break + endtry + endwhile + + while 1 + try + Xpath 'h' + call {NAME("F", 4)}(ARG(4711, 4), 4) + Xpath 'i' + catch /.*/ + call assert_report('should not get here') + finally + call assert_equal("", v:errmsg) + let v:errmsg = "" + break + endtry + endwhile + + catch /^0$/ " default return value + call assert_report('should not get here') + catch /.*/ + call assert_report('should not get here') + finally + call assert_equal("", v:errmsg) + let v:errmsg = "" + break + endtry + endwhile + + call assert_equal('bAcdDBefEGCghFIai', g:Xpath) + delfunction F +endfunc + +"------------------------------------------------------------------------------- +" Test 68: :throw across function calls in expressions {{{1 +" +" On a function call within an expression, an exception might be +" thrown when evaluating the function name, during evaluation of the +" arguments, or when the function is being executed. The exception +" can be caught by the caller. +" +" This test reuses the functions THROW(), NAME(), and ARG() from the +" previous test. +"------------------------------------------------------------------------------- + +func Test_throw_across_call_expr() + XpathINIT + + func F(x, n) + if a:n == 2 + call assert_report('should not get here') + elseif a:n == 4 + Xpath 'a' + endif + return a:x + endfunction + + while 1 + try + let error = 0 + let v:errmsg = "" + + while 1 + try + Xpath 'b' + let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1) + call assert_report('should not get here') + catch /^name$/ + Xpath 'c' + catch /.*/ + call assert_report('should not get here') + finally + call assert_equal("", v:errmsg) + let v:errmsg = "" + break + endtry + endwhile + call assert_true(!exists('var1')) + + while 1 + try + Xpath 'd' + let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2) + call assert_report('should not get here') + catch /^arg$/ + Xpath 'e' + catch /.*/ + call assert_report('should not get here') + finally + call assert_equal("", v:errmsg) + let v:errmsg = "" + break + endtry + endwhile + call assert_true(!exists('var2')) + + while 1 + try + Xpath 'f' + let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3) + call assert_report('should not get here') + catch /^call$/ + Xpath 'g' + catch /^0$/ " default return value + call assert_report('should not get here') + catch /.*/ + call assert_report('should not get here') + finally + call assert_equal("", v:errmsg) + let v:errmsg = "" + break + endtry + endwhile + call assert_true(!exists('var3')) + + while 1 + try + Xpath 'h' + let var4 = {NAME("F", 4)}(ARG(4711, 4), 4) + Xpath 'i' + catch /.*/ + call assert_report('should not get here') + finally + call assert_equal("", v:errmsg) + let v:errmsg = "" + break + endtry + endwhile + call assert_true(exists('var4') && var4 == 4711) + + catch /^0$/ " default return value + call assert_report('should not get here') + catch /.*/ + call assert_report('should not get here') + finally + call assert_equal("", v:errmsg) + break + endtry + endwhile + + call assert_equal('bAcdDBefEGCghFIai', g:Xpath) + delfunc F +endfunc + +"------------------------------------------------------------------------------- +" Test 76: Errors, interrupts, :throw during expression evaluation {{{1 +" +" When a function call made during expression evaluation is aborted +" due to an error inside a :try/:endtry region or due to an interrupt +" or a :throw, the expression evaluation is aborted as well. No +" message is displayed for the cancelled expression evaluation. On an +" error not inside :try/:endtry, the expression evaluation continues. +"------------------------------------------------------------------------------- + +func Test_expr_eval_error() + let test =<< trim [CODE] + let taken = "" + + func ERR(n) + let g:taken = g:taken .. "E" .. a:n + asdf + endfunc + + func ERRabort(n) abort + let g:taken = g:taken .. "A" .. a:n + asdf + endfunc " returns -1; may cause follow-up msg for illegal var/func name + + func WRAP(n, arg) + let g:taken = g:taken .. "W" .. a:n + let g:saved_errmsg = v:errmsg + return arg + endfunc + + func INT(n) + let g:taken = g:taken .. "I" .. a:n + call interrupt() + endfunc + + func THR(n) + let g:taken = g:taken .. "T" .. a:n + throw "should not be caught" + endfunc + + func CONT(n) + let g:taken = g:taken .. "C" .. a:n + endfunc + + func MSG(n) + let g:taken = g:taken .. "M" .. a:n + let errmsg = (a:n >= 37 && a:n <= 44) ? g:saved_errmsg : v:errmsg + let msgptn = (a:n >= 10 && a:n <= 27) ? "^$" : "asdf" + call assert_match(msgptn, errmsg) + let v:errmsg = "" + let g:saved_errmsg = "" + endfunc + + let v:errmsg = "" + + try + let t = 1 + while t <= 9 + Xloop 'a' + try + if t == 1 + let v{ERR(t) + CONT(t)} = 0 + elseif t == 2 + let v{ERR(t) + CONT(t)} + elseif t == 3 + let var = exists('v{ERR(t) + CONT(t)}') + elseif t == 4 + unlet v{ERR(t) + CONT(t)} + elseif t == 5 + function F{ERR(t) + CONT(t)}() + endfunction + elseif t == 6 + function F{ERR(t) + CONT(t)} + elseif t == 7 + let var = exists('*F{ERR(t) + CONT(t)}') + elseif t == 8 + delfunction F{ERR(t) + CONT(t)} + elseif t == 9 + let var = ERR(t) + CONT(t) + endif + catch /asdf/ + " v:errmsg is not set when the error message is converted to an + " exception. Set it to the original error message. + let v:errmsg = substitute(v:exception, '^Vim:', '', "") + catch /^Vim\((\a\+)\)\=:/ + " An error exception has been thrown after the original error. + let v:errmsg = "" + finally + call MSG(t) + let t = t + 1 + XloopNEXT + continue " discard an aborting error + endtry + endwhile + catch /.*/ + call assert_report('should not get here') + endtry + + try + let t = 10 + while t <= 18 + Xloop 'b' + try + if t == 10 + let v{INT(t) + CONT(t)} = 0 + elseif t == 11 + let v{INT(t) + CONT(t)} + elseif t == 12 + let var = exists('v{INT(t) + CONT(t)}') + elseif t == 13 + unlet v{INT(t) + CONT(t)} + elseif t == 14 + function F{INT(t) + CONT(t)}() + endfunction + elseif t == 15 + function F{INT(t) + CONT(t)} + elseif t == 16 + let var = exists('*F{INT(t) + CONT(t)}') + elseif t == 17 + delfunction F{INT(t) + CONT(t)} + elseif t == 18 + let var = INT(t) + CONT(t) + endif + catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/ + " An error exception has been triggered after the interrupt. + let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") + finally + call MSG(t) + let t = t + 1 + XloopNEXT + continue " discard interrupt + endtry + endwhile + catch /.*/ + call assert_report('should not get here') + endtry + + try + let t = 19 + while t <= 27 + Xloop 'c' + try + if t == 19 + let v{THR(t) + CONT(t)} = 0 + elseif t == 20 + let v{THR(t) + CONT(t)} + elseif t == 21 + let var = exists('v{THR(t) + CONT(t)}') + elseif t == 22 + unlet v{THR(t) + CONT(t)} + elseif t == 23 + function F{THR(t) + CONT(t)}() + endfunction + elseif t == 24 + function F{THR(t) + CONT(t)} + elseif t == 25 + let var = exists('*F{THR(t) + CONT(t)}') + elseif t == 26 + delfunction F{THR(t) + CONT(t)} + elseif t == 27 + let var = THR(t) + CONT(t) + endif + catch /^Vim\((\a\+)\)\=:/ + " An error exception has been triggered after the :throw. + let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") + finally + call MSG(t) + let t = t + 1 + XloopNEXT + continue " discard exception + endtry + endwhile + catch /.*/ + call assert_report('should not get here') + endtry + + let v{ERR(28) + CONT(28)} = 0 + call MSG(28) + let v{ERR(29) + CONT(29)} + call MSG(29) + let var = exists('v{ERR(30) + CONT(30)}') + call MSG(30) + unlet v{ERR(31) + CONT(31)} + call MSG(31) + function F{ERR(32) + CONT(32)}() + endfunction + call MSG(32) + function F{ERR(33) + CONT(33)} + call MSG(33) + let var = exists('*F{ERR(34) + CONT(34)}') + call MSG(34) + delfunction F{ERR(35) + CONT(35)} + call MSG(35) + let var = ERR(36) + CONT(36) + call MSG(36) + + let saved_errmsg = "" + + let v{WRAP(37, ERRabort(37)) + CONT(37)} = 0 + call MSG(37) + let v{WRAP(38, ERRabort(38)) + CONT(38)} + call MSG(38) + let var = exists('v{WRAP(39, ERRabort(39)) + CONT(39)}') + call MSG(39) + unlet v{WRAP(40, ERRabort(40)) + CONT(40)} + call MSG(40) + function F{WRAP(41, ERRabort(41)) + CONT(41)}() + endfunction + call MSG(41) + function F{WRAP(42, ERRabort(42)) + CONT(42)} + call MSG(42) + let var = exists('*F{WRAP(43, ERRabort(43)) + CONT(43)}') + call MSG(43) + delfunction F{WRAP(44, ERRabort(44)) + CONT(44)} + call MSG(44) + let var = ERRabort(45) + CONT(45) + call MSG(45) + Xpath 'd' + + let expected = "" + \ .. "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9" + \ .. "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18" + \ .. "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27" + \ .. "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33" + \ .. "E34C34M34E35C35M35E36C36M36" + \ .. "A37W37C37M37A38W38C38M38A39W39C39M39A40W40C40M40A41W41C41M41" + \ .. "A42W42C42M42A43W43C43M43A44W44C44M44A45C45M45" + call assert_equal(expected, taken) + [CODE] + let verify =<< trim [CODE] + let expected = "a1a2a3a4a5a6a7a8a9" + \ .. "b10b11b12b13b14b15b16b17b18" + \ .. "c19c20c21c22c23c24c25c26c27d" + call assert_equal(expected, g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 77: Errors, interrupts, :throw in name{brace-expression} {{{1 +" +" When a function call made during evaluation of an expression in +" braces as part of a function name after ":function" is aborted due +" to an error inside a :try/:endtry region or due to an interrupt or +" a :throw, the expression evaluation is aborted as well, and the +" function definition is ignored, skipping all commands to the +" ":endfunction". On an error not inside :try/:endtry, the expression +" evaluation continues and the function gets defined, and can be +" called and deleted. +"------------------------------------------------------------------------------- +func Test_brace_expr_error() + let test =<< trim [CODE] + func ERR() abort + Xloop 'a' + asdf + endfunc " returns -1 + + func OK() + Xloop 'b' + let v:errmsg = "" + return 0 + endfunc + + let v:errmsg = "" + + Xpath 'c' + func F{1 + ERR() + OK()}(arg) + " F0 should be defined. + if exists("a:arg") && a:arg == "calling" + Xpath 'd' + else + call assert_report('should not get here') + endif + endfunction + call assert_equal("", v:errmsg) + XloopNEXT + + Xpath 'e' + call F{1 + ERR() + OK()}("calling") + call assert_equal("", v:errmsg) + XloopNEXT + + Xpath 'f' + delfunction F{1 + ERR() + OK()} + call assert_equal("", v:errmsg) + XloopNEXT + + try + while 1 + try + Xpath 'g' + func G{1 + ERR() + OK()}(arg) + " G0 should not be defined, and the function body should be + " skipped. + call assert_report('should not get here') + " Use an unmatched ":finally" to check whether the body is + " skipped when an error occurs in ERR(). This works whether or + " not the exception is converted to an exception. + finally + call assert_report('should not get here') + endtry + try + call assert_report('should not get here') + endfunction + + call assert_report('should not get here') + catch /asdf/ + " Jumped to when the function is not defined and the body is + " skipped. + Xpath 'h' + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'i' + break + endtry " jumped to when the body is not skipped + endwhile + catch /.*/ + call assert_report('should not get here') + endtry + [CODE] + let verify =<< trim [CODE] + call assert_equal('ca1b1ea2b2dfa3b3ga4hi', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 78: Messages on parsing errors in expression evaluation {{{1 +" +" When an expression evaluation detects a parsing error, an error +" message is given and converted to an exception, and the expression +" evaluation is aborted. +"------------------------------------------------------------------------------- +func Test_expr_eval_error_msg() + CheckEnglish + + let test =<< trim [CODE] + let taken = "" + + func F(n) + let g:taken = g:taken . "F" . a:n + endfunc + + func MSG(n, enr, emsg) + let g:taken = g:taken . "M" . a:n + call assert_match('^' .. a:enr .. ':', v:errmsg) + call assert_match(a:emsg, v:errmsg) + endfunc + + func CONT(n) + let g:taken = g:taken . "C" . a:n + endfunc + + let v:errmsg = "" + try + let t = 1 + while t <= 14 + let g:taken = g:taken . "T" . t + let v:errmsg = "" + try + if t == 1 + let v{novar + CONT(t)} = 0 + elseif t == 2 + let v{novar + CONT(t)} + elseif t == 3 + let var = exists('v{novar + CONT(t)}') + elseif t == 4 + unlet v{novar + CONT(t)} + elseif t == 5 + function F{novar + CONT(t)}() + endfunction + elseif t == 6 + function F{novar + CONT(t)} + elseif t == 7 + let var = exists('*F{novar + CONT(t)}') + elseif t == 8 + delfunction F{novar + CONT(t)} + elseif t == 9 + echo novar + CONT(t) + elseif t == 10 + echo v{novar + CONT(t)} + elseif t == 11 + echo F{novar + CONT(t)} + elseif t == 12 + let var = novar + CONT(t) + elseif t == 13 + let var = v{novar + CONT(t)} + elseif t == 14 + let var = F{novar + CONT(t)}() + endif + catch /^Vim\((\a\+)\)\=:/ + Xloop 'a' + " v:errmsg is not set when the error message is converted to an + " exception. Set it to the original error message. + let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") + finally + Xloop 'b' + if t <= 8 && t != 3 && t != 7 + call MSG(t, 'E475', 'Invalid argument\>') + else + call MSG(t, 'E121', "Undefined variable") + endif + let t = t + 1 + XloopNEXT + continue " discard an aborting error + endtry + endwhile + catch /.*/ + call assert_report('should not get here') + endtry + + func T(n, expr, enr, emsg) + try + let g:taken = g:taken . "T" . a:n + let v:errmsg = "" + try + execute "let var = " . a:expr + catch /^Vim\((\a\+)\)\=:/ + Xloop 'c' + " v:errmsg is not set when the error message is converted to an + " exception. Set it to the original error message. + let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "") + finally + Xloop 'd' + call MSG(a:n, a:enr, a:emsg) + XloopNEXT + " Discard an aborting error: + return + endtry + catch /.*/ + call assert_report('should not get here') + endtry + endfunc + + call T(15, 'Nofunc() + CONT(15)', 'E117', "Unknown function") + call T(16, 'F(1 2 + CONT(16))', 'E116', "Invalid arguments") + call T(17, 'F(1, 2) + CONT(17)', 'E118', "Too many arguments") + call T(18, 'F() + CONT(18)', 'E119', "Not enough arguments") + call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'") + call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'") + call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression") + call T(22, '1 2 + CONT(22)', 'E15', "Invalid expression") + call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'") + call T(24, '("abc) + CONT(24)', 'E114', "Missing quote") + call T(25, "('abc) + CONT(25)", 'E115', "Missing quote") + call T(26, '& + CONT(26)', 'E112', "Option name missing") + call T(27, '&asdf + CONT(27)', 'E113', "Unknown option") + + let expected = "" + \ .. "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14" + \ .. "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25" + \ .. "T26M26T27M27" + + call assert_equal(expected, taken) + [CODE] + let verify =<< trim [CODE] + let expected = "a1b1a2b2a3b3a4b4a5b5a6b6a7b7a8b8a9b9a10b10a11b11a12b12" + \ .. "a13b13a14b14c15d15c16d16c17d17c18d18c19d19c20d20" + \ .. "c21d21c22d22c23d23c24d24c25d25c26d26c27d27" + call assert_equal(expected, g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 79: Throwing one of several errors for the same command {{{1 +" +" When several errors appear in a row (for instance during expression +" evaluation), the first as the most specific one is used when +" throwing an error exception. If, however, a syntax error is +" detected afterwards, this one is used for the error exception. +" On a syntax error, the next command is not executed, on a normal +" error, however, it is (relevant only in a function without the +" "abort" flag). v:errmsg is not set. +" +" If throwing error exceptions is configured off, v:errmsg is always +" set to the latest error message, that is, to the more general +" message or the syntax error, respectively. +"------------------------------------------------------------------------------- +func Test_throw_multi_error() + CheckEnglish + + let test =<< trim [CODE] + func NEXT(cmd) + exec a:cmd . " | Xloop 'a'" + endfun + + call NEXT('echo novar') " (checks nextcmd) + XloopNEXT + call NEXT('let novar #') " (skips nextcmd) + XloopNEXT + call NEXT('unlet novar #') " (skips nextcmd) + XloopNEXT + call NEXT('let {novar}') " (skips nextcmd) + XloopNEXT + call NEXT('unlet{ novar}') " (skips nextcmd) + + call assert_equal('a1', g:Xpath) + XpathINIT + XloopINIT + + func EXEC(cmd) + exec a:cmd + endfunc + + try + while 1 " dummy loop + try + let v:errmsg = "" + call EXEC('echo novar') " normal error + catch /^Vim\((\a\+)\)\=:/ + Xpath 'b' + call assert_match('E121: Undefined variable: novar', v:exception) + finally + Xpath 'c' + call assert_equal("", v:errmsg) + break + endtry + endwhile + + Xpath 'd' + let cmd = "let" + while cmd != "" + try + let v:errmsg = "" + call EXEC(cmd . ' novar #') " normal plus syntax error + catch /^Vim\((\a\+)\)\=:/ + Xloop 'e' + call assert_match('E488: Trailing characters', v:exception) + finally + Xloop 'f' + call assert_equal("", v:errmsg) + if cmd == "let" + let cmd = "unlet" + else + let cmd = "" + endif + XloopNEXT + continue + endtry + endwhile + + Xpath 'g' + let cmd = "let" + while cmd != "" + try + let v:errmsg = "" + call EXEC(cmd . ' {novar}') " normal plus syntax error + catch /^Vim\((\a\+)\)\=:/ + Xloop 'h' + call assert_match('E475: Invalid argument: {novar}', v:exception) + finally + Xloop 'i' + call assert_equal("", v:errmsg) + if cmd == "let" + let cmd = "unlet" + else + let cmd = "" + endif + XloopNEXT + continue + endtry + endwhile + catch /.*/ + call assert_report('should not get here') + endtry + Xpath 'j' + [CODE] + let verify =<< trim [CODE] + call assert_equal('bcde1f1e2f2gh3i3h4i4j', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 80: Syntax error in expression for illegal :elseif {{{1 +" +" If there is a syntax error in the expression after an illegal +" :elseif, an error message is given (or an error exception thrown) +" for the illegal :elseif rather than the expression error. +"------------------------------------------------------------------------------- +func Test_if_syntax_error() + CheckEnglish + + let test =<< trim [CODE] + let v:errmsg = "" + if 0 + else + elseif 1 ||| 2 + endif + Xpath 'a' + call assert_match('E584: :elseif after :else', v:errmsg) + + let v:errmsg = "" + if 1 + else + elseif 1 ||| 2 + endif + Xpath 'b' + call assert_match('E584: :elseif after :else', v:errmsg) + + let v:errmsg = "" + elseif 1 ||| 2 + Xpath 'c' + call assert_match('E582: :elseif without :if', v:errmsg) + + let v:errmsg = "" + while 1 + elseif 1 ||| 2 + endwhile + Xpath 'd' + call assert_match('E582: :elseif without :if', v:errmsg) + + while 1 + try + try + let v:errmsg = "" + if 0 + else + elseif 1 ||| 2 + endif + catch /^Vim\((\a\+)\)\=:/ + Xpath 'e' + call assert_match('E584: :elseif after :else', v:exception) + finally + Xpath 'f' + call assert_equal("", v:errmsg) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'g' + break + endtry + endwhile + + while 1 + try + try + let v:errmsg = "" + if 1 + else + elseif 1 ||| 2 + endif + catch /^Vim\((\a\+)\)\=:/ + Xpath 'h' + call assert_match('E584: :elseif after :else', v:exception) + finally + Xpath 'i' + call assert_equal("", v:errmsg) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'j' + break + endtry + endwhile + + while 1 + try + try + let v:errmsg = "" + elseif 1 ||| 2 + catch /^Vim\((\a\+)\)\=:/ + Xpath 'k' + call assert_match('E582: :elseif without :if', v:exception) + finally + Xpath 'l' + call assert_equal("", v:errmsg) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'm' + break + endtry + endwhile + + while 1 + try + try + let v:errmsg = "" + while 1 + elseif 1 ||| 2 + endwhile + catch /^Vim\((\a\+)\)\=:/ + Xpath 'n' + call assert_match('E582: :elseif without :if', v:exception) + finally + Xpath 'o' + call assert_equal("", v:errmsg) + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'p' + break + endtry + endwhile + Xpath 'q' + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcdefghijklmnopq', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 81: Discarding exceptions after an error or interrupt {{{1 +" +" When an exception is thrown from inside a :try conditional without +" :catch and :finally clauses and an error or interrupt occurs before +" the :endtry is reached, the exception is discarded. +"------------------------------------------------------------------------------- + +func Test_discard_exception_after_error_1() + let test =<< trim [CODE] + try + Xpath 'a' + try + Xpath 'b' + throw "arrgh" + call assert_report('should not get here') + if 1 + call assert_report('should not get here') + " error after :throw: missing :endif + endtry + call assert_report('should not get here') + catch /arrgh/ + call assert_report('should not get here') + endtry + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('ab', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +" TODO: Not able inject an interrupt after throwing an exception +func Disable_Test_discard_exception_after_error_2() + let test =<< trim [CODE] + try + Xpath 'a' + try + Xpath 'b' + throw "arrgh" + call interrupt() " FIXME: throw is not interrupted here + call assert_report('should not get here') + endtry + call assert_report('should not get here') + catch /arrgh/ + call assert_report('should not get here') + endtry + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('ab', g:Xpath) + [CODE] + call RunInNewVim(test, verify) endfunc "------------------------------------------------------------------------------- diff --git a/src/version.c b/src/version.c index 627df9923f5cc7..662a17cfa62164 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1417, /**/ 1416, /**/ From 8294d49937b99067522fda8a9399bb9533e3c44e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Aug 2020 22:40:56 +0200 Subject: [PATCH 0132/1384] patch 8.2.1418: Vim9: invalid error for missing white space Problem: Vim9: invalid error for missing white space after function. Solution: Do not skip over white space. (closes #6679) --- src/testdir/test_vim9_expr.vim | 8 +++++++- src/userfunc.c | 6 +++++- src/version.c | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index d2d2e0b1ebfa4b..f831b5abe5cedc 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -706,7 +706,7 @@ def RetVoid() let x = 1 enddef -def Test_expr4_vimscript() +def Test_expr4_vim9script() # check line continuation let lines =<< trim END vim9script @@ -819,6 +819,12 @@ def Test_expr4_vimscript() echo 2!= 3 END CheckScriptFailure(lines, 'E1004:') + + lines =<< trim END + vim9script + echo len('xxx') == 3 + END + CheckScriptSuccess(lines) enddef func Test_expr4_fails() diff --git a/src/userfunc.c b/src/userfunc.c index 7d3039a4595229..f38c978f4ef982 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -686,7 +686,10 @@ get_func_tv( while (--argcount >= 0) clear_tv(&argvars[argcount]); - *arg = skipwhite(argp); + if (in_vim9script()) + *arg = argp; + else + *arg = skipwhite(argp); return ret; } @@ -4097,6 +4100,7 @@ ex_call(exarg_T *eap) if (!failed || eap->cstack->cs_trylevel > 0) { // Check for trailing illegal characters and a following command. + arg = skipwhite(arg); if (!ends_excmd2(eap->arg, arg)) { if (!failed) diff --git a/src/version.c b/src/version.c index 662a17cfa62164..bfd5070c4bf31e 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1418, /**/ 1417, /**/ From 59eccb92e3c68f65525e08d2113213ff7d7ed00a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Mon, 10 Aug 2020 23:09:37 +0200 Subject: [PATCH 0133/1384] patch 8.2.1419: Vim9: not operator applied too early Problem: Vim9: not operator applied too early. Solution: Implement the "numeric_only" argument. (closes #6680) --- src/testdir/test_vim9_expr.vim | 5 +++- src/version.c | 2 ++ src/vim9compile.c | 44 ++++++++++++++++++++++------------ 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index f831b5abe5cedc..22ac442bcb4e72 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1744,7 +1744,7 @@ def Test_expr7_call() assert_equal('yes', 'yes'->Echo()) assert_equal('yes', 'yes' ->s:Echo4Arg()) - assert_equal(1, !range(5)->empty()) + assert_equal(true, !range(5)->empty()) assert_equal([0, 1, 2], --3->range()) call CheckDefFailure(["let x = 'yes'->Echo"], 'E107:') @@ -1782,6 +1782,9 @@ def Test_expr7_not() assert_equal(true, !test_void()) assert_equal(true, !test_unknown()) + + assert_equal(false, ![1, 2, 3]->reverse()) + assert_equal(true, ![]->reverse()) END CheckDefSuccess(lines) CheckScriptSuccess(['vim9script'] + lines) diff --git a/src/version.c b/src/version.c index bfd5070c4bf31e..990b945ab469c7 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1419, /**/ 1418, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 81206b3aca1b0e..d327b485556079 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2723,11 +2723,12 @@ compile_get_register(char_u **arg, cctx_T *cctx) /* * Apply leading '!', '-' and '+' to constant "rettv". + * When "numeric_only" is TRUE do not apply '!'. */ static int -apply_leader(typval_T *rettv, char_u *start, char_u *end) +apply_leader(typval_T *rettv, int numeric_only, char_u *start, char_u **end) { - char_u *p = end; + char_u *p = *end; // this works from end to start while (p > start) @@ -2762,6 +2763,11 @@ apply_leader(typval_T *rettv, char_u *start, char_u *end) rettv->vval.v_number = val; } } + else if (numeric_only) + { + ++p; + break; + } else { int v = tv2bool(rettv); @@ -2772,6 +2778,7 @@ apply_leader(typval_T *rettv, char_u *start, char_u *end) rettv->vval.v_number = v ? VVAL_FALSE : VVAL_TRUE; } } + *end = p; return OK; } @@ -2860,11 +2867,12 @@ get_compare_type(char_u *p, int *len, int *type_is) /* * Compile code to apply '-', '+' and '!'. + * When "numeric_only" is TRUE do not apply '!'. */ static int -compile_leader(cctx_T *cctx, char_u *start, char_u *end) +compile_leader(cctx_T *cctx, int numeric_only, char_u *start, char_u **end) { - char_u *p = end; + char_u *p = *end; // this works from end to start while (p > start) @@ -2890,6 +2898,11 @@ compile_leader(cctx_T *cctx, char_u *start, char_u *end) if (isn == NULL) return FAIL; } + else if (numeric_only) + { + ++p; + break; + } else { int invert = TRUE; @@ -2903,6 +2916,7 @@ compile_leader(cctx_T *cctx, char_u *start, char_u *end) return FAIL; } } + *end = p; return OK; } @@ -2914,10 +2928,12 @@ compile_leader(cctx_T *cctx, char_u *start, char_u *end) compile_subscript( char_u **arg, cctx_T *cctx, - char_u **start_leader, - char_u *end_leader, + char_u *start_leader, + char_u **end_leader, ppconst_T *ppconst) { + char_u *name_start = *end_leader; + for (;;) { char_u *p = skipwhite(*arg); @@ -2959,7 +2975,7 @@ compile_subscript( *arg = skipwhite(p + 1); if (compile_arguments(arg, cctx, &argcount) == FAIL) return FAIL; - if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL) + if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL) return FAIL; } else if (*p == '-' && p[1] == '>') @@ -2972,9 +2988,8 @@ compile_subscript( // something->method() // Apply the '!', '-' and '+' first: // -1.0->func() works like (-1.0)->func() - if (compile_leader(cctx, *start_leader, end_leader) == FAIL) + if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL) return FAIL; - *start_leader = end_leader; // don't apply again later p += 2; *arg = skipwhite(p); @@ -3329,13 +3344,12 @@ compile_expr7( if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used) { - // apply the '!', '-' and '+' before the constant - if (apply_leader(rettv, start_leader, end_leader) == FAIL) + // apply the '-' and '+' before the constant, but not '!' + if (apply_leader(rettv, TRUE, start_leader, &end_leader) == FAIL) { clear_tv(rettv); return FAIL; } - start_leader = end_leader; // don't apply again below if (cctx->ctx_skip == SKIP_YES) clear_tv(rettv); @@ -3373,18 +3387,18 @@ compile_expr7( // Handle following "[]", ".member", etc. // Then deal with prefixed '-', '+' and '!', if not done already. - if (compile_subscript(arg, cctx, &start_leader, end_leader, + if (compile_subscript(arg, cctx, start_leader, &end_leader, ppconst) == FAIL) return FAIL; if (ppconst->pp_used > 0) { // apply the '!', '-' and '+' before the constant rettv = &ppconst->pp_tv[ppconst->pp_used - 1]; - if (apply_leader(rettv, start_leader, end_leader) == FAIL) + if (apply_leader(rettv, FALSE, start_leader, &end_leader) == FAIL) return FAIL; return OK; } - if (compile_leader(cctx, start_leader, end_leader) == FAIL) + if (compile_leader(cctx, FALSE, start_leader, &end_leader) == FAIL) return FAIL; return OK; } From f7c4d83609acdfe0e4d0fec9413697ac97c0c3f9 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 11 Aug 2020 20:42:19 +0200 Subject: [PATCH 0134/1384] patch 8.2.1420: test 49 is old style Problem: Test 49 is old style. Solution: Convert remaining parts to new style. Remove obsolete items. (Yegappan Lakshmanan, closes #6683) --- Filelist | 9 +- runtime/doc/testing.txt | 15 +- src/Make_mvc.mak | 12 +- src/Makefile | 8 +- src/testdir/Make_all.mak | 18 - src/testdir/Make_amiga.mak | 9 +- src/testdir/Make_dos.mak | 13 +- src/testdir/Make_ming.mak | 25 +- src/testdir/Make_vms.mms | 34 +- src/testdir/Makefile | 50 +- src/testdir/README.txt | 21 - src/testdir/test49.in | 32 - src/testdir/test49.ok | 12 - src/testdir/test49.vim | 1454 -------------------------------- src/testdir/test_quickfix.vim | 23 + src/testdir/test_vimscript.vim | 506 ++++++++++- src/version.c | 2 + 17 files changed, 561 insertions(+), 1682 deletions(-) delete mode 100644 src/testdir/test49.in delete mode 100644 src/testdir/test49.ok delete mode 100644 src/testdir/test49.vim diff --git a/Filelist b/Filelist index 37f1d8c77a927c..02574e9a18ec36 100644 --- a/Filelist +++ b/Filelist @@ -158,7 +158,9 @@ SRC_ALL = \ src/testdir/gen_opt_test.vim \ src/testdir/README.txt \ src/testdir/Make_all.mak \ - src/testdir/*.in \ + src/testdir/dotest.in \ + src/testdir/test1.in \ + src/testdir/test77a.in \ src/testdir/*.py \ src/testdir/lsan-suppress.txt \ src/testdir/sautest/autoload/*.vim \ @@ -177,9 +179,8 @@ SRC_ALL = \ src/testdir/summarize.vim \ src/testdir/term_util.vim \ src/testdir/view_util.vim \ - src/testdir/test[0-9]*.ok \ - src/testdir/test[0-9]*a.ok \ - src/testdir/test49.vim \ +- src/testdir/test1.ok \ + src/testdir/test77a.ok \ src/testdir/test83-tags? \ src/testdir/test77a.com \ src/testdir/test_*.vim \ diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt index f1173a1f0bac73..1147673d599236 100644 --- a/runtime/doc/testing.txt +++ b/runtime/doc/testing.txt @@ -20,18 +20,11 @@ and for testing plugins. Vim can be tested after building it, usually with "make test". The tests are located in the directory "src/testdir". -There are several types of tests added over time: - test33.in oldest, don't add any of these - test_something.in old style tests - test_something.vim new style tests - *new-style-testing* -New tests should be added as new style tests. These use functions such as -|assert_equal()| to keep the test commands and the expected result in one -place. - *old-style-testing* -In some cases an old style test needs to be used. E.g. when testing Vim -without the |+eval| feature. +New tests should be added as new style tests. The test scripts are named +test_.vim (replace with the feature under test). These use +functions such as |assert_equal()| to keep the test commands and the expected +result in one place. Find more information in the file src/testdir/README.txt. diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index 9c3deb62d35c15..8ac39e22b55dea 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -1326,14 +1326,6 @@ MAIN_TARGET = $(VIM).exe # Target to run individual tests. VIMTESTTARGET = $(VIM).exe -OLD_TEST_OUTFILES = \ - $(SCRIPTS_FIRST) \ - $(SCRIPTS_ALL) \ - $(SCRIPTS_MORE1) \ - $(SCRIPTS_MORE4) \ - $(SCRIPTS_WIN32) \ - $(SCRIPTS_GUI) - all: $(MAIN_TARGET) \ vimrun.exe \ install.exe \ @@ -1485,9 +1477,9 @@ testclean: $(MAKE) /NOLOGO -f Make_dos.mak clean cd .. -# Run individual OLD style test. +# Run test1 to bootstrap tests # These do not depend on the executable, compile it when needed. -$(OLD_TEST_OUTFILES:.out=): +$(SCRIPTS_FIRST:.out=): cd testdir - if exist $@.out del $@.out $(MAKE) /NOLOGO -f Make_dos.mak VIMPROG=..\$(VIMTESTTARGET) nolog diff --git a/src/Makefile b/src/Makefile index 55c366472782d3..5d73fc91a3f99e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2259,8 +2259,6 @@ test check: unittests $(TERM_TEST) scripttests # # This will produce a lot of garbage on your screen, including a few error # messages. Don't worry about that. -# If there is a real error, there will be a difference between "testXX.out" and -# a "testXX.ok" file. # If everything is alright, the final message will be "ALL DONE". If not you # get "TEST FAILURE". # @@ -2311,9 +2309,9 @@ test_libvterm: CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)"; \ fi -# Run individual OLD style test. -# These do not depend on the executable, compile it when needed. -test1 test49: +# Run test1, used to bootstrap tests. +# This does not depend on the executable, compile first it when needed. +test1: cd testdir; rm -f $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE) # Run individual NEW style test. diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 0900a6cfd80d63..57ba651c6533a8 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -10,24 +10,6 @@ NO_INITS = -U NONE $(NO_PLUGINS) # The first script creates small.vim. SCRIPTS_FIRST = test1.out -# Tests that run on all systems. -SCRIPTS_ALL = - -# Tests that run on most systems, but not on Amiga. -SCRIPTS_MORE1 = - -# Tests that run on most systems, but not on Amiga and DOS/Windows. -SCRIPTS_MORE2 = test49.out - -# Tests that run on most systems, but not on VMS -SCRIPTS_MORE4 = - -# Tests specifically for MS-Windows. -SCRIPTS_WIN32 = - -# Tests for the GUI. -SCRIPTS_GUI = - # Tests for Vim9 script. TEST_VIM9 = \ test_vim9_cmd \ diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak index e6e55e3b4f41ce..efd5808429883d 100644 --- a/src/testdir/Make_amiga.mak +++ b/src/testdir/Make_amiga.mak @@ -9,14 +9,9 @@ default: nongui include Make_all.mak -SCRIPTS = $(SCRIPTS_ALL) $(SCRIPTS_MORE4) +.SUFFIXES: .in .out .res .vim -# Must run test1 first to create small.vim. -$(SCRIPTS) $(SCRIPTS_GUI) $(NEW_TESTS_RES): $(SCRIPTS_FIRST) - -.SUFFIXES: .in .out - -nongui: /tmp $(SCRIPTS_FIRST) $(SCRIPTS) +nongui: /tmp $(SCRIPTS_FIRST) csh -c echo ALL DONE clean: diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak index f97b3e9bb4a2a4..5931da25df03e1 100644 --- a/src/testdir/Make_dos.mak +++ b/src/testdir/Make_dos.mak @@ -9,25 +9,20 @@ default: nongui !include Make_all.mak -# Omitted: -# test49 fails in various ways - -SCRIPTS = $(SCRIPTS_ALL) $(SCRIPTS_MORE1) $(SCRIPTS_MORE4) - -TEST_OUTFILES = $(SCRIPTS_FIRST) $(SCRIPTS) $(SCRIPTS_WIN32) $(SCRIPTS_GUI) +TEST_OUTFILES = $(SCRIPTS_FIRST) DOSTMP = dostmp DOSTMP_OUTFILES = $(TEST_OUTFILES:test=dostmp\test) DOSTMP_INFILES = $(DOSTMP_OUTFILES:.out=.in) .SUFFIXES: .in .out .res .vim -nongui: nolog $(SCRIPTS_FIRST) $(SCRIPTS) newtests report +nongui: nolog $(SCRIPTS_FIRST) newtests report small: nolog report -gui: nolog $(SCRIPTS_FIRST) $(SCRIPTS) $(SCRIPTS_GUI) newtests report +gui: nolog $(SCRIPTS_FIRST) newtests report -win32: nolog $(SCRIPTS_FIRST) $(SCRIPTS) $(SCRIPTS_WIN32) newtests report +win32: nolog $(SCRIPTS_FIRST) newtests report # Copy the input files to dostmp, changing the fileformat to dos. $(DOSTMP_INFILES): $(*B).in diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak index e1f34674920ea3..b34ae1d2c3105c 100644 --- a/src/testdir/Make_ming.mak +++ b/src/testdir/Make_ming.mak @@ -28,19 +28,17 @@ default: vimall include Make_all.mak -SCRIPTS = $(SCRIPTS_ALL) $(SCRIPTS_MORE1) $(SCRIPTS_MORE4) $(SCRIPTS_WIN32) - SCRIPTS_BENCH = test_bench_regexp.res # Must run test1 first to create small.vim. -$(SCRIPTS) $(SCRIPTS_GUI) $(SCRIPTS_WIN32) $(NEW_TESTS_RES): $(SCRIPTS_FIRST) +$(NEW_TESTS_RES): $(SCRIPTS_FIRST) .SUFFIXES: .in .out .res .vim -vimall: fixff $(SCRIPTS_FIRST) $(SCRIPTS) $(SCRIPTS_GUI) $(SCRIPTS_WIN32) newtests +vimall: fixff $(SCRIPTS_FIRST) newtests @echo ALL DONE -nongui: fixff nolog $(SCRIPTS_FIRST) $(SCRIPTS) newtests +nongui: fixff nolog $(SCRIPTS_FIRST) newtests @echo ALL DONE benchmark: $(SCRIPTS_BENCH) @@ -48,10 +46,10 @@ benchmark: $(SCRIPTS_BENCH) small: nolog @echo ALL DONE -gui: fixff nolog $(SCRIPTS_FIRST) $(SCRIPTS) $(SCRIPTS_GUI) newtests +gui: fixff nolog $(SCRIPTS_FIRST) newtests @echo ALL DONE -win32: fixff nolog $(SCRIPTS_FIRST) $(SCRIPTS) $(SCRIPTS_WIN32) newtests +win32: fixff nolog $(SCRIPTS_FIRST) newtests @echo ALL DONE # TODO: find a way to avoid changing the distributed files. @@ -88,19 +86,6 @@ test1.out: test1.in -@if exist test.out $(DEL) test.out -@if exist viminfo $(DEL) viminfo -.in.out: - -@if exist $*.ok $(CP) $*.ok test.ok - $(VIMPROG) -u dos.vim $(NO_INITS) -s dotest.in $*.in - @diff test.out $*.ok - -@if exist $*.out $(DEL) $*.out - @$(MV) test.out $*.out - -@if exist Xdir1 $(DELDIR) Xdir1 - -@if exist Xfind $(DELDIR) Xfind - -@if exist XfakeHOME $(DELDIR) XfakeHOME - -@if exist X* $(DEL) X* - -@if exist test.ok $(DEL) test.ok - -@if exist viminfo $(DEL) viminfo - nolog: -@if exist test.log $(DEL) test.log -@if exist messages $(DEL) messages diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms index 59da981b370704..f36ae6edd83dff 100644 --- a/src/testdir/Make_vms.mms +++ b/src/testdir/Make_vms.mms @@ -27,26 +27,6 @@ # Uncomment if you want tests in GUI mode. Terminal mode is default. # WANT_GUI = YES -# Comment out if you want to run Unix specific tests as well, but please -# be aware, that on OpenVMS will fail, because of cat, rm, etc commands -# and directory handling. -# WANT_UNIX = YES - -# Comment out if you have gzip on your system -# HAVE_GZIP = YES - -# Comment out if you have GNU compatible diff on your system -# HAVE_GDIFF = YES - -# Comment out if you have ICONV support -# HAVE_ICONV = YES - -# Comment out if you have LUA support -# HAVE_LUA = YES - -# Comment out if you have PYTHON support -# HAVE_PYTHON = YES - ####################################################################### # End of configuration section. # @@ -57,16 +37,12 @@ VIMPROG = <->vim.exe .SUFFIXES : .out .in -SCRIPT = test1.out test49.out test77a.out +SCRIPT = test1.out test77a.out .IFDEF WANT_GUI GUI_OPTION = -g .ENDIF -.IFDEF WANT_UNIX -SCRIPT_UNIX = test49.out -.ENDIF - .in.out : -@ !clean up before doing the test -@ if "''F$SEARCH("test.out.*")'" .NES. "" then delete/noconfirm/nolog test.out.* @@ -87,7 +63,7 @@ SCRIPT_UNIX = test49.out -@ if "''F$SEARCH("Xdotest.*")'" .NES. "" then delete/noconfirm/nolog Xdotest.*.* -@ if "''F$SEARCH("Xtest.*")'" .NES. "" then delete/noconfirm/nolog Xtest.*.* -all : clean nolog $(START_WITH) $(SCRIPT) $(SCRIPT_UNIX) nolog +all : clean nolog $(START_WITH) $(SCRIPT) nolog -@ write sys$output " " -@ write sys$output "-----------------------------------------------" -@ write sys$output " All done" @@ -111,12 +87,6 @@ nolog : -@ write sys$output "-----------------------------------------------" -@ write sys$output "MAKE_VMS.MMS options:" -@ write sys$output " WANT_GUI = ""$(WANT_GUI)"" " - -@ write sys$output " WANT_UNIX = ""$(WANT_UNIX)"" " - -@ write sys$output " HAVE_GZIP = ""$(HAVE_GZIP)"" " - -@ write sys$output " HAVE_GDIFF = ""$(HAVE_GDIFF)"" " - -@ write sys$output " HAVE_ICONV = ""$(HAVE_ICONV)"" " - -@ write sys$output " HAVE_LUA = ""$(HAVE_LUA)"" " - -@ write sys$output " HAVE_PYTHON= ""$(HAVE_PYTHON)"" " -@ write sys$output "Default vimrc file is VMS.VIM:" -@ write sys$output "-----------------------------------------------" -@ type VMS.VIM diff --git a/src/testdir/Makefile b/src/testdir/Makefile index 7f9ef0434266ab..0d51fde3e13b67 100644 --- a/src/testdir/Makefile +++ b/src/testdir/Makefile @@ -23,28 +23,19 @@ REDIR_TEST_TO_NULL = --cmd 'au SwapExists * let v:swapchoice = "e"' > /dev/null default: nongui # The list of tests is common to all systems. -# This defines NEW_TESTS, NEW_TESTS_RES, SCRIPTS_ALL, SCRIPTS_MORE* and -# SCRIPTS_GUI. +# This defines SCRIPTS_FIRST, NEW_TESTS and NEW_TESTS_RES include Make_all.mak - -SCRIPTS = $(SCRIPTS_ALL) \ - $(SCRIPTS_MORE1) \ - $(SCRIPTS_MORE2) \ - $(SCRIPTS_MORE4) - # Explicit dependencies. -test49.out: test49.vim - test_options.res test_alot.res: opt_test.vim SCRIPTS_BENCH = test_bench_regexp.res .SUFFIXES: .in .out .res .vim -nongui: nolog $(SCRIPTS_FIRST) $(SCRIPTS) newtests report +nongui: nolog $(SCRIPTS_FIRST) newtests report -gui: nolog $(SCRIPTS_FIRST) $(SCRIPTS) $(SCRIPTS_GUI) newtests report +gui: nolog $(SCRIPTS_FIRST) newtests report benchmark: $(SCRIPTS_BENCH) @@ -63,10 +54,10 @@ report: else echo ALL DONE; \ fi" -$(SCRIPTS_FIRST) $(SCRIPTS) $(SCRIPTS_GUI) $(NEW_TESTS_RES): $(VIMPROG) +$(SCRIPTS_FIRST) $(NEW_TESTS_RES): $(VIMPROG) # Must run test1 first to create small.vim. -$(SCRIPTS) $(SCRIPTS_GUI) $(NEW_TESTS_RES): $(SCRIPTS_FIRST) +$(NEW_TESTS_RES): $(SCRIPTS_FIRST) # Execute an individual new style test, e.g.: @@ -116,37 +107,6 @@ test1.out: test1.in echo; exit 1; fi" -rm -rf X* viminfo -.in.out: - -rm -rf $*.failed test.ok $(RM_ON_RUN) - cp $*.ok test.ok - # Sleep a moment to avoid that the xterm title is messed up. - # 200 msec is sufficient, but only modern sleep supports a fraction of - # a second, fall back to a second if it fails. - @-/bin/sh -c "sleep .2 > /dev/null 2>&1 || sleep 1" - $(RUN_VIM) $*.in $(REDIR_TEST_TO_NULL) - - # For flaky tests retry one time. No tests at the moment. - #@/bin/sh -c "if test -f test.out -a $* = test61; then \ - # if diff test.out $*.ok; \ - # then echo flaky test ok first time; \ - # else rm -rf $*.failed $(RM_ON_RUN); \ - # $(RUN_VIM) $*.in; \ - # fi \ - # fi" - - # Check if the test.out file matches test.ok. - @/bin/sh -c "if test -f test.out; then \ - if diff test.out $*.ok; \ - then mv -f test.out $*.out; \ - else echo $* FAILED >>test.log; mv -f test.out $*.failed; \ - fi \ - else echo $* NO OUTPUT >>test.log; \ - fi" - @/bin/sh -c "if test -f valgrind; then\ - mv -f valgrind valgrind.$*; \ - fi" - -rm -rf X* test.ok viminfo - nolog: -rm -f test.log messages diff --git a/src/testdir/README.txt b/src/testdir/README.txt index d6391467617cd1..8bfe47582a2a3c 100644 --- a/src/testdir/README.txt +++ b/src/testdir/README.txt @@ -4,14 +4,6 @@ For testing an indent script see runtime/indent/testdir/README.txt. If it makes sense, add a new test method to an already existing file. You may want to separate it from other tests with comment lines. -The numbered tests are older, we have switched to named tests. Don't add any -more numbered tests. - -And then you can choose between a new style test, which is a Vim script, or an -old style test, which uses Normal mode commands. Use a new style test if you -can. Use an old style test when it needs to run without the +eval feature. - - TO ADD A NEW STYLE TEST: 1) Create a test_.vim file. @@ -57,16 +49,3 @@ TO ADD A SCREEN DUMP TEST: Mostly the same as writing a new style test. Additionally, see help on "terminal-dumptest". Put the reference dump in "dumps/Test_func_name.dump". - -TO ADD AN OLD STYLE TEST: - -1) Create test_.in and test_.ok files. -2) Add test_.out to SCRIPTS_ALL in Make_all.mak in alphabetical order. -3) Use make test_.out to run a single test in src/testdir/. - Use make test_ to run a single test in src/. -4) Also add an entry in src/Makefile. - -Keep in mind that the files are used as if everything was typed: -- To add comments use: :" (that's an Ex command comment) -- A line break is like pressing Enter. If that happens on the last line - you'll hear a beep! diff --git a/src/testdir/test49.in b/src/testdir/test49.in deleted file mode 100644 index 79f13f6a562550..00000000000000 --- a/src/testdir/test49.in +++ /dev/null @@ -1,32 +0,0 @@ -This is a test of the script language. - -If after adding a new test, the test output doesn't appear properly in -test49.failed, try to add one or more "G"s at the line ending in "test.out" - -STARTTEST -:so small.vim -:se nocp nomore viminfo+=nviminfo -:lang mess C -:so test49.vim -:" Go back to this file and append the results from register r. -:buf test49.in -G"rp:/^Results/,$w! test.out -:" -:" make valgrind happy -:redir => funclist -:silent func -:redir END -:for line in split(funclist, "\n") -: let name = matchstr(line, 'function \zs[A-Z]\w*\ze(') -: if name != '' -: exe "delfunc " . name -: endif -:endfor -:for v in keys(g:) -: silent! exe "unlet " . v -:endfor -:unlet v -:qa! -ENDTEST - -Results of test49.vim: diff --git a/src/testdir/test49.ok b/src/testdir/test49.ok deleted file mode 100644 index d687f5bc7794a8..00000000000000 --- a/src/testdir/test49.ok +++ /dev/null @@ -1,12 +0,0 @@ -Results of test49.vim: -*** Test 82: OK (8454401) -*** Test 83: OK (2835) -*** Test 84: OK (934782101) -*** Test 85: OK (198689) ---- Test 86: No Crash for vimgrep on BufUnload -*** Test 86: OK (0) ---- Test 88: All tests were run with throwing exceptions on error. - The $VIMNOERRTHROW control is not configured. ---- Test 88: All tests were run with throwing exceptions on interrupt. - The $VIMNOINTTHROW control is not configured. -*** Test 88: OK (50443995) diff --git a/src/testdir/test49.vim b/src/testdir/test49.vim deleted file mode 100644 index bc3cfc83d46936..00000000000000 --- a/src/testdir/test49.vim +++ /dev/null @@ -1,1454 +0,0 @@ -" Vim script language tests -" Author: Servatius Brandt -" Last Change: 2020 Jun 07 - -"------------------------------------------------------------------------------- -" Test environment {{{1 -"------------------------------------------------------------------------------- - - -" Adding new tests easily. {{{2 -" -" Writing new tests is eased considerably with the following functions and -" abbreviations (see "Commands for recording the execution path", "Automatic -" argument generation"). -" -" To get the abbreviations, execute the command -" -" :let test49_set_env = 1 | source test49.vim -" -" To get them always (from src/testdir), put a line -" -" au! BufRead test49.vim let test49_set_env = 1 | source test49.vim -" -" into the local .vimrc file in the src/testdir directory. -" -if exists("test49_set_env") && test49_set_env - - " Automatic argument generation for the test environment commands. - - function! Xsum() - let addend = substitute(getline("."), '^.*"\s*X:\s*\|^.*', '', "") - " Evaluate arithmetic expression. - if addend != "" - exec "let g:Xsum = g:Xsum + " . addend - endif - endfunction - - function! Xcheck() - let g:Xsum=0 - ?XpathINIT?,.call Xsum() - exec "norm A " - return g:Xsum - endfunction - - iab Xcheck Xcheck=Xcheck()x - - function! Xcomment(num) - let str = "" - let tabwidth = &sts ? &sts : &ts - let tabs = (48+tabwidth - a:num - virtcol(".")) / tabwidth - while tabs > 0 - let str = str . "\t" - let tabs = tabs - 1 - endwhile - let str = str . '" X:' - return str - endfunction - - function! Xloop() - let back = line(".") . "|norm" . virtcol(".") . "|" - norm 0 - let last = search('X\(loop\|path\)INIT\|Xloop\>', "bW") - exec back - let theline = getline(last) - if theline =~ 'X\(loop\|path\)INIT' - let num = 1 - else - let num = 2 * substitute(theline, '.*Xloop\s*\(\d\+\).*', '\1', "") - endif - ?X\(loop\|path\)INIT? - \s/\(XloopINIT!\=\s*\d\+\s\+\)\@<=\(\d\+\)/\=2*submatch(2)/ - exec back - exec "norm a " - return num . Xcomment(strlen(num)) - endfunction - - iab Xloop Xloop=Xloop()x - - function! Xpath(loopinit) - let back = line(".") . "|norm" . virtcol(".") . "|" - norm 0 - let last = search('XpathINIT\|Xpath\>\|XloopINIT', "bW") - exec back - let theline = getline(last) - if theline =~ 'XpathINIT' - let num = 1 - elseif theline =~ 'Xpath\>' - let num = 2 * substitute(theline, '.*Xpath\s*\(\d\+\).*', '\1', "") - else - let pattern = '.*XloopINIT!\=\s*\(\d\+\)\s*\(\d\+\).*' - let num = substitute(theline, pattern, '\1', "") - let factor = substitute(theline, pattern, '\2', "") - " The "x" from the "Xpath" iab and the character triggering its - " expansion are in the input buffer. Save and clear typeahead so - " that it is not read away by the call to "input()" below. Restore - " afterwards. - call inputsave() - let loops = input("Number of iterations in previous loop? ") - call inputrestore() - while (loops > 0) - let num = num * factor - let loops = loops - 1 - endwhile - endif - exec "norm a " - if a:loopinit - return num . " 1" - endif - return num . Xcomment(strlen(num)) - endfunction - - iab Xpath Xpath=Xpath(0)x - iab XloopINIT XloopINIT=Xpath(1)x - - " Also useful (see ExtraVim below): - aug ExtraVim - au! - au BufEnter syn region ExtraVim - \ start=+^if\s\+ExtraVim(.*)+ end=+^endif+ - \ transparent keepend - au BufEnter syn match ExtraComment /^"/ - \ contained containedin=ExtraVim - au BufEnter hi link ExtraComment vimComment - aug END - - aug Xpath - au BufEnter syn keyword Xpath - \ XpathINIT Xpath XloopINIT Xloop XloopNEXT Xcheck Xout - au BufEnter hi link Xpath Special - aug END - - do BufEnter - - " Do not execute the tests when sourcing this file for getting the functions - " and abbreviations above, which are intended for easily adding new test - " cases; they are not needed for test execution. Unlet the variable - " controlling this so that an explicit ":source" command for this file will - " execute the tests. - unlet test49_set_env - finish - -endif - - -" Commands for recording the execution path. {{{2 -" -" The Xpath/Xloop commands can be used for computing the eXecution path by -" adding (different) powers of 2 from those script lines, for which the -" execution should be checked. Xloop provides different addends for each -" execution of a loop. Permitted values are 2^0 to 2^30, so that 31 execution -" points (multiply counted inside loops) can be tested. -" -" Note that the arguments of the following commands can be generated -" automatically, see below. -" -" Usage: {{{3 -" -" - Use XpathINIT at the beginning of the test. -" -" - Use Xpath to check if a line is executed. -" Argument: power of 2 (decimal). -" -" - To check multiple execution of loops use Xloop for automatically -" computing Xpath values: -" -" - Use XloopINIT before the loop. -" Two arguments: -" - the first Xpath value (power of 2) to be used (Xnext), -" - factor for computing a new Xnext value when reexecuting a loop -" (by a ":continue" or ":endwhile"); this should be 2^n where -" n is the number of Xloop commands inside the loop. -" If XloopINIT! is used, the first execution of XloopNEXT is -" a no-operation. -" -" - Use Xloop inside the loop: -" One argument: -" The argument and the Xnext value are multiplied to build the -" next Xpath value. No new Xnext value is prepared. The argument -" should be 2^(n-1) for the nth Xloop command inside the loop. -" If the loop has only one Xloop command, the argument can be -" omitted (default: 1). -" -" - Use XloopNEXT before ":continue" and ":endwhile". This computes a new -" Xnext value for the next execution of the loop by multiplying the old -" one with the factor specified in the XloopINIT command. No Argument. -" Alternatively, when XloopINIT! is used, a single XloopNEXT at the -" beginning of the loop can be used. -" -" Nested loops are not supported. -" -" - Use Xcheck at end of each test. It prints the test number, the expected -" execution path value, the test result ("OK" or "FAIL"), and, if the tests -" fails, the actual execution path. -" One argument: -" Expected Xpath/Xloop sum for the correct execution path. -" In order that this value can be computed automatically, do the -" following: For each line in the test with an Xpath and Xloop -" command, add a comment starting with "X:" and specifying an -" expression that evaluates to the value contributed by this line to -" the correct execution path. (For copying an Xpath argument of at -" least two digits into the comment, press .) At the end of the -" test, just type "Xcheck" and press . -" -" - In order to add additional information to the test output file, use the -" Xout command. Argument(s) like ":echo". -" -" Automatic argument generation: {{{3 -" -" The arguments of the Xpath, XloopINIT, Xloop, and Xcheck commands can be -" generated automatically, so that new tests can easily be written without -" mental arithmetic. The Xcheck argument is computed from the "X:" comments -" of the preceding Xpath and Xloop commands. See the commands and -" abbreviations at the beginning of this file. -" -" Implementation: {{{3 -" XpathINIT, Xpath, XloopINIT, Xloop, XloopNEXT, Xcheck, Xout. -" -" The variants for existing g:ExtraVimResult are needed when executing a script -" in an extra Vim process, see ExtraVim below. - -" EXTRA_VIM_START - do not change or remove this line. - -com! XpathINIT let g:Xpath = 0 - -if exists("g:ExtraVimResult") - com! -count -bar Xpath exec "!echo >>" . g:ExtraVimResult -else - com! -count -bar Xpath let g:Xpath = g:Xpath + -endif - -com! -count -nargs=1 -bang - \ XloopINIT let g:Xnext = | - \ let g:Xfactor = | - \ let g:Xskip = strlen("") - -if exists("g:ExtraVimResult") - com! -count=1 -bar Xloop exec "!echo " . (g:Xnext * ) . " >>" . - \ g:ExtraVimResult -else - com! -count=1 -bar Xloop let g:Xpath = g:Xpath + g:Xnext * -endif - -com! XloopNEXT let g:Xnext = g:Xnext * - \ (g:Xskip ? 1 : g:Xfactor) | - \ let g:Xskip = 0 - -let @r = "" -let Xtest = 1 -com! -count Xcheck let Xresult = "*** Test " . - \ (Xtest<10?" ":Xtest<100?" ":"") . - \ Xtest . ": " . ( - \ (Xpath==) ? "OK (".Xpath.")" : - \ "FAIL (".Xpath." instead of )" - \ ) | - \ let @R = Xresult . "\n" | - \ echo Xresult | - \ let Xtest = Xtest + 1 - -if exists("g:ExtraVimResult") - com! -nargs=+ Xoutq exec "!echo @R:'" . - \ substitute(substitute(, - \ "'", '&\\&&', "g"), "\n", "@NL@", "g") - \ . "' >>" . g:ExtraVimResult -else - com! -nargs=+ Xoutq let @R = "--- Test " . - \ (g:Xtest<10?" ":g:Xtest<100?" ":"") . - \ g:Xtest . ": " . substitute(, - \ "\n", "&\t ", "g") . "\n" -endif -com! -nargs=+ Xout exec 'Xoutq' - -" Switch off storing of lines for undoing changes. Speeds things up a little. -set undolevels=-1 - -" EXTRA_VIM_STOP - do not change or remove this line. - - -" ExtraVim() - Run a script file in an extra Vim process. {{{2 -" -" This is useful for testing immediate abortion of the script processing due to -" an error in a command dynamically enclosed by a :try/:tryend region or when an -" exception is thrown but not caught or when an interrupt occurs. It can also -" be used for testing :finish. -" -" An interrupt location can be specified by an "INTERRUPT" comment. A number -" telling how often this location is reached (in a loop or in several function -" calls) should be specified as argument. When missing, once per script -" invocation or function call is assumed. INTERRUPT locations are tested by -" setting a breakpoint in that line and using the ">quit" debug command when -" the breakpoint is reached. A function for which an INTERRUPT location is -" specified must be defined before calling it (or executing it as a script by -" using ExecAsScript below). -" -" This function is only called in normal modus ("g:ExtraVimResult" undefined). -" -" Tests to be executed as an extra script should be written as follows: -" -" column 1 column 1 -" | | -" v v -" -" XpathINIT XpathINIT -" if ExtraVim() if ExtraVim() -" ... " ... -" ... " ... -" endif endif -" Xcheck Xcheck -" -" Double quotes in column 1 are removed before the script is executed. -" They should be used if the test has unbalanced conditionals (:if/:endif, -" :while:/endwhile, :try/:endtry) or for a line with a syntax error. The -" extra script may use Xpath, XloopINIT, Xloop, XloopNEXT, and Xout as usual. -" -" A file name may be specified as argument. All messages of the extra Vim -" process are then redirected to the file. An existing file is overwritten. -" -let ExtraVimCount = 0 -let ExtraVimBase = expand("") -let ExtraVimTestEnv = "" -" -function ExtraVim(...) - " Count how often this function is called. - let g:ExtraVimCount = g:ExtraVimCount + 1 - - " Disable folds to prevent that the ranges in the ":write" commands below - " are extended up to the end of a closed fold. This also speeds things up - " considerably. - set nofoldenable - - " Open a buffer for this test script and copy the test environment to - " a temporary file. Take account of parts relevant for the extra script - " execution only. - let current_buffnr = bufnr("%") - execute "view +1" g:ExtraVimBase - if g:ExtraVimCount == 1 - let g:ExtraVimTestEnv = tempname() - execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w" - \ g:ExtraVimTestEnv "|']+" - execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>" - \ g:ExtraVimTestEnv "|']+" - execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>" - \ g:ExtraVimTestEnv "|']+" - execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>" - \ g:ExtraVimTestEnv "|']+" - endif - - " Start the extra Vim script with a ":source" command for the test - " environment. The source line number where the extra script will be - " appended, needs to be passed as variable "ExtraVimBegin" to the script. - let extra_script = tempname() - exec "!echo 'source " . g:ExtraVimTestEnv . "' >" . extra_script - let extra_begin = 1 - - " Starting behind the test environment, skip over the first g:ExtraVimCount - " occurrences of "if ExtraVim()" and copy the following lines up to the - " matching "endif" to the extra Vim script. - execute "/E" . "ND_OF_TEST_ENVIRONMENT/" - exec 'norm ' . g:ExtraVimCount . '/^\s*if\s\+ExtraVim(.*)/+' . "\n" - execute ".,/^endif/-write >>" . extra_script - - " Open a buffer for the extra Vim script, delete all ^", and write the - " script if was actually modified. - execute "edit +" . (extra_begin + 1) extra_script - ,$s/^"//e - update - - " Count the INTERRUPTs and build the breakpoint and quit commands. - let breakpoints = "" - let debug_quits = "" - let in_func = 0 - exec extra_begin - while search( - \ '"\s*INTERRUPT\h\@!\|^\s*fu\%[nction]\>!\=\s*\%(\u\|s:\)\w*\s*(\|' - \ . '^\s*\\\|^\s*endf\%[unction]\>\|' - \ . '\%(^\s*fu\%[nction]!\=\s*\)\@ 0 - let theline = getline(".") - if theline =~ '^\s*fu' - " Function definition. - let in_func = 1 - let func_start = line(".") - let func_name = substitute(theline, - \ '^\s*fu\%[nction]!\=\s*\(\%(\u\|s:\)\w*\).*', '\1', "") - elseif theline =~ '^\s*endf' - " End of function definition. - let in_func = 0 - else - let finding = substitute(theline, '.*\(\%' . col(".") . 'c.*\)', - \ '\1', "") - if finding =~ '^"\s*INTERRUPT\h\@!' - " Interrupt comment. Compose as many quit commands as - " specified. - let cnt = substitute(finding, - \ '^"\s*INTERRUPT\s*\(\d*\).*$', '\1', "") - let quits = "" - while cnt > 0 - " Use "\r" rather than "\n" to separate the quit commands. - " "\r" is not interpreted as command separator by the ":!" - " command below but works to separate commands in the - " external vim. - let quits = quits . "q\r" - let cnt = cnt - 1 - endwhile - if in_func - " Add the function breakpoint and note the number of quits - " to be used, if specified, or one for every call else. - let breakpoints = breakpoints . " -c 'breakadd func " . - \ (line(".") - func_start) . " " . - \ func_name . "'" - if quits != "" - let debug_quits = debug_quits . quits - elseif !exists("quits{func_name}") - let quits{func_name} = "q\r" - else - let quits{func_name} = quits{func_name} . "q\r" - endif - else - " Add the file breakpoint and the quits to be used for it. - let breakpoints = breakpoints . " -c 'breakadd file " . - \ line(".") . " " . extra_script . "'" - if quits == "" - let quits = "q\r" - endif - let debug_quits = debug_quits . quits - endif - else - " Add the quits to be used for calling the function or executing - " it as script file. - if finding =~ '^ExecAsScript' - " Sourcing function as script. - let finding = substitute(finding, - \ '^ExecAsScript\s\+\(\%(\u\|s:\)\w*\).*', '\1', "") - else - " Function call. - let finding = substitute(finding, - \ '^\(\%(\u\|s:\)\w*\).*', '\1', "") - endif - if exists("quits{finding}") - let debug_quits = debug_quits . quits{finding} - endif - endif - endif - endwhile - - " Close the buffer for the script and create an (empty) resultfile. - bwipeout - let resultfile = tempname() - exec "!>" . resultfile - - " Run the script in an extra vim. Switch to extra modus by passing the - " resultfile in ExtraVimResult. Redirect messages to the file specified as - " argument if any. Use ":debuggreedy" so that the commands provided on the - " pipe are consumed at the debug prompt. Use "-N" to enable command-line - " continuation ("C" in 'cpo'). Add "nviminfo" to 'viminfo' to avoid - " messing up the user's viminfo file. - let redirect = a:0 ? - \ " -c 'au VimLeave * redir END' -c 'redir\\! >" . a:1 . "'" : "" - exec "!echo '" . debug_quits . "q' | " .. v:progpath .. " -u NONE -N -Xes" . redirect . - \ " -c 'debuggreedy|set viminfo+=nviminfo'" . - \ " -c 'let ExtraVimBegin = " . extra_begin . "'" . - \ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints . - \ " -S " . extra_script - - " Build the resulting sum for resultfile and add it to g:Xpath. Add Xout - " information provided by the extra Vim process to the test output. - let sum = 0 - exec "edit" resultfile - let line = 1 - while line <= line("$") - let theline = getline(line) - if theline =~ '^@R:' - exec 'Xout "' . substitute(substitute( - \ escape(escape(theline, '"'), '\"'), - \ '^@R:', '', ""), '@NL@', "\n", "g") . '"' - else - let sum = sum + getline(line) - endif - let line = line + 1 - endwhile - bwipeout - let g:Xpath = g:Xpath + sum - - " Delete the extra script and the resultfile. - call delete(extra_script) - call delete(resultfile) - - " Switch back to the buffer that was active when this function was entered. - exec "buffer" current_buffnr - - " Return 0. This protects extra scripts from being run in the main Vim - " process. - return 0 -endfunction - - -" ExtraVimThrowpoint() - Relative throwpoint in ExtraVim script {{{2 -" -" Evaluates v:throwpoint and returns the throwpoint relative to the beginning of -" an ExtraVim script as passed by ExtraVim() in ExtraVimBegin. -" -" EXTRA_VIM_START - do not change or remove this line. -function ExtraVimThrowpoint() - if !exists("g:ExtraVimBegin") - Xout "ExtraVimThrowpoint() used outside ExtraVim() script." - return v:throwpoint - endif - - if v:throwpoint =~ '^function\>' - return v:throwpoint - endif - - return "line " . - \ (substitute(v:throwpoint, '.*, line ', '', "") - g:ExtraVimBegin) . - \ " of ExtraVim() script" -endfunction -" EXTRA_VIM_STOP - do not change or remove this line. - - -" MakeScript() - Make a script file from a function. {{{2 -" -" Create a script that consists of the body of the function a:funcname. -" Replace any ":return" by a ":finish", any argument variable by a global -" variable, and every ":call" by a ":source" for the next following argument -" in the variable argument list. This function is useful if similar tests are -" to be made for a ":return" from a function call or a ":finish" in a script -" file. -" -" In order to execute a function specifying an INTERRUPT location (see ExtraVim) -" as a script file, use ExecAsScript below. -" -" EXTRA_VIM_START - do not change or remove this line. -function MakeScript(funcname, ...) - let script = tempname() - execute "redir! >" . script - execute "function" a:funcname - redir END - execute "edit" script - " Delete the "function" and the "endfunction" lines. Do not include the - " word "function" in the pattern since it might be translated if LANG is - " set. When MakeScript() is being debugged, this deletes also the debugging - " output of its line 3 and 4. - exec '1,/.*' . a:funcname . '(.*)/d' - /^\d*\s*endfunction\>/,$d - %s/^\d*//e - %s/return/finish/e - %s/\ 0 - let cnt = cnt + 1 - s/\" . bplist - breaklist - redir END - execute "edit" bplist - " Get the line number from the function breakpoint. Works also when - " LANG is set. - execute 'v/^\s*\d\+\s\+func\s\+' . a:funcname . '\s.*/d' - %s/^\s*\d\+\s\+func\s\+\%(\u\|s:\)\w*\s\D*\(\d*\).*/\1/e - let cnt = 0 - while cnt < line("$") - let cnt = cnt + 1 - if getline(cnt) != "" - execute "breakadd file" getline(cnt) script - endif - endwhile - bwipeout! - call delete(bplist) - endif - - " Source and delete the script. - exec "source" script - call delete(script) -endfunction - -com! -nargs=1 -bar ExecAsScript call ExecAsScript() -" EXTRA_VIM_STOP - do not change or remove this line. - - -" END_OF_TEST_ENVIRONMENT - do not change or remove this line. - -function! MESSAGES(...) - try - exec "edit" g:msgfile - catch /^Vim(edit):/ - return 0 - endtry - - let english = v:lang == "C" || v:lang =~ '^[Ee]n' - let match = 1 - norm gg - - let num = a:0 / 2 - let cnt = 1 - while cnt <= num - let enr = a:{2*cnt - 1} - let emsg= a:{2*cnt} - let cnt = cnt + 1 - - if enr == "" - Xout "TODO: Add message number for:" emsg - elseif enr == "INT" - let enr = "" - endif - if enr == "" && !english - continue - endif - let pattern = (enr != "") ? enr . ':.*' : '' - if english - let pattern = pattern . emsg - endif - if !search(pattern, "W") - let match = 0 - Xout "No match for:" pattern - endif - norm $ - endwhile - - bwipeout! - return match -endfunction - -" Following tests were moved to test_vimscript.vim: -" 1-24, 27-31, 34-40, 49-50, 52-68, 76-81, 87 -" Following tests were moved to test_trycatch.vim: -" 25-26, 32-33, 41-48, 51, 69-75 -let Xtest = 82 - -"------------------------------------------------------------------------------- -" Test 82: Ignoring :catch clauses after an error or interrupt {{{1 -" -" When an exception is thrown and an error or interrupt occurs before -" the matching :catch clause is reached, the exception is discarded -" and the :catch clause is ignored (also for the error or interrupt -" exception being thrown then). -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - try - try - Xpath 1 " X: 1 - throw "arrgh" - Xpath 2 " X: 0 -" if 1 - Xpath 4 " X: 0 - " error after :throw: missing :endif - catch /.*/ - Xpath 8 " X: 0 - Xout v:exception "in" ExtraVimThrowpoint() - catch /.*/ - Xpath 16 " X: 0 - Xout v:exception "in" ExtraVimThrowpoint() - endtry - Xpath 32 " X: 0 - catch /arrgh/ - Xpath 64 " X: 0 - endtry - Xpath 128 " X: 0 -endif - -if ExtraVim() - function! E() - try - try - Xpath 256 " X: 256 - throw "arrgh" - Xpath 512 " X: 0 -" if 1 - Xpath 1024 " X: 0 - " error after :throw: missing :endif - catch /.*/ - Xpath 2048 " X: 0 - Xout v:exception "in" ExtraVimThrowpoint() - catch /.*/ - Xpath 4096 " X: 0 - Xout v:exception "in" ExtraVimThrowpoint() - endtry - Xpath 8192 " X: 0 - catch /arrgh/ - Xpath 16384 " X: 0 - endtry - endfunction - - call E() - Xpath 32768 " X: 0 -endif - -if ExtraVim() - try - try - Xpath 65536 " X: 65536 - throw "arrgh" - Xpath 131072 " X: 0 - catch /.*/ "INTERRUPT - Xpath 262144 " X: 0 - Xout v:exception "in" ExtraVimThrowpoint() - catch /.*/ - Xpath 524288 " X: 0 - Xout v:exception "in" ExtraVimThrowpoint() - endtry - Xpath 1048576 " X: 0 - catch /arrgh/ - Xpath 2097152 " X: 0 - endtry - Xpath 4194304 " X: 0 -endif - -if ExtraVim() - function I() - try - try - Xpath 8388608 " X: 8388608 - throw "arrgh" - Xpath 16777216 " X: 0 - catch /.*/ "INTERRUPT - Xpath 33554432 " X: 0 - Xout v:exception "in" ExtraVimThrowpoint() - catch /.*/ - Xpath 67108864 " X: 0 - Xout v:exception "in" ExtraVimThrowpoint() - endtry - Xpath 134217728 " X: 0 - catch /arrgh/ - Xpath 268435456 " X: 0 - endtry - endfunction - - call I() - Xpath 536870912 " X: 0 -endif - -Xcheck 8454401 - - -"------------------------------------------------------------------------------- -" Test 83: Executing :finally clauses after an error or interrupt {{{1 -" -" When an exception is thrown and an error or interrupt occurs before -" the :finally of the innermost :try is reached, the exception is -" discarded and the :finally clause is executed. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - try - Xpath 1 " X: 1 - try - Xpath 2 " X: 2 - throw "arrgh" - Xpath 4 " X: 0 -" if 1 - Xpath 8 " X: 0 - " error after :throw: missing :endif - finally - Xpath 16 " X: 16 - endtry - Xpath 32 " X: 0 - catch /arrgh/ - Xpath 64 " X: 0 - endtry - Xpath 128 " X: 0 -endif - -if ExtraVim() - try - Xpath 256 " X: 256 - try - Xpath 512 " X: 512 - throw "arrgh" - Xpath 1024 " X: 0 - finally "INTERRUPT - Xpath 2048 " X: 2048 - endtry - Xpath 4096 " X: 0 - catch /arrgh/ - Xpath 8192 " X: 0 - endtry - Xpath 16384 " X: 0 -endif - -Xcheck 2835 - - -"------------------------------------------------------------------------------- -" Test 84: Exceptions in autocommand sequences. {{{1 -" -" When an exception occurs in a sequence of autocommands for -" a specific event, the rest of the sequence is not executed. The -" command that triggered the autocommand execution aborts, and the -" exception is propagated to the caller. -" -" For the FuncUndefined event under a function call expression or -" :call command, the function is not executed, even when it has -" been defined by the autocommands before the exception occurred. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - function! INT() - "INTERRUPT - let dummy = 0 - endfunction - - aug TMP - autocmd! - - autocmd User x1 Xpath 1 " X: 1 - autocmd User x1 throw "x1" - autocmd User x1 Xpath 2 " X: 0 - - autocmd User x2 Xpath 4 " X: 4 - autocmd User x2 asdf - autocmd User x2 Xpath 8 " X: 0 - - autocmd User x3 Xpath 16 " X: 16 - autocmd User x3 call INT() - autocmd User x3 Xpath 32 " X: 0 - - autocmd FuncUndefined U1 function! U1() - autocmd FuncUndefined U1 Xpath 64 " X: 0 - autocmd FuncUndefined U1 endfunction - autocmd FuncUndefined U1 Xpath 128 " X: 128 - autocmd FuncUndefined U1 throw "U1" - autocmd FuncUndefined U1 Xpath 256 " X: 0 - - autocmd FuncUndefined U2 function! U2() - autocmd FuncUndefined U2 Xpath 512 " X: 0 - autocmd FuncUndefined U2 endfunction - autocmd FuncUndefined U2 Xpath 1024 " X: 1024 - autocmd FuncUndefined U2 ASDF - autocmd FuncUndefined U2 Xpath 2048 " X: 0 - - autocmd FuncUndefined U3 function! U3() - autocmd FuncUndefined U3 Xpath 4096 " X: 0 - autocmd FuncUndefined U3 endfunction - autocmd FuncUndefined U3 Xpath 8192 " X: 8192 - autocmd FuncUndefined U3 call INT() - autocmd FuncUndefined U3 Xpath 16384 " X: 0 - aug END - - try - try - Xpath 32768 " X: 32768 - doautocmd User x1 - catch /x1/ - Xpath 65536 " X: 65536 - endtry - - while 1 - try - Xpath 131072 " X: 131072 - let caught = 0 - doautocmd User x2 - catch /asdf/ - let caught = 1 - finally - Xpath 262144 " X: 262144 - if !caught && !$VIMNOERRTHROW - Xpath 524288 " X: 0 - " Propagate uncaught error exception, - else - " ... but break loop for caught error exception, - " or discard error and break loop if $VIMNOERRTHROW - break - endif - endtry - endwhile - - while 1 - try - Xpath 1048576 " X: 1048576 - let caught = 0 - doautocmd User x3 - catch /Vim:Interrupt/ - let caught = 1 - finally - Xpath 2097152 " X: 2097152 - if !caught && !$VIMNOINTTHROW - Xpath 4194304 " X: 0 - " Propagate uncaught interrupt exception, - else - " ... but break loop for caught interrupt exception, - " or discard interrupt and break loop if $VIMNOINTTHROW - break - endif - endtry - endwhile - - if exists("*U1") | delfunction U1 | endif - if exists("*U2") | delfunction U2 | endif - if exists("*U3") | delfunction U3 | endif - - try - Xpath 8388608 " X: 8388608 - call U1() - catch /U1/ - Xpath 16777216 " X: 16777216 - endtry - - while 1 - try - Xpath 33554432 " X: 33554432 - let caught = 0 - call U2() - catch /ASDF/ - let caught = 1 - finally - Xpath 67108864 " X: 67108864 - if !caught && !$VIMNOERRTHROW - Xpath 134217728 " X: 0 - " Propagate uncaught error exception, - else - " ... but break loop for caught error exception, - " or discard error and break loop if $VIMNOERRTHROW - break - endif - endtry - endwhile - - while 1 - try - Xpath 268435456 " X: 268435456 - let caught = 0 - call U3() - catch /Vim:Interrupt/ - let caught = 1 - finally - Xpath 536870912 " X: 536870912 - if !caught && !$VIMNOINTTHROW - Xpath 1073741824 " X: 0 - " Propagate uncaught interrupt exception, - else - " ... but break loop for caught interrupt exception, - " or discard interrupt and break loop if $VIMNOINTTHROW - break - endif - endtry - endwhile - catch /.*/ - " The Xpath command does not accept 2^31 (negative); display explicitly: - exec "!echo 2147483648 >>" . g:ExtraVimResult - Xout "Caught" v:exception "in" v:throwpoint - endtry - - unlet caught - delfunction INT - delfunction U1 - delfunction U2 - delfunction U3 - au! TMP - aug! TMP -endif - -Xcheck 934782101 - - -"------------------------------------------------------------------------------- -" Test 85: Error exceptions in autocommands for I/O command events {{{1 -" -" When an I/O command is inside :try/:endtry, autocommands to be -" executed after it should be skipped on an error (exception) in the -" command itself or in autocommands to be executed before the command. -" In the latter case, the I/O command should not be executed either. -" Example 1: BufWritePre, :write, BufWritePost -" Example 2: FileReadPre, :read, FileReadPost. -"------------------------------------------------------------------------------- - -XpathINIT - -function! MSG(enr, emsg) - let english = v:lang == "C" || v:lang =~ '^[Ee]n' - if a:enr == "" - Xout "TODO: Add message number for:" a:emsg - let v:errmsg = ":" . v:errmsg - endif - let match = 1 - if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) - let match = 0 - if v:errmsg == "" - Xout "Message missing." - else - let v:errmsg = escape(v:errmsg, '"') - Xout "Unexpected message:" v:errmsg - endif - endif - return match -endfunction - -" Remove the autocommands for the events specified as arguments in all used -" autogroups. -function Delete_autocommands(...) - let augfile = tempname() - while 1 - try - exec "redir >" . augfile - aug - redir END - exec "edit" augfile - g/^$/d - norm G$ - let wrap = "w" - while search('\%( \|^\)\@<=.\{-}\%( \)\@=', wrap) > 0 - let wrap = "W" - exec "norm y/ \n" - let argno = 1 - while argno <= a:0 - exec "au!" escape(@", " ") a:{argno} - let argno = argno + 1 - endwhile - endwhile - catch /.*/ - finally - bwipeout! - call delete(augfile) - break " discard errors for $VIMNOERRTHROW - endtry - endwhile -endfunction - -call Delete_autocommands("BufWritePre", "BufWritePost") - -while 1 - try - try - let post = 0 - aug TMP - au! BufWritePost * let post = 1 - aug END - let caught = 0 - write /n/o/n/e/x/i/s/t/e/n/t - catch /^Vim(write):/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(write):', '', "") - finally - Xpath 1 " X: 1 - if !caught && !$VIMNOERRTHROW - Xpath 2 " X: 0 - endif - let v:errmsg = substitute(v:errmsg, '^"/n/o/n/e/x/i/s/t/e/n/t" ', - \ '', "") - if !MSG('E212', "Can't open file for writing") - Xpath 4 " X: 0 - endif - if post - Xpath 8 " X: 0 - Xout "BufWritePost commands executed after write error" - endif - au! TMP - aug! TMP - endtry - catch /.*/ - Xpath 16 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -while 1 - try - try - let post = 0 - aug TMP - au! BufWritePre * asdf - au! BufWritePost * let post = 1 - aug END - let tmpfile = tempname() - let caught = 0 - exec "write" tmpfile - catch /^Vim\((write)\)\=:/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim\((write)\)\=:', '', "") - finally - Xpath 32 " X: 32 - if !caught && !$VIMNOERRTHROW - Xpath 64 " X: 0 - endif - let v:errmsg = substitute(v:errmsg, '^"'.tmpfile.'" ', '', "") - if !MSG('E492', "Not an editor command") - Xpath 128 " X: 0 - endif - if filereadable(tmpfile) - Xpath 256 " X: 0 - Xout ":write command not suppressed after BufWritePre error" - endif - if post - Xpath 512 " X: 0 - Xout "BufWritePost commands executed after BufWritePre error" - endif - au! TMP - aug! TMP - endtry - catch /.*/ - Xpath 1024 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -call delete(tmpfile) - -call Delete_autocommands("BufWritePre", "BufWritePost", - \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost") - -while 1 - try - try - let post = 0 - aug TMP - au! FileReadPost * let post = 1 - aug END - let caught = 0 - read /n/o/n/e/x/i/s/t/e/n/t - catch /^Vim(read):/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim(read):', '', "") - finally - Xpath 2048 " X: 2048 - if !caught && !$VIMNOERRTHROW - Xpath 4096 " X: 0 - endif - let v:errmsg = substitute(v:errmsg, ' /n/o/n/e/x/i/s/t/e/n/t$', - \ '', "") - if !MSG('E484', "Can't open file") - Xpath 8192 " X: 0 - endif - if post - Xpath 16384 " X: 0 - Xout "FileReadPost commands executed after write error" - endif - au! TMP - aug! TMP - endtry - catch /.*/ - Xpath 32768 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -while 1 - try - let infile = tempname() - let tmpfile = tempname() - exec "!echo XYZ >" . infile - exec "edit" tmpfile - try - Xpath 65536 " X: 65536 - try - let post = 0 - aug TMP - au! FileReadPre * asdf - au! FileReadPost * let post = 1 - aug END - let caught = 0 - exec "0read" infile - catch /^Vim\((read)\)\=:/ - let caught = 1 - let v:errmsg = substitute(v:exception, '^Vim\((read)\)\=:', '', - \ "") - finally - Xpath 131072 " X: 131072 - if !caught && !$VIMNOERRTHROW - Xpath 262144 " X: 0 - endif - let v:errmsg = substitute(v:errmsg, ' '.infile.'$', '', "") - if !MSG('E492', "Not an editor command") - Xpath 524288 " X: 0 - endif - if getline("1") == "XYZ" - Xpath 1048576 " X: 0 - Xout ":read command not suppressed after FileReadPre error" - endif - if post - Xpath 2097152 " X: 0 - Xout "FileReadPost commands executed after " . - \ "FileReadPre error" - endif - au! TMP - aug! TMP - endtry - finally - bwipeout! - endtry - catch /.*/ - Xpath 4194304 " X: 0 - Xout v:exception "in" v:throwpoint - finally - break " discard error for $VIMNOERRTHROW - endtry -endwhile - -call delete(infile) -call delete(tmpfile) -unlet! caught post infile tmpfile -delfunction MSG -delfunction Delete_autocommands - -Xcheck 198689 - -"------------------------------------------------------------------------------- -" Test 86: setloclist crash {{{1 -" -" Executing a setloclist() on BufUnload shouldn't crash Vim -"------------------------------------------------------------------------------- - -func F - au BufUnload * :call setloclist(0, [{'bufnr':1, 'lnum':1, 'col':1, 'text': 'tango down'}]) - - :lvimgrep /.*/ *.mak -endfunc - -XpathINIT - -ExecAsScript F - -delfunction F -Xout "No Crash for vimgrep on BufUnload" -Xcheck 0 - -" Test 87 was moved to test_vimscript.vim -let Xtest = 88 - - -"------------------------------------------------------------------------------- -" Test 88: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1 -" -" It is possible to configure Vim for throwing exceptions on error -" or interrupt, controlled by variables $VIMNOERRTHROW and -" $VIMNOINTTHROW. This is just for increasing the number of tests. -" All tests here should run for all four combinations of setting -" these variables to 0 or 1. The variables are intended for the -" development phase only. In the final release, Vim should be -" configured to always use error and interrupt exceptions. -" -" The test result is "OK", -" -" - if the $VIMNOERRTHROW and the $VIMNOINTTHROW control are not -" configured and exceptions are thrown on error and on -" interrupt. -" -" - if the $VIMNOERRTHROW or the $VIMNOINTTHROW control is -" configured and works as intended. -" -" What actually happens, is shown in the test output. -" -" Otherwise, the test result is "FAIL", and the test output describes -" the problem. -" -" IMPORTANT: This must be the last test because it sets $VIMNOERRTHROW and -" $VIMNOINTTHROW. -"------------------------------------------------------------------------------- - -XpathINIT - -if ExtraVim() - - function! ThrowOnError() - XloopNEXT - let caught = 0 - try - Xloop 1 " X: 1 + 8 + 64 - asdf - catch /.*/ - let caught = 1 " error exception caught - finally - Xloop 2 " X: 2 + 16 + 128 - return caught " discard aborting error - endtry - Xloop 4 " X: 0 - endfunction - - let quits_skipped = 0 - - function! ThrowOnInterrupt() - XloopNEXT - let caught = 0 - try - Xloop 1 " X: (1 + 8 + 64) * 512 - "INTERRUPT3 - let dummy = 0 - let g:quits_skipped = g:quits_skipped + 1 - catch /.*/ - let caught = 1 " interrupt exception caught - finally - Xloop 2 " X: (2 + 16 + 128) * 512 - return caught " discard interrupt - endtry - Xloop 4 " X: 0 - endfunction - - function! CheckThrow(Type) - execute 'return ThrowOn' . a:Type . '()' - endfunction - - function! CheckConfiguration(type) " type is "error" or "interrupt" - - let type = a:type - let Type = substitute(type, '.*', '\u&', "") - let VAR = '$VIMNO' . substitute(type, '\(...\).*', '\U\1', "") . 'THROW' - - if type == "error" - XloopINIT! 1 8 - elseif type == "interrupt" - XloopINIT! 512 8 - endif - - exec 'let requested_for_tests = exists(VAR) && ' . VAR . ' == 0' - exec 'let suppressed_for_tests = ' . VAR . ' != 0' - let used_in_tests = CheckThrow(Type) - - exec 'let ' . VAR . ' = 0' - let request_works = CheckThrow(Type) - - exec 'let ' . VAR . ' = 1' - let suppress_works = !CheckThrow(Type) - - if type == "error" - XloopINIT! 262144 8 - elseif type == "interrupt" - XloopINIT! 2097152 8 - - if g:quits_skipped != 0 - Xloop 1 " X: 0*2097152 - Xout "Test environment error. Interrupt breakpoints skipped: " - \ . g:quits_skipped . ".\n" - \ . "Cannot check whether interrupt exceptions are thrown." - return - endif - endif - - let failure = - \ !suppressed_for_tests && !used_in_tests - \ || !request_works - - let contradiction = - \ used_in_tests - \ ? suppressed_for_tests && !request_works - \ : !suppressed_for_tests - - if failure - " Failure in configuration. - Xloop 2 " X: 0 * 2* (262144 + 2097152) - elseif contradiction - " Failure in test logic. Should not happen. - Xloop 4 " X: 0 * 4 * (262144 + 2097152) - endif - - let var_control_configured = - \ request_works != used_in_tests - \ || suppress_works == used_in_tests - - let var_control_not_configured = - \ requested_for_tests || suppressed_for_tests - \ ? request_works && !suppress_works - \ : request_works == used_in_tests - \ && suppress_works != used_in_tests - - let with = used_in_tests ? "with" : "without" - - let set = suppressed_for_tests ? "non-zero" : - \ requested_for_tests ? "0" : "unset" - - let although = contradiction && !var_control_not_configured - \ ? ",\nalthough " - \ : ".\n" - - let output = "All tests were run " . with . " throwing exceptions on " - \ . type . although - - if !var_control_not_configured - let output = output . VAR . " was " . set . "." - - if !request_works && !requested_for_tests - let output = output . - \ "\n" . Type . " exceptions are not thrown when " . VAR . - \ " is\nset to 0." - endif - - if !suppress_works && (!used_in_tests || - \ !request_works && - \ !requested_for_tests && !suppressed_for_tests) - let output = output . - \ "\n" . Type . " exceptions are thrown when " . VAR . - \ " is set to 1." - endif - - if !failure && var_control_configured - let output = output . - \ "\nRun tests also with " . substitute(VAR, '^\$', '', "") - \ . "=" . used_in_tests . "." - \ . "\nThis is for testing in the development phase only." - \ . " Remove the \n" - \ . VAR . " control in the final release." - endif - else - let output = output . - \ "The " . VAR . " control is not configured." - endif - - Xout output - endfunction - - call CheckConfiguration("error") - Xpath 16777216 " X: 16777216 - call CheckConfiguration("interrupt") - Xpath 33554432 " X: 33554432 -endif - -Xcheck 50443995 - -" IMPORTANT: No test should be added after this test because it changes -" $VIMNOERRTHROW and $VIMNOINTTHROW. - - -"------------------------------------------------------------------------------- -" Modelines {{{1 -" vim: ts=8 sw=4 tw=80 fdm=marker -"------------------------------------------------------------------------------- diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index e71a3dfdec2317..6a86b1d77c7c7e 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -5040,4 +5040,27 @@ func Test_lhelpgrep_from_help_window() new | only! endfunc +" Test for the crash fixed by 7.3.715 +func Test_setloclist_crash() + %bw! + let g:BufNum = bufnr() + augroup QF_Test + au! + au BufUnload * call setloclist(0, [{'bufnr':g:BufNum, 'lnum':1, 'col':1, 'text': 'tango down'}]) + augroup END + + try + lvimgrep /.*/ *.mak + catch /E926:/ + endtry + call assert_equal('tango down', getloclist(0, {'items' : 0}).items[0].text) + call assert_equal(1, getloclist(0, {'size' : 0}).size) + + augroup QF_Test + au! + augroup END + unlet g:BufNum + %bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_vimscript.vim b/src/testdir/test_vimscript.vim index e63f647bb5bc72..1b00fc9e78c454 100644 --- a/src/testdir/test_vimscript.vim +++ b/src/testdir/test_vimscript.vim @@ -1,5 +1,6 @@ " Test various aspects of the Vim script language. -" Most of this was formerly in test49. +" Most of this was formerly in test49.vim (developed by Servatius Brandt +" ) source check.vim source shared.vim @@ -5868,7 +5869,7 @@ func Test_discard_exception_after_error_1() call RunInNewVim(test, verify) endfunc -" TODO: Not able inject an interrupt after throwing an exception +" TODO: Need to interrupt the code before the endtry is invoked func Disable_Test_discard_exception_after_error_2() let test =<< trim [CODE] try @@ -5891,6 +5892,507 @@ func Disable_Test_discard_exception_after_error_2() call RunInNewVim(test, verify) endfunc +"------------------------------------------------------------------------------- +" Test 82: Ignoring :catch clauses after an error or interrupt {{{1 +" +" When an exception is thrown and an error or interrupt occurs before +" the matching :catch clause is reached, the exception is discarded +" and the :catch clause is ignored (also for the error or interrupt +" exception being thrown then). +"------------------------------------------------------------------------------- + +func Test_ignore_catch_after_error_1() + let test =<< trim [CODE] + try + try + Xpath 'a' + throw "arrgh" + call assert_report('should not get here') + if 1 + call assert_report('should not get here') + " error after :throw: missing :endif + catch /.*/ + call assert_report('should not get here') + catch /.*/ + call assert_report('should not get here') + endtry + call assert_report('should not get here') + catch /arrgh/ + call assert_report('should not get here') + endtry + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('a', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +func Test_ignore_catch_after_error_2() + let test =<< trim [CODE] + func E() + try + try + Xpath 'a' + throw "arrgh" + call assert_report('should not get here') + if 1 + call assert_report('should not get here') + " error after :throw: missing :endif + catch /.*/ + call assert_report('should not get here') + catch /.*/ + call assert_report('should not get here') + endtry + call assert_report('should not get here') + catch /arrgh/ + call assert_report('should not get here') + endtry + endfunc + + call E() + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('a', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +" TODO: Need to interrupt the code right before the catch is invoked +func FIXME_Test_ignore_catch_after_intr_1() + let test =<< trim [CODE] + try + try + Xpath 'a' + throw "arrgh" + call assert_report('should not get here') + catch /.*/ " TODO: Need to interrupt before this catch is + call interrupt() " invoked + call assert_report('should not get here') + catch /.*/ + call assert_report('should not get here') + endtry + call assert_report('should not get here') + catch /arrgh/ + call assert_report('should not get here') + endtry + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('a', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +" TODO: Need to interrupt the code right before the catch is invoked +func FIXME_Test_ignore_catch_after_intr_2() + let test =<< trim [CODE] + func I() + try + try + Xpath 'a' + throw "arrgh" + call assert_report('should not get here') + catch /.*/ " TODO: Need to interrupt before this catch is + " invoked + call interrupt() + call assert_report('should not get here') + catch /.*/ + call assert_report('should not get here') + endtry + call assert_report('should not get here') + catch /arrgh/ + call assert_report('should not get here') + endtry + endfunc + + call I() + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('a', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 83: Executing :finally clauses after an error or interrupt {{{1 +" +" When an exception is thrown and an error or interrupt occurs before +" the :finally of the innermost :try is reached, the exception is +" discarded and the :finally clause is executed. +"------------------------------------------------------------------------------- + +func Test_finally_after_error() + let test =<< trim [CODE] + try + Xpath 'a' + try + Xpath 'b' + throw "arrgh" + call assert_report('should not get here') + if 1 + call assert_report('should not get here') + " error after :throw: missing :endif + finally + Xpath 'c' + endtry + call assert_report('should not get here') + catch /arrgh/ + call assert_report('should not get here') + endtry + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('abc', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +" TODO: Need to interrupt the code right before the finally is invoked +func FIXME_Test_finally_after_intr() + let test =<< trim [CODE] + try + Xpath 'a' + try + Xpath 'b' + throw "arrgh" + call assert_report('should not get here') + finally " TODO: Need to interrupt before the finally is invoked + Xpath 'c' + endtry + call assert_report('should not get here') + catch /arrgh/ + call assert_report('should not get here') + endtry + call assert_report('should not get here') + [CODE] + let verify =<< trim [CODE] + call assert_equal('abc', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 84: Exceptions in autocommand sequences. {{{1 +" +" When an exception occurs in a sequence of autocommands for +" a specific event, the rest of the sequence is not executed. The +" command that triggered the autocommand execution aborts, and the +" exception is propagated to the caller. +" +" For the FuncUndefined event under a function call expression or +" :call command, the function is not executed, even when it has +" been defined by the autocommands before the exception occurred. +"------------------------------------------------------------------------------- + +func Test_autocmd_exception() + let test =<< trim [CODE] + func INT() + call interrupt() + endfunc + + aug TMP + autocmd! + + autocmd User x1 Xpath 'a' + autocmd User x1 throw "x1" + autocmd User x1 call assert_report('should not get here') + + autocmd User x2 Xpath 'b' + autocmd User x2 asdf + autocmd User x2 call assert_report('should not get here') + + autocmd User x3 Xpath 'c' + autocmd User x3 call INT() + autocmd User x3 call assert_report('should not get here') + + autocmd FuncUndefined U1 func U1() + autocmd FuncUndefined U1 call assert_report('should not get here') + autocmd FuncUndefined U1 endfunc + autocmd FuncUndefined U1 Xpath 'd' + autocmd FuncUndefined U1 throw "U1" + autocmd FuncUndefined U1 call assert_report('should not get here') + + autocmd FuncUndefined U2 func U2() + autocmd FuncUndefined U2 call assert_report('should not get here') + autocmd FuncUndefined U2 endfunc + autocmd FuncUndefined U2 Xpath 'e' + autocmd FuncUndefined U2 ASDF + autocmd FuncUndefined U2 call assert_report('should not get here') + + autocmd FuncUndefined U3 func U3() + autocmd FuncUndefined U3 call assert_report('should not get here') + autocmd FuncUndefined U3 endfunc + autocmd FuncUndefined U3 Xpath 'f' + autocmd FuncUndefined U3 call INT() + autocmd FuncUndefined U3 call assert_report('should not get here') + aug END + + try + try + Xpath 'g' + doautocmd User x1 + catch /x1/ + Xpath 'h' + endtry + + while 1 + try + Xpath 'i' + doautocmd User x2 + catch /asdf/ + Xpath 'j' + finally + Xpath 'k' + break + endtry + endwhile + + while 1 + try + Xpath 'l' + doautocmd User x3 + catch /Vim:Interrupt/ + Xpath 'm' + finally + Xpath 'n' + " ... but break loop for caught interrupt exception, + " or discard interrupt and break loop if $VIMNOINTTHROW + break + endtry + endwhile + + if exists("*U1") | delfunction U1 | endif + if exists("*U2") | delfunction U2 | endif + if exists("*U3") | delfunction U3 | endif + + try + Xpath 'o' + call U1() + catch /U1/ + Xpath 'p' + endtry + + while 1 + try + Xpath 'q' + call U2() + catch /ASDF/ + Xpath 'r' + finally + Xpath 's' + " ... but break loop for caught error exception, + " or discard error and break loop if $VIMNOERRTHROW + break + endtry + endwhile + + while 1 + try + Xpath 't' + call U3() + catch /Vim:Interrupt/ + Xpath 'u' + finally + Xpath 'v' + " ... but break loop for caught interrupt exception, + " or discard interrupt and break loop if $VIMNOINTTHROW + break + endtry + endwhile + catch /.*/ + call assert_report('should not get here') + endtry + Xpath 'w' + [CODE] + let verify =<< trim [CODE] + call assert_equal('gahibjklcmnodpqerstfuvw', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + +"------------------------------------------------------------------------------- +" Test 85: Error exceptions in autocommands for I/O command events {{{1 +" +" When an I/O command is inside :try/:endtry, autocommands to be +" executed after it should be skipped on an error (exception) in the +" command itself or in autocommands to be executed before the command. +" In the latter case, the I/O command should not be executed either. +" Example 1: BufWritePre, :write, BufWritePost +" Example 2: FileReadPre, :read, FileReadPost. +"------------------------------------------------------------------------------- + +func Test_autocmd_error_io_exception() + let test =<< trim [CODE] + " Remove the autocommands for the events specified as arguments in all used + " autogroups. + func Delete_autocommands(...) + let augfile = tempname() + while 1 + try + exec "redir >" . augfile + aug + redir END + exec "edit" augfile + g/^$/d + norm G$ + let wrap = "w" + while search('\%( \|^\)\@<=.\{-}\%( \)\@=', wrap) > 0 + let wrap = "W" + exec "norm y/ \n" + let argno = 1 + while argno <= a:0 + exec "au!" escape(@", " ") a:{argno} + let argno = argno + 1 + endwhile + endwhile + catch /.*/ + finally + bwipeout! + call delete(augfile) + break + endtry + endwhile + endfunc + + call Delete_autocommands("BufWritePre", "BufWritePost") + + while 1 + try + try + let post = 0 + aug TMP + au! BufWritePost * let post = 1 + aug END + write /n/o/n/e/x/i/s/t/e/n/t + catch /^Vim(write):/ + Xpath 'a' + call assert_match("E212: Can't open file for writing", v:exception) + finally + Xpath 'b' + call assert_equal(0, post) + au! TMP + aug! TMP + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'c' + break + endtry + endwhile + + while 1 + try + try + let post = 0 + aug TMP + au! BufWritePre * asdf + au! BufWritePost * let post = 1 + aug END + let tmpfile = tempname() + exec "write" tmpfile + catch /^Vim\((write)\)\=:/ + Xpath 'd' + call assert_match('E492: Not an editor command', v:exception) + finally + Xpath 'e' + if filereadable(tmpfile) + call assert_report('should not get here') + endif + call assert_equal(0, post) + au! TMP + aug! TMP + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'f' + break + endtry + endwhile + + call delete(tmpfile) + + call Delete_autocommands("BufWritePre", "BufWritePost", + \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost") + + while 1 + try + try + let post = 0 + aug TMP + au! FileReadPost * let post = 1 + aug END + let caught = 0 + read /n/o/n/e/x/i/s/t/e/n/t + catch /^Vim(read):/ + Xpath 'g' + call assert_match("E484: Can't open file", v:exception) + finally + Xpath 'h' + call assert_equal(0, post) + au! TMP + aug! TMP + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'i' + break + endtry + endwhile + + while 1 + try + let infile = tempname() + let tmpfile = tempname() + call writefile(["XYZ"], infile) + exec "edit" tmpfile + try + Xpath 'j' + try + let post = 0 + aug TMP + au! FileReadPre * asdf + au! FileReadPost * let post = 1 + aug END + exec "0read" infile + catch /^Vim\((read)\)\=:/ + Xpath 'k' + call assert_match('E492: Not an editor command', v:exception) + finally + Xpath 'l' + if getline("1") == "XYZ" + call assert_report('should not get here') + endif + call assert_equal(0, post) + au! TMP + aug! TMP + endtry + finally + Xpath 'm' + bwipeout! + endtry + catch /.*/ + call assert_report('should not get here') + finally + Xpath 'n' + break + endtry + endwhile + + call delete(infile) + call delete(tmpfile) + [CODE] + let verify =<< trim [CODE] + call assert_equal('abcdefghijklmn', g:Xpath) + [CODE] + call RunInNewVim(test, verify) +endfunc + "------------------------------------------------------------------------------- " Test 87 using (expr) ? funcref : funcref {{{1 " diff --git a/src/version.c b/src/version.c index 990b945ab469c7..a31436bd0fb576 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1420, /**/ 1419, /**/ From 4301a729eabafee388aaf8465cf780d3f84cec95 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 11 Aug 2020 20:51:08 +0200 Subject: [PATCH 0135/1384] patch 8.2.1421: Vim9: handling "+" and "-" before number differs from script Problem: Vim9: handling "+" and "-" before number differs from Vim script. Solution: Use the same sequence of commands. --- src/version.c | 2 ++ src/vim9compile.c | 16 +++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/version.c b/src/version.c index a31436bd0fb576..7411bc0d89e2f1 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1421, /**/ 1420, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index d327b485556079..72c26ce46ee409 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3206,6 +3206,15 @@ compile_expr7( case '9': case '.': if (eval_number(arg, rettv, TRUE, FALSE) == FAIL) return FAIL; + // Apply "-" and "+" just before the number now, right to + // left. Matters especially when "->" follows. Stops at + // '!'. + if (apply_leader(rettv, TRUE, + start_leader, &end_leader) == FAIL) + { + clear_tv(rettv); + return FAIL; + } break; /* @@ -3344,13 +3353,6 @@ compile_expr7( if (rettv->v_type != VAR_UNKNOWN && used_before == ppconst->pp_used) { - // apply the '-' and '+' before the constant, but not '!' - if (apply_leader(rettv, TRUE, start_leader, &end_leader) == FAIL) - { - clear_tv(rettv); - return FAIL; - } - if (cctx->ctx_skip == SKIP_YES) clear_tv(rettv); else From 097148e849136b49052b1b5123c714fb1d74db9b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 11 Aug 2020 21:58:20 +0200 Subject: [PATCH 0136/1384] patch 8.2.1422: the Mac GUI implementation is outdated Problem: The Mac GUI implementation is outdated and probably doesn't even work. Solution: Remove the Mac GUI code. The MacVim project provides the supported Vim GUI version. --- Filelist | 2 - src/INSTALLmac.txt | 24 +- src/Makefile | 18 - src/auto/configure | 118 +- src/configure.ac | 82 +- src/evalfunc.c | 8 +- src/feature.h | 20 +- src/fileio.c | 6 - src/globals.h | 6 +- src/gui.c | 6 +- src/gui.h | 37 +- src/gui_mac.c | 6706 ----------------------------------------- src/if_mzsch.c | 14 - src/main.c | 39 - src/misc2.c | 2 +- src/mouse.c | 4 +- src/option.h | 3 - src/optiondefs.h | 12 +- src/os_mac.h | 19 - src/os_mac_conv.c | 2 +- src/os_unix.c | 4 +- src/proto.h | 3 - src/proto/gui_mac.pro | 153 - src/structs.h | 12 - src/version.c | 2 + src/vim.h | 10 +- 26 files changed, 48 insertions(+), 7264 deletions(-) delete mode 100644 src/gui_mac.c delete mode 100644 src/proto/gui_mac.pro diff --git a/Filelist b/Filelist index 02574e9a18ec36..fd8ff05e508ccd 100644 --- a/Filelist +++ b/Filelist @@ -642,13 +642,11 @@ SRC_HAIKU = \ SRC_MAC = \ src/INSTALLmac.txt \ src/dehqx.py \ - src/gui_mac.c \ src/os_mac_rsrc/*.icns \ src/os_mac.h \ src/os_mac.rsr.hqx \ src/os_mac_conv.c \ src/os_macosx.m \ - src/proto/gui_mac.pro \ src/proto/os_mac_conv.pro \ # source files for VMS (in the extra archive) diff --git a/src/INSTALLmac.txt b/src/INSTALLmac.txt index e957682a145597..ac122c351b5184 100644 --- a/src/INSTALLmac.txt +++ b/src/INSTALLmac.txt @@ -16,7 +16,7 @@ Summary ---------------------------------------------------------------------------- 1 MacOS X - 1.1. Carbon interface + 1.1. Terminal version 1.2. X (Athena, GTK, Motif) or plain text. MacOS Classic is no longer supported. If you really want it use Vim 6.4. @@ -27,9 +27,9 @@ MacOS Classic is no longer supported. If you really want it use Vim 6.4. 1.0 Considerations - Only '/' supported as path separator. + Only '/' is supported as path separator. -1.1 Carbon interface (default) +1.1 Terminal version (default) You can compile vim with the standard Unix routine: cd .../src @@ -37,14 +37,7 @@ MacOS Classic is no longer supported. If you really want it use Vim 6.4. make test sudo make install - "make" will create a working Vim.app application bundle in the src - directory. You can move this bundle (the Vim.app directory) anywhere - you want. Or use "make install" to move it to /Applications. - - You need at least Xcode 1.5 to compile Vim 7.0. - - Configure will create a universal binary if possible. This requires - installing the universal SDK (currently for 10.4). + You need at least Xcode 1.5. To overrule the architecture do this before running make: @@ -53,17 +46,16 @@ MacOS Classic is no longer supported. If you really want it use Vim 6.4. ./configure --with-mac-arch=ppc -1.2 X-Windows or Plain Text +1.2 X-Windows - If you do not want the Carbon interface, you must explicitly tell - configure to use a different GUI. + You must explicitly tell configure to use a GUI. cd .../src ./configure --disable-darwin --enable-gui=gtk2 make; make install - NOTE: The following GUI options are supported: - no (for text), motif, athena, nextaw + NOTE: The following GUI options are possible (but might not work): + no (for terminal only), motif, athena, nextaw gtk, gtk2, gnome, gnome2, NOTE: You need to first install XFree86 and XDarwin. diff --git a/src/Makefile b/src/Makefile index 5d73fc91a3f99e..35fe41e74c2522 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1373,24 +1373,6 @@ PHOTONGUI_MAN_TARGETS = yes PHOTONGUI_TESTTARGET = gui PHOTONGUI_BUNDLE = -# CARBON GUI -CARBONGUI_SRC = gui.c gui_mac.c -CARBONGUI_OBJ = objects/gui.o objects/gui_mac.o -CARBONGUI_DEFS = -DFEAT_GUI_MAC -fno-common -fpascal-strings \ - -Wall -Wno-unknown-pragmas \ - -mdynamic-no-pic -pipe -CARBONGUI_IPATH = -I. -Iproto -CARBONGUI_LIBS_DIR = -CARBONGUI_LIBS1 = -framework Carbon -CARBONGUI_LIBS2 = -CARBONGUI_INSTALL = install_macosx -CARBONGUI_TARGETS = -CARBONGUI_MAN_TARGETS = -CARBONGUI_TESTTARGET = gui -CARBONGUI_BUNDLE = gui_bundle -APPDIR = $(VIMNAME).app -CARBONGUI_TESTARG = VIMPROG=../$(APPDIR)/Contents/MacOS/$(VIMTARGET) - ### Haiku GUI HAIKUGUI_SRC = gui.c gui_haiku.cc HAIKUGUI_OBJ = objects/gui.o objects/gui_haiku.o diff --git a/src/auto/configure b/src/auto/configure index 54ee35d87a5d4c..fcb2f40e8cec53 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -829,7 +829,6 @@ enable_gtk3_check enable_motif_check enable_athena_check enable_nextaw_check -enable_carbon_check enable_gtktest with_gnome_includes with_gnome_libs @@ -1509,7 +1508,6 @@ Optional Features: --enable-motif-check If auto-select GUI, check for Motif default=yes --enable-athena-check If auto-select GUI, check for Athena default=yes --enable-nextaw-check If auto-select GUI, check for neXtaw default=yes - --enable-carbon-check If auto-select GUI, check for Carbon default=yes --disable-gtktest Do not try to compile and run a test GTK program --disable-icon-cache-update update disabled --disable-desktop-database-update update disabled @@ -4746,8 +4744,18 @@ rm -f core conftest.err conftest.$ac_objext \ OS_EXTRA_SRC="os_macosx.m os_mac_conv.c"; OS_EXTRA_OBJ="objects/os_macosx.o objects/os_mac_conv.o" CPPFLAGS="$CPPFLAGS -DMACOS_X_DARWIN" + fi + + if test "$MACARCH" = "intel" -o "$MACARCH" = "both"; then + CFLAGS=`echo "$CFLAGS" | sed 's/-O[23456789]/-Oz/'` + fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi - # On IRIX 5.3, sys/types and inttypes.h are conflicting. +# On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : @@ -4764,28 +4772,6 @@ fi done -ac_fn_c_check_header_mongrel "$LINENO" "Carbon/Carbon.h" "ac_cv_header_Carbon_Carbon_h" "$ac_includes_default" -if test "x$ac_cv_header_Carbon_Carbon_h" = xyes; then : - CARBON=yes -fi - - - if test "x$CARBON" = "xyes"; then - if test -z "$with_x" -a "X$enable_gui" != Xmotif -a "X$enable_gui" != Xathena -a "X$enable_gui" != Xgtk2 -a "X$enable_gui" != Xgtk3; then - with_x=no - fi - fi - fi - - if test "$MACARCH" = "intel" -o "$MACARCH" = "both"; then - CFLAGS=`echo "$CFLAGS" | sed 's/-O[23456789]/-Oz/'` - fi - -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - for ac_header in AvailabilityMacros.h do : ac_fn_c_check_header_mongrel "$LINENO" "AvailabilityMacros.h" "ac_cv_header_AvailabilityMacros_h" "$ac_includes_default" @@ -9212,7 +9198,6 @@ SKIP_ATHENA=YES SKIP_NEXTAW=YES SKIP_PHOTON=YES SKIP_HAIKU=YES -SKIP_CARBON=YES GUITYPE=NONE if test "x$HAIKU" = "xyes"; then @@ -9247,25 +9232,6 @@ $as_echo "Sorry, $enable_gui GUI is not supported" >&6; } SKIP_PHOTON=YES ;; esac -elif test "x$MACOS_X" = "xyes" -a "x$with_x" = "xno" ; then - SKIP_CARBON= - case "$enable_gui_canon" in - no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no GUI support" >&5 -$as_echo "no GUI support" >&6; } - SKIP_CARBON=YES ;; - yes|"") { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes - automatic GUI support" >&5 -$as_echo "yes - automatic GUI support" >&6; } - gui_auto=yes ;; - auto) { $as_echo "$as_me:${as_lineno-$LINENO}: result: auto - Carbon GUI is outdated - disable GUI support" >&5 -$as_echo "auto - Carbon GUI is outdated - disable GUI support" >&6; } - SKIP_CARBON=YES ;; - carbon) { $as_echo "$as_me:${as_lineno-$LINENO}: result: Carbon GUI support" >&5 -$as_echo "Carbon GUI support" >&6; } ;; - *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: Sorry, $enable_gui GUI is not supported" >&5 -$as_echo "Sorry, $enable_gui GUI is not supported" >&6; } - SKIP_CARBON=YES ;; - esac - else case "$enable_gui_canon" in @@ -9278,8 +9244,7 @@ $as_echo "yes/auto - automatic GUI support" >&6; } SKIP_GNOME= SKIP_MOTIF= SKIP_ATHENA= - SKIP_NEXTAW= - SKIP_CARBON=;; + SKIP_NEXTAW=;; gtk2) { $as_echo "$as_me:${as_lineno-$LINENO}: result: GTK+ 2.x GUI support" >&5 $as_echo "GTK+ 2.x GUI support" >&6; } SKIP_GTK2=;; @@ -9409,56 +9374,6 @@ $as_echo "$enable_nextaw_check" >&6; }; fi fi -if test "x$SKIP_CARBON" != "xYES" -a "$enable_gui_canon" != "carbon"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether or not to look for Carbon" >&5 -$as_echo_n "checking whether or not to look for Carbon... " >&6; } - # Check whether --enable-carbon-check was given. -if test "${enable_carbon_check+set}" = set; then : - enableval=$enable_carbon_check; -else - enable_carbon_check="yes" -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_carbon_check" >&5 -$as_echo "$enable_carbon_check" >&6; }; - if test "x$enable_carbon_check" = "xno"; then - SKIP_CARBON=YES - fi -fi - - -if test "x$MACOS_X" = "xyes" -a -z "$SKIP_CARBON" -a "x$CARBON" = "xyes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Carbon GUI" >&5 -$as_echo_n "checking for Carbon GUI... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; }; - GUITYPE=CARBONGUI - if test "$VIMNAME" = "vim"; then - VIMNAME=Vim - fi - - if test "x$MACARCH" = "xboth"; then - CPPFLAGS="$CPPFLAGS -I$DEVELOPER_DIR/SDKs/MacOSX10.4u.sdk/Developer/Headers/FlatCarbon" - else - CPPFLAGS="$CPPFLAGS -I$DEVELOPER_DIR/Headers/FlatCarbon" - fi - - if test x$prefix = xNONE; then - prefix=/Applications - fi - - datadir='${prefix}/Vim.app/Contents/Resources' - - SKIP_GTK2=YES; - SKIP_GNOME=YES; - SKIP_MOTIF=YES; - SKIP_ATHENA=YES; - SKIP_NEXTAW=YES; - SKIP_PHOTON=YES; - SKIP_HAIKU=YES; - SKIP_CARBON=YES -fi - @@ -14860,11 +14775,7 @@ fi if test "$MACOS_X" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we need macOS frameworks" >&5 $as_echo_n "checking whether we need macOS frameworks... " >&6; } - if test "$GUITYPE" = "CARBONGUI"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, we need Carbon" >&5 -$as_echo "yes, we need Carbon" >&6; } - LIBS="$LIBS -framework Carbon" - elif test "$MACOS_X_DARWIN" = "yes"; then + if test "$MACOS_X_DARWIN" = "yes"; then if test "$features" = "tiny"; then OS_EXTRA_SRC=`echo "$OS_EXTRA_SRC" | sed -e 's+os_macosx.m++'` OS_EXTRA_OBJ=`echo "$OS_EXTRA_OBJ" | sed -e 's+objects/os_macosx.o++'` @@ -14881,9 +14792,6 @@ $as_echo "yes, we need AppKit" >&6; } $as_echo "no" >&6; } fi fi -if test "x$MACARCH" = "xboth" && test "x$GUITYPE" = "xCARBONGUI"; then - LDFLAGS="$LDFLAGS -isysroot $DEVELOPER_DIR/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc" -fi DEPEND_CFLAGS_FILTER= if test "$GCC" = yes; then diff --git a/src/configure.ac b/src/configure.ac index 054ea1dcb8d11f..8a5216a8a3ceab 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -262,16 +262,6 @@ if test "`(uname) 2>/dev/null`" = Darwin; then dnl TODO: use -arch i386 on Intel machines dnl Removed -no-cpp-precomp, only for very old compilers. CPPFLAGS="$CPPFLAGS -DMACOS_X_DARWIN" - - dnl If Carbon is found, assume we don't want X11 - dnl unless it was specifically asked for (--with-x) - dnl or Motif, Athena or GTK GUI is used. - AC_CHECK_HEADER(Carbon/Carbon.h, CARBON=yes) - if test "x$CARBON" = "xyes"; then - if test -z "$with_x" -a "X$enable_gui" != Xmotif -a "X$enable_gui" != Xathena -a "X$enable_gui" != Xgtk2 -a "X$enable_gui" != Xgtk3; then - with_x=no - fi - fi fi dnl Avoid a bug with -O2 with gcc 4.0.1. Symptom: malloc() reports double @@ -2406,7 +2396,6 @@ SKIP_ATHENA=YES SKIP_NEXTAW=YES SKIP_PHOTON=YES SKIP_HAIKU=YES -SKIP_CARBON=YES GUITYPE=NONE if test "x$HAIKU" = "xyes"; then @@ -2432,20 +2421,6 @@ elif test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then SKIP_PHOTON=YES ;; esac -elif test "x$MACOS_X" = "xyes" -a "x$with_x" = "xno" ; then - SKIP_CARBON= - case "$enable_gui_canon" in - no) AC_MSG_RESULT(no GUI support) - SKIP_CARBON=YES ;; - yes|"") AC_MSG_RESULT(yes - automatic GUI support) - gui_auto=yes ;; - auto) AC_MSG_RESULT(auto - Carbon GUI is outdated - disable GUI support) - SKIP_CARBON=YES ;; - carbon) AC_MSG_RESULT(Carbon GUI support) ;; - *) AC_MSG_RESULT([Sorry, $enable_gui GUI is not supported]) - SKIP_CARBON=YES ;; - esac - else case "$enable_gui_canon" in @@ -2456,8 +2431,7 @@ else SKIP_GNOME= SKIP_MOTIF= SKIP_ATHENA= - SKIP_NEXTAW= - SKIP_CARBON=;; + SKIP_NEXTAW=;; gtk2) AC_MSG_RESULT(GTK+ 2.x GUI support) SKIP_GTK2=;; gnome2) AC_MSG_RESULT(GNOME 2.x GUI support) @@ -2544,52 +2518,6 @@ if test "x$SKIP_NEXTAW" != "xYES" -a "$enable_gui_canon" != "nextaw"; then fi fi -if test "x$SKIP_CARBON" != "xYES" -a "$enable_gui_canon" != "carbon"; then - AC_MSG_CHECKING(whether or not to look for Carbon) - AC_ARG_ENABLE(carbon-check, - [ --enable-carbon-check If auto-select GUI, check for Carbon [default=yes]], - , enable_carbon_check="yes") - AC_MSG_RESULT($enable_carbon_check); - if test "x$enable_carbon_check" = "xno"; then - SKIP_CARBON=YES - fi -fi - - -if test "x$MACOS_X" = "xyes" -a -z "$SKIP_CARBON" -a "x$CARBON" = "xyes"; then - AC_MSG_CHECKING(for Carbon GUI) - dnl already did the check, just give the message - AC_MSG_RESULT(yes); - GUITYPE=CARBONGUI - if test "$VIMNAME" = "vim"; then - VIMNAME=Vim - fi - - if test "x$MACARCH" = "xboth"; then - CPPFLAGS="$CPPFLAGS -I$DEVELOPER_DIR/SDKs/MacOSX10.4u.sdk/Developer/Headers/FlatCarbon" - else - CPPFLAGS="$CPPFLAGS -I$DEVELOPER_DIR/Headers/FlatCarbon" - fi - - dnl Default install directory is not /usr/local - if test x$prefix = xNONE; then - prefix=/Applications - fi - - dnl Sorry for the hard coded default - datadir='${prefix}/Vim.app/Contents/Resources' - - dnl skip everything else - SKIP_GTK2=YES; - SKIP_GNOME=YES; - SKIP_MOTIF=YES; - SKIP_ATHENA=YES; - SKIP_NEXTAW=YES; - SKIP_PHOTON=YES; - SKIP_HAIKU=YES; - SKIP_CARBON=YES -fi - dnl define an autoconf function to check for a specified version of GTK, and dnl try to compile/link a GTK program. dnl @@ -4454,10 +4382,7 @@ fi if test "$MACOS_X" = "yes"; then AC_MSG_CHECKING([whether we need macOS frameworks]) - if test "$GUITYPE" = "CARBONGUI"; then - AC_MSG_RESULT([yes, we need Carbon]) - LIBS="$LIBS -framework Carbon" - elif test "$MACOS_X_DARWIN" = "yes"; then + if test "$MACOS_X_DARWIN" = "yes"; then if test "$features" = "tiny"; then dnl Since no FEAT_CLIPBOARD, no longer need for os_macosx.m. OS_EXTRA_SRC=`echo "$OS_EXTRA_SRC" | sed -e 's+os_macosx.m++'` @@ -4472,9 +4397,6 @@ if test "$MACOS_X" = "yes"; then AC_MSG_RESULT([no]) fi fi -if test "x$MACARCH" = "xboth" && test "x$GUITYPE" = "xCARBONGUI"; then - LDFLAGS="$LDFLAGS -isysroot $DEVELOPER_DIR/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc" -fi dnl gcc 3.1 changed the meaning of -MM. The only solution appears to be to dnl use "-isystem" instead of "-I" for all non-Vim include dirs. diff --git a/src/evalfunc.c b/src/evalfunc.c index 5607ef9e5ba8a2..bbc3404e5bbb25 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -3920,13 +3920,7 @@ f_has(typval_T *argvars, typval_T *rettv) 0 #endif }, - {"gui_mac", -#ifdef FEAT_GUI_MAC - 1 -#else - 0 -#endif - }, + {"gui_mac", 0}, {"gui_motif", #ifdef FEAT_GUI_MOTIF 1 diff --git a/src/feature.h b/src/feature.h index 49175272f89d95..0c68f79f2a631c 100644 --- a/src/feature.h +++ b/src/feature.h @@ -632,7 +632,6 @@ #if defined(FEAT_NORMAL) \ && (defined(FEAT_GUI_GTK) \ || (defined(FEAT_GUI_MOTIF) && defined(HAVE_XM_NOTEBOOK_H)) \ - || defined(FEAT_GUI_MAC) \ || defined(FEAT_GUI_HAIKU) \ || (defined(FEAT_GUI_MSWIN) \ && (!defined(_MSC_VER) || _MSC_VER > 1020))) @@ -646,8 +645,7 @@ #if defined(FEAT_NORMAL) # define FEAT_BROWSE_CMD # if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \ - || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU) || defined(FEAT_GUI_PHOTON) \ - || defined(FEAT_GUI_MAC) + || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU) || defined(FEAT_GUI_PHOTON) # define FEAT_BROWSE # endif #endif @@ -657,8 +655,7 @@ * there is no terminal version, and on Windows we can't figure out how to * fork one off with :gui. */ -#if (defined(FEAT_GUI_MSWIN) && !defined(VIMDLL)) \ - || (defined(FEAT_GUI_MAC) && !defined(MACOS_X_DARWIN)) +#if defined(FEAT_GUI_MSWIN) && !defined(VIMDLL) # define ALWAYS_USE_GUI #endif @@ -673,8 +670,7 @@ || defined(FEAT_GUI_GTK) \ || defined(FEAT_GUI_PHOTON) \ || defined(FEAT_GUI_HAIKU) \ - || defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_MAC) + || defined(FEAT_GUI_MSWIN) # define FEAT_CON_DIALOG # define FEAT_GUI_DIALOG # else @@ -690,7 +686,7 @@ #if defined(FEAT_GUI_DIALOG) && \ (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \ || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) \ + || defined(FEAT_GUI_PHOTON) \ || defined(FEAT_GUI_HAIKU)) # define FEAT_GUI_TEXTDIALOG # ifndef ALWAYS_USE_GUI @@ -705,11 +701,6 @@ # define FEAT_TERMGUICOLORS #endif -// Mac specific thing: Codewarrior interface. -#ifdef FEAT_GUI_MAC -# define FEAT_CW_EDITOR -#endif - /* * +vartabs 'vartabstop' and 'varsofttabstop' options. */ @@ -1091,8 +1082,7 @@ #endif #if defined(FEAT_MZSCHEME) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK) \ - || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \ - || defined(FEAT_GUI_MAC)) + || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)) # define MZSCHEME_GUI_THREADS #endif diff --git a/src/fileio.c b/src/fileio.c index 189d4f41adcc6e..361109313b2a70 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -403,11 +403,6 @@ readfile( */ swap_mode = (st.st_mode & 0644) | 0600; #endif -#ifdef FEAT_CW_EDITOR - // Get the FSSpec on MacOS - // TODO: Update it properly when the buffer name changes - (void)GetFSSpecFromPath(curbuf->b_ffname, &curbuf->b_FSSpec); -#endif #ifdef VMS curbuf->b_fab_rfm = st.st_fab_rfm; curbuf->b_fab_rat = st.st_fab_rat; @@ -3389,7 +3384,6 @@ shorten_fnames(int force) #if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \ || defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_MAC) \ || defined(FEAT_GUI_HAIKU) \ || defined(PROTO) /* diff --git a/src/globals.h b/src/globals.h index 72b8a1e4604ebe..f64a874e4d11d7 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1569,7 +1569,7 @@ EXTERN char e_failed[] INIT(= N_("E472: Command failed")); #if defined(FEAT_GUI) && defined(FEAT_XFONTSET) EXTERN char e_fontset[] INIT(= N_("E234: Unknown fontset: %s")); #endif -#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MAC) \ +#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) \ || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU) EXTERN char e_font[] INIT(= N_("E235: Unknown font: %s")); #endif @@ -1806,10 +1806,6 @@ EXTERN char e_colon_required[] INIT(= N_("E1050: Colon required before a range") EXTERN char e_alloc_color[] INIT(= N_("E254: Cannot allocate color %s")); #endif -#ifdef FEAT_GUI_MAC -EXTERN short disallow_gui INIT(= FALSE); -#endif - EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM")); EXTERN char bot_top_msg[] INIT(= N_("search hit BOTTOM, continuing at TOP")); diff --git a/src/gui.c b/src/gui.c index 5d003a38b26bd6..5ae29facdebb1d 100644 --- a/src/gui.c +++ b/src/gui.c @@ -56,7 +56,7 @@ static int disable_flush = 0; // If > 0, gui_mch_flush() is disabled. * this makes the thumb indicate the part of the text that is shown. Motif * can't do this. */ -#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MAC) +#if defined(FEAT_GUI_ATHENA) # define SCROLL_PAST_END #endif @@ -846,7 +846,7 @@ gui_exit(int rc) } #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(PROTO) + || defined(FEAT_GUI_PHOTON) || defined(PROTO) # define NEED_GUI_UPDATE_SCREEN 1 /* * Called when the GUI shell is closed by the user. If there are no changed @@ -1377,7 +1377,7 @@ gui_position_components(int total_width UNUSED) #endif # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_MAC)) + || defined(FEAT_GUI_MOTIF)) if (gui_has_tabline()) text_area_y += gui.tabline_height; #endif diff --git a/src/gui.h b/src/gui.h index cfc4448168ac85..8b8b7fb1638552 100644 --- a/src/gui.h +++ b/src/gui.h @@ -39,25 +39,6 @@ # include #endif -#ifdef FEAT_GUI_MAC -# include -/*# include */ -# include -# include -# include -# include -# if !(defined (TARGET_API_MAC_CARBON) && (TARGET_API_MAC_CARBON)) -# include -# endif -# include -/*# include */ -# include -# include -/* -# include -# include */ -#endif - #ifdef FEAT_GUI_PHOTON # include # include @@ -68,7 +49,7 @@ * On some systems scrolling needs to be done right away instead of in the * main loop. */ -#if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK) +#if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK) # define USE_ON_FLY_SCROLL #endif @@ -77,7 +58,6 @@ */ #if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \ || defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_MAC) \ || defined(FEAT_GUI_HAIKU) # define HAVE_DROP_FILE #endif @@ -209,9 +189,6 @@ typedef struct GuiScrollbar #if FEAT_GUI_HAIKU VimScrollBar *id; // Pointer to real scroll bar #endif -#ifdef FEAT_GUI_MAC - ControlHandle id; // A handle to the scrollbar -#endif #ifdef FEAT_GUI_PHOTON PtWidget_t *id; #endif @@ -435,7 +412,7 @@ typedef struct Gui #if defined(FEAT_GUI_TABLINE) \ && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) \ - || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_HAIKU)) + || defined(FEAT_GUI_HAIKU)) int tabline_height; #endif @@ -473,14 +450,6 @@ typedef struct Gui int vdcmp; // Vim Direct Communication Message Port #endif -#ifdef FEAT_GUI_MAC - WindowPtr VimWindow; - MenuHandle MacOSHelpMenu; // Help menu provided by the MacOS - int MacOSHelpItems; // Nr of help-items supplied by MacOS - WindowPtr wid; // Window id of text area - int visibility; // Is window partially/fully obscured? -#endif - #ifdef FEAT_GUI_PHOTON PtWidget_t *vimWindow; // PtWindow PtWidget_t *vimTextArea; // PtRaw @@ -599,6 +568,6 @@ typedef enum # endif #endif // FEAT_GUI_GTK -#if defined(UNIX) && !defined(FEAT_GUI_MAC) +#if defined(UNIX) # define GUI_MAY_FORK #endif diff --git a/src/gui_mac.c b/src/gui_mac.c deleted file mode 100644 index b19061705efe50..00000000000000 --- a/src/gui_mac.c +++ /dev/null @@ -1,6706 +0,0 @@ -/* vi:set ts=8 sts=4 sw=4 noet: - * - * VIM - Vi IMproved by Bram Moolenaar - * GUI/Motif support by Robert Webb - * Macintosh port by Dany St-Amant - * and Axel Kielhorn - * Port to MPW by Bernhard Pruemmer - * Initial Carbon port by Ammon Skidmore - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - * See README.txt for an overview of the Vim source code. - */ - -/* - * NOTES: - Vim 7+ does not support classic MacOS. Please use Vim 6.x - * - Comments mentioning FAQ refer to the book: - * "Macworld Mac Programming FAQs" from "IDG Books" - */ - -/* - * TODO: Change still to merge from the macvim's iDisk - * - * error_ga, mch_errmsg, Navigation's changes in gui_mch_browse - * uses of MenuItemIndex, changes in gui_mch_set_shellsize, - * ScrapManager error handling. - * Comments about function remaining to Carbonize. - * - */ - -/* - * TODO (Jussi) - * * Clipboard does not work (at least some cases) - * * ATSU font rendering has some problems - * * Investigate and remove dead code (there is still lots of that) - */ - -#include // included first to avoid CR problems -#include "vim.h" - -#define USE_CARBONIZED -#define USE_AEVENT // Enable AEVENT -#undef USE_OFFSETED_WINDOW // Debugging feature: start Vim window OFFSETed - -// Compile as CodeWarrior External Editor -#if defined(FEAT_CW_EDITOR) && !defined(USE_AEVENT) -# define USE_AEVENT // Need Apple Event Support -#endif - -// Vim's Scrap flavor. -#define VIMSCRAPFLAVOR 'VIM!' -#define SCRAPTEXTFLAVOR kScrapFlavorTypeUnicode - -static EventHandlerUPP mouseWheelHandlerUPP = NULL; -SInt32 gMacSystemVersion; - -#ifdef MACOS_CONVERT -# define USE_CARBONKEYHANDLER - -static int im_is_active = FALSE; -# if 0 - // TODO: Implement me! -static int im_start_row = 0; -static int im_start_col = 0; -# endif - -# define NR_ELEMS(x) (sizeof(x) / sizeof(x[0])) - -static TSMDocumentID gTSMDocument; - -static void im_on_window_switch(int active); -static EventHandlerUPP keyEventHandlerUPP = NULL; -static EventHandlerUPP winEventHandlerUPP = NULL; - -static pascal OSStatus gui_mac_handle_window_activate( - EventHandlerCallRef nextHandler, EventRef theEvent, void *data); - -static pascal OSStatus gui_mac_handle_text_input( - EventHandlerCallRef nextHandler, EventRef theEvent, void *data); - -static pascal OSStatus gui_mac_update_input_area( - EventHandlerCallRef nextHandler, EventRef theEvent); - -static pascal OSStatus gui_mac_unicode_key_event( - EventHandlerCallRef nextHandler, EventRef theEvent); - -#endif - - -// Include some file. TODO: move into os_mac.h -#include -#include -#include -#ifdef USE_AEVENT -# include -# include -#endif -# include -#if UNIVERSAL_INTERFACES_VERSION >= 0x0330 -# include -# include // Navigation only part of ?? -#endif - -// Help Manager (balloon.h, HM prefixed functions) are not supported -// under Carbon (Jussi) -# if 0 -// New Help Interface for Mac, not implemented yet. -# include -# endif - -/* - * These seem to be rectangle options. Why are they not found in - * headers? (Jussi) - */ -#define kNothing 0 -#define kCreateEmpty 2 //1 -#define kCreateRect 2 -#define kDestroy 3 - -/* - * Dany: Don't like those... - */ -#define topLeft(r) (((Point*)&(r))[0]) -#define botRight(r) (((Point*)&(r))[1]) - - -// Time of last mouse click, to detect double-click -static long lastMouseTick = 0; - -// ??? -static RgnHandle cursorRgn; -static RgnHandle dragRgn; -static Rect dragRect; -static short dragRectEnbl; -static short dragRectControl; - -// This variable is set when waiting for an event, which is the only moment -// scrollbar dragging can be done directly. It's not allowed while commands -// are executed, because it may move the cursor and that may cause unexpected -// problems (e.g., while ":s" is working). -static int allow_scrollbar = FALSE; - -// Last mouse click caused contextual menu, (to provide proper release) -static short clickIsPopup; - -// Feedback Action for Scrollbar -ControlActionUPP gScrollAction; -ControlActionUPP gScrollDrag; - -// Keeping track of which scrollbar is being dragged -static ControlHandle dragged_sb = NULL; - -// Vector of char_u --> control index for hotkeys in dialogs -static short *gDialogHotKeys; - -static struct -{ - FMFontFamily family; - FMFontSize size; - FMFontStyle style; - Boolean isPanelVisible; -} gFontPanelInfo = { 0, 0, 0, false }; - -#ifdef MACOS_CONVERT -# define USE_ATSUI_DRAWING -int p_macatsui_last; -ATSUStyle gFontStyle; -ATSUStyle gWideFontStyle; -Boolean gIsFontFallbackSet; -UInt32 useAntialias_cached = 0x0; -#endif - -// Colors Macros -#define RGB(r,g,b) ((r) << 16) + ((g) << 8) + (b) -#define Red(c) ((c & 0x00FF0000) >> 16) -#define Green(c) ((c & 0x0000FF00) >> 8) -#define Blue(c) ((c & 0x000000FF) >> 0) - -// Key mapping - -#define vk_Esc 0x35 // -> 1B - -#define vk_F1 0x7A // -> 10 -#define vk_F2 0x78 //0x63 -#define vk_F3 0x63 //0x76 -#define vk_F4 0x76 //0x60 -#define vk_F5 0x60 //0x61 -#define vk_F6 0x61 //0x62 -#define vk_F7 0x62 //0x63 ? -#define vk_F8 0x64 -#define vk_F9 0x65 -#define vk_F10 0x6D -#define vk_F11 0x67 -#define vk_F12 0x6F -#define vk_F13 0x69 -#define vk_F14 0x6B -#define vk_F15 0x71 - -#define vk_Clr 0x47 // -> 1B (ESC) -#define vk_Enter 0x4C // -> 03 - -#define vk_Space 0x31 // -> 20 -#define vk_Tab 0x30 // -> 09 -#define vk_Return 0x24 // -> 0D -// This is wrong for OSX, what is it for? -#define vk_Delete 0X08 // -> 08 BackSpace - -#define vk_Help 0x72 // -> 05 -#define vk_Home 0x73 // -> 01 -#define vk_PageUp 0x74 // -> 0D -#define vk_FwdDelete 0x75 // -> 7F -#define vk_End 0x77 // -> 04 -#define vk_PageDown 0x79 // -> 0C - -#define vk_Up 0x7E // -> 1E -#define vk_Down 0x7D // -> 1F -#define vk_Left 0x7B // -> 1C -#define vk_Right 0x7C // -> 1D - -#define vk_Undo vk_F1 -#define vk_Cut vk_F2 -#define vk_Copy vk_F3 -#define vk_Paste vk_F4 -#define vk_PrintScreen vk_F13 -#define vk_SCrollLock vk_F14 -#define vk_Pause vk_F15 -#define vk_NumLock vk_Clr -#define vk_Insert vk_Help - -#define KeySym char - -static struct -{ - KeySym key_sym; - char_u vim_code0; - char_u vim_code1; -} special_keys[] = -{ - {vk_Up, 'k', 'u'}, - {vk_Down, 'k', 'd'}, - {vk_Left, 'k', 'l'}, - {vk_Right, 'k', 'r'}, - - {vk_F1, 'k', '1'}, - {vk_F2, 'k', '2'}, - {vk_F3, 'k', '3'}, - {vk_F4, 'k', '4'}, - {vk_F5, 'k', '5'}, - {vk_F6, 'k', '6'}, - {vk_F7, 'k', '7'}, - {vk_F8, 'k', '8'}, - {vk_F9, 'k', '9'}, - {vk_F10, 'k', ';'}, - - {vk_F11, 'F', '1'}, - {vk_F12, 'F', '2'}, - {vk_F13, 'F', '3'}, - {vk_F14, 'F', '4'}, - {vk_F15, 'F', '5'}, - -// {XK_Help, '%', '1'}, -// {XK_Undo, '&', '8'}, -// {XK_BackSpace, 'k', 'b'}, -// {vk_Delete, 'k', 'b'}, - {vk_Insert, 'k', 'I'}, - {vk_FwdDelete, 'k', 'D'}, - {vk_Home, 'k', 'h'}, - {vk_End, '@', '7'}, -// {XK_Prior, 'k', 'P'}, -// {XK_Next, 'k', 'N'}, -// {XK_Print, '%', '9'}, - - {vk_PageUp, 'k', 'P'}, - {vk_PageDown, 'k', 'N'}, - - // End of list marker: - {(KeySym)0, 0, 0} -}; - -/* - * ------------------------------------------------------------ - * Forward declaration (for those needed) - * ------------------------------------------------------------ - */ - -#ifdef USE_AEVENT -OSErr HandleUnusedParms(const AppleEvent *theAEvent); -#endif - -#ifdef FEAT_GUI_TABLINE -static void initialise_tabline(void); -static WindowRef drawer = NULL; // TODO: put into gui.h -#endif - -#ifdef USE_ATSUI_DRAWING -static void gui_mac_set_font_attributes(GuiFont font); -#endif - -/* - * ------------------------------------------------------------ - * Conversion Utility - * ------------------------------------------------------------ - */ - -/* - * C2Pascal_save - * - * Allocate memory and convert the C-String passed in - * into a pascal string - * - */ - - char_u * -C2Pascal_save(char_u *Cstring) -{ - char_u *PascalString; - int len; - - if (Cstring == NULL) - return NULL; - - len = STRLEN(Cstring); - - if (len > 255) // Truncate if necessary - len = 255; - - PascalString = alloc(len + 1); - if (PascalString != NULL) - { - mch_memmove(PascalString + 1, Cstring, len); - PascalString[0] = len; - } - - return PascalString; -} - -/* - * C2Pascal_save_and_remove_backslash - * - * Allocate memory and convert the C-String passed in - * into a pascal string. Also remove the backslash at the same time - * - */ - - char_u * -C2Pascal_save_and_remove_backslash(char_u *Cstring) -{ - char_u *PascalString; - int len; - char_u *p, *c; - - len = STRLEN(Cstring); - - if (len > 255) // Truncate if necessary - len = 255; - - PascalString = alloc(len + 1); - if (PascalString != NULL) - { - for (c = Cstring, p = PascalString+1, len = 0; (*c != 0) && (len < 255); c++) - { - if ((*c == '\\') && (c[1] != 0)) - c++; - *p = *c; - p++; - len++; - } - PascalString[0] = len; - } - - return PascalString; -} - -/* - * Convert the modifiers of an Event into vim's modifiers (mouse) - */ - - int_u -EventModifiers2VimMouseModifiers(EventModifiers macModifiers) -{ - int_u vimModifiers = 0x00; - - if (macModifiers & (shiftKey | rightShiftKey)) - vimModifiers |= MOUSE_SHIFT; - if (macModifiers & (controlKey | rightControlKey)) - vimModifiers |= MOUSE_CTRL; - if (macModifiers & (optionKey | rightOptionKey)) - vimModifiers |= MOUSE_ALT; -#if 0 - // Not yet supported - if (macModifiers & (cmdKey)) // There's no rightCmdKey - vimModifiers |= MOUSE_CMD; -#endif - return (vimModifiers); -} - -/* - * Convert the modifiers of an Event into vim's modifiers (keys) - */ - - static int_u -EventModifiers2VimModifiers(EventModifiers macModifiers) -{ - int_u vimModifiers = 0x00; - - if (macModifiers & (shiftKey | rightShiftKey)) - vimModifiers |= MOD_MASK_SHIFT; - if (macModifiers & (controlKey | rightControlKey)) - vimModifiers |= MOD_MASK_CTRL; - if (macModifiers & (optionKey | rightOptionKey)) - vimModifiers |= MOD_MASK_ALT; -#ifdef USE_CMD_KEY - if (macModifiers & (cmdKey)) // There's no rightCmdKey - vimModifiers |= MOD_MASK_CMD; -#endif - return (vimModifiers); -} - -/* - * Convert a string representing a point size into pixels. The string should - * be a positive decimal number, with an optional decimal point (eg, "12", or - * "10.5"). The pixel value is returned, and a pointer to the next unconverted - * character is stored in *end. The flag "vertical" says whether this - * calculation is for a vertical (height) size or a horizontal (width) one. - * - * From gui_w48.c - */ - static int -points_to_pixels(char_u *str, char_u **end, int vertical) -{ - int pixels; - int points = 0; - int divisor = 0; - - while (*str) - { - if (*str == '.' && divisor == 0) - { - // Start keeping a divisor, for later - divisor = 1; - continue; - } - - if (!isdigit(*str)) - break; - - points *= 10; - points += *str - '0'; - divisor *= 10; - - ++str; - } - - if (divisor == 0) - divisor = 1; - - pixels = points/divisor; - *end = str; - return pixels; -} - -#ifdef MACOS_CONVERT -/* - * Deletes all traces of any Windows-style mnemonic text (including any - * parentheses) from a menu item and returns the cleaned menu item title. - * The caller is responsible for releasing the returned string. - */ - static CFStringRef -menu_title_removing_mnemonic(vimmenu_T *menu) -{ - CFStringRef name; - size_t menuTitleLen; - CFIndex displayLen; - CFRange mnemonicStart; - CFRange mnemonicEnd; - CFMutableStringRef cleanedName; - - menuTitleLen = STRLEN(menu->dname); - name = (CFStringRef) mac_enc_to_cfstring(menu->dname, menuTitleLen); - - if (name) - { - // Simple mnemonic-removal algorithm, assumes single parenthesized - // mnemonic character towards the end of the menu text - mnemonicStart = CFStringFind(name, CFSTR("("), kCFCompareBackwards); - displayLen = CFStringGetLength(name); - - if (mnemonicStart.location != kCFNotFound - && (mnemonicStart.location + 2) < displayLen - && CFStringGetCharacterAtIndex(name, - mnemonicStart.location + 1) == (UniChar)menu->mnemonic) - { - if (CFStringFindWithOptions(name, CFSTR(")"), - CFRangeMake(mnemonicStart.location + 1, - displayLen - mnemonicStart.location - 1), - kCFCompareBackwards, &mnemonicEnd) && - (mnemonicStart.location + 2) == mnemonicEnd.location) - { - cleanedName = CFStringCreateMutableCopy(NULL, 0, name); - if (cleanedName) - { - CFStringDelete(cleanedName, - CFRangeMake(mnemonicStart.location, - mnemonicEnd.location + 1 - - mnemonicStart.location)); - - CFRelease(name); - name = cleanedName; - } - } - } - } - - return name; -} -#endif - -/* - * Convert a list of FSSpec aliases into a list of fullpathname - * character strings. - */ - - char_u ** -new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error) -{ - char_u **fnames = NULL; - OSErr newError; - long fileCount; - FSSpec fileToOpen; - long actualSize; - AEKeyword dummyKeyword; - DescType dummyType; - - // Get number of files in list - *error = AECountItems(theList, numFiles); - if (*error) - return fnames; - - // Allocate the pointer list - fnames = ALLOC_MULT(char_u *, *numFiles); - - // Empty out the list - for (fileCount = 0; fileCount < *numFiles; fileCount++) - fnames[fileCount] = NULL; - - // Scan the list of FSSpec - for (fileCount = 1; fileCount <= *numFiles; fileCount++) - { - // Get the alias for the nth file, convert to an FSSpec - newError = AEGetNthPtr(theList, fileCount, typeFSS, - &dummyKeyword, &dummyType, - (Ptr) &fileToOpen, sizeof(FSSpec), &actualSize); - if (newError) - { - // Caller is able to clean up - // TODO: Should be clean up or not? For safety. - return fnames; - } - - // Convert the FSSpec to a pathname - fnames[fileCount - 1] = FullPathFromFSSpec_save(fileToOpen); - } - - return (fnames); -} - -/* - * ------------------------------------------------------------ - * CodeWarrior External Editor Support - * ------------------------------------------------------------ - */ -#ifdef FEAT_CW_EDITOR - -/* - * Handle the Window Search event from CodeWarrior - * - * Description - * ----------- - * - * The IDE sends the Window Search AppleEvent to the editor when it - * needs to know whether a particular file is open in the editor. - * - * Event Reply - * ----------- - * - * None. Put data in the location specified in the structure received. - * - * Remarks - * ------- - * - * When the editor receives this event, determine whether the specified - * file is open. If it is, return the modification date/time for that file - * in the appropriate location specified in the structure. If the file is - * not opened, put the value fnfErr(file not found) in that location. - * - */ - -typedef struct WindowSearch WindowSearch; -struct WindowSearch // for handling class 'KAHL', event 'SRCH', keyDirectObject typeChar -{ - FSSpec theFile; // identifies the file - long *theDate; // where to put the modification date/time -}; - - pascal OSErr -Handle_KAHL_SRCH_AE( - const AppleEvent *theAEvent, - AppleEvent *theReply, - long refCon) -{ - OSErr error = noErr; - buf_T *buf; - int foundFile = false; - DescType typeCode; - WindowSearch SearchData; - Size actualSize; - - error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &SearchData, sizeof(WindowSearch), &actualSize); - if (error) - return error; - - error = HandleUnusedParms(theAEvent); - if (error) - return error; - - FOR_ALL_BUFFERS(buf) - if (buf->b_ml.ml_mfp != NULL - && SearchData.theFile.parID == buf->b_FSSpec.parID - && SearchData.theFile.name[0] == buf->b_FSSpec.name[0] - && STRNCMP(SearchData.theFile.name, buf->b_FSSpec.name, buf->b_FSSpec.name[0] + 1) == 0) - { - foundFile = true; - break; - } - - if (foundFile == false) - *SearchData.theDate = fnfErr; - else - *SearchData.theDate = buf->b_mtime; - - return error; -}; - -/* - * Handle the Modified (from IDE to Editor) event from CodeWarrior - * - * Description - * ----------- - * - * The IDE sends this event to the external editor when it wants to - * know which files that are open in the editor have been modified. - * - * Parameters None. - * ---------- - * - * Event Reply - * ----------- - * The reply for this event is: - * - * keyDirectObject typeAEList required - * each element in the list is a structure of typeChar - * - * Remarks - * ------- - * - * When building the reply event, include one element in the list for - * each open file that has been modified. - * - */ - -typedef struct ModificationInfo ModificationInfo; -struct ModificationInfo // for replying to class 'KAHL', event 'MOD ', keyDirectObject typeAEList -{ - FSSpec theFile; // identifies the file - long theDate; // the date/time the file was last modified - short saved; // set this to zero when replying, unused -}; - - pascal OSErr -Handle_KAHL_MOD_AE( - const AppleEvent *theAEvent, - AppleEvent *theReply, - long refCon) -{ - OSErr error = noErr; - AEDescList replyList; - long numFiles; - ModificationInfo theFile; - buf_T *buf; - - theFile.saved = 0; - - error = HandleUnusedParms(theAEvent); - if (error) - return error; - - // Send the reply -// replyObject.descriptorType = typeNull; -// replyObject.dataHandle = nil; - -// AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data) - error = AECreateList(nil, 0, false, &replyList); - if (error) - return error; - -#if 0 - error = AECountItems(&replyList, &numFiles); - - // AEPutKeyDesc(&replyList, keyAEPnject, &aDesc) - // AEPutKeyPtr(&replyList, keyAEPosition, typeChar, (Ptr)&theType, - // sizeof(DescType)) - - // AEPutDesc -#endif - - numFiles = 0; - FOR_ALL_BUFFERS(buf) - if (buf->b_ml.ml_mfp != NULL) - { - // Add this file to the list - theFile.theFile = buf->b_FSSpec; - theFile.theDate = buf->b_mtime; -// theFile.theDate = time(NULL) & (time_t) 0xFFFFFFF0; - error = AEPutPtr(&replyList, numFiles, typeChar, (Ptr) &theFile, sizeof(theFile)); - }; - -#if 0 - error = AECountItems(&replyList, &numFiles); -#endif - - // We can add data only if something to reply - error = AEPutParamDesc(theReply, keyDirectObject, &replyList); - - if (replyList.dataHandle) - AEDisposeDesc(&replyList); - - return error; -}; - -/* - * Handle the Get Text event from CodeWarrior - * - * Description - * ----------- - * - * The IDE sends the Get Text AppleEvent to the editor when it needs - * the source code from a file. For example, when the user issues a - * Check Syntax or Compile command, the compiler needs access to - * the source code contained in the file. - * - * Event Reply - * ----------- - * - * None. Put data in locations specified in the structure received. - * - * Remarks - * ------- - * - * When the editor receives this event, it must set the size of the handle - * in theText to fit the data in the file. It must then copy the entire - * contents of the specified file into the memory location specified in - * theText. - * - */ - -typedef struct CW_GetText CW_GetText; -struct CW_GetText // for handling class 'KAHL', event 'GTTX', keyDirectObject typeChar -{ - FSSpec theFile; // identifies the file - Handle theText; // the location where you return the text (must be resized properly) - long *unused; // 0 (not used) - long *theDate; // where to put the modification date/time -}; - - pascal OSErr -Handle_KAHL_GTTX_AE( - const AppleEvent *theAEvent, - AppleEvent *theReply, - long refCon) -{ - OSErr error = noErr; - buf_T *buf; - int foundFile = false; - DescType typeCode; - CW_GetText GetTextData; - Size actualSize; - char_u *line; - char_u *fullbuffer = NULL; - long linesize; - long lineStart; - long BufferSize; - long lineno; - - error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &GetTextData, sizeof(GetTextData), &actualSize); - - if (error) - return error; - - FOR_ALL_BUFFERS(buf) - if (buf->b_ml.ml_mfp != NULL) - if (GetTextData.theFile.parID == buf->b_FSSpec.parID) - { - foundFile = true; - break; - } - - if (foundFile) - { - BufferSize = 0; // GetHandleSize(GetTextData.theText); - for (lineno = 0; lineno <= buf->b_ml.ml_line_count; lineno++) - { - // Must use the right buffer - line = ml_get_buf(buf, (linenr_T) lineno, FALSE); - linesize = STRLEN(line) + 1; - lineStart = BufferSize; - BufferSize += linesize; - // Resize handle to linesize+1 to include the linefeed - SetHandleSize(GetTextData.theText, BufferSize); - if (GetHandleSize(GetTextData.theText) != BufferSize) - { - break; // Simple handling for now - } - else - { - HLock(GetTextData.theText); - fullbuffer = (char_u *) *GetTextData.theText; - STRCPY((char_u *)(fullbuffer + lineStart), line); - fullbuffer[BufferSize-1] = '\r'; - HUnlock(GetTextData.theText); - } - } - if (fullbuffer != NULL) - { - HLock(GetTextData.theText); - fullbuffer[BufferSize-1] = 0; - HUnlock(GetTextData.theText); - } - if (foundFile == false) - *GetTextData.theDate = fnfErr; - else -// *GetTextData.theDate = time(NULL) & (time_t) 0xFFFFFFF0; - *GetTextData.theDate = buf->b_mtime; - } - - error = HandleUnusedParms(theAEvent); - - return error; -} - -/* - * - */ - -/* - * Taken from MoreAppleEvents:ProcessHelpers - */ - pascal OSErr -FindProcessBySignature( - const OSType targetType, - const OSType targetCreator, - ProcessSerialNumberPtr psnPtr) -{ - OSErr anErr = noErr; - Boolean lookingForProcess = true; - - ProcessInfoRec infoRec; - - infoRec.processInfoLength = sizeof(ProcessInfoRec); - infoRec.processName = nil; - infoRec.processAppSpec = nil; - - psnPtr->lowLongOfPSN = kNoProcess; - psnPtr->highLongOfPSN = kNoProcess; - - while (lookingForProcess) - { - anErr = GetNextProcess(psnPtr); - if (anErr != noErr) - lookingForProcess = false; - else - { - anErr = GetProcessInformation(psnPtr, &infoRec); - if ((anErr == noErr) - && (infoRec.processType == targetType) - && (infoRec.processSignature == targetCreator)) - lookingForProcess = false; - } - } - - return anErr; -}//end FindProcessBySignature - - void -Send_KAHL_MOD_AE(buf_T *buf) -{ - OSErr anErr = noErr; - AEDesc targetAppDesc = { typeNull, nil }; - ProcessSerialNumber psn = { kNoProcess, kNoProcess }; - AppleEvent theReply = { typeNull, nil }; - AESendMode sendMode; - AppleEvent theEvent = {typeNull, nil }; - AEIdleUPP idleProcUPP = nil; - ModificationInfo ModData; - - - anErr = FindProcessBySignature('APPL', 'CWIE', &psn); - if (anErr == noErr) - { - anErr = AECreateDesc(typeProcessSerialNumber, &psn, - sizeof(ProcessSerialNumber), &targetAppDesc); - - if (anErr == noErr) - { - anErr = AECreateAppleEvent( 'KAHL', 'MOD ', &targetAppDesc, - kAutoGenerateReturnID, kAnyTransactionID, &theEvent); - } - - AEDisposeDesc(&targetAppDesc); - - // Add the parms - ModData.theFile = buf->b_FSSpec; - ModData.theDate = buf->b_mtime; - - if (anErr == noErr) - anErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, &ModData, sizeof(ModData)); - - if (idleProcUPP == nil) - sendMode = kAENoReply; - else - sendMode = kAEWaitReply; - - if (anErr == noErr) - anErr = AESend(&theEvent, &theReply, sendMode, kAENormalPriority, kNoTimeOut, idleProcUPP, nil); - if (anErr == noErr && sendMode == kAEWaitReply) - { -// anErr = AEHGetHandlerError(&theReply); - } - (void) AEDisposeDesc(&theReply); - } -} -#endif // FEAT_CW_EDITOR - -/* - * ------------------------------------------------------------ - * Apple Event Handling procedure - * ------------------------------------------------------------ - */ -#ifdef USE_AEVENT - -/* - * Handle the Unused parms of an AppleEvent - */ - - OSErr -HandleUnusedParms(const AppleEvent *theAEvent) -{ - OSErr error; - long actualSize; - DescType dummyType; - AEKeyword missedKeyword; - - // Get the "missed keyword" attribute from the AppleEvent. - error = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr, - typeKeyword, &dummyType, - (Ptr)&missedKeyword, sizeof(missedKeyword), - &actualSize); - - // If the descriptor isn't found, then we got the required parameters. - if (error == errAEDescNotFound) - { - error = noErr; - } - else - { -#if 0 - // Why is this removed? - error = errAEEventNotHandled; -#endif - } - - return error; -} - - -/* - * Handle the ODoc AppleEvent - * - * Deals with all files dragged to the application icon. - * - */ - -typedef struct SelectionRange SelectionRange; -struct SelectionRange // for handling kCoreClassEvent:kOpenDocuments:keyAEPosition typeChar -{ - short unused1; // 0 (not used) - short lineNum; // line to select (<0 to specify range) - long startRange; // start of selection range (if line < 0) - long endRange; // end of selection range (if line < 0) - long unused2; // 0 (not used) - long theDate; // modification date/time -}; - -static long drop_numFiles; -static short drop_gotPosition; -static SelectionRange drop_thePosition; - - static void -drop_callback(void *cookie UNUSED) -{ - // TODO: Handle the goto/select line more cleanly - if ((drop_numFiles == 1) & (drop_gotPosition)) - { - if (drop_thePosition.lineNum >= 0) - { - lnum = drop_thePosition.lineNum + 1; - // oap->motion_type = MLINE; - // setpcmark(); - if (lnum < 1L) - lnum = 1L; - else if (lnum > curbuf->b_ml.ml_line_count) - lnum = curbuf->b_ml.ml_line_count; - curwin->w_cursor.lnum = lnum; - curwin->w_cursor.col = 0; - // beginline(BL_SOL | BL_FIX); - } - else - goto_byte(drop_thePosition.startRange + 1); - } - - // Update the screen display - update_screen(NOT_VALID); - - // Select the text if possible - if (drop_gotPosition) - { - VIsual_active = TRUE; - VIsual_select = FALSE; - VIsual = curwin->w_cursor; - if (drop_thePosition.lineNum < 0) - { - VIsual_mode = 'v'; - goto_byte(drop_thePosition.endRange); - } - else - { - VIsual_mode = 'V'; - VIsual.col = 0; - } - } -} - -/* - * The IDE uses the optional keyAEPosition parameter to tell the ed- - * itor the selection range. If lineNum is zero or greater, scroll the text - * to the specified line. If lineNum is less than zero, use the values in - * startRange and endRange to select the specified characters. Scroll - * the text to display the selection. If lineNum, startRange, and - * endRange are all negative, there is no selection range specified. - */ - pascal OSErr -HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon) -{ - /* - * TODO: Clean up the code with convert the AppleEvent into - * a ":args" - */ - OSErr error = noErr; -// OSErr firstError = noErr; -// short numErrors = 0; - AEDesc theList; - DescType typeCode; - long numFiles; - // long fileCount; - char_u **fnames; -// char_u fname[256]; - Size actualSize; - SelectionRange thePosition; - short gotPosition = false; - long lnum; - - // the direct object parameter is the list of aliases to files (one or more) - error = AEGetParamDesc(theAEvent, keyDirectObject, typeAEList, &theList); - if (error) - return error; - - - error = AEGetParamPtr(theAEvent, keyAEPosition, typeChar, &typeCode, (Ptr) &thePosition, sizeof(SelectionRange), &actualSize); - if (error == noErr) - gotPosition = true; - if (error == errAEDescNotFound) - error = noErr; - if (error) - return error; - -/* - error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition); - - if (^error) then - { - if (thePosition.lineNum >= 0) - { - // Goto this line - } - else - { - // Set the range char wise - } - } - */ - - reset_VIsual(); - fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error); - - if (error) - { - // TODO: empty fnames[] first - vim_free(fnames); - return (error); - } - - if (starting > 0) - { - int i; - char_u *p; - int fnum = -1; - - // these are the initial files dropped on the Vim icon - for (i = 0 ; i < numFiles; i++) - { - if (ga_grow(&global_alist.al_ga, 1) == FAIL - || (p = vim_strsave(fnames[i])) == NULL) - mch_exit(2); - else - alist_add(&global_alist, p, 2); - if (fnum == -1) - fnum = GARGLIST[GARGCOUNT - 1].ae_fnum; - } - - // If the file name was already in the buffer list we need to switch - // to it. - if (curbuf->b_fnum != fnum) - { - char_u cmd[30]; - - vim_snprintf((char *)cmd, 30, "silent %dbuffer", fnum); - do_cmdline_cmd(cmd); - } - - // Change directory to the location of the first file. - if (GARGCOUNT > 0 - && vim_chdirfile(alist_name(&GARGLIST[0]), "drop") == OK) - shorten_fnames(TRUE); - - goto finished; - } - - // Handle the drop, :edit to get to the file - drop_numFiles = numFiles; - drop_gotPosition = gotPosition; - drop_thePosition = thePosition; - handle_drop(numFiles, fnames, FALSE, drop_callback, NULL); - - setcursor(); - out_flush(); - - // Fake mouse event to wake from stall - PostEvent(mouseUp, 0); - -finished: - AEDisposeDesc(&theList); // dispose what we allocated - - error = HandleUnusedParms(theAEvent); - return error; -} - -/* - * - */ - pascal OSErr -Handle_aevt_oapp_AE( - const AppleEvent *theAEvent, - AppleEvent *theReply, - long refCon) -{ - OSErr error = noErr; - - error = HandleUnusedParms(theAEvent); - return error; -} - -/* - * - */ - pascal OSErr -Handle_aevt_quit_AE( - const AppleEvent *theAEvent, - AppleEvent *theReply, - long refCon) -{ - OSErr error = noErr; - - error = HandleUnusedParms(theAEvent); - if (error) - return error; - - // Need to fake a :confirm qa - do_cmdline_cmd((char_u *)"confirm qa"); - - return error; -} - -/* - * - */ - pascal OSErr -Handle_aevt_pdoc_AE( - const AppleEvent *theAEvent, - AppleEvent *theReply, - long refCon) -{ - OSErr error = noErr; - - error = HandleUnusedParms(theAEvent); - - return error; -} - -/* - * Handling of unknown AppleEvent - * - * (Just get rid of all the parms) - */ - pascal OSErr -Handle_unknown_AE( - const AppleEvent *theAEvent, - AppleEvent *theReply, - long refCon) -{ - OSErr error = noErr; - - error = HandleUnusedParms(theAEvent); - - return error; -} - - -/* - * Install the various AppleEvent Handlers - */ - OSErr -InstallAEHandlers(void) -{ - OSErr error; - - // install open application handler - error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, - NewAEEventHandlerUPP(Handle_aevt_oapp_AE), 0, false); - if (error) - return error; - - // install quit application handler - error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, - NewAEEventHandlerUPP(Handle_aevt_quit_AE), 0, false); - if (error) - return error; - - // install open document handler - error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, - NewAEEventHandlerUPP(HandleODocAE), 0, false); - if (error) - return error; - - // install print document handler - error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, - NewAEEventHandlerUPP(Handle_aevt_pdoc_AE), 0, false); - -// Install Core Suite -#if 0 - error = AEInstallEventHandler(kAECoreSuite, kAEClone, - NewAEEventHandlerUPP(Handle_unknown_AE), nil, false); - - error = AEInstallEventHandler(kAECoreSuite, kAEClose, - NewAEEventHandlerUPP(Handle_unknown_AE), nil, false); - - error = AEInstallEventHandler(kAECoreSuite, kAECountElements, - NewAEEventHandlerUPP(Handle_unknown_AE), nil, false); - - error = AEInstallEventHandler(kAECoreSuite, kAECreateElement, - NewAEEventHandlerUPP(Handle_unknown_AE), nil, false); - - error = AEInstallEventHandler(kAECoreSuite, kAEDelete, - NewAEEventHandlerUPP(Handle_unknown_AE), nil, false); - - error = AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist, - NewAEEventHandlerUPP(Handle_unknown_AE), nil, false); - - error = AEInstallEventHandler(kAECoreSuite, kAEGetData, - NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetData, false); - - error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize, - NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetDataSize, false); - - error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo, - NewAEEventHandlerUPP(Handle_unknown_AE), nil, false); - - error = AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo, - NewAEEventHandlerUPP(Handle_unknown_AE), nil, false); - - error = AEInstallEventHandler(kAECoreSuite, kAEMove, - NewAEEventHandlerUPP(Handle_unknown_AE), nil, false); - - error = AEInstallEventHandler(kAECoreSuite, kAESave, - NewAEEventHandlerUPP(Handle_unknown_AE), nil, false); - - error = AEInstallEventHandler(kAECoreSuite, kAESetData, - NewAEEventHandlerUPP(Handle_unknown_AE), nil, false); -#endif - -#ifdef FEAT_CW_EDITOR - /* - * Bind codewarrior support handlers - */ - error = AEInstallEventHandler('KAHL', 'GTTX', - NewAEEventHandlerUPP(Handle_KAHL_GTTX_AE), 0, false); - if (error) - return error; - error = AEInstallEventHandler('KAHL', 'SRCH', - NewAEEventHandlerUPP(Handle_KAHL_SRCH_AE), 0, false); - if (error) - return error; - error = AEInstallEventHandler('KAHL', 'MOD ', - NewAEEventHandlerUPP(Handle_KAHL_MOD_AE), 0, false); -#endif - - return error; - -} -#endif // USE_AEVENT - - -/* - * Callback function, installed by InstallFontPanelHandler(), below, - * to handle Font Panel events. - */ - static OSStatus -FontPanelHandler( - EventHandlerCallRef inHandlerCallRef, - EventRef inEvent, - void *inUserData) -{ - if (GetEventKind(inEvent) == kEventFontPanelClosed) - { - gFontPanelInfo.isPanelVisible = false; - return noErr; - } - - if (GetEventKind(inEvent) == kEventFontSelection) - { - OSStatus status; - FMFontFamily newFamily; - FMFontSize newSize; - FMFontStyle newStyle; - - // Retrieve the font family ID number. - status = GetEventParameter(inEvent, kEventParamFMFontFamily, - /*inDesiredType=*/typeFMFontFamily, /*outActualType=*/NULL, - /*inBufferSize=*/sizeof(FMFontFamily), /*outActualSize=*/NULL, - &newFamily); - if (status == noErr) - gFontPanelInfo.family = newFamily; - - // Retrieve the font size. - status = GetEventParameter(inEvent, kEventParamFMFontSize, - typeFMFontSize, NULL, sizeof(FMFontSize), NULL, &newSize); - if (status == noErr) - gFontPanelInfo.size = newSize; - - // Retrieve the font style (bold, etc.). Currently unused. - status = GetEventParameter(inEvent, kEventParamFMFontStyle, - typeFMFontStyle, NULL, sizeof(FMFontStyle), NULL, &newStyle); - if (status == noErr) - gFontPanelInfo.style = newStyle; - } - return noErr; -} - - - static void -InstallFontPanelHandler(void) -{ - EventTypeSpec eventTypes[2]; - EventHandlerUPP handlerUPP; - // EventHandlerRef handlerRef; - - eventTypes[0].eventClass = kEventClassFont; - eventTypes[0].eventKind = kEventFontSelection; - eventTypes[1].eventClass = kEventClassFont; - eventTypes[1].eventKind = kEventFontPanelClosed; - - handlerUPP = NewEventHandlerUPP(FontPanelHandler); - - InstallApplicationEventHandler(handlerUPP, /*numTypes=*/2, eventTypes, - /*userData=*/NULL, /*handlerRef=*/NULL); -} - - -/* - * Fill the buffer pointed to by outName with the name and size - * of the font currently selected in the Font Panel. - */ -#define FONT_STYLE_BUFFER_SIZE 32 - static void -GetFontPanelSelection(char_u *outName) -{ - Str255 buf; - ByteCount fontNameLen = 0; - ATSUFontID fid; - char_u styleString[FONT_STYLE_BUFFER_SIZE]; - - if (!outName) - return; - - if (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr) - { - // Canonicalize localized font names - if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family, - gFontPanelInfo.style, &fid, NULL) != noErr) - return; - - // Request font name with Mac encoding (otherwise we could - // get an unwanted utf-16 name) - if (ATSUFindFontName(fid, kFontFullName, kFontMacintoshPlatform, - kFontNoScriptCode, kFontNoLanguageCode, - 255, (char *)outName, &fontNameLen, NULL) != noErr) - return; - - // Only encode font size, because style (bold, italic, etc) is - // already part of the font full name - vim_snprintf((char *)styleString, FONT_STYLE_BUFFER_SIZE, ":h%d", - gFontPanelInfo.size/*, - ((gFontPanelInfo.style & bold)!=0 ? ":b" : ""), - ((gFontPanelInfo.style & italic)!=0 ? ":i" : ""), - ((gFontPanelInfo.style & underline)!=0 ? ":u" : "")*/); - - if ((fontNameLen + STRLEN(styleString)) < 255) - STRCPY(outName + fontNameLen, styleString); - } - else - { - *outName = NUL; - } -} - - -/* - * ------------------------------------------------------------ - * Unfiled yet - * ------------------------------------------------------------ - */ - -/* - * gui_mac_get_menu_item_index - * - * Returns the index inside the menu where - */ - short // Should we return MenuItemIndex? -gui_mac_get_menu_item_index(vimmenu_T *pMenu) -{ - short index; - short itemIndex = -1; - vimmenu_T *pBrother; - - // Only menu without parent are the: - // -menu in the menubar - // -popup menu - // -toolbar (guess) - // - // Which are not items anyway. - if (pMenu->parent) - { - // Start from the Oldest Brother - pBrother = pMenu->parent->children; - index = 1; - while ((pBrother) && (itemIndex == -1)) - { - if (pBrother == pMenu) - itemIndex = index; - index++; - pBrother = pBrother->next; - } - } - return itemIndex; -} - - static vimmenu_T * -gui_mac_get_vim_menu(short menuID, short itemIndex, vimmenu_T *pMenu) -{ - short index; - vimmenu_T *pChildMenu; - vimmenu_T *pElder = pMenu->parent; - - - // Only menu without parent are the: - // -menu in the menubar - // -popup menu - // -toolbar (guess) - // - // Which are not items anyway. - - if ((pElder) && (pElder->submenu_id == menuID)) - { - for (index = 1; (index != itemIndex) && (pMenu != NULL); index++) - pMenu = pMenu->next; - } - else - { - for (; pMenu != NULL; pMenu = pMenu->next) - { - if (pMenu->children != NULL) - { - pChildMenu = gui_mac_get_vim_menu - (menuID, itemIndex, pMenu->children); - if (pChildMenu) - { - pMenu = pChildMenu; - break; - } - } - } - } - return pMenu; -} - -/* - * ------------------------------------------------------------ - * MacOS Feedback procedures - * ------------------------------------------------------------ - */ - pascal - void -gui_mac_drag_thumb(ControlHandle theControl, short partCode) -{ - scrollbar_T *sb; - int value, dragging; - ControlHandle theControlToUse; - int dont_scroll_save = dont_scroll; - - theControlToUse = dragged_sb; - - sb = gui_find_scrollbar((long) GetControlReference(theControlToUse)); - - if (sb == NULL) - return; - - // Need to find value by diff between Old Poss New Pos - value = GetControl32BitValue(theControlToUse); - dragging = (partCode != 0); - - // When "allow_scrollbar" is FALSE still need to remember the new - // position, but don't actually scroll by setting "dont_scroll". - dont_scroll = !allow_scrollbar; - gui_drag_scrollbar(sb, value, dragging); - dont_scroll = dont_scroll_save; -} - - pascal - void -gui_mac_scroll_action(ControlHandle theControl, short partCode) -{ - // TODO: have live support - scrollbar_T *sb, *sb_info; - long data; - long value; - int page; - int dragging = FALSE; - int dont_scroll_save = dont_scroll; - - sb = gui_find_scrollbar((long)GetControlReference(theControl)); - - if (sb == NULL) - return; - - if (sb->wp != NULL) // Left or right scrollbar - { - /* - * Careful: need to get scrollbar info out of first (left) scrollbar - * for window, but keep real scrollbar too because we must pass it to - * gui_drag_scrollbar(). - */ - sb_info = &sb->wp->w_scrollbars[0]; - - if (sb_info->size > 5) - page = sb_info->size - 2; // use two lines of context - else - page = sb_info->size; - } - else // Bottom scrollbar - { - sb_info = sb; - page = curwin->w_width - 5; - } - - switch (partCode) - { - case kControlUpButtonPart: data = -1; break; - case kControlDownButtonPart: data = 1; break; - case kControlPageDownPart: data = page; break; - case kControlPageUpPart: data = -page; break; - default: data = 0; break; - } - - value = sb_info->value + data; -// if (value > sb_info->max) -// value = sb_info->max; -// else if (value < 0) -// value = 0; - - // When "allow_scrollbar" is FALSE still need to remember the new - // position, but don't actually scroll by setting "dont_scroll". - dont_scroll = !allow_scrollbar; - gui_drag_scrollbar(sb, value, dragging); - dont_scroll = dont_scroll_save; - - out_flush(); - gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max); - -#if 0 - if (sb_info->wp != NULL) - { - win_T *wp; - int sb_num; - - sb_num = 0; - for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp)) - sb_num++; - - if (wp != NULL) - { - current_scrollbar = sb_num; - scrollbar_value = value; - gui_do_scroll(); - gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max); - } - } -#endif -} - -/* - * ------------------------------------------------------------ - * MacOS Click Handling procedures - * ------------------------------------------------------------ - */ - - -/* - * Handle a click inside the window, it may happens in the - * scrollbar or the contents. - * - * TODO: Add support for potential TOOLBAR - */ - void -gui_mac_doInContentClick(EventRecord *theEvent, WindowPtr whichWindow) -{ - Point thePoint; - int_u vimModifiers; - short thePortion; - ControlHandle theControl; - int vimMouseButton; - short dblClick; - - thePoint = theEvent->where; - GlobalToLocal(&thePoint); - SelectWindow(whichWindow); - - thePortion = FindControl(thePoint, whichWindow, &theControl); - - if (theControl != NUL) - { - // We hit a scrollbar - - if (thePortion != kControlIndicatorPart) - { - dragged_sb = theControl; - TrackControl(theControl, thePoint, gScrollAction); - dragged_sb = NULL; - } - else - { - dragged_sb = theControl; -#if 1 - TrackControl(theControl, thePoint, gScrollDrag); -#else - TrackControl(theControl, thePoint, NULL); -#endif - // pass 0 as the part to tell gui_mac_drag_thumb, that the mouse - // button has been released - gui_mac_drag_thumb(theControl, 0); // Should it be thePortion ? (Dany) - dragged_sb = NULL; - } - } - else - { - // We are inside the contents - - // Convert the CTRL, OPTION, SHIFT and CMD key - vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers); - - // Defaults to MOUSE_LEFT as there's only one mouse button - vimMouseButton = MOUSE_LEFT; - - // Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT - // TODO: NEEDED? - clickIsPopup = FALSE; - - if (mouse_model_popup() && IsShowContextualMenuClick(theEvent)) - { - vimMouseButton = MOUSE_RIGHT; - vimModifiers &= ~MOUSE_CTRL; - clickIsPopup = TRUE; - } - - // Is it a double click ? - dblClick = ((theEvent->when - lastMouseTick) < GetDblTime()); - - // Send the mouse click to Vim - gui_send_mouse_event(vimMouseButton, thePoint.h, - thePoint.v, dblClick, vimModifiers); - - // Create the rectangle around the cursor to detect - // the mouse dragging -#if 0 - // TODO: Do we need to this even for the contextual menu? - // It may be require for popup_setpos, but for popup? - if (vimMouseButton == MOUSE_LEFT) -#endif - { - SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)), - FILL_Y(Y_2_ROW(thePoint.v)), - FILL_X(X_2_COL(thePoint.h)+1), - FILL_Y(Y_2_ROW(thePoint.v)+1)); - - dragRectEnbl = TRUE; - dragRectControl = kCreateRect; - } - } -} - -/* - * Handle the click in the titlebar (to move the window) - */ - void -gui_mac_doInDragClick(Point where, WindowPtr whichWindow) -{ - Rect movingLimits; - Rect *movingLimitsPtr = &movingLimits; - - // TODO: may try to prevent move outside screen? - movingLimitsPtr = GetRegionBounds(GetGrayRgn(), &movingLimits); - DragWindow(whichWindow, where, movingLimitsPtr); -} - -/* - * Handle the click in the grow box - */ - void -gui_mac_doInGrowClick(Point where, WindowPtr whichWindow) -{ - - long newSize; - unsigned short newWidth; - unsigned short newHeight; - Rect resizeLimits; - Rect *resizeLimitsPtr = &resizeLimits; - Rect NewContentRect; - - resizeLimitsPtr = GetRegionBounds(GetGrayRgn(), &resizeLimits); - - // Set the minimum size - // TODO: Should this come from Vim? - resizeLimits.top = 100; - resizeLimits.left = 100; - - newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect); - newWidth = NewContentRect.right - NewContentRect.left; - newHeight = NewContentRect.bottom - NewContentRect.top; - gui_resize_shell(newWidth, newHeight); - gui_mch_set_bg_color(gui.back_pixel); - gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH); -} - -/* - * Handle the click in the zoom box - */ - static void -gui_mac_doInZoomClick(EventRecord *theEvent, WindowPtr whichWindow) -{ - Rect r; - Point p; - short thePart; - - // ideal width is current - p.h = Columns * gui.char_width + 2 * gui.border_offset; - if (gui.which_scrollbars[SBAR_LEFT]) - p.h += gui.scrollbar_width; - if (gui.which_scrollbars[SBAR_RIGHT]) - p.h += gui.scrollbar_width; - // ideal height is as high as we can get - p.v = 15 * 1024; - - thePart = IsWindowInStandardState(whichWindow, &p, &r) - ? inZoomIn : inZoomOut; - - if (!TrackBox(whichWindow, theEvent->where, thePart)) - return; - - // use returned width - p.h = r.right - r.left; - // adjust returned height - p.v = r.bottom - r.top - 2 * gui.border_offset; - if (gui.which_scrollbars[SBAR_BOTTOM]) - p.v -= gui.scrollbar_height; - p.v -= p.v % gui.char_height; - p.v += 2 * gui.border_width; - if (gui.which_scrollbars[SBAR_BOTTOM]) - p.v += gui.scrollbar_height; - - ZoomWindowIdeal(whichWindow, thePart, &p); - - GetWindowBounds(whichWindow, kWindowContentRgn, &r); - gui_resize_shell(r.right - r.left, r.bottom - r.top); - gui_mch_set_bg_color(gui.back_pixel); - gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH); -} - -/* - * ------------------------------------------------------------ - * MacOS Event Handling procedure - * ------------------------------------------------------------ - */ - -/* - * Handle the Update Event - */ - - void -gui_mac_doUpdateEvent(EventRecord *event) -{ - WindowPtr whichWindow; - GrafPtr savePort; - RgnHandle updateRgn; - Rect updateRect; - Rect *updateRectPtr; - Rect rc; - Rect growRect; - RgnHandle saveRgn; - - - updateRgn = NewRgn(); - if (updateRgn == NULL) - return; - - // This could be done by the caller as we - // don't require anything else out of the event - whichWindow = (WindowPtr) event->message; - - // Save Current Port - GetPort(&savePort); - - // Select the Window's Port - SetPortWindowPort(whichWindow); - - // Let's update the window - BeginUpdate(whichWindow); - // Redraw the biggest rectangle covering the area - // to be updated. - GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn); -# if 0 - // Would be more appropriate to use the following but doesn't - // seem to work under MacOS X (Dany) - GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn); -# endif - - // Use the HLock useless in Carbon? Is it harmful? - HLock((Handle) updateRgn); - - updateRectPtr = GetRegionBounds(updateRgn, &updateRect); -# if 0 - // Code from original Carbon Port (using GetWindowRegion. - // I believe the UpdateRgn is already in local (Dany) - GlobalToLocal(&topLeft(updateRect)); // preCarbon? - GlobalToLocal(&botRight(updateRect)); -# endif - // Update the content (i.e. the text) - gui_redraw(updateRectPtr->left, updateRectPtr->top, - updateRectPtr->right - updateRectPtr->left, - updateRectPtr->bottom - updateRectPtr->top); - // Clear the border areas if needed - gui_mch_set_bg_color(gui.back_pixel); - if (updateRectPtr->left < FILL_X(0)) - { - SetRect(&rc, 0, 0, FILL_X(0), FILL_Y(Rows)); - EraseRect(&rc); - } - if (updateRectPtr->top < FILL_Y(0)) - { - SetRect(&rc, 0, 0, FILL_X(Columns), FILL_Y(0)); - EraseRect(&rc); - } - if (updateRectPtr->right > FILL_X(Columns)) - { - SetRect(&rc, FILL_X(Columns), 0, - FILL_X(Columns) + gui.border_offset, FILL_Y(Rows)); - EraseRect(&rc); - } - if (updateRectPtr->bottom > FILL_Y(Rows)) - { - SetRect(&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset, - FILL_Y(Rows) + gui.border_offset); - EraseRect(&rc); - } - HUnlock((Handle) updateRgn); - DisposeRgn(updateRgn); - - // Update scrollbars - DrawControls(whichWindow); - - // Update the GrowBox - // Taken from FAQ 33-27 - saveRgn = NewRgn(); - GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect); - GetClip(saveRgn); - ClipRect(&growRect); - DrawGrowIcon(whichWindow); - SetClip(saveRgn); - DisposeRgn(saveRgn); - EndUpdate(whichWindow); - - // Restore original Port - SetPort(savePort); -} - -/* - * Handle the activate/deactivate event - * (apply to a window) - */ - void -gui_mac_doActivateEvent(EventRecord *event) -{ - WindowPtr whichWindow; - - whichWindow = (WindowPtr) event->message; - // Dim scrollbars - if (whichWindow == gui.VimWindow) - { - ControlRef rootControl; - GetRootControl(gui.VimWindow, &rootControl); - if ((event->modifiers) & activeFlag) - ActivateControl(rootControl); - else - DeactivateControl(rootControl); - } - - // Activate - gui_focus_change((event->modifiers) & activeFlag); -} - - -/* - * Handle the suspend/resume event - * (apply to the application) - */ - void -gui_mac_doSuspendEvent(EventRecord *event) -{ - // The frontmost application just changed - - // NOTE: the suspend may happen before the deactivate - // seen on MacOS X - - // May not need to change focus as the window will - // get an activate/deactivate event - if (event->message & 1) - // Resume - gui_focus_change(TRUE); - else - // Suspend - gui_focus_change(FALSE); -} - -/* - * Handle the key - */ -#ifdef USE_CARBONKEYHANDLER - static pascal OSStatus -gui_mac_handle_window_activate( - EventHandlerCallRef nextHandler, - EventRef theEvent, - void *data) -{ - UInt32 eventClass = GetEventClass(theEvent); - UInt32 eventKind = GetEventKind(theEvent); - - if (eventClass == kEventClassWindow) - { - switch (eventKind) - { - case kEventWindowActivated: - im_on_window_switch(TRUE); - return noErr; - - case kEventWindowDeactivated: - im_on_window_switch(FALSE); - return noErr; - } - } - - return eventNotHandledErr; -} - - static pascal OSStatus -gui_mac_handle_text_input( - EventHandlerCallRef nextHandler, - EventRef theEvent, - void *data) -{ - UInt32 eventClass = GetEventClass(theEvent); - UInt32 eventKind = GetEventKind(theEvent); - - if (eventClass != kEventClassTextInput) - return eventNotHandledErr; - - if ((kEventTextInputUpdateActiveInputArea != eventKind) && - (kEventTextInputUnicodeForKeyEvent != eventKind) && - (kEventTextInputOffsetToPos != eventKind) && - (kEventTextInputPosToOffset != eventKind) && - (kEventTextInputGetSelectedText != eventKind)) - return eventNotHandledErr; - - switch (eventKind) - { - case kEventTextInputUpdateActiveInputArea: - return gui_mac_update_input_area(nextHandler, theEvent); - case kEventTextInputUnicodeForKeyEvent: - return gui_mac_unicode_key_event(nextHandler, theEvent); - - case kEventTextInputOffsetToPos: - case kEventTextInputPosToOffset: - case kEventTextInputGetSelectedText: - break; - } - - return eventNotHandledErr; -} - - static pascal -OSStatus gui_mac_update_input_area( - EventHandlerCallRef nextHandler, - EventRef theEvent) -{ - return eventNotHandledErr; -} - -static int dialog_busy = FALSE; // TRUE when gui_mch_dialog() wants the - // keys - -# define INLINE_KEY_BUFFER_SIZE 80 - static pascal OSStatus -gui_mac_unicode_key_event( - EventHandlerCallRef nextHandler, - EventRef theEvent) -{ - // Multibyte-friendly key event handler - OSStatus err = -1; - UInt32 actualSize; - UniChar *text; - char_u result[INLINE_KEY_BUFFER_SIZE]; - short len = 0; - UInt32 key_sym; - char charcode; - int key_char; - UInt32 modifiers, vimModifiers; - size_t encLen; - char_u *to = NULL; - Boolean isSpecial = FALSE; - int i; - EventRef keyEvent; - - // Mask the mouse (as per user setting) - if (p_mh) - ObscureCursor(); - - // Don't use the keys when the dialog wants them. - if (dialog_busy) - return eventNotHandledErr; - - if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText, - typeUnicodeText, NULL, 0, &actualSize, NULL)) - return eventNotHandledErr; - - text = alloc(actualSize); - if (!text) - return eventNotHandledErr; - - err = GetEventParameter(theEvent, kEventParamTextInputSendText, - typeUnicodeText, NULL, actualSize, NULL, text); - require_noerr(err, done); - - err = GetEventParameter(theEvent, kEventParamTextInputSendKeyboardEvent, - typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent); - require_noerr(err, done); - - err = GetEventParameter(keyEvent, kEventParamKeyModifiers, - typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - require_noerr(err, done); - - err = GetEventParameter(keyEvent, kEventParamKeyCode, - typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym); - require_noerr(err, done); - - err = GetEventParameter(keyEvent, kEventParamKeyMacCharCodes, - typeChar, NULL, sizeof(char), NULL, &charcode); - require_noerr(err, done); - -#ifndef USE_CMD_KEY - if (modifiers & cmdKey) - goto done; // Let system handle Cmd+... -#endif - - key_char = charcode; - vimModifiers = EventModifiers2VimModifiers(modifiers); - - // Find the special key (eg., for cursor keys) - if (actualSize <= sizeof(UniChar) && - ((text[0] < 0x20) || (text[0] == 0x7f))) - { - for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i) - if (special_keys[i].key_sym == key_sym) - { - key_char = TO_SPECIAL(special_keys[i].vim_code0, - special_keys[i].vim_code1); - key_char = simplify_key(key_char, - (int *)&vimModifiers); - isSpecial = TRUE; - break; - } - } - - // Intercept CMD-. and CTRL-c - if (((modifiers & controlKey) && key_char == 'c') || - ((modifiers & cmdKey) && key_char == '.')) - got_int = TRUE; - - if (!isSpecial) - { - // remove SHIFT for keys that are already shifted, e.g., - // '(' and '*' - if (key_char < 0x100 && !isalpha(key_char) && isprint(key_char)) - vimModifiers &= ~MOD_MASK_SHIFT; - - // remove CTRL from keys that already have it - if (key_char < 0x20) - vimModifiers &= ~MOD_MASK_CTRL; - - // don't process unicode characters here - if (!IS_SPECIAL(key_char)) - { - // Following code to simplify and consolidate vimModifiers - // taken liberally from gui_w48.c - key_char = simplify_key(key_char, (int *)&vimModifiers); - - // Unify modifiers somewhat. No longer use ALT to set the 8th bit. - key_char = extract_modifiers(key_char, (int *)&vimModifiers, - FALSE, NULL); - if (key_char == CSI) - key_char = K_CSI; - - if (IS_SPECIAL(key_char)) - isSpecial = TRUE; - } - } - - if (vimModifiers) - { - result[len++] = CSI; - result[len++] = KS_MODIFIER; - result[len++] = vimModifiers; - } - - if (isSpecial && IS_SPECIAL(key_char)) - { - result[len++] = CSI; - result[len++] = K_SECOND(key_char); - result[len++] = K_THIRD(key_char); - } - else - { - encLen = actualSize; - to = mac_utf16_to_enc(text, actualSize, &encLen); - if (to) - { - // This is basically add_to_input_buf_csi() - for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i) - { - result[len++] = to[i]; - if (to[i] == CSI) - { - result[len++] = KS_EXTRA; - result[len++] = (int)KE_CSI; - } - } - vim_free(to); - } - } - - add_to_input_buf(result, len); - err = noErr; - -done: - vim_free(text); - if (err == noErr) - { - // Fake event to wake up WNE (required to get - // key repeat working - PostEvent(keyUp, 0); - return noErr; - } - - return eventNotHandledErr; -} -#else - void -gui_mac_doKeyEvent(EventRecord *theEvent) -{ - // TODO: add support for COMMAND KEY - long menu; - unsigned char string[20]; - short num, i; - short len = 0; - KeySym key_sym; - int key_char; - int modifiers; - int simplify = FALSE; - - // Mask the mouse (as per user setting) - if (p_mh) - ObscureCursor(); - - // Get the key code and its ASCII representation - key_sym = ((theEvent->message & keyCodeMask) >> 8); - key_char = theEvent->message & charCodeMask; - num = 1; - - // Intercept CTRL-C - if (theEvent->modifiers & controlKey) - { - if (key_char == Ctrl_C && ctrl_c_interrupts) - got_int = TRUE; - else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0 - && (key_char == '2' || key_char == '6')) - { - // CTRL-^ and CTRL-@ don't work in the normal way. - if (key_char == '2') - key_char = Ctrl_AT; - else - key_char = Ctrl_HAT; - theEvent->modifiers = 0; - } - } - - // Intercept CMD-. - if (theEvent->modifiers & cmdKey) - if (key_char == '.') - got_int = TRUE; - - // Handle command key as per menu - // TODO: should override be allowed? Require YAO or could use 'winaltkey' - if (theEvent->modifiers & cmdKey) - // Only accept CMD alone or with CAPLOCKS and the mouse button. - // Why the mouse button? - if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0) - { - menu = MenuKey(key_char); - if (HiWord(menu)) - { - gui_mac_handle_menu(menu); - return; - } - } - - // Convert the modifiers - modifiers = EventModifiers2VimModifiers(theEvent->modifiers); - - - // Handle special keys. -#if 0 - // Why has this been removed? - if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey))) -#endif - { - // Find the special key (for non-printable keyt_char) - if ((key_char < 0x20) || (key_char == 0x7f)) - for (i = 0; special_keys[i].key_sym != (KeySym)0; i++) - if (special_keys[i].key_sym == key_sym) - { -# if 0 - // We currently don't have not so special key - if (special_keys[i].vim_code1 == NUL) - key_char = special_keys[i].vim_code0; - else -# endif - key_char = TO_SPECIAL(special_keys[i].vim_code0, - special_keys[i].vim_code1); - simplify = TRUE; - break; - } - } - - // For some keys the modifier is included in the char itself. - if (simplify || key_char == TAB || key_char == ' ') - key_char = simplify_key(key_char, &modifiers); - - // Add the modifier to the input bu if needed - // Do not want SHIFT-A or CTRL-A with modifier - if (!IS_SPECIAL(key_char) - && key_sym != vk_Space - && key_sym != vk_Tab - && key_sym != vk_Return - && key_sym != vk_Enter - && key_sym != vk_Esc) - { -#if 1 - // Clear modifiers when only one modifier is set - if ((modifiers == MOD_MASK_SHIFT) - || (modifiers == MOD_MASK_CTRL) - || (modifiers == MOD_MASK_ALT)) - modifiers = 0; -#else - if (modifiers & MOD_MASK_CTRL) - modifiers = modifiers & ~MOD_MASK_CTRL; - if (modifiers & MOD_MASK_ALT) - modifiers = modifiers & ~MOD_MASK_ALT; - if (modifiers & MOD_MASK_SHIFT) - modifiers = modifiers & ~MOD_MASK_SHIFT; -#endif - } - if (modifiers) - { - string[len++] = CSI; - string[len++] = KS_MODIFIER; - string[len++] = modifiers; - } - - if (IS_SPECIAL(key_char)) - { - string[len++] = CSI; - string[len++] = K_SECOND(key_char); - string[len++] = K_THIRD(key_char); - } - else - { - // Convert characters when needed (e.g., from MacRoman to latin1). - // This doesn't work for the NUL byte. - if (input_conv.vc_type != CONV_NONE && key_char > 0) - { - char_u from[2], *to; - int l; - - from[0] = key_char; - from[1] = NUL; - l = 1; - to = string_convert(&input_conv, from, &l); - if (to != NULL) - { - for (i = 0; i < l && len < 19; i++) - { - if (to[i] == CSI) - { - string[len++] = KS_EXTRA; - string[len++] = KE_CSI; - } - else - string[len++] = to[i]; - } - vim_free(to); - } - else - string[len++] = key_char; - } - else - string[len++] = key_char; - } - - if (len == 1 && string[0] == CSI) - { - // Turn CSI into K_CSI. - string[ len++ ] = KS_EXTRA; - string[ len++ ] = KE_CSI; - } - - add_to_input_buf(string, len); -} -#endif - -/* - * Handle MouseClick - */ - void -gui_mac_doMouseDownEvent(EventRecord *theEvent) -{ - short thePart; - WindowPtr whichWindow; - - thePart = FindWindow(theEvent->where, &whichWindow); - -#ifdef FEAT_GUI_TABLINE - // prevent that the vim window size changes if it's activated by a - // click into the tab pane - if (whichWindow == drawer) - return; -#endif - - switch (thePart) - { - case (inDesk): - // TODO: what to do? - break; - - case (inMenuBar): - gui_mac_handle_menu(MenuSelect(theEvent->where)); - break; - - case (inContent): - gui_mac_doInContentClick(theEvent, whichWindow); - break; - - case (inDrag): - gui_mac_doInDragClick(theEvent->where, whichWindow); - break; - - case (inGrow): - gui_mac_doInGrowClick(theEvent->where, whichWindow); - break; - - case (inGoAway): - if (TrackGoAway(whichWindow, theEvent->where)) - gui_shell_closed(); - break; - - case (inZoomIn): - case (inZoomOut): - gui_mac_doInZoomClick(theEvent, whichWindow); - break; - } -} - -/* - * Handle MouseMoved - * [this event is a moving in and out of a region] - */ - void -gui_mac_doMouseMovedEvent(EventRecord *event) -{ - Point thePoint; - int_u vimModifiers; - - thePoint = event->where; - GlobalToLocal(&thePoint); - vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers); - - if (!Button()) - gui_mouse_moved(thePoint.h, thePoint.v); - else - if (!clickIsPopup) - gui_send_mouse_event(MOUSE_DRAG, thePoint.h, - thePoint.v, FALSE, vimModifiers); - - // Reset the region from which we move in and out - SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)), - FILL_Y(Y_2_ROW(thePoint.v)), - FILL_X(X_2_COL(thePoint.h)+1), - FILL_Y(Y_2_ROW(thePoint.v)+1)); - - if (dragRectEnbl) - dragRectControl = kCreateRect; - -} - -/* - * Handle the mouse release - */ - void -gui_mac_doMouseUpEvent(EventRecord *theEvent) -{ - Point thePoint; - int_u vimModifiers; - - // TODO: Properly convert the Contextual menu mouse-up - // Potential source of the double menu - lastMouseTick = theEvent->when; - dragRectEnbl = FALSE; - dragRectControl = kCreateEmpty; - thePoint = theEvent->where; - GlobalToLocal(&thePoint); - - vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers); - if (clickIsPopup) - { - vimModifiers &= ~MOUSE_CTRL; - clickIsPopup = FALSE; - } - gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers); -} - - static pascal OSStatus -gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent, - void *data) -{ - Point point; - Rect bounds; - UInt32 mod; - SInt32 delta; - int_u vim_mod; - EventMouseWheelAxis axis; - - if (noErr == GetEventParameter(theEvent, kEventParamMouseWheelAxis, - typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis) - && axis != kEventMouseWheelAxisY) - goto bail; // Vim only does up-down scrolling - - if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta, - typeSInt32, NULL, sizeof(SInt32), NULL, &delta)) - goto bail; - if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation, - typeQDPoint, NULL, sizeof(Point), NULL, &point)) - goto bail; - if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers, - typeUInt32, NULL, sizeof(UInt32), NULL, &mod)) - goto bail; - - vim_mod = 0; - if (mod & shiftKey) - vim_mod |= MOUSE_SHIFT; - if (mod & controlKey) - vim_mod |= MOUSE_CTRL; - if (mod & optionKey) - vim_mod |= MOUSE_ALT; - - if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds)) - { - point.h -= bounds.left; - point.v -= bounds.top; - } - - gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5, - point.h, point.v, FALSE, vim_mod); - - // post a bogus event to wake up WaitNextEvent - PostEvent(keyUp, 0); - - return noErr; - -bail: - /* - * when we fail give any additional callback handler a chance to perform - * its actions - */ - return CallNextEventHandler(nextHandler, theEvent); -} - - void -gui_mch_mousehide(int hide) -{ - // TODO -} - -#if 0 - -/* - * This would be the normal way of invoking the contextual menu - * but the Vim API doesn't seem to a support a request to get - * the menu that we should display - */ - void -gui_mac_handle_contextual_menu(EventRecord *event) -{ -/* - * Clone PopUp to use menu - * Create a object descriptor for the current selection - * Call the procedure - */ - -// Call to Handle Popup - OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem); - - if (status != noErr) - return; - - if (CntxType == kCMMenuItemSelected) - { - // Handle the menu CntxMenuID, CntxMenuItem - // The submenu can be handle directly by gui_mac_handle_menu - // But what about the current menu, is the many changed by ContextualMenuSelect - gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem); - } - else if (CntxMenuID == kCMShowHelpSelected) - { - // Should come up with the help - } - -} -#endif - -/* - * Handle menubar selection - */ - void -gui_mac_handle_menu(long menuChoice) -{ - short menu = HiWord(menuChoice); - short item = LoWord(menuChoice); - vimmenu_T *theVimMenu = root_menu; - - if (menu == 256) // TODO: use constant or gui.xyz - { - if (item == 1) - gui_mch_beep(); // TODO: Popup dialog or do :intro - } - else if (item != 0) - { - theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu); - - if (theVimMenu) - gui_menu_cb(theVimMenu); - } - HiliteMenu(0); -} - -/* - * Dispatch the event to proper handler - */ - - void -gui_mac_handle_event(EventRecord *event) -{ - OSErr error; - - // Handle contextual menu right now (if needed) - if (IsShowContextualMenuClick(event)) - { -# if 0 - gui_mac_handle_contextual_menu(event); -# else - gui_mac_doMouseDownEvent(event); -# endif - return; - } - - // Handle normal event - switch (event->what) - { -#ifndef USE_CARBONKEYHANDLER - case (keyDown): - case (autoKey): - gui_mac_doKeyEvent(event); - break; -#endif - case (keyUp): - // We don't care about when the key is released - break; - - case (mouseDown): - gui_mac_doMouseDownEvent(event); - break; - - case (mouseUp): - gui_mac_doMouseUpEvent(event); - break; - - case (updateEvt): - gui_mac_doUpdateEvent(event); - break; - - case (diskEvt): - // We don't need special handling for disk insertion - break; - - case (activateEvt): - gui_mac_doActivateEvent(event); - break; - - case (osEvt): - switch ((event->message >> 24) & 0xFF) - { - case (0xFA): // mouseMovedMessage - gui_mac_doMouseMovedEvent(event); - break; - case (0x01): // suspendResumeMessage - gui_mac_doSuspendEvent(event); - break; - } - break; - -#ifdef USE_AEVENT - case (kHighLevelEvent): - // Someone's talking to us, through AppleEvents - error = AEProcessAppleEvent(event); // TODO: Error Handling - break; -#endif - } -} - -/* - * ------------------------------------------------------------ - * Unknown Stuff - * ------------------------------------------------------------ - */ - - - GuiFont -gui_mac_find_font(char_u *font_name) -{ - char_u c; - char_u *p; - char_u pFontName[256]; - Str255 systemFontname; - short font_id; - short size=9; - GuiFont font; -#if 0 - char_u *fontNamePtr; -#endif - - for (p = font_name; ((*p != 0) && (*p != ':')); p++) - ; - - c = *p; - *p = 0; - -#if 1 - STRCPY(&pFontName[1], font_name); - pFontName[0] = STRLEN(font_name); - *p = c; - - // Get the font name, minus the style suffix (:h, etc) - char_u fontName[256]; - char_u *styleStart = vim_strchr(font_name, ':'); - size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName); - vim_strncpy(fontName, font_name, fontNameLen); - - ATSUFontID fontRef; - FMFontStyle fontStyle; - font_id = 0; - - if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName, - kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode, - &fontRef) == noErr) - { - if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr) - font_id = 0; - } - - if (font_id == 0) - { - /* - * Try again, this time replacing underscores in the font name - * with spaces (:set guifont allows the two to be used - * interchangeably; the Font Manager doesn't). - */ - int i, changed = FALSE; - - for (i = pFontName[0]; i > 0; --i) - { - if (pFontName[i] == '_') - { - pFontName[i] = ' '; - changed = TRUE; - } - } - if (changed) - if (ATSUFindFontFromName(&pFontName[1], pFontName[0], - kFontFullName, kFontNoPlatformCode, kFontNoScriptCode, - kFontNoLanguageCode, &fontRef) == noErr) - { - if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr) - font_id = 0; - } - } - -#else - // name = C2Pascal_save(menu->dname); - fontNamePtr = C2Pascal_save_and_remove_backslash(font_name); - - GetFNum(fontNamePtr, &font_id); -#endif - - - if (font_id == 0) - { - // Oups, the system font was it the one the user want - - if (FMGetFontFamilyName(systemFont, systemFontname) != noErr) - return NOFONT; - if (!EqualString(pFontName, systemFontname, false, false)) - return NOFONT; - } - if (*p == ':') - { - p++; - // Set the values found after ':' - while (*p) - { - switch (*p++) - { - case 'h': - size = points_to_pixels(p, &p, TRUE); - break; - /* - * TODO: Maybe accept width and styles - */ - } - while (*p == ':') - p++; - } - } - - if (size < 1) - size = 1; // Avoid having a size of 0 with system font - - font = (size << 16) + ((long) font_id & 0xFFFF); - - return font; -} - -/* - * ------------------------------------------------------------ - * GUI_MCH functionality - * ------------------------------------------------------------ - */ - -/* - * Parse the GUI related command-line arguments. Any arguments used are - * deleted from argv, and *argc is decremented accordingly. This is called - * when vim is started, whether or not the GUI has been started. - */ - void -gui_mch_prepare(int *argc, char **argv) -{ - // TODO: Move most of this stuff toward gui_mch_init -#ifdef USE_EXE_NAME - FSSpec applDir; -# ifndef USE_FIND_BUNDLE_PATH - short applVRefNum; - long applDirID; - Str255 volName; -# else - ProcessSerialNumber psn; - FSRef applFSRef; -# endif -#endif - -#if 0 - InitCursor(); - - RegisterAppearanceClient(); - -#ifdef USE_AEVENT - (void) InstallAEHandlers(); -#endif - - pomme = NewMenu(256, "\p\024"); // 0x14= = Apple Menu - - AppendMenu(pomme, "\pAbout VIM"); - - InsertMenu(pomme, 0); - - DrawMenuBar(); - - -#ifndef USE_OFFSETED_WINDOW - SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11); -#else - SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11); -#endif - - - CreateNewWindow(kDocumentWindowClass, - kWindowResizableAttribute | kWindowCollapseBoxAttribute, - &windRect, &gui.VimWindow); - SetPortWindowPort(gui.VimWindow); - - gui.char_width = 7; - gui.char_height = 11; - gui.char_ascent = 6; - gui.num_rows = 24; - gui.num_cols = 80; - gui.in_focus = TRUE; // For the moment -> syn. of front application - - gScrollAction = NewControlActionUPP(gui_mac_scroll_action); - gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb); - - dragRectEnbl = FALSE; - dragRgn = NULL; - dragRectControl = kCreateEmpty; - cursorRgn = NewRgn(); -#endif -#ifdef USE_EXE_NAME -# ifndef USE_FIND_BUNDLE_PATH - HGetVol(volName, &applVRefNum, &applDirID); - // TN2015: mention a possible bad VRefNum - FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir); -# else - // OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr) - // of TN2015 - (void)GetCurrentProcess(&psn); - // if (err != noErr) return err; - - (void)GetProcessBundleLocation(&psn, &applFSRef); - // if (err != noErr) return err; - - (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL); - - // This technique returns NIL when we disallow_gui -# endif - exe_name = FullPathFromFSSpec_save(applDir); -#endif -} - -#ifndef ALWAYS_USE_GUI -/* - * Check if the GUI can be started. Called before gvimrc is sourced. - * Return OK or FAIL. - */ - int -gui_mch_init_check(void) -{ - // TODO: For MacOS X find a way to return FAIL, if the user logged in - // using the >console - if (disallow_gui) // see main.c for reason to disallow - return FAIL; - return OK; -} -#endif - - static OSErr -receiveHandler(WindowRef theWindow, void *handlerRefCon, DragRef theDrag) -{ - int x, y; - int_u modifiers; - char_u **fnames = NULL; - int count; - int i, j; - - // Get drop position, modifiers and count of items - { - Point point; - SInt16 mouseUpModifiers; - UInt16 countItem; - - GetDragMouse(theDrag, &point, NULL); - GlobalToLocal(&point); - x = point.h; - y = point.v; - GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers); - modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers); - CountDragItems(theDrag, &countItem); - count = countItem; - } - - fnames = ALLOC_MULT(char_u *, count); - if (fnames == NULL) - return dragNotAcceptedErr; - - // Get file names dropped - for (i = j = 0; i < count; ++i) - { - DragItemRef item; - OSErr err; - Size size; - FlavorType type = flavorTypeHFS; - HFSFlavor hfsFlavor; - - fnames[i] = NULL; - GetDragItemReferenceNumber(theDrag, i + 1, &item); - err = GetFlavorDataSize(theDrag, item, type, &size); - if (err != noErr || size > sizeof(hfsFlavor)) - continue; - err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0); - if (err != noErr) - continue; - fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec); - } - count = j; - - gui_handle_drop(x, y, modifiers, fnames, count); - - // Fake mouse event to wake from stall - PostEvent(mouseUp, 0); - - return noErr; -} - -/* - * Initialise the GUI. Create all the windows, set up all the call-backs - * etc. - */ - int -gui_mch_init(void) -{ - // TODO: Move most of this stuff toward gui_mch_init - Rect windRect; - MenuHandle pomme; - EventHandlerRef mouseWheelHandlerRef; - EventTypeSpec eventTypeSpec; - ControlRef rootControl; - - if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr) - gMacSystemVersion = 0x1000; // TODO: Default to minimum sensible value - -#if 1 - InitCursor(); - - RegisterAppearanceClient(); - -#ifdef USE_AEVENT - (void) InstallAEHandlers(); -#endif - - pomme = NewMenu(256, "\p\024"); // 0x14= = Apple Menu - - AppendMenu(pomme, "\pAbout VIM"); - - InsertMenu(pomme, 0); - - DrawMenuBar(); - - -#ifndef USE_OFFSETED_WINDOW - SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11); -#else - SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11); -#endif - - gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true, - zoomDocProc, - (WindowPtr)-1L, true, 0); - CreateRootControl(gui.VimWindow, &rootControl); - InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler, - gui.VimWindow, NULL); - SetPortWindowPort(gui.VimWindow); - - gui.char_width = 7; - gui.char_height = 11; - gui.char_ascent = 6; - gui.num_rows = 24; - gui.num_cols = 80; - gui.in_focus = TRUE; // For the moment -> syn. of front application - - gScrollAction = NewControlActionUPP(gui_mac_scroll_action); - gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb); - - // Install Carbon event callbacks. - (void)InstallFontPanelHandler(); - - dragRectEnbl = FALSE; - dragRgn = NULL; - dragRectControl = kCreateEmpty; - cursorRgn = NewRgn(); -#endif - // Display any pending error messages - display_errors(); - - // Get background/foreground colors from system - // TODO: do the appropriate call to get real defaults - gui.norm_pixel = 0x00000000; - gui.back_pixel = 0x00FFFFFF; - - // Get the colors from the "Normal" group (set in syntax.c or in a vimrc - // file). - set_normal_colors(); - - /* - * Check that none of the colors are the same as the background color. - * Then store the current values as the defaults. - */ - gui_check_colors(); - gui.def_norm_pixel = gui.norm_pixel; - gui.def_back_pixel = gui.back_pixel; - - // Get the colors for the highlight groups (gui_check_colors() might have - // changed them) - highlight_gui_started(); - - /* - * Setting the gui constants - */ -#ifdef FEAT_MENU - gui.menu_height = 0; -#endif - gui.scrollbar_height = gui.scrollbar_width = 15; // cheat 1 overlap - gui.border_offset = gui.border_width = 2; - - // If Quartz-style text anti aliasing is available (see - // gui_mch_draw_string() below), enable it for all font sizes. - vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1"); - - eventTypeSpec.eventClass = kEventClassMouse; - eventTypeSpec.eventKind = kEventMouseWheelMoved; - mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel); - if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1, - &eventTypeSpec, NULL, &mouseWheelHandlerRef)) - { - mouseWheelHandlerRef = NULL; - DisposeEventHandlerUPP(mouseWheelHandlerUPP); - mouseWheelHandlerUPP = NULL; - } - -#ifdef USE_CARBONKEYHANDLER - InterfaceTypeList supportedServices = { kUnicodeDocument }; - NewTSMDocument(1, supportedServices, &gTSMDocument, 0); - - // We don't support inline input yet, use input window by default - UseInputWindow(gTSMDocument, TRUE); - - // Should we activate the document by default? - // ActivateTSMDocument(gTSMDocument); - - EventTypeSpec textEventTypes[] = { - { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, - { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, - { kEventClassTextInput, kEventTextInputPosToOffset }, - { kEventClassTextInput, kEventTextInputOffsetToPos }, - }; - - keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_handle_text_input); - if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, - NR_ELEMS(textEventTypes), - textEventTypes, NULL, NULL)) - { - DisposeEventHandlerUPP(keyEventHandlerUPP); - keyEventHandlerUPP = NULL; - } - - EventTypeSpec windowEventTypes[] = { - { kEventClassWindow, kEventWindowActivated }, - { kEventClassWindow, kEventWindowDeactivated }, - }; - - // Install window event handler to support TSMDocument activate and - // deactivate - winEventHandlerUPP = NewEventHandlerUPP(gui_mac_handle_window_activate); - if (noErr != InstallWindowEventHandler(gui.VimWindow, - winEventHandlerUPP, - NR_ELEMS(windowEventTypes), - windowEventTypes, NULL, NULL)) - { - DisposeEventHandlerUPP(winEventHandlerUPP); - winEventHandlerUPP = NULL; - } -#endif - -#ifdef FEAT_GUI_TABLINE - /* - * Create the tabline - */ - initialise_tabline(); -#endif - - // TODO: Load bitmap if using TOOLBAR - return OK; -} - -/* - * Called when the foreground or background color has been changed. - */ - void -gui_mch_new_colors(void) -{ - // TODO: - // This proc is called when Normal is set to a value - // so what must be done? I don't know -} - -/* - * Open the GUI window which was created by a call to gui_mch_init(). - */ - int -gui_mch_open(void) -{ - ShowWindow(gui.VimWindow); - - if (gui_win_x != -1 && gui_win_y != -1) - gui_mch_set_winpos(gui_win_x, gui_win_y); - - /* - * Make the GUI the foreground process (in case it was launched - * from the Terminal or via :gui). - */ - { - ProcessSerialNumber psn; - if (GetCurrentProcess(&psn) == noErr) - SetFrontProcess(&psn); - } - - return OK; -} - -#ifdef USE_ATSUI_DRAWING - static void -gui_mac_dispose_atsui_style(void) -{ - if (p_macatsui && gFontStyle) - ATSUDisposeStyle(gFontStyle); - if (p_macatsui && gWideFontStyle) - ATSUDisposeStyle(gWideFontStyle); -} -#endif - - void -gui_mch_exit(int rc) -{ - // TODO: find out all what is missing here? - DisposeRgn(cursorRgn); - -#ifdef USE_CARBONKEYHANDLER - if (keyEventHandlerUPP) - DisposeEventHandlerUPP(keyEventHandlerUPP); -#endif - - if (mouseWheelHandlerUPP != NULL) - DisposeEventHandlerUPP(mouseWheelHandlerUPP); - -#ifdef USE_ATSUI_DRAWING - gui_mac_dispose_atsui_style(); -#endif - -#ifdef USE_CARBONKEYHANDLER - FixTSMDocument(gTSMDocument); - DeactivateTSMDocument(gTSMDocument); - DeleteTSMDocument(gTSMDocument); -#endif - - // Exit to shell? - exit(rc); -} - -/* - * Get the position of the top left corner of the window. - */ - int -gui_mch_get_winpos(int *x, int *y) -{ - // TODO - Rect bounds; - OSStatus status; - - // Carbon >= 1.0.2, MacOS >= 8.5 - status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds); - - if (status != noErr) - return FAIL; - *x = bounds.left; - *y = bounds.top; - return OK; -} - -/* - * Set the position of the top left corner of the window to the given - * coordinates. - */ - void -gui_mch_set_winpos(int x, int y) -{ - // TODO: Should make sure the window is move within range - // e.g.: y > ~16 [Menu bar], x > 0, x < screen width - MoveWindowStructure(gui.VimWindow, x, y); -} - - void -gui_mch_set_shellsize( - int width, - int height, - int min_width, - int min_height, - int base_width, - int base_height, - int direction) -{ - CGrafPtr VimPort; - Rect VimBound; - - if (gui.which_scrollbars[SBAR_LEFT]) - { - VimPort = GetWindowPort(gui.VimWindow); - GetPortBounds(VimPort, &VimBound); - VimBound.left = -gui.scrollbar_width; // + 1; - SetPortBounds(VimPort, &VimBound); - // GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ?? - } - else - { - VimPort = GetWindowPort(gui.VimWindow); - GetPortBounds(VimPort, &VimBound); - VimBound.left = 0; - SetPortBounds(VimPort, &VimBound); - } - - SizeWindow(gui.VimWindow, width, height, TRUE); - - gui_resize_shell(width, height); -} - -/* - * Get the screen dimensions. - * Allow 10 pixels for horizontal borders, 40 for vertical borders. - * Is there no way to find out how wide the borders really are? - * TODO: Add live update of those value on suspend/resume. - */ - void -gui_mch_get_screen_dimensions(int *screen_w, int *screen_h) -{ - GDHandle dominantDevice = GetMainDevice(); - Rect screenRect = (**dominantDevice).gdRect; - - *screen_w = screenRect.right - 10; - *screen_h = screenRect.bottom - 40; -} - - -/* - * Open the Font Panel and wait for the user to select a font and - * close the panel. Then fill the buffer pointed to by font_name with - * the name and size of the selected font and return the font's handle, - * or NOFONT in case of an error. - */ - static GuiFont -gui_mac_select_font(char_u *font_name) -{ - GuiFont selected_font = NOFONT; - OSStatus status; - FontSelectionQDStyle curr_font; - - // Initialize the Font Panel with the current font. - curr_font.instance.fontFamily = gui.norm_font & 0xFFFF; - curr_font.size = (gui.norm_font >> 16); - // TODO: set fontStyle once styles are supported in gui_mac_find_font() - curr_font.instance.fontStyle = 0; - curr_font.hasColor = false; - curr_font.version = 0; // version number of the style structure - status = SetFontInfoForSelection(kFontSelectionQDType, - /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL); - - gFontPanelInfo.family = curr_font.instance.fontFamily; - gFontPanelInfo.style = curr_font.instance.fontStyle; - gFontPanelInfo.size = curr_font.size; - - // Pop up the Font Panel. - status = FPShowHideFontPanel(); - if (status == noErr) - { - /* - * The Font Panel is modeless. We really need it to be modal, - * so we spin in an event loop until the panel is closed. - */ - gFontPanelInfo.isPanelVisible = true; - while (gFontPanelInfo.isPanelVisible) - { - EventRecord e; - WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL); - } - - GetFontPanelSelection(font_name); - selected_font = gui_mac_find_font(font_name); - } - return selected_font; -} - -#ifdef USE_ATSUI_DRAWING - static void -gui_mac_create_atsui_style(void) -{ - if (p_macatsui && gFontStyle == NULL) - { - if (ATSUCreateStyle(&gFontStyle) != noErr) - gFontStyle = NULL; - } - if (p_macatsui && gWideFontStyle == NULL) - { - if (ATSUCreateStyle(&gWideFontStyle) != noErr) - gWideFontStyle = NULL; - } - - p_macatsui_last = p_macatsui; -} -#endif - -/* - * Initialise vim to use the font with the given name. Return FAIL if the font - * could not be loaded, OK otherwise. - */ - int -gui_mch_init_font(char_u *font_name, int fontset) -{ - // TODO: Add support for bold italic underline proportional etc... - Str255 suggestedFont = "\pMonaco"; - int suggestedSize = 10; - FontInfo font_info; - short font_id; - GuiFont font; - char_u used_font_name[512]; - -#ifdef USE_ATSUI_DRAWING - gui_mac_create_atsui_style(); -#endif - - if (font_name == NULL) - { - // First try to get the suggested font - GetFNum(suggestedFont, &font_id); - - if (font_id == 0) - { - // Then pickup the standard application font - font_id = GetAppFont(); - STRCPY(used_font_name, "default"); - } - else - STRCPY(used_font_name, "Monaco"); - font = (suggestedSize << 16) + ((long) font_id & 0xFFFF); - } - else if (STRCMP(font_name, "*") == 0) - { - char_u *new_p_guifont; - - font = gui_mac_select_font(used_font_name); - if (font == NOFONT) - return FAIL; - - // Set guifont to the name of the selected font. - new_p_guifont = alloc(STRLEN(used_font_name) + 1); - if (new_p_guifont != NULL) - { - STRCPY(new_p_guifont, used_font_name); - vim_free(p_guifont); - p_guifont = new_p_guifont; - // Replace spaces in the font name with underscores. - for ( ; *new_p_guifont; ++new_p_guifont) - { - if (*new_p_guifont == ' ') - *new_p_guifont = '_'; - } - } - } - else - { - font = gui_mac_find_font(font_name); - vim_strncpy(used_font_name, font_name, sizeof(used_font_name) - 1); - - if (font == NOFONT) - return FAIL; - } - - gui.norm_font = font; - - hl_set_font_name(used_font_name); - - TextSize(font >> 16); - TextFont(font & 0xFFFF); - - GetFontInfo(&font_info); - - gui.char_ascent = font_info.ascent; - gui.char_width = CharWidth('_'); - gui.char_height = font_info.ascent + font_info.descent + p_linespace; - -#ifdef USE_ATSUI_DRAWING - if (p_macatsui && gFontStyle) - gui_mac_set_font_attributes(font); -#endif - - return OK; -} - -/* - * Adjust gui.char_height (after 'linespace' was changed). - */ - int -gui_mch_adjust_charheight(void) -{ - FontInfo font_info; - - GetFontInfo(&font_info); - gui.char_height = font_info.ascent + font_info.descent + p_linespace; - gui.char_ascent = font_info.ascent + p_linespace / 2; - return OK; -} - -/* - * Get a font structure for highlighting. - */ - GuiFont -gui_mch_get_font(char_u *name, int giveErrorIfMissing) -{ - GuiFont font; - - font = gui_mac_find_font(name); - - if (font == NOFONT) - { - if (giveErrorIfMissing) - semsg(_(e_font), name); - return NOFONT; - } - /* - * TODO : Accept only monospace - */ - - return font; -} - -#if defined(FEAT_EVAL) || defined(PROTO) -/* - * Return the name of font "font" in allocated memory. - * Don't know how to get the actual name, thus use the provided name. - */ - char_u * -gui_mch_get_fontname(GuiFont font, char_u *name) -{ - if (name == NULL) - return NULL; - return vim_strsave(name); -} -#endif - -#ifdef USE_ATSUI_DRAWING - static void -gui_mac_set_font_attributes(GuiFont font) -{ - ATSUFontID fontID; - Fixed fontSize; - Fixed fontWidth; - - fontID = font & 0xFFFF; - fontSize = Long2Fix(font >> 16); - fontWidth = Long2Fix(gui.char_width); - - ATSUAttributeTag attribTags[] = - { - kATSUFontTag, kATSUSizeTag, kATSUImposeWidthTag, - kATSUMaxATSUITagValue + 1 - }; - - ByteCount attribSizes[] = - { - sizeof(ATSUFontID), sizeof(Fixed), sizeof(fontWidth), - sizeof(font) - }; - - ATSUAttributeValuePtr attribValues[] = - { - &fontID, &fontSize, &fontWidth, &font - }; - - if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr) - { - if (ATSUSetAttributes(gFontStyle, - (sizeof attribTags) / sizeof(ATSUAttributeTag), - attribTags, attribSizes, attribValues) != noErr) - { -# ifndef NDEBUG - fprintf(stderr, "couldn't set font style\n"); -# endif - ATSUDisposeStyle(gFontStyle); - gFontStyle = NULL; - } - - if (has_mbyte) - { - // FIXME: we should use a more mbyte sensitive way to support - // wide font drawing - fontWidth = Long2Fix(gui.char_width * 2); - - if (ATSUSetAttributes(gWideFontStyle, - (sizeof attribTags) / sizeof(ATSUAttributeTag), - attribTags, attribSizes, attribValues) != noErr) - { - ATSUDisposeStyle(gWideFontStyle); - gWideFontStyle = NULL; - } - } - } -} -#endif - -/* - * Set the current text font. - */ - void -gui_mch_set_font(GuiFont font) -{ -#ifdef USE_ATSUI_DRAWING - GuiFont currFont; - ByteCount actualFontByteCount; - - if (p_macatsui && gFontStyle) - { - // Avoid setting same font again - if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue + 1, - sizeof(font), &currFont, &actualFontByteCount) == noErr - && actualFontByteCount == (sizeof font)) - { - if (currFont == font) - return; - } - - gui_mac_set_font_attributes(font); - } - - if (p_macatsui && !gIsFontFallbackSet) - { - // Setup automatic font substitution. The user's guifontwide - // is tried first, then the system tries other fonts. -#if 0 - ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag }; - ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) }; - ATSUCreateFontFallbacks(&gFontFallbacks); - ATSUSetObjFontFallbacks(gFontFallbacks, ); -#endif - if (gui.wide_font) - { - ATSUFontID fallbackFonts; - gIsFontFallbackSet = TRUE; - - if (FMGetFontFromFontFamilyInstance( - (gui.wide_font & 0xFFFF), - 0, - &fallbackFonts, - NULL) == noErr) - { - ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), - &fallbackFonts, - kATSUSequentialFallbacksPreferred); - } -// ATSUAttributeValuePtr fallbackValues[] = { }; - } - } -#endif - TextSize(font >> 16); - TextFont(font & 0xFFFF); -} - -/* - * If a font is not going to be used, free its structure. - */ - void -gui_mch_free_font(GuiFont font) -{ - /* - * Free font when "font" is not 0. - * Nothing to do in the current implementation, since - * nothing is allocated for each font used. - */ -} - -/* - * Return the Pixel value (color) for the given color name. This routine was - * pretty much taken from example code in the Silicon Graphics OSF/Motif - * Programmer's Guide. - * Return INVALCOLOR when failed. - */ - guicolor_T -gui_mch_get_color(char_u *name) -{ - // TODO: Add support for the new named color of MacOS 8 - RGBColor MacColor; - - if (STRICMP(name, "hilite") == 0) - { - LMGetHiliteRGB(&MacColor); - return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8)); - } - return gui_get_color_cmn(name); -} - - guicolor_T -gui_mch_get_rgb_color(int r, int g, int b) -{ - return gui_get_rgb_color_cmn(r, g, b); -} - -/* - * Set the current text foreground color. - */ - void -gui_mch_set_fg_color(guicolor_T color) -{ - RGBColor TheColor; - - TheColor.red = Red(color) * 0x0101; - TheColor.green = Green(color) * 0x0101; - TheColor.blue = Blue(color) * 0x0101; - - RGBForeColor(&TheColor); -} - -/* - * Set the current text background color. - */ - void -gui_mch_set_bg_color(guicolor_T color) -{ - RGBColor TheColor; - - TheColor.red = Red(color) * 0x0101; - TheColor.green = Green(color) * 0x0101; - TheColor.blue = Blue(color) * 0x0101; - - RGBBackColor(&TheColor); -} - -RGBColor specialColor; - -/* - * Set the current text special color. - */ - void -gui_mch_set_sp_color(guicolor_T color) -{ - specialColor.red = Red(color) * 0x0101; - specialColor.green = Green(color) * 0x0101; - specialColor.blue = Blue(color) * 0x0101; -} - -/* - * Draw undercurl at the bottom of the character cell. - */ - static void -draw_undercurl(int flags, int row, int col, int cells) -{ - int x; - int offset; - const static int val[8] = {1, 0, 0, 0, 1, 2, 2, 2 }; - int y = FILL_Y(row + 1) - 1; - - RGBForeColor(&specialColor); - - offset = val[FILL_X(col) % 8]; - MoveTo(FILL_X(col), y - offset); - - for (x = FILL_X(col); x < FILL_X(col + cells); ++x) - { - offset = val[x % 8]; - LineTo(x, y - offset); - } -} - - - static void -draw_string_QD(int row, int col, char_u *s, int len, int flags) -{ - char_u *tofree = NULL; - - if (output_conv.vc_type != CONV_NONE) - { - tofree = string_convert(&output_conv, s, &len); - if (tofree != NULL) - s = tofree; - } - - /* - * On OS X, try using Quartz-style text antialiasing. - */ - if (gMacSystemVersion >= 0x1020) - { - // Quartz antialiasing is available only in OS 10.2 and later. - UInt32 qd_flags = (p_antialias ? - kQDUseCGTextRendering | kQDUseCGTextMetrics : 0); - QDSwapTextFlags(qd_flags); - } - - /* - * When antialiasing we're using srcOr mode, we have to clear the block - * before drawing the text. - * Also needed when 'linespace' is non-zero to remove the cursor and - * underlining. - * But not when drawing transparently. - * The following is like calling gui_mch_clear_block(row, col, row, col + - * len - 1), but without setting the bg color to gui.back_pixel. - */ - if (((gMacSystemVersion >= 0x1020 && p_antialias) || p_linespace != 0) - && !(flags & DRAW_TRANSP)) - { - Rect rc; - - rc.left = FILL_X(col); - rc.top = FILL_Y(row); - // Multibyte computation taken from gui_w32.c - if (has_mbyte) - { - // Compute the length in display cells. - rc.right = FILL_X(col + mb_string2cells(s, len)); - } - else - rc.right = FILL_X(col + len) + (col + len == Columns); - rc.bottom = FILL_Y(row + 1); - EraseRect(&rc); - } - - if (gMacSystemVersion >= 0x1020 && p_antialias) - { - StyleParameter face; - - face = normal; - if (flags & DRAW_BOLD) - face |= bold; - if (flags & DRAW_UNDERL) - face |= underline; - TextFace(face); - - // Quartz antialiasing works only in srcOr transfer mode. - TextMode(srcOr); - - MoveTo(TEXT_X(col), TEXT_Y(row)); - DrawText((char*)s, 0, len); - } - else - { - // Use old-style, non-antialiased QuickDraw text rendering. - TextMode(srcCopy); - TextFace(normal); - - // SelectFont(hdc, gui.currFont); - - if (flags & DRAW_TRANSP) - TextMode(srcOr); - - MoveTo(TEXT_X(col), TEXT_Y(row)); - DrawText((char *)s, 0, len); - - if (flags & DRAW_BOLD) - { - TextMode(srcOr); - MoveTo(TEXT_X(col) + 1, TEXT_Y(row)); - DrawText((char *)s, 0, len); - } - - if (flags & DRAW_UNDERL) - { - MoveTo(FILL_X(col), FILL_Y(row + 1) - 1); - LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1); - } - if (flags & DRAW_STRIKE) - { - MoveTo(FILL_X(col), FILL_Y(row + 1) - gui.char_height/2); - LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - gui.char_height/2); - } - } - - if (flags & DRAW_UNDERC) - draw_undercurl(flags, row, col, len); - - vim_free(tofree); -} - -#ifdef USE_ATSUI_DRAWING - - static void -draw_string_ATSUI(int row, int col, char_u *s, int len, int flags) -{ - // ATSUI requires utf-16 strings - UniCharCount utf16_len; - UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len); - utf16_len /= sizeof(UniChar); - - // - ATSUI automatically antialiases text (Someone) - // - for some reason it does not work... (Jussi) -#ifdef MAC_ATSUI_DEBUG - fprintf(stderr, "row = %d, col = %d, len = %d: '%c'\n", - row, col, len, len == 1 ? s[0] : ' '); -#endif - /* - * When antialiasing we're using srcOr mode, we have to clear the block - * before drawing the text. - * Also needed when 'linespace' is non-zero to remove the cursor and - * underlining. - * But not when drawing transparently. - * The following is like calling gui_mch_clear_block(row, col, row, col + - * len - 1), but without setting the bg color to gui.back_pixel. - */ - if ((flags & DRAW_TRANSP) == 0) - { - Rect rc; - - rc.left = FILL_X(col); - rc.top = FILL_Y(row); - // Multibyte computation taken from gui_w32.c - if (has_mbyte) - { - // Compute the length in display cells. - rc.right = FILL_X(col + mb_string2cells(s, len)); - } - else - rc.right = FILL_X(col + len) + (col + len == Columns); - - rc.bottom = FILL_Y(row + 1); - EraseRect(&rc); - } - - { - TextMode(srcCopy); - TextFace(normal); - - // SelectFont(hdc, gui.currFont); - if (flags & DRAW_TRANSP) - TextMode(srcOr); - - MoveTo(TEXT_X(col), TEXT_Y(row)); - - if (gFontStyle && flags & DRAW_BOLD) - { - Boolean attValue = true; - ATSUAttributeTag attribTags[] = { kATSUQDBoldfaceTag }; - ByteCount attribSizes[] = { sizeof(Boolean) }; - ATSUAttributeValuePtr attribValues[] = { &attValue }; - - ATSUSetAttributes(gFontStyle, 1, attribTags, attribSizes, attribValues); - } - - UInt32 useAntialias = p_antialias ? kATSStyleApplyAntiAliasing - : kATSStyleNoAntiAliasing; - if (useAntialias != useAntialias_cached) - { - ATSUAttributeTag attribTags[] = { kATSUStyleRenderingOptionsTag }; - ByteCount attribSizes[] = { sizeof(UInt32) }; - ATSUAttributeValuePtr attribValues[] = { &useAntialias }; - - if (gFontStyle) - ATSUSetAttributes(gFontStyle, 1, attribTags, - attribSizes, attribValues); - if (gWideFontStyle) - ATSUSetAttributes(gWideFontStyle, 1, attribTags, - attribSizes, attribValues); - - useAntialias_cached = useAntialias; - } - - if (has_mbyte) - { - int n, width_in_cell, last_width_in_cell; - UniCharArrayOffset offset = 0; - UniCharCount yet_to_draw = 0; - ATSUTextLayout textLayout; - ATSUStyle textStyle; - - last_width_in_cell = 1; - ATSUCreateTextLayout(&textLayout); - ATSUSetTextPointerLocation(textLayout, tofree, - kATSUFromTextBeginning, - kATSUToTextEnd, utf16_len); - /* - ATSUSetRunStyle(textLayout, gFontStyle, - kATSUFromTextBeginning, kATSUToTextEnd); */ - - // Compute the length in display cells. - for (n = 0; n < len; n += MB_BYTE2LEN(s[n])) - { - width_in_cell = (*mb_ptr2cells)(s + n); - - // probably we are switching from single byte character - // to multibyte characters (which requires more than one - // cell to draw) - if (width_in_cell != last_width_in_cell) - { -#ifdef MAC_ATSUI_DEBUG - fprintf(stderr, "\tn = %2d, (%d-%d), offset = %d, yet_to_draw = %d\n", - n, last_width_in_cell, width_in_cell, offset, yet_to_draw); -#endif - textStyle = last_width_in_cell > 1 ? gWideFontStyle - : gFontStyle; - - ATSUSetRunStyle(textLayout, textStyle, offset, yet_to_draw); - offset += yet_to_draw; - yet_to_draw = 0; - last_width_in_cell = width_in_cell; - } - - yet_to_draw++; - } - - if (yet_to_draw) - { -#ifdef MAC_ATSUI_DEBUG - fprintf(stderr, "\tn = %2d, (%d-%d), offset = %d, yet_to_draw = %d\n", - n, last_width_in_cell, width_in_cell, offset, yet_to_draw); -#endif - // finish the rest style - textStyle = width_in_cell > 1 ? gWideFontStyle : gFontStyle; - ATSUSetRunStyle(textLayout, textStyle, offset, kATSUToTextEnd); - } - - ATSUSetTransientFontMatching(textLayout, TRUE); - ATSUDrawText(textLayout, - kATSUFromTextBeginning, kATSUToTextEnd, - kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc); - ATSUDisposeTextLayout(textLayout); - } - else - { - ATSUTextLayout textLayout; - - if (ATSUCreateTextLayoutWithTextPtr(tofree, - kATSUFromTextBeginning, kATSUToTextEnd, - utf16_len, - (gFontStyle ? 1 : 0), &utf16_len, - (gFontStyle ? &gFontStyle : NULL), - &textLayout) == noErr) - { - ATSUSetTransientFontMatching(textLayout, TRUE); - - ATSUDrawText(textLayout, - kATSUFromTextBeginning, kATSUToTextEnd, - kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc); - - ATSUDisposeTextLayout(textLayout); - } - } - - // drawing is done, now reset bold to normal - if (gFontStyle && flags & DRAW_BOLD) - { - Boolean attValue = false; - - ATSUAttributeTag attribTags[] = { kATSUQDBoldfaceTag }; - ByteCount attribSizes[] = { sizeof(Boolean) }; - ATSUAttributeValuePtr attribValues[] = { &attValue }; - - ATSUSetAttributes(gFontStyle, 1, attribTags, attribSizes, - attribValues); - } - } - - if (flags & DRAW_UNDERC) - draw_undercurl(flags, row, col, len); - - vim_free(tofree); -} -#endif - - void -gui_mch_draw_string(int row, int col, char_u *s, int len, int flags) -{ -#if defined(USE_ATSUI_DRAWING) - if (p_macatsui == 0 && p_macatsui_last != 0) - // switch from macatsui to nomacatsui - gui_mac_dispose_atsui_style(); - else if (p_macatsui != 0 && p_macatsui_last == 0) - // switch from nomacatsui to macatsui - gui_mac_create_atsui_style(); - - if (p_macatsui) - draw_string_ATSUI(row, col, s, len, flags); - else -#endif - draw_string_QD(row, col, s, len, flags); -} - -/* - * Return OK if the key with the termcap name "name" is supported. - */ - int -gui_mch_haskey(char_u *name) -{ - int i; - - for (i = 0; special_keys[i].key_sym != (KeySym)0; i++) - if (name[0] == special_keys[i].vim_code0 && - name[1] == special_keys[i].vim_code1) - return OK; - return FAIL; -} - - void -gui_mch_beep(void) -{ - SysBeep(1); // Should this be 0? (????) -} - - void -gui_mch_flash(int msec) -{ - // Do a visual beep by reversing the foreground and background colors - Rect rc; - - /* - * Note: InvertRect() excludes right and bottom of rectangle. - */ - rc.left = 0; - rc.top = 0; - rc.right = gui.num_cols * gui.char_width; - rc.bottom = gui.num_rows * gui.char_height; - InvertRect(&rc); - - ui_delay((long)msec, TRUE); // wait for some msec - - InvertRect(&rc); -} - -/* - * Invert a rectangle from row r, column c, for nr rows and nc columns. - */ - void -gui_mch_invert_rectangle(int r, int c, int nr, int nc) -{ - Rect rc; - - /* - * Note: InvertRect() excludes right and bottom of rectangle. - */ - rc.left = FILL_X(c); - rc.top = FILL_Y(r); - rc.right = rc.left + nc * gui.char_width; - rc.bottom = rc.top + nr * gui.char_height; - InvertRect(&rc); -} - -/* - * Iconify the GUI window. - */ - void -gui_mch_iconify(void) -{ - // TODO: find out what could replace iconify - // -window shade? - // -hide application? -} - -#if defined(FEAT_EVAL) || defined(PROTO) -/* - * Bring the Vim window to the foreground. - */ - void -gui_mch_set_foreground(void) -{ - // TODO -} -#endif - -/* - * Draw a cursor without focus. - */ - void -gui_mch_draw_hollow_cursor(guicolor_T color) -{ - Rect rc; - - /* - * Note: FrameRect() excludes right and bottom of rectangle. - */ - rc.left = FILL_X(gui.col); - rc.top = FILL_Y(gui.row); - rc.right = rc.left + gui.char_width; - if (mb_lefthalve(gui.row, gui.col)) - rc.right += gui.char_width; - rc.bottom = rc.top + gui.char_height; - - gui_mch_set_fg_color(color); - - FrameRect(&rc); -} - -/* - * Draw part of a cursor, only w pixels wide, and h pixels high. - */ - void -gui_mch_draw_part_cursor(int w, int h, guicolor_T color) -{ - Rect rc; - -#ifdef FEAT_RIGHTLEFT - // vertical line should be on the right of current point - if (CURSOR_BAR_RIGHT) - rc.left = FILL_X(gui.col + 1) - w; - else -#endif - rc.left = FILL_X(gui.col); - rc.top = FILL_Y(gui.row) + gui.char_height - h; - rc.right = rc.left + w; - rc.bottom = rc.top + h; - - gui_mch_set_fg_color(color); - - FrameRect(&rc); -// PaintRect(&rc); -} - - - -/* - * Catch up with any queued X events. This may put keyboard input into the - * input buffer, call resize call-backs, trigger timers etc. If there is - * nothing in the X event queue (& no timers pending), then we return - * immediately. - */ - void -gui_mch_update(void) -{ - // TODO: find what to do - // maybe call gui_mch_wait_for_chars (0) - // more like look at EventQueue then - // call heart of gui_mch_wait_for_chars; - // - // if (eventther) - // gui_mac_handle_event(&event); - EventRecord theEvent; - - if (EventAvail(everyEvent, &theEvent)) - if (theEvent.what != nullEvent) - gui_mch_wait_for_chars(0); -} - -/* - * Simple wrapper to neglect more easily the time - * spent inside WaitNextEvent while profiling. - */ - - pascal - Boolean -WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn) -{ - if (((long) sleep) < -1) - sleep = 32767; - return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn); -} - -/* - * GUI input routine called by gui_wait_for_chars(). Waits for a character - * from the keyboard. - * wtime == -1 Wait forever. - * wtime == 0 This should never happen. - * wtime > 0 Wait wtime milliseconds for a character. - * Returns OK if a character was found to be available within the given time, - * or FAIL otherwise. - */ - int -gui_mch_wait_for_chars(int wtime) -{ - EventMask mask = (everyEvent); - EventRecord event; - long entryTick; - long currentTick; - long sleeppyTick; - - // If we are providing life feedback with the scrollbar, - // we don't want to try to wait for an event, or else - // there won't be any life feedback. - if (dragged_sb != NULL) - return FAIL; - // TODO: Check if FAIL is the proper return code - - entryTick = TickCount(); - - allow_scrollbar = TRUE; - - do - { -#if 0 - if (dragRectControl == kCreateEmpty) - { - dragRgn = NULL; - dragRectControl = kNothing; - } - else -#endif - if (dragRectControl == kCreateRect) - { - dragRgn = cursorRgn; - RectRgn(dragRgn, &dragRect); - dragRectControl = kNothing; - } - /* - * Don't use gui_mch_update() because then we will spin-lock until a - * char arrives, instead we use WaitNextEventWrp() to hang until an - * event arrives. No need to check for input_buf_full because we are - * returning as soon as it contains a single char. - */ - // TODO: reduce wtime accordingly??? - if (wtime > -1) - sleeppyTick = 60 * wtime / 1000; - else - sleeppyTick = 32767; - - if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn)) - { - gui_mac_handle_event(&event); - if (input_available()) - { - allow_scrollbar = FALSE; - return OK; - } - } - currentTick = TickCount(); - } - while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000)); - - allow_scrollbar = FALSE; - return FAIL; -} - -/* - * Output routines. - */ - -/* - * Flush any output to the screen - */ - void -gui_mch_flush(void) -{ - // TODO: Is anything needed here? -} - -/* - * Clear a rectangular region of the screen from text pos (row1, col1) to - * (row2, col2) inclusive. - */ - void -gui_mch_clear_block(int row1, int col1, int row2, int col2) -{ - Rect rc; - - /* - * Clear one extra pixel at the far right, for when bold characters have - * spilled over to the next column. - */ - rc.left = FILL_X(col1); - rc.top = FILL_Y(row1); - rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1); - rc.bottom = FILL_Y(row2 + 1); - - gui_mch_set_bg_color(gui.back_pixel); - EraseRect(&rc); -} - -/* - * Clear the whole text window. - */ - void -gui_mch_clear_all(void) -{ - Rect rc; - - rc.left = 0; - rc.top = 0; - rc.right = Columns * gui.char_width + 2 * gui.border_width; - rc.bottom = Rows * gui.char_height + 2 * gui.border_width; - - gui_mch_set_bg_color(gui.back_pixel); - EraseRect(&rc); -// gui_mch_set_fg_color(gui.norm_pixel); -// FrameRect(&rc); -} - -/* - * Delete the given number of lines from the given row, scrolling up any - * text further down within the scroll region. - */ - void -gui_mch_delete_lines(int row, int num_lines) -{ - Rect rc; - - // changed without checking! - rc.left = FILL_X(gui.scroll_region_left); - rc.right = FILL_X(gui.scroll_region_right + 1); - rc.top = FILL_Y(row); - rc.bottom = FILL_Y(gui.scroll_region_bot + 1); - - gui_mch_set_bg_color(gui.back_pixel); - ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil); - - gui_clear_block(gui.scroll_region_bot - num_lines + 1, - gui.scroll_region_left, - gui.scroll_region_bot, gui.scroll_region_right); -} - -/* - * Insert the given number of lines before the given row, scrolling down any - * following text within the scroll region. - */ - void -gui_mch_insert_lines(int row, int num_lines) -{ - Rect rc; - - rc.left = FILL_X(gui.scroll_region_left); - rc.right = FILL_X(gui.scroll_region_right + 1); - rc.top = FILL_Y(row); - rc.bottom = FILL_Y(gui.scroll_region_bot + 1); - - gui_mch_set_bg_color(gui.back_pixel); - - ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil); - - // Update gui.cursor_row if the cursor scrolled or copied over - if (gui.cursor_row >= gui.row - && gui.cursor_col >= gui.scroll_region_left - && gui.cursor_col <= gui.scroll_region_right) - { - if (gui.cursor_row <= gui.scroll_region_bot - num_lines) - gui.cursor_row += num_lines; - else if (gui.cursor_row <= gui.scroll_region_bot) - gui.cursor_is_valid = FALSE; - } - - gui_clear_block(row, gui.scroll_region_left, - row + num_lines - 1, gui.scroll_region_right); -} - - /* - * TODO: add a vim format to the clipboard which remember - * LINEWISE, CHARWISE, BLOCKWISE - */ - - void -clip_mch_request_selection(Clipboard_T *cbd) -{ - - Handle textOfClip; - int flavor = 0; - Size scrapSize; - ScrapFlavorFlags scrapFlags; - ScrapRef scrap = nil; - OSStatus error; - int type; - char *searchCR; - char_u *tempclip; - - - error = GetCurrentScrap(&scrap); - if (error != noErr) - return; - - error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags); - if (error == noErr) - { - error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize); - if (error == noErr && scrapSize > 1) - flavor = 1; - } - - if (flavor == 0) - { - error = GetScrapFlavorFlags(scrap, SCRAPTEXTFLAVOR, &scrapFlags); - if (error != noErr) - return; - - error = GetScrapFlavorSize(scrap, SCRAPTEXTFLAVOR, &scrapSize); - if (error != noErr) - return; - } - - ReserveMem(scrapSize); - - // In CARBON we don't need a Handle, a pointer is good - textOfClip = NewHandle(scrapSize); - - // tempclip = alloc(scrapSize+1); - HLock(textOfClip); - error = GetScrapFlavorData(scrap, - flavor ? VIMSCRAPFLAVOR : SCRAPTEXTFLAVOR, - &scrapSize, *textOfClip); - scrapSize -= flavor; - - if (flavor) - type = **textOfClip; - else - type = MAUTO; - - tempclip = alloc(scrapSize + 1); - mch_memmove(tempclip, *textOfClip + flavor, scrapSize); - tempclip[scrapSize] = 0; - -#ifdef MACOS_CONVERT - { - // Convert from utf-16 (clipboard) - size_t encLen = 0; - char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen); - - if (to != NULL) - { - scrapSize = encLen; - vim_free(tempclip); - tempclip = to; - } - } -#endif - - searchCR = (char *)tempclip; - while (searchCR != NULL) - { - searchCR = strchr(searchCR, '\r'); - if (searchCR != NULL) - *searchCR = '\n'; - } - - clip_yank_selection(type, tempclip, scrapSize, cbd); - - vim_free(tempclip); - HUnlock(textOfClip); - - DisposeHandle(textOfClip); -} - - void -clip_mch_lose_selection(Clipboard_T *cbd) -{ - /* - * TODO: Really nothing to do? - */ -} - - int -clip_mch_own_selection(Clipboard_T *cbd) -{ - return OK; -} - -/* - * Send the current selection to the clipboard. - */ - void -clip_mch_set_selection(Clipboard_T *cbd) -{ - Handle textOfClip; - long scrapSize; - int type; - ScrapRef scrap; - - char_u *str = NULL; - - if (!cbd->owned) - return; - - clip_get_selection(cbd); - - /* - * Once we set the clipboard, lose ownership. If another application sets - * the clipboard, we don't want to think that we still own it. - */ - cbd->owned = FALSE; - - type = clip_convert_selection(&str, (long_u *)&scrapSize, cbd); - -#ifdef MACOS_CONVERT - size_t utf16_len = 0; - UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len); - if (to) - { - scrapSize = utf16_len; - vim_free(str); - str = (char_u *)to; - } -#endif - - if (type >= 0) - { - ClearCurrentScrap(); - - textOfClip = NewHandle(scrapSize + 1); - HLock(textOfClip); - - **textOfClip = type; - mch_memmove(*textOfClip + 1, str, scrapSize); - GetCurrentScrap(&scrap); - PutScrapFlavor(scrap, SCRAPTEXTFLAVOR, kScrapFlavorMaskNone, - scrapSize, *textOfClip + 1); - PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone, - scrapSize + 1, *textOfClip); - HUnlock(textOfClip); - DisposeHandle(textOfClip); - } - - vim_free(str); -} - - void -gui_mch_set_text_area_pos(int x, int y, int w, int h) -{ - Rect VimBound; - -// HideWindow(gui.VimWindow); - GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound); - - if (gui.which_scrollbars[SBAR_LEFT]) - VimBound.left = -gui.scrollbar_width + 1; - else - VimBound.left = 0; - - SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound); - - ShowWindow(gui.VimWindow); -} - -/* - * Menu stuff. - */ - - void -gui_mch_enable_menu(int flag) -{ - /* - * Menu is always active. - */ -} - - void -gui_mch_set_menu_pos(int x, int y, int w, int h) -{ - /* - * The menu is always at the top of the screen. - */ -} - -/* - * Add a sub menu to the menu bar. - */ - void -gui_mch_add_menu(vimmenu_T *menu, int idx) -{ - /* - * TODO: Try to use only menu_id instead of both menu_id and menu_handle. - * TODO: use menu->mnemonic and menu->actext - * TODO: Try to reuse menu id - * Carbon Help suggest to use only id between 1 and 235 - */ - static long next_avail_id = 128; - long menu_after_me = 0; // Default to the end - CFStringRef name; - short index; - vimmenu_T *parent = menu->parent; - vimmenu_T *brother = menu->next; - - // Cannot add a menu if ... - if ((parent != NULL && parent->submenu_id == 0)) - return; - - // menu ID greater than 1024 are reserved for ??? - if (next_avail_id == 1024) - return; - - // My brother could be the PopUp, find my real brother - while ((brother != NULL) && (!menu_is_menubar(brother->name))) - brother = brother->next; - - // Find where to insert the menu (for MenuBar) - if ((parent == NULL) && (brother != NULL)) - menu_after_me = brother->submenu_id; - - // If the menu is not part of the menubar (and its submenus), add it 'nowhere' - if (!menu_is_menubar(menu->name)) - menu_after_me = hierMenu; - - // Convert the name -#ifdef MACOS_CONVERT - name = menu_title_removing_mnemonic(menu); -#else - name = C2Pascal_save(menu->dname); -#endif - if (name == NULL) - return; - - // Create the menu unless it's the help menu - { - // Carbon suggest use of - // OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *); - // OSStatus SetMenuTitle(MenuRef, ConstStr255Param title); - menu->submenu_id = next_avail_id; - if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr) - SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name); - next_avail_id++; - } - - if (parent == NULL) - { - // Adding a menu to the menubar, or in the no mans land (for PopUp) - - // TODO: Verify if we could only Insert Menu if really part of the - // menubar The Inserted menu are scanned or the Command-key combos - - // Insert the menu - InsertMenu(menu->submenu_handle, menu_after_me); // insert before -#if 1 - // Vim should normally update it. TODO: verify - DrawMenuBar(); -#endif - } - else - { - // Adding as a submenu - - index = gui_mac_get_menu_item_index(menu); - - // Call InsertMenuItem followed by SetMenuItemText - // to avoid special character recognition by InsertMenuItem - InsertMenuItem(parent->submenu_handle, "\p ", idx); // afterItem - SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name); - SetItemCmd(parent->submenu_handle, idx+1, 0x1B); - SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id); - InsertMenu(menu->submenu_handle, hierMenu); - } - - CFRelease(name); - -#if 0 - // Done by Vim later on - DrawMenuBar(); -#endif -} - -/* - * Add a menu item to a menu - */ - void -gui_mch_add_menu_item(vimmenu_T *menu, int idx) -{ - CFStringRef name; - vimmenu_T *parent = menu->parent; - int menu_inserted; - - // Cannot add item, if the menu have not been created - if (parent->submenu_id == 0) - return; - - // Could call SetMenuRefCon [CARBON] to associate with the Menu, - // for older OS call GetMenuItemData (menu, item, isCommandID?, data) - - // Convert the name -#ifdef MACOS_CONVERT - name = menu_title_removing_mnemonic(menu); -#else - name = C2Pascal_save(menu->dname); -#endif - - // Where are just a menu item, so no handle, no id - menu->submenu_id = 0; - menu->submenu_handle = NULL; - - menu_inserted = 0; - if (menu->actext) - { - // If the accelerator text for the menu item looks like it describes - // a command key (e.g., "" or ""), display it as the - // item's command equivalent. - int key = 0; - int modifiers = 0; - char_u *p_actext; - - p_actext = menu->actext; - key = find_special_key(&p_actext, &modifiers, FSK_SIMPLIFY, NULL); - if (*p_actext != 0) - key = 0; // error: trailing text - // find_special_key() returns a keycode with as many of the - // specified modifiers as appropriate already applied (e.g., for - // "" it returns Ctrl-X as the keycode and MOD_MASK_CMD - // as the only modifier). Since we want to display all of the - // modifiers, we need to convert the keycode back to a printable - // character plus modifiers. - // TODO: Write an alternative find_special_key() that doesn't - // apply modifiers. - if (key > 0 && key < 32) - { - // Convert a control key to an uppercase letter. Note that - // by this point it is no longer possible to distinguish - // between, e.g., Ctrl-S and Ctrl-Shift-S. - modifiers |= MOD_MASK_CTRL; - key += '@'; - } - // If the keycode is an uppercase letter, set the Shift modifier. - // If it is a lowercase letter, don't set the modifier, but convert - // the letter to uppercase for display in the menu. - else if (key >= 'A' && key <= 'Z') - modifiers |= MOD_MASK_SHIFT; - else if (key >= 'a' && key <= 'z') - key += 'A' - 'a'; - // Note: keycodes below 0x22 are reserved by Apple. - if (key >= 0x22 && vim_isprintc_strict(key)) - { - int valid = 1; - char_u mac_mods = kMenuNoModifiers; - // Convert Vim modifier codes to Menu Manager equivalents. - if (modifiers & MOD_MASK_SHIFT) - mac_mods |= kMenuShiftModifier; - if (modifiers & MOD_MASK_CTRL) - mac_mods |= kMenuControlModifier; - if (!(modifiers & MOD_MASK_CMD)) - mac_mods |= kMenuNoCommandModifier; - if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK) - valid = 0; // TODO: will Alt someday map to Option? - if (valid) - { - char_u item_txt[10]; - // Insert the menu item after idx, with its command key. - item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/'; - item_txt[3] = key; - InsertMenuItem(parent->submenu_handle, item_txt, idx); - // Set the modifier keys. - SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods); - menu_inserted = 1; - } - } - } - // Call InsertMenuItem followed by SetMenuItemText - // to avoid special character recognition by InsertMenuItem - if (!menu_inserted) - InsertMenuItem(parent->submenu_handle, "\p ", idx); // afterItem - // Set the menu item name. - SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name); - -#if 0 - // Called by Vim - DrawMenuBar(); -#endif - - CFRelease(name); -} - - void -gui_mch_toggle_tearoffs(int enable) -{ - // no tearoff menus -} - -/* - * Destroy the machine specific menu widget. - */ - void -gui_mch_destroy_menu(vimmenu_T *menu) -{ - short index = gui_mac_get_menu_item_index(menu); - - if (index > 0) - { - if (menu->parent) - { - { - // For now just don't delete help menu items. (Huh? Dany) - DeleteMenuItem(menu->parent->submenu_handle, index); - - // Delete the Menu if it was a hierarchical Menu - if (menu->submenu_id != 0) - { - DeleteMenu(menu->submenu_id); - DisposeMenu(menu->submenu_handle); - } - } - } -#ifdef DEBUG_MAC_MENU - else - { - printf("gmdm 2\n"); - } -#endif - } - else - { - { - DeleteMenu(menu->submenu_id); - DisposeMenu(menu->submenu_handle); - } - } - // Shouldn't this be already done by Vim. TODO: Check - DrawMenuBar(); -} - -/* - * Make a menu either grey or not grey. - */ - void -gui_mch_menu_grey(vimmenu_T *menu, int grey) -{ - // TODO: Check if menu really exists - short index = gui_mac_get_menu_item_index(menu); -/* - index = menu->index; -*/ - if (grey) - { - if (menu->children) - DisableMenuItem(menu->submenu_handle, index); - if (menu->parent) - if (menu->parent->submenu_handle) - DisableMenuItem(menu->parent->submenu_handle, index); - } - else - { - if (menu->children) - EnableMenuItem(menu->submenu_handle, index); - if (menu->parent) - if (menu->parent->submenu_handle) - EnableMenuItem(menu->parent->submenu_handle, index); - } -} - -/* - * Make menu item hidden or not hidden - */ - void -gui_mch_menu_hidden(vimmenu_T *menu, int hidden) -{ - // There's no hidden mode on MacOS - gui_mch_menu_grey(menu, hidden); -} - - -/* - * This is called after setting all the menus to grey/hidden or not. - */ - void -gui_mch_draw_menubar(void) -{ - DrawMenuBar(); -} - - -/* - * Scrollbar stuff. - */ - - void -gui_mch_enable_scrollbar( - scrollbar_T *sb, - int flag) -{ - if (flag) - ShowControl(sb->id); - else - HideControl(sb->id); - -#ifdef DEBUG_MAC_SB - printf("enb_sb (%x) %x\n",sb->id, flag); -#endif -} - - void -gui_mch_set_scrollbar_thumb( - scrollbar_T *sb, - long val, - long size, - long max) -{ - SetControl32BitMaximum (sb->id, max); - SetControl32BitMinimum (sb->id, 0); - SetControl32BitValue (sb->id, val); - SetControlViewSize (sb->id, size); -#ifdef DEBUG_MAC_SB - printf("thumb_sb (%x) %lx, %lx,%lx\n",sb->id, val, size, max); -#endif -} - - void -gui_mch_set_scrollbar_pos( - scrollbar_T *sb, - int x, - int y, - int w, - int h) -{ - gui_mch_set_bg_color(gui.back_pixel); -#if 0 - if (gui.which_scrollbars[SBAR_LEFT]) - { - MoveControl(sb->id, x-16, y); - SizeControl(sb->id, w + 1, h); - } - else - { - MoveControl(sb->id, x, y); - SizeControl(sb->id, w + 1, h); - } -#endif - if (sb == &gui.bottom_sbar) - h += 1; - else - w += 1; - - if (gui.which_scrollbars[SBAR_LEFT]) - x -= 15; - - MoveControl(sb->id, x, y); - SizeControl(sb->id, w, h); -#ifdef DEBUG_MAC_SB - printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h); -#endif -} - - int -gui_mch_get_scrollbar_xpadding(void) -{ - // TODO: Calculate the padding for adjust scrollbar position when the - // Window is maximized. - return 0; -} - - int -gui_mch_get_scrollbar_ypadding(void) -{ - // TODO: Calculate the padding for adjust scrollbar position when the - // Window is maximized. - return 0; -} - - void -gui_mch_create_scrollbar( - scrollbar_T *sb, - int orient) // SBAR_VERT or SBAR_HORIZ -{ - Rect bounds; - - bounds.top = -16; - bounds.bottom = -10; - bounds.right = -10; - bounds.left = -16; - - sb->id = NewControl(gui.VimWindow, - &bounds, - "\pScrollBar", - TRUE, - 0, // current - 0, // top - 0, // bottom - kControlScrollBarLiveProc, - (long) sb->ident); -#ifdef DEBUG_MAC_SB - printf("create_sb (%x) %x\n",sb->id, orient); -#endif -} - - void -gui_mch_destroy_scrollbar(scrollbar_T *sb) -{ - gui_mch_set_bg_color(gui.back_pixel); - DisposeControl(sb->id); -#ifdef DEBUG_MAC_SB - printf("dest_sb (%x) \n",sb->id); -#endif -} - - int -gui_mch_is_blinking(void) -{ - return FALSE; -} - - int -gui_mch_is_blink_off(void) -{ - return FALSE; -} - -/* - * Cursor blink functions. - * - * This is a simple state machine: - * BLINK_NONE not blinking at all - * BLINK_OFF blinking, cursor is not shown - * BLINK_ON blinking, cursor is shown - */ - void -gui_mch_set_blinking(long wait, long on, long off) -{ -#if 0 - // TODO: TODO: TODO: TODO: - blink_waittime = wait; - blink_ontime = on; - blink_offtime = off; -#endif -} - -/* - * Stop the cursor blinking. Show the cursor if it wasn't shown. - */ - void -gui_mch_stop_blink(int may_call_gui_update_cursor) -{ - if (may_call_gui_update_cursor) - gui_update_cursor(TRUE, FALSE); -#if 0 - // TODO: TODO: TODO: TODO: - gui_w32_rm_blink_timer(); - if (blink_state == BLINK_OFF) - gui_update_cursor(TRUE, FALSE); - blink_state = BLINK_NONE; -#endif -} - -/* - * Start the cursor blinking. If it was already blinking, this restarts the - * waiting time and shows the cursor. - */ - void -gui_mch_start_blink(void) -{ - gui_update_cursor(TRUE, FALSE); - // TODO: TODO: TODO: TODO: -// gui_w32_rm_blink_timer(); - - // Only switch blinking on if none of the times is zero -#if 0 - if (blink_waittime && blink_ontime && blink_offtime) - { - blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime, - (TIMERPROC)_OnBlinkTimer); - blink_state = BLINK_ON; - gui_update_cursor(TRUE, FALSE); - } -#endif -} - -/* - * Return the RGB value of a pixel as long. - */ - guicolor_T -gui_mch_get_rgb(guicolor_T pixel) -{ - return (guicolor_T)((Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel)); -} - - - -#ifdef FEAT_BROWSE -/* - * Pop open a file browser and return the file selected, in allocated memory, - * or NULL if Cancel is hit. - * saving - TRUE if the file will be saved to, FALSE if it will be opened. - * title - Title message for the file browser dialog. - * dflt - Default name of file. - * ext - Default extension to be added to files without extensions. - * initdir - directory in which to open the browser (NULL = current dir) - * filter - Filter for matched files to choose from. - * Has a format like this: - * "C Files (*.c)\0*.c\0" - * "All Files\0*.*\0\0" - * If these two strings were concatenated, then a choice of two file - * filters will be selectable to the user. Then only matching files will - * be shown in the browser. If NULL, the default allows all files. - * - * *NOTE* - the filter string must be terminated with TWO nulls. - */ - char_u * -gui_mch_browse( - int saving, - char_u *title, - char_u *dflt, - char_u *ext, - char_u *initdir, - char_u *filter) -{ - // TODO: Add Ammon's safety check (Dany) - NavReplyRecord reply; - char_u *fname = NULL; - char_u **fnames = NULL; - long numFiles; - NavDialogOptions navOptions; - OSErr error; - - // Get Navigation Service Defaults value - NavGetDefaultDialogOptions(&navOptions); - - - // TODO: If we get a :browse args, set the Multiple bit. - navOptions.dialogOptionFlags = kNavAllowInvisibleFiles - | kNavDontAutoTranslate - | kNavDontAddTranslateItems - // | kNavAllowMultipleFiles - | kNavAllowStationery; - - (void) C2PascalString(title, &navOptions.message); - (void) C2PascalString(dflt, &navOptions.savedFileName); - // Could set clientName? - // windowTitle? (there's no title bar?) - - if (saving) - { - // Change first parm AEDesc (typeFSS) *defaultLocation to match dflt - NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL); - if (!reply.validRecord) - return NULL; - } - else - { - // Change first parm AEDesc (typeFSS) *defaultLocation to match dflt - NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL); - if (!reply.validRecord) - return NULL; - } - - fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error); - - NavDisposeReply(&reply); - - if (fnames) - { - fname = fnames[0]; - vim_free(fnames); - } - - // TODO: Shorten the file name if possible - return fname; -} -#endif // FEAT_BROWSE - -#ifdef FEAT_GUI_DIALOG -/* - * Stuff for dialogues - */ - -/* - * Create a dialogue dynamically from the parameter strings. - * type = type of dialogue (question, alert, etc.) - * title = dialogue title. may be NULL for default title. - * message = text to display. Dialogue sizes to accommodate it. - * buttons = '\n' separated list of button captions, default first. - * dfltbutton = number of default button. - * - * This routine returns 1 if the first button is pressed, - * 2 for the second, etc. - * - * 0 indicates Esc was pressed. - * -1 for unexpected error - * - * If stubbing out this fn, return 1. - */ - -typedef struct -{ - short idx; - short width; // Size of the text in pixel - Rect box; -} vgmDlgItm; // Vim Gui_Mac.c Dialog Item - -#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top) - - static void -macMoveDialogItem( - DialogRef theDialog, - short itemNumber, - short X, - short Y, - Rect *inBox) -{ -#if 0 // USE_CARBONIZED - // Untested - MoveDialogItem(theDialog, itemNumber, X, Y); - if (inBox != nil) - GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox); -#else - short itemType; - Handle itemHandle; - Rect localBox; - Rect *itemBox = &localBox; - - if (inBox != nil) - itemBox = inBox; - - GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox); - OffsetRect(itemBox, -itemBox->left, -itemBox->top); - OffsetRect(itemBox, X, Y); - // To move a control (like a button) we need to call both - // MoveControl and SetDialogItem. FAQ 6-18 - if (1) //(itemType & kControlDialogItem) - MoveControl((ControlRef) itemHandle, X, Y); - SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox); -#endif -} - - static void -macSizeDialogItem( - DialogRef theDialog, - short itemNumber, - short width, - short height) -{ - short itemType; - Handle itemHandle; - Rect itemBox; - - GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox); - - // When width or height is zero do not change it - if (width == 0) - width = itemBox.right - itemBox.left; - if (height == 0) - height = itemBox.bottom - itemBox.top; - -#if 0 // USE_CARBONIZED - SizeDialogItem(theDialog, itemNumber, width, height); // Untested -#else - // Resize the bounding box - itemBox.right = itemBox.left + width; - itemBox.bottom = itemBox.top + height; - - // To resize a control (like a button) we need to call both - // SizeControl and SetDialogItem. (deducted from FAQ 6-18) - if (itemType & kControlDialogItem) - SizeControl((ControlRef) itemHandle, width, height); - - // Configure back the item - SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox); -#endif -} - - static void -macSetDialogItemText( - DialogRef theDialog, - short itemNumber, - Str255 itemName) -{ - short itemType; - Handle itemHandle; - Rect itemBox; - - GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox); - - if (itemType & kControlDialogItem) - SetControlTitle((ControlRef) itemHandle, itemName); - else - SetDialogItemText(itemHandle, itemName); -} - - -/* - * ModalDialog() handler for message dialogs that have hotkey accelerators. - * Expects a mapping of hotkey char to control index in gDialogHotKeys; - * setting gDialogHotKeys to NULL disables any hotkey handling. - */ - static pascal Boolean -DialogHotkeyFilterProc ( - DialogRef theDialog, - EventRecord *event, - DialogItemIndex *itemHit) -{ - char_u keyHit; - - if (event->what == keyDown || event->what == autoKey) - { - keyHit = (event->message & charCodeMask); - - if (gDialogHotKeys && gDialogHotKeys[keyHit]) - { -#ifdef DEBUG_MAC_DIALOG_HOTKEYS - printf("user pressed hotkey '%c' --> item %d\n", keyHit, gDialogHotKeys[keyHit]); -#endif - *itemHit = gDialogHotKeys[keyHit]; - - // When handing off to StdFilterProc, pretend that the user - // clicked the control manually. Note that this is also supposed - // to cause the button to hilite briefly (to give some user - // feedback), but this seems not to actually work (or it's too - // fast to be seen). - event->what = kEventControlSimulateHit; - - return true; // we took care of it - } - - // Defer to the OS's standard behavior for this event. - // This ensures that Enter will still activate the default button. - return StdFilterProc(theDialog, event, itemHit); - } - return false; // Let ModalDialog deal with it -} - - -/* - * TODO: There have been some crashes with dialogs, check your inbox - * (Jussi) - */ - int -gui_mch_dialog( - int type, - char_u *title, - char_u *message, - char_u *buttons, - int dfltbutton, - char_u *textfield, - int ex_cmd) -{ - Handle buttonDITL; - Handle iconDITL; - Handle inputDITL; - Handle messageDITL; - Handle itemHandle; - Handle iconHandle; - DialogPtr theDialog; - char_u len; - char_u PascalTitle[256]; // place holder for the title - char_u name[256]; - GrafPtr oldPort; - short itemHit; - char_u *buttonChar; - short hotKeys[256]; // map of hotkey -> control ID - char_u aHotKey; - Rect box; - short button; - short lastButton; - short itemType; - short useIcon; - short width; - short totalButtonWidth = 0; // the width of all buttons together - // including spacing - short widestButton = 0; - short dfltButtonEdge = 20; // gut feeling - short dfltElementSpacing = 13; // from IM:V.2-29 - short dfltIconSideSpace = 23; // from IM:V.2-29 - short maximumWidth = 400; // gut feeling - short maxButtonWidth = 175; // gut feeling - - short vertical; - short dialogHeight; - short messageLines = 3; - FontInfo textFontInfo; - - vgmDlgItm iconItm; - vgmDlgItm messageItm; - vgmDlgItm inputItm; - vgmDlgItm buttonItm; - - WindowRef theWindow; - - ModalFilterUPP dialogUPP; - - // Check 'v' flag in 'guioptions': vertical button placement. - vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL); - - // Create a new Dialog Box from template. - theDialog = GetNewDialog(129, nil, (WindowRef) -1); - - // Get the WindowRef - theWindow = GetDialogWindow(theDialog); - - // Hide the window. - // 1. to avoid seeing slow drawing - // 2. to prevent a problem seen while moving dialog item - // within a visible window. (non-Carbon MacOS 9) - // Could be avoided by changing the resource. - HideWindow(theWindow); - - // Change the graphical port to the dialog, - // so we can measure the text with the proper font - GetPort(&oldPort); - SetPortDialogPort(theDialog); - - // Get the info about the default text, - // used to calculate the height of the message - // and of the text field - GetFontInfo(&textFontInfo); - - // Set the dialog title - if (title != NULL) - { - (void) C2PascalString(title, &PascalTitle); - SetWTitle(theWindow, PascalTitle); - } - - // Creates the buttons and add them to the Dialog Box. - buttonDITL = GetResource('DITL', 130); - buttonChar = buttons; - button = 0; - - // initialize the hotkey mapping - CLEAR_FIELD(hotKeys); - - for (;*buttonChar != 0;) - { - // Get the name of the button - button++; - len = 0; - for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++) - { - if (*buttonChar != DLG_HOTKEY_CHAR) - name[++len] = *buttonChar; - else - { - aHotKey = (char_u)*(buttonChar+1); - if (aHotKey >= 'A' && aHotKey <= 'Z') - aHotKey = (char_u)((int)aHotKey + (int)'a' - (int)'A'); - hotKeys[aHotKey] = button; -#ifdef DEBUG_MAC_DIALOG_HOTKEYS - printf("### hotKey for button %d is '%c'\n", button, aHotKey); -#endif - } - } - - if (*buttonChar != 0) - buttonChar++; - name[0] = len; - - // Add the button - AppendDITL(theDialog, buttonDITL, overlayDITL); // appendDITLRight); - - // Change the button's name - macSetDialogItemText(theDialog, button, name); - - // Resize the button to fit its name - width = StringWidth(name) + 2 * dfltButtonEdge; - // Limit the size of any button to an acceptable value. - // TODO: Should be based on the message width - if (width > maxButtonWidth) - width = maxButtonWidth; - macSizeDialogItem(theDialog, button, width, 0); - - totalButtonWidth += width; - - if (width > widestButton) - widestButton = width; - } - ReleaseResource(buttonDITL); - lastButton = button; - - // Add the icon to the Dialog Box. - iconItm.idx = lastButton + 1; - iconDITL = GetResource('DITL', 131); - switch (type) - { - case VIM_GENERIC: - case VIM_INFO: - case VIM_QUESTION: useIcon = kNoteIcon; break; - case VIM_WARNING: useIcon = kCautionIcon; break; - case VIM_ERROR: useIcon = kStopIcon; break; - default: useIcon = kStopIcon; - } - AppendDITL(theDialog, iconDITL, overlayDITL); - ReleaseResource(iconDITL); - GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box); - // TODO: Should the item be freed? - iconHandle = GetIcon(useIcon); - SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box); - - // Add the message to the Dialog box. - messageItm.idx = lastButton + 2; - messageDITL = GetResource('DITL', 132); - AppendDITL(theDialog, messageDITL, overlayDITL); - ReleaseResource(messageDITL); - GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box); - (void) C2PascalString(message, &name); - SetDialogItemText(itemHandle, name); - messageItm.width = StringWidth(name); - - // Add the input box if needed - if (textfield != NULL) - { - // Cheat for now reuse the message and convert to text edit - inputItm.idx = lastButton + 3; - inputDITL = GetResource('DITL', 132); - AppendDITL(theDialog, inputDITL, overlayDITL); - ReleaseResource(inputDITL); - GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box); -// SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box); - (void) C2PascalString(textfield, &name); - SetDialogItemText(itemHandle, name); - inputItm.width = StringWidth(name); - - // Hotkeys don't make sense if there's a text field - gDialogHotKeys = NULL; - } - else - // Install hotkey table - gDialogHotKeys = (short *)&hotKeys; - - // Set the and button. - SetDialogDefaultItem(theDialog, dfltbutton); - SetDialogCancelItem(theDialog, 0); - - // Reposition element - - // Check if we need to force vertical - if (totalButtonWidth > maximumWidth) - vertical = TRUE; - - // Place icon - macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box); - iconItm.box.right = box.right; - iconItm.box.bottom = box.bottom; - - // Place Message - messageItm.box.left = iconItm.box.right + dfltIconSideSpace; - macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent)); - macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box); - - // Place Input - if (textfield != NULL) - { - inputItm.box.left = messageItm.box.left; - inputItm.box.top = messageItm.box.bottom + dfltElementSpacing; - macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent); - macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box); - // Convert the static text into a text edit. - // For some reason this change need to be done last (Dany) - GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box); - SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box); - SelectDialogItemText(theDialog, inputItm.idx, 0, 32767); - } - - // Place Button - if (textfield != NULL) - { - buttonItm.box.left = inputItm.box.left; - buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing; - } - else - { - buttonItm.box.left = messageItm.box.left; - buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing; - } - - for (button=1; button <= lastButton; button++) - { - - macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box); - // With vertical, it's better to have all buttons the same length - if (vertical) - { - macSizeDialogItem(theDialog, button, widestButton, 0); - GetDialogItem(theDialog, button, &itemType, &itemHandle, &box); - } - // Calculate position of next button - if (vertical) - buttonItm.box.top = box.bottom + dfltElementSpacing; - else - buttonItm.box.left = box.right + dfltElementSpacing; - } - - // Resize the dialog box - dialogHeight = box.bottom + dfltElementSpacing; - SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE); - - // Magic resize - AutoSizeDialog(theDialog); - // Need a horizontal resize anyway so not that useful - - // Display it - ShowWindow(theWindow); -// BringToFront(theWindow); - SelectWindow(theWindow); - -// DrawDialog(theDialog); -#if 0 - GetPort(&oldPort); - SetPortDialogPort(theDialog); -#endif - -#ifdef USE_CARBONKEYHANDLER - // Avoid that we use key events for the main window. - dialog_busy = TRUE; -#endif - - // Prepare the shortcut-handling filterProc for handing to the dialog - dialogUPP = NewModalFilterUPP(DialogHotkeyFilterProc); - - // Hang until one of the button is hit - do - ModalDialog(dialogUPP, &itemHit); - while ((itemHit < 1) || (itemHit > lastButton)); - -#ifdef USE_CARBONKEYHANDLER - dialog_busy = FALSE; -#endif - - // Copy back the text entered by the user into the param - if (textfield != NULL) - { - GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box); - GetDialogItemText(itemHandle, (char_u *) &name); -#if IOSIZE < 256 - // Truncate the name to IOSIZE if needed - if (name[0] > IOSIZE) - name[0] = IOSIZE - 1; -#endif - vim_strncpy(textfield, &name[1], name[0]); - } - - // Restore the original graphical port - SetPort(oldPort); - - // Free the modal filterProc - DisposeRoutineDescriptor(dialogUPP); - - // Get ride of the dialog (free memory) - DisposeDialog(theDialog); - - return itemHit; -/* - * Useful thing which could be used - * SetDialogTimeout(): Auto click a button after timeout - * SetDialogTracksCursor() : Get the I-beam cursor over input box - * MoveDialogItem(): Probably better than SetDialogItem - * SizeDialogItem(): (but is it Carbon Only?) - * AutoSizeDialog(): Magic resize of dialog based on text length - */ -} -#endif // FEAT_DIALOG_GUI - -/* - * Display the saved error message(s). - */ -#ifdef USE_MCH_ERRMSG - void -display_errors(void) -{ - char *p; - char_u pError[256]; - - if (error_ga.ga_data == NULL) - return; - - // avoid putting up a message box with blanks only - for (p = (char *)error_ga.ga_data; *p; ++p) - if (!isspace(*p)) - { - if (STRLEN(p) > 255) - pError[0] = 255; - else - pError[0] = STRLEN(p); - - STRNCPY(&pError[1], p, pError[0]); - ParamText(pError, nil, nil, nil); - Alert(128, nil); - break; - // TODO: handled message longer than 256 chars - // use auto-sizeable alert - // or dialog with scrollbars (TextEdit zone) - } - ga_clear(&error_ga); -} -#endif - -/* - * Get current mouse coordinates in text window. - */ - void -gui_mch_getmouse(int *x, int *y) -{ - Point where; - - GetMouse(&where); - - *x = where.h; - *y = where.v; -} - - void -gui_mch_setmouse(int x, int y) -{ - // TODO -#if 0 - // From FAQ 3-11 - - CursorDevicePtr myMouse; - Point where; - - if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap) - != NGetTrapAddress(_Unimplemented, ToolTrap)) - { - // New way - - /* - * Get first device with one button. - * This will probably be the standard mouse - * start at head of cursor dev list - * - */ - - myMouse = nil; - - do - { - // Get the next cursor device - CursorDeviceNextDevice(&myMouse); - } - while ((myMouse != nil) && (myMouse->cntButtons != 1)); - - CursorDeviceMoveTo(myMouse, x, y); - } - else - { - // Old way - where.h = x; - where.v = y; - - *(Point *)RawMouse = where; - *(Point *)MTemp = where; - *(Ptr) CrsrNew = 0xFFFF; - } -#endif -} - - void -gui_mch_show_popupmenu(vimmenu_T *menu) -{ -/* - * Clone PopUp to use menu - * Create a object descriptor for the current selection - * Call the procedure - */ - - MenuHandle CntxMenu; - Point where; - OSStatus status; - UInt32 CntxType; - SInt16 CntxMenuID; - UInt16 CntxMenuItem; - Str255 HelpName = ""; - GrafPtr savePort; - - // Save Current Port: On MacOS X we seem to lose the port - GetPort(&savePort); //OSX - - GetMouse(&where); - LocalToGlobal(&where); //OSX - CntxMenu = menu->submenu_handle; - - // TODO: Get the text selection from Vim - - // Call to Handle Popup - status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemRemoveHelp, - HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem); - - if (status == noErr) - { - if (CntxType == kCMMenuItemSelected) - { - // Handle the menu CntxMenuID, CntxMenuItem - // The submenu can be handle directly by gui_mac_handle_menu - // But what about the current menu, is the menu changed by - // ContextualMenuSelect - gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem); - } - else if (CntxMenuID == kCMShowHelpSelected) - { - // Should come up with the help - } - } - - // Restore original Port - SetPort(savePort); //OSX -} - -#if defined(FEAT_CW_EDITOR) || defined(PROTO) -// TODO: Is it need for MACOS_X? (Dany) - void -mch_post_buffer_write(buf_T *buf) -{ - GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec); - Send_KAHL_MOD_AE(buf); -} -#endif - -#ifdef FEAT_TITLE -/* - * Set the window title and icon. - * (The icon is not taken care of). - */ - void -gui_mch_settitle(char_u *title, char_u *icon) -{ - // TODO: Get vim to make sure maxlen (from p_titlelen) is smaller - // that 256. Even better get it to fit nicely in the titlebar. -#ifdef MACOS_CONVERT - CFStringRef windowTitle; - size_t windowTitleLen; -#else - char_u *pascalTitle; -#endif - - if (title == NULL) // nothing to do - return; - -#ifdef MACOS_CONVERT - windowTitleLen = STRLEN(title); - windowTitle = (CFStringRef)mac_enc_to_cfstring(title, windowTitleLen); - - if (windowTitle) - { - SetWindowTitleWithCFString(gui.VimWindow, windowTitle); - CFRelease(windowTitle); - } -#else - pascalTitle = C2Pascal_save(title); - if (pascalTitle != NULL) - { - SetWTitle(gui.VimWindow, pascalTitle); - vim_free(pascalTitle); - } -#endif -} -#endif - -/* - * Transferred from os_mac.c for MacOS X using os_unix.c prep work - */ - - int -C2PascalString(char_u *CString, Str255 *PascalString) -{ - char_u *PascalPtr = (char_u *) PascalString; - int len; - int i; - - PascalPtr[0] = 0; - if (CString == NULL) - return 0; - - len = STRLEN(CString); - if (len > 255) - len = 255; - - for (i = 0; i < len; i++) - PascalPtr[i+1] = CString[i]; - - PascalPtr[0] = len; - - return 0; -} - - int -GetFSSpecFromPath(char_u *file, FSSpec *fileFSSpec) -{ - // From FAQ 8-12 - Str255 filePascal; - CInfoPBRec myCPB; - OSErr err; - - (void) C2PascalString(file, &filePascal); - - myCPB.dirInfo.ioNamePtr = filePascal; - myCPB.dirInfo.ioVRefNum = 0; - myCPB.dirInfo.ioFDirIndex = 0; - myCPB.dirInfo.ioDrDirID = 0; - - err= PBGetCatInfo(&myCPB, false); - - // vRefNum, dirID, name - FSMakeFSSpec(0, 0, filePascal, fileFSSpec); - - // TODO: Use an error code mechanism - return 0; -} - -/* - * Convert a FSSpec to a full path - */ - -char_u *FullPathFromFSSpec_save(FSSpec file) -{ - /* - * TODO: Add protection for 256 char max. - */ - - CInfoPBRec theCPB; - char_u fname[256]; - char_u *filenamePtr = fname; - OSErr error; - int folder = 1; -#ifdef USE_UNIXFILENAME - SInt16 dfltVol_vRefNum; - SInt32 dfltVol_dirID; - FSRef refFile; - OSStatus status; - UInt32 pathSize = 256; - char_u pathname[256]; - char_u *path = pathname; -#else - Str255 directoryName; - char_u temporary[255]; - char_u *temporaryPtr = temporary; -#endif - -#ifdef USE_UNIXFILENAME - // Get the default volume - // TODO: Remove as this only work if Vim is on the Boot Volume - error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID); - - if (error) - return NULL; -#endif - - // Start filling fname with file.name - vim_strncpy(filenamePtr, &file.name[1], file.name[0]); - - // Get the info about the file specified in FSSpec - theCPB.dirInfo.ioFDirIndex = 0; - theCPB.dirInfo.ioNamePtr = file.name; - theCPB.dirInfo.ioVRefNum = file.vRefNum; - //theCPB.hFileInfo.ioDirID = 0; - theCPB.dirInfo.ioDrDirID = file.parID; - - // As ioFDirIndex = 0, get the info of ioNamePtr, - // which is relative to ioVrefNum, ioDirID - error = PBGetCatInfo(&theCPB, false); - - // If we are called for a new file we expect fnfErr - if ((error) && (error != fnfErr)) - return NULL; - - // Check if it's a file or folder - // default to file if file don't exist - if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error)) - folder = 0; // It's not a folder - else - folder = 1; - -#ifdef USE_UNIXFILENAME - /* - * The functions used here are available in Carbon, but do nothing on - * MacOS 8 and 9. - */ - if (error == fnfErr) - { - // If the file to be saved does not already exist, it isn't possible - // to convert its FSSpec into an FSRef. But we can construct an - // FSSpec for the file's parent folder (since we have its volume and - // directory IDs), and since that folder does exist, we can convert - // that FSSpec into an FSRef, convert the FSRef in turn into a path, - // and, finally, append the filename. - FSSpec dirSpec; - FSRef dirRef; - Str255 emptyFilename = "\p"; - error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum, - theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec); - if (error) - return NULL; - - error = FSpMakeFSRef(&dirSpec, &dirRef); - if (error) - return NULL; - - status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize); - if (status) - return NULL; - - STRCAT(path, "/"); - STRCAT(path, filenamePtr); - } - else - { - // If the file to be saved already exists, we can get its full path - // by converting its FSSpec into an FSRef. - error=FSpMakeFSRef(&file, &refFile); - if (error) - return NULL; - - status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize); - if (status) - return NULL; - } - - // Add a slash at the end if needed - if (folder) - STRCAT(path, "/"); - - return (vim_strsave(path)); -#else - // TODO: Get rid of all USE_UNIXFILENAME below - // Set ioNamePtr, it's the same area which is always reused. - theCPB.dirInfo.ioNamePtr = directoryName; - - // Trick for first entry, set ioDrParID to the first value - // we want for ioDrDirID - theCPB.dirInfo.ioDrParID = file.parID; - theCPB.dirInfo.ioDrDirID = file.parID; - - if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/)) - do - { - theCPB.dirInfo.ioFDirIndex = -1; - // theCPB.dirInfo.ioNamePtr = directoryName; Already done above. - theCPB.dirInfo.ioVRefNum = file.vRefNum; - // theCPB.dirInfo.ioDirID = irrelevant when ioFDirIndex = -1 - theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID; - - // As ioFDirIndex = -1, get the info of ioDrDirID, - // *ioNamePtr[0 TO 31] will be updated - error = PBGetCatInfo(&theCPB,false); - - if (error) - return NULL; - - // Put the new directoryName in front of the current fname - STRCPY(temporaryPtr, filenamePtr); - vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]); - STRCAT(filenamePtr, ":"); - STRCAT(filenamePtr, temporaryPtr); - } -#if 1 // def USE_UNIXFILENAME - while ((theCPB.dirInfo.ioDrParID != fsRtDirID) - /* && (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/); -#else - while (theCPB.dirInfo.ioDrDirID != fsRtDirID); -#endif - - // Get the information about the volume on which the file reside - theCPB.dirInfo.ioFDirIndex = -1; - // theCPB.dirInfo.ioNamePtr = directoryName; Already done above. - theCPB.dirInfo.ioVRefNum = file.vRefNum; - // theCPB.dirInfo.ioDirID = irrelevant when ioFDirIndex = -1 - theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID; - - // As ioFDirIndex = -1, get the info of ioDrDirID, - // *ioNamePtr[0 TO 31] will be updated - error = PBGetCatInfo(&theCPB,false); - - if (error) - return NULL; - - // For MacOS Classic always add the volume name - // For MacOS X add the volume name preceded by "Volumes" - // when we are not referring to the boot volume -#ifdef USE_UNIXFILENAME - if (file.vRefNum != dfltVol_vRefNum) -#endif - { - // Add the volume name - STRCPY(temporaryPtr, filenamePtr); - vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]); - STRCAT(filenamePtr, ":"); - STRCAT(filenamePtr, temporaryPtr); - -#ifdef USE_UNIXFILENAME - STRCPY(temporaryPtr, filenamePtr); - filenamePtr[0] = 0; // NULL terminate the string - STRCAT(filenamePtr, "Volumes:"); - STRCAT(filenamePtr, temporaryPtr); -#endif - } - - // Append final path separator if it's a folder - if (folder) - STRCAT(fname, ":"); - - // As we use Unix File Name for MacOS X convert it -#ifdef USE_UNIXFILENAME - // Need to insert leading / - // TODO: get the above code to use directly the / - STRCPY(&temporaryPtr[1], filenamePtr); - temporaryPtr[0] = '/'; - STRCPY(filenamePtr, temporaryPtr); - { - char *p; - for (p = fname; *p; p++) - if (*p == ':') - *p = '/'; - } -#endif - - return (vim_strsave(fname)); -#endif -} - -#if defined(USE_CARBONKEYHANDLER) || defined(PROTO) -/* - * Input Method Control functions. - */ - -/* - * Notify cursor position to IM. - */ - void -im_set_position(int row, int col) -{ -# if 0 - // TODO: Implement me! - im_start_row = row; - im_start_col = col; -# endif -} - -static ScriptLanguageRecord gTSLWindow; -static ScriptLanguageRecord gTSLInsert; -static ScriptLanguageRecord gTSLDefault = { 0, 0 }; - -static Component gTSCWindow; -static Component gTSCInsert; -static Component gTSCDefault; - -static int im_initialized = 0; - - static void -im_on_window_switch(int active) -{ - ScriptLanguageRecord *slptr = NULL; - OSStatus err; - - if (! gui.in_use) - return; - - if (im_initialized == 0) - { - im_initialized = 1; - - // save default TSM component (should be U.S.) to default - GetDefaultInputMethodOfClass(&gTSCDefault, &gTSLDefault, - kKeyboardInputMethodClass); - } - - if (active == TRUE) - { - im_is_active = TRUE; - ActivateTSMDocument(gTSMDocument); - slptr = &gTSLWindow; - - if (slptr) - { - err = SetDefaultInputMethodOfClass(gTSCWindow, slptr, - kKeyboardInputMethodClass); - if (err == noErr) - err = SetTextServiceLanguage(slptr); - - if (err == noErr) - KeyScript(slptr->fScript | smKeyForceKeyScriptMask); - } - } - else - { - err = GetTextServiceLanguage(&gTSLWindow); - if (err == noErr) - slptr = &gTSLWindow; - - if (slptr) - GetDefaultInputMethodOfClass(&gTSCWindow, slptr, - kKeyboardInputMethodClass); - - im_is_active = FALSE; - DeactivateTSMDocument(gTSMDocument); - } -} - -/* - * Set IM status on ("active" is TRUE) or off ("active" is FALSE). - */ - void -im_set_active(int active) -{ - ScriptLanguageRecord *slptr = NULL; - OSStatus err; - - if (!gui.in_use) - return; - - if (im_initialized == 0) - { - im_initialized = 1; - - // save default TSM component (should be U.S.) to default - GetDefaultInputMethodOfClass(&gTSCDefault, &gTSLDefault, - kKeyboardInputMethodClass); - } - - if (active == TRUE) - { - im_is_active = TRUE; - ActivateTSMDocument(gTSMDocument); - slptr = &gTSLInsert; - - if (slptr) - { - err = SetDefaultInputMethodOfClass(gTSCInsert, slptr, - kKeyboardInputMethodClass); - if (err == noErr) - err = SetTextServiceLanguage(slptr); - - if (err == noErr) - KeyScript(slptr->fScript | smKeyForceKeyScriptMask); - } - } - else - { - err = GetTextServiceLanguage(&gTSLInsert); - if (err == noErr) - slptr = &gTSLInsert; - - if (slptr) - GetDefaultInputMethodOfClass(&gTSCInsert, slptr, - kKeyboardInputMethodClass); - - // restore to default when switch to normal mode, so than we could - // enter commands easier - SetDefaultInputMethodOfClass(gTSCDefault, &gTSLDefault, - kKeyboardInputMethodClass); - SetTextServiceLanguage(&gTSLDefault); - - im_is_active = FALSE; - DeactivateTSMDocument(gTSMDocument); - } -} - -/* - * Get IM status. When IM is on, return not 0. Else return 0. - */ - int -im_get_status(void) -{ - if (! gui.in_use) - return 0; - - return im_is_active; -} - -#endif - - - -#if defined(FEAT_GUI_TABLINE) || defined(PROTO) -// drawer implementation -static MenuRef contextMenu = NULL; -enum -{ - kTabContextMenuId = 42 -}; - -// the caller has to CFRelease() the returned string - static CFStringRef -getTabLabel(tabpage_T *page) -{ - get_tabline_label(page, FALSE); -#ifdef MACOS_CONVERT - return (CFStringRef)mac_enc_to_cfstring(NameBuff, STRLEN(NameBuff)); -#else - // TODO: check internal encoding? - return CFStringCreateWithCString(kCFAllocatorDefault, (char *)NameBuff, - kCFStringEncodingMacRoman); -#endif -} - - -#define DRAWER_SIZE 150 -#define DRAWER_INSET 16 - -static ControlRef dataBrowser = NULL; - -// when the tabline is hidden, vim doesn't call update_tabline(). When -// the tabline is shown again, show_tabline() is called before update_tabline(), -// and because of this, the tab labels and vim's internal tabs are out of sync -// for a very short time. to prevent inconsistent state, we store the labels -// of the tabs, not pointers to the tabs (which are invalid for a short time). -static CFStringRef *tabLabels = NULL; -static int tabLabelsSize = 0; - -enum -{ - kTabsColumn = 'Tabs' -}; - - static int -getTabCount(void) -{ - tabpage_T *tp; - int numTabs = 0; - - FOR_ALL_TABPAGES(tp) - ++numTabs; - return numTabs; -} - -// data browser item display callback - static OSStatus -dbItemDataCallback(ControlRef browser, - DataBrowserItemID itemID, - DataBrowserPropertyID property /* column id */, - DataBrowserItemDataRef itemData, - Boolean changeValue) -{ - OSStatus status = noErr; - - // assert(property == kTabsColumn); // why is this violated?? - - // changeValue is true if we have a modifiable list and data was changed. - // In our case, it's always false. - // (that is: if (changeValue) updateInternalData(); else return - // internalData(); - if (!changeValue) - { - CFStringRef str; - - assert(itemID - 1 >= 0 && itemID - 1 < tabLabelsSize); - str = tabLabels[itemID - 1]; - status = SetDataBrowserItemDataText(itemData, str); - } - else - status = errDataBrowserPropertyNotSupported; - - return status; -} - -// data browser action callback - static void -dbItemNotificationCallback(ControlRef browser, - DataBrowserItemID item, - DataBrowserItemNotification message) -{ - switch (message) - { - case kDataBrowserItemSelected: - send_tabline_event(item); - break; - } -} - -// callbacks needed for contextual menu: - static void -dbGetContextualMenuCallback(ControlRef browser, - MenuRef *menu, - UInt32 *helpType, - CFStringRef *helpItemString, - AEDesc *selection) -{ - // on mac os 9: kCMHelpItemNoHelp, but it's not the same - *helpType = kCMHelpItemRemoveHelp; // OS X only ;-) - *helpItemString = NULL; - - *menu = contextMenu; -} - - static void -dbSelectContextualMenuCallback(ControlRef browser, - MenuRef menu, - UInt32 selectionType, - SInt16 menuID, - MenuItemIndex menuItem) -{ - if (selectionType == kCMMenuItemSelected) - { - MenuCommand command; - GetMenuItemCommandID(menu, menuItem, &command); - - // get tab that was selected when the context menu appeared - // (there is always one tab selected). TODO: check if the context menu - // isn't opened on an item but on empty space (has to be possible some - // way, the finder does it too ;-) ) - Handle items = NewHandle(0); - if (items != NULL) - { - int numItems; - - GetDataBrowserItems(browser, kDataBrowserNoItem, false, - kDataBrowserItemIsSelected, items); - numItems = GetHandleSize(items) / sizeof(DataBrowserItemID); - if (numItems > 0) - { - int idx; - DataBrowserItemID *itemsPtr; - - HLock(items); - itemsPtr = (DataBrowserItemID *)*items; - idx = itemsPtr[0]; - HUnlock(items); - send_tabline_menu_event(idx, command); - } - DisposeHandle(items); - } - } -} - -// focus callback of the data browser to always leave focus in vim - static OSStatus -dbFocusCallback(EventHandlerCallRef handler, EventRef event, void *data) -{ - assert(GetEventClass(event) == kEventClassControl - && GetEventKind(event) == kEventControlSetFocusPart); - - return paramErr; -} - - -// drawer callback to resize data browser to drawer size - static OSStatus -drawerCallback(EventHandlerCallRef handler, EventRef event, void *data) -{ - switch (GetEventKind(event)) - { - case kEventWindowBoundsChanged: // move or resize - { - UInt32 attribs; - GetEventParameter(event, kEventParamAttributes, typeUInt32, - NULL, sizeof(attribs), NULL, &attribs); - if (attribs & kWindowBoundsChangeSizeChanged) // resize - { - Rect r; - GetWindowBounds(drawer, kWindowContentRgn, &r); - SetRect(&r, 0, 0, r.right - r.left, r.bottom - r.top); - SetControlBounds(dataBrowser, &r); - SetDataBrowserTableViewNamedColumnWidth(dataBrowser, - kTabsColumn, r.right); - } - } - break; - } - - return eventNotHandledErr; -} - -// Load DataBrowserChangeAttributes() dynamically on tiger (and better). -// This way the code works on 10.2 and 10.3 as well (it doesn't have the -// blue highlights in the list view on these systems, though. Oh well.) - - -#import - -enum { kMyDataBrowserAttributeListViewAlternatingRowColors = (1 << 1) }; - - static OSStatus -myDataBrowserChangeAttributes(ControlRef inDataBrowser, - OptionBits inAttributesToSet, - OptionBits inAttributesToClear) -{ - long osVersion; - char *symbolName; - NSSymbol symbol = NULL; - OSStatus (*dataBrowserChangeAttributes)(ControlRef inDataBrowser, - OptionBits inAttributesToSet, OptionBits inAttributesToClear); - - Gestalt(gestaltSystemVersion, &osVersion); - if (osVersion < 0x1040) // only supported for 10.4 (and up) - return noErr; - - // C name mangling... - symbolName = "_DataBrowserChangeAttributes"; - if (!NSIsSymbolNameDefined(symbolName) - || (symbol = NSLookupAndBindSymbol(symbolName)) == NULL) - return noErr; - - dataBrowserChangeAttributes = NSAddressOfSymbol(symbol); - if (dataBrowserChangeAttributes == NULL) - return noErr; // well... - return dataBrowserChangeAttributes(inDataBrowser, - inAttributesToSet, inAttributesToClear); -} - - static void -initialise_tabline(void) -{ - Rect drawerRect = { 0, 0, 0, DRAWER_SIZE }; - DataBrowserCallbacks dbCallbacks; - EventTypeSpec focusEvent = {kEventClassControl, kEventControlSetFocusPart}; - EventTypeSpec resizeEvent = {kEventClassWindow, kEventWindowBoundsChanged}; - DataBrowserListViewColumnDesc colDesc; - - // drawers have to have compositing enabled - CreateNewWindow(kDrawerWindowClass, - kWindowStandardHandlerAttribute - | kWindowCompositingAttribute - | kWindowResizableAttribute - | kWindowLiveResizeAttribute, - &drawerRect, &drawer); - - SetThemeWindowBackground(drawer, kThemeBrushDrawerBackground, true); - SetDrawerParent(drawer, gui.VimWindow); - SetDrawerOffsets(drawer, kWindowOffsetUnchanged, DRAWER_INSET); - - - // create list view embedded in drawer - CreateDataBrowserControl(drawer, &drawerRect, kDataBrowserListView, - &dataBrowser); - - dbCallbacks.version = kDataBrowserLatestCallbacks; - InitDataBrowserCallbacks(&dbCallbacks); - dbCallbacks.u.v1.itemDataCallback = - NewDataBrowserItemDataUPP(dbItemDataCallback); - dbCallbacks.u.v1.itemNotificationCallback = - NewDataBrowserItemNotificationUPP(dbItemNotificationCallback); - dbCallbacks.u.v1.getContextualMenuCallback = - NewDataBrowserGetContextualMenuUPP(dbGetContextualMenuCallback); - dbCallbacks.u.v1.selectContextualMenuCallback = - NewDataBrowserSelectContextualMenuUPP(dbSelectContextualMenuCallback); - - SetDataBrowserCallbacks(dataBrowser, &dbCallbacks); - - SetDataBrowserListViewHeaderBtnHeight(dataBrowser, 0); // no header - SetDataBrowserHasScrollBars(dataBrowser, false, true); // only vertical - SetDataBrowserSelectionFlags(dataBrowser, - kDataBrowserSelectOnlyOne | kDataBrowserNeverEmptySelectionSet); - SetDataBrowserTableViewHiliteStyle(dataBrowser, - kDataBrowserTableViewFillHilite); - Boolean b = false; - SetControlData(dataBrowser, kControlEntireControl, - kControlDataBrowserIncludesFrameAndFocusTag, sizeof(b), &b); - - // enable blue background in data browser (this is only in 10.4 and vim - // has to support older osx versions as well, so we have to load this - // function dynamically) - myDataBrowserChangeAttributes(dataBrowser, - kMyDataBrowserAttributeListViewAlternatingRowColors, 0); - - // install callback that keeps focus in vim and away from the data browser - InstallControlEventHandler(dataBrowser, dbFocusCallback, 1, &focusEvent, - NULL, NULL); - - // install callback that keeps data browser at the size of the drawer - InstallWindowEventHandler(drawer, drawerCallback, 1, &resizeEvent, - NULL, NULL); - - // add "tabs" column to data browser - colDesc.propertyDesc.propertyID = kTabsColumn; - colDesc.propertyDesc.propertyType = kDataBrowserTextType; - - // add if items can be selected (?): kDataBrowserListViewSelectionColumn - colDesc.propertyDesc.propertyFlags = kDataBrowserDefaultPropertyFlags; - - colDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc; - colDesc.headerBtnDesc.minimumWidth = 100; - colDesc.headerBtnDesc.maximumWidth = 150; - colDesc.headerBtnDesc.titleOffset = 0; - colDesc.headerBtnDesc.titleString = CFSTR("Tabs"); - colDesc.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing; - colDesc.headerBtnDesc.btnFontStyle.flags = 0; // use default font - colDesc.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly; - - AddDataBrowserListViewColumn(dataBrowser, &colDesc, 0); - - // create tabline popup menu required by vim docs (see :he tabline-menu) - CreateNewMenu(kTabContextMenuId, 0, &contextMenu); - AppendMenuItemTextWithCFString(contextMenu, CFSTR("Close Tab"), 0, - TABLINE_MENU_CLOSE, NULL); - AppendMenuItemTextWithCFString(contextMenu, CFSTR("New Tab"), 0, - TABLINE_MENU_NEW, NULL); - AppendMenuItemTextWithCFString(contextMenu, CFSTR("Open Tab..."), 0, - TABLINE_MENU_OPEN, NULL); -} - - -/* - * Show or hide the tabline. - */ - void -gui_mch_show_tabline(int showit) -{ - if (showit == 0) - CloseDrawer(drawer, true); - else - OpenDrawer(drawer, kWindowEdgeRight, true); -} - -/* - * Return TRUE when tabline is displayed. - */ - int -gui_mch_showing_tabline(void) -{ - WindowDrawerState state = GetDrawerState(drawer); - - return state == kWindowDrawerOpen || state == kWindowDrawerOpening; -} - -/* - * Update the labels of the tabline. - */ - void -gui_mch_update_tabline(void) -{ - tabpage_T *tp; - int numTabs = getTabCount(); - int nr = 1; - int curtabidx = 1; - - // adjust data browser - if (tabLabels != NULL) - { - int i; - - for (i = 0; i < tabLabelsSize; ++i) - CFRelease(tabLabels[i]); - free(tabLabels); - } - tabLabels = (CFStringRef *)malloc(numTabs * sizeof(CFStringRef)); - tabLabelsSize = numTabs; - - for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr) - { - if (tp == curtab) - curtabidx = nr; - tabLabels[nr-1] = getTabLabel(tp); - } - - RemoveDataBrowserItems(dataBrowser, kDataBrowserNoItem, 0, NULL, - kDataBrowserItemNoProperty); - // data browser uses ids 1, 2, 3, ... numTabs per default, so we - // can pass NULL for the id array - AddDataBrowserItems(dataBrowser, kDataBrowserNoItem, numTabs, NULL, - kDataBrowserItemNoProperty); - - DataBrowserItemID item = curtabidx; - SetDataBrowserSelectedItems(dataBrowser, 1, &item, kDataBrowserItemsAssign); -} - -/* - * Set the current tab to "nr". First tab is 1. - */ - void -gui_mch_set_curtab(int nr) -{ - DataBrowserItemID item = nr; - SetDataBrowserSelectedItems(dataBrowser, 1, &item, kDataBrowserItemsAssign); - - // TODO: call something like this?: (or restore scroll position, or...) - RevealDataBrowserItem(dataBrowser, item, kTabsColumn, - kDataBrowserRevealOnly); -} - -#endif // FEAT_GUI_TABLINE diff --git a/src/if_mzsch.c b/src/if_mzsch.c index bfcdbea97ee753..7b5293670976e7 100644 --- a/src/if_mzsch.c +++ b/src/if_mzsch.c @@ -812,10 +812,6 @@ static guint timer_id = 0; #elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) static void timer_proc(XtPointer, XtIntervalId *); static XtIntervalId timer_id = (XtIntervalId)0; -#elif defined(FEAT_GUI_MAC) -pascal void timer_proc(EventLoopTimerRef, void *); -static EventLoopTimerRef timer_id = NULL; -static EventLoopTimerUPP timerUPP; #endif #if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL) // Win32 console and Unix @@ -852,9 +848,6 @@ timer_proc(gpointer data UNUSED) # elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) static void timer_proc(XtPointer timed_out UNUSED, XtIntervalId *interval_id UNUSED) -# elif defined(FEAT_GUI_MAC) - pascal void -timer_proc(EventLoopTimerRef theTimer UNUSED, void *userData UNUSED) # endif { scheme_check_threads(); @@ -877,10 +870,6 @@ setup_timer(void) timer_id = g_timeout_add((guint)p_mzq, (GSourceFunc)timer_proc, NULL); # elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) timer_id = XtAppAddTimeOut(app_context, p_mzq, timer_proc, NULL); -# elif defined(FEAT_GUI_MAC) - timerUPP = NewEventLoopTimerUPP(timer_proc); - InstallEventLoopTimer(GetMainEventLoop(), p_mzq * kEventDurationMillisecond, - p_mzq * kEventDurationMillisecond, timerUPP, NULL, &timer_id); # endif } @@ -893,9 +882,6 @@ remove_timer(void) g_source_remove(timer_id); # elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) XtRemoveTimeOut(timer_id); -# elif defined(FEAT_GUI_MAC) - RemoveEventLoopTimer(timer_id); - DisposeEventLoopTimerUPP(timerUPP); # endif timer_id = 0; } diff --git a/src/main.c b/src/main.c index 86156b7281faad..c87fdbfb550521 100644 --- a/src/main.c +++ b/src/main.c @@ -298,33 +298,6 @@ main params.want_full_screen = FALSE; #endif -#if defined(FEAT_GUI_MAC) && defined(MACOS_X_DARWIN) - // When the GUI is started from Finder, need to display messages in a - // message box. isatty(2) returns TRUE anyway, thus we need to check the - // name to know we're not started from a terminal. - if (gui.starting && (!isatty(2) || strcmp("/dev/console", ttyname(2)) == 0)) - { - params.want_full_screen = FALSE; - - // Avoid always using "/" as the current directory. Note that when - // started from Finder the arglist will be filled later in - // HandleODocAE() and "fname" will be NULL. - if (getcwd((char *)NameBuff, MAXPATHL) != NULL - && STRCMP(NameBuff, "/") == 0) - { - if (params.fname != NULL) - (void)vim_chdirfile(params.fname, "drop"); - else - { - expand_env((char_u *)"$HOME", NameBuff, MAXPATHL); - vim_chdir(NameBuff); - } - if (start_dir != NULL) - mch_dirname(start_dir, MAXPATHL); - } - } -#endif - /* * mch_init() sets up the terminal (window) for use. This must be * done after resetting full_screen, otherwise it may move the cursor. @@ -1843,18 +1816,6 @@ parse_command_name(mparm_T *parmp) initstr = gettail((char_u *)parmp->argv[0]); -#ifdef FEAT_GUI_MAC - // An issue has been seen when launching Vim in such a way that - // $PWD/$ARGV[0] or $ARGV[0] is not the absolute path to the - // executable or a symbolic link of it. Until this issue is resolved - // we prohibit the GUI from being used. - if (STRCMP(initstr, parmp->argv[0]) == 0) - disallow_gui = TRUE; - - // TODO: On MacOS X default to gui if argv[0] ends in: - // /Vim.app/Contents/MacOS/Vim -#endif - #ifdef FEAT_EVAL set_vim_var_string(VV_PROGNAME, initstr, -1); set_progpath((char_u *)parmp->argv[0]); diff --git a/src/misc2.c b/src/misc2.c index 3e16c3633d941a..0370bdf0d3a594 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -3341,7 +3341,7 @@ same_directory(char_u *f1, char_u *f2) } #if defined(FEAT_SESSION) || defined(FEAT_AUTOCHDIR) \ - || defined(MSWIN) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK) \ + || defined(MSWIN) || defined(FEAT_GUI_GTK) \ || defined(FEAT_NETBEANS_INTG) \ || defined(PROTO) /* diff --git a/src/mouse.c b/src/mouse.c index 56472a3f05b2ff..7af90494ffef65 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -116,7 +116,7 @@ find_end_of_word(pos_T *pos) #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \ || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \ - || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON) \ + || defined(FEAT_GUI_PHOTON) \ || defined(FEAT_TERM_POPUP_MENU) # define USE_POPUP_SETPOS # define NEED_VCOL2COL @@ -532,7 +532,7 @@ do_mouse( if (gui.in_use) { # if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \ - || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) + || defined(FEAT_GUI_PHOTON) if (!is_click) // Ignore right button release events, only shows the popup // menu on the button down event. diff --git a/src/option.h b/src/option.h index 7777bd689c74f3..421ee7acdd230b 100644 --- a/src/option.h +++ b/src/option.h @@ -701,9 +701,6 @@ EXTERN int p_lpl; // 'loadplugins' #if defined(DYNAMIC_LUA) EXTERN char_u *p_luadll; // 'luadll' #endif -#ifdef FEAT_GUI_MAC -EXTERN int p_macatsui; // 'macatsui' -#endif EXTERN int p_magic; // 'magic' EXTERN char_u *p_menc; // 'makeencoding' #ifdef FEAT_QUICKFIX diff --git a/src/optiondefs.h b/src/optiondefs.h index f1f1af3090f822..9afa84df5c5ce9 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -331,13 +331,8 @@ static struct vimoption options[] = #endif (char_u *)0L} SCTX_INIT}, {"antialias", "anti", P_BOOL|P_VI_DEF|P_VIM|P_RCLR, -#if defined(FEAT_GUI_MAC) - (char_u *)&p_antialias, PV_NONE, - {(char_u *)FALSE, (char_u *)FALSE} -#else (char_u *)NULL, PV_NONE, {(char_u *)FALSE, (char_u *)FALSE} -#endif SCTX_INIT}, {"arabic", "arab", P_BOOL|P_VI_DEF|P_VIM|P_CURSWANT, #ifdef FEAT_ARABIC @@ -1209,7 +1204,7 @@ static struct vimoption options[] = {"guioptions", "go", P_STRING|P_VI_DEF|P_RALL|P_FLAGLIST, #if defined(FEAT_GUI) (char_u *)&p_go, PV_NONE, -# if defined(UNIX) && !defined(FEAT_GUI_MAC) +# if defined(UNIX) {(char_u *)"aegimrLtT", (char_u *)0L} # else {(char_u *)"egmrLtT", (char_u *)0L} @@ -1618,13 +1613,8 @@ static struct vimoption options[] = #endif SCTX_INIT}, {"macatsui", NULL, P_BOOL|P_VI_DEF|P_RCLR, -#ifdef FEAT_GUI_MAC - (char_u *)&p_macatsui, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} -#else (char_u *)NULL, PV_NONE, {(char_u *)"", (char_u *)0L} -#endif SCTX_INIT}, {"magic", NULL, P_BOOL|P_VI_DEF, (char_u *)&p_magic, PV_NONE, diff --git a/src/os_mac.h b/src/os_mac.h index d052bb5d2744b1..6524609152013d 100644 --- a/src/os_mac.h +++ b/src/os_mac.h @@ -20,25 +20,6 @@ # include #endif -/* - * Macintosh machine-dependent things. - * - * Include the Mac header files, unless also compiling with X11 (the header - * files have many conflicts). - */ -#ifdef FEAT_GUI_MAC -# include // Apple calls it QuickDraw.h... -# include -# include -# include -# include -# include -# include -# include -# include -# include -#endif - /* * Unix interface */ diff --git a/src/os_mac_conv.c b/src/os_mac_conv.c index 6c52e7d20fe423..3daf74a48ae311 100644 --- a/src/os_mac_conv.c +++ b/src/os_mac_conv.c @@ -17,7 +17,7 @@ #include "vim.h" -#if !defined(FEAT_GUI_MAC) && !defined(PROTO) +#if !defined(PROTO) # include #endif diff --git a/src/os_unix.c b/src/os_unix.c index c9b3f92ffc99ce..0f61367f2a1075 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -2194,7 +2194,7 @@ mch_settitle(char_u *title, char_u *icon) if (get_x11_windis() == OK) type = 1; #else -# if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) \ +# if defined(FEAT_GUI_PHOTON) \ || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU) if (gui.in_use) type = 1; @@ -2229,7 +2229,7 @@ mch_settitle(char_u *title, char_u *icon) set_x11_title(title); // x11 #endif #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_HAIKU) \ - || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) + || defined(FEAT_GUI_PHOTON) else gui_mch_settitle(title, icon); #endif diff --git a/src/proto.h b/src/proto.h index e894987ba30c7d..e715ca41bc9a85 100644 --- a/src/proto.h +++ b/src/proto.h @@ -323,9 +323,6 @@ extern char *vim_SelFile(Widget toplevel, char *prompt, char *init_path, int (*s # ifdef FEAT_GUI_HAIKU # include "gui_haiku.pro" # endif -# ifdef FEAT_GUI_MAC -# include "gui_mac.pro" -# endif # ifdef FEAT_GUI_X11 # include "gui_x11.pro" # endif diff --git a/src/proto/gui_mac.pro b/src/proto/gui_mac.pro deleted file mode 100644 index 1fa34532b27015..00000000000000 --- a/src/proto/gui_mac.pro +++ /dev/null @@ -1,153 +0,0 @@ -/* gui_mac.c */ - -/* - * Mac specific prototypes - */ - -pascal Boolean WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn); -pascal void gui_mac_scroll_action(ControlHandle theControl, short partCode); -pascal void gui_mac_drag_thumb (ControlHandle theControl, short partCode); -void gui_mac_handle_event(EventRecord *event); -void gui_mac_doMouseDown(EventRecord *theEvent); -void gui_mac_do_key(EventRecord *theEvent); -void gui_mac_handle_menu(long menuChoice); -void gui_mac_focus_change(EventRecord *event); -void gui_mac_update(EventRecord *event); -short gui_mch_get_mac_menu_item_index(vimmenu_T *menu, vimmenu_T *parent); -int gui_mch_is_blinking(void); -int gui_mch_is_blink_off(void); -void gui_mch_set_blinking(long wait, long on, long off); -void gui_mch_stop_blink(int may_call_gui_update_cursor); -void gui_mch_start_blink(void); -void gui_mch_getmouse(int *x, int *y); -void gui_mch_setmouse(int x, int y); -void gui_mch_prepare(int *argc, char **argv); -int gui_mch_init_check(void); -int gui_mch_init(void); -void gui_mch_new_colors(void); -int gui_mch_open(void); -void gui_mch_exit(int); -void gui_mch_set_winsize(int width, int height, int min_width, int min_height, int base_width, int base_height); -int gui_mch_get_winpos(int *x, int *y); -void gui_mch_set_winpos(int x, int y); -void gui_mch_set_shellsize(int width, int height, int min_width, int min_height, int base_width, int base_height, int direction); -void gui_mch_get_screen_dimensions(int *screen_w, int *screen_h); -void gui_mch_set_text_area_pos(int x, int y, int w, int h); -void gui_mch_enable_scrollbar(scrollbar_T *sb, int flag); -void gui_mch_set_scrollbar_thumb(scrollbar_T *sb, long val, long size, long max); -void gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h); -int gui_mch_get_scrollbar_xpadding(void); -int gui_mch_get_scrollbar_ypadding(void); -void gui_mch_create_scrollbar(scrollbar_T *sb, int orient); -void gui_mch_destroy_scrollbar(scrollbar_T *sb); -int gui_mch_adjust_charheight(void); -int gui_mch_init_font(char_u *font_name, int fontset); -GuiFont gui_mch_get_font(char_u *name, int giveErrorIfMissing); -char_u *gui_mch_get_fontname(GuiFont font, char_u *name); -GuiFont gui_mac_find_font(char_u *font_name); -void gui_mch_set_font(GuiFont font); -int gui_mch_same_font(GuiFont f1, GuiFont f2); -void gui_mch_free_font(GuiFont font); -guicolor_T gui_mch_get_color(char_u *name); -guicolor_T gui_mch_get_rgb_color(int r, int g, int b); -void gui_mch_set_fg_color(guicolor_T color); -void gui_mch_set_bg_color(guicolor_T color); -void gui_mch_set_sp_color(guicolor_T color); -void gui_mch_draw_string(int row, int col, char_u *s, int len, int flags); -int gui_mch_haskey(char_u *name); -void gui_mch_beep(void); -void gui_mch_flash(int msec); -void gui_mch_invert_rectangle(int r, int c, int nr, int nc); -void gui_mch_iconify(void); -void gui_mch_settitle(char_u *title, char_u *icon); -void gui_mch_draw_hollow_cursor(guicolor_T color); -void gui_mch_draw_part_cursor(int w, int h, guicolor_T color); -void gui_mch_update(void); -int gui_mch_wait_for_chars(int wtime); -void gui_mch_flush(void); -void gui_mch_clear_block(int row1, int col1, int row2, int col2); -void gui_mch_clear_all(void); -void gui_mch_delete_lines(int row, int num_lines); -void gui_mch_insert_lines(int row, int num_lines); -void gui_mch_enable_menu(int flag); -void gui_mch_set_menu_pos(int x, int y, int w, int h); -/*void gui_mch_add_menu(vimmenu_T *menu, vimmenu_T *parent, int idx);*/ -void gui_mch_add_menu(vimmenu_T *menu, int pos); -/*void gui_mch_add_menu_item(vimmenu_T *menu, vimmenu_T *parent, int idx);*/ -void gui_mch_add_menu_item(vimmenu_T *menu, int idx); -void gui_mch_show_popupmenu(vimmenu_T *menu); -void gui_mch_destroy_menu(vimmenu_T *menu); -void gui_mch_menu_grey(vimmenu_T *menu, int grey); -void gui_mch_menu_hidden(vimmenu_T *menu, int hidden); -void gui_mch_draw_menubar(void); -int gui_mch_get_lightness(guicolor_T pixel); -guicolor_T gui_mch_get_rgb(guicolor_T pixel); -int gui_mch_get_mouse_x(void); -int gui_mch_get_mouse_y(void); -void gui_mch_setmouse(int x, int y); -void gui_mch_show_popupmenu(vimmenu_T *menu); -int gui_mch_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfltbutton, char_u *textfield, int ex_cmd); -char_u *gui_mch_browse(int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter); -void gui_mch_set_foreground(void); -void gui_mch_show_tabline(int showit); -int gui_mch_showing_tabline(void); -void gui_mch_update_tabline(void); -void gui_mch_set_curtab(int nr); - -char_u *C2Pascal_save(char_u *Cstring); -char_u *C2Pascal_save_and_remove_backslash(char_u *Cstring); -int_u EventModifiers2VimMouseModifiers(EventModifiers macModifiers); -char_u **new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error); - - -void gui_request_selection(void); -void gui_mch_lose_selection(void); -int gui_mch_own_selection(void); -void gui_mch_clear_selection(void); - -void gui_win_new_height(win_T *wp); -void gui_win_comp_pos(void); -void gui_win_free(win_T *wp); -void gui_win_alloc(win_T *wp); -void mch_post_buffer_write (buf_T *buf); - -void mch_errmsg(char *str); -void mch_display_error(void); -void clip_mch_lose_selection(Clipboard_T *cbd); -void clip_mch_request_selection(Clipboard_T *cbd); -void clip_mch_set_selection(Clipboard_T *cbd); -int clip_mch_own_selection(Clipboard_T *cbd); - -pascal OSErr FindProcessBySignature( const OSType targetType, - const OSType targetCreator, ProcessSerialNumberPtr psnPtr ); -OSErr InstallAEHandlers (void); -pascal OSErr HandleODocAE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon); -pascal OSErr Handle_aevt_oapp_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon); -pascal OSErr Handle_aevt_quit_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon); -pascal OSErr Handle_aevt_pdoc_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon); -pascal OSErr Handle_unknown_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon); -/* Shoulde we return MenuItemIndex? IMO yes, I did that for 5.7 ak*/ -short gui_mac_get_menu_item_index (vimmenu_T *pMenu); - -pascal OSErr Handle_KAHL_SRCH_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon); -pascal OSErr Handle_KAHL_MOD_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon); -pascal OSErr Handle_KAHL_GTTX_AE (const AppleEvent *theAEvent, AppleEvent *theReply, long refCon); -void Send_KAHL_MOD_AE (buf_T *buf); - -void gui_mac_doInContentClick(EventRecord *theEvent, WindowPtr whichWindow); -void gui_mac_doInDragClick(Point where, WindowPtr whichWindow); -void gui_mac_doInGrowClick(Point where, WindowPtr whichWindow); -void gui_mac_doUpdateEvent(EventRecord *event); -void gui_mac_doActivateEvent(EventRecord *event); -void gui_mac_doSuspendEvent(EventRecord *event); -void gui_mac_doKeyEvent(EventRecord *theEvent); -void gui_mac_doMouseDownEvent(EventRecord *theEvent); -void gui_mac_doMouseMovedEvent(EventRecord *event); -void gui_mac_doMouseUpEvent(EventRecord *theEvent); -void gui_mch_mousehide(int hide); - -int C2PascalString (char_u *CString, Str255 *PascalString); -int GetFSSpecFromPath ( char_u *file, FSSpec *fileFSSpec); -char_u *FullPathFromFSSpec_save (FSSpec file); - -/* vim: set ft=c : */ diff --git a/src/structs.h b/src/structs.h index a80de6a71f92e5..c94fa94e2c2402 100644 --- a/src/structs.h +++ b/src/structs.h @@ -2530,9 +2530,6 @@ struct file_buffer dev_t b_dev; // device number ino_t b_ino; // inode number #endif -#ifdef FEAT_CW_EDITOR - FSSpec b_FSSpec; // MacOS File Identification -#endif #ifdef VMS char b_fab_rfm; // Record format char b_fab_rat; // Record attribute @@ -3790,15 +3787,6 @@ struct VimMenu BPictureButton *button; # endif #endif -#ifdef FEAT_GUI_MAC -// MenuHandle id; -// short index; // the item index within the father menu - short menu_id; // the menu id to which this item belongs - short submenu_id; // the menu id of the children (could be - // get through some tricks) - MenuHandle menu_handle; - MenuHandle submenu_handle; -#endif #ifdef FEAT_GUI_PHOTON PtWidget_t *id; PtWidget_t *submenu_id; diff --git a/src/version.c b/src/version.c index 7411bc0d89e2f1..8ebd3e0adb347d 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1422, /**/ 1421, /**/ diff --git a/src/vim.h b/src/vim.h index 1001117b12cb79..a780ec9feff241 100644 --- a/src/vim.h +++ b/src/vim.h @@ -97,14 +97,12 @@ // Unless made through the Makefile enforce GUI on Mac #if defined(MACOS_X) && !defined(HAVE_CONFIG_H) # define UNIX -# define FEAT_GUI_MAC #endif #if defined(FEAT_GUI_MOTIF) \ || defined(FEAT_GUI_GTK) \ || defined(FEAT_GUI_ATHENA) \ || defined(FEAT_GUI_HAIKU) \ - || defined(FEAT_GUI_MAC) \ || defined(FEAT_GUI_MSWIN) \ || defined(FEAT_GUI_PHOTON) # define FEAT_GUI_ENABLED // also defined with NO_X11_INCLUDES @@ -2144,7 +2142,7 @@ typedef enum { // been seen at that stage. But it must be before globals.h, where error_ga // is declared. #if !defined(MSWIN) && !defined(FEAT_GUI_X11) && !defined(FEAT_GUI_HAIKU) \ - && !defined(FEAT_GUI_GTK) && !defined(FEAT_GUI_MAC) && !defined(PROTO) + && !defined(FEAT_GUI_GTK) && !defined(PROTO) # define mch_errmsg(str) fprintf(stderr, "%s", (str)) # define display_errors() fflush(stderr) # define mch_msg(str) printf("%s", (str)) @@ -2154,8 +2152,7 @@ typedef enum { # if defined(FEAT_EVAL) \ && (!defined(FEAT_GUI_MSWIN) \ - || !(defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME))) \ - && !(defined(FEAT_GUI_MAC) && defined(MACOS_CONVERT)) + || !(defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME))) // Whether IME is supported by im_get_status() defined in mbyte.c. // For Win32 GUI it's in gui_w32.c when FEAT_MBYTE_IME or GLOBAL_IME is defined. // for Mac it is in gui_mac.c for the GUI or in os_mac_conv.c when @@ -2166,8 +2163,7 @@ typedef enum { #if defined(FEAT_XIM) \ || defined(IME_WITHOUT_XIM) \ || (defined(FEAT_GUI_MSWIN) \ - && (defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME))) \ - || defined(FEAT_GUI_MAC) + && (defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME))) // im_set_active() is available # define HAVE_INPUT_METHOD #endif From 035d6e91bd83574cab5a913c5c3a924d9011696b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 11 Aug 2020 22:30:42 +0200 Subject: [PATCH 0137/1384] patch 8.2.1423: Vim9: find global function when looking for script-local Problem: Vim9: find global function when looking for script-local. Solution: Don't strip prefix if name starts with "s:". (closes #6688) --- src/testdir/test_vim9_func.vim | 9 +++++++++ src/userfunc.c | 4 ++-- src/version.c | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 4a020c9afa678c..772b52ab97b0db 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -203,6 +203,15 @@ def Test_global_local_function() assert_equal('local', Func()) END CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + def g:Funcy() + echo 'funcy' + enddef + s:Funcy() + END + CheckScriptFailure(lines, 'E117:') enddef func TakesOneArg(arg) diff --git a/src/userfunc.c b/src/userfunc.c index f38c978f4ef982..9ab5ffe5258faa 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -2132,8 +2132,8 @@ call_func( char_u *p = untrans_function_name(rfname); // If using Vim9 script try not local to the script. - // TODO: should not do this if the name started with "s:". - if (p != NULL) + // Don't do this if the name starts with "s:". + if (p != NULL && (funcname[0] != 's' || funcname[1] != ':')) fp = find_func(p, is_global, NULL); } diff --git a/src/version.c b/src/version.c index 8ebd3e0adb347d..f6257b58a86cca 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1423, /**/ 1422, /**/ From 040f975fc1de14ada5e0a7324bb5e51e461be2dd Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 11 Aug 2020 23:08:48 +0200 Subject: [PATCH 0138/1384] patch 8.2.1424: Mac build fails Problem: Mac build fails. Solution: Adjust configure to not fall back to Athena. Adjust some other files. --- src/auto/configure | 17 +++++++++++++++++ src/configure.ac | 15 +++++++++++++++ src/libvterm/src/state.c | 4 ++-- src/os_macosx.m | 2 +- src/version.c | 13 +++---------- 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/auto/configure b/src/auto/configure index fcb2f40e8cec53..5cef5554850b61 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -4744,6 +4744,10 @@ rm -f core conftest.err conftest.$ac_objext \ OS_EXTRA_SRC="os_macosx.m os_mac_conv.c"; OS_EXTRA_OBJ="objects/os_macosx.o objects/os_mac_conv.o" CPPFLAGS="$CPPFLAGS -DMACOS_X_DARWIN" + + if test -z "$with_x" -a "X$enable_gui" != Xmotif -a "X$enable_gui" != Xathena -a "X$enable_gui" != Xgtk2 -a "X$enable_gui" != Xgtk3; then + with_x=no + fi fi if test "$MACARCH" = "intel" -o "$MACARCH" = "both"; then @@ -9232,6 +9236,19 @@ $as_echo "Sorry, $enable_gui GUI is not supported" >&6; } SKIP_PHOTON=YES ;; esac +elif test "x$MACOS_X" = "xyes" -a "x$with_x" = "xno" ; then + case "$enable_gui_canon" in + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no GUI support" >&5 +$as_echo "no GUI support" >&6; } ;; + yes|"") { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes - automatic GUI support" >&5 +$as_echo "yes - automatic GUI support" >&6; } + gui_auto=yes ;; + auto) { $as_echo "$as_me:${as_lineno-$LINENO}: result: auto - disable GUI support for Mac OS" >&5 +$as_echo "auto - disable GUI support for Mac OS" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: Sorry, $enable_gui GUI is not supported" >&5 +$as_echo "Sorry, $enable_gui GUI is not supported" >&6; } + SKIP_CARBON=YES ;; + esac else case "$enable_gui_canon" in diff --git a/src/configure.ac b/src/configure.ac index 8a5216a8a3ceab..e17a74c9a76e5f 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -262,6 +262,12 @@ if test "`(uname) 2>/dev/null`" = Darwin; then dnl TODO: use -arch i386 on Intel machines dnl Removed -no-cpp-precomp, only for very old compilers. CPPFLAGS="$CPPFLAGS -DMACOS_X_DARWIN" + + dnl Assume we don't want X11 unless it was specifically asked for + dnl (--with-x) or Motif, Athena or GTK GUI is used. + if test -z "$with_x" -a "X$enable_gui" != Xmotif -a "X$enable_gui" != Xathena -a "X$enable_gui" != Xgtk2 -a "X$enable_gui" != Xgtk3; then + with_x=no + fi fi dnl Avoid a bug with -O2 with gcc 4.0.1. Symptom: malloc() reports double @@ -2421,6 +2427,15 @@ elif test "x$QNX" = "xyes" -a "x$with_x" = "xno" ; then SKIP_PHOTON=YES ;; esac +elif test "x$MACOS_X" = "xyes" -a "x$with_x" = "xno" ; then + case "$enable_gui_canon" in + no) AC_MSG_RESULT(no GUI support) ;; + yes|"") AC_MSG_RESULT(yes - automatic GUI support) + gui_auto=yes ;; + auto) AC_MSG_RESULT(auto - disable GUI support for Mac OS) ;; + *) AC_MSG_RESULT([Sorry, $enable_gui GUI is not supported]) + SKIP_CARBON=YES ;; + esac else case "$enable_gui_canon" in diff --git a/src/libvterm/src/state.c b/src/libvterm/src/state.c index 4fe3d7d20b6fde..390aa8dce4d8ea 100644 --- a/src/libvterm/src/state.c +++ b/src/libvterm/src/state.c @@ -133,7 +133,7 @@ static void scroll(VTermState *state, VTermRect rect, int downward, int rightwar if(rect.start_col == 0 && rect.end_col == state->cols && rightward == 0) { int height = rect.end_row - rect.start_row - abs(downward); int row; - VTermLineInfo zeroLineInfo = { 0 }; + VTermLineInfo zeroLineInfo = {0x0}; if(downward > 0) { memmove(state->lineinfo + rect.start_row, @@ -1813,7 +1813,7 @@ static int on_resize(int rows, int cols, void *user) } for( ; row < rows; row++) { - VTermLineInfo lineInfo = {0}; + VTermLineInfo lineInfo = {0x0}; newlineinfo[row] = lineInfo; } diff --git a/src/os_macosx.m b/src/os_macosx.m index 4c04395ea4184f..0ac59b4ccde9ec 100644 --- a/src/os_macosx.m +++ b/src/os_macosx.m @@ -33,7 +33,7 @@ * gui_mac.c are used then. TODO: remove those instead? * But for MacVim we do need these ones. */ -#if defined(FEAT_CLIPBOARD) && (!defined(FEAT_GUI_ENABLED) || defined(FEAT_GUI_MACVIM)) +#if defined(FEAT_CLIPBOARD) && (!defined(FEAT_GUI_ENABLED)) /* Used to identify clipboard data copied from Vim. */ diff --git a/src/version.c b/src/version.c index f6257b58a86cca..ec86fb4f52c02a 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1424, /**/ 1423, /**/ @@ -3954,17 +3956,8 @@ list_version(void) # else # if defined(MSWIN) msg_puts(_("with GUI.")); -# else -# if defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON - msg_puts(_("with Carbon GUI.")); -# else -# if defined(TARGET_API_MAC_OSX) && TARGET_API_MAC_OSX - msg_puts(_("with Cocoa GUI.")); -# else -# endif -# endif -# endif # endif +# endif # endif # endif # endif From 575f24b3f3d8cd8bfc2da402c2938c0c7ace7877 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Aug 2020 14:21:11 +0200 Subject: [PATCH 0139/1384] patch 8.2.1425: Vim9: cannot use call() without :call Problem: Vim9: cannot use call() without :call. Solution: Do not skip over "call(". (closes #6689) --- src/testdir/test_vim9_func.vim | 6 ++++++ src/version.c | 2 ++ src/vim9compile.c | 9 ++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 772b52ab97b0db..24078f56ed9e87 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -290,6 +290,12 @@ def Test_call_def_varargs() CheckScriptFailure(lines, 'E1013:') enddef +def Test_call_call() + let l = [3, 2, 1] + call('reverse', [l]) + assert_equal([1, 2, 3], l) +enddef + let s:value = '' def FuncOneDefArg(opt = 'text') diff --git a/src/version.c b/src/version.c index ec86fb4f52c02a..1ab7a618ce5dd3 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1425, /**/ 1424, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 72c26ce46ee409..53dca8057b6d92 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -6484,8 +6484,15 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx) cmdmod = save_cmdmod; // Skip ":call" to get to the function name. + p = ea.cmd; if (checkforcmd(&ea.cmd, "call", 3)) - ea.cmd = skipwhite(ea.cmd); + { + if (*ea.cmd == '(') + // not for "call()" + ea.cmd = p; + else + ea.cmd = skipwhite(ea.cmd); + } if (!starts_with_colon) { From a177344dc0c337e5b272c1c59d13964a8318bcfa Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Aug 2020 15:21:22 +0200 Subject: [PATCH 0140/1384] patch 8.2.1426: Vim9: cannot call autoload function in :def function Problem: Vim9: cannot call autoload function in :def function. Solution: Load the autoload script. (closes #6690) --- src/scriptfile.c | 2 +- src/testdir/test_vim9_expr.vim | 15 +++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 9 ++++++--- src/vim9execute.c | 21 +++++++++++++++++++++ 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/scriptfile.c b/src/scriptfile.c index 38215914d5aefd..320340f8d7e989 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1991,7 +1991,7 @@ autoload_name(char_u *name) if (scriptname == NULL) return NULL; STRCPY(scriptname, "autoload/"); - STRCAT(scriptname, name); + STRCAT(scriptname, name[0] == 'g' && name[1] == ':' ? name + 2: name); for (p = scriptname + 9; (p = vim_strchr(p, AUTOLOAD_CHAR)) != NULL; q = p, ++p) *p = '/'; diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 22ac442bcb4e72..3d16053561068e 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1752,6 +1752,21 @@ def Test_expr7_call() "vim9script", "let x = substitute ('x', 'x', 'x', 'x')" ], 'E121:') + + let auto_lines =<< trim END + def g:some#func(): string + return 'found' + enddef + END + mkdir('Xruntime/autoload', 'p') + writefile(auto_lines, 'Xruntime/autoload/some.vim') + let save_rtp = &rtp + &rtp = getcwd() .. '/Xruntime,' .. &rtp + assert_equal('found', g:some#func()) + assert_equal('found', some#func()) + + &rtp = save_rtp + delete('Xruntime', 'rf') enddef diff --git a/src/version.c b/src/version.c index 1ab7a618ce5dd3..6edd5ec2e89a5e 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1426, /**/ 1425, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 53dca8057b6d92..88108f4982bd65 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2214,6 +2214,7 @@ compile_call( int error = FCERR_NONE; ufunc_T *ufunc; int res = FAIL; + int is_autoload; // we can evaluate "has('name')" at compile time if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0) @@ -2258,7 +2259,8 @@ compile_call( if (compile_arguments(arg, cctx, &argcount) == FAIL) goto theend; - if (ASCII_ISLOWER(*name) && name[1] != ':') + is_autoload = vim_strchr(name, '#') != NULL; + if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload) { int idx; @@ -2281,8 +2283,9 @@ compile_call( // If the name is a variable, load it and use PCALL. // Not for g:Func(), we don't know if it is a variable or not. + // Not for eome#Func(), it will be loaded later. p = namebuf; - if (STRNCMP(namebuf, "g:", 2) != 0 + if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload && compile_load(&p, namebuf + varlen, cctx, FALSE) == OK) { garray_T *stack = &cctx->ctx_type_stack; @@ -2295,7 +2298,7 @@ compile_call( // A global function may be defined only later. Need to figure out at // runtime. Also handles a FuncRef at runtime. - if (STRNCMP(namebuf, "g:", 2) == 0) + if (STRNCMP(namebuf, "g:", 2) == 0 || is_autoload) res = generate_UCALL(cctx, name, argcount); else semsg(_(e_unknownfunc), namebuf); diff --git a/src/vim9execute.c b/src/vim9execute.c index 6e9b53d689ee23..fed7fed0e64fae 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -545,6 +545,15 @@ call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr) return OK; } +/* + * Return TRUE if an error was given or CTRL-C was pressed. + */ + static int +vim9_aborting(int prev_called_emsg) +{ + return called_emsg > prev_called_emsg || got_int || did_throw; +} + /* * Execute a function by "name". * This can be a builtin function or a user function. @@ -568,6 +577,18 @@ call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) } ufunc = find_func(name, FALSE, NULL); + + if (ufunc == NULL) + { + int called_emsg_before = called_emsg; + + if (script_autoload(name, TRUE)) + // loaded a package, search for the function again + ufunc = find_func(name, FALSE, NULL); + if (vim9_aborting(called_emsg_before)) + return FAIL; // bail out if loading the script caused an error + } + if (ufunc != NULL) return call_ufunc(ufunc, argcount, ectx, iptr); From 7c5ad34878a338f1db57337b5ca9f68c0c39424e Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Aug 2020 15:48:55 +0200 Subject: [PATCH 0141/1384] patch 8.2.1427: Vim9: cannot use a range with marks in :def function Problem: Vim9: cannot use a range with marks in :def function. Solution: Parse range after colon. (closes #6686) --- src/testdir/test_vim9_disassemble.vim | 45 ++++++++++++++++++--------- src/version.c | 2 ++ src/vim9compile.c | 2 +- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 5d9447d8ca11a5..3c7724df112b1a 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -83,20 +83,37 @@ enddef def Test_disassemble_exec_expr() let res = execute('disass s:EditExpand') - assert_match('\d*_EditExpand.*' .. - ' let filename = "file".*' .. - '\d PUSHS "file".*' .. - '\d STORE $0.*' .. - ' let filenr = 123.*' .. - '\d STORE 123 in $1.*' .. - ' edit the`=filename``=filenr`.txt.*' .. - '\d PUSHS "edit the".*' .. - '\d LOAD $0.*' .. - '\d LOAD $1.*' .. - '\d 2STRING stack\[-1\].*' .. - '\d PUSHS ".txt".*' .. - '\d EXECCONCAT 4.*' .. - '\d PUSHNR 0.*' .. + assert_match('\d*_EditExpand\_s*' .. + ' let filename = "file"\_s*' .. + '\d PUSHS "file"\_s*' .. + '\d STORE $0\_s*' .. + ' let filenr = 123\_s*' .. + '\d STORE 123 in $1\_s*' .. + ' edit the`=filename``=filenr`.txt\_s*' .. + '\d PUSHS "edit the"\_s*' .. + '\d LOAD $0\_s*' .. + '\d LOAD $1\_s*' .. + '\d 2STRING stack\[-1\]\_s*' .. + '\d\+ PUSHS ".txt"\_s*' .. + '\d\+ EXECCONCAT 4\_s*' .. + '\d\+ PUSHNR 0\_s*' .. + '\d\+ RETURN', + res) +enddef + +def s:YankRange() + norm! m[jjm] + :'[,']yank +enddef + +def Test_disassemble_yank_range() + let res = execute('disass s:YankRange') + assert_match('\d*_YankRange.*' .. + ' norm! m\[jjm\]\_s*' .. + '\d EXEC norm! m\[jjm\]\_s*' .. + ' :''\[,''\]yank\_s*' .. + '\d EXEC :''\[,''\]yank\_s*' .. + '\d PUSHNR 0\_s*' .. '\d RETURN', res) enddef diff --git a/src/version.c b/src/version.c index 6edd5ec2e89a5e..63c9c3d30b2425 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1427, /**/ 1426, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 88108f4982bd65..dfcff508fa6db5 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -6567,7 +6567,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx) * 'text'->func() should not be confused with 'a mark */ cmd = ea.cmd; - if (*cmd != '\'') + if (*cmd != '\'' || starts_with_colon) { ea.cmd = skip_range(ea.cmd, NULL); if (ea.cmd > cmd && !starts_with_colon) From ed677f5587af366f185f8922b7dde4a98c884328 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Aug 2020 16:38:10 +0200 Subject: [PATCH 0142/1384] patch 8.2.1428: Vim9: :def function does not abort on nested function error Problem: Vim9: :def function does not abort on nested function error. Solution: Check whether an error message was given. (closes #6691) --- src/testdir/test_vim9_script.vim | 18 ++++++++++++++++++ src/version.c | 2 ++ src/vim9execute.c | 13 +++++++++---- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index d30511c394d623..8742883e16952e 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1054,6 +1054,24 @@ def Test_throw_vimscript() CheckScriptSuccess(lines) enddef +def Test_error_in_nested_function() + # an error in a nested :function aborts executin in the calling :def function + let lines =<< trim END + vim9script + def Func() + Error() + g:test_var = 1 + enddef + func Error() abort + eval [][0] + endfunc + Func() + END + g:test_var = 0 + CheckScriptFailure(lines, 'E684:') + assert_equal(0, g:test_var) +enddef + def Test_cexpr_vimscript() # only checks line continuation set errorformat=File\ %f\ line\ %l diff --git a/src/version.c b/src/version.c index 63c9c3d30b2425..46d027d14ec632 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1428, /**/ 1427, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index fed7fed0e64fae..00adff3850d816 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -505,6 +505,7 @@ call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr) funcexe_T funcexe; int error; int idx; + int called_emsg_before = called_emsg; if (ufunc->uf_def_status == UF_TO_BE_COMPILED && compile_def_function(ufunc, FALSE, NULL) == FAIL) @@ -542,6 +543,9 @@ call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr) user_func_error(error, ufunc->uf_name); return FAIL; } + if (called_emsg > called_emsg_before) + // Error other than from calling the function itself. + return FAIL; return OK; } @@ -670,10 +674,11 @@ store_var(char_u *name, typval_T *tv) static int call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) { - int called_emsg_before = called_emsg; + int called_emsg_before = called_emsg; + int res; - if (call_by_name(name, argcount, ectx, iptr) == FAIL - && called_emsg == called_emsg_before) + res = call_by_name(name, argcount, ectx, iptr); + if (res == FAIL && called_emsg == called_emsg_before) { dictitem_T *v; @@ -690,7 +695,7 @@ call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr) } return call_partial(&v->di_tv, argcount, ectx); } - return OK; + return res; } /* From 17a836cbee6b8d8ff555f8e307f48a779908db41 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Aug 2020 17:35:58 +0200 Subject: [PATCH 0143/1384] patch 8.2.1429: Vim9: no error for missing white after : in dict Problem: Vim9: no error for missing white after : in dict. Solution: Check for white space. (closes #6671) Also check that there is no white before the :. --- src/testdir/test_vim9_expr.vim | 4 ++++ src/testdir/test_vim9_func.vim | 2 +- src/version.c | 2 ++ src/vim9compile.c | 13 ++++++++++--- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 3d16053561068e..a942dd4dea0ccf 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1494,6 +1494,10 @@ def Test_expr7_dict() mixed = #{a: 234} mixed = #{} + call CheckDefFailure(["let x = #{a:8}"], 'E1069:') + call CheckDefFailure(["let x = #{a : 8}"], 'E1068:') + call CheckDefFailure(["let x = #{a :8}"], 'E1068:') + call CheckDefFailure(["let x = #{8: 8}"], 'E1014:') call CheckDefFailure(["let x = #{xxx}"], 'E720:') call CheckDefFailure(["let x = #{xxx: 1", "let y = 2"], 'E722:') diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 24078f56ed9e87..1f9768ff9acc6e 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -774,7 +774,7 @@ func Test_InternalFuncRetType() enddef def RetListAny(): list - return items({'k' : 'v'}) + return items({'k': 'v'}) enddef def RetListString(): list diff --git a/src/version.c b/src/version.c index 46d027d14ec632..b290fdcb1bbd60 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1429, /**/ 1428, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index dfcff508fa6db5..502c66f3726236 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2593,14 +2593,21 @@ compile_dict(char_u **arg, cctx_T *cctx, int literal) } } - *arg = skipwhite(*arg); if (**arg != ':') { - semsg(_(e_missing_dict_colon), *arg); + if (*skipwhite(*arg) == ':') + semsg(_(e_no_white_before), ":"); + else + semsg(_(e_missing_dict_colon), *arg); return FAIL; } - whitep = *arg + 1; + if (!IS_WHITE_OR_NUL(*whitep)) + { + semsg(_(e_white_after), ":"); + return FAIL; + } + *arg = skipwhite(*arg + 1); if (may_get_next_line(whitep, arg, cctx) == FAIL) { From db199216e81865350a8d56a603bb86cab672bfad Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Aug 2020 18:01:53 +0200 Subject: [PATCH 0144/1384] patch 8.2.1430: Vim9: error for missing comma instead of extra white space Problem: Vim9: error for missing comma instead of extra white space. Solution: Check if comma can be found after white space. (closes #6668) Also check for extra white space in literal dict. (closes #6670) --- src/dict.c | 9 +++++++-- src/list.c | 7 ++++++- src/testdir/test_vim9_expr.vim | 21 +++++++++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 5 +++++ 5 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/dict.c b/src/dict.c index b381d476dc80ed..b6c9016342d220 100644 --- a/src/dict.c +++ b/src/dict.c @@ -781,7 +781,7 @@ get_literal_key(char_u **arg, typval_T *tv) tv->v_type = VAR_STRING; tv->vval.v_string = vim_strnsave(*arg, p - *arg); - *arg = skipwhite(p); + *arg = p; return OK; } @@ -845,7 +845,12 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal) if (**arg != ':') { if (evaluate) - semsg(_(e_missing_dict_colon), *arg); + { + if (*skipwhite(*arg) == ':') + semsg(_(e_no_white_before), ":"); + else + semsg(_(e_missing_dict_colon), *arg); + } clear_tv(&tvkey); goto failret; } diff --git a/src/list.c b/src/list.c index 14a31bcfb71b43..212d8272adc616 100644 --- a/src/list.c +++ b/src/list.c @@ -1219,7 +1219,12 @@ eval_list(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int do_error) if (!had_comma) { if (do_error) - semsg(_("E696: Missing comma in List: %s"), *arg); + { + if (**arg == ',') + semsg(_(e_no_white_before), ","); + else + semsg(_("E696: Missing comma in List: %s"), *arg); + } goto failret; } } diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index a942dd4dea0ccf..e963d9471ddfec 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1383,7 +1383,10 @@ def Test_expr7_list() call CheckDefExecFailure(["let x = g:anint[3]"], 'E714:') call CheckDefFailure(["let x = g:list_mixed[xxx]"], 'E1001:') + call CheckDefFailure(["let x = [1,2,3]"], 'E1069:') + call CheckDefFailure(["let x = [1 ,2, 3]"], 'E1068:') + call CheckDefExecFailure(["let x = g:list_mixed['xx']"], 'E1029:') call CheckDefFailure(["let x = g:list_mixed["], 'E1097:') call CheckDefFailure(["let x = g:list_mixed[0"], 'E1097:') @@ -1422,6 +1425,12 @@ def Test_expr7_list_vim9script() let l = [11,22] END CheckScriptFailure(lines, 'E1069:') + + lines =<< trim END + vim9script + let l = [11 , 22] + END + CheckScriptFailure(lines, 'E1068:') enddef def Test_expr7_lambda() @@ -1556,6 +1565,18 @@ def Test_expr7_dict_vim9script() let d = #{one: 1,two: 2} END CheckScriptFailure(lines, 'E1069:') + + lines =<< trim END + vim9script + let d = #{one : 1} + END + CheckScriptFailure(lines, 'E1068:') + + lines =<< trim END + vim9script + let d = #{one:1} + END + CheckScriptFailure(lines, 'E1069:') enddef let g:oneString = 'one' diff --git a/src/version.c b/src/version.c index b290fdcb1bbd60..7bafa94330cf26 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1430, /**/ 1429, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 502c66f3726236..6c43ad2f919385 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2394,6 +2394,11 @@ compile_list(char_u **arg, cctx_T *cctx) semsg(_(e_list_end), *arg); return FAIL; } + if (*p == ',') + { + semsg(_(e_no_white_before), ","); + return FAIL; + } if (*p == ']') { ++p; From c3d6e8a46a8fc5de622e8df9dbd25edd03e00c5b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Aug 2020 18:34:28 +0200 Subject: [PATCH 0145/1384] patch 8.2.1431: Vim9: no error for white space before comma in dict Problem: Vim9: no error for white space before comma in dict. Solution: Check for extra white space. (closes #6674) --- src/dict.c | 7 ++++++- src/testdir/test_vim9_expr.vim | 7 +++++++ src/version.c | 2 ++ src/vim9compile.c | 5 +++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/dict.c b/src/dict.c index b6c9016342d220..a5569e68b61f0d 100644 --- a/src/dict.c +++ b/src/dict.c @@ -922,7 +922,12 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal) if (!had_comma) { if (evaluate) - semsg(_(e_missing_dict_comma), *arg); + { + if (**arg == ',') + semsg(_(e_no_white_before), ","); + else + semsg(_(e_missing_dict_comma), *arg); + } goto failret; } } diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index e963d9471ddfec..09792effbd7fdb 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1506,6 +1506,7 @@ def Test_expr7_dict() call CheckDefFailure(["let x = #{a:8}"], 'E1069:') call CheckDefFailure(["let x = #{a : 8}"], 'E1068:') call CheckDefFailure(["let x = #{a :8}"], 'E1068:') + call CheckDefFailure(["let x = #{a: 8 , b: 9}"], 'E1068:') call CheckDefFailure(["let x = #{8: 8}"], 'E1014:') call CheckDefFailure(["let x = #{xxx}"], 'E720:') @@ -1577,6 +1578,12 @@ def Test_expr7_dict_vim9script() let d = #{one:1} END CheckScriptFailure(lines, 'E1069:') + + lines =<< trim END + vim9script + let d = #{one: 1 , two: 2} + END + CheckScriptFailure(lines, 'E1068:') enddef let g:oneString = 'one' diff --git a/src/version.c b/src/version.c index 7bafa94330cf26..06fce6e7f81afb 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1431, /**/ 1430, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index 6c43ad2f919385..8b58d968898a26 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2638,6 +2638,11 @@ compile_dict(char_u **arg, cctx_T *cctx, int literal) semsg(_(e_missing_dict_comma), *arg); goto failret; } + if (IS_WHITE_OR_NUL(*whitep)) + { + semsg(_(e_no_white_before), ","); + return FAIL; + } whitep = *arg + 1; *arg = skipwhite(*arg + 1); } From 6d91bcb4d23b5c6a0be72c384beaf385e2d9d606 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 12 Aug 2020 18:50:36 +0200 Subject: [PATCH 0146/1384] patch 8.2.1432: various inconsistencies in test files Problem: Various inconsistencies in test files. Solution: Add modelines where they were missing. Use Check commands instead of silently skipping over tests. Adjust indents and comments. (Ken Takata, closes #6695) --- src/testdir/test_arglist.vim | 10 +- src/testdir/test_assert.vim | 2 + src/testdir/test_autochdir.vim | 2 + src/testdir/test_autocmd.vim | 28 +- src/testdir/test_autoload.vim | 2 + src/testdir/test_balloon.vim | 2 + src/testdir/test_balloon_gui.vim | 2 + src/testdir/test_behave.vim | 2 + src/testdir/test_blockedit.vim | 1 - src/testdir/test_breakindent.vim | 80 +- src/testdir/test_bufline.vim | 2 + src/testdir/test_bufwintabinfo.vim | 3 + src/testdir/test_cd.vim | 2 + src/testdir/test_changedtick.vim | 2 + src/testdir/test_changelist.vim | 6 +- src/testdir/test_channel.vim | 4 +- src/testdir/test_checkpath.vim | 2 + src/testdir/test_cindent.vim | 1 - src/testdir/test_cjk_linebreak.vim | 4 + src/testdir/test_clientserver.vim | 2 +- src/testdir/test_close_count.vim | 4 +- src/testdir/test_cmdline.vim | 36 +- src/testdir/test_command_count.vim | 2 + src/testdir/test_comparators.vim | 4 + src/testdir/test_compiler.vim | 2 + src/testdir/test_crypt.vim | 2 + src/testdir/test_cursorline.vim | 2 + src/testdir/test_curswant.vim | 2 + src/testdir/test_debugger.vim | 2 + src/testdir/test_delete.vim | 2 + src/testdir/test_diffmode.vim | 6 +- src/testdir/test_digraph.vim | 8 +- src/testdir/test_display.vim | 3 + src/testdir/test_edit.vim | 46 +- src/testdir/test_environ.vim | 4 + src/testdir/test_erasebackword.vim | 3 + src/testdir/test_escaped_glob.vim | 12 +- src/testdir/test_ex_equal.vim | 2 + src/testdir/test_ex_undo.vim | 2 + src/testdir/test_ex_z.vim | 2 + src/testdir/test_exec_while_if.vim | 2 + src/testdir/test_exists.vim | 1 + src/testdir/test_exists_autocmd.vim | 2 + src/testdir/test_exit.vim | 2 + src/testdir/test_expand_dllpath.vim | 4 + src/testdir/test_expr_utf8.vim | 2 + src/testdir/test_feedkeys.vim | 2 + src/testdir/test_file_size.vim | 11 +- src/testdir/test_fileformat.vim | 1 + src/testdir/test_filter_cmd.vim | 2 + src/testdir/test_find_complete.vim | 2 + src/testdir/test_findfile.vim | 2 + src/testdir/test_fixeol.vim | 3 + src/testdir/test_flatten.vim | 3 + src/testdir/test_fnameescape.vim | 2 +- src/testdir/test_fold.vim | 4 +- src/testdir/test_functions.vim | 32 +- src/testdir/test_ga.vim | 1 + src/testdir/test_getcwd.vim | 4 + src/testdir/test_getvar.vim | 2 + src/testdir/test_glob2regpat.vim | 2 + src/testdir/test_global.vim | 2 + src/testdir/test_gui.vim | 36 +- src/testdir/test_gui_init.vim | 2 + src/testdir/test_highlight.vim | 16 +- src/testdir/test_hlsearch.vim | 8 +- src/testdir/test_iminsert.vim | 5 +- src/testdir/test_increment_dbcs.vim | 1 + src/testdir/test_ins_complete.vim | 2 + src/testdir/test_interrupt.vim | 2 + src/testdir/test_job_fails.vim | 15 +- src/testdir/test_join.vim | 2 + src/testdir/test_json.vim | 2 + src/testdir/test_jumplist.vim | 8 +- src/testdir/test_jumps.vim | 4 + src/testdir/test_lambda.vim | 6 +- src/testdir/test_langmap.vim | 2 + src/testdir/test_largefile.vim | 2 + src/testdir/test_lineending.vim | 3 + src/testdir/test_listchars.vim | 2 + src/testdir/test_listener.vim | 18 +- src/testdir/test_listlbr.vim | 4 +- src/testdir/test_listlbr_utf8.vim | 4 +- src/testdir/test_makeencoding.vim | 2 + src/testdir/test_man.vim | 2 + src/testdir/test_mapping.vim | 13 +- src/testdir/test_marks.vim | 1 + src/testdir/test_matchadd_conceal.vim | 2 + src/testdir/test_matchadd_conceal_utf8.vim | 2 + src/testdir/test_memory_usage.vim | 2 + src/testdir/test_menu.vim | 4 +- src/testdir/test_messages.vim | 10 +- src/testdir/test_mksession.vim | 21 +- src/testdir/test_modeline.vim | 12 +- src/testdir/test_nested_function.vim | 13 +- src/testdir/test_number.vim | 2 + src/testdir/test_options.vim | 19 +- src/testdir/test_packadd.vim | 9 +- src/testdir/test_partial.vim | 43 +- src/testdir/test_paste.vim | 4 +- src/testdir/test_plus_arg_edit.vim | 1 + src/testdir/test_preview.vim | 1 + src/testdir/test_profile.vim | 2 + src/testdir/test_prompt_buffer.vim | 20 +- src/testdir/test_quickfix.vim | 850 ++++++++++----------- src/testdir/test_quotestar.vim | 4 +- src/testdir/test_random.vim | 2 + src/testdir/test_recover.vim | 2 + src/testdir/test_regex_char_classes.vim | 2 + src/testdir/test_regexp_latin.vim | 1 + src/testdir/test_registers.vim | 2 - src/testdir/test_rename.vim | 2 + src/testdir/test_retab.vim | 3 + src/testdir/test_scriptnames.vim | 2 + src/testdir/test_scroll_opt.vim | 3 +- src/testdir/test_scrollbind.vim | 3 + src/testdir/test_search_stat.vim | 2 + src/testdir/test_searchpos.vim | 2 + src/testdir/test_set.vim | 2 + src/testdir/test_sha256.vim | 2 + src/testdir/test_shift.vim | 2 + src/testdir/test_shortpathname.vim | 2 + src/testdir/test_signs.vim | 2 + src/testdir/test_sort.vim | 6 +- src/testdir/test_sound.vim | 2 + src/testdir/test_source_utf8.vim | 3 + src/testdir/test_spellfile.vim | 2 + src/testdir/test_startup.vim | 17 +- src/testdir/test_startup_utf8.vim | 8 +- src/testdir/test_stat.vim | 19 +- src/testdir/test_suspend.vim | 9 +- src/testdir/test_swap.vim | 14 +- src/testdir/test_syntax.vim | 17 +- src/testdir/test_tab.vim | 2 + src/testdir/test_tabline.vim | 1 + src/testdir/test_tagcase.vim | 2 + src/testdir/test_tagjump.vim | 14 +- src/testdir/test_taglist.vim | 11 +- src/testdir/test_termcodes.vim | 1 - src/testdir/test_termencoding.vim | 2 + src/testdir/test_terminal.vim | 4 +- src/testdir/test_terminal2.vim | 3 +- src/testdir/test_terminal3.vim | 2 + src/testdir/test_terminal_fail.vim | 22 +- src/testdir/test_true_false.vim | 2 + src/testdir/test_utf8_comparisons.vim | 2 + src/testdir/test_vartabs.vim | 4 +- src/testdir/test_version.vim | 2 + src/testdir/test_vim9_expr.vim | 2 + src/testdir/test_winbar.vim | 1 + src/testdir/test_winbuf_close.vim | 1 + src/testdir/test_window_cmd.vim | 6 +- src/testdir/test_window_id.vim | 1 + src/testdir/test_windows_home.vim | 2 + src/testdir/test_wnext.vim | 2 + src/testdir/test_wordcount.vim | 2 + src/testdir/test_writefile.vim | 10 +- src/testdir/test_xxd.vim | 3 + src/version.c | 2 + 159 files changed, 942 insertions(+), 873 deletions(-) diff --git a/src/testdir/test_arglist.vim b/src/testdir/test_arglist.vim index 198ca989a09a55..820d8b9695f7b0 100644 --- a/src/testdir/test_arglist.vim +++ b/src/testdir/test_arglist.vim @@ -242,11 +242,11 @@ endfunc func Test_args_with_quote() " Only on Unix can a file name include a double quote. - if has('unix') - args \"foobar - call assert_equal('"foobar', argv(0)) - %argdelete - endif + CheckUnix + + args \"foobar + call assert_equal('"foobar', argv(0)) + %argdelete endfunc " Test for 0argadd and 0argedit diff --git a/src/testdir/test_assert.vim b/src/testdir/test_assert.vim index 416060528cc6e3..a3b45a17001331 100644 --- a/src/testdir/test_assert.vim +++ b/src/testdir/test_assert.vim @@ -374,3 +374,5 @@ func Test_zz_quit_detected() " Verify that if a test function ends Vim the test script detects this. quit endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_autochdir.vim b/src/testdir/test_autochdir.vim index 1473854c97d342..d36d32609266cc 100644 --- a/src/testdir/test_autochdir.vim +++ b/src/testdir/test_autochdir.vim @@ -24,3 +24,5 @@ func Test_set_filename() call chdir(cwd) call delete('samples/Xtest') endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index e6c7ec03c342e6..ca8cc04c2d42b9 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -70,9 +70,7 @@ if has('timers') endfunc func Test_cursorhold_insert_with_timer_interrupt() - if !has('job') - return - endif + CheckFeature job " Need to move the cursor. call feedkeys("ggG", "xt") @@ -535,9 +533,7 @@ func s:AutoCommandOptionSet(match) endfunc func Test_OptionSet() - if !has("eval") || !exists("+autochdir") - return - endif + CheckOption autochdir badd test_autocmd.vim @@ -1778,12 +1774,11 @@ func Test_nocatch_wipe_all_buffers() endfunc func Test_nocatch_wipe_dummy_buffer() - if has('quickfix') - " Nasty autocommand: wipe buffer on any event. - au * x bwipe - call assert_fails('lv½ /x', 'E937') - au! - endif + CheckFeature quickfix + " Nasty autocommand: wipe buffer on any event. + au * x bwipe + call assert_fails('lv½ /x', 'E937') + au! endfunc function s:Before_test_dirchanged() @@ -1834,9 +1829,7 @@ function Test_dirchanged_local() endfunc function Test_dirchanged_auto() - if !exists('+autochdir') - return - endif + CheckOption autochdir call s:Before_test_dirchanged() call test_autochdir() autocmd test_dirchanged DirChanged auto call add(s:li, "auto:") @@ -2087,9 +2080,8 @@ endfunc " - FileReadPost decompress the file func Test_ReadWrite_Autocmds() " Run this test only on Unix-like systems and if gzip is available - if !has('unix') || !executable("gzip") - return - endif + CheckUnix + CheckExecutable gzip " Make $GZIP empty, "-v" would cause trouble. let $GZIP = "" diff --git a/src/testdir/test_autoload.vim b/src/testdir/test_autoload.vim index 57967bf64fb2cc..384ee1a3286ef6 100644 --- a/src/testdir/test_autoload.vim +++ b/src/testdir/test_autoload.vim @@ -22,3 +22,5 @@ func Test_autoload_vim9script() call assert_equal('some', auto9#getsome()) call assert_equal(49, auto9#add42(7)) endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_balloon.vim b/src/testdir/test_balloon.vim index bb22f7bf2e7d2f..319e54601ea05a 100644 --- a/src/testdir/test_balloon.vim +++ b/src/testdir/test_balloon.vim @@ -64,3 +64,5 @@ func Test_balloon_eval_term_visual() call StopVimInTerminal(buf) call delete('XTest_beval_visual') endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_balloon_gui.vim b/src/testdir/test_balloon_gui.vim index 70a88f36f167dd..d01114c1c6f4ad 100644 --- a/src/testdir/test_balloon_gui.vim +++ b/src/testdir/test_balloon_gui.vim @@ -17,3 +17,5 @@ func Test_balloon_show_gui() sleep 10m call balloon_show('') endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_behave.vim b/src/testdir/test_behave.vim index c26bfe7ce302ee..72411b4870f364 100644 --- a/src/testdir/test_behave.vim +++ b/src/testdir/test_behave.vim @@ -27,3 +27,5 @@ endfunc func Test_behave_error() call assert_fails('behave x', 'E475:') endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_blockedit.vim b/src/testdir/test_blockedit.vim index 180524cd73b72b..de56f23cbbc5e0 100644 --- a/src/testdir/test_blockedit.vim +++ b/src/testdir/test_blockedit.vim @@ -1,5 +1,4 @@ " Test for block inserting -" func Test_blockinsert_indent() new diff --git a/src/testdir/test_breakindent.vim b/src/testdir/test_breakindent.vim index 30c44f4dd660e4..42b8c8cf254c86 100644 --- a/src/testdir/test_breakindent.vim +++ b/src/testdir/test_breakindent.vim @@ -46,9 +46,7 @@ endfunc func Test_breakindent01_vartabs() " like 01 but with vartabs feature - if !has("vartabs") - return - endif + CheckFeature vartabs call s:test_windows('setl briopt=min:0 vts=4') let lines = s:screen_lines(line('.'),8) let expect = [ @@ -75,9 +73,7 @@ func Test_breakindent02() endfunc func Test_breakindent02_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs " simple breakindent test with showbreak set call s:test_windows('setl briopt=min:0 sbr=>> vts=4') let lines = s:screen_lines(line('.'),8) @@ -106,9 +102,7 @@ endfunc func Test_breakindent03_vartabs() " simple breakindent test with showbreak set and briopt including sbr - if !has("vartabs") - return - endif + CheckFeature vartabs call s:test_windows('setl briopt=sbr,min:0 sbr=++ vts=4') let lines = s:screen_lines(line('.'),8) let expect = [ @@ -139,9 +133,7 @@ endfunc func Test_breakindent04_vartabs() " breakindent set with min width 18 - if !has("vartabs") - return - endif + CheckFeature vartabs call s:test_windows('setl sbr= briopt=min:18 vts=4') let lines = s:screen_lines(line('.'),8) let expect = [ @@ -169,9 +161,7 @@ endfunc func Test_breakindent05_vartabs() " breakindent set and shift by 2 - if !has("vartabs") - return - endif + CheckFeature vartabs call s:test_windows('setl briopt=shift:2,min:0 vts=4') let lines = s:screen_lines(line('.'),8) let expect = [ @@ -198,9 +188,7 @@ endfunc func Test_breakindent06_vartabs() " breakindent set and shift by -1 - if !has("vartabs") - return - endif + CheckFeature vartabs call s:test_windows('setl briopt=shift:-1,min:0 vts=4') let lines = s:screen_lines(line('.'),8) let expect = [ @@ -227,9 +215,7 @@ func Test_breakindent07() endfunc func Test_breakindent07_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs " breakindent set and shift by 1, Number set sbr=? and briopt:sbr call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 cpo+=n vts=4') let lines = s:screen_lines(line('.'),10) @@ -258,9 +244,7 @@ func Test_breakindent07a() endfunc func Test_breakindent07a_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs " breakindent set and shift by 1, Number set sbr=? and briopt:sbr call s:test_windows('setl briopt=shift:1,sbr,min:0 nu sbr=? nuw=4 vts=4') let lines = s:screen_lines(line('.'),10) @@ -293,9 +277,7 @@ func Test_breakindent08() endfunc func Test_breakindent08_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list cpo+=n ts=4 vts=4') " make sure, cache is invalidated! @@ -327,9 +309,7 @@ func Test_breakindent08a() endfunc func Test_breakindent08a_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs " breakindent set and shift by 1, Number and list set sbr=# and briopt:sbr call s:test_windows('setl briopt=shift:1,sbr,min:0 nu nuw=4 sbr=# list vts=4') let lines = s:screen_lines(line('.'),10) @@ -356,9 +336,7 @@ func Test_breakindent09() endfunc func Test_breakindent09_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs " breakindent set and shift by 1, Number and list set sbr=# call s:test_windows('setl briopt=shift:1,min:0 nu nuw=4 sbr=# list vts=4') let lines = s:screen_lines(line('.'),10) @@ -390,9 +368,7 @@ func Test_breakindent10() endfunc func Test_breakindent10_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs " breakindent set, Number set sbr=~ call s:test_windows('setl cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0 vts=4') " make sure, cache is invalidated! @@ -421,9 +397,7 @@ func Test_breakindent11() endfunc func Test_breakindent11_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs " test strdisplaywidth() call s:test_windows('setl cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4 vts=4') let text = getline(2) @@ -447,9 +421,7 @@ func Test_breakindent12() endfunc func Test_breakindent12_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs " test breakindent with long indent let s:input = "\t\t\t\t\t{" call s:test_windows('setl breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4 list listchars=tab:>- vts=4') @@ -478,9 +450,7 @@ func Test_breakindent13() endfunc func Test_breakindent13_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs let s:input = "" call s:test_windows('setl breakindent briopt=min:10 ts=8 vts=8') vert resize 20 @@ -512,9 +482,7 @@ func Test_breakindent14() endfunc func Test_breakindent14_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs let s:input = "" call s:test_windows('setl breakindent briopt= ts=8 vts=8') vert resize 30 @@ -548,9 +516,7 @@ func Test_breakindent15() endfunc func Test_breakindent15_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs let s:input = "" call s:test_windows('setl breakindent briopt= ts=8 sw=8 vts=8') vert resize 30 @@ -592,9 +558,7 @@ func Test_breakindent16() endfunc func Test_breakindent16_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs " Check that overlong lines are indented correctly. let s:input = "" call s:test_windows('setl breakindent briopt=min:0 ts=4 vts=4') @@ -620,9 +584,7 @@ func Test_breakindent16_vartabs() endfunc func Test_breakindent17_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs let s:input = "" call s:test_windows('setl breakindent list listchars=tab:<-> showbreak=+++') call setline(1, "\t" . repeat('a', 63)) @@ -640,9 +602,7 @@ func Test_breakindent17_vartabs() endfunc func Test_breakindent18_vartabs() - if !has("vartabs") - return - endif + CheckFeature vartabs let s:input = "" call s:test_windows('setl breakindent list listchars=tab:<->') call setline(1, "\t" . repeat('a', 63)) diff --git a/src/testdir/test_bufline.vim b/src/testdir/test_bufline.vim index 3326e7d2971f57..0f5bac8733d96f 100644 --- a/src/testdir/test_bufline.vim +++ b/src/testdir/test_bufline.vim @@ -202,3 +202,5 @@ func Test_appendbufline_redraw() call StopVimInTerminal(buf) call delete('XscriptMatchCommon') endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_bufwintabinfo.vim b/src/testdir/test_bufwintabinfo.vim index eafadff63f2abf..f201753a22aca9 100644 --- a/src/testdir/test_bufwintabinfo.vim +++ b/src/testdir/test_bufwintabinfo.vim @@ -1,4 +1,5 @@ " Tests for the getbufinfo(), getwininfo() and gettabinfo() functions + source check.vim func Test_getbufwintabinfo() @@ -168,3 +169,5 @@ func Test_getbufinfo_lines() edit Xfoo bw! endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_cd.vim b/src/testdir/test_cd.vim index 8a0fbb247d0f05..0899bcde624e6d 100644 --- a/src/testdir/test_cd.vim +++ b/src/testdir/test_cd.vim @@ -191,3 +191,5 @@ func Test_cd_completion() call delete('XComplDir2', 'd') call delete('XComplFile') endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_changedtick.vim b/src/testdir/test_changedtick.vim index c789cdc1bc61f8..b7e7cd681e7a9e 100644 --- a/src/testdir/test_changedtick.vim +++ b/src/testdir/test_changedtick.vim @@ -93,3 +93,5 @@ func Test_changedtick_not_incremented_with_write() bwipe call delete(fname) endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_changelist.vim b/src/testdir/test_changelist.vim index 3741f32e69e718..9b28ede77d6474 100644 --- a/src/testdir/test_changelist.vim +++ b/src/testdir/test_changelist.vim @@ -1,10 +1,10 @@ " Tests for the changelist functionality +source check.vim + " Tests for the getchangelist() function func Test_getchangelist() - if !has("jumplist") - return - endif + CheckFeature jumplist bwipe! enew diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim index ae7e3014cf7f42..065e8b403b3594 100644 --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -1348,9 +1348,7 @@ endfunction " This caused a crash, because messages were handled while peeking for a " character. func Test_exit_cb_wipes_buf() - if !has('timers') - return - endif + CheckFeature timers set cursorline lazyredraw call test_override('redraw_flag', 1) new diff --git a/src/testdir/test_checkpath.vim b/src/testdir/test_checkpath.vim index eff30cf2058e47..28e9105736d58d 100644 --- a/src/testdir/test_checkpath.vim +++ b/src/testdir/test_checkpath.vim @@ -102,3 +102,5 @@ func Test_checkpath3() set include& set includeexpr& endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_cindent.vim b/src/testdir/test_cindent.vim index dc8c51dbfe44cf..5926408d2e9997 100644 --- a/src/testdir/test_cindent.vim +++ b/src/testdir/test_cindent.vim @@ -1,5 +1,4 @@ " Test for cinoptions and cindent -" func Test_cino_hash() " Test that curbuf->b_ind_hash_comment is correctly reset diff --git a/src/testdir/test_cjk_linebreak.vim b/src/testdir/test_cjk_linebreak.vim index dfaa8fa1af2c28..17c59164a1a1d6 100644 --- a/src/testdir/test_cjk_linebreak.vim +++ b/src/testdir/test_cjk_linebreak.vim @@ -1,3 +1,5 @@ +" Test for CJK linebreak + scriptencoding utf-8 func Run_cjk_linebreak_after(rigorous) @@ -95,3 +97,5 @@ func Test_cjk_linebreak_join_punct() %d_ endfor endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_clientserver.vim b/src/testdir/test_clientserver.vim index db63ce3afaa184..ab80bd2d562b45 100644 --- a/src/testdir/test_clientserver.vim +++ b/src/testdir/test_clientserver.vim @@ -30,7 +30,7 @@ endfunc func Test_client_server() let cmd = GetVimCommand() if cmd == '' - return + throw 'GetVimCommand() failed' endif call Check_X11_Connection() diff --git a/src/testdir/test_close_count.vim b/src/testdir/test_close_count.vim index 1f9adba32daab4..c0c37304ef8426 100644 --- a/src/testdir/test_close_count.vim +++ b/src/testdir/test_close_count.vim @@ -1,5 +1,5 @@ - " Tests for :[count]close! command + func Test_close_count() enew! | only @@ -172,3 +172,5 @@ func Test_winclose_command() set nohidden only! endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 539b782f310ba6..266513ee9fb486 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -86,9 +86,7 @@ func Test_complete_wildmenu() endfunc func Test_map_completion() - if !has('cmdline_compl') - return - endif + CheckFeature cmdline_compl call feedkeys(":map \\"\", 'xt') call assert_equal('"map ', getreg(':')) call feedkeys(":map